Version 7.0, September 28, 2026

9/15/26  [EDGcpfe/28958]
Virtual and consteval specifiers on the "==" implied by a defaulted "<=>"

The equality operator implicitly declared for a class that defines a
three-way comparison operator as defaulted is now itself declared "virtual"
or "consteval" if the three-way comparison operator is so declared, and its
definition is generated when a virtual function table requires it.  For
example:

  struct B {
    virtual std::strong_ordering operator<=>(B const&) const = default;
  };                    // Implicitly declares a virtual "operator==".

  struct D: B {
    bool operator==(B const&) const override;  // Previously an error.
  };                                           // Now okay.


9/15/26  [EDGcpfe/29053]
Spurious unreferenced variable warning in a template braced-init-list

A local variable used only as an element of a braced-init-list on the
right-hand side of an assignment was reported as unreferenced during
prototype instantiation of a function template when that list was
instantiation-dependent.  For example:

  struct S { int b, e; }
  template<int N> void g(S *arr, int b) {
    const int e = b + N;
    arr[0] = { b, e };   // e was previously warned about.
  }                      // Now silently accepted.

That is now fixed.


9/15/26  [EDGcpfe/25951,EDGcpfe/29043]
C23: New tag compatibility rules

In C23 mode, a structure, union, or enumerated type may now be defined more
than once in the same scope, and two such types defined in different scopes
of one translation unit are compatible when they are defined with the same
tag and their members correspond.  Corresponding members must be declared
with the same name and with compatible types, corresponding bit fields must
have the same width and signedness, and corresponding enumerators must have
the same values.  For example:

  struct S { int i; };
  void f(struct S p);
  void g(void) {
    struct S { int i; } s = { 42 };
    f(s);                // OK in C23: The two "struct S" types match.
  }

This implements paper N3037 of the ISO C standardization committee (WG14).


9/14/26  [EDGcpfe/25946,EDGcpfe/29042]
C23: Empty initializers

An empty initializer ("{}") can now be used in C23 mode for an object of any
complete type, including scalar types and variable-length arrays.  The object
is initialized as if each of its members and elements were initialized from a
zero-valued constant.  Such initializers are also accepted for earlier C
standards in the GNU C emulation modes and in the Clang C emulation modes for
Clang 17 and later, where they are an extension.  For example:

  void f(int n) {
    int i = {};            // Zero.
    double d = {};         // Zero.
    void *p = {};          // Null.
    int vla[n] = {};       // Every element is zero.
    int j = (int){} + 1;   // One.
  }

An empty initializer cannot determine the bound of an array, and a
variable-length array still accepts no other form of initializer:

  int a[] = {};            // Error: The bound cannot be deduced.
  void g(int n) {
    int b[n] = { 0 };      // Error: Not an empty initializer.
  }

This implements paper N2900 of the ISO C standardization committee (WG14).


9/14/26  [EDGcpfe/29049]
Dimensions of a deduced variably modified type were evaluated twice

When the type deduced for a variable declared with "auto" in C23, or with the
GNU C "__auto_type" extension, is variably modified, its dimensions were
evaluated once where the initializer appears and once more where the
declaration appears.  A dimension expression with a side effect therefore took
effect twice, and the declaration was also placed at the start of the
enclosing block rather than where it was written.  That is now fixed.  For
example:

  int i = 1;
  void g(void) {
    auto p = (int (*)[++i]) 0;   // "++i" was evaluated twice, once before
    // i is now 2                //   f was entered.
  }


9/14/26  [EDGcpfe/29051]
Abort when lowering extended-precision complex types

An out-of-bounds access (in C99 complex lowering) could occur when
lowering casts or arithmetic on a complex type whose element type is
an extended floating-point type (_Float16, _Float32, _Float64, or
_Float128).  For example, with --gnu_version=160100 --c++23:

  __complex__ long double a;
  __complex__ _Float128 b;
  void f(void) { b = (__complex__ _Float128)a; }


9/14/26  [EDGcpfe/29050]
Memory safety improvements for USE_FIXED_ADDRESS_FOR_MMAP

The front end now takes advantage of MAP_FIXED_NOREPLACE on Linux (when
available) to eliminate the risk of clobbering existing overlapping memory
mappings on Linux kernels 4.17 and later.  Additionally, the front end will now
attempt to use a non-fixed address as a fallback even in
USE_FIXED_ADDRESS_FOR_MMAP=1 configurations.


9/11/26  [EDGcpfe/29041]
C23: auto-type variables

The front end now accepts "auto" as a deduced type-specifier in C23 mode.
"auto" retains its traditional storage class meaning as well: Which of the two
meanings applies is determined by whether a type specifier is also present.
For example:

  void f(void) {
    auto x = 42;            // Deduces "int".
    auto ptr = &x;          // Deduces "int *".
    auto int y = 7;         // "auto" is a storage class specifier here.
  }

This implements paper N3007 of the ISO C standardization committee (WG14).

The GCC "__auto_type" feature (see the entry for EDGcpfe/15176,EDGcpfe/16691)
deduces a type from an initializer in the same way, and the two specifiers now
share an implementation.  "__auto_type" previously kept a function type instead
of decaying it, and kept the qualifiers of its initializer: That is now fixed.


9/11/26  [EDGcpfe/29035]
C++-generating back end: return with dependent braced-init-list

When a return statement returns a braced-init-list whose single element has a
dependent type, the choice between aggregate initialization and a copy cannot
be made until the template is instantiated.  The front end deferred that
choice without recording that the source had braces, so the C++-generating
back end put out the element without them.  The regenerated template could
then have a different meaning, or be ill-formed.  That is now fixed.  For
example:

  template<int> struct S { bool value; };
  bool g(bool, void*);
  template<typename T> S<42> f(T v, void *s) {
    return { g(v, s) };      // Was put out as "return g(v, s);", which
  }                          //   cannot initialize an S<42>.


9/11/26  [EDGcpfe/29032]
Lifetime extension through subscripting, ".*", and conditional expressions

When a reference is bound to a subobject of a temporary, the lifetime of that
temporary is extended to match that of the reference.  The front end
recognized only some of the operations through which such a binding can be
made: The subscripting of an array, the selection of a member with the ".*"
operator, and the selection of a branch of a conditional expression that is a
glvalue were not among them, and a temporary reached through one of those was
therefore destroyed at the end of the full-expression containing the
initialization.  That is now fixed.  For example:

  int d;
  struct A { int a[2]; int b; ~A() { ++d; } };

  int A::*pm = &A::b;
  int c;

  int f() {
    const int &r = A().a[0];      // Each A() is now destroyed when r, s, or
    const int &s = A().*pm;       //   t goes out of scope, rather than at
    const int &t = c ? A().a[0]   //   the end of its own initialization.
                     : A().a[1];
    return d;                     // Now returns zero.
  }


9/11/26  [EDGcpfe/29048]
Use of freed routine fixup entries during default argument fixup

When an instance of a class template is required while the definition of that
template is still being processed, the front end first completes the fixup of
the default arguments of the member functions in that template.  Scanning such
a default argument can itself require a class to be completed, and the
instantiation that results could perform the fixup of the inline function
bodies of the class whose default arguments were being scanned.  That fixup
frees the routine fixup entries that were being walked, so the walk continued
into the list of available entries, which could lead to unpredictable behavior,
including an internal error.  The fixup of inline function bodies is now
deferred until the default arguments have been scanned.


9/10/26  [EDGcpfe/29034]
".*" operand that is a cast to a dependent reference type

A cast to a dependent reference type written with a type operator, as in
"static_cast<decltype(x) &&>(x)", yields an IL entry whose type is the
reference type itself, so that the type operator is not lost.  The handling of
a ".*" operator ignored that possibility and the front end therefore rejected
the left operand as not having class type (or the right operand as not having
pointer-to-member type).  That is now fixed.  For example:

  struct V { int i; };
  template<typename F, typename T, typename U>
    auto f(F T::*pm, U &&x)
    -> decltype(static_cast<decltype(x) &&>(x).*pm) {  // Previously an error.
                                                       //  Now okay.
      return static_cast<decltype(x) &&>(x).*pm;
    }
  int main() {
    V v{7};
    return f(&V::i, v);
  }


9/9/26   [EDGcpfe/29014]
Avoiding excessive recursion in the interpreter

The interpreter no longer uses recursive calls to walk the IL.  Instead, an
ordinary loop managing "work items" drives the process.  This avoids situations
where the front end aborted due to overflowing the call stack.


9/9/26   [EDGcpfe/29047]
Clang compatibility: arguments dropped from __builtin_masked_... calls

Previously, calls of __builtin_masked_load, __builtin_masked_expand_load, and
__builtin_masked_gather (see the changes for EDGcpfe/28718 in version 6.9) only
had their first argument recorded in the IL for the call.  That is now fixed.


9/8/26   [EDGcpfe/28266]
Declarations in a class body

A new configuration macro, MAINTAIN_CLASS_MEMBER_LIST, causes the front end to
record for each class that is defined the declarations that appear in the body
of that class (in the order in which they appeared).  The list is pointed to
by the new field member_declarations of the class type supplement and has one
an_il_entity_list_entry per declaration.  An entry can identify a field, a
routine, a variable, a type, a template, a using-declaration, or a static
assertion.  A friend declaration written in the body is included even though
the entity it declares is not a member of the class, but declarations that the
front end generates itself (e.g., an implicitly-declared constructor) are not.


9/8/26   [EDGcpfe/29040]
Clang compatibility: builtin argument checking

The __builtin_elementwise_ldexp builtin now accepts scalar arguments.  The
second argument must still be an integer type with the same "shape" as the
first argument: a scalar for a scalar first argument, or a vector of integer
type with the same number of elements for a vector first argument.  The second
argument is now also converted to a prvalue, and the routine generated for such
a call now has the integer type as the second parameter.

Additionally, the __builtin_elementwise_... and __builtin_reduce_... builtins
that require integer arguments (e.g., __builtin_elementwise_popcount) now
accept enumeration types (for __builtin_reduce_..., as the element type of
the argument vector).  An enumeration type whose underlying type is unsigned
is also now accepted as the argument of __builtin_clzg, __builtin_ctzg, and
__builtin_popcountg.

A complex floating-point type is no longer accepted for the
__builtin_elementwise_... and __builtin_reduce_... builtins that accept
floating-point arguments.

A brace-enclosed list as an argument of an __builtin_elementwise_... call or of
__builtin_invoke could previously lead to a front end crash; it is now
diagnosed.  Likewise, an already-diagnosed erroneous argument to an
__builtin_elementwise_... call no longer leads to an internal error due to a
failed assertion in do_constexpr_builtin_elementwise_binary_op during constant
evaluation of such a call.


9/7/26   [EDGcpfe/29044]
C++-generating back end, GNU compatibility: __typeof__ in template definition

In configurations with ALL_TEMPLATE_INFO_IN_IL set to FALSE or with the
--no_parse_templates command-line option, the C++-generating back end put
out the GNU/clang __typeof__ operator appearing in a template definition as
"typeof", without the leading and trailing underscores.  Those compilers
only accept the shorter form when GNU extensions are explicitly enabled,
i.e., with a -std=gnu++XX command-line option.  The front end has now been
changed to put out the longer form whenever gcc or clang is the target
compiler.  This failure was a consequence of the changes for
EDGcpfe/25938,EDGcpfe/26054 in version 6.5.  For example, with
--gnu_version=120100 --no_parse_templates:

  template<typename> struct S {
    typedef __typeof__ ( 1 ) type;   // Previously generated as "typeof"
  };


9/7/26   [EDGcpfe/29028]
Calls of type-generic builtins with dependent arguments

A call of a type-generic builtin (e.g., __builtin_clzg or a __sync_* or
__atomic_* builtin) with a dependent argument is now kept as an unknown
dependent function call.  Previously, such a call was processed using the
dependent argument types, which could create a routine entry whose type
contains a template parameter; IL consumers could mistake it for a real
routine.  For example, with --gnu_version=150200:

  template<typename T>
  void f(T t) {
    __builtin_clzg(t);  // Previously recorded a call of an "int(T)" routine.
  }

Additionally, a call of a generic __atomic_* builtin in a substitution context
previously resulted in a substitution failure.  For example, with
--gnu_version=150200:

  template<typename T>
  auto g(T t) -> decltype(__atomic_load(&t, &t, 0)) *;
  auto p = g(1);  // Previously a spurious error, now okay.


9/3/26   [EDGcpfe/29025]
Abort in is_trivially_copyable_type for a using-declared operator= from a
dependent base

Consider:

  template<class T> struct B;
  template<class T> struct D : B<T> {
    D &operator=(const D &);
    using B<T>::type::operator=;
  };

A using-declaration that names an assignment operator through a dependent
qualified name contributes a projection symbol to the overload set recorded
in the class symbol supplement.  The fundamental symbol of such a projection
stands for a member of a nonreal class rather than a member function, and
is_trivially_copyable_type asserted that every candidate in that overload set
is a member function.  With checking disabled, it instead read the routine
pointer of a symbol that is not a routine, which could produce an arbitrary
answer.  Such candidates are now skipped: Nothing is known about the operator
they name, so it can neither establish nor rule out trivial copyability.

Note that the front end itself never asks whether the class in the example is
trivially copyable, because that query requires a complete, instantiated type;
the problem was observed through a back end that records a POD attribute for
every class type it emits.


9/3/26   [EDGcpfe/29038]
Local variables of type a_constant in expr.c

Version 6.9 of the front end introduced local variables of type a_constant in
the expr.c source code.  Such local variables lack an IL entry prefix, which
can result in memory corruption when pointers to the variables are passed to
various functions.  This has now been fixed (by using local_constant() instead;
see the entry for EDGcpfe/16056).


9/3/26   [EDGcpfe/29037]
C++-generating back end: Dropped reference in a cast to a type operator

Consider:

  template<class T, const T &x> constexpr T id() { return x; }
  struct S { };
  template<class T> struct A {
    static S s;
    S f() { return id<decltype(s), (decltype(s) &&)s>(); }
  };
  template<class T> S A<T>::s = S();
  S g() { A<int> a; return a.f(); }

A cast to a reference type is recorded with the referenced type as the type
of the operation node, and the back end restored the reference when
generating the cast.  It skipped that step whenever the node type was a type
operator, on the assumption that the reference was part of the type operator
itself; but that is so only when the type operator denotes a reference type.
As a result, the cast above was generated as "(decltype(s))s", which yields
a temporary rather than an lvalue referring to "A<int>::s", and recompiling
the generated code produced errors about a reference or pointer to a
temporary with limited lifetime.  The reference is now restored unless the
type operator denotes a reference type.


9/3/26   [EDGcpfe/29033]
Clang compatibility: "#pragma clang riscv intrinsic"

The front end now supports the "#pragma clang riscv intrinsic" construct used
by the Clang RISC-V vector headers (<riscv_vector.h>, <andes_vector.h>, and
<sifive_vector.h>).  It also predeclares the RISC-V OFP8 vector types used by
Clang 23 and later (for example, __rvv_float8e4m3m1_t and
__rvv_float8e5m2m1_t).  This is a small IL CHANGE.

In addition, loading the builtin functions associated with headers such as
<riscv_vector.h>, <arm_neon.h>, and <arm_sve.h> previously eagerly created a
function declaration for every applicable builtin function.  Now, function
declarations are created lazily when a builtin function is first referenced.
Compilation times for translation units that load those builtins are
significantly reduced.

The builtin signatures for Clang 22 have also been updated to the final 22.1.0
release; previously, the signatures were based on RC1 (see the changes for
EDGcpfe/28648 in version 6.9).


9/2/26   [EDGcpfe/29031]
Implicit move ignored &&-qualified conversion functions

A return or throw of an implicitly-movable entity first performs overload
resolution as if the entity were an rvalue.  In C++11 and later, if that
selects a conversion function (e.g., operator T() &&), that conversion is
used.  If it selects only a copy constructor such as X(X const&), overload
resolution is retried treating the entity as an lvalue, matching GCC and
Clang.  The front end previously kept the rvalue conversion only for a
constructor whose first parameter is an rvalue reference.  For example:

  struct S { int i; };
  struct X {
    operator S() & = delete;
    operator S() && { return {42}; }
  };
  S f(X x) {
    return x;  // Previously an error.  Now okay.
  }

Previously this  called operator S() & instead of operator S() &&.  That is
now fixed.


9/1/26   [EDGcpfe/28964]
Subnormal hex floating-point literals that cannot be represented exactly

The front end previously produced incorrect values for hexadecimal
floating-point literals whose values require a subnormal representation but
cannot be represented exactly in the associated data type.  This is now
fixed.  For example:

  double d = 0x3p-1075;   // Previously infinity, now equal to 0x1p-1073


9/1/26   [EDGcpfe/29030]
--[no_]bit_precise_integers in eccp.sh script

The changes for EDGcpfe/25899 et al. added command-line options to control
whether C23 _BitInt types are accepted.  However, the eccp.sh script was not
updated to accept and propagate those same options: That is now fixed.


9/1/26   [EDGcpfe/29000]
Spurious error on deduction guide return types when using name references

In configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE (as
with the C++-generating back end), a valid deduction guide return type written
as a class template specialization could be rejected because lexical typerefs
recording the form of the name (e.g., trk_template_arg_list) were not skipped
when checking the return type.  For example:

  using INT = int;
  template<typename> struct C { };
  C<int> *c;
  C() -> C<INT>;  // Was erroneously diagnosed

This is now fixed.  (This is a regression from version 6.8.)


9/1/26   [EDGcpfe/28645]
Template template parameter expanding an empty enclosing pack

During the instantiation of an enclosing template with an empty parameter pack,
a template template parameter declared as a pack expansion of that enclosing
pack was incorrectly treated as a nontype template parameter, which could
trigger an internal error due to a failed assertion in
update_template_param_symbol.  This regression was introduced by the changes
for EDGcpfe/27707 (in version 6.8).  For example, with --c++20:

  template<typename ... Ts>
  void f() {
    auto l = []<template<Ts> typename ...>{ };
  }
  template void f<>();  // Previously triggered an internal error, now okay.


8/28/26  [EDGcpfe/25498]
Using unknown references in constant expressions

The standardization committee's paper P2280R4 relaxes the rules for constant
expressions so that a reference whose referent is not known to the constant
evaluator, such as a reference parameter of the function being compiled, can
be used in a constant expression as long as the result does not depend on the
object the reference is bound to.  The front end has now been updated
accordingly.  For example, with --c++14:

  using Sz = decltype(sizeof(0));
  template<class T, Sz N> constexpr Sz f(T (&)[N]) {
    return N;
  }
  struct S { enum { e = 42 }; };
  struct X { static constexpr Sz r() { return 3; } };
  void g(char (&arr)[8], S &s, X &x) {
    constexpr auto n = f(arr);       // Previously an error, now 8.
    constexpr int h = s.e;           // Previously an error, now 42.
    static_assert(x.r() == 3, "");   // Previously an error, now okay.
  }

The same holds for class member access through the "this" pointer:

  struct Outer {
    struct Inner { constexpr int f() const { return 42; } } inside;
    void check() {
      static_assert(inside.f() == 42, "");  // Previously an error, now okay.
    }
  };


8/28/26  [EDGcpfe/29022]
C++/CLI: Incorrect mapping of certain integer types to System:: types

integer_kind_to_cli_symbol_kind converted an_integer_kind values to
a_cli_symbol_kind by unchecked offset arithmetic.  That only matches
ik_char through ik_unsigned_long_long.  Later kinds (__int128, _BitInt)
landed on unrelated CLI types (System::Single, System::Double,
System::Boolean).  For example, with --cppcli --bit_precise_integers:

  typedef _BitInt(24) i24;
  int f() { return i24::MaxValue; }
      // Previously accepted as System::Double::MaxValue.

That is now fixed.


8/28/26  [EDGcpfe/24003,EDGcpfe/26323,EDGcpfe/29024]
Clang compatibility: two argument form of "deprecated" attribute

The front end now accepts the two-argument form of the "deprecated" attribute
in Clang emulation modes.  For example, with --clang:

  void f(void) __attribute__((deprecated("message", "replacement")));


8/27/26  [EDGcpfe/29026]
GNU compatibility: __builtin_constexpr_diag

The GNU builtin __builtin_constexpr_diag, which is GCC 16's intrinsic for the
facility proposed in C++ paper P2758R5 to let constant evaluation produce
diagnostics, is now supported.  Its three arguments are a severity, a tag
naming the diagnostic, and the text to be reported.  For example, with
--c++26 --gnu=160100:

  constexpr int f(int i) {
    if (i < 0) __builtin_constexpr_diag(1, "negative", "a negative argument");
    return i;
  }
  constexpr int j = f(-1);
      // "warning: interpreter: a negative argument [negative]"

A severity of 0 produces a remark, 1 a warning, and 2 an error.  Adding 16 to
the severity asks that the diagnostic be reported at the call of the routine
containing the call, which is what wrappers such as the proposed
std::constexpr_error_str would want.  The tag, which is omitted from the output
when it is empty, and the text may each be given as a pointer to a string
literal or as an object with the representation of std::string_view.

The new --constexpr_diag_suppress, --constexpr_diag_remark,
--constexpr_diag_warning, and --constexpr_diag_error options each take a comma
separated list of tags and give the severity to be used for the diagnostics
requested with those tags; --constexpr_diag_suppress asks that no diagnostic be
produced.  This is the mechanism that P2758 recommends implementations provide
so that a library can let its users control the diagnostics it produces.  For
the example above, --constexpr_diag_error=negative makes the warning an error.


8/27/26  [EDGcpfe/29020]
Microsoft mode: Out-of-range enumerator folded to 0 with a typeref enum-base

In Microsoft mode an enumerator whose value is outside the range of a fixed
underlying type is truncated into that type rather than rejected.  When the
enum-base was expressed with a typedef name (or anything other than a bare
built-in type name), a signed underlying type caused the truncated value to
become 0.  For example, with --microsoft --c++17:

  typedef short i16;
  enum ViaTypedef : i16 { A = 0x7FFFFFFF };
  static_assert(A == -1, "A");  // Previously 0 == -1.  Now okay.

This is now fixed.


8/27/26  [EDGcpfe/28999]
C++26 and GNU compatibility: <meta> support

The front end's experimental support for reflection (see the entry for
EDGcpfe/26698) has been upgraded to support most metafunctions adopted for
C++26 (through the committee's papers P2996R13, P3096R12, and P3394R4).  In
addition, the front end can now ingest GCC 16.1's version of the <meta> header
and intrinsically evaluate most of the consteval functions it declares.


8/27/26  [EDGcpfe/29023]
Spurious error for dependent member call with explicit template arguments

A call with explicit template arguments to an operator member of a dependent
class could be wrongly rejected when an unrelated template contained a plain
dependent call to the same operator member.  For example, with --c++11:

  template<typename T> T v();
  template<typename T, class F>
  auto f(F) -> decltype(v<F>().template operator()<1>());
  struct C {
    template<int = 0> int operator()() const;
  };
  template<typename T>
  int g() {
    return v<T>().operator()();
  }
  int i = f<int>(C{});  // Previously a spurious error, now okay.


8/26/26  [EDGcpfe/28740]
Substituting explicitly-specified template arguments with trailing empty pack

Previously, a trailing empty pack in an explicitly-specified template argument
list could result in a spurious substitution failure.  For example, with
--c++11:

  struct C {
    template<typename> static int f();
  };
  template<typename T, typename ... Us>
  auto f(T, Us ...) -> decltype(C::f<T, Us ...>());
  int i = f(1);  // Previously a spurious error, now okay.


8/25/26  [EDGcpfe/25155,EDGcpfe/28856]
Abort on constrained templated friend function

A friend function defined in a class template and declared with a trailing
requires-clause could trigger an internal error due to a failed assertion in
resolve_pending_trailing_requires_clause when it was referenced again after an
earlier call.  For example, with --c++20:

  template<typename T> concept X = requires(T t) { f(t); };
  template<bool B> struct C {
    friend int f(C) requires B { return 0; }
  };
  int i = f(C<true>());
  bool b = X<C<true>>;  // Previously triggered an internal error.  Now okay.

Additionally, a direct call to such a function did not check its trailing
requires-clause when it was the only candidate.  For example, with --c++20:

  template<bool B> struct D {
    friend int f(D) requires B { return 0; }
  };
  int i = f(D<false>());  // Previously incorrectly accepted.  Now an error.


8/24/26  [EDGcpfe/29016]
GNU compatibility: __builtin_is_structural

GCC 16 introduced a new intrinsic __builtin_is_structural.  The front end now
also supports that intrinsic to test for structural types in GNU C++ modes
with gnu_version >= 160000.


8/24/26  [EDGcpfe/29015]
Avoid dependency on User32.dll (Windows only)

compare_file_chars_case_insensitive in host_envir.c has been updated to
remove an unnecessary dependency on User32.dll on Windows.


8/24/26  [EDGcpfe/28592]
C++/CX: missing skip_typerefs in type validation for new-expression

A missing skip_typerefs call could lead to undefined behavior when validating
the allocated type in a new-expression.  For example, with --cppcx:

  using namespace Platform;
  using BoxInt = Box<int>;

  void f() {
    BoxInt^ v = ref new BoxInt(0);
  }


8/21/26  [EDGcpfe/25572,EDGcpfe/28978]
Pack expansion of requires expression

Previously, expanding a requires expression was spuriously rejected with "pack
expansion does not make use of any argument packs".  For example, with --c++20:

  template<bool ... Bs>
  struct B {
    static constexpr bool v = true;
  };
  template<typename ... Ts>
  struct C {
    static constexpr bool v =
      B<requires(Ts t) { t; } ...>::v;  // Previously a spurious error.
  };                                    // Now okay.


8/20/26  [EDGcpfe/28940]
Unicode version 17.0.0

The set of characters that can be used in identifiers, the table of similar
glyphs that might be used in source-level malicious exploits (see
EDGcpfe/24810,EDGcpfe/24829), and the list of character names and code
points (see EDGcpfe/25513,EDGcpfe/25845) have been updated to reflect
version 17.0.0 of the Unicode standard.


8/20/26  [EDGcpfe/29012]
Replace remaining stdlib qsort/bsearch calls in the front end

The remaining front-end uses of the C library qsort and bsearch routines have
been replaced by the util.h sort and bin_search templates.  This change also
fixed bugs in sort_args (in util.h) for the 3- and 4-element cases.


8/19/26  [EDGcpfe/28991,EDGcpfe/28992]
C++: Friend defined in a class template used from a constexpr destructor

A friend function defined in a class template could be left with a dangling
pointer to a freed routine-fixup entry if the function was already referenced
(for example, from a constexpr destructor) before the enclosing class
template was instantiated.  A later reference then aborted.  For example:

  template<typename T> struct P {
    T *px;
    P(bool = true);
    constexpr ~P() { f(px); }
  };
  struct B;
  template<typename T> struct C {
    friend void f(B*) {}
  };
  void f(B*);
  P<B> a;
  struct B : C<B> {};
  template<typename T> struct D: B {};
  P<D<int>> b;  // Previously an internal error.  Now accepted.

This is now fixed.


8/19/26  [EDGcpfe/29010]
Microsoft C compatibility: Local static variables in extern-inline functions

In Microsoft C99 and later modes, the front end previously issued a
discretionary error for the following example:

  inline int g(void) {
    static int i = 42;
    return i;
  }

because C disallows local static variables in non-static inline definitions.
MSVC, however, silently permits this and the front end now emulates that by
only issuing a remark in that case.


8/19/26  [EDGcpfe/29011]
Implicit assignment operators that override a virtual operator=

An implicitly-declared copy or move assignment operator that overrides a
virtual assignment operator in a base class was previously emitted as a
declaration only, with no function body.  Calls through the vtable therefore
failed to link.  For example:

  struct D;
  struct B { virtual D& operator=(D const&); };
  struct D : B {
    D(int i) : i(i) {}
    int i;
    // Implicit copy-assignment operator.
  };
  D& B::operator=(D const&) { return static_cast<D&>(*this); }
  int main() {
    D d1(123), d2(0);
    A &ar = d1;
    ar = d2;          // Previously an undefined reference at link time.
  }                   // Now assigns through D's copy assignment.

This is now fixed.


8/19/26  [EDGcpfe/29006]
Clang compatibility: enable_if and deleted converting constructors

Evaluating a Clang enable_if attribute on a multi-argument candidate could
issue a diagnostic for a conversion that uses a deleted function, even when
that candidate was not selected.  For example, in Clang C++17 mode:

  struct S {
    operator unsigned long long() const;
    S(int) = delete;
  };
  bool operator==(unsigned long long lhs, const S &rhs)
      __attribute__((enable_if(lhs == 0, "")));
  bool g(S s) { return s == 0; }
                      // Previously an error (S::S(int) is deleted).
                      // Now accepted.

This is now fixed.


8/19/26  [EDGcpfe/29005]
GNU and Clang compatibility: Member calls on by-copy captures in lambda
headers

The P2579 implementation (see the entry for EDGcpfe/21022 et al.) treats
by-copy captures as const in a non-mutable lambda header.  GCC and Clang apply
that adjustment only when computing decltype of a (parenthesized)
id-expression; they do not const-qualify the object of a member call.
The front end now emulates that behavior in GNU and Clang modes.  For example:

  struct S { S operator+=(S const&); };
  S g;
  void f() {
    S s1, s2;
    auto lm = [=]() -> decltype(s1.operator+=(s2)) { return g; };
                      // Previously always an error (object type is S const).
                      // Now accepted in GNU and Clang C++ modes.
  }


8/19/26  [EDGcpfe/25497,EDGcpfe/26173,EDGcpfe/26947,EDGcpfe/27563,
          EDGcpfe/28495]
C++20: Matching operator!= disables rewritten operator== candidates

The front end now implements the C++20 defect report resolution from P2468R2
("The Equality Operator You Are Looking For").  An operator== is not used as a
rewritten candidate (with reversed operands, or as a rewrite of !=) when a
corresponding operator!= is found in the applicable scope.  For example, in
C++20 mode:

  struct B {
    void operator==(B const&);
    void operator!=(B const&);
  };
  struct D: B {
    D() {
      B x;
      x == B();  // Previously ambiguous with a reversed candidate.  Now okay.
    }
  };


8/19/26  [EDGcpfe/26102,EDGcpfe/27040]
Abort on virtual call with a template default argument

In configurations with OPTIMIZE_VIRTUAL_FUNCTION_CALLS set to TRUE, a virtual
call to a function with a default argument, where that function is a member of
a class template, aborted due to a failed internal assertion in
instantiate_default_argument when the function was found via a
using-declaration and called from a constructor or destructor.  For example,
with --gnu_version=150200:

  template<typename> struct B {
    virtual void f(int = 0);
  };
  template<typename> struct D : B<int> {
    void f(int);
  };
  struct C : D<int> {
    using B<int>::f;
    C() { f(); }  // Previously triggered an abort.  Now okay.
  };


8/18/26  [EDGcpfe/29009]
Clang compatibility: __cpp_runtime_arrays

The changes for EDGcpfe/28560 in version 6.9 added the feature-test macro
__cpp_runtime_arrays used by gcc to indicate support for the non-standard
variable length array feature.  Although clang supports the feature, it
does not define that macro, so the front end has now been changed
accordingly.  For example, with --clang_version=200000:

  #if defined(__cpp_runtime_arrays)
  #error Incorrect macro setting   // Previously triggered, now skipped
  #endif


8/18/26  [EDGcpfe/29008]
Missing template string for members of an in-class explicit specialization

In configurations with RECORD_TEMPLATE_STRINGS set to TRUE, the front end
previously did not record the string representation for member templates of an
in-class explicit specialization.  For example, with --c++11:

  struct S {
    template<typename T> struct C { };
    template<> struct C<int> {
      template<typename T> using A = T;  // Previously not recorded as a string
                                         // representation in the IL.
    };
  };


8/17/26  [EDGcpfe/29007]
C++-generating back end: segfault with member template

In C++-generating back end configurations with ALL_TEMPLATE_INFO_IN_IL set
to FALSE, a member template of an in-class explicit specialization of a
class template could cause an abort dereferencing a NULL pointer.  This is
now fixed.  For example, with --microsoft_version=1951 --ms_c++latest:

  template<typename, typename = int, typename = int> struct S { };
  struct O {
    template <template <typename...> typename C> struct D;
    template<> struct D<S> {
      template<typename T, typename... Args>
      using A = S<T, int, Args...>;   // Previously aborted, now okay
    };
  };


8/14/26  [EDGcpfe/25502,EDGcpfe/25847]
C++23: Un-deprecation of volatile compound assignments

The front end now implements the resolutions of Core issue 2654 (a DR against
C++23).  Compound assignment operators on volatile-qualified objects are no
longer deprecated.  Increment, decrement, and simple assignment (when the
value is used) of volatile objects remain deprecated.  For example,
with --c++20:

  volatile int v;
  int i;
  v += i;   // No longer deprecated.
  ++v;      // Still deprecated.


8/13/26  [EDGcpfe/25524]
C++23: Explicit object parameter for assignment and comparison

The front end now implements the resolution of Core issue 2586.  A copy or
move assignment operator may be declared with an explicit object parameter,
and a comparison operator with an explicit object parameter may be defaulted.
For example, with --c++23:

  struct C {
    C& operator=(this C&, C const&);  // Now a copy assignment operator.
  };
  struct D {
    bool operator==(this D const&, D const&) = default;  // Now okay.
  };


8/13/26  [EDGcpfe/29004]
C++-generating back end, Microsoft compatibility: volatile-qualified parameters

The changes for EDGcpfe/28825 in version 6.9 suppressed top-level volatile
qualifiers in function parameter declarations in the output of the
C++-generating back end.  That change, however, was too broad, since MSVC
includes the presence or absence of such qualifiers in the mangled names of
functions.  Consequently, the C++-generating back end no longer suppresses
"volatile" in parameter declarations when msvc_is_generated_code_target is
TRUE.  For example, with --microsoft_version=1950:

  void f(int * volatile);   // Previously omitted "volatile", now preserved


8/13/26  [EDGcpfe/29003]
_Pragma operator in #if expression

When _Pragma appears in the expression of a #if directive, the front end
incorrectly treated names appearing in the _Pragma operand as if they were
part of a preprocessor expression, i.e., any identifier not defined as a
macro was replaced by the integer value 0.  This generally resulted in the
_Pragma failing to have its intended effect.  For example, with
--ms_c++latest:

  #define M _Pragma("pack(push, 1)")
  #if (0 + M 1)
  #endif
  struct S {
    char      c;
    long long d;
  };
  static_assert(sizeof(S) == 9, "Incorrect size");

Because the "push" in the _Pragma operand was replaced by the integer value
0, the pragma attempted to set the alignment to 0 instead of 1 and the
static assertion failed.  This is now fixed.


8/13/26  [EDGcpfe/29001]
Performance improvements for CTAD through template template parameters

When class template argument deduction (CTAD) was performed for a placeholder
naming a type template template parameter, the deduction guides of the template
argument were always transformed through an invented alias template (see the
changes for EDGcpfe/28857 in version 6.9).  This transformation is now skipped
when the template template parameter has no constraints and its parameter list
is either a single parameter pack or is equivalent to that of the template
argument.  For example, with --c++20:

  template<typename T> struct B { B(T); };
  template<template<typename...> class TT>
  void f() { TT t(1); }  // No longer performs alias-like CTAD transformations
  template void f<B>();

In addition, a diagnostic that names a deduction guide now always includes its
parameter list and trailing return type.  For example, with --c++17:

  template<typename T>
  struct C { };
  explicit C() -> C<int>;
  C c = { };  // Previously shown as deduction guide "C", now "C()->C<int>"


8/12/26  [EDGcpfe/28288,EDGcpfe/28876]
Representation of T() vs T{} for aggregate types

A functional-notation cast T() of an aggregate was previously represented as a
dik_zero dynamic initialization of temporary, even when it appeared in an
aggregate initializer list (in the backing expression of the constant entry
representing that entry).  Now it is represented as a plain aggregate constant,
consistent with the braced case (i.e., T{}).  For example, with --c++20:

  struct X {};
  struct Y {
    X X;
  };
  static Y y1 = { X{} };   // Always represented by a plain ck_aggregate.
  static Y y2 = { X() };   // Previously a nonconstant aggregate with a
                           // dik_zero backing expression.  Now similar to y1.

This also addresses a bug in the constant-evaluation of value-initialized
union objects.  For example, with --c++20:

  union U { int i; };
  struct S {
    U u;
    constexpr S() : u() {}
  };
  constexpr S s;  // Previously an error about U::i not being initialized.
                  // Now okay.


8/12/26  [EDGcpfe/27881]
Inconsistent conditional compilation in decl_routine

The local variable decl_modifiers in decl_routine was declared under a
condition that did not cover all of its uses.  E.g., uses that record the
marked_as_gnu_extension flag in source-sequence information were compiled
whenever GENERATE_SOURCE_SEQUENCE_LISTS was TRUE, but the variable itself
was declared for that purpose only when GNU_EXTENSIONS_ALLOWED was also
TRUE.  That mismatch could cause a compilation failure in some
configurations.  The conditions are now consistent.


8/12/26  [EDGcpfe/28867]
Adjustment of by-copy captures in lambda headers

The entry for EDGcpfe/21022,EDGcpfe/21246,EDGcpfe/24784,EDGcpfe/25500 describes
changes implementing support for P2579, which affects the types of captured
entities in lambda headers.  That implementation was too broad, treating all
automatic variables mentioned in a lambda header (after the parameter list) as
const lvalues whenever the lambda call operator was const.  The adjustment now
applies only when the variable would be captured by copy.  Uses in an
unevaluated operand with an empty capture list, or with a by-reference
capture, were incorrectly const-qualified and could then reject a valid
non-const call.  For example, with --c++11:

  struct B;
  struct D { bool operator()(B*) noexcept; };
  void f(D& c) {
    auto m = [](B* a) noexcept(noexcept(c(a))) { return true; };
    // Previously: error, object type is const D.  Now okay.
  }


8/12/26  [EDGcpfe/28944]
C++-generating back end: CTAD with lambda as expression temporary

In cases where class template argument deduction is used with a constexpr
constructor and the resulting temporary is passed as an expression the
C++-generating back end could put out the deduced class type using an
undeclared temporary name (of the form __T12345678) as an explicit template
argument.  This is now fixed.  For example, with --c++20:

  template<typename T1, typename T2> struct pair {
    constexpr pair(const T1 &a, const T2 &b);
    T1 first; T2 second;
  };
  template<typename T> T f(T v) { return v; }
  void g() {
    // Previously generated as:
    //   f(pair<class __T12345678, int>{[]{}, 0})
    f(pair{[]{}, 0});
  }


8/12/26  [EDGcpfe/28955,EDGcpfe/28976]
Unary * on instantiation-dependent but non-type-dependent operands

The changes for EDGcpfe/24532 et al. (in version 6.9) caused some uses of the
unary "*" operator to be analyzed "generically" when an operand was
instantiation-dependent but not type-dependent.  That dropped the result type
of operator* and could then cause a spurious parse error on a following 
member template argument list.  For example:

  struct W { template<typename> void f(); };
  struct It { W& operator*(); };
  struct Arg {};
  struct S {
    It get(Arg);
    template<typename> void g() {
      Arg a{};
      (*get(a)).f<int>();  // Previously: "type name is not allowed".
    }
  };

Unary "*" is now handled like "->": Only type dependence (not instantiation
dependence) causes generic treatment, so the result type remains available
for parsing a subsequent member template-id.

8/12/26  [EDGcpfe/28960]
Assertion failure in extract_value_from_constant

Consider:

  constexpr BigObject b{ /* ... */ };
  auto &r = b.member();  // Could assert in extract_value_from_constant.

where BigObject is too large to represent in interpreter storage.  The
failure to materialize b in the interpreter could leave a representation of
the address of b uninitialized but some later processing (that should have
been skipped since interpretation already failed) still consulted that address
for processing.  That resulted in a spurious assertion failure.  This bug is
now fixed.


8/11/26  [EDGcpfe/28982]
Dependent integral constant matching std::nullptr_t parameter

In a template prototype instantiation, a value-dependent integral constant
that might be zero is not treated as a null pointer constant when matching
a pointer parameter (see EDGcpfe/9380).  That treatment is now extended to
parameters of type std::nullptr_t as well (except in Microsoft mode).  For
example, with --c++11:

  void f(decltype(nullptr));
  void f(long);                 // (1)
  template <int N> void g() {
    const int n = N;
    f(n);  // Previously ambiguous.  Now calls (1).
  }
  int main() { g<99>(); }


8/11/26  [EDGcpfe/28993]
GCC compatibility: Allow member overload with and without a ref-qualifier

Consider:

  struct S {
    void f();
    void f() &&;  // Now accepted (as by GCC 16).
  };

This is now accepted in GNU C++20 modes with gnu_version >= 160000.  (See also
EDGcpfe/28870, which implements a related C++23 rule.)


8/11/26  [EDGcpfe/27616,EDGcpfe/28822]
Lowering of spaceship operator with floating-point operands

For a spaceship operator that operates on floating-point operands, the standard
requires that the result of the operation be std::partial_ordering::unordered
if one or more of the operands is a NaN.  The code generated by lowering
had neglected to account for the NaN case and now does for the basic floating-
point types (i.e., float, double, long double).  For example, with
--c++23 --g++:

  #include <compare>
  auto x = 42.0 <=> __builtin_nan(0);

Note that this change requires runtime library support to detect NaN values
at runtime.  In particular, it is assumed that the __builtin_isnanf,
__builtin_isnan, and __builtin_isnanl routines are available at link time.
Note also that a spaceship operation on extended floating-point types will
generate references to runtime library routines __builtin_isnanf16,
__builtin_isnanf80, __builtin_isnanf128, and __builtin_isnanb16 (which are not
supplied by EDG nor readily available in standard libraries).


8/5/26   [EDGcpfe/28998]
Performance regression for programs with many non-type template arguments

The changes for EDGcpfe/28295 in release 6.9 added a check, applied whenever a
non-type template argument is prepared, for a reference to a variable of an
enclosing function scope.  That check involved an IL traversal that could come
to dominate compile time (or even trigger an abort due to exceeding call stack
limits).  This has been fixed by reducing the circumstances in which the check
is performed and by having the traversal performance by the check be more
efficient.  The changes for EDGcpfe/28295 could also cause the proliferation
of copies of backing expressions for constant template arguments, resulting in
a noticeable increase in memory usage for some cases: This copying is now much
reduced.


8/5/26   [EDGcpfe/28995]
Regression resulting in loss of pragma preceding #if preprocessor directive

The changes for EDGcpfe/28636 (in version 6.9) introduced a regression in
pragma processing where a pragma preceding an #if preprocessor directive is
never processed.  For example, with --c++20:

  #pragma pack(push, 1)
  struct P {};
  #pragma pack(pop)
  #if (0 + 1)
  #endif
  struct NP { char c; long long l; };
  static_assert(sizeof(NP) == 16);  // Previously failed, now okay.


8/5/26   [EDGcpfe/28997]
Infinite loop on invalid structured binding pack

Previously, a structured binding pack whose container type has no components to
bind to could cause the front end to go into an infinite loop.  For example,
with --c++26:

  void f(auto v) {
    auto [... p] = v;  // Error, but previously caused the front end to enter
  }                    // an infinite loop.
  template void f(int);


8/5/26   [EDGcpfe/28996]
Spurious partial specialization matching failure with alias in function type

With the changes for EDGcpfe/21155,EDGcpfe/28528 (in version 6.9), a partial
specialization could fail to match (due to duplicated deduced pack elements)
when its argument list contains a function type with a parameter pack along
with an alias that is discarded when the pattern is processed.  For example,
with --c++17:

  template<typename T> using A = int;
  template<typename T, T> struct C;
  template<typename R, typename ... Args, R fn(int, Args...)>
  struct C<R(*)(A<R>, Args...), fn> { };
  int f(int, int);
  C<int(*)(int, int), &f> c;  // Previously a spurious error, now okay.


8/4/26   [EDGcpfe/28795]
Spurious deduction failure with dependent template template parameter

Previously, when a template template parameter depends on another template
parameter, the front end rejected a valid template template argument under the
C++17 "at least as specialized" matching rules, causing spurious deduction
failures.  For example, with --c++17:

  template<typename T, T>
  struct C { };
  template<typename T, template<typename, T> class TT>
  struct D { };
  template<typename T, template<typename, T> class TT1>
  void f(D<T, TT1>) { }
  void g() { f(D<int, C>{}); }  // Previously failed deduction, now okay.

In addition, when substituting into a template template parameter, a spurious
"hides template parameter" warning was issued if one of its parameters had the
same name as an enclosing template parameter declared after the template
template parameter.  For example, with --c++17:

  template<typename T, T>
  struct C { };
  template<template<typename T, T> class TT, typename T>
  struct D { };
  D<C, int> d;  // Previously a spurious warning, now okay.


7/30/26  [EDGcpfe/28517]
Spurious deduction failure with braced-init-list pack expansion

Deduction for a function template call could spuriously fail when substituting
template arguments into an expression containing a call with a braced-init-list
argument that contained a pack expansion.  For example, with --c++11:

  template<int> using A = int;
  struct C {
    static constexpr int f(int i) { return i; }
    template<int ... Is> using type = A<f({Is ...})>;
  };
  template<typename T, typename = typename T::template type<1>>
  int g();
  int i = g<C>();  // Previously failed deduction, now okay.


7/29/26  [EDGcpfe/26296,EDGcpfe/26412,EDGcpfe/26993,EDGcpfe/28172,
          EDGcpfe/28765]
Class members not found in lambdas instantiated from friend definitions

Previously, the front end failed to find enclosing class members by unqualified
name lookup from a lambda inside a function defined in a friend declaration
when that lambda was instantiated at a later point (e.g., while checking a
dependent noexcept specifier).  For example, with --c++14:

  template<typename T>
  int f(T t) noexcept(noexcept(t(1)));
  struct C {
    using type = int;
    friend int g(C) {
      return f([] (auto a) {
        return type{a};  // Previously a spurious error, now okay.
      });
    }
  };
  int i = g(C());


7/29/26  [EDGcpfe/28966]
Clang compatibility: Clang 23 builtins

The front end has been updated with the latest builtin signatures from Clang
version 23 (based on the recently-released RC2).


7/28/26  [EDGcpfe/24913,EDGcpfe/28969]
Spurious error on redeclaration of typedef with calling convention

Consider, in GNU C++ mode (in configurations supporting x86-32 calling
conventions):

  typedef void __attribute__((__stdcall__)) f(void);
  typedef void __attribute__((__stdcall__)) f(void);

Previously, this triggered a spurious redeclaration incompatibility error.
That is now fixed.


7/28/26  [EDGcpfe/28959]
Mem-initializer named with a template-id

Consider, in Microsoft mode (or in configurations in which class name injection
is disabled):

  template <class ...P> struct S : S<void, P>... {
    S(int i) : S<>(i) { }   // Previously bound to base class S<void, P>.
  };

The mem-initializer for S<> was previously bound to a base class that merely
shares the identifier S.  That is now fixed.


7/27/26  [EDGcpfe/28527]
Internal error on pack expansion for non-pack alias template parameter

A pack expansion used as an argument for a non-pack parameter of an alias
template could leave a later non-pack parameter without an argument, resulting
in an error type entry being inserted into the IL tree.  In some
configurations, that error type entry reached the mangling routines and
triggered an assertion failure in record_substitution_for_type.  Such uses are
now diagnosed, implementing the current direction of Core issue 1430 (which is
still open).  For example, with --c++11:

  template<typename T>
  using A1 = T;
  template<typename T, typename U, typename ... Vs>
  using A2 = A1<U>;
  template<typename ... Ts>
  using A3 = A2<Ts...>;  // Previously an internal error.
                         // Now an error.


7/27/26  [EDGcpfe/28979]
Abort in find_allocated_name_reference in some configurations

In configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE, an
explicitly-specified non-type template argument referring to a local constexpr
variable could in some cases trigger an internal error due to a failed
assertion in find_allocated_name_reference.  For example, with --c++14:

  using uint = unsigned;
  template<uint, int = 0> void f();
  auto l = [](auto) {
    constexpr uint U = 1 + 1;
    return [&](auto v) {
      f<U, sizeof v>();
      f<U>();  // Previously triggered an internal error, now okay.
    };
  };


7/25/26  [EDGcpfe/28952]
Enumerations with a fixed underlying type of bool

Enumerations with a fixed underlying type of bool (e.g., "enum E : bool;") had
been assigned an underlying integer type (as given by the TARG_BOOL_INT_KIND
and TARG_C_BOOL_INT_KIND configuration macros) but now retains the fact that
the underlying type is bool (i.e., a_type::variant.integer.bool_type is now
TRUE).


7/24/26  [EDGcpfe/28983]
Operand of [[assume(...)]] attribute

The front end previously processed the operand of the [[assume(...)]] attribute
as an unevaluated operand (i.e., similar to the operand of a sizeof operator).
Now it is handled as a potentially-evaluated operand.  If lowering is enabled,
that operand is lowered.


7/23/26  [EDGcpfe/28956]
is_empty_class_type

The function is_empty_class_type did not ensure that a template class passed
to it is instantiated before testing if it is empty.  This could, for example,
lead to wrong results from reflection queries.  That is now fixed.


7/23/26  [EDGcpfe/28971]
Abort in type_pointed_to on address cast to integer

Consider:

  void f(void *);
  void g() { f((void*)(long)(const void*)"a"); }

In some modes and configurations, this could result in an internal error in
type_pointed_to (which was passed an integer type of a ck_address constant).
That is now fixed.


7/23/26  [EDGcpfe/28974]
Explicitly-defaulted destructors and constexpr

Consider, in C++20 mode:

  struct X { int x; constexpr ~X() {} };
  struct S {
    X m;
    ~S() = default;  // Previously not considered constexpr.
  };
  constexpr S s{};   // Previously an error.  Now okay.

The front end previously did not mark an explicitly-defaulted destructor as
constexpr even though an equivalent implicitly-generated destructor would have
been so marked.  This is the case for the S::~S() destructor in the example
above, leading to a spurious error about the initializer of s not being
constant.  That is now fixed.


7/23/26  [EDGcpfe/26485,EDGcpfe/28496]
Internal error on generic lambda in a variable template member (IL CHANGE when
NEED_NAME_MANGLING is FALSE)

When instantiating a generic lambda in the initializer of a variable template
member of a class template, the front end could fail to restore the enclosing
variable template's instantiation context.  This could trigger an internal
error or lookup failures when the lambda called a function template with
another generic lambda.  For example, with --c++17:

  template<typename T>
  auto f(T t) -> decltype(t(0));
  template<int>
  struct C {
    template<typename>
    static constexpr auto l = [] (auto) { return f([] (auto) { return 0; }); };
  };
  int i = C<1>::l<int>(0);  // Previously triggered an internal error.
                            // Now okay.

With this change, the IL now always retains a lambda closure class's parent
entity information (previously, this was only done in configurations with
NEED_NAME_MANGLING set to TRUE).


7/22/26  [EDGcpfe/25686,EDGcpfe/28289,EDGcpfe/28965]
Spurious constraint satisfaction error with class template redeclaration

Previously, a redeclaration of a constrained class template could result in a
spurious constraint satisfaction error when using parameter packs in the
requires clause.  For example, with --c++20:

  template<typename ... Ts>
  concept X = sizeof ... (Ts) == 2;
  template<typename ... Ts> requires X<Ts ...>
  struct B;
  template<typename ... Ts> requires X<Ts ...>
  struct B { };
  B<int, int> b;  // Previously a spurious error, now okay.


7/21/26  [EDGcpfe/28957]
C++-generating back end: template parameter names with nested generic lambda

In some cases involving a generic lambda with explicit template parameters
nested inside another template, the C++-generating back end replaced the
name of a template parameter of the outer template with the name of the
corresponding template parameter of the generic lambda.  This is how fixed.
For example, with --c++20 --gnu_version=140200 --parse_templates:

  template <auto f> struct S {
    template <typename T> static constexpr bool value = true;
  };
  template <typename T>
    requires S<[]<typename U>() { return 0; }>::
      template value<T>   // Previously generated as "value<U>"
  void foo() {}


7/21/26  [EDGcpfe/20633,EDGcpfe/24974,EDGcpfe/28306]
Spurious exception specification instantiation error with exceptions disabled

Previously, in modes with exceptions disabled and where the exception
specification is not part of the function type, the front end would instantiate
a member function template exception specification when the enclosing class
template was instantiated.  For example, with --c++11 --no_exceptions:

  template<typename T>
  struct C {
    template<typename>
    void f(int) noexcept(T::v);  // Previously a spurious error, now okay.
  };
  C<int> c;


7/21/26  [EDGcpfe/24978,EDGcpfe/25610,EDGcpfe/26815,EDGcpfe/27444,
          EDGcpfe/27490,EDGcpfe/28447]
Braced initializers for template parameter initialization

The front end now supports braced initializers to initialize non-type template
parameters as specified in WG21 paper P2308R1 (adopted as a Defect Report).
For example, with --c++11:

  template<int>
  struct C { };
  C<{}> c0;  // Previously a spurious error, now okay.


Version 6.9, July 20, 2026

7/16/26  [EDGcpfe/28936]
Default encoding for source files

By default, most implementations now expect source files to be encoded as
UTF-8, and the default configuration of the front end has now been changed
accordingly.  The previous behavior may be restored by explicitly setting
UNICODE_SOURCE_SUPPORTED and/or DEFAULT_UNICODE_SOURCE_KIND as desired.


7/14/26  [EDGcpfe/28954]
C++26: value of __cplusplus

The value of the predefined __cplusplus macro in non-emulation C++26 modes
has been changed from its placeholder value of 202600L to the value given
in the C++26 Draft International Standard, 202603L.  As of this writing,
g++ (16.1.0) and clang (22.1.x) use the placeholder value of 202400L, and
MSVC (19.52) uses 199711L; the front end follows suit in its respective
emulation modes.


7/10/26  [EDGcpfe/26127,EDGcpfe/28803,EDGcpfe/28868,EDGcpfe/28930]
Exception specification of a defaulted default constructor with a folded
default member initializer

Since C++17 (P0003R5), a call to a function that does not have a non-throwing
exception specification is potentially throwing even when the call is a
constant expression.  When a default member initializer was a constant
expression, the front end folded it to a constant and then failed to account
for the (notional) constructor call that it performs, so the generated default
constructor could be incorrectly treated as non-throwing.  For example:

  struct S { int x; constexpr S() : x(0) {} };  // constexpr, not noexcept
  struct A { S m = S(); };
  static_assert(!noexcept(A()));  // now holds (previously failed)

A related case, in which the default member initializer belongs to a member of
an anonymous union, was also corrected:

  struct T { union { S u = S(); }; };
  static_assert(!noexcept(T()));  // now holds (previously failed)


7/10/26  [EDGcpfe/28942]
Use "_Bool/bool" types in generated C by default

In C-generating configurations, a C++ "bool" type had been emitted in the
generated C code as the underlying type (typically "char" or "int").  A
change has been made to now use "_Bool" instead.  If the back end C compiler
doesn't support "_Bool", the previous behavior can be restored by setting
octl.render_c99_bool to FALSE in c_gen_be_init.


7/10/26  [EDGcpfe/28941]
GNU and Clang C++ compatibility: unrestricted unions in pre-C++11 modes

GCC (since version 4.6) and Clang (since version 3.1) accept "unrestricted
unions" (i.e., unions with members whose types have nontrivial special member
functions, a C++11 feature) in their pre-C++11 modes, with a warning.  The
front end now matches that behavior in the corresponding GNU and Clang C++
modes.  For example:

  struct S { S(); };
  union U { S s; };  // Previously an error; now accepted with a warning.


7/10/26  [EDGcpfe/28928]
GNU and Clang C++ compatibility: variable templates in C++03 mode

The changes for EDGcpfe/27938,EDGcpfe/27974 (in version 6.8) enabled variable
templates in some GNU and Clang C++11 modes (with a warning).  It turns out
that the corresponding versions of GCC and Clang also accept variable templates
in their C++03 modes.  The front end now matches that behavior


7/10/26  [EDGcpfe/28927]
Structured bindings in Clang C++03 mode

The changes for EDGcpfe/20107 etc. (introduced in version 6.6) enabled
structured bindings in Clang C++11 mode when clang_version >= 40000.  It
turns out that Clang 4 and later also accept structured bindings in C++03
mode: The front end has been updated to match that behavior in corresponding
Clang C++03 modes.


7/10/26  [EDGcpfe/28926]
Lambda expressions in Clang C++03 mode

Lambda expressions are now accepted with a warning in Clang C++03 mode
when clang_version >= 190000.


7/10/26  [EDGcpfe/28925]
Enum-type name qualifiers in Clang C++03 mode

The front end now accepts enum-type name qualifiers with a warning in Clang
C++03 mode when clang_version >= 30700.  For example:

  enum E { e, f };
  auto r = E::e;  // Normally requires C++11, but
                  // accepted in Clang C++03 mode


7/9/26   [EDGcpfe/28915]
Diagnosis of non-C-like unnamed classes

The front end now more consistently issues a diagnostic in C++ modes when an
unnamed class type containing non-C-like constructs acquires a name for
linkage purposes. For example:

  typedef struct {
    struct N {
      void f(void) {}
    };
  } S;  // Now elicits a diagnostic.

The diagnostic is a discretionary error in strict mode and in non-permissive
Microsoft C++ modes with microsoft_version >= 1926.  In other modes, the
diagnostic is a warning.


7/9/26   [EDGcpfe/28913]
Assignment of empty class objects during constant evaluation

Assignment of an empty class type with trivial copy semantics does not
actually access or modify storage.  The front end previously rejected such an
assignment when the destination object's lifetime began outside the constant
evaluation, reporting an attempt to access run-time storage.  For example:

  struct E {} x;
  constexpr E y{};
  constexpr auto r = (x = y);  // Previously an error.  Now okay.

That is now fixed.


7/9/26   [EDGcpfe/28922]
_Float32 vs. float after a user-defined conversion

When ranking two user-defined conversion sequences that share the same
conversion function, a same-representation floating-point conversion (for
example, float to _Float32) was incorrectly preferred over an identity
conversion or a floating-point promotion.  For example, with --gnu=140200
--c++23:

  float g(float);
  _Float32 g(_Float32);
  template<typename T> struct X { operator T() const; };
  using R = decltype(g(X<float>{}));
    // R was previously _Float32; now float.

That is now fixed.


7/9/26   [EDGcpfe/24502,EDGcpfe/27855,EDGcpfe/28923]
GCC/Clang compatibility: Character zeros as null pointer constants

In C++11 and later modes, GCC 7 and later no longer treat a zero of character
type (for example, (unsigned char)0 or '\0') as a null pointer constant, and
Clang never did.  The front end previously still treated such expressions as
null pointer constants in GNU and Clang C++ modes, which could lead to
spurious errors.  For example, with --gnu_version=70000 --c++11:

  struct X {
    void operator+=(char*);
    void operator+=(char);
  };
  void g(X &msg) {
    msg += (unsigned char)0;  // Previously ambiguous; now okay.
  }

That is now fixed.  (Microsoft modes retain the prior behavior to match MSVC.)
In GNU C++ modes, casting a zero literal to a non-character integer type (for
example, (int)0) can still produce a null pointer constant, matching g++.


7/9/26   [EDGcpfe/28704,EDGcpfe/28938]
Internal error in record_substitution_for_type during constraint checking

Previously, constraint checking involving a failed variable template
specialization could result in an error type entry being inserted into the IL
tree.  In some configurations, that error type entry reached the mangling
routines and triggered an assertion failure in record_substitution_for_type.
For example, with --c++20:

  template<typename T> constexpr bool v = true;
  template<typename T> struct B { };
  struct C {
    template<typename T, bool = v<T>> operator T();
  };
  template<typename T> concept X = requires (T t) { B{t}; };
  static_assert(!X<C>);  // Previously triggered an assertion failure.
                         // Now okay.


7/8/26   [EDGcpfe/28909]
Internal error in copy_pack_expansion_descr_with_substitution

In some fairly complex cases involving class template argument deduction (CTAD)
for alias templates, the changes for EDGcpfe/28857 (not in a release) could
lead to an internal error in copy_pack_expansion_descr_with_substitution.  That
is now fixed.


7/8/26   [EDGcpfe/28924]
Pack expansion in CTAD for alias templates

Previously, the front end sometimes incorrectly expanded packs for dependent
sizeof..., fold, or pack indexing expressions when transforming deduction
guides for alias templates.  This could result in class template argument
deduction (CTAD) for alias templates deducing the wrong type.  For example,
with --c++20:

  template<typename, typename> constexpr bool is_same_v = false;
  template<typename T>         constexpr bool is_same_v<T, T> = true;
  template<typename T, int N>
  struct C {
    C(T*, auto ...);
  };
  template<typename T, typename... Us>
  C(T*, Us ...) -> C<T, sizeof ... (Us)>;
  template<typename T, int N>
  using A = C<T, N>;
  A a{"", 1, 2, 3};
  static_assert(is_same_v<decltype(a), A<const char, 3>>, "Unexpected");
    // Previously failed, now okay.


7/6/26   [EDGcpfe/28918]
GCC compatibility: PODness and [[no_unique_address]

Consider, in C++20 mode with the IA-64 ABI (and int a 4-byte-aligned type):

  struct PodOrNot {
    int i;
    [[no_unique_address]] char c;
  };
  struct S {
    [[no_unique_address]] PodOrNot x;
    char d, e, f;
  };
  static_assert(sizeof(S) == 8);

This fails with the EDG front end as well as with Clang, because PodOrNot is
considered a "POD for layout purposes": Ignoring the attributes, PodOrNot is
clearly a struct that could be expressed in C.  The tail padding of such a
"POD" class cannot be reused by a derived class or a [[no_unique_address]]
member.  However, it appears GCC treats the [[no_unique_address]] attribute in
PodOrNot as an aspect that disqualifies PodOrNot from being a "POD for layout
purposes".  That in turn allows the three bytes of tail padding of PodOrNot to
be used to store the members d, e, and f of S.  The front end now emulates
that behavior in GCC compatibility mode.


7/6/26   [EDGcpfe/26816]
Severity of narrowing diagnostics

In C++11 modes, the front end now diagnoses

  int x = { 42.0 };

with an error instead of a warning.  Note that other similar cases are still
diagnosed with a warning because existing practice for the severity of
diagnostics reporting violations of C++11 narrowing rules varies widely.  In
general, the front end prefers erring on the side of warnings since that is
more likely to be helpful in various compatibility modes.


7/6/26   [EDGcpfe/28937]
C++-generating back end: spelling of enum base types (IL CHANGE)

Previously, the IL did not record the spelling of an explicitly-specified base
type for each declaration of an enum.  For example, with --c++11:

  using uint1 = unsigned int;
  namespace ns {
    enum E : uint1 {};  // Previously generated as "enum E : ns::uint2 {};"
  }
  namespace ns {
    using uint2 = unsigned int;
    enum E : ns::uint2;
  }

Now, the base_type field of an enum type refers to the type specified in the
enum definition.  In configurations that maintain source sequence lists,
including C++-generating back end configurations, each opaque enum declaration
specifies its base type in the declared_type field of the corresponding
secondary source sequence entry.


6/25/26  [EDGcpfe/28920]
Intrinsic handling of std::is_integral_v

The changes for EDGcpfe/28491 allow the front end to handle the instantiation
of std::is_integral_v as an intrinsic.  However, it appears that for
std::is_integral_v<__int128> and std::integral_v<unsigned __int128> different
standard libraries produce different results.  The front end therefore no
longer handles std::is_integral_v<T> intrinsically if T is a 128-bit integer
type.


6/25/26  [EDGcpfe/28870]
C++23: Relaxed ref-qualifier overloading rule (P1787R6)

Two non-static member functions with the same name and parameter types, where
exactly one has a ref-qualifier, no longer always conflict in C++23.  This is
a consequence of committee paper P1787R6.  For example:

  struct S {
    S f(int) const;
    S f(int) &&;   // Now accepted in C++23 modes.
  };

This behavior is extended to GNU C++20 modes with gnu_version >= 160000
(to match GCC16's behavior).


6/23/26  [EDGcpfe/28911]
Suppressing template argument and name qualifier tracking

The changes for EDGcpfe/26294 in version 6.8 added information to the IL
that tracks the exact template argument list used in each reference to a
template instance as well as more thoroughly tracking the qualifiers used
to name various entities.  In some large and complex translation units,
this additional information can result in very significant overhead,
particularly in the depth of recursion when traversing the IL.  Previously,
the presence of this information in the IL was controlled by the value of
the DEFAULT_RECORD_FORM_OF_NAME_REFERENCE configuration macro.  A new
configuration macro has now been added to control this information: When
CREATE_LEXICAL_TYPEREFS is FALSE, this additional tracking information will
not be present in the IL, regardless of the value of
DEFAULT_RECORD_FORM_OF_NAME_REFERENCE.  If not explicitly set, its value is
the same as DEFAULT_RECORD_FORM_OF_NAME_REFERENCE.


6/23/26  [EDGcpfe/28910]
GNU C++ compatibility: __integer_pack in an initializer-list

In GNU C++ modes, the __integer_pack(N) construct is now accepted as an
element of an expression list (for example, a braced-init-list, a function
argument list, or a parenthesized initializer), in addition to the already-
supported template-argument context.

  template<auto N, typename T>
    constexpr T zeroAndUp[N] = { __integer_pack(T(N))... };


6/23/26
Clang compatibility: __-prefixed _BitInt literal suffixes

In Clang 19 and later modes, integer literals can use the __wb and
__uwb suffixes, with the same _BitInt width selection as the standard
wb and uwb suffixes.  In Clang C++ mode, the standard wb and uwb
spellings remain unavailable.


6/23/26  [EDGcpfe/28862]
C++-generating back end: Missing cast on address of overloaded member

Consider:

  struct S {
    void f();
    void f(int);
  };
  template <class T> struct W {};
  int main() {
    W<decltype(static_cast<void (S::*)(int)>(&S::f))> w;
  }

Previously, the C++-generating back end rendered the decltype operand as
"decltype((&S::f))", which is ill-formed because f is overloaded.  This
happened when a constant in the file-scope memory region had its backing
expression in a function-scope memory region: The link to that expression was
then discarded.  The backing expression is now reached indirectly through an
a_local_expr_node_ref entry, which in turn enables the rendering of the
original decltype operand.


6/23/26   [EDGcpfe/26109,EDGcpfe/28827]
Enumerations with a bool underlying type

An enumeration with a fixed underlying type of bool can represent only the
values false and true.  Two problems with such enumerations have been fixed:

  enum E : bool { e0, e1 };
  static_assert((int)(E)42 == 1);  // Now okay.
  enum F : bool { f0, f1, f2 };    // Now an error.

Converting a value to such an enumeration failed to first convert it to
bool, as required by the standard.  For example, "(int)(E)42" now
yields 1 (the value of "(E)true") rather than 42 (as it did previously).

An enumerator whose value is outside the range of bool (here f2, whose
underlying value would be 2) was not diagnosed.  Now such an out-of-range
enumerator elicits an error (a warning in Microsoft mode).


6/22/26   [EDGcpfe/28907]
Internal error when substituting incomplete or abstract types

Consider the following case:

  template<typename T> void foo(T) { };
  struct Incomplete;
  int main() {
    foo<Incomplete>(0);
  }

While substituting an abstract or incomplete type during a function template
instantiation, the EDG front end sometimes emitted an internal error instead of
an appropriate diagnostic.  This issue is now fixed.


6/22/26  [EDGcpfe/28905]
Microsoft mode abort on incomplete struct typedef

Consider, in Microsoft mode:

  typedef struct {

Previously, this aborted with an internal error in pop_scope_full
(scope_stk.c).  That is now fixed.


6/22/26  [EDGcpfe/28865]
GCC and Clang C++ compatibility: Conversion function preferred in direct
initialization
 
In direct-initialization of a class type, older GCC (before GCC 14) and Clang
may prefer a conversion function that is eligible for copy elision over a
constructor that would otherwise be selected through a standard conversion
sequence.  Consider:

  struct X;
  struct Y {
    constexpr Y() {}                     // (1)
    constexpr explicit Y(const X &) {}   // (2)
  };
  struct X { constexpr operator Y() { return Y(); } };
  Y var(X{});

The committee resolved this via Core issue 2327 (with paper P2828): The
conversion function is not a candidate here, so the explicit converting
constructor (2) is called.  The front end already implemented that resolution
by default.  When emulating an earlier GCC version (gnu_version < 140000) or
any Clang version, the front end now matches their behavior: X::operator Y is
selected (initializing var through the eliding copy/move constructor (1)) when
its implicit object parameter is the better reference binding -- here X& is
less cv-qualified than the const X& of (2).  When the two bindings are
indistinguishable (for example, if operator Y were const-qualified), the
converting constructor (2) is kept.


6/19/26  [EDGcpfe/28898]
Overflow of hexadecimal and delimited octal characters on 32-bit host

On host platforms for which type "long" is 32 bits, the front end
previously issued spurious "character value out of range" errors for
hexadecimal and delimited octal characters whose values exceed 0x7fffffff.
This is now fixed.  For example,

  char32_t *str = U"\x80000000";   // Previously a spurious error


6/17/26  [EDGcpfe/28899]
Intrinsic treatment of commonly-occurring class template type members

The front end now can recognize attempts to substitute constructs like
std::remove_cv<T>::type and produce the resulting type without instantiating
the underlying class template.  The framework to customize this handling is
very similar to that for alias templates (see the entry for EDGcpfe/28580).
The intrinsic treatment is enabled when the global variable
templ_type_member_intrinsics_enabled is TRUE.  That variable is initialized by 
the new configuration macro DEFAULT_TEMPL_TYPE_MEMBER_INTRINSICS_ENABLED (which
is TRUE by default).  The variable can also be controlled from the command line
with the --set_flag/--clear_flag options.  See the comments in sys_predef.h for
how to add support for additional templates.


6/16/26  [EDGcpfe/28571]
Command-line option --top_templates=N

The front end now supports a command-line option --top_templates=N that reports
the templates that were substituted the most.  N specifies how many templates
to report; if N is zero, every template with a nonzero number of substitutions
is reported.  The data needed for the report is collected only when the option
is specified.


6/16/26  [EDGcpfe/28590]
Regression in concept subsumption

The changes for EDGcpfe/28019 (in version 6.8) were incomplete in a way that
theoretically could trigger aborts, but none were observed.  The missing change
is now applied.


6/16/26  [EDGcpfe/28886]
Implicit "typename" on friend declaration in template

Consider, in C++20 mode:

  template<typename> struct X { using type = int; };
  struct S {
    template<typename T> friend X<T>::type f(S);
  };
 
Previously, this elicited a spurious error about a missing "typename" keyword
before the return type X<T>::type.  That is now fixed.


6/16/26  [EDGcpfe/28884]
Clang __builtin_invoke and pointer-to-data-member

The intrinsic handling of __builtin_invoke (accepted in some Clang C++ modes)
failed to handle pointer-to-data-member cases.  That is now fixed.


6/16/26  [EDGcpfe/28894]
GNU compatibility: GCC 15.3 builtins

The front end has been updated with the latest builtin signatures from GCC
version 15.3.


6/15/26  [EDGcpfe/28839]
Improved handling of GNU statement expressions

The changes for EDGcpfe/28806 exacerbated pre-existing issues with the handling
of IL representing GNU statement expressions, particularly when that IL needed
to be allocated in file scope memory.  Often, these issues manifested as
"IL write-read" errors, although other aborting modes were also observed.
All known issues in this category are now fixed.


6/15/26  [EDGcpfe/28885]
Clang compatibility: exclude_from_explicit_instantiation attribute

The front end now accepts Clang's exclude_from_explicit_instantiation attribute
when clang_version >= 80000.  For example, with --clang_version 220100:

  template<typename T> struct C;
  template<typename T>
  struct B {
    __attribute__((exclude_from_explicit_instantiation)) int f() {
      return C<T>::v;
    }
  };
  template struct B<int>;  // Does not cause the instantiation of B<int>::f().


6/10/26  [EDGcpfe/25372]
Warning when --create_pch is used but no PCH file is created

When the --create_pch command-line option is specified but no precompiled
header file is written for some reason (such as the translation unit not
having any #include directives), a warning is now issued.  For example:

  edgcpfe --create_pch=foo.pch empty.c

where empty.c contains no #include directives.


6/10/26  [EDGcpfe/25301]
Missing diagnostic for redeclaration of deduction guide

Formerly, duplicate user-declared deduction guides were accepted by the front
end.  An error is now diagnosed for such cases, except in g++ mode with
gnu_version less than 110000 or in clang mode with clang_version less
than 90000.

  template <class T> struct S {
    template <class U> S(U &&u) {}
  };

  template <class U> S(U &&) -> S<U>;
  template <class U> S(U &&) -> S<U>; // now an error in most modes


6/9/26   [EDGcpfe/28887]
C++-generating back end: elaborated type specifier in explicit temporary

As a result of the changes for EDGcpfe/26294 in version 6.8, in some cases
involving an explicit temporary of a tag type whose name is hidden by the
name of a non-type entity, the C++-generating back end could put out the
type's name using an elaborated type specifier, which is syntactically
incorrect.  This is now fixed.  For example, with --c++17:

  struct A { };
  using T = A;
  namespace ns { struct T { }; }
  inline ns::T f() {
    return ns::T{};   // Previously generated as "struct ns::T{}"
  }
  using namespace ns;


6/9/26   [EDGcpfe/28844]
Clang compatibility: Enable C++ standard attributes in all modes

When clang_version >= 170000, C++ standard attributes are now enabled in all
C++ modes.


6/9/26   [EDGcpfe/25813]
PCH issue with unnamed_field_symbol

The pointer returned by unnamed_field_symbol was a local static variable.
When a precompiled header was used, only the symbol header was restored
from the PCH file; the symbol itself was not initialized, and pointers in
anonymous-field entries could refer to the address of the local static
from the process that created the PCH.  The symbol is now dynamically
allocated, its pointer is saved in the PCH file, and unnamed_field_symbol
has been renamed to get_unnamed_field_symbol.  With these changes the
issue is now fixed.


6/9/26   [EDGcpfe/27232]
Spurious "**NON FILE SCOPE PTR**" in IL display with the alternate IL
file format)

When displaying intermediate language with the alternate IL file format,
pointers to string entries could be labeled "**NON FILE SCOPE PTR**" even
though the string remained in file-scope memory.  During IL output,
assign_entry_number records the memory region kind in the file_scope flag
of the entry prefix for the region from which the string is referenced.
The IL display program now labels such string entries "**possible
non-file-scope ptr**".


6/6/26   [EDGcpfe/28882]
C++-generating back end, GNU compatibility: decltype type dependency

In the following example,

  template <typename T> struct A { using E = T; };
  template <typename T> struct B  { using V = T; };
  template <typename T> struct C {
    B<A<double>> v;
    typename decltype(v)::V::E x;   // #1
  };

g++ treats the type in the line marked #1 as dependent when compiling for
C++17, requiring use of the "typename" keyword.  As a result of the changes
for EDGcpfe/26294 in version 6.8, the C++-generating back end incorrectly
omitted the "typename" keyword in the generated code for this example.  This
is now fixed.


6/6/26   [EDGcpfe/28878]
C++-generating back end: invalid decltype operand

In some complex cases, the C++-generating back end emitted a decltype
operator whose operand was invalid, involving either an out-of-scope name
or a generated temporary name (of the form __T12345678).  This is now fixed,
and the underlying type of the decltype specifier in such cases is used
instead.


6/2/26   [EDGcpfe/28712]
Template-head requires clauses on implicit deduction guides

Previously, implicit deduction guides synthesized from a constructor template
did not include template-head requires clauses from the class or constructor
template.  Class template argument deduction (CTAD) could therefore fail or
select an unsuitable guide.  For example, with --c++20:

  template<typename ... Ts>
  struct C {
    C(Ts ...);
    template<typename U> requires false
    C(U u);
  };
  C c(1);  // Previously a spurious error.  Now okay.


6/2/26   [EDGcpfe/28875]
C++-generating back end: Extraneous parentheses rendered on decltype construct

Consider, in GNU C++11 mode:

  struct Inner { int x = 0; };
  struct Outer { Inner member{}; };
  using MemberType = decltype(Outer{}.member);

Previously, the C++-generating back end added extraneous parentheses around the
decltype operand, which in turn changed the resulting MemberType type.  That is
now fixed.


6/1/26   [EDGcpfe/28877]
C++-generating back end: globally-qualified dependent non-type template args

In some cases involving a globally-qualified dependent non-type template
argument, the C++-generating back end could omit the leading "::" from the
argument.  Depending on how the template is used, this omission could
result in incorrect mangling and linkage errors when the generated code was
compiled.  This is now fixed.  For example, with --c++17:

  template<typename T> constexpr inline bool v = false;
  template<bool> struct S { using t = int; };
  template<typename T> void f(typename ::S<::v<T>>::t);  // Previously omitted
                                                         // "::" before "v"


6/1/26   [EDGcpfe/28872]
C++-generating back end: functional-notation casts to hidden tag types

The C++-generating back end sometimes generated incorrect code for a cast
to a class or enumeration type whose name is hidden by the name of a
non-type entity.  The C++-generating back end now uses an equivalent
typedef name if one is available in such cases.  For example, with --c++11:

  struct A { };
  void A(int);   // Hides struct A
  struct B {
    struct A a;
    typedef struct A BA;
  };
  static B b1 = {B::BA{}};   // Previously generated "b1 = {struct A{}}",
                             // which is syntactically incorrect
  static B b2 = {B::BA()};   // Previously generated "b2 = {A()};", which
                             // names the function, not the class


6/1/26   [EDGcpfe/28674]
Internal error in find_template_variable during constraint checking

In Microsoft mode, the front end could abort with an internal error in
find_template_variable while checking a constraint that referred to a variable
template specialization, when that check was triggered in a further nested
template context.  For example, with --ms_c++20:

  template<typename T> constexpr int v = 1;
  template<typename T> struct X {
    template<typename V>
    operator V() requires(v<T> == 1);
  };
  auto b = [](auto p) {
    return requires { p + X<int>(); };  // Previously triggered an internal
  }(1);                                 // error.  Now okay.


5/29/26  [EDGcpfe/25899,EDGcpfe/27503,EDGcpfe/28820]
C23: _BitInt support

In C23 mode, the front end now supports C23 _BitInt types, as specified by the
C standardization committee's paper N2763.  A limitation of this initial
implementation is that literals and constant-evaluated values have to fit in
an_integer_value.  For example, if an_integer_value is limited to 128-bit
values, _BitInt(1024) may be accepted as a type, but a _BitInt literal like
1234567890123456789012345678901234567890wb (which requires more than 128 bits
to represent) will elicit an error.  In addition to C23 mode, the front end
also accepts _BitInt types:
  - in all (i.e., pre-C23) GNU C modes with gnu_version >= 140000, and
  - in all Clang C and C++ modes with clang_version >= 140000.
In Clang C++ modes, _BitInt literal suffixes are currently not accepted (Clang
C++ does not accept the standard suffixes either, but offers alternative
suffixes which the current front end does not emulate).  The command-line
option --[no_]bit_precise_integers explicitly enables or disables this feature.


5/28/26  [EDGcpfe/28866]
C++-generating back end: elaborated type specifiers in base specifier lists

As a result of the changes for EDGcpfe/26294 in version 6.8, the
C++-generating back end sometimes used an elaborated type specifier to
name a base class in the base class list of a class definition.  This is
now fixed.  For example:

  class A {
  protected:
    class I {};
  };
  class B : public A {};
  struct C : public B {
    struct I : public B::I {};  // Previously generated as "class B::I"
  };


5/28/26  [EDGcpfe/28861]
Clang and GCC compatibility: Type of captures in lambda headers

The entry for EDGcpfe/21022,EDGcpfe/21246,EDGcpfe/24784,EDGcpfe/25500 described
changes implementing support for P2579, which affects the types of captured
entities in lambda headers.  At the time, it appeared MSVC, GCC, and Clang did
not implement that Defect Report.  Since then support was added in Clang 17
and GCC 16: The front end now emulates that in its corresponding modes.
Moreover, the front end made no exception for Clang, GCC, and Microsoft modes
when the potentially-captured entity appeared in an unevaluated context.  That
is now fixed as well.


5/28/26  [EDGcpfe/28060,EDGcpfe/28845]
Clang compatibility: Accept new C++ features in older C++ modes

In Clang mode with clang_version >= 90000, the front end now accepts:
  - generic lambdas in pre-C++14 modes,
  - initializer declarations in selection statements (like "if (int x = 0; x)")
    in pre-C++17 modes,
  - "if constexpr" in pre-C++17 modes, and
  - init-captures in pre-C++17 modes.

In such situations a warning is issued about the feature not being standard
in that mode.


5/28/26  [EDGcpfe/28669]
New configuration macro for RISC-V vector builtins

A new configuration macro, RISCV_VECTOR_BUILTINS_ENABLED, controls whether the
automatically-generated RISC-V vector builtin tables in builtin_defs.h are
included in the front end build.  Those tables (introduced for EDGcpfe/28572)
contain a very large number of entries and can account for a significant
fraction of the resulting binary size.  When building the front end with the
Microsoft C++ compiler, including these tables may require the /bigobj option
because of object file size limits.


5/28/26  [EDGcpfe/28661]
Incorrect reuse of dependent class instantiation during alias instantiation

During alias template instantiation, a dependent class template instance could
be incorrectly reused, resulting in spurious errors.  For example, with
--c++11:

  template<int> struct B;
  template<> struct B<2> {
    template<typename T, typename> using A = T;
  };
  template<typename ... Ts>
  using A1 = typename B<sizeof ... (Ts)>::template A<Ts ...>;
  template<typename ... Ts> using A2 = A1<char, Ts...>;
  template<typename ... Ts> struct C;
  template<typename ... Ts> struct C<A2<Ts ...>, Ts ...> { };
  C<char, int> c;  // Previously a spurious error, now okay.


5/27/26  [EDGcpfe/28339,EDGcpfe/28819]
Deduction of Clang "ext_vector" types

Consider, in Clang C++ mode:

  template<typename T, unsigned long N>
    using V __attribute((ext_vector_type(N))) = T;
  template<typename T, unsigned long N> int f(V<T, N>);
  V<short, 8> v;
  int r = f(v == v);  // Previously an error.  Now okay.

Previously, this resulted in a spurious error due to deduction failure.
There were multiple causes for that failure (including incorrect handling
of the result of v == v, which is a "boolean vector"): All the causes are
now fixed and the example is now accepted.


5/27/26  [EDGcpfe/28423]
Spurious error on fold expression in disambiguating prescan

Previously, a unary right fold could result in a spurious error during a
disambiguating prescan.  For example, with --c++17:

  template<auto ... Is>
  decltype((Is + ...)) f();  // Previously a spurious error, now okay.
  int i = f<1>();


5/27/26  [EDGcpfe/28365,EDGcpfe/28690]
Spurious ADL failure in a generic lambda in a friend definition

The changes for EDGcpfe/27707 (in version 6.8) introduced a regression when
--defer_parse_function_templates is enabled (as is usually the case in GNU C++
modes).  A call inside a generic lambda in a function defined in a friend
function declaration of a class template could fail to find a friend function
by argument-dependent lookup (ADL).  For example, with --c++14
--defer_parse_function_templates:

  template<typename> struct D1;
  template<typename> struct D2;
  template<typename T> struct B { using type = int; };
  template<typename T> using A = B<D2<T>>;
  template<typename T> struct C { using type = typename T::type; };
  template<typename T> struct C<D1<T>> : C<A<T>> {};
  template<typename T> struct S1 {
    using type = typename C<D1<T>>::type;
    friend int g(S1);
  };
  template<typename T> struct S2 {
    friend int f(S2) {
      return [] (auto) {
        return g(S1<T>{});  // Previously a spurious error, now okay.
      } (1);
    }
  };
  int i = f(S2<int>{});


5/21/26  [EDGcpfe/28849]
GCC/Clang compatibility: CTAD for alias templates in pre-C++20 modes

In Clang 19+ modes, the front end now accepts the C++20 class template argument
deduction (CTAD) for alias templates feature with a warning in pre-C++20 modes.
In GCC 10+ modes, the feature is accepted only for simple alias templates (see
the entry for EDGcpfe/28073).


5/20/26  [EDGcpfe/28859]
Spurious parsing error on parenthesized lambda in template declaration

Consider, in C++17 mode:

  template<int I = ([]{ if constexpr (true) return 42; } )()>
  int f() { return I; }

The front end attempted to cache the tokens of the default template argument,
but did so incorrectly and issued a number of spurious errors as a result of
the incorrect caching.  That is now fixed.


5/20/26  [EDGcpfe/28857]
CTAD for type template template parameters

The front end now supports class template argument deduction (CTAD) when the
placeholder for a deduced class type designates a type template template
parameter, as specified in WG21 paper P3865R3.  Because the paper was adopted
as a Defect Report, this change applies in all modes that support class
template argument deduction.  For example, with --c++17:

  template<typename T = char>
  struct C {
    C(const char *);
  };
  template<template<typename T = int> class TT>
  void f() {
    TT t = "";  // Previously deduced as C<char>, now deduced as C<int>
  }
  template void f<C>();


5/19/26  [EDGcpfe/28855]
C++-generating back end, GNU compatibility: template alias designating a
template parameter

G++ has a bug that causes it to report spurious errors when the "typename"
keyword is used with an alias template specialization that resolves to a
template parameter when the alias template is a member of a non-dependent
class type.  For example, with --gnu_version=140200 --c++17:

  template <typename T> using A = T;
  template <typename> struct B {
    template <typename T> using C = T;
  };
  template <typename> struct D {
    template <typename T,
              int (*)(A<D<B<int>::C<T>>>)>
    void f();
  };

The C++-generating back end previously put out the second template parameter
of D::f as:

    int (*)(A<D<typename B<int>::template C<T>>>)

triggering the g++ bug, since B<int> is not dependent and B<int>::C<T> is
simply T, a template parameter.  The C++-generating back end has now been
modified to treat such types as non-dependent when
gcc_is_generated_code_target is TRUE, thus suppressing the "typename" and
"template" keywords that would otherwise be present.


5/18/26  [EDGcpfe/22563,EDGcpfe/28133,EDGcpfe/28800]
Operands of feature-test macro operators

At the time feature-test macro operators like __has_attribute were
implemented in the front end, clang did not macro-expand the operands, and
the front end followed suit for all emulations, including for the C++
standard __has_cpp_attribute operator, as the Standard originally did not
specify whether the operand was macro-expanded or not.  However, core issue
2390, which was adopted as a Defect Report and thus applies to all versions
of the Standard, resolved this omission by requiring the operand to be
macro-expanded.  Furthermore, beginning with version 14.0, clang now
macro-expands these operands, as gcc has done since it originally
implemented them.  The front end has now been changed to use the unexpanded
version of such operands only in clang mode with clang_version at least
30300 and less than 140000; in all other cases, it macro-expands the
operand before processing it.  For example, with --gnu_version=120300, the
following code compiles without error, while it fails with the #error
report with --clang_version=130000:

  #define A noreturn
  #define B A
  #define C B
  #if !__has_attribute(C)
  #error __has_attribute operand not expanded
  #endif


5/15/26  [EDGcpfe/28853]
Multi-TU IL scope list corruption

In rare cases the IL scope's list of associated IL entities could become
corrupted in multi-translation unit mode.  This is now fixed.


5/11/26  [EDGcpfe/28840]
C++-generating back end: missing "typename" keyword for dependent decltype

In some cases, the changes for EDGcpfe/26294 in version 6.8 could result in
the C++-generating back end failing to emit a necessary "typename" keyword
preceding a dependent decltype used as a name qualifier.  This is now fixed.
For example, with --c++17 --gnu_version=130300:

  struct Inner { typedef int tp; };
  template <class T> struct Outer {
    Inner m;
    void f() {
      static_cast<typename decltype(m)::tp>(0);  // Previously omitted
                                                 // "typename"
    }
  };


5/11/26  [EDGcpfe/28841]
Regression resulting in rare loss of a preceding pragma

With the changes for EDGcpfe/28636 (not in a release but distributed to
customers in a patch), a rare situation could arise if customers added a new
immediate pragma that does not fetch pp-tokens and accepts a string argument,
e.g.:

  #pragma warning(push) // previously would go missing
  #pragma test_immediate "x"

This is now fixed.


5/11/26  [EDGcpfe/25516]
C++23: CTAD for inheriting constructors

The front end now supports class template argument deduction (CTAD) for
inheriting constructors, as specified in WG21 paper P2582R1.  For example, with
--c++23:

  template<typename T>
  struct B {
    B(T);
  };
  template<typename T>
  struct D : B<T> {
    using B<T>::B;
  };
  D d(1);  // Now deduced as D<int>

The IL routine entry for a deduction guide generated from an inheriting
constructors has its is_deduction_guide_from_inheriting_ctor flag set to TRUE.


5/9/26   [EDGcpfe/28837]
C++-generating back end: invalid qualification of member function in nontype
template argument

As noted in the entry for EDGcpfe/12641, early versions of g++ had a bug
that required that a member function name used in a nontype template
argument be written as a qualified-id, and the C++-generating back end was
modified to use a qualified name in such contexts.  However, it is not
always possible to produce a valid qualified-id for a member function of a
class template.  For example, consider

  template<int> struct A { };
  template<class> struct B {    // template parameter is unnamed
    static constexpr int f() { return 0; }
    void g(int B) {  // Function parameter B hides the injected-class-name B
      A<f()>{};      // Previously generated as A<::B::f()>, since the template
                     // parameter for ::B cannot be named
    }
  };

When compiled with --c++17 --clang_version=190100, the generated code could
not be compiled.  Since the g++ bug requiring use of a qualified-id was
fixed in gcc version 6.1, the C++-generating back end now only forces
generation of a qualified-id when gcc_is_generated_code_target is TRUE and
gnu_target_version_number is less than 60000.


5/8/26   [EDGcpfe/28295]
Class template argument deduction from default template argument

Consider, in C++20 mode:

  template<int N> struct CTStr {
    constexpr CTStr(char const (&)[N]) {}
    void func() const {}
  };
  template<CTStr Name = ""> struct S {
    void f() const {
      Name.func();
    }
  };
  int main(){
    S{}.f();
  }

Previously, the front end mistakenly deduced a type char const* instead of
CTStr<1> for the deduced template argument of S in S{}.  In turn, this
triggered a spurious error on the call Name.func().  That is now fixed.


5/7/26   [EDGcpfe/26684,EDGcpfe/27846]
Microsoft compatibility: Concatenation with __FUNCSIG__

In Microsoft mode, the front end now accepts code such as

  int main() {
    static_assert(true, " " __FUNCSIG__);
  }

where __FUNCSIG__ is handled as a string literal that can be concatenated
similarly to ordinary preprocessing string literals (however, that
concatenation is handled at the expression level).


5/7/26   [EDGcpfe/13839,EDGcpfe/22461,EDGcpfe/28774]
Incorrect field used for anonymous unions in lowered subobject classes

The lowering process adjusts expressions that refer to anonymous union fields
and in doing so had inadvertently used fields in a complete object class
rather than the subobject class.  This invalid IL could cause problems for
back ends and had resulted in an assertion failure
("dump_field_from_second_operand: wrong field class") in C-generating back end
configurations configured for the IA-64 ABI.  For example (with --c++11):

  struct A {
    virtual void f();
    union {int x = 37;};
  };
  struct B : A {
    constexpr B() {}
  };
  auto x = new B[0]{ {} };


5/7/26   [EDGcpfe/28835]
GNU compatibility: GCC 16.1 builtins

The front end has been updated with the latest builtin signatures from GCC
version 16.1.


5/6/26   [EDGcpfe/26684,EDGcpfe/27846,EDGcpfe/28831]
Spurious error on use of __FUNCSIG__ in template

Consider, in Microsoft C++ mode with --parse_templates (or other options
forcing the parsing of function templates in their generic form):

  namespace Envir {
    namespace N {
      struct E {};
      template<typename T> constexpr E f() {
        static_assert(__FUNCSIG__[13] != 'X', "");
        return {};
      }
    }
  }
  namespace NN { struct Tag; }
  constexpr auto r = Envir::N::f<NN::Tag>();

Previously, this elicited a constant-evaluation error in some configurations
with a C++-generating back end because __FUNCSIG__ records the string
"__FUNCSIG__" during prototype instantiations and subscripting that string
with index 13 reaches outside the bounds of the string.  That is now fixed:
The string is treated as template-dependent in that context.


5/5/26   [EDGcpfe/28824]
C++-generating back end drops explicit cast needed for deduction

Consider:

  template<typename ...Ts> struct Seq {
    Seq() = default;
    explicit Seq(Ts...);
    Seq(Seq const&) = default;
    Seq(Seq&&) = default;
  };
  int main() {
    using S = Seq<void*, int>;
    Seq seq(S(nullptr, 42));
  }

Here, the initialization of seq and the cast to S correspond to a single
initialization due to copy elision.  As a consequence, the C++-generating back
end previously rendered the initialization as "Seq seq(nullptr, 42);", which
deduces a type for seq that is Seq<nullptr_t, int> instead of the intended
type S (i.e., Seq<void*, int>).  This is now fixed by recording the presence
of the cast in the variable initialization entry.


5/4/26   [EDGcpfe/28826]
C++-generating back end: extraneous class keyword in explicit temporary

The C++-generating back end sometimes incorrectly added a class keyword in
an explicit temporary expression.  This is now fixed.  For example, with
--c++23:

  namespace N1 {}
  namespace N2 {
  using namespace N1;
  }
  namespace N1 {
  class C {
  public:
    enum E { e0 };
    C(E, int);
  };
  } // namespace N1
  namespace N2 {
  using C = struct {
    int f();
    // Previously added "class" keyword at the beginning of the initializer:
    //        ... = class N1::C(...
    N1::C stream_ = N1::C(N1::C::E::e0, f());
  };
  }


5/4/26   [EDGcpfe/28826]
ADD_CHECKING_PRAGMAS_FOR_INTERNAL_TESTING not reported in config dump

Previously, ADD_CHECKING_PRAGMAS_FOR_INTERNAL_TESTING was not included in the
configuration options dumped by --dump_configuration.  This is now fixed.


5/1/26   [EDGcpfe/28823]
Unsigned comparison warnings in template instantiations

Consider:

  template<unsigned N> bool f(unsigned x) {
    return x < N;
  }
  bool r = f<0>(1);

Previously, the instantiation of f<0> triggered a warning about the comparison
x < N always being false.  However, such diagnostics are not very helpful
since they depend on particular template arguments.  The front end therefore
no longer issues such diagnostics in real template instantiations.  (They are
still emitted in prototype instantiations: If a comparison would be pointless
for all instantiations, a warning will then still be emitted.)


5/1/26   [EDGcpfe/28825]
C++-generating back end: volatile-qualified parameter types

In general, the C++-generating back end attempts to preserve the source
form of the program as faithfully as possible in the generated code.  An
exception has now been made, however, for "volatile" qualifiers in function
parameter declarations.  WG21 paper P1152R4, adopted for C++20, deprecated
such declarations, and current compilers issue diagnostics for them.  In
view of these developments and the fact that the actual type of the
parameter is unaffected by the presence or absence of top-level
cv-qualification, the C++-generating back end now suppresses "volatile"
qualifiers appearing in the source code when generating parameter
declarations.  For example:

  void f(volatile int);   // Now generates "void f(int);"


4/30/26  [EDGcpfe/24302,EDGcpfe/28505]
Spurious pack expansion error for default template argument of member template

Previously, a pack expansion where the pattern refers to a member template with
default template arguments could result in a spurious pack expansion error.
For example, with --c++11:

  template<typename ... Ts>
  struct B { };
  template<typename ... Ts>
  struct C {
    template<typename T, typename U = T>  // Previously a spurious error.
    struct A;                             // Now okay.
    B<A<Ts> ...> b;
  };


4/27/26  [EDGcpfe/28808]
cv-qualification in auto(x) and auto{x}

The front end previously erroneously preserved top-level cv-qualification on
class prvalues produced by C++23 functional-notation casts to "auto".  That is
now fixed.  For example:

  struct S {};
  S const s;
  S &&r = auto(static_cast<S const&&>(s));  // Previously an error.
                                            // Now okay.


4/27/26  [EDGcpfe/28804]
if consteval in C++20 modes

The front end now accepts "if consteval" and "if not consteval" in C++20 mode
with a warning, matching the behavior of other compilers.  In strict ANSI mode,
the diagnostic uses the configured strict ANSI error severity instead.  For
example, with --c++20:

  consteval int f(int i) { return i; }
  constexpr int g(int i) {
    if consteval {
      return f(i);  // Now accepted with a warning in C++20 mode.
    }
    return 0;
  }


4/27/26  [EDGcpfe/28801]
Assertion failure on constexpr variable template with class temporary

Consider, in C++20 mode:

  struct D {
    constexpr ~D() {}
  };
  struct S {
    D a = D{};
  };
  template<typename T> constexpr auto v = T{}.a;
  D vs = v<S>;

Previously, the front end aborted with an assertion failure in
unbundle_init_component_expressions in overload.c, due to inconsistent
handling of the initial parsing of the initializer for the instantiation of
v<S> to determine its deduced type and the subsequent processing of that
initializer to complete the representation of vs.  That is now fixed.


4/26/26  [EDGcpfe/26823,EDGcpfe/27650]
C++26: Pack indexing (IL CHANGE)

The front end now supports pack indexing, which has been adopted for the
upcoming C++26 Standard via WG21 paper P2662R3.  For example, with --c++26:

  template<int I, typename ... Ts>
  constexpr auto f(Ts ... vs) -> Ts ... [I] {
    return vs ... [I];
  }
  static_assert(f<0>(1, 2L) == 1 && f<1>(1, 2L) == 2L);

A dependent type pack-index-specifier is represented as a trk_pack_index
typeref, and a dependent pack-index-expr is represented as an enk_pack_index
expression node.


4/24/26  [EDGcpfe/28806]
Regression in library use of find_assoc_pragma

The changes for EDGcpfe/27282 (in version 6.7) introduced a regression by
changing where in the IL pragmas are represented.  This change was not
reflected in find_assoc_pragma, resulting in pragmas associated with classes
not being found.  This is now fixed.


4/23/26  [EDGcpfe/28810]
C++-generating back end: missing name qualifier in trailing return type

In some cases, the C++-generating back end could omit the name qualification
required when a function parameter name hides a name in a containing scope
that is used in the function's trailing return type.  This is now fixed.
For example, with --c++20:

  int x;
  template <int *> struct A { }; 
  auto f(int x) -> decltype(new A<&::x>);   // Previously omitted "::"


4/23/26  [EDGcpfe/28807]
Unbounded loop computing preorder base class list in C++/CLI mode

In configurations with IA64_ABI set to TRUE, the front end maintains a list of
base classes in "preorder traversal order".  This list is normally computed
once the base class list is complete, but with C++/CLI managed class types it
is possible for additional base classes to be implicitly added long after the
base class list has been parsed: This requires the preorder list to be
recomputed.  Previously this recomputation was done erroneously such that the
front end could get stuck in an unbounded loop.  That is now fixed.


4/23/26  [EDGcpfe/28759]
Clang compatibility: incorrect lookup bug emulation

The front end emulates a g++ lookup bug (in g++ versions prior to 6.x) that
treats certain names as templates without the use of the "template" keyword.
However, this emulation was incorrectly also enabled in Clang mode.  For
example, with --clang:

  template<typename T> void f();
  template<typename T> struct C {
    T f;
  };
  template<typename T> bool g(C<T> c) {
    return c.f < 0;  // Previously a spurious error.  Now okay.
  }
  template bool g(C<int>);


4/22/26  [EDGcpfe/26092]
C++23: Static and explicit-object member functions with matching parameters

Consider:

  struct S {
    void f(this const S&);   // (1) Explicit-this member.
    void f() &;              // (2) Ordinary nonstatic member.
    static void f(int = 0);  // (3) Ordinary static member.
    void calls() {
      (&S::f)(S{});    // Calls (1).
      (&S::f)(*this);  // Selects (2), which is an error.
      (&S::f)();       // Calls (3).
    }
  };

Previously, the front diagnosed each call in S::calls().  Now, the front end
implements the proposal in the standardization committee's paper P2797R0, which
makes the first and third call valid.  The second call is also handled
differently: Previously, it was treated as not matching any candidate.  Now it
is considered to match candidate (2), but calls of this form may not resolve
to ordinary nonstatic member functions.


4/21/26  [EDGcpfe/28551]
Spurious error on constexpr constructor of a class template with a base class

Consider:

  template<typename T> struct Base { 
    constexpr Base() = default;
    T arr[2];
  };
  template<typename T>
  struct Derived : public Base<T> {
      constexpr Derived() = default;
  };
  Derived<double> d;

The front end previously erroneously rejected this because the base class
constructor doesn't initialize its array elements.  However, since the
Derived<double> constructor is templated, this should only result in it being
treated as effectively not constexpr, rather than triggering an error.  That
is now fixed.


4/21/26  [EDGcpfe/28798]
Regression causing assertion failure in add_pragmas_to_string

With the changes for EDGcpfe/27955 (in version 6.8), an assertion failure
occurs in configurations using the C++-generating back end when encountering
"pseudo-pragmas".  For example, the following resulted in an assertion failure:

  template<class T> void m() { /*NOTREACHED*/ }

This is now fixed.


4/20/26  [EDGcpfe/24618,EDGcpfe/25469,EDGcpfe/25535,EDGcpfe/25665,
          EDGcpfe/26243,EDGcpfe/26272,EDGcpfe/26528,EDGcpfe/26711,
          EDGcpfe/26725,EDGcpfe/27660,EDGcpfe/27779,EDGcpfe/27879,
          EDGcpfe/28262,EDGcpfe/28391,EDGcpfe/28486,EDGcpfe/28767]
Copying and substituting lambda expressions

The front end was previously unable to copy and substitute lambda expressions.
This caused any case requiring substitution of a lambda expression to fail.
For example:

  template<auto> constexpr bool True = true;
  template<typename> concept C = True<[](int){}>;
  static_assert(C<int>);  // Previously failed.  Now okay.

Some cases of lambda substitution are still not handled correctly, but these
changes make most of the more straightforward situations now work as expected.


4/17/26  [EDGcpfe/28494,EDGcpfe/28563]
Abort in i_copy_dynamic_init on lambda in template argument list

Consider, in C++20 mode:

  struct D { ~D(); };
  struct X {
    X(D l = D()) {}
  };
  template<typename> int v;
  int main() {
    v<decltype( []{ X(); } )>;
  }

This previously aborted in i_copy_dynamic_init (in file il.c) while copying
the default argument of the X::X(D) constructor.  That is now fixed.


4/16/26  [EDGcpfe/28799]
Incorrect declaration of orig_char_from_embed_directive

The function orig_char_from_embed_directive (lexical.h and lexical.c) was
previously declared as returning type "a_const_char".  Because top-level
cv-qualifiers are meaningless in function return types, the function has
now been changed to return "char".


4/16/26  [EDGcpfe/24619,EDGcpfe/26682,EDGcpfe/28602]
Incorrect handling of deducibility in C++17 (and later) modes

Consider:

  template<typename> struct W {};
  template<int> struct X {
    enum { x };
    template<typename T> X(T);
  };
  template<typename T> void f(X<T::x>, W<T>);
  void g(W<X<1>> w) {
    f(1, w);
  }

The parameter type X<T::x> of function template f is "not deducible", and so
T should be deduced from the other parameter (of deducible type W<T>).
However, in C++17 mode, the front end failed to mark the first parameter as not
deducible and when attempting deduction on it for the call f(1, w) then failed
deduction altogether.  This issue also affected partial specialization (which
is based on deduction).  For example:

  template<auto, auto> struct S;
  template<typename X, typename Y, X X::*x, Y Y::*y> class S<x, y> {};

This previously elicited a spurious error about template parameter X not
being deducible.  This is now fixed.


4/16/26  [EDGcpfe/24532,EDGcpfe/25753,EDGcpfe/26858,EDGcpfe/28017,
          EDGcpfe/28664,EDGcpfe/28666]
Operators with template-dependent but not type-dependent operands

The front end previously attempted to perform full semantic analysis on
operators applied to template-dependent operands whose type is known before
substituting template parameters.  This sometimes resulted in premature
diagnostics.  For example:

  struct X { X& operator=(X const&) = delete; };
  struct S {
    S() {}
    template<typename T> struct N {
      X &x;
      N &operator=(N const &src) {
        x = src.x;
      }
    };
  };
  S s;

Previously, this triggered an error about attempting to call a deleted
assignment operator from within S::N::operator=, even though that template is
never instantiated by this example.  Now, such uses of operators are treated
more generically, and diagnostics are delayed until actual instantiation.


4/15/26  [EDGcpfe/28793]
Name lookup in instantiated alias template declaration

Previously, the front end failed to exclude using directives declared after an
alias template when looking up names during an alias template instantiation.
For example, with --c++11:

  namespace ns1 { template<typename T> using A = T; }
  namespace ns2 { template<typename T> using A = void; }
  namespace ns {
    using namespace ns1;
    template<typename> struct C {
      template<typename T> using type = A<T>;  // Previously ambiguous, now
                                               // okay.
    };
  }
  using namespace ns2;
  ns::C<int>::type<int> i = 1;


4/14/26  [EDGcpfe/26143,EDGcpfe/28640]
Attributes on declaration in C mode had caused assertion failure

The presence of attributes on a declaration appearing after a label in C modes
that allow that construct had caused an assertion failure (in
add_statement_list) and is now fixed.  For example, with --c23:

  void f(char c) {
    switch (c) {
      default:
        [[maybe_unused]] int i;
    }
  }


4/13/26  [EDGcpfe/26766]
Microsoft C++ compatibility: typeid of array of const elements

The typeid operator normally ignores the top-level qualification of its
type operand.  In C++, array types have the top-level qualification of their
element types.  For example, the program:

  #include <typeinfo>
  int main() {
    return &typeid(int const[2]) != &typeid(int[2]);
  }

should return zero (i.e., "false") because the two types are equivalent for
the typeid operator.  However, it appears the Microsoft compiler does not
implement this correctly for array of const types, and thus the above returns
one (i.e., "true") when compiled with MSVC.  The front end now emulates the
MSVC behavior in its Microsoft bugs mode.


4/13/26  [EDGcpfe/22050,EDGcpfe/24177,EDGcpfe/28705]
Defaulted constexpr constructor in a union

Consider, in C++20 mode:

  union U {
    int x;
    constexpr U() = default;
  };

Previously, the front end issued a spurious error for this case in all C++
modes accepting constexpr constructors.  Now, the error is no longer issued
in C++20 modes because C++20 no longer requires objects during constant
evaluation to be fully initialized.  This was already handled for non-union
class types (see the entry for EDGcpfe/23646), but the union case was
overlooked.  These changes also eliminate a spurious error on constexpr
constructor instantiations that turn out not to initialize a member.  For
example:

  template<typename T> struct S {
    constexpr S() = default;
    constexpr S(int): S() {}
    int x, y = 2;
  };
  int main() {
    S<int> si(1);
  }

Previously, this elicited an error about S<int>::x not being initialized by
the default constructor, but that is not a requirement for instantiated
constructors such as this one.


4/13/26  [EDGcpfe/28794]
Abort on __builtin_bit_cast in dependent context

Applying the intrinsic __builtin_bit_cast (supported in some Clang and
Microsoft modes) to a template-dependent operand could trigger an internal
error in interpret.c.  For example:

  template<typename T> void g(T v) {
    constexpr long N = __builtin_bit_cast(long, v);
  }

That is now fixed.


4/13/26  [EDGcpfe/28790]
C++-generating back end: performance with deeply-nested template instantiations

As described in the entry for EDGcpfe/11015, the C++-generating back end
maintains a table of accessible typedefs that can be substituted for uses
of inaccessible types in the generated code.  (The changes for
EDGcpfe/26294 tracking the actual template arguments used in each given
reference significantly reduced, but did not completely eliminate, the
contexts in which such substitutions are needed.)  Some accessible typedefs
are not candidates for these substitutions because naming the typedef would
cause an unbounded recursion, for example,

  template<typename T> struct S {
    typedef T type;   // public typedef
  };

If X is a private type, S<X>::type cannot be used to replace a use of X
because the substitution of the typedef for X would apply to the template
argument in S<X>, which would also be replaced by S<X>::type, etc.: X =>
S<X>::type => S<S<X>::type>::type, etc., ad infinitum.  As a result, the
C++-generating back end checked for this kind of circularity and avoided
adding such typedefs to the typedef table.  With complex deeply-nested
template instantiations, however, this check can be very expensive and have
a significant performance impact.  As a result, typedefs of this sort are
now added to the table without regard to any possible circularity and then
the circularity check is performed when considering whether the typedef is
a potential candidate for replacing a given use of an inaccessible type.
This change greatly improves the performance with complex examples,
especially after the changes for EDGcpfe/26294.


4/10/26  [EDGcpfe/25556]
Abort on arithmetic on GNU-mode label address

Consider, in GNU C++ mode:

  void g(void*);
  int main() {
  label:
    g(&&label + 42);
  }

This previously elicited an internal error in the constant-evaluation
interpreter.  That is now fixed.


4/10/26  [EDGcpfe/26030]
Microsoft compatibility: Default initialization of const objects

Consider:

  auto p = new int const;

This is invalid (an initializer value is required when allocating a const
int type), but earlier versions of MSVC do not diagnose the error, and neither
did the front end.  However, newer versions of MSVC do diagnose this case: The
front end has been updated to also diagnose it when microsoft_version >= 1928.


4/10/26  [EDGcpfe/28684]
Spurious warning on returning a reference from a lambda

Consider:

  int g() {
    int i = 42;
    return [&]()->int& { return i; }();
  }

The front end previously issued a warning about returning a reference to a
local variable.  However, in this case the local variable is captured from an
enclosing function, which makes the construct more likely to be valid.  The
front end therefore no longer warns about such cases.


4/9/26   [EDGcpfe/28791]
C++-generating back end: Assertion failure in gen_enum_qualifier

Consider:

  template<typename T, T t> void f() {}
  void g() {
    struct S { enum Color { red, green, blue }; };
    auto p = &g<S::Color, S::Color::red>;
  }

This example could lead to an internal error in the C++-generating back end
(in gen_enum_qualifier) as the consequence of an earlier incorrect access to a
variant member of a_type during the rendering of the template argument
S::Color::red.  The abort did not occur in all configurations or even
consistently for a specific configuration.  That is now fixed.


4/9/26   [EDGcpfe/28673]
Spurious error on use of result from __builtin_add_overflow, etc.

Consider, in Clang C++ mode:

  constexpr int f() {
    int r;
    bool ovfl = __builtin_mul_overflow(2, 2, &r);
    return r;
  }
  constexpr int x = f();

The constant-evaluation interpreter previously failed to mark the variable r
as "initialized" by the call to __builtin_mul_overflow.  That in turn resulted
in a spurious error about the initializer for x not being constant.  That is
now fixed.


4/9/26   [EDGcpfe/28792]
Rendering of address constants as template arguments

In some GNU modes, the front end accepts certain address constant expressions
as template arguments that are not valid C++.  For example:

  int *gv;
  template<typename T, T *const Val> T *const v = Val;
  auto s = v<int*, v<int*, &gv>>;

The template argument "v<int*, &gv>" is nonstandard and triggers an error with
most target compilers.  The front end accepts it in GNU C++ modes, however,
and prior to version 6.8, the C++-generating back end rendered it as "&gv",
which is valid C++ (unlike the original form).  Version 6.8, however, more
faithfully rendered the input, thereby triggering errors in target compilers.
Now, the rendering matches that of version 6.7 again.


4/8/26   [EDGcpfe/28782]
C++-generating back end, clang compatibility: user-defined literal operator
names

The canonical form of user-defined literal operator names places the suffix
immediately adjacent to the double quotes with no intervening white space
(e.g., operator ""_xyz).  Early versions of clang required a space,
however, so the C++-generating back end originally always used the form
with the space when clang_is_generated_code_target was TRUE.  After
observing that recent versions of clang issue a deprecation warning for the
form with a space, the C++-generating back end was changed in version 6.8
(see EDGcpfe/28526) to use the non-space form for clang output whenever
clang_target_version_number was at least 60000.

However, the actual rule followed by clang is more complex: it only accepts
the non-space form when the suffix begins with an underscore, requiring the
space when the suffix does not begin with an underscore.  The C++-generating
back end has now been changed to produce the required forms in both cases
when clang_is_generated_code_target is TRUE.


4/8/26   [EDGcpfe/26534,EDGcpfe/28787]
Abbreviated friend template definitions in class templates

Consider, in C++20 mode:

  template<typename T> struct S {
    friend constexpr void f(auto n) noexcept {}
    T v;
  };
  void g() {
    S<int> s{ 0 };  // Previously an error about too many initializers.
  }                 // Now okay.

Previously, during the instantiation of S<int>, the front end ignored all the
members following the abbreviated friend template definition.  In this case,
that means that it treated S<int> as having no member v, and thus issuing an
error message about s having too many initializer values.  That is now fixed.


4/8/26   [EDGcpfe/28770]
Spurious incomplete type error on class template being instantiated

In some fairly complex situations, the front end sometimes instantiated a
function template a little too early as a consequence of instantiating a class
template.  If the function template instantiation required the completeness of
the class template instantiation, this resulted in a spurious "incomplete type"
error.  That is now fixed.


4/7/26   [EDGcpfe/28781]
C++-generating back end: using directives and elaborated type specifiers

As a result of the changes for EDGcpfe/26294 in version 6.8, the
C++-generating back end sometimes failed to use an elaborated type
specifier when it is needed to disambiguate between names made visible by
using directives.  This is now fixed.  For example, with --c++11:

  namespace A {
      int z;
  }
  namespace B {
     struct z {};
  }
  namespace C {
     using namespace A;
     using namespace B;
  }
  void () {
    struct C::z oz;   // Previously omitted the "struct" keyword
  }


4/7/26   [EDGcpfe/28785]
Slight change with builtins *_is_pointer_interconvertible_with_class

Code was rearranged to avoid loading a potentially undefined value (though
that value was never dereferenced).  There is no observable change in behavior.


4/6/26   [EDGcpfe/26656,EDGcpfe/27450]
Spurious error on casting a function to a reference-to-pointer

Consider:

  void g() noexcept;
  using PF = void (*)();
  PF const &rrpf = static_cast<PF const&&>(g);

Previously, this was spuriously diagnosed as a conversion error.  That is now
fixed.


4/6/26   [EDGcpfe/28780,EDGcpfe/28783]
C++-generating back end, Microsoft/GCC compatibility: elaborated type
specifiers and scoped enumerations

MSVC has a bug that causes it to report a spurious error when a scoped
enumeration is used as the type in an alias declaration and is named using an
elaborated type specifier.  GCC versions prior to GCC 11 had a similar bug,
except a warning was issued instead of an error.  In some cases, the C++-
generating back end gratuitously generated such elaborated type specifiers,
triggering the spurious MSVC or GCC diagnostic.  This is now fixed.  For
example, with --microsoft --c++11:

  namespace N {
    enum class E { e };
  }
  using namespace N;
  using E = N::E;   // Previously generated as "enum N::E", triggering the
                    // MSVC bug


4/6/26   [EDGcpfe/28775]
Internal error in discard_constant_expr_object_lifetime

Consider, in C++23 mode:

  struct S {
    int i;
    constexpr ~S() {}
  };
  constexpr S g(bool b) {
    if consteval {
      return b ? S() : S();
    }
    return S();
  }
  int main() {
    int arr[g(true).i];
  }

Previously, this aborted in discard_constant_expr_object_lifetime (exprutil.c,
with an internal error) because it was assumed that object lifetime entries in
a constant context could only appear during error recovery.  That erroneous
assumption has now been dropped.


4/3/26   [EDGcpfe/28772]
Compile-time control of name reference creation

The changes in version 6.8 for EDGcpfe/26294 for tracking the form of
template arguments and name qualifiers were enabled by the configuration
macro DEFAULT_RECORD_FORM_OF_NAME_REFERENCE.  Setting that macro to TRUE
resulted in significant IL changes that required corresponding changes to
back ends.  There is a global variable, record_form_of_name_reference, that
controlled some, but not all, of these IL changes.  The effect of this
variable has now been extended to cover all the IL changes associated with
EDGcpfe/26294, so setting it to FALSE at the beginning of a compilation
will result in the same IL as configuring
DEFAULT_RECORD_FORM_OF_NAME_REFERENCE to FALSE.


4/2/26   [EDGcpfe/28749]
Evaluation of captured constexpr variable in a constant-evaluated context

Consider:

  struct C {
    int val;
    constexpr int &operator[](int) const { return (int&)val; }
  };
  int main() {
    constexpr C c{1};
    [c]() {
      if constexpr (c[1]) {}
    }();
  }

Previously, the constant-evaluation interpreter could not look through the
capture of c to determine the value of c[1]: A spurious error about an attempt
at accessing run-time storage ensued.  That is now fixed.


4/2/26   [EDGcpfe/25956,EDGcpfe/25957,EDGcpfe/28763]
C23: Old-style function declarators and function definitions

C23 removes support for non-prototype function declarators and for old-style
parameter lists in function definitions.  The front end now implements those
changes in its C23 mode by default.  For example:

  void f();

Prior to C23, this was a non-prototype function declaration; i.e., the number
and the types of the parameters accepted by this function were not a priori
known.  In C23, this declaration is treated equivalently to

  void f(void);

(just as in C++; the function takes no parameters).  The previous behavior can
be restored with the command-line option --no_require_func_prototypes.
Another example:

  void g(i) int i; {}

This now elicits a discretionary error in C23 mode (a warning in GNU C23 modes)
because old-style definitions are no longer valid in C23.  These changes
implement the C committee's papers N2432 and N2841.


4/1/26   [EDGcpfe/28769]
C mode remarks on declaration with multiple non-prototype function declarators

Consider, in C mode with remarks enabled:

  extern void f1(), f2(), f3();

This elicits remarks because the function declarators are non-prototype (e.g.,
"f1()" instead of "f1(void)"), but previously that remark was repeated on each
declarator for each declarator that preceded it.  So, there were two identical
remarks for f2(), and three identical remarks for f3().  That is now fixed.


4/1/26   [EDGcpfe/28768]
__builtin_invoke and std::reference_wrapper

Consider, in Clang 21 C++20 mode:

  #include <functional>
  struct E {};
  struct F { int& operator()(E&&) &; };
  int& g(F obj, E arg) {
    std::reference_wrapper<F> w(obj);
    auto pmf = &F::operator();
    return __builtin_invoke(pmf, w, static_cast<E&&>(arg));
  }

This previously elicited a spurious error because the front end failed to
"unwrap" the std::reference_wrapper obj prior to applying the pointer-to-
member-function on it.  That is now fixed.


3/31/26  [EDGcpfe/28319]
C++-generating back end: initialization with empty std::initializer_list

In some cases in which an object of a class with an initializer-list
construct is initialized to an empty initializer list, the C++-generating
back end could put out an erroneous initializer.  This is now fixed.  For
example, with --gnu_version=140100:

  #include <initializer_list>
  struct A {
    constexpr A(std::initializer_list<int> l) : i(l.size()) { }
    int i;
  };
  constexpr int f() {
    A a{};   // Previously generated as "A a{{}}"
    return a.i;
  }


3/31/26  [EDGcpfe/28760]
C++-generating back end and built-in alias templates

Consider:

  template<typename T> struct X { using type = T; };
  int main() {
    using Z = __builtin_common_type<X, X, int, double>::type;
  }

Previously, __builtin_common_type was erroneously rendered as
__builtin_common_type_alias by the C++-generating back end because of the way
builtin-in alias templates are handled by the front end.  That is now fixed.


3/31/26  [EDGcpfe/28758]
C++23: Constexpr constructor calling non-constexpr constructors

In C++23 mode, the front end no longer diagnoses constexpr constructors that
call non-constexpr constructors as part of subobject initialization (as long
as that constexpr constructor is not invoked in a context that requires a
constant).  For example:

  struct S {
    S(int);
    constexpr S(): S(0) {}  // Previously an error.  Now okay.
  };
  S s1;            // Okay.
  constexpr S s2;  // Still an error.

This change in behavior is the result of the C++ standardization committee's
paper P2448R2.


3/30/26  [EDGcpfe/28750,EDGcpfe/28766]
Clang compatibility: Nonstandard anonymous struct destruction

Consider:

  struct D { ~D() {} };
  struct S {
    struct {
      D d;
    };
  };
  S s;  // Previously an error.  Now accepted in Clang C++ modes.

Class type S contains a nonstandard anonymous struct.  GCC imposes constraints
similar to anonymous unions, which makes the example above an error because of
the nontrivial destructor required to destroy the anonymous member.  Clang,
however, accepts this case, and the front end now emulates that behavior in
Clang C++ modes.


3/27/26  [EDGcpfe/28762]
C++-generating back end: explicit temporary in template argument

In some cases, the C++-generating back end could put out a
syntactically-incorrect form for an explicit temporary for an aggregate
class type appearing as a non-type template argument, adding a "const"
qualifier before the aggregate class name.  This regression in version 6.8
was the result of the changes for EDGcpfe/26253,EDGcpfe/27917.  This is now
fixed.  For example, with --c++20:

  struct S { int x; };
  template<typename, S> void f() {}
  void g() {
    constexpr S s = S{1};
    auto l = []<typename T>(T) {
      f<T, s>();   // Previously generated as "f<T, const S{1}>()"
    };
  }


3/25/26  [EDGcpfe/28756]
Floating-point rounding mode

The C++ Standard does not specify how conversions to floating-point types
should handle values that cannot be represented exactly in the target type,
only requiring that the result be either the nearest representable value
above or below the source value.  In configurations in which
USE_HOST_FP_CONVERSION_ROUTINES is FALSE, the front end performed
compile-time calculations using the IEEE rule that rounds to the nearest
representable value, with ties (values that fall exactly midway between
representable values) rounding away from zero.  The GNU and clang
compilers, however, use the rule that rounds ties to the nearest even value
(lowest bit of the mantissa being zero).  The front end has now been
changed to do the same.  For example:

  float f = (float)0x8000008;   // Previous result was 0x4D000001 (odd),
                                // now 0x4D000000 (even)


3/23/26  [EDGcpfe/28754,EDGcpfe/28755]
C++-generating back end: failure to parenthesize top-level comma expression

In certain contexts, a top-level comma is taken not as the operator in a
comma expression but as a separator between expressions.  The C++23
Standard introduced two contexts in which a top-level comma is not
permitted and thus must be enclosed in parentheses: the operand of an
"assume" attribute (see EDGcpfe/25517,EDGcpfe/25844) and the subscript
expression in an array element access (see EDGcpfe/24785 et al.).  The
C++-generating back end previously failed to generate the necessary
parentheses in these cases.  This is now fixed.  For example, with --c++23:

  void f();
  void g(int &r, int *p, int i) {
    int j = r;
    [[assume((f(), j == r))]]; // Previously generated as "assume(f(), j==r)"
    j = p[(j, r)];             // Previously generated as "p[j, r]"
  }


3/23/26  [EDGcpfe/28665]
Microsoft compatibility: __declspec on statement

The processing of a __declspec construct on a statement had caused some
irregularities during the parsing, resulting in some inconsistencies in the
IL.  In the following example (with --microsoft), only one stmk_asm
statement had been generated:

  void f() {
      [[]] asm("nop");          // generated an stmk_asm
      __declspec() asm("nop");  // had generated no stmk_asm (now fixed)
  }


3/19/26  [EDGcpfe/28277,EDGcpfe/28746]
Improvements to substitutions of constant template argument expressions

In some cases, the front end successfully substituted constant template
argument expressions but it considered the substitution failed because there
was insufficient information at the point of substitution to produce a
constant value.  For example:

  template<typename, int> void f() {}
  int main() {
    []<typename T = int>(){
      constexpr int N = 0;
      static_assert(requires () {f<T, N>(); });  // Previously failed.
    }();                                         // Now okay.
  }

Here, f in f<T, N> is at first assumed unknown (because it might be overloaded)
and so the template argument list <T, N> is substituted without knowing whether
the expression N will be a prvalue (which can be folded) or a glvalue (which
would be invalid).  Previously, this inability to fold the expression N caused
substitution to fail, and thus the requires expression to produce a false
value.  Now, the unfolded expression is propagated for later processing and
folded when it is bound to the template constant parameter: The requires-
expression now produces true and the example is accepted.


3/18/26  [EDGcpfe/28745]
Address of C11 _Generic lvalue

In some configurations, the front end was unable to "see through" a C11
_Generic selection to identify a constant address.  That could result in
spurious errors.  For example, in GNU C11 mode:

  struct S* arr[1];
  struct S** p = _Generic(arr, struct S**: arr);  // Previously an error in
                                                  // some configurations.

That is now fixed.


3/18/26  [EDGcpfe/21155,EDGcpfe/28528]
Improvements to parameter pack deduction

Consider:

  template<typename T, typename ...> struct X { using type = int; };
  template<typename ...Ts>
    int f(typename X<Ts ...>::type, Ts...);            // (1)
  template<typename T, typename... Ts>
    int f(typename X<T*, Ts ...>::type, T*, Ts...);    // (2)
  int r = f(1, "");                                    // (3)

Template (2) is "more specialized" than template (1), and should thus be
selected in line (3).  However, a bug in parameter pack deduction previously
prevented the front end from determining the partial order between the two
templates.  That is now fixed.

A related problem occurred in the following example:

  template<typename> struct E {};
  template<typename> struct S {
    template<typename ...Ts> using NA = E<Ts...>;
  };
  template<typename U, typename ...Vs>
    using A = typename S<U>::template NA<Vs...>;
  template<typename U, typename ...Ps> int f(A<U, Ps...>);
  int r = f<int>(E<int>{});  // Previously failed deduction.  Now okay.

Previously, deducing the pack Ps... through the alias template failed, causing
the example to produce a spurious error.  That is now also fixed.


3/17/26  [EDGcpfe/28736]
Temporaries in short-circuiting fold-expressions

Consider, in C++17 mode:

  extern "C" int printf(char const*, ...);
  template<int N>
  struct Tmp {
    ~Tmp() { if (N != 0) printf("%d\n", N); }
    operator bool() const { return N != 0; }
  };
  template<int ... N> void f() {
    (Tmp<N>{} && ...);
  }
  int main() {
    f<0, 1>();
  }

The fold expression expands to the equivalent of (Tmp<0>{} && Tmp<1>{}), where
only the first temporary is constructed since it converts to a false value.
Hence, only that temporary should be destroyed, but the front end failed to
maintain the needed conditions to track the evaluated temporaries in this
situation.  As a result, a destructor was also run for potential temporaries
that were not actually produced (in this case, the temporary that Tmp<1>{}
might have produced).  This is now fixed.


3/17/26  [EDGcpfe/28731]
__builtin_invoke and class templates

The front end previously failed to trigger the instantiation of a class
template specialization passed to __builtin_invoke.  This resulted in spurious
diagnostics about a missing call operator.  That is now fixed.


3/13/26  [EDGcpfe/28622]
Abort in trans_copy in some configurations

The changes for EDGcpfe/27217 could cause the generation of source sequence
entries in secondary translation units when GENERATE_SOURCE_SEQUENCE_LISTS is
TRUE, which in turn triggered an internal error in trans_copy.c.  This
regression, introduced in version 6.7 of the front end, is now fixed.  (It is
unusual to enable secondary translation unit support -- i.e., setting
COMPILE_MULTIPLE_TRANSLATION_UNITS to TRUE -- and source sequence entries at
the same time.)


3/12/26  [EDGcpfe/28718]
Clang compatibility: __builtin_elementwise_ldexp, __builtin_masked_load,
__builtin_masked_expand_load, __builtin_masked_gather

Support has been added for these Clang builtins whose return type is
dependent on the type of arguments supplied: __builtin_elementwise_ldexp,
__builtin_masked_load, __builtin_masked_expand_load, __builtin_masked_gather.


3/12/26  [EDGcpfe/28720]
Clang compatibility: __builtin_dedup_pack

In Clang C++ modes with clang_version >= 220000, the front end now implements
support for an intrinsic __builtin_dedup_pack template.


3/11/26  [EDGcpfe/25488,EDGcpfe/27895]
Out-of-range enumerator values with --ms_extensions

In Microsoft mode, enumerator constants have type "int", and out-of-range
enumerator constant values are truncated if needed.  Previously, the second
part was not done in non-Microsoft modes with --ms_extensions, but the first
part still applied.  This resulted in error with an example like

  enum E { e = 4'000'000'000 };

(assuming a 32-bit int type) because 4'000'000'000 is outside the range of
type int.  That is now fixed.  Furthermore, this nonstandard behavior is now
entirely avoided in non-permissive Microsoft modes.


3/11/26  [EDGcpfe/28136,EDGcpfe/28316,EDGcpfe/28733]
Deduction of OpenCL vector types in Clang modes

The front end now can deduce the element type and the length of template-
dependent OpenCL vector types in Clang C++ modes (such types are introduced
with the ext_vector_type attribute).  For example:

  template<class T, unsigned long N>
    using Vec __attribute__((__ext_vector_type__(N))) = T;
  template<unsigned long N> void f(Vec<int, N>) {}
  void g(Vec<int, 4> v) {
    f(v);  // Now okay in Clang C++ modes.
  }


3/9/26   [EDGcpfe/22048,EDGcpfe/24821,EDGcpfe/28029,EDGcpfe/28146,
          EDGcpfe/28737]
Defaulted virtual function missing a definition

The front end sometimes failed to trigger the generation of the definition for
a defaulted virtual function.  For example:

  #include <compare>
  struct S {
    virtual std::strong_ordering operator<=>(S const&) const = default;
  } s;
  int main() {}

This could lead to linker errors or prelinker loops.  That is now fixed.


3/9/26   [EDGcpfe/28738]
Spurious constant-evaluation error when capturing an empty class variable

Consider:

  auto lm = [](auto &&p) { return [p]{}; };  // (1)
  constexpr auto lm_wrap = lm([](auto) {});

Here, line (1) copies an empty lambda as a capture.  Previously, the front end
issued an error claiming that this involves uninitialized data.  That is now
fixed.


3/9/26   [EDGcpfe/28732]
Clang compatibility: Accept an optional fourth argument on diagnose_if
attributes

Clang 20.1.0 allows an optional fourth string argument to diagnose_if
attributes.  The front end now allows that as well.  Arguments to diagnose_if
are parsed and recorded, but are otherwise ignored.


3/9/26   [EDGcpfe/28735]
Internal error when processing large types

Previously, an internal error in lower_constant (lower_il.c) could occur
when processing types whose size exceeded the front end's constexpr
type size limit.  For example, with --c++11:

  struct arr { unsigned char x[1ull << 31]; };

  int sink(arr) { return 0; };

  int main() {
    arr x{};
    int y = sink(x);
  }

The error occurred due to incorrect handling of certain failure modes while
constant folding.  This issue has now been fixed.


3/7/26   [EDGcpfe/28715]
__builtin_add_overflow, etc.

The changes for EDGcpfe/28586 (not yet in a release, but distributed as a
patch) introduced a bug with some combinations of unsigned 128-bit values and
signed narrower values.  For example, in Clang C++17 mode:

  constexpr bool plus_overflows(signed char x, unsigned __int128 y) {
    unsigned __int128  sum;
    return __builtin_add_overflow(x, y, &sum);
  }
  static_assert(!plus_overflows(0, 0));  // Failed after EDGcpfe/28586.

That is now fixed.


3/6/26   [EDGcpfe/27775,EDGcpfe/28548]
C++26: Structured binding packs

The front end now supports structured binding packs, which have been adopted
for the upcoming C++26 Standard via WG21 paper P1061R10.  For example, with
--c++26:

  auto l = [] (auto v) {
    auto [... b] = v;
    return (b + ...);
  };

As part of this change, the field is_parameter_pack of a_variable has been
renamed to is_pack, as it is now also set to TRUE for a structured binding
pack.  This is a small IL CHANGE.


3/5/26   [EDGcpfe/28719]
Clang compatibility: Folding of __builtin_elementwise_... functions.

In Clang mode, the front end can now constant-evaluate calls to some of the
__builtin_elementwise_... built-in functions.  The initial list of supported
functions is __builtin_elementwise_abs, __builtin_elementwise_min, and
__builtin_elementwise_max.  Error recovery for erroneous uses of these
functions has also been improved somewhat.


3/5/26   [EDGcpfe/23609,EDGcpfe/23845,EDGcpfe/23927,EDGcpfe/24247,
          EDGcpfe/27220,EDGcpfe/28636]
Pragma processing corrections

Pragma processing has been significantly simplified.  In configurations that
generate template strings (RECORD_TEMPLATE_STRINGS=1) multiple bugs where the
pragma was preserved in the wrong token cache or in the wrong position have
been fixed.  Additional bugs have been resolved in rare cases where token
lookahead would result in duplicate processing of a pragma or no pragma
processing occurring at all.


3/5/26   [EDGcpfe/28730]
Use of __make_integer_seq without MICROSOFT_EXTENSIONS_ALLOWED enabled

The changes for EDGcpfe/18124 (in version 4.14) enabled the use of
__make_integer_seq in all modes (previously it was only available in Microsoft
emulation modes).  Those changes were incomplete, requiring that the
MICROSOFT_EXTENSIONS_ALLOWED configuration was TRUE.  That has been fixed.


3/5/26   [EDGcpfe/28024]
Instantiation of C++23 lambda without a parameter declaration clause

The front end failed to instantiate C++23 lambdas that are declared without a
parameter declaration clause.  For example, with --c++23:

  int i = []<int = 0> -> int { return 1; }();  // Previously an error.
                                               // Now okay.


3/4/26   [EDGcpfe/28702]
Performance degradation due to long name qualifier lists

In certain cases involving alias templates in namespace scope, the front end
may create long lists of name qualifiers for namespace symbols, which can lead
to significant performance degradation.  For example:

  namespace ns {
    template<typename T> struct C { using type = C; };
    template<typename T> using B = typename C<T>::type;
    template<typename T> using A = typename ns::B<T>::type;
  }

Here, any use of the alias template "ns::A" will add an entry to the name
qualifier list of namespace "ns".


3/4/26   [EDGcpfe/28695]
Trailing return type in C++23 lambda without a parameter declaration clause

Previously, the front end failed to parse a C++23 lambda expression with a
trailing return type that immediately follows a requires clause.  For example,
with --c++23:

  auto l = []<typename> requires true -> void { };  // Previously a spurious
                                                    // error.  Now okay.


3/2/26   [EDGcpfe/28721]
Clang compatibility: __builtin_lt_synthesizes_from_spaceship, etc.

In Clang C++ mode, with clang_version >= 220000, the front end now accepts the
following type trait helpers:
   __builtin_lt_synthesizes_from_spaceship(Type1, Type2)
   __builtin_gt_synthesizes_from_spaceship(Type1, Type2)
   __builtin_le_synthesizes_from_spaceship(Type1, Type2)
   __builtin_ge_synthesizes_from_spaceship(Type1, Type2)
which return whether, respectively, applying operator <, >, <=, or >= to
operands of types Type1 and Type2 involves the use of an operator<=>.


3/2/26   [EDGcpfe/28722]
Clang compatibility: builtin signatures

In Clang mode, the __builtin_popcountg, __builtin_ctzg, and __builtin_clzg
builtins now accept a bool or vector of bool argument.


3/2/26   [EDGcpfe/28724]
RISC-V: Additional builtins for the RVA23 profile

The builtin signatures have been updated to include additional builtins for the
RISC-V RVA23 profile.  Additionally, the builtin condition 'R' has been added
to enable defining RISC-V-specific builtin functions in the user-defined
builtin table.


2/27/26  [EDGcpfe/28529]
GNU C++ compatibility: Narrowing conversions

When resolving a constructor call with braced-initializer notation, the front
end previously did not diagnose narrowing conversion as errors in GNU and Clang
C++ modes (nor in Microsoft C++ mode, but that remains unchanged).  Now, this
behavior is no longer enabled in Clang mode.  Furthermore, in GCC mode, it is
limited to modes with gnu_version < 50000 if the narrowing happens in an
unevaluated operand (e.g., in a decltype(...) or sizeof(...) construct).


2/27/26  [EDGcpfe/28716]
Missing skip_typerefs could lead to undefined behavior

A missing skip_typerefs call could lead to undefined behavior, for example in
the following case (with --c++11):

  template <int> void f() {}
  template decltype(f<0>) f<0>;


2/27/26  [EDGcpfe/28717]
Clang compatibility: Allow GNU-style standard attributes in "clang" namespace

Beginning with version 21, Clang now allows non-standard GNU attributes with
standard attribute syntax when using the "clang" attribute namespace.  The
front end now supports this; for example, with --clang_version 210000:

  using vfloat4 = float [[clang::ext_vector_type(4)]];


2/26/26  [EDGcpfe/28713]
Abort in ptr_remap_function

In configurations with IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE and
ALTERNATE_IL_FILE_FORMAT set to FALSE, the front end could abort in an internal
error in ptr_remap_function ("address not in any mem block", in il_read.c).
This regression, introduced in version 6.8 of the front end, is now fixed.


2/25/26  [EDGcpfe/23896,EDGcpfe/25187,EDGcpfe/25986]
operator<=> and array types

The front end previously performed implicit array-to-pointer conversion for any
array operand of operator<=>.  Now, it only performs that conversion if the
other operand is a pointer; otherwise, an error is issued.


2/23/26  [EDGcpfe/28677]
Missing has_temporary_lifetime flag

Consider:

  struct S { constexpr S() {} };
  struct X { X(S const&); };
  void g() {
    X xs((S()));
  }

The changes for EDGcpfe/27839 caused the "has_temporary_lifetime" flag to be
FALSE on the a_dynamic_init_entry representing the constructor call S().  That
regression (introduced in version 6.8) is now fixed.


2/23/26  [EDGcpfe/28662]
Bad handling of new-expression with ck_init_repeat in interpreter

When the initialization part of an array new-expression contains a ck_aggregate
constant with a ck_init_repeat component, the front end sometimes did not
correctly handle the initialization of elements after the first one covered by
the ck_init_repeat entry.  That is now fixed.


2/23/26  [EDGcpfe/28471]
Microsoft compatibility: __builtin_is_implicit_lifetime

The new type trait intrinsic __builtin_is_implicit_lifetime is now also enabled
in Microsoft mode with microsoft_version >= 1951.



2/19/26  [EDGcpfe/28682]
Abort in prep_special_selector_operand

Consider, in a recent Clang C++ mode:

  template<int> struct V {};
  template<typename T> struct X: V<__is_assignable(T, T)> {};
  struct S {
    operator int();
    S operator=(int p) __attribute__((enable_if(p, "")));
  };
  int g() { X<S> v; }

Previously, this triggered an internal error in prep_special_selector_operand
(in overload.c) while the front end attempted to evaluate the enable_if operand
(a dummy operand created to evaluate the __is_assignable intrinsic).  That is
now fixed.


2/17/26  [EDGcpfe/28696]
Constexpr array variable templates

Consider:

  template<typename T> constexpr T arr[8];  // Previously an error.  Now okay.

Previously, the front end issued an error because it treated arr as an
uninitialized array.  However, type T might still turn out to be a class type
with a nontrivial default constructor.  The spurious error is now no longer
issued.


2/16/26  [EDGcpfe/28671]
Template-dependent array designators

In C++ modes that permit array designators (e.g., Clang and GNU C++ modes in
particular), the front end now accepts such designators in some template-
dependent contexts.  For example:

  using Arr = float[10];
  template<int N> auto f1() {
    Arr arr1 = { [N] = 42 };  // Now accepted in some C++ modes.
    return arr1[N];
  }


2/13/26  [EDGcpfe/28687]
C++-generating back end: name reference in scoped enumeration qualifier

The changes for EDGcpfe/28686 (not in a release but distributed to
customers in a patch) could result in generated code that, while correct,
failed in some complex cases to reflect the actual name qualifier used for
a scoped enumerator in the original source.  This is now fixed.


2/13/26  [EDGcpfe/28701]
Assertion failure in prelower_class_type

An assertion failure in prelower_class_type had occurred in C mode on the
following example and is now fixed.  With --gcc:

  struct A { unsigned long x; };
  const struct A a = { 0 };
  void f() {
    __asm__ ("movq %0, %%mm0" : : "m"(a) : "mm0");
  }


2/12/26  [EDGcpfe/28700]
Missing name reference for function template specialization lvalue

In configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE, the
front end failed to record name references for function template specialization
lvalues that are not used as the postfix expression in a function call.  This
also prevented the C++-generating back end from accurately reconstructing such
expressions. For example, with --c++14:

  namespace ns1 {
    template<typename> int f();
  }
  namespace ns2 {
    using namespace ns1;
  }
  auto *f(int i) {
    return ns2::f<decltype(i)>;  // Previously reconstructed as "ns1::f<int>".
  }


2/11/26  [EDGcpfe/28699]
Abort with __is_invocable

Consider:

  namespace std {
    template<typename ... Ts> struct reference_wrapper {};
  };
  struct S {};
  using X = std::reference_wrapper<S>;
  static_assert(!__is_invocable(int S::*, X));

This combination of applying __is_invocable on a pointer-to-member type with
an object type that is an instance of std::reference_wrapper previously
triggered an invalid memory access (usually resulting in an aborted process).
That is now fixed.


2/11/26  [EDGcpfe/28624]
Template lower_bound renamed to low_bound

The EDG lower_bound template in util.h could trigger ambiguities with some
std::lower_bound implementations.  To avoid such problems, the EDG template
has been renamed to low_bound.


2/11/26  [EDGcpfe/28698]
Use FP_LONG_DOUBLE_IS_BINARY128 for 64-bit ARM and RISC-V on Linux

A change has been made to set FP_LONG_DOUBLE_IS_BINARY128 instead of
FP_LONG_DOUBLE_IS_80BIT_EXTENDED in defines.h.linux for 64-bit ARM and RISC-V
architectures.


2/10/26  [EDGcpfe/28693]
Regression in cleanup of template_cache_segment_table

With the changes for EDGcpfe/27955 (in version 6.8), template cache segments
were not removed from template_cache_segment_table when destroyed.  This
resulted in increased memory usage for some translation units and (in rare
cases) segfaults.  This is now fixed.


2/9/26   [EDGcpfe/28692]
C++-generating back end: missing __integer_pack template argument

With the changes for EDGcpfe/26294 in version 6.8, the front end failed to mark
an __integer_pack template argument as explicitly specified, resulting in the
argument not being included by the C++ generating back end in some contexts.
For example, with --c++11 --gnu_version 150200:

  template<int ... Is>
  struct C {
    struct D { };
  };

  template<int I>
  using A = typename C<__integer_pack(I)...>::D;  // Previously generated as
                                                  // "typename C<>::D"


2/7/26   [EDGcpfe/28603]
Clang compatibility: Integer overflow in enumerator constant values

Consider, in a configuration with 32-bit int types:

  enum E { e = 2147483647 + 100 };

The constant expression for the enumerator constant exceeds the range of type
int, which is ordinarily an error.  However, Clang does not diagnose this
prior to version 19.  The front end now emulates that behavior (with a
warning) in Clang C++ mode when clang_version < 190000.  This is a regression
because version 6.6 of the front end also accidentally accepted such code.


2/5/26   [EDGcpfe/28672]
Regression causing incorrect rendering of function name tokens

With the changes for EDGcpfe/27955 (in version 6.8), tokens like __FUNCTION__
and __FUNCSIG__ were incorrectly rendered as "__FUNCTION__" and "__FUNCSIG__"
(this is observable primarily in configurations that make use of
RECORD_TEMPLATE_STRINGS=1 or BACK_END_IS_CP_GEN_BE=1).  This is now fixed.


2/5/26   [EDGcpfe/25818,EDGcpfe/28688]
Attributes on concepts and [[deprecated]]

The front end now accepts attributes on concepts.  Initially, the only
attribute accepted for a concept is [[deprecated]] (or the variant with a
message).  This was added to the language through the defect resolution of the
C++ committee's Core issue 2428.


2/4/26   [EDGcpfe/28686]
C++-generating back end: assertion failure with use of scoped enumerator

As a result the changes for EDGcpfe/26294 in version 6.8, some very complex
code in which a scoped enumerator appears as a non-type template argument
could result in an assertion failure in either gen_name or
gen_enum_qualifier.  This is now fixed.


2/4/26   [EDGcpfe/28680]
Regression causing assertion failure in if_statement

With the changes for EDGcpfe/27955 (in version 6.8), an assertion failure could
occur as a result of using invalidated iterators stored by an
a_constexpr_if_cache_info object that has had its underlying token cache
operated on by template member body extraction.  This is now fixed.


2/3/26   [EDGcpfe/28681]
Assertion failure when casting 128-bit complex type

An assertion failure (in lower_c99_complex_cast) could occur in certain
configurations when casting from a 128-bit complex type.  For example,
with --gnu_version=150200:

  void f(__complex__ _Float128 v) {
    __complex__ long double x = v;
  }


2/3/26   [EDGcpfe/27863,EDGcpfe/28427]
Segfault in lower_delete with delete[] with --ms_extensions

A segmentation fault could occur in lower_delete when --ms_extensions is used
with certain delete[] operations.  For example (with --ms_extensions),  

  void f(int *ptr) {
    delete[] ptr;
  }


2/3/26   [EDGcpfe/28679]
Missing skip_typerefs could lead to undefined behavior in lowering

The lowering of an enk_param_ref could result in undefined behavior due to
missing skip_typeref calls and is now fixed.  Additionally, a couple of
misuses of the class_type_supp macro have been changed to class_symbol_supp
and some additional debug code has been added to help prevent future problems.


2/2/26   [EDGcpfe/17833,EDGcpfe/18654,EDGcpfe/28444,EDGcpfe/28522]
GCC, Clang, and MSVC compatibility: Partial ordering of variadic templates

Consider:

  template<typename ... Ts> int f(Ts &...); // #1
  template<typename T>      int f(T &&);    // #2
  int i;
  int j = f(i);

Prior to the resolution of Core issue 1395, partial ordering would prefer the
non-variadic function template #2.  With the resolution of Core issue 1395, the
partial ordering rules changed to prefer #1 instead.  However, GCC, Clang, and
MSVC do not yet implement this resolution, and the front end therefore now
emulates their behavior in its corresponding emulation modes.


1/30/26  [EDGcpfe/28670]
C++-generating back end: value-initialization in static initializer

The changes for EDGcpfe/27137 in version 6.8 introduced a regression in the
handling of a declaration of a variable that is direct-initialized with a
value-initialized explicit temporary, e.g.,

  struct T { int x; };
  T s ( ( T() ) );
  T *p = &s;

In version 6.8 when compiled with --microsoft, the declaration of "s" was
put out as

  T s ( T() );

which declares "s" as a function with a pointer-to-function parameter
instead of as an initialized variable.  This is now fixed and the
disambiguating parentheses are restored.


1/26/26  [EDGcpfe/28068,EDGcpfe/28654]
GNU/Clang compatibility: __builtin_is_implicit_lifetime

The new type trait intrinsic __builtin_is_implicit_lifetime is now supported in
Clang 20+ and GCC 16+ modes.


1/22/26  [EDGcpfe/27976,EDGcpfe/28658]
Abort with __is_trivially_equality_comparable applied to incomplete class

The front end previously aborted (null pointer indirection) when the type trait
helper __is_trivially_equality_comparable is applied to an incomplete class
type.  That is now fixed.


1/22/26  [EDGcpfe/28048,EDGcpfe/28655]
Explicit-this conversion templates

Consider:

  struct S {
    operator int(this auto &&self);  // (1)
  };
  int r = S{};  // (2)

Previously, the front end failed to parse line (1) because of a bug interacting
with abbreviated template syntax.  That is now fixed.  Furthermore, the front
end did not correctly deduce templated explicit-this parameters for conversion
templates, resulting in a spurious error on line (2).  That is now also fixed.


1/22/26  [EDGcpfe/25649,EDGcpfe/28610]
Spurious error during disambiguation of for statement

The changes for EDGcpfe/27435 (in version 6.7) introduced a regression during
disambiguation of a for statement containing a declaration with a constrained
placeholder type.  For example, with --c++20:

  template<typename, int> concept C = true;
  void f(auto t) {
    for (C<1> auto v : t) { }  // Previously a spurious error, now okay.
  }

Additionally, this also fixes an issue where a decltype specifier refers to a
declarator in the same declaration of a for statement.  For example, with
--c++11:

  void g() {
    for (int i = decltype(i)();;) {}  // Previously a spurious error, now okay.
  }


1/22/26  [EDGcpfe/17809]
C++-generating back end: friend declaration in local class

The C++-generating back end previously aborted with a failed assertion in
gen_declaration_statement when a local class contains a friend declaration.
This is now fixed.  For example:

  void f() {
    class C;
    class X1 {
      friend C;   // Previously caused an assertion failure
    };
  }


1/21/26  [EDGcpfe/28652]
GNU C++ compatibility: Explicit "this" in pre-C++23 modes

In GNU C++ modes with gnu_version >= 140000 the front end now accepts the C++23
explicit "this" feature (see the entry for EDGcpfe/24781) with a warning in
pre-C++23 modes.


1/21/26  [EDGcpfe/28653]
GNU/Clang compatibility: __builtin_is_virtual_base_of

The new type trait intrinsic __builtin_is_virtual_base_of is now supported in
Clang 20+ and GCC 15+ modes.


1/21/26  [EDGcpfe/28656]
Microsoft compatibility: Extended range-based-for now available with --ms_c++17

The changes to extend the lifetime of temporaries in a range-based-for
(see the Changes entry for EDGcpfe/25861,EDGcpfe/26070,EDGcpfe/27957) have
now been enabled with --ms_c++17 or later (previously they were available in
Microsoft mode only with --c++23 or --ms_c++23).


1/21/26  [EDGcpfe/28649]
Clang compatibility: Special handling for new __builtin_elementwise_* builtins

Clang 22 added new __builtin_elementwise_fshl, __builtin_elementwise_fshr,
__builtin_elementwise_clzg, and __builtin_elementwise_ctzg builtins for which
special handling is required.


1/20/26  [EDGcpfe/28572]
GNU compatibility: "#pragma riscv intrinsic"

The front end now supports the "#pragma riscv intrinsic" construct to support
the GCC header file "riscv_vector.h" on RISC-V platforms.


1/20/26  [EDGcpfe/28650]
Missing field initialization in alloc_instantiation_directive

In configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE, the code in
alloc_instantiation_directive failed to initialize the declared_type field
(that was added with the changes for EDGcpfe/26294 in version 6.8).


1/19/26  [EDGcpfe/28648]
Clang compatibility: Clang 22 builtins

The front end has been updated with the latest builtin signatures from Clang
version 22 (based on the recently-released RC1).


1/16/26  [EDGcpfe/28647]
Overload resolution with __fp16 argument

The changes for EDGcpfe/28034 in version 6.8 of the front end introduced
special handling for __fp16 types during overload resolution.  However, the
change did not correctly account for uses of __fp16 through type aliases and
such situations could lead to the new tie-breaker rule randomly being ignored.
That is now fixed.


1/15/26  [EDGcpfe/28644]
C++-generating back end: dependent using declarations

As a result of the changes for EDGcpfe/26294 in version 6.8, the
C++-generating back end sometimes incorrectly dropped the "typename"
keyword in a dependent using declaration naming a type.  This is now fixed.
For example, with --c++14:

  template <typename> struct a;
  template <typename b> using c = typename a<b>::d;
  template <typename e> using h = c<e>;
  template <typename e> class j {
    using typename h<e>::l;   // Previously omitted "typename"
  };


1/15/26  [EDGcpfe/28635]
C++-generating back end, Microsoft compatibility: dependent operator template
calls

As a workaround for a bug in early versions of MSVC, the C++-generating
back end previously omitted the "template" keyword in a dependent call to
an operator template with an explicit template argument list when MSVC is
the generated code target (see EDGcpfe/16078).  The most recent versions of
MSVC now require the keyword to be present, however, and the previous bug
has long been fixed, so the C++-generating back end will now suppress the
keyword only when msvc_target_version_number is less than 1910.  For
example, with --microsoft --msvc_target_version=1950 --parse_templates:

  template<typename T> void t() {
    T a;
    a.template operator()<int>();   // Previously omitted "template"
  }


1/14/26  [EDGcpfe/28642]
GNU compatibility: GCC 16 builtins

The front end has been updated with the latest builtin signatures from
GCC version 16 (based on the 20260111 pre-release snapshot).


1/13/26  [EDGcpfe/28641]
GCC and Clang C compatibility: Constant-evaluation of some built-ins

Consider, in GCC or Clang C mode:

  int arr[__builtin_strlen("abc")];

Previously, this resulted in errors because traditional C and C++03 constant
expressions can only involve integral constant operands.  Now, that constraint
is lifted for certain built-in functions (like __builtin_strlen) and the
example above is accepted.


1/12/26  [EDGcpfe/28639]
Inconsistent initialization of local_static_constexpr_enabled

The thread-local variable local_static_constexpr_enabled was not consistently
initialized when MULTIPLE_THREAD_COMPILATION is TRUE.  This is now fixed.


1/12/26  [EDGcpfe/28634]
for-loop initialization and break statements

Consider:

  struct D { D(); ~D(); operator bool(); };
  void g() {
    for (D d0; D d1;) {
      D d2;
      break;
    }
  }

The break statement is expressed in the IL as a special goto-label statement
pair.  Previously, this transformation produced code more or less as follows:

    { D d0;
      for (; D d1;) {
        D d2;
        /* Clean up d2, d1, and d0. */
        goto break_label;
      }
      /* Clean up d0 here. */
      break_label:;
    }

I.e., the destruction of any variable declared in the for-loop initialization
was done in two places, before the "goto" and also before the break label.
Now, instead, it is done only following the break label, resulting in
transformed code more or less as follows:

    { D d0;
      for (; D d1;) {
        D d2;
        /* Clean up d2 and d1, but not d0. */
        goto break_label;
      }
      break_label:;
      /* Clean up d0 here. */
    }

The two representations are semantically equivalent, but the latter is a little
more representationally efficient and it has the property that the break label
statement remains immediately-following the associated for-loop statement in
the IL.


1/8/26   [EDGcpfe/28604]
Regression causing assertion failure when using implicit includes

The changes for EDGcpfe/27955 (in version 6.8), introduced a regression causing
an assertion failure in f_entity_can_be_instantiated.  This assertion failure
occurs when parsing the following example with "--c++17 --implicit_include":

  struct I { static constexpr int one = 1; };
  template<typename T> struct S {
    static constexpr int N = T::one;
    S() {}
    S(E<N> x) {}
  };
  void g() {
    S<I> x;
    S y(x);
  }

This is now fixed.


1/12/26  [EDGcpfe/28630]
Assertion failure on zero-length array initialization

In configurations that use lowering, the lowering of an array with zero
elements had, in some cases, caused an assertion failure in
lower_dynamic_init_aggregate_constant.  This regression was introduced in
version 6.8 (by the changes for EDGcpfe/28106) and is now fixed.  For example,
with --g++:

  struct A {
   A();
  } a[0];


1/12/26  [EDGcpfe/28638]
Constant evaluation of __builtin_complex

The front end can now evaluate __builtin_complex invocations in its
constant-evaluation interpreter.


1/8/26   [EDGcpfe/28620]
Microsoft C++ compatibility: operator[]

In Microsoft C++ modes with either microsoft_version >= 1942 and the option
--ms_c++latest or microsoft_version >= 1943 and the option --ms_c++23, a
user-declared operator[] can have zero or more parameters and those parameters
can have default arguments (see also the changes for EDGcpfe/24785,... in
version 6.8).


1/8/26   [EDGcpfe/28633]
Use of uninitialized variable in conv_utf8_buffer (Windows only)

The front end in configurations without CPPCLI_ENABLING_POSSIBLE set used an
uninitialized variable in the conv_utf8_buffer function (i.e., when processing
UTF-8 paths on Windows).  This could lead to crashes and is now fixed.


1/7/26   [EDGcpfe/27257]
GCC compatibility: Severity of narrowing in brace-notation cast

Consider, in C++11 mode:

  struct S { unsigned arr[2]; };
  int make_int();
  S g() {
    return S{ 1, make_int() };  // Normally a narrowing error.
  }                             // Now a warning in GNU C++ mode.

Technically, this is invalid in C++11 because the initialization of arr[1]
with make_int() requires a narrowing conversion.  However, GCC only issues a
warning in this case and the front end now emulates that (GCC also only issues
a warning in various other cases that ought to be errors, but the front end
already emulated those other cases).


1/7/26   [EDGcpfe/28397,EDGcpfe/28632]
Abort on checking of nested constraints

With the changes for EDGcpfe/27599 (in version 6.7), the front end could abort
in some cases due to a failed internal assertion in get_expr_rescan_info when
checking nested constraints.  For example, with --c++20:

  template<int> struct C {
    static constexpr bool v = true;
  };
  template<int I> struct B
  {
    template<int> struct D {
      static int f(auto) requires(C<I>::v);  // Previously aborted.  Now okay.
    };
  };
  int i = B<1>::D<2>::f(3);


1/6/26   [EDGcpfe/28619]
Lambda-vs-designator disambiguation with lambda attributes

Consider, in C++23 mode:

  struct F { template<typename T> F(T) {} };
  auto r = F{ [] [[]] () {} };  // Previously an error.  Now okay.

The front end previously treated the first bracket ("[") in the initializer of
r as the beginning of an array designator.  This was caused by the presence of
attributes following the leading "[]" and resulted in spurious syntax errors.
The disambiguation for this case has now been fixed to correctly handle lambda
attributes (a C++23 feature; see the Changes for EDGcpfe/25076,EDGcpfe/26487
in version 6.6).


1/5/26   [EDGcpfe/28618]
Regression causing segfault in extract_member_bodies

With the changes for EDGcpfe/27955 (in version 6.8), in rare cases, a segfault
could occur during sorting of template cache segments within
extract_member_bodies.  This is now fixed.


12/31/25 [EDGcpfe/28627]
Allow use of type containing an unknown-sized array with --ms_extensions

The use of a type containing an unknown-sized array is allowed in Microsoft
mode but had been disallowed in GNU/Clang modes with --ms_extensions.  This
is now allowed in C mode (with --gcc --ms_extensions):

  struct A {
    int x[];
  };
  struct B {
    struct A a;
    int i;
  };


12/31/25 [EDGcpfe/28562]
C++-generating back end: injected-class-name in templated function definition

In general, the injected-class-name of a class template can be referred to
using either the template name by itself or with its template parameters as
the corresponding template arguments (the latter form is required when
there is a name qualifier, because the qualified name refers to the
template itself, not directly to the injected-class-name).  The
C++-generating back end previously always used the latter form, even in
unqualified names.  However, a member name in the class template definition
can hide the name of a template parameter in the definition of a member of
the class template, potentially making the longer form incorrect in such
cases.  The C++-generating back end has now been changed to use only the
class template name by itself when referring to the template's unqualified
injected-class-name, avoiding this issue.  For example:

  template <class T, class> struct A {
    typedef T U;
    T f(const int&);
    T f(int, int);
  };
  template <class T, class U> T A<T, U>::f(const int &a) {
    return A::f(a, 0);   // #1
  }
  A<char,int> x;
  char z = x.f(0);   // #2

The C++-generating back end previously put out the name of the member
function on the line marked #1 as "A<T,U>::f".  However, at that point the
template parameter U is hidden by the member typedef A::U, so the meaning
of "A<T,U>" is "A<T,A::U>", which is a different type unless the arguments
for T and U denote the same type.

When A<char,int>::f(const int&) is instantiated at #2, in the original
source form, the call "A::f(a,0)" refers to a non-static member of the same
class, A<char,int>, so "this->" is implicitly added to the call.  With the
form previously used by the C++-generating back end, however, the qualifier
denotes A<char,char> instead of A<char,int>, and the call elicits an error
because of a missing object expression in the reference to the non-static
member function A<char,char>::f(int,int).


12/29/25 [EDGcpfe/28606]
C++-generating back end: qualification resulting in inaccessible names

In some cases, the C++-generating back end added qualification to a name
from a base class, even though naming it in that class would result in the
name being inaccessible in the current scope.  This is now fixed.  For
example, with --c++23:

  struct D;
  namespace N {
    class B {
      friend struct ::D;
      static void f(::D&);  // private
      static void f(int);   // private
    };
  }
  struct D : private N::B {
    using N::B::f;   // public
  };
  void g()   {
    D *dp;
    dp->f(*dp);   // Previously generated as (inaccessible) "dp->N::B::f"
  }


12/29/25 [EDGcpfe/28491]
Intrinsic treatment of commonly-occurring variable templates

The front end now has the capability to recognize certain variable templates
and handle their initializer "intrinsically".  The initial implementation
provides support for std::is_integral_v and std::is_object_v.  When the
capability is enabled, instantiation of the associated initializers ignores
the definition in the source code and produces the standard resulting value
(which normally should be equivalent to what the source code specifies).  This 
often bypasses the instantiation of associated class templates (like
std::is_integral) resulting in better performance (including reduced memory
usage).  Occasionally, it may also affect diagnostics that previously
mentioned these associated templates, including possibly not diagnosing cases
where the associated class template is invalid.  The intrinsic treatment is
enabled when the global variable var_templ_intrinsics_enabled is TRUE.  That
variable is initialized by the new (TRUE by default) configuration macro
DEFAULT_VAR_TEMPL_INTRINSICS_ENABLED.  The variable can also be controlled
from the command line with the --set_flag/--clear_flag options.  See the
comments in sys_predef.h for how to add support for additional variable
templates.


12/29/25 [EDGcpfe/28607]
C++-generating back end, Microsoft compatibility: class-type explicit temporary
as non-type template argument

MSVC has a bug that results in a fatal compiler error when an explicit
temporary of class type is used as a non-type template argument in a block
scope.  For example, the following code,

  struct A { int x; };
  template<A> void f() { }
  int main() {
    (void(*)())&f<A{0}>;
  }

results in MSVC exiting with fatal error C1903.  Enclosing the template
argument in parentheses, i.e., "f<(A{0})>", avoids the MSVC bug, and the
C++-generating back end has now been changed to add parentheses in such
cases when msvc_is_generated_code_target is TRUE.


12/29/25 [EDGcpfe/28609]
C++-generating back end: initializer for decltype(auto) variable

The changes in version 6.8 for EDGcpfe/28434 contained a logic error that
inadvertently omitted significant parentheses around a variable name used
as the initializer for a variable declared with the "decltype(auto)" type.
This is now fixed.  For example, with --c++23:

  void g() {
    int x;
    decltype(auto) y = (x);   // Previously omitted parens around "x"
  }


12/24/25 [EDGcpfe/28621]
Microsoft C++23: Local non-automatic variables in constant evaluation

The changes for EDGcpfe/25856 in version 6.8 are now also enabled in
Microsoft C++23 mode (--ms_c++23) if microsoft_version >= 1944.


12/24/25 [EDGcpfe/27832]
Constant evaluation of null pointer offsets

The front end now accepts some null pointer "offset" computations at compile
time in Clang C++ modes, particularly in array dimension expressions.
For example:

  int arr1[(long)(char*)0];  // Previously an error.  Now okay.
  struct S { int i; };
  int arr2[(((long long)&(((S*)0)->i)) == 0)? 1 : -1];  // Ditto.


12/23/25 [EDGcpfe/19447,EDGcpfe/28601]
Severity of floating-point conversion diagnostics

In nonstrict C modes the front end now reduces the severity of certain
floating-point conversion diagnostics to a warning instead of an error.
For example (assuming a 32-bit IEEE-754 float type):

  float sf = 2.4674957095607889277282112901141e-77;

Previously, this resulted in an error in C mode because the initializer must
be constant but the given constant underflows to zero.  Now, the example is
accepted with a warning.


12/23/25 [EDGcpfe/28600]
auto(...) and auto{...} in non-C++23 modes

The changes for EDGcpfe/26452 and EDGcpfe/28379 enabled the C++23 "auto cast"
feature in modes that aren't C++23 modes from the front end's perspective.
However, those changes overlooked some ambiguity resolution issues, causing,
e.g., the following example to mis-parsed:

  template<typename T> void f() noexcept(noexcept((auto(T{}))));

This is now fixed.


12/23/25 [EDGcpfe/28587]
Build warnings with Visual Studio

In some configurations, a few data types and constructs were resulting in
warnings when the front end was compiled with recent versions of Visual
Studio.  These have now been addressed.


12/22/25 [EDGcpfe/28593]
Internal error with C11 _Generic construct

In configurations with REPRESENT_C11_GENERIC_CONSTRUCT_IN_IL, the front end
could abort with an internal error in Microsoft C11 modes when processing a
C11 _Generic construct: The internal error triggered in the function
conv_glvalue_expr_to_prvalue (exprutil.c, with message "bad expr").  That is
now fixed.


12/19/25 [EDGcpfe/28586]
__builtin_add_overflow, etc.

The changes for EDGcpfe/18917 (etc.) added support for folding of arithmetic
operation intrinsics (like __builtin_add_overflow, etc.) that record the
occurrence of overflow.  Some cases combining signed source types and an
unsigned destination type did not produce the correct result.  For example:

  constexpr bool f() {
    unsigned b{};
    return  __builtin_sub_overflow(0, -1, &b);
  }
  static_assert(!f(), "");  // Previously failed.  Now okay.

That is now fixed.


12/19/25 [EDGcpfe/28585]
Covariant overrides and accessibility

Consider:

  class C;
  class BR {};
  class DR: private BR { friend C; };
  class B { virtual BR *f(); };
  class C: B { DR *f(); };
  class D: C { DR *f(); };  // Previously an error.  Now okay.

Previously, the front end produced an error claiming the return type of D::f()
is not covariant with the function it overrides.  This was triggered because
it checked accessibility for the conversion of DR* to BR* in the context of D,
even though that conversion is only needed for C::f().  That is now fixed.


12/19/25 [EDGcpfe/28598]
Incorrect handling of constant-folded default arguments

Consider:

  struct X {
    int x;
    constexpr X(): x(0) {}
    constexpr X(X const& a): x(a.x) {}
  };
  int f(X a = {}) {
    return ++a.x;
  }
  int main() {
    return f() + f() - 2;
  }

Previously, the two calls of f() were represented by IL that involved an
enk_constant argument node pointing to the same constant (the constant was
obtained by folding the default argument).  Lowering then proceeded to create
a single variable holding that constant value and erroneously passing that
variable "by hidden reference" to the lowered function f(...). That is now
fixed: The argument to the call f() is now an enk_temp_init node initialized
with the folded constant, thereby ensuring that every call sees a distinct
argument object.


12/19/25 [EDGcpfe/28614]
Constant-evaluation of relational operators involving NaNs

Some constant-evaluation of relational operators involving NaN values had
produced incorrect results.  For example, with --g++ --c++23:

  static_assert (!(__builtin_nanf("") <= 0.0f));


12/18/25 [EDGcpfe/28613]
C++-generating back end: Unnecessary qualification of template-ids

As a result of the changes for EDGcpfe/26294 in version 6.8, the
C++-generating back end could add unnecessary qualification in uses of the
names of some template instances.  This is now fixed.  For example:

  template<typename T> struct A { static const bool v = false; };
  template<typename T> struct B : public A<T> { };
  template<bool> struct C { };
  template<typename T> struct D : C<A<T>::v> { };  // Previously "::C"


12/17/25 [EDGcpfe/28584]
Attributes on asm declarations

The front end now potentially accepts attributes on asm declarations.  This
implements the resolution of Core issue 2262.  For example:

  [[]] asm("nop");  // Now accepted by the front end.

Core issue 2262 was resolved as a feature addition for C++17, but common
practice is to accept these attributes in C++11 mode and later: The front end
follows suit in nonstrict modes.


12/17/25 [EDGcpfe/28605]
Missing skip_typerefs could lead to undefined behavior

A missing skip_typerefs could lead to undefined behavior in some
configurations.  For example:

  namespace N {
    struct A {
      constexpr A() noexcept = default;
      static constexpr A str(const int& str) noexcept {
        return A{};
      }
    };
    struct B {
      constexpr B(const char* str) noexcept {}
      constexpr operator A() const noexcept {
        return A();
      }
    };
    enum class V { U };
    template<A A, V Vr> void f(const B&); 
  }
  template<N::B tag, N::V Vr> struct A {
    virtual void operator<<(int) {
      f<tag, Vr>(tag);
    }
  };
  void f() {
     A<"()", N::V::U> i;
  }


12/16/25 [EDGcpfe/28589]
Spurious user-defined literal lookup errors

Previously, in some fairly complex cases involving fold expressions in template
constraints, lookup for user-defined literals could spuriously fail.  For
example, with --c++20:

  template<bool ... Bs> requires (Bs && ...)
  int f();
  namespace ns {
    int operator ""_udl(unsigned long long);
  }
  using ns::operator ""_udl;
  int i = f<true, true>() + 2_udl;  // Previously a spurious error.  Now okay.


12/15/25 [EDGcpfe/28583]
Excessive memory use for non-type template argument backing expressions

The changes for EDGcpfe/27947 in release 6.8 resulted in unnecessary copies
of some backing expressions for non-type template arguments; in large
programs, the additional memory burden could be significant.  This has now
been addressed and the unnecessary copies are no longer created.


12/15/25 [EDGcpfe/28595]
Clang compatibility: Abort on __builtin_invoke

Previously, the front end could abort with a failed assertion in
conv_expr_function_designator_to_ptr_to_function when applying __builtin_invoke
to a constexpr function call operator template or a generic lambda.  For
example, with --c++ --clang_version 210100:

  int f(int);
  int i = __builtin_invoke([](auto v) -> int { // Previously triggered an
      return f(v);                             // assertion failure.  Now okay.
    }, 1);

This change also fixes an abort due to a null pointer indirection when
attempting to use __builtin_invoke with too few arguments.  For example, with
--c++ --clang_version 210100:

  int j = __builtin_invoke();  // Previously segfaulted.  Now an error.


12/12/25 [EDGcpfe/27897,EDGcpfe/28594]
GNU/Clang compatibility: packed attribute on enums with --ms_extensions

The front end now correctly sizes enum types with the packed attribute in
GNU/Clang modes when --ms_extensions is specified.  For example (with --gcc
--ms_extensions):

  enum E { e } __attribute__((__packed__));
  _Static_assert(sizeof(enum E) == 1, "");


12/11/25 [EDGcpfe/26434]
Incorrect lowered IL generated for some range-based for statements

In some cases, the lowered IL generated for a range-based for statement
could generate a temporary variable that was used in an outer scope but
defined in an inner scope.  With the C-generating back end, the following
example (with --c++20) had generated C code that would not compile:

  struct A {
    constexpr int operator*() const { return 0; }
    A& operator++() { return *this; }
    friend bool operator==(const A& l, const A& r) { return true; }
  };
  struct B {
    A begin() const { return A{}; }
    A end() const { return A{}; }
  };
  void f() {
    auto rng = B{};
    for (const auto& e : rng) {}
  }


12/8/25  [EDGcpfe/28582]
GNU/Clang compatibility: enable asm statements with --ms_extensions

A change has been made to enable "asm" statements in GNU/Clang mode with
--ms_extensions.


12/7/25  [EDGcpfe/28574]
C++-generating back end: explicit enumerator values

The C++-generating back end generally suppressed explicit enumerator values
if the value is that of the preceding enumerator plus one, regardless of
whether the value was explicit in the source code.  Now, however, it will
put out an explicit enumerator value if it was specified in the source as a
hexadecimal or octal literal.  For example:

  enum { A = 0x7FFFFFFFUL,
         B = 0x80000000UL   // Previously omitted "= 0x80000000UL"
  };


12/6/25  [EDGcpfe/28576]
C++-generating back end, GNU C compatibility: arrays of unknown bound in
compound literals

There is a bug in gcc that results in incorrect processing of a C-language
compound literal if the type is an array with a bound of 0.  For example,
gcc compiles the following code without error:

  void f() {
    typedef struct { int i; char *s; } A;
    const A a[] = {
      { .i = 0, .s = (char[]){} },   // #1
      { .i = 1, .s = (char[]){1} }
    };
    _Static_assert(sizeof(a) == 2 * sizeof(A));
  }

If the commented line is changed to read

      { .i = 0, .s = (char[0]){} },

gcc reports that the static assertion failed.  When the array bound is
omitted, as in the original form of the example, the front end deduces the
bound from the initializer, giving a bound of 0 for the initializer "{}",
and the C++-generating back end previously put out "char[0]" for the type,
triggering the gcc bug when the generated code was compiled.  This has now
been changed; when gcc_is_generated_code_target is TRUE, the C++-generating
back end now emits the type of an array of zero bound as, e.g., "char[]",
avoiding the gcc bug.


12/5/25  [EDGcpfe/28580]
Intrinsic treatment of commonly-occurring alias templates

The front end now has the capability to recognize certain alias templates and
handle their substitution "intrinsically".  The initial implementation provides
support for std::remove_cv_t, std::remove_const_t, std::remove_volatile_t,
std::remove_reference_t, and std::remove_cvref_t.  When the capability is
enabled, substitution of these aliases ignores the definition in the source
code and produces the standard underlying types (which normally should be
equivalent to what the source code specifies).  This often bypasses the
instantiation of associated class templates (like std::remove_cv) resulting in
better performance (including reduced memory usage).  Occasionally, it may also
affect diagnostics that previously mentioned these associated templates and
now only mention the underlying type instead.  The intrinsic treatment is
enabled when the global variable alias_templ_intrinsics_enabled is TRUE.  That
variable is initialized by the new (TRUE by default) configuration macro
DEFAULT_ALIAS_TEMPL_INTRINSICS_ENABLED.  The variable can also be controlled
from the command line with the --set_flag/--clear_flag options.  See the
comments in sys_predef.h for how to add support for additional alias templates.


12/5/25  [EDGcpfe/28217]
Nonstandard SVR4 lookup quirk in C modes

Consider, in C mode:

  int f1(void) {
    extern void f();
    extern int i;
  }
  int f2() {
    f();       // Invalid.
    return i;  // Invalid.
  }

SVR4 C (an old C dialect) accepts this even though f() and i should not be
visible outside f1().  The front end previously extended that lenience to
other nonstrict C modes, but that is not common practice for other C compilers.
Now, this quirk is only accepted in SVR4 C modes.


12/4/25  [EDGcpfe/28579]
[[clang::no_specializations]] and system headers

The front end no longer issues an error for explicit specialization of a
template declared with [[clang::no_specializations]] (or equivalent) if that
explicit specialization appears in a system header.  This is a workaround for
the front end not supporting the

  #pragma clang diagnostic ignored "-Winvalid-specialization"

directive and that directive is used in LLVM libc++ headers.


12/4/25  [EDGcpfe/28573]
C++-generating back end: default template arguments in explicit specializations

The C++-generating back end sometimes omitted default template arguments
in the template-id in an explicit specialization, which could result in
errors compiling the generated code.  This is now fixed, and all template
arguments are emitted in that context.  For example:

  enum E { O };
  template<typename> struct K;
  template<typename T, E k = K<T>::e> constexpr E e() {
    return k;
  }
  template<typename T, E = e<T>()> struct L;
  template<> struct L<int, O> {  // Previously generated as "L<int>", causing
                                 // failed deduction for e<T>() in default arg
                                 // during instantiation of L<int> below since
                                 // K<int> is not defined at this point
  };
  template<> struct K<int> {
    static constexpr E e = O;
  };
  L<int> l;


12/4/25  [EDGcpfe/28578]
Block scope expressions in attributes caused IL overwriting

The changes for EDGcpfe/25517,EDGcpfe/25844 (in version 6.8) introduced
a bug that could overwrite IL when a block scope expression argument in an
attribute was used (currently only the case with "assume" and "enable_if"
attributes).  That is now fixed.  For example:

  void f() { __attribute__((__assume__(unsigned()))); }


12/4/25  [EDGcpfe/28577]
Incorrect legacy configuration macro name

The changes for EDGcpfe/27947 (in version 6.8) introduced a new
configuration macro, BACKING_EXPR_FOR_NONTYPE_TEMPL_ARG, that made an
existing similar macro, KEEP_TEMPLATE_ARG_EXPR_THAT_CAUSES_INSTANTIATION,
obsolete.  An attempt was made to ease the transition by defaulting the
value of the new macro to that of the older macro; unfortunately, the name
of the older macro was incorrect in this setting, disabling the implicit
migration.  That is now fixed.


12/2/25  [EDGcpfe/28500]
Recording macro arguments

When configured with RECORD_MACRO_ARGS set to TRUE, the front end now adds
the field "arguments" to a_macro_invocation_record.  For invocations of
function-like macros, the new field points to a null-terminated string
containing the text of the unexpanded macro arguments in the corresponding
invocation.  The tokens of each argument are separated by a single space
character, and the arguments are separated by a comma-space pair.  The
field is NULL for object-like macros.  For example:

  #define M(x,y)  /* Nothing */
  #define X a
  M(X /* */ b,c  ,   d+e)   // Argument string is "X b, c, d + e"


12/2/25  [EDGcpfe/28575]
Regression resulting in all PCH files failing to load

With the changes for EDGcpfe/28019 (in version 6.8), the front end (when built
on platforms where the size_t and long types differ in size) would fail to
read all PCH files.  This is now fixed.


12/2/25  [EDGcpfe/28568]
Erroneous IL produced for aggregate initializer containing pointer to function

Consider:

  void g();
  int main() {
    void (*apf[2])(void) = { nullptr, &g };
  }

The changes for EDGcpfe/28480 (in version 6.8) cause the front end to sometimes
emit a ck_init_repeat entry when multiple aggregate initializers are equal
after folding.  A bug in the determination of "equality" for null pointers
resulted in this mechanism being triggered erroneously when a null pointer is
followed by a non-null function pointer (as in the example above).  That is
now fixed.


12/2/25  [EDGcpfe/27044]
Compilation issues when building on non-x86 platforms

Support for the __float128 type is not widely available on non-x86 platforms,
which can lead to compilation issues with the default configuration on Linux.
A change has been made to use _Float128 instead of __float128 as the host
floating point type on non-x86 platforms.


12/2/25  [EDGcpfe/28565]
Support for RISC-V processors (IL CHANGE)

Two new configuration macros, TARG_SUPPORTS_RISCV32 and TARG_SUPPORTS_RISCV64
(and corresponding global variables targ_supports_riscv32 and
targ_supports_riscv64) have been added to support RISC-V processors.  This
change also adds support for builtins on RISC-V architectures with the
exception of builtins for the RISC-V vector extension.  Support for
RISC-V-specific vector types has also been added, which are represented as
tk_riscv_vector types in the IL.


12/1/25  [EDGcpfe/28552]
Assertion failure in diagnostic_pragma

In some cases, the use of "#pragma diagnostic" could result in an assertion
failure in diagnostic_pragma.  For example, with --c++14 --g++:

  #pragma diagnostic push
  template <class T> constexpr void f() {
    _Pragma("diagnostic push")
    _Pragma("diagnostic pop")
  }
  #pragma diagnostic pop
  #pragma diagnostic push
  void g() {
      f<void>();
  }
  #pragma diagnostic pop


12/1/25  [EDGcpfe/28553]
Variadic expansion of attributes

Consider, in GNU C++11 mode:

  template<int ...Is> [[gnu::aligned(Is) ... ]] void g() {}
  int main() {
    g<2, 4, 8>();
  }

The front end previously failed to apply the expanded attribute to the instance
of g.  That is now fixed.


12/1/25  [EDGcpfe/28569]
Cross-translation-unit correspondences

In configurations where the front end might have to deal with multiple
translation units simultaneously, it records "cross-translation unit
correspondence" entries.  Previously, however, it also accidentally did so
in other configurations (for some template instantiations).  That is now
fixed.


12/1/25  [EDGcpfe/28567]
Regression resulting in a crash during PCH loading

With the changes for EDGcpfe/27955 (in version 6.8), the front end could
sometimes segfault from using memory freed during the PCH loading process.
This is now fixed.


11/27/25 [EDGcpfe/24985,EDGcpfe/25973,EDGcpfe/26112,EDGcpfe/28367]
Abbreviated function template syntax for deduction guides

The resolution of Core issue 2697 clarified that a deduction guide cannot be
declared using abbreviated function template syntax.  However, as this is
accepted by GCC, Clang, and MSVC, the front end now also accepts it in
non-strict modes.  For example, with --c++20 --no_strict:

  template<typename>
  struct C {
    C(int);
  };
  C(auto i) -> C<decltype(i)>;  // Previously an error, now accepted in
                                // non-strict modes.

This change also fixes an issue parsing constrained generic parameters during
disambiguation.  For example, with --c++20:

  template<typename> concept X = true;
  void f(int(*)(), X auto);  // Previously a spurious error, now okay.


11/26/25 [EDGcpfe/28526]
C++-generating back end, clang compatibility: user-defined literal names

Early versions of clang did not accept the form of user-defined literal
operator names in which the literal suffix appears following the double
quotes with no intervening white space, e.g., operator""_x, so the
C++-generating back end added a space before the suffix when generating
code targeting clang.  Versions of clang beginning with 6.0 do accept this
form of the operator name, however, so the C++-generating back end now only
adds the space when clang_target_version_number is less than 60000.


11/26/25 [EDGcpfe/28561]
C++-generating back end: qualified trivial destructor names

MSVC has a bug in determining the type of a trivial destructor call when
the destructor name is qualified.  For example, given

  struct S { }; 
  void f(S *p) { return p->S::~S(); }

MSVC complains that a void function returns a value.  The C++-generating
back end generates qualified names in such cases, triggering the MSVC bug.
Now, when msvc_is_generated_code_target is TRUE, the C++-generating back
end explicitly casts trivial destructor calls to void, so the expression in
the example above is put out as

  (void)p->S::~S()

avoiding the MSVC bug.


11/25/25 [EDGcpfe/28531]
C++-generating back end, Microsoft compatibility: address of overloaded
static member function

MSVC reports a spurious error if an attempt is made to take the address of
a static member function that is overloaded with a non-static member
function unless the function name is written as a qualified name.  The
C++-generating back end previously did not qualify the function name in
this context, triggering the MSVC bug when the generated code was compiled.
This is now fixed, and a qualifier is emitted for the name in such cases
when msvc_is_generated_code_target is TRUE.  For example, with --microsoft:

  struct S {
    static void f(int) {}
    void f() {}
    void g() {
      void (*fp)(int) = &S::f;   // Previously generated as "&f"
    }
  };


11/25/25 [EDGcpfe/28560]
GNU compatibility: __cpp_runtime_arrays

Although the feature is not part of standard C++, g++ supports
variable-length arrays in C++ mode and sets the feature-test macro
__cpp_runtime_arrays to the value 198712L.  The front end emulates the
support for the feature, but it failed to set the feature-test macro.  This
is now fixed.  For example, with --c++11 --g++:

  #if !defined(__cpp_runtime_arrays) || __cpp_runtime_arrays != 198712
  #error Missing macro.   // Previously triggered, now okay.
  #endif


11/25/25 [EDGcpfe/28559]
GNU compatibility: __cpp_init_captures in C++11 mode

Although g++ supports lambda init-captures with -std=c++11, it does not
define the corresponding feature-test macro because they were part of C++14
(see EDGcpfe/28556).  The front end previously did not make a similar
distinction and defined __cpp_init_captures whenever the feature was
supported in the current emulation.  This is now fixed.  For example, with
--g++ --c++11:

  #ifdef __cpp_init_captures
  #error Incorrect feature-test macro  // Previously issued, now okay
  #endif


-------------------------------------------------------------------------------
Version 6.8, November 21, 2025

11/20/25 [EDGcpfe/28556]
GNU compatibility: defining feature-test macros in early versions

Although g++ often enables various features from recent versions of the
C++ Standard when an earlier version of the Standard is specified on the
command line, it generally does not define the corresponding feature-test
macro in such cases.  There are some exceptions to this rule, however.
Binary literals were introduced in C++14, while inheriting constructors
and hexadecimal floating-point literals were part of C++17.  Nevertheless,
g++ defines __cpp_binary_literals, __cpp_inheriting_constructors, and
__cpp_hex_float with -std=c++11.  The front end has now been changed to
emulate this behavior in g++ mode.  For example, with --g++ --c++11:

  long i = __cpp_hex_float;   // Previously an error, now has value 201603


11/18/25 [EDGcpfe/28524]
Abort due to use of a routine fixup entry that was freed

The front end sometimes accidentally left a routine fixup entry on two
distinct lists (a list associated with a class and one associated with a
translation unit).  This could cause the entry to be processed twice: The
first processing would free the entry and the second could then cause access
to freed storage, which often resulted in an abort.  That is now fixed.


11/15/25 [EDGcpfe/28530]
C-generating back end: C99 inline function definitions

According to the C99 and later Standards, the definition of an inline
function is an "inline definition" if no file-scope declaration of the
function in a given translation unit contains the "extern" keyword.  An
inline definition does not provide an external definition for the function.
Because a compiler is not required to replace a call to an inline function
with an inline expansion but can instead generate a call to its external
definition, an inline definition may result in linkage errors if no
external definition of the function is provided in another translation
unit.

The C-generating back end previously put out declarations of an inline
function with the "extern" keyword, regardless of whether the "extern"
keyword appears in the original source, and thus incorrectly converted
inline definitions to external definitions.  This is now fixed.  For
example, in the following code the declaration and definition of "fun1"
were previously incorrectly prefixed with the "extern" keyword in the
generated code:

  int x = 0;
  inline void fun1() {   // Previously prefixed with "extern"
    x = 1;
  }
  int main () {
    fun1(); // Possible linkage error in the original, always succeeded with
            // the generated C because fun1 became an external definition
  }

This is now fixed.


11/13/25 [EDGcpfe/28484]
Microsoft compatibility: Reference initialization type traits

In Microsoft mode with microsoft_version >= 1951 the front end now accepts the
type trait helpers __reference_constructs_from_temporary and
__reference_converts_from_temporary.  (These were previously already accepted
in GCC and Clang compatibility modes.)


11/10/25 [EDGcpfe/28477]
Unified friend listing (IL CHANGE)

The IL representation of a class's befriended entities (in
a_class_type_supplement) has been unified; there is now a single list (the new
friends field) representing all befriended entities (previously, there were
friend_routines and friend_classes fields).  Additionally, befriended
templates are now included in this list (previously, they could not easily be
retrieved).


11/7/25  [EDGcpfe/28520]
Clang compatibility: floating-point template parameters enabled with --c++20

Floating-point template parameters (a C++20 feature) are now enabled when
clang_version >= 180000 and --c++20 or later is specified.


11/7/25  [EDGcpfe/28521]
C++-generating back end: template parameter pack expansions

The C++-generating back end previously enclosed a template parameter name
in redundant parentheses when it appears in a pack expansion in a template
argument.  Although most implementations accept the resulting code without
an error, clang reports a deduction problem.  Accordingly, the
C++-generating back end has now been changed to suppress these redundant
parentheses in the generated code.  For example, with --c++20:

  template<int...>  struct A { };
  template<typename T> struct B { };
  template<auto... Xs> struct B<A<Xs...>> { };  // Previously generated as
                                                // B<A<(Xs)...>>


11/5/25  [EDGcpfe/28519]
C++-generating back end: friend declarations of dependent nested type

The front end previously incorrectly added a "class" keyword to a friend
declaration of a dependent nested type.  This is now fixed.  For example,
with --c++17:

  template <bool, typename a> struct A { typedef a type; };
  template <bool b, typename a> using c = typename A<b, a>::type;
  template <bool b> class d {
    friend c<b, int>; // Previously generated as "friend class A<b,int>::type"
  };


11/5/25  [EDGcpfe/28445]
Exception specifications on deallocation functions

Since C++11, predefined deallocation function declarations should be "noexcept"
but were instead "throw()".  Now fixed.


11/5/25  [EDGcpfe/28428]
Floating point configuration consistency

The C and C++ Standards do not mandate the representation to be used for
the "long double" type.  The front end accommodates this flexibility by
offering three configuration options, FP_LONG_DOUBLE_IS_BINARY64,
FP_LONG_DOUBLE_IS_80BIT_EXTENDED, and FP_LONG_DOUBLE_IS_BINARY128, to
specify the representation to be used.  However, it also allows configuring
the characteristics (the number of bits in the mantissa and the minimum and
maximum exponent values) of each floating point type.  The front end now
ensures that the TARG_LDBL_MANT_DIG, TARG_LDBL_MIN_EXP, and
TARG_LDBL_MAX_EXP settings match the FP_LONG_DOUBLE_IS_* setting and issues
a build error if a mismatch is detected.  In addition, if the TARG_LDBL_*
values are not set explicitly but one of the FP_LONG_DOUBLE_IS_* options is
TRUE, the TARG_LDBL_* values are defaulted to match the selected
FP_LONG_DOUBLE_IS_* option.


11/4/25  [EDGcpfe/28370]
GCC and Clang C++ compatibility: Core issue 2084

The changes for EDGcpfe/21433 implemented the resolution for core issue 2084,
which causes a union to be default constructible if it has a single member
with a default initializer even if another member has a nontrivial default
constructor (which in other circumstances would make the union's default
constructor deleted).  However, those changes were not enabled in Clang and
GCC modes because neither Clang nor GCC implemented that resolution at the
time.  Now, the standard-conforming behavior is enabled in GCC mode with
gnu_version >= 130000 and in Clang mode with clang_version >= 170000.


11/4/25  [EDGcpfe/28516]
Spurious protected member access error

Consider (in C++20 mode):

  template<typename T> struct B {
  protected:
    void f() requires true {}
  };
  struct D: B<int> {
    void d() {
      this->f();  // Previously an error.  Now okay.
    }
  };

Previously, the front end erroneously issued an error about f() being
inaccessible.  Accessing a protected member from a derived class requires the
selector object to be of a derived type (and not of the class enclosing the
member; e.g., ((B<int>*)this)->f() would be an error).  The spurious error for
this example was the result of "this" being prematurely converted to the base
class type.  That is now fixed.


11/2/25  [EDGcpfe/28514]
Type with defaulted trivial destructor spuriously considered non-literal

In some complex cases, a type containing a defaulted trivial destructor was
sometimes treated as "non-literal" even when it satisfied all the standard
requirements for a literal type.  This could lead to spurious errors, e.g.,
when the type was used as the return type of a constexpr function.  This is
now fixed.


11/2/25  [EDGcpfe/28513]
Hexadecimal floating-point literals and 80-bit floating-point types

In configurations supporting 80-bit floating-point types, the front end
previously sometimes created invalid internal values when converting from
some hexadecimal floating-point literals.  This is now fixed.  For example,
with --g++:

  __float80 f0 = 0x0.0000000b504f334p-16385W;   // Previously produced an
                                                // incorrect value, now okay.


10/30/25 [EDGcpfe/28379]
Microsoft compatibility: auto(...) and auto{...}

The C++23 feature that allows function-notation casts to type "auto" is now
also accepted when microsoft_version >= 1950 and --ms_c++23 is specified on
the command line.


10/30/25 [EDGcpfe/28485]
Clang compatibility: __make_signed and __make_unsigned

When __make_signed and __make_unsigned are applied to enumeration types, the
front end previously handled enumeration types as if they were replaced with
their underlying type.  Now, instead, the result is based on the "lowest rank
integer" whose size equals the size of the enumeration type.  For example,
if long and long long have the same size, but int has a smaller size than long,
then with

  enum E: unsigned long long {};

__make_signed(E) now produces type long whereas previously it produced type
long long.


10/30/25 [EDGcpfe/28504]
Clang compatibility: Implicit type contexts in pre-C++20 modes

C++20 introduced "implicit type contexts" where the "typename" keyword is no
longer required to disambiguate names with a dependent qualifier.  For
example:

  template<typename T> using A1 = typename T::Type;
  template<typename T> using A2 = T::Type;

Prior to C++20, the definition of A1 is valid but A2 is not.  C++20 made the
"typename" prefix optional in this context (since nothing but a type is valid
here).  In Clang pre-C++20 modes (with clang_version >= 160000), the front end
now also accepts the second form but with a warning indicating that the
missing "typename" is nonstandard.


10/28/25 [EDGcpfe/24748,EDGcpfe/26366,EDGcpfe/28510,EDGcpfe/28511]
Friends defined in class template instantiations and constexpr requirements

Certain failing constraints on constexpr functions -- such as the requirement
that their return type be a literal type -- do not result in an error if the
failure is on the instance of a templated function; instead, that instance is
silently handled as a non-constexpr function.  The front end now treats
constexpr friend functions defined in class templates in the same way.
For example:

  struct S { S(); };  // Not a literal type.
  template<typename T> S g(T);
  template<typename T> struct X {
    friend constexpr auto f(X<T> x) {
      return g(x);
    }
  };
  X<int> xi;
  auto r = f(xi);

Previously, this example complained about the return type of f(X<int>) not
being a literal type.  Now the example is accepted.


10/28/25 [EDGcpfe/28507]
Microsoft and GNU compatibility: Literal types

Consider, in C++14 or C++17 mode:

  class C {
    int i = 0, j;
  };
  static_assert(!__is_literal_type(C), "");  // Now an error in GNU and
                                             // Microsoft modes.

C is normally not a literal type because its default constructor doesn't
initialize j (and thus is not constexpr) and it is not an aggregate class
(because it has private members).  GCC and MSVC, however, do treat C as a
literal type and the front end now emulates that behavior.


10/28/25 [EDGcpfe/28503]
C++-generating back end renders implicit operator== declaration

Consider:

  #include <compare>
  struct S {
    friend std::strong_ordering operator<=>(S, S) = default;
  };

An implicit operator== is generated by the front end for struct S.  Previously,
the front end erroneously also generated a source sequence entry for a
declaration of that operator==, which in turn caused the C++-generating back
end to render that declaration (but not its associated definition).  That could
then lead to linker errors in the target code (due to the missing definition
for the generated operator== declaration).  That is now fixed: No source
sequence entry is generated for the implicit declaration (which is thus not
rendered by the C++-generating back end).


10/27/25 [EDGcpfe/28498]
Clang compatibility: extended floating-point types

As of at least version 21, clang does not support the extended
floating-point types defined in the C++23 Standard.  The front end,
however, erroneously did so in clang emulation mode.  This is now fixed.
For example, with --clang_version=210000 --c++23:

#ifdef __STDCPP_FLOAT32_T__
 _Float32 float32;   // Previously an error, "_Float32 is undefined"; now
                     // accepted because the feature-test macro is not defined
#endif


10/27/25 [EDGcpfe/28436]
GNU/clang compatibility: large integer user-defined literals

In clang and g++ modes, the front end previously issued spurious
diagnostics (a warning in g++ mode, a discretionary error in clang mode)
for very large integer user-defined literals that invoke a raw user-defined
literal operator or a specialization of a user-defined literal template.
(Such user-defined literals were accepted without a diagnostic in other
emulation modes.)  This is now fixed.  For example, with --c++17
--clang_version=190100:

  template <char... Cs> __int128 operator""_i128() {
    return 0;
  }
  __int128 i128_max() {
    return 170141183460469231731687303715884105727_i128;  // Previously an
                                                          // error, now okay
  }


10/27/25 [EDGcpfe/28315]
Microsoft compatibility: friend class name injection

A change has been made to no longer enable friend class name injection when
Microsoft extensions are used in modes other than Microsoft or Microsoft
compatibility modes, in order to better emulate the behavior of GCC/Clang.  For
example, with --c++ --clang_version 210100 --ms_extensions:

  template<typename>
  struct C {
    template<typename>
    friend struct B;
    struct B;  // Previously a spurious error.  Now okay.
  };


10/24/25 [EDGcpfe/26294]
Recording the form of template arguments (IL CHANGE)

In configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE, the
front end now records the form of template arguments and any name qualifiers
used for type specifiers in the IL.  A typeref of kind trk_template_arg_list
represents an alternative template argument list that differs from the
canonical template argument list for a class template specialization.
Furthermore, a typeref of kind trk_name_qualifier represents the name
qualifiers used for a type specifier.  This information is stored in the
template_arg_list and name_qualifier fields, respectively, of the associated
typeref type supplement.  Additionally, the is_global_qualified_name flag in
the typeref variant of a typeref of kind trk_name_qualifier indicates that the
type specifier uses a global namespace qualifier.  For example, with --c++11:

  using INT1 = int;
  using INT2 = int;
  inline namespace ns {
    template<typename T> class C {};
  }
  C<INT1> c1;
  C<INT2> c2;
  ns::C<int> c3;

Here, the type of c1 points directly to the class template specialization with
the canonical template argument list <INT1>.  The type of c2 points to a
trk_template_arg_list typeref with an alternative template argument list <INT2>
for the same class template specialization, and the type of c3 points to a
trk_template_arg_list typeref with an alternative template argument list <int>,
which in turn points to a trk_name_qualifier typeref with the name qualifier
ns.  For cases where the new typeref kinds are not needed, a new utility
function skip_lexical_typerefs has been added to skip over these typeref kinds.

Similarly, the orig_template_arg_list field of a_name_reference points to the
template argument list as written for variable and function template
specializations.  Additionally, an orig_class_of_which_a_member field has been
added for pointer-to-member types, and a declared_type field for explicit
instantiation directives, referring to the types as written.

The C++-generating back end has also been updated to use the new information in
the generated output.


10/23/25 [EDGcpfe/27955,EDGcpfe/27993]
Token Cache Refactor

The internal representation of token caches has been refactored.  Token caches
now have a more C++-style API that provides a good foundation for future
improvements, improves memory safety, and greatly improves encapsulation.  As a
result of these changes, multiple crashes that previously occurred when the
front end was attempting to parse invalid C++ code are now fixed.


10/22/25 [EDGcpfe/27848,EDGcpfe/28506]
Spurious errors and/or abort on new-expression with a parenthesized initializer

A new-expression for a non-dependent type with a parenthesized aggregate
initializer appearing in a template could trigger parsing errors.  In some
configurations those errors could lead to an abort (an internal error).  For
example, in GNU C++20 mode:

  struct S { int i; };
  template<typename T> S* f(T p) {
    S s = { x };
    return new S(s);  // Previously could trigger parsing errors followed by
  }                   // an internal error.

This is now fixed.


10/22/25 [EDGcpfe/28469]
Substitution failure on friend function template

Previously, the front end sometimes failed to substitute into a friend function
template with a non-type template parameter declared using a typedef name.  For
example, with --c++11:

  using INT = int;
  template<int> struct B {};
  template<typename>
  struct C {
    template<INT i, B<i + 1> * = nullptr>
    friend int f(C, B<i>) {
      return 0;
    }
  };
  int i = f(C<int>{}, B<0>{});  // Previously a spurious error.  Now okay.


10/20/25 [EDGcpfe/28480]
Repeated array element values in constant expressions (IL CHANGE)

The constant evaluation interpreter now recognizes repeated array element
values in its results and represents them using a ck_init_repeat entry
instead of producing a potentially-large sequence of identical a_constant
entries.  As part of this change a few fixes were applied to the handling
of ck_aggregate and ck_init_repeat entries for arrays elsewhere in the
interpreter.


10/17/25 [EDGcpfe/28497]
Direct reference binding and explicit conversion functions

Consider:

  struct X {};
  struct Y { explicit operator X&&(); } y;
  X &&r(y);  // Previously an error.  Now okay.

The front end previously did not consider the conversion function in this
context because it is declared "explicit".  That is now fixed.  In Clang and
Microsoft C++ modes, this consideration is extended to some cases where the
conversion function does not produce a glvalue (i.e., does not have a reference
return type).


10/16/25 [EDGcpfe/28501]
Incorrect substitution of function parameter pack

Consider, with --c++11:

  template<typename> struct C;
  template<typename ... As>
  struct C<int(As ...)> {
    template<typename U> using A = int;
    template<typename U, typename = typename C<int(As ...)>::template A<U>>
    struct V;
    template<typename U, typename V = V<U>> void f();
  };
  C<int(int)> c;

With the changes for EDGcpfe/24353,EDGcpfe/24386,EDGcpfe/24492,EDGcpfe/24598,
EDGcpfe/26367 (in version 6.6), the front end instantiated the type
C<int(int...)> in addition to C<int(int)>.  When using the C-generating back
end, this would result in spurious redefinition errors in the generated code.


10/15/25 [EDGcpfe/28466]
Assertion failure in check_name_hiding_by_template_parameters

In some configurations, a translation unit containing an abbreviated
function template with more than nine deduced parameters resulted in an
assertion failure in check_name_hiding_by_template_parameters.  This is
now fixed.  For example, with --c++20:

  void kernel(auto a1, auto a2, auto a3, auto a4, auto a5,
              auto a6, auto a7, auto a8, auto a9, auto a10) {}


10/14/25 [EDGcpfe/28479]
GNU/Clang C compatibility: Use of static const variables in constant expression

Consider, in C mode:

  typedef struct { int a; } A;
  typedef struct { int c; } C;
  void g() {
    static const C x = { 42 };
    static A y = { x.c };
  }

Ordinarily, this is an error because in standard C the expression x.c is not
constant.  However, recent versions of GCC and Clang do accept this code and
the front end now emulates that behavior in its corresponding modes (when
gnu_version >= 80000 or clang_version >= 170000, respectively).

10/14/25 [EDGcpfe/28313]
Abort on type constraint with dependent non-type template parameter

Previously, the front end would abort due to a failed assertion in
update_template_param_symbol for a type constraint declared with a dependent
non-type template parameter.  For example, with --c++20:

  template<typename, int, auto>
  concept C = true;
  template<C<1, 2>>  // Previously triggered an assertion failure.  Now okay.
  struct A;


10/13/25 [EDGcpfe/24634,EDGcpfe/27214,EDGcpfe/27836,EDGcpfe/27902]
Spurious substitution failure for aggregate initialization from a pack

Previously, when a template argument list was explicitly specified for a pack
of a function template, initial substitution could fail if that pack was used
as the initializer of an aggregate.  For example, with --c++11:

  struct A {
    int i;
  };
  template<typename ... Ts>
  decltype(A{Ts{} ...}) f();
  auto v = f<int>();  // Previously a spurious error.  Now okay.


10/10/25 [EDGcpfe/28460]
is_decl_after_first_in_comma_list

When GENERATE_SOURCE_SEQUENCE_LISTS is configured to TRUE, the front end
records "source sequence entries" for statements and declared entities
appearing in the source code.  It also indicates whether an entity is declared
in a "secondary declarator" (i.e., a declarator that appears right after
another declarator separated by a comma) in two ways:
  1) For the "primary declaration" of an entity X, this is indicated by a flag
     is_decl_after_first_in_comma_list in the a_source_correspondence for X.
  2) For a "secondary declaration" of an entity X, this is indicated by a flag
     is_decl_after_first_in_comma_list in the secondary source sequence entry
     for that declaration of X.
In most configurations, source sequence entries are not recorded for template
instantiations, and thus the is_decl_after_first_in_comma_list flags were not
recorded for entities resulting from instantiations.  Now, however, the front
end does set the is_decl_after_first_in_comma_list in the source correspondence
of local variables and fields resulting from instantiations.  Those particular
entities cannot have secondary declarations, and thus the meaning of the flag
in the source correspondence is unambiguous.


10/10/25 [EDGcpfe/28492]
Fix segfault caused by memory corruption when reading a PCH

Previously, when using a PCH, the front end could allocate memory at addresses
that conflicted with memory used within the PCH while performing PCH fixup.
This could result in memory corruption that ultimately could lead to a segfault
or other failure at random locations within the front end.  This is now fixed.


10/9/25  [EDGcpfe/24604,EDGcpfe/25943,EDGcpfe/27793,EDGcpfe/27833,
          EDGcpfe/28149,EDGcpfe/28468]
C23: Explicit underlying enum types

In C23 mode, the front end now accepts an explicit underlying type for the
declaration of an enumeration type.  (This is similar to a C++11 feature.)
For example:

  enum Answer: unsigned char { No, Yes, Maybe };

This is also accepted in all Clang C modes with clang_version >= 80000 and in
all GNU C modes with gnu_version >= 130000 (i.e., not just in C23 modes).
This feature was added to C23 through the C standardization committee's paper
N3030.


10/9/25  [EDGcpfe/28472]
Equivalence of type template arguments using typedef names

The changes for EDGcpfe/26872 (in version 6.7) introduced a regression where
type template arguments using typedef names were not always considered
equivalent.  For example, with --c++11:

  template<typename> struct B;
  template<typename T> using A = B<T>;
  template<typename T> struct C {
    using AT = A<T>;
    void f(C<AT> *);
  };
  template<typename T>
  void C<T>::f(C<B<T>> *) {}  // Previously a spurious error.  Now okay.


10/8/25  [EDGcpfe/28478]
Variable template declaration with incomplete type

Consider:

  struct S {
    struct I;
    template<typename> static I x;
  };

The front end previously always issued an error reporting that x is declared
with an incomplete type.  It no longer does that in Microsoft, GNU, and Clang
C++ modes.  For Clang mode, the error is only omitted for member templates,
but for Microsoft and GNU modes it is omitted for all variable templates.


10/8/25  [EDGcpfe/28335,EDGcpfe/28483]
Clang/GCC: __add_lvalue_reference for cv-qualified reference types

Previously, the front dropped any cv-qualifier when applying the
__add_lvalue_reference type-transforming intrinsic to a reference type.  For
example, with --gnu_version 150100:

  using type = __add_lvalue_reference(const int &);
  using type = const int &;  // Previously a spurious error.  Now okay.


10/6/25  [EDGcpfe/8796,EDGcpfe/16454,EDGcpfe/24948,EDGcpfe/28482]
Clang/GCC: "static" in array parameter dimensions

C99 permits the "static" keyword in array parameter dimensions.  For example:

  void f(int a[static 4]) {}

Clang and GCC also accept this in their C89/C90 mode, and the front end now
emulates this (with a warning).


10/3/25  [EDGcpfe/28473]
Microsoft compatibility: Return value copy elision in constant evaluation

Consider, in C++20 mode:

    struct S {
      constexpr S(int *p): p(p) {}
      constexpr S(S const&): p(nullptr) {}
      constexpr ~S() {
        if (p != nullptr) *p = 1;
      }
      int *p;
    };
    constexpr S g(int n) {
      return true ? S(&n) : S(&n);  // (1)
    }
    static_assert(g(42).p == nullptr);  // Normally not constant.  Now okay in
                                        // Microsoft mode.

The return statement in (1) normally does not involve a copy constructor
invocation (it must be elided in C++17).  MSVC, however, does introduce a
copy constructor invocation during the constant evaluation and that causes
the embedded pointer of the result to be set to null, thus making the
static_assert condition true.  The front end now emulates that behavior.



10/1/25  [EDGcpfe/28438]
Clang compatibility: clang::no_specializations attribute

The clang::no_specializations attribute is now accepted by the front end
when clang_version >= 200000.  The "_Clang" attribute namespace is also now
a synonym for the "clang" attribute namespace.  The following example now
gives an error (with --clang_version 200000):
  
  template <class T> [[_Clang::no_specializations]] void f();
  template <> void f<int>();


10/1/25  [EDGcpfe/19349,EDGcpfe/20562,EDGcpfe/21710,EDGcpfe/22775,
          EDGcpfe/26431]
Abort on nested lambda in default member initializer

Previously, a lambda expression nested in a default argument of another lambda
expression, which is itself used in a default member initializer, resulted in
an incorrect variant access, likely leading to aborts and other incorrect
behavior.  For example, with --c++11:

  class A {
    int x = [](int i = [] { return 1; }()) { return 2; }();
  };


9/30/25  [EDGcpfe/28141,EDGcpfe/28464]
Clang compatibility: Conversion of _Nullable pointers

The front end now accepts the conversion of a _Nullable pointer to a plain
pointer (in Clang modes).  For example:

  int *_Nullable p = nullptr;
  int *& q = p;  // Previously an error.  Now okay.


9/30/25  [EDGcpfe/28406]
Incorrect recording of type constraint for abbreviated friend templates

Consider, in C++20 mode:

  template<typename, typename, int> concept C = true;
  template<typename T, int I> struct X {
    friend constexpr auto operator+(C<T, I> auto) {
      return true;
    }
  };
  static_assert(+X<int, 42>{});

This previously triggered a memory error because the constraint C<T, I> was
not correctly substituted in the friend definition introduced by X<int, 42>.
That is now fixed.  (In other similar examples, different error modes could
occur, such as spurious "duplicate definition" errors induced by the friend
template substitution.)


9/30/25  [EDGcpfe/28440]
Missing case in form_vector_type_attribute

The vk_neon_builtin case was missing from a switch statement in
form_vector_type_attribute, which could result in a failed assertion when
forming a diagnostic involving such a GNU vector type (e.g.,
__builtin_aarch64_simd_oi for ARM64 platforms).


9/29/25  [EDGcpfe/28298]
C++-generating back end: Incorrect parentheses around decltype operand

Consider, in C++20 mode:

  struct X {};
  template<X XV> auto f()->typename decltype(XV)::type;

Previously, the decltype construct in this example was incorrectly rendered as
"decltype((XV))" (i.e., with extraneous parentheses).  That is now fixed.  The
fix is to more accurately record the flag decltype_expr_not_parenthesized in
the a_type entry representing that decltype construct.  (Note that the flag is
only set if the parentheses can make a difference in the resulting type.)


9/29/25  [EDGcpfe/28470]
Excessive stack usage during IL walks for set_class_keep_definition_in_il

In some cases, the IL walk could result in very deep call stacks for
set_class_keep_definition_in_il.  To limit the recursion depth,
set_class_keep_definition_in_il now uses an internal list to defer processing
instead of recursing immediately.


9/25/25  [EDGcpfe/25786,EDGcpfe/28132,EDGcpfe/28462]
Microsoft C++ compatibility: Constant address of dllimport variables

In Microsoft C++ mode, the front end now accepts constant expressions that
produce the address of a dllimport variable in more contexts.  Conversely,
it now more consistently diagnoses attempts to use such a constant expression
to initialize a constinit variable.


9/25/25  [EDGcpfe/28410]
Constraints on unnamed classes

The front end now diagnoses non-C-like members of unnamed class types that
acquire a name "for linkage purposes".  That includes closure types associated
with such types.  The diagnostic is a warning, except in strict mode and in
Microsoft C++ modes with microsoft_version >= 1926.  For example:

  struct B {};
  typedef struct: B {          // Nonstandard: Base class.
    int f();                   // Nonstandard: Member function.
    int i = 0;                 // Nonstandard: Default member initializer.
    using C = decltype([]{});  // Nonstandard: Member typedef-name and
  } N;                         //              closure type.

Furthermore, static data member declarations in unnamed class types are now
diagnosed in more modes.  Previously, they were permitted in all GNU C++ modes;
now, this is only true when gnu_version < 40900.


9/24/25  [EDGcpfe/23041,EDGcpfe/23207]
Abort on parenthesized member function template declaration

In some cases where a member function template of a partially specialized class
template is declared with a parenthesized declarator, the front end could abort
with a failed assertion in find_template_class.  For example, with --c++11:

  template<typename T> using A = T;
  template<typename T> struct C;
  template<typename T>
  struct C<T *> {
    template<typename U>
    A<C> (f)(int);  // Previously triggered an assertion failure.  Now okay.
  };


9/22/25  [EDGcpfe/27835]
IL write-read error on expressions involving __builtin_source_location

Some uses of __builtin_source_location and similar functions could lead to an
abort while reading an IL file (an IL write-read error for an expression node).
This bug manifested in configurations with IL_SHOULD_BE_WRITTEN_TO_FILE set
to TRUE.  For example:

  template<typename> struct I;
  template<typename F> void g(F) { using R = I<decltype(F()().f())>; }
  struct L { L(char const*); };
  struct result {
    void f(L = __builtin_FUNCTION());  // Previously triggered an
  };                                   // IL write-read error.
  int main() {
    g([] -> result {});
  }

This is now fixed.


9/22/25  [EDGcpfe/25545,EDGcpfe/27021,EDGcpfe/27952,EDGcpfe/28442]
__is_layout_compatible

The following bugs in the front end's implementation of __is_layout_compatible
have been fixed:
  1) Previously, __is_layout_compatible(X, Y) was always false when X is
     defined with the keyword "struct" and Y is defined with "class" (or
     vice versa).
  2) Previously, __is_layout_compatible failed to instantiate specializations
     of class templates if needed.
  3) Previously, __is_layout_compatible failed to take the no_unique_address
     attribute into account.


9/22/25  [EDGcpfe/28431]
Missing diagnostic in reference conversion with brace-notation cast

The front end previously failed to diagnose the following cast:

  int const ic = 42;
  using RI = int&;
  RI ri = RI{ic};  // Previously silently accepted.  Now an error.

That is now fixed.


9/19/25  [EDGcpfe/28443]
Constexpr ctor-initializers for bases containing only zero-length arrays

Consider, in Clang or GCC C++17 (or earlier) mode:

  struct E { int e[0]; };
  struct D: E {
    constexpr D() {}  // Previously an error.  Now okay.
  };

Previously, this triggered an error about a constexpr constructor having to
initialize its direct base classes.  However, base classes with no data are
not so constrained, and the front end now recognizes the case above as such:
No error is issued for this case anymore.


9/19/25  [EDGcpfe/28433]
GCC-mode aborts or spurious errors with some specific identifiers

Consider:

  struct S { template<typename T> void operator()(T); } id;
  static_assert(noexcept(id(S())));

This previously aborted with an internal error in extract_node_from_operand.
Other very similar examples could erroneously trigger an error about a missing
right parenthesis.  A key element in this example is the fact that "id" is an
identifier that sometimes has a special meaning to the front end (a relatively
small set of such identifiers is listed in the initializer for the array
intrinsic_names in symbol_tbl.c).  This regression -- introduced by the changes
for EDGcpfe/27970 (not yet in a release, but distributed to some customers as
a patch) -- is now fixed.


9/19/25  [EDGcpfe/28023]
GCC/Clang C++ compatibility: Invalid class member calls in templates

Consider:

  struct S { void f(); };
  template<typename T> void f(S s, T t) {
    s.f(t);  // Invalid.  Now accepted in more situations.
  }

The call s.f(t) can be resolved while parsing the template and is invalid since
S::f takes no arguments.  Clang and GCC accept such cases, however.  The front
end also accepted that case when prototype instantiations are deferred until
their first use (often the default).  Now, the front accepts this in Clang and
GCC C++ modes even when prototype instantiations are not deferred (e.g., they
are normally not deferred when targeting the C++-generating back end).


9/18/25  [EDGcpfe/19941]
Diagnosing explicit default constructor uses for copy-initialization

Consider:

  struct E { explicit E() = default; };
  struct X { E e; };
  X x = {};  // Previously accepted.  Now an error.

The front end previously ignored the fact that a trivial default constructor
may not be eligible for certain initializations, and thus accepted the example
above even though it requires a non-explicit default constructor.  This is now
fixed: An error is issued.


9/18/25  [EDGcpfe/28448]
GNU/Clang compatibility: exception specification on __builtin_source_location

The signature for the __builtin_source_location builtin has been changed to
be noexcept.  For example, with --clang_version=150000 --c++20:

  #include <source_location>
  static_assert(noexcept(__builtin_source_location()));  // No longer asserts.


9/18/25  [EDGcpfe/28424]
Spurious subsumption of disjunctive clauses in constraints

Consider, in C++20 mode:

  template<typename T> constexpr bool true_1 = true;
  template<typename T> constexpr bool true_2 = true;
  template<typename T> concept C1 = true_1<T>;
  template<typename T> concept C2 = true_2<T>;
  template<typename T> concept C3 = ((C1<T> || C2<T>) && C1<T*>) || C1<T>;
  int g(C3 auto) { return 1; }
  int g(C1 auto) { return 3; }
  int r = g(0);  // Previously ambiguous.  Now okay.

This example previously reported an ambiguity because a bug in the subsumption
algorithm caused the front end to mistakenly conclude that C3 subsumes C1.
That is now fixed.


9/16/25  [EDGcpfe/25939]
C23: false and true

In C23 modes, "true" and "false" are now keywords.  This implements the
changes to the C standard made by the C standardization committee's paper
N2935.


9/15/25  [EDGcpfe/25760,EDGcpfe/28425]
Instantiation of friend function template noexcept specifier

Ordinarily, the noexcept specifier of a function template is instantiated when
the exception specification is needed.  However, for a friend function
template, the instantiation was not always delayed when the enclosing class
template was instantiated from within an explicit specialization declaration.
For example:

  template<typename T> struct D {
    template<typename U>
    friend void f(D, U) noexcept(T::v);  // Previously an error.  Now okay.
  };
  template<typename> struct C;
  template<> struct C<int> {
    D<int> d;
  };


9/11/25  [EDGcpfe/28434]
C++-generating back end: member access expression in decltype(auto) initializer

In a declaration in which the type is "decltype(auto)" and the initializer
is a member access expression (e.g., "x.a" or "p->a"), the C++-generating
back end previously incorrectly enclosed the initializer in parentheses,
resulting in an incorrect type.  This is now fixed.  For example:

  struct A { int i; };
  A a;
  decltype(auto) i5 = a.i;  // Previously generated as (a.i)


9/10/25  [EDGcpfe/22258,EDGcpfe/28429]
Trailing empty statements in GNU statement expressions

In GNU C mode and in Clang C and C++ modes, trailing empty statements are now
ignored when determining the result of a GNU statement expression.  For
example:

  int main() {
    return ({ 42; ; });  // Now valid in GNU C modes and in Clang C and C++
  }                      // modes.  Still an error in GNU C++ mode.

Previously, this was an error because the final statement of the statement
expression did not produce a result.  Now that final empty statement is
ignored in various modes, which makes the case valid in those modes.


9/9/25   [EDGcpfe/28249,EDGcpfe/28426]
C++26: Attribute [[indeterminate]]

In C++26 mode, the front end now accepts the attribute [[indeterminate]] on
declarations of block scope variables and function parameters.  Additionally,
a_variable entries that have no explicit initializer and for which default
initialization does not actually initialize the variable, now record this fact
with a new "uninitialized" flag.


9/9/25   [EDGcpfe/27845]
Spurious instantiation of variable template initializer during substitution

Previously, substitution of a variable template always triggered the
instantiation of its initializer, even when the variable was used only in an
unevaluated context.  For example, with --c++20:

  template<typename T>
  int c = sizeof(T);  // Previously a spurious error.  Now okay.
  template<typename T>
  constexpr bool v = requires { c<T>; };
  static_assert(v<void>);


9/8/25   [EDGcpfe/26226,EDGcpfe/28416]
Incorrect handling of some lifetimes for constexpr variable initializers

Consider:

  #include <initializer_list>
  struct S {
    constexpr S(std::initializer_list<int> lst): lst(lst) {}
    std::initializer_list<int> lst;
  };
  int main() {
    constexpr static std::initializer_list<int> li = {4};
    constexpr S s{li};
  }

Previously, this failed because the front end failed to recognize the lifetime
of the array underlying the li variable as having static storage.  That is now
fixed.


9/8/25   [EDGcpfe/24065,EDGcpfe/24735,EDGcpfe/25677]
Microsoft compatibility: pack expansions and Microsoft nonreal base classes

In Microsoft mode, the front end emulates a Microsoft feature that finds
certain names in dependent base classes.  That emulation could cause incorrect
behavior when a pack is provided for a non-pack parameter in the template
argument list of a dependent base class specifier.  For example, with --c++11
--microsoft:

  template<typename T, typename ...>
  struct B {
    template<typename U = T>  // Previously a spurious error.  Now okay.
    void foo();
  };
  template<typename ... Ts>
  struct D : B<Ts ...>
  { };


9/5/25   [EDGcpfe/28420]
Complete-type requirement for __underlying_type

The type trait helper __underlying_type previously failed to enforce the
requirement that the given enumeration type is complete.  That is now fixed.
For example:

  enum E {
    e = __underlying_type(E)()  // Previously accepted.  Now an error.
  };


9/5/25   [EDGcpfe/26253,EDGcpfe/27917]
Deduced constant template arguments of class type

Consider, in C++20 mode:

  struct S {
    int f();  // Not const-qualified
  };
  template<auto V> int g() requires requires { V.f(); } = delete;
  template<auto V> int g();
  int r = g<S{}>();

The deduction of V produces a value of class type, and that type ought to be
const-qualified according to the standard (because the underlying model is
that of a constexpr variable).  However, in this case, the front end failed to
imbue const-ness on the V during substitution, which caused the requires-
expression constraint to pass.  As a result, the deleted candidate was
erroneously preferred in the call g<S{}>().  That is now fixed (the constrained
candidate now fails the constraint, and thus the second candidate is selected).
This change also fixes some uses of constexpr variables of class types (which
sometimes lost their const-qualification when evaluated in constant
expressions).


9/3/25   [EDGcpfe/28377]
C++-generating back end: Rendering of casts in contexts with copy-elision

Consider, in C++17 mode:

  struct S { S(S const&); };
  struct C { operator S() const; };
  C get();
  int main() {
    S const s{static_cast<S>(get())};
  }

Previously, the explicit conversion in the initialization of s was lost in the
output rendered by the C++-generating back end because the copy constructor
invocation for the initialization of s is elided and the "explicit cast" flag
was recorded on that invocation.  In some cases, the resulting code was no
longer valid C++.  That is now fixed.


9/3/25   [EDGcpfe/28170]
Split builtin_kinds.h from builtin_defs.h

To improve compilation times, the builtin function kinds have been split from
builtin_defs.h into a separate builtin_kinds.h header.


9/2/25   [EDGcpfe/28360]
Message internationalization

A number of previously-hard-coded English strings (used mainly for debugging
purposes) have now been moved to error_msgs.txt so that they can more easily
be translated into other languages.


8/29/25  [EDGcpfe/28297]
Spurious error on some fold-expressions

Consider, in C++17 mode:

  template<int ... Ns> struct S {
    static auto f() { return (1 + Ns + ...); }
  };
  int r = S<1, 2, 3, 4>::f();

This previously triggered an error in the instantiation of the fold expression.
That is now fixed.


8/29/25  [EDGcpfe/28200]
Spurious diagnostic with deleted move constructor

Consider, in C++17 mode:

  struct V {
    constexpr V() noexcept = default;
    constexpr V(const V&) noexcept = default;
    V(V&&) = delete;
    constexpr V(char const (&)[42]) noexcept {}
  };
  constexpr V makeV() { return V{}; }
  constexpr V k{makeV()};  // Previously an error.  Now okay.

The front end previously issued an error claiming invocation of the deleted
move constructor of V, even though that invocation is completely avoided in
C++17 (through so-called "mandatory copy elision").  This is now fixed.


8/28/25  [EDGcpfe/28422]
GCC 12 compatibility: Lookup of identifiers in noexcept specifiers

Consider:

  struct S {
    template<typename T> int f(T const &p) noexcept(noexcept(s = p));
    int s;
  };

Previously, the identifier s was not found in GNU C++ modes, to match observed
GCC behavior.  GCC appears to have fixed this lookup bug in GCC 12, and the
front end now matches that when gnu_version >= 120000.


8/28/25  [EDGcpfe/28244]
Microsoft mode abort on instantiation of variable template containing a
requires-expression

Consider, in Microsoft C++20 mode:

  template<auto N> constexpr bool vt = requires { N>0; };
  static_assert(vt<42>);  // Previously aborted.  Now okay.

Previously, this aborted with an internal error in get_expr_rescan_info
(expr.c).  That is now fixed.


8/27/25  [EDGcpfe/28411]
Abort on definition of enum type first declared in another namespace

Consider:

  namespace N1 { enum class E; }
  namespace N2 {
    using N1::E;
    enum class E { e };
  }

Previously, this aborted in move_to_end_of_types_list (il.c) with a null
pointer indirection.  That is now fixed.  In GCC and Microsoft modes, the
example above is now accepted.  In other modes, an error is now issued
(defining E in N2 is not valid).


8/27/25  [EDGcpfe/28264,EDGcpfe/28340]
Abort in find_subobject_for_interpreter_address during constant memcpy/memmove

In various situations involving the invocation of memcpy/memmove during
constant evaluation (this is possible in GNU and Clang modes; see the entry for
EDGcpfe/22879), the front end could abort with an internal error in
find_subobject_for_interpreter_address (interpret.c).  This is now fixed.


8/26/25  [EDGcpfe/27549]
Microsoft compatibility: va_copy

In configurations with DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE set to
TRUE, the front end now includes va_copy among the built-in operators enabled
in Microsoft modes when "#include <stdarg.h>" is encountered (when
microsoft_version >= 1900).


8/26/25  [EDGcpfe/28412]
Assertion failure in make_static_assert_string_for_output

In cases where a static_assert is not terminated by a semicolon but is followed
by a preprocessing directive, an assertion failure (in
make_static_assert_string_for_output) could occur and is now fixed.
For example, with --c++17:

  static_assert(false, "a string")    // Missing semicolon
  #if defined(SOME_DEF)
  #endif


8/25/25  [EDGcpfe/28374]
Clang compatibility: __builtin_common_type

In Clang C++ modes with clang_version >= 200000, the front end now implements
support for an intrinsic __builtin_common_type template.  This template is
used by libc++ to implement std::common_type.


8/25/25  [EDGcpfe/28414]
Consistency checking for floating point configurations

The front end previously accepted invalid configurations in which the size
specified for a floating point type is too small for the number of bits
required for the specified mantissa and exponent values.  In configurations
with CHECKING set to TRUE, the front end now tests these values for all
floating point types during its start-up initialization and issues a
catastrophic error if an inconsistency is found.


8/24/25  [EDGcpfe/28389]
C++-generating back end: attributes dropped on class template declarations

When using the C++-generating back end, attributes had been silently dropped
on class template declarations that are not definitions.  For example
(with --c++14):

  template <class> struct [[deprecated]] A;


8/21/25  [EDGcpfe/28088,EDGcpfe/28173]
Abort in transfer_arg_operand_for_template_arg during substitution

In somewhat complex cases the front end failed an assertion check in
transfer_arg_operand_for_template_arg (in expr.c) because some information
needed to perform expression substitution had not been recorded as needed.
That is now fixed.


8/20/25  [EDGcpfe/28407]
GNU/clang compatibility: bit pattern for signaling NaNs

The IEEE floating point standard does not fully specify the bit pattern for
a signaling NaN.  The values previously produced by the front end for
signaling NaNs by __builtin_nan* functions invoked with an empty string
operand were valid but were different from those produced by the GNU and
clang implementations.  The front end has now been revised to produce the
same bit patterns as GNU and clang for these builtin functions.  For
example, with --c++20 --gnu_version=110400:

  #include <bit>
  static_assert(std::bit_cast<unsigned>(__builtin_nansf("")) == 0x7fa00000);


8/20/25  [EDGcpfe/28398]
Abort during diagnostic involving undetermined type

Consider, in C++20 mode:

  template<typename> concept C = false;
  template<C T> using A = void;
  struct S {};
  template<typename T, typename = A<T>, int = 42> void g() {}
  int main() {
    g<S>();  // Previously triggered an abort.  Now an ordinary error message.
  }

Previously, this triggered an abort (a null pointer indirection) while emitting
a diagnostic (g<S> cannot be called because of a constraint failure).  The
abort was the consequence of the template argument list for g<S> not being
fully determined.  That is now fixed: Template arguments that are not yet
determined are now rendered in a special way (specified in the error_msg.txt
file).


8/19/25  [EDGcpfe/28409]
Segfault when using PCH files with mmap on old versions of Linux

Previously, on older versions of Linux in configurations with
USE_MMAP_FOR_MEMORY_REGIONS set to TRUE, a segfault could occur when using PCH
files (at any point where the memory loaded from the PCH is mutated).  This is
now fixed.


8/19/25  [EDGcpfe/28408]
Add TARG_SIZE_T_MAX to the output of --dump_configuration

The TARG_SIZE_T_MAX configuration macro's value is now dumped when
--dump_configuration is specified.


8/15/25  [EDGcpfe/28399]
C++-generating back end: address constant expressions in template arguments

The C++-generating back end sometimes put out address constant expressions
appearing as non-type template arguments in an incorrect form, resulting in
code that could not be compiled successfully.  This is now fixed.  For
example, with --c++20:

  template <int* p> struct X { };
  struct S {
    int m;
    int n;
  };
  extern S s;
  constexpr S *ps = &s;
  X<&ps[0].m> xsm;
  X<&ps[0].n> xsn;
  template <class T> void f();
  void f() {
    f<X<&ps[0].m>>();  // Previously generated as "X<&s>"
    f<X<&ps[0].n>>();  // Previously generated as "X<(int*)(((char*)&s)+4)>"
  }

The original source forms of those template arguments are now preserved in
the generated code.


8/14/25  [EDGcpfe/28392]
C++-generating back end: trailing requires clause for lambda expressions

The C++-generating back end previously failed to put out a trailing requires
clause appearing in a generic lambda expression.  This is now fixed.  For
example, with --c++20:

  template<typename> concept C = true;
  auto l = []<typename T>(T) requires C<T> { };  // Previously omitted the
                                                 // requires clause


8/12/25  [EDGcpfe/28242]
Poor performance of add_to_dependent_type_fixup_list

The function add_to_dependent_type_fixup_list could lead to unnecessarily poor
performance in somewhat unusual cases (involving many function declarations
that refer to dependent types).  That is now fixed.


8/10/25  [EDGcpfe/28386]
Additional memory management metrics

Additional memory management metrics have been added to the memory usage report
(-d-space_used command line option).  These metrics provide insight into the
application's allocation behavior and interactions with malloc and free.
Additionally, a bug has been fixed that caused an undercount of the total
memory used.


8/8/25   [EDGcpfe/28384]
Fixed lexical state corruption

Previously, the lexical state could become corrupted while processing some
grammatically-incorrect lambdas and module entities.  In rare cases, this could
result in assertion failures in scan_lambda_declarator (and likely other
places).


8/8/25   [EDGcpfe/28092,EDGcpfe/28328]
Clang compatibility: __is_bitwise_cloneable

In Clang C++ mode with clang_version >= 190000, the front end now supports the
type trait helper __is_bitwise_cloneable.


8/8/25   [EDGcpfe/21022,EDGcpfe/21246,EDGcpfe/24784,EDGcpfe/25500]
Handling of captures in a lambda header

The C++ standardization paper P2579R0 (and its predecessor, P2036R3) changes
the way captures are handled in a lambda header.  In particular:
  - referring to a capture after the parameter list of a lambda produces
    a "const" lvalue if the lambda is not "mutable", and
  - init-captures are visible throughout the lambda header.
These changes were voted into the standard as a defect report (DR), which means
they apply to all language modes.  However, it appears MSVC, GCC, and Clang do
not yet implement this feature and the front end therefore approximates their
behavior in its corresponding modes.  The front end now also diagnoses lambda
parameters and (C++20) explicit template parameters whose names conflict with
explicitly-specified captures.


8/8/25   [EDGcpfe/28383]
Segfault involving freed overload resolution descriptors

Previously, in rare cases, overload resolution stack entries could be
reallocated while still in use resulting in a possible segfault.  This is now
fixed.


8/8/25   [EDGcpfe/20813,EDGcpfe/27780,EDGcpfe/28376]
GNU compatibility: Pointer arguments to __atomic_... builtins

GCC allows the "value" parameter of __atomic_... builtins to also have pointer
type.  For example, with --g++:

  void f(char *p, char *v) {
    __atomic_store_n(p, v, 0);  // Now accepted in GNU mode.
  }


8/7/25   [EDGcpfe/28372]
Clang compatibility: __builtin_invoke

The new builtin __builtin_invoke is now supported for Clang 21 and later.


8/7/25   [EDGcpfe/28380]
Segfault in db_token_range

Previously, calling db_token_range could result in a segfault if the temporary
text buffer had not been initialized earlier in the program.  This is now
fixed.


8/6/25   [EDGcpfe/28375]
Alignment of variable templates

Any alignment attributes attached to a variable template had not been
applied to variable template instances.  That had caused the static_assert
to fail in the following case (with --c++17 -tused):

  template <class T> T v [[align(32)]];
  static_assert(alignof(v<char>) == 32);


8/6/25   [EDGcpfe/24784,EDGcpfe/25500]
Adjustments to handling of identifiers in lambda headers

The front end now diagnoses (with a discretionary error) lambda parameters and
(C++20) explicit lambda template parameters whose names conflict with that of
an explicit capture of that lambda.  For example (in C++17 mode):

  auto lm = [x = 1](int x) { return x; };  // Now an error.

Furthermore, the front end now also implements the changes in the C++
standardization committee's paper P2579R0 (adopted as a DR), which causes
some additional uses of captured variables to become "const".  For example:

  void g() {
    int x;
    int const y = 0;
    [=]() -> decltype((x)) { // Previously returned "int&".  Now "int const&".
      return y;              // Previously an error.  Now okay.
    };
  }


8/6/25   [EDGcpfe/26143,EDGcpfe/28004]
Clang compatibility: Enabling standard attribute syntax in C mode

Clang accepts standard attribute syntax (a C23 feature) in C mode beginning
with version 17.1.0 and the front end now emulates that.

Additionally, a bug that had prevented attribute namespaces from being
parsed in GNU C modes was fixed.


8/4/25   [EDGcpfe/27269,EDGcpfe/28215]
Microsoft/GNU compatibility: Availability of various clang feature-test macros

Clang has introduced a number of non-standard feature-test macros (see the
Changes entry for EDGcpfe/14767 et al.).  The use of these feature-test macros
in headers shared across platforms led to the change described in the Changes
entry (namely the introduction of the
DEFINE_FEATURE_TEST_MACRO_OPERATORS_IN_ALL_MODES configuration macro), but
enabling those feature-test macros in improper modes (especially Microsoft
emulation mode) had defeated the logic in the header files, resulting in
spurious errors.

That macro has now been removed and the front end now better emulates the
versions in which these non-standard feature-test macros now appear.
Specifically, here are the affected feature-test macros and the GNU version
in which they appear:

  __has_include_next: gnu_version >= 50000
  __has_attribute: gnu_version >= 50000
  __has_builtin: gnu_version >= 100000
  __has_feature: gnu_version >= 140000
  __has_extension: gnu_version >= 140000

All are available in C and C++ modes.  None are currently available in
Microsoft emulation modes.


7/31/25  [EDGcpfe/28368]
Abort on lowering of __mfp8 initialization

Consider, in a configuration supporting ARM vector extensions:

  typedef __attribute__((neon_vector_type(16))) __mfp8 WV;
  __mfp8 wght;
  WV wv = {wght};

This previously triggered an internal error when attempting to lower the IL
for this example (lowering caused the invocation of type_change_constant_full,
where the internal error occurred).  That is now fixed.


7/30/25  [EDGcpfe/28362]
Abort in matches_template_decl_requires_clause with nested class template

Consider:

  template<typename> struct S {
    template<typename> struct N;
  };
  template<typename T> template<typename U> struct S<T>::N<U*> {};
  template<> template<typename W> struct S<int>::N<W*> {};

This previously triggered an internal error in templates.c (function
matches_template_decl_requires_clause).  That is now fixed.


7/30/25  [EDGcpfe/26641,EDGcpfe/27432]
Variable template partial specializations using requires-clauses

Consider, in C++20 mode:

  template<typename> int v;
  template<typename T> int v<T*>;                // (1)
  template<typename T> requires true int v<T*>;  // Previously an error.

Previously, the front end mistakenly treated the last partial specialization
declaration as a redeclaration of the partial specialization (1).  That
resulted in a spurious error about the requires-clause being incompatible.
Now it is correctly treated as a distinct partial specialization since the
requires-clause is distinct.


7/29/25  [EDGcpfe/27947]
C++-generating back end: backing expressions for non-type template arguments

The C++-generating back end relies on the existence of backing expressions
for non-type template arguments in order to generate correct code that
accurately reflects the semantics of the original source code.  The
KEEP_TEMPLATE_ARG_EXPR_THAT_CAUSES_INSTANTIATION configuration option
controlled whether these backing expressions were preserved; however, that
option was not required to be TRUE in C++-generating back end
configurations, resulting in incorrect code generation in some
configurations.  That is no longer permitted; instead, a build error will
occur if such a configuration is attempted.

In addition, the name of the configuration option reflected an earlier,
more limited usage of these backing expressions, so the option has been
renamed as BACKING_EXPR_FOR_NONTYPE_TEMPL_ARG.  Previous configurations
that set the option using the old name will continue to work, as the value
of the new option will be taken from the old setting if it is defined.


7/28/25  [EDGcpfe/28361]
C++-generating back end: new-expression with variadic braced initializer

Consider (in C++20 mode, or in C++11 mode after the changes for
EDGcpfe/25685,EDGcpfe/27368):

  template<int ... Ns> int *v = new int[]{Ns...};

The IL representing the new-expression in the generic definition of v
previously erroneously included a length of one for the allocated array.  As
a result, the C++-generating back end rendered the example as:

  template< int ...Ns> int *v = new int [1]{Ns...};

which is not equivalent (and will fail to instantiate if more than one
template argument is supplied for v).  This is now fixed: The array type
in the generic representation of the new-expression no longer includes a
specified bound.


7/28/25  [EDGcpfe/25685,EDGcpfe/27368]
Deducing array size in new-expressions

The changes for EDGcpfe/20914 implemented support for deducing an array size
from a new expression.  For example:

  char *str = new char[]{ "message" };

Those changes limited this feature to C++20 mode because the committee paper
that enabled it (P1009R2) was voted on during the C++20 standardization cycle.
However, the paper was voted as the resolution to a defect report and thus is
intended to apply to all language modes that allow initializers for arrays in
such contexts.  The front end therefore now accepts cases such as the example
above in all C++11 (and later) modes.


7/28/25  [EDGcpfe/24181]
Overload resolution failure for parameters declared using typedef names

Previously, the front end did not always treat a typedef name as
equivalent to the aliased type during partial ordering, which could lead to
spurious overload resolution failures.  For example, with --c++11:

  using INT = int;
  template<typename T> int f(T, INT &&);
  template<typename T> int f(T *, int &&);
  int i = f("", 0);  // Previously a spurious error.  Now okay.


7/26/25  [EDGcpfe/28359]
C++-generating back end: non-type template arguments of class type

The C++-generating back end sometimes generated incorrect code when a
non-type template argument is of class type and constructed via a constexpr
constructor.  This is now fixed.  For example, with --c++20:

  struct C {
    constexpr C(char) { }
  };
  template<C> struct X { };
  X<C('a')> x;   // previously generated as X<C{}>


7/25/25  [EDGcpfe/28357]
Traversal of self-referencing aggregate constant entries

Some complex constant evaluations can result in an a_constant/ck_aggregate
entry X that directly or indirectly contains a ck_address/abk_temporary that
points back to X.  Traversing X using the traverse_constant function or the
machinery in il_display.c then resulted in runaway recursion.  That is now
fixed by having those routines detect such circular references and terminate
the recursion.


7/25/25  [EDGcpfe/27137]
static_assert failure details

When a static_assert declaration fails and the condition is (at the top level)
a comparison of integer values, the front end now adds a note indicating the
values involved in that comparison.  For example:

  constexpr int f() { return 42; }
  static_assert(f() == 8, "");

For the example above, the front end will add to the diagnostic about the
static assertion having failed a note explaining that the comparison ended up
as 42 == 8.

This feature required some pervasive changes to the way constant evaluation is
performed.  In particular, the front end now avoids most early folding of
constant expressions if it knows that the enclosing full expression is required
to be constant eventually.  This can be considered an IL CHANGE: No a_constant
entries are created any longer for the intermediate expressions.  These changes
also revealed some pre-existing shortcomings in the constant evaluation
interpreter, and those have been fixed (the handling of vector operations was
improved in particular).


7/25/25  [EDGcpfe/27671,EDGcpfe/27945]
Layout of classes with a base extending beyond direct nonstatic data members

Consider, in an IA-64 ABI configuration and int having size and alignment 4:

  struct E {};
  struct B {
    int i;
    [[no_unique_address]] E e1;
    [[no_unique_address]] E e2;
    B() {}
  };
  struct D: B {};

sizeof(B) == 8 (4 bytes for B::i and padding for the subsequent (empty) data
members).  sizeof(D) should therefore also equal 8, but the front end
previously erroneously recorded a size of 4 for D.  That is now fixed.


7/24/25  [EDGcpfe/28358]
Clang compatibility: Clang 21 builtins

The front end has been updated with the latest builtin signatures from Clang
version 21 (based on the recently-released RC1).


7/24/25  [EDGcpfe/27654,EDGcpfe/28350]
Matching of partial specialization with a placeholder for a deduced class type

Previously, the front end failed to match a partial specialization declared
with a placeholder for a deduced class type.  For example, with --c++20:

  template<int>
  struct S {
    char c;
  };
  template<typename T, S s> struct N;
  template<typename T, S s> struct N<T *, s> { };
  N<int *, S<0>{'a'}> n;  // Previously a spurious error.  Now okay.


7/23/25  [EDGcpfe/28169]
Spurious error on qualified name within a default argument

Consider:

  struct S {
    int f(int P = P::C);
    struct P { static int const C = 1; };
  };

The default argument "P::C" must be cached before it is parsed.  The changes
for EDGcpfe/27249,EDGcpfe/27478 in version 6.7 caused this caching process to
verify the validity of qualified names, which in turn caused a spurious error
in this example because P in P::C is not a valid name qualifier at the point
where the default argument is cached.  This is now fixed.


7/23/25  [EDGcpfe/28195]
Clang compatibility: Exception specifications on C standard library functions

In Clang C++ mode, the following conflicting declarations

  extern "C" {
    int xyz(int) throw();
    int xyz(int);
  }

are now accepted if __builtin_xyz is the name of a built-in function.
(Ordinarily, such an exception specification mismatch elicits an error.)


7/23/25  [EDGcpfe/28112,EDGcpfe/28246]
Over-eager instantiation of primary variable template type

Consider, with --c++14:

  template<typename T>
  struct C {
    T t;  // Previously a spurious error.  Now okay
  };
  template<typename T> C<T> var;
  template<> C<void *> var<void>;

Previously, the front end attempted to instantiate the type of the primary
variable template, specialized with T=void, when parsing the explicit template
specialization declaration.  That is now fixed.


7/22/25  [EDGcpfe/27876]
GCC compatibility: spurious error using "module" as an identifier

Consider the following, with --c++20 --gnu_version=150100:

  int module;   // Previously an error, now okay

Previously, the front end would process the identifier "module" as a keyword
when emulating g++ in C++20 mode or later.  g++ does not enable the module
keyword in any release version without the use of -fmodules.  The front end now
requires the --modules command-line option to be passed in g++ emulation mode
to enable module keywords.


7/22/25  [EDGcpfe/22555,EDGcpfe/28231]
Abort in Clang and Microsoft modes on some CTAD cases

Consider, in C++17 mode:

  template<typename = int> struct S {};
  template<typename> void g() {
    S s;
  }

During CTAD (class template argument deduction) in Clang or Microsoft mode,
this triggered a null pointer indirection in the front end.  That is now fixed.


7/22/25  [EDGcpfe/28354]
Array designators for arrays of types with nontrivial construction/destruction

Array designators were previously not permitted in C++ mode if the designated
elements may involve nontrivial construction or destruction.  GCC also
disallows such cases, except it permits designators that have no effect (i.e.,
designators that do not change the index of the next initializer).  The front
end now emulates that in GNU C++ modes.  For example:

  struct X { ~X(); };
  X arr[3] = { X{}, [1] = X{} };  // Now okay.  The array designator has no
                                  // effect.


7/22/25  [EDGcpfe/28353]
Abort on overloaded default constructor

Consider, in C++20 mode:

  template <typename... Ts> struct S {
    constexpr S() = default;
    constexpr explicit S(Ts...) noexcept requires (sizeof...(Ts) != 0) {}
  };
  constexpr S s1;
  constexpr S s2{};

Depending on the configuration, either or both of the variable declarations
could trigger assertion failures.  That is now fixed.


7/21/25  [EDGcpfe/27056,EDGcpfe/28185,EDGcpfe/28343]
Generated default constructor with default-initialized variant member

Consider, in C++11 (or later) mode:

  struct X { X(int); };
  struct S {
    S() = default;
    union {
      int i = {};
      X x;
    };
  };
  S s;  // Previously an error.  Now okay.

According to the standard, the default constructor of S should be deleted
because the variant member S::x cannot be default constructed.  However, Core
issue 1623 (which is still open) has long argued that this shouldn't matter
since there is a default-initialized variant member that determines which
member should be initialized by default.  Only Clang appears to still enforce
the standard rule.  The front end now matches the other implementations (GCC,
MSVC) in accepting the example above when not in Clang mode.


7/21/25  [EDGcpfe/28235]
Type-dependence of decltype-specifier used as nested name specifier

Previously, the front end also considered a decltype-specifier used as a nested
name specifier to be dependent if its operand was value-dependent.  For
example, with --c++11:

  struct B {
    using type = int;
    int i;
  };
  template<int I>
  void f() {
    B b{ I };
    decltype(b)::type t;  // Previously a spurious error.  Now okay.
  }
  template void f<0>();


7/21/25  [EDGcpfe/28338]
Abort on requires expression in default template argument

With the changes for EDGcpfe/27599 (in version 6.7), the front end could enter
an unbounded recursion for a requires expression appearing in a default
template argument.  For example, with --c++20:

  template<typename T, bool = requires { T::v; }>
  struct A : A<T> { };  // Previously aborted, now okay.


7/18/25  [EDGcpfe/28139]
Spurious error on template-dependent reinterpret_cast

Consider:

  struct S {};
  extern S *p;
  template<typename T> T g() {
    return reinterpret_cast<T>(*p);
  }

This previously triggered an error during the prototype instantiation of g<T>()
even though the template is viable (i.e., permits valid instantiations).  That
is now fixed.


7/18/25  [EDGcpfe/28140]
Constant address of a weak function aliasing a known non-weak function

In modes that accept weak functions (through attributes), the front end
previously treated the address of such functions as non-constant (because
in general that address may be null or the address of an actual function).
Now, if the weak function is an alias (specified with an attribute like
"alias" or "weakref") to a known non-weak function, its address is treated
as a constant.


7/18/25  [EDGcpfe/28312,EDGcpfe/28318]
C-generating back end: generated code compatibility with C23 target

The C23 Standard changed the C language in certain ways that are
incompatible with the code produced by the C-generating back end.  To
accommodate these changes, a new configuration macro,
C_GEN_BE_GENERATES_C23, has been introduced.  When set to TRUE, this macro
changes the output of the C-generating back end in the following ways:

  - A function whose parameter list contains only an ellipsis is declared
    with an ellipsis instead of as a function with no prototype.

  - A C function that is declared implicitly by a call and that is not
    defined in the current translation unit is declared with a parameter
    list containing only an ellipsis instead of as a function with no
    prototype.

  - The code assumes a built-in "bool" type instead of defining a typedef
    for "bool".

Because gcc version 15.1.0 defaults to C23 mode, C_GEN_BE_GENERATES_C23
defaults to TRUE when GCC_IS_GENERATED_CODE_TARGET is TRUE and
GNU_TARGET_VERSION_NUMBER is at least 150000; otherwise, it defaults to
FALSE.


7/18/25  [EDGcpfe/28261]
C++-generating back end: incorrect qualification of member function call

In a call to a member function with a noexcept specifier, the C++-generating
back end previously sometimes put out a name qualifier used in the noexcept
specifier for the member function name.  For example, with --c++11:

  struct A {
    static constexpr bool v = false;
  };
  template<typename T> struct B {
    void g(int) noexcept(A::v);
  };
  struct D : B<bool> {
    void f() {
      g(1);  // Previously generated as "this->A::g(1)"
    }
  };


7/17/25  [EDGcpfe/28121,EDGcpfe/28178]
Relaxed checking of empty pack-expanded argument lists in templates

Consider:

  template<typename T, typename... As> int g() {
    [](auto...ps) { new T(As(ps)...); };
    return 42;
  }
  struct S { S(int); };
  int r = g<S>();

This previously (justifiably) issued an error: The initialization T(As(ps)...)
for the call g<S>() expands to S(), which has no match.  However, it appears
existing practice (by MSVC, GCC, and Clang) is not to diagnose that error
(presumably because it appears within a template; in this case, a generic
lambda).  The front end now emulates that.


7/17/25  [EDGcpfe/27632,EDGcpfe/28224]
Spurious syntax error on noexcept specifier for generic lambda in template

Consider:

  template<typename T> struct S {
    static constexpr auto lambda = [](auto) noexcept(true) {};
  };
  S<int> s;

Previously, this elicited spurious syntax errors during the instantiation of
S<int> (the first of which complained about a missing expression).  That is
now fixed.


7/17/25  [EDGcpfe/28309]
Microsoft compatibility: Interaction between #pragma pack and alignas

Consider, in Microsoft mode with sizeof(double) == 8 and sizeof(bool) == 1:

  struct S {
    alignas(16) double x;
    double y;
  };
  #pragma pack(8)
  struct P {
    S x;
    bool y;
  };
  static_assert(sizeof(P) == 32);  // Previously failed.  Now okay.
  static_assert(alignof(P) == 16); // Ditto.

MSVC ignores packing directives for fields of types with explicit alignment
requirements.  The front end already emulated that when the explicit alignment
is specified with __declspec(align(...)) (see the Changes entry of 8/1/05),
but failed to do so when the alignment is specified using the standard
"alignas" specifier.  That is now fixed.


7/16/25  [EDGcpfe/28314]
Runaway recursion in interpreter

Consider:

  struct S {
    char *p;
    char c;
    constexpr S(): p(&c) { c = 0; }
    S(const S &o): p(&c) { c = 0; }
  };
  S const &ref = S();
  S const val = ref;

This previously aborted due to runaway recursion in extract_value_from_constant
(in interpret.c).  That is now fixed.


7/15/25  [EDGcpfe/28323]
Excessive memory use during opportunistic constant evaluation

The changes for EDGcpfe/27588 in version 6.7 of the front end significantly
increased the amount of storage that could be allocated for constant
evaluation.  In some cases, this resulted in excessive memory use by the
interpreter while attempting to constant-evaluate expressions that aren't
actually required to produce constant results.  This has now been addressed,
in part by introducing separate allocation limits when
std::is_constant_evaluated() is true and when it is false.


7/15/25  [EDGcpfe/28324]
Possible reference to freed memory with MAKE_FRONT_END_CALLABLE

When using MAKE_FRONT_END_CALLABLE, a very rare occurrence of memory reuse from
a previous compilation could occur in
determine_get_call_for_tuple_like_binding.  This could result in an abort or
some kind of internal error.  Now fixed.


7/12/25  [EDGcpfe/28310]
Signedness of Z-suffix literals

Consider (with a 64-bit size_t type):

  auto r = 0xFFFF'FFFF'FFFF'FFFFz;

Previously, the constant was erroneously given a signed type, but for non-
decimal literals an unsigned type should used if the signed type corresponding
to size_t cannot represent the literal (unsigned) value.  In GNU C++ mode, a
signed type is still produced (to emulate a GCC bug in this area).


7/10/25  [EDGcpfe/28308]
Microsoft compatibility: Packing and explicitly-aligned types

In Microsoft modes, the front end ignores packing directives for subobjects of
types with explicit alignment requirements (see the entry for EDGcpfe/23937).
However, this behavior did not extend to indirect base classes containing
subobjects with explicit alignment requirements.  For example, with --ms_c++17:

  #pragma pack(1)
  struct alignas(16) A {};
  struct B { A a; };  // 16-byte aligned despite #pragma in effect.
  struct D : B {};    // Ditto.
  struct E : D {};    // Ditto.
  static_assert(alignof(E) == 16, "");  // Now accepted in Microsoft mode.


7/9/25   [EDGcpfe/28073]
Equivalence of alias templates in partial template specialization matching

The changes for EDGcpfe/20656,EDGcpfe/26160,EDGcpfe/26449 in version 6.6
implemented the direction of Core issue 1286 to treat simple alias templates as
equivalent to the aliased template, but did not consider matching of partial
template specializations.  For example, with --c++11:

  template<typename T> struct C;
  template<typename T> using A = C<T>;
  template<typename T, template<typename> class> struct B;
  template<typename T> struct B<T, C> { };
  B<int, A> b;  // Previously a spurious error.  Now okay.


7/7/25   [EDGcpfe/28258]
Regression preventing some cases of PCH creation

The changes for EDGcpfe/27321 (in 6.7) resulted in a regression where PCH files
spuriously were not being created with the reason "not between top level
declarations."  This issue occurred in some cases when using the "all" or
"used" template instantiation mode (via command line or via the value of
DEFAULT_INSTANTIATION_MODE).  This is now fixed.


7/7/25   [EDGcpfe/25885,EDGcpfe/27661,EDGcpfe/28296]
Deduction of an auto template parameter from an array bound

In some cases, an auto template parameter was not correctly deduced from an
array bound in a reference parameter.  For example:

  template<auto N> struct S {
    static constexpr auto size = N;
    constexpr S(const char* str) {}
  };
  template<auto N> S(const char(&)[N]) -> S<N>;
  template<S> int g();  // Class template argument deduction.
  int r = g<"x">();

Here, deduction of N from the length of "x" previously failed.  That is now
fixed.


7/2/25   [EDGcpfe/28299]
C++-generating back end: name of dependent conversion operator in using decl

In a using-declaration naming a dependent conversion operator, the
C++-generating back end previously sometimes put out the conversion type
referring to an incorrect name.  This is now fixed.  For example, with
--c++11:

  template <typename a> struct b { operator a &(); };
  template <typename c> struct d {
    using c::operator c &;   // Previously generated as "c::operator a &"
  };


7/2/25   [EDGcpfe/28207]
Constant-evaluation of std::construct_at for a union

Consider, in C++20 mode:

  inline void *operator new(decltype(sizeof(1)), void *ptr) noexcept {
    return ptr;
  }
  void operator delete(void*, void*);
  namespace std {
    // A simplified implementation of std::construct_at sufficient to
    // illustrate the issue.
    template<typename T, typename... Args>
      constexpr T* construct_at(T *ptr, Args &&...args) noexcept {
        return ::new((void *)ptr) T(args...);
      }
  }
  union U {
    int x;
    constexpr U(int x): x(x) {}
  };
  constexpr int g() {
    U u(1);
    std::construct_at(&u, 2);
    return u.x;
  }
  static_assert(g() == 2);  // Previously failed.  Now okay.

The use of std::construct_at (a type-safe interface to placement-new that can
be evaluated at compile time) for a union type previously caused the active
member of the result of that operation to be de-activated.  In the example
above, that resulted in the static_assert condition "g() == 2" spuriously being
reported as non-constant.  This is a regression introduced in version 6.7 of
the front end by the changes for EDGcpfe/27588.  That is now fixed.


7/2/25   [EDGcpfe/18441,EDGcpfe/19893,EDGcpfe/28209]
Internal error in make_initializer_for_lambda

Consider:

  template<typename T> class X {
    ~X();
  };
  template<typename> void f(X<char> v) {
    static_assert([v]{return true;}(), "Expected");
  }

The front end previously aborted with an internal error originating in
make_initializer_for_lambda (expr.c).  This is now fixed.  Note that the
static_assert expression is invalid (since it is non-constant due to the
capture of a value with nontrivial destruction), and an error will be issued
when the function is instantiated.


7/2/25   [EDGcpfe/28294]
Vector operations requiring integer operands

The front end previously failed to diagnose certain vector operations on
floating-point operands that are required to be integer operands.  For example,
in Clang mode:

  typedef __attribute__((ext_vector_type(4))) float Vec4;
  void g() {
    Vec4 v;
    (v ^ 4);  // Previously accepted.  Now an error.
  } 


7/1/25   [EDGcpfe/27355]
Clang compatibility: _Nonnull and _Nullability qualifiers

In Clang modes, the front end now ignores the _Nonnull and _Nullability
qualifiers when considering pointer convertibility.  For example:

 int *_Nonnull *p;
 int *         *q = p;  // Previously an error.  Now okay.


7/1/25   [EDGcpfe/28278]
Abort on constant-evaluation of decltype operand during template instantiation

The changes for EDGcpfe/27531 introduced a regression in version 6.7 of the
front end, where certain uses of function parameters in a decltype operand
could trigger an abort in function get_runtime_array_pos in the constant-
evaluation interpreter (reproduced with somewhat complex cases).  This is now
fixed.


7/1/25   [EDGcpfe/28228]
GCC compatibility: spurious default template template parameter matching error

Previously, the front end failed to apply the new C++17 "at least as
specialized" rules when checking whether a default template template argument
could be used as an argument to a template template parameter in GNU mode.  For
example, with --c++17 --g++:

  template<typename, typename = int>
  struct C;
  template<typename, template<typename> class = C>
  using A = int;
  A<int> a;  // Previously a spurious error.  Now okay.


6/30/25  [EDGcpfe/28284]
C++-generating back end: explicit-object lambdas

Lambda expressions with an explicit "this" parameter were previously
incorrectly put out by the C++-generating back end with a "static"
qualifier.  This is now fixed.  For example, with --c++23:

  auto b = [](this auto self, int x) {  // Previously generated as
                                        // [](this auto self, int x) static {
    return x;
  }

6/30/25  [EDGcpfe/28283]
Clang compatibility: Operations on ext_vector of bool types

In Clang modes, the front end supports types such as

  using Vec8B = bool __attribute((ext_vector_type(16)));

Previously, the front end permitted most arithmetic, shifting, and logical
operations on such types.  Now such operations are diagnosed as errors to
match the behavior of Clang.


6/26/25  [EDGcpfe/26910,EDGcpfe/28263]
Segfault in reconcile_template_param_lists on #pragma GCC target

In configurations where GNU_FUNCTION_MULTIVERSIONING is TRUE, the application
of a GCC "target" pragma to a template member function with an out-of-line
definition had caused a segfault (in reconcile_template_param_lists).  For
example (with --g++):

  #pragma GCC target "avx512f"
  template <class T> struct S {
    void f();
  };
  template <class T> void S<T>::f() {}


6/25/25  [EDGcpfe/28237]
Statement expressions in file-scope memory

Consider, in GNU C11 mode:

  struct S { char *str; } *sptr;
  void g() {
    sizeof(struct {
      _Static_assert(!(__builtin_has_attribute(&({
                                                   typeof(*sptr) *var = 0;
                                                   ((typeof(*(sptr)) *)(var));
                                                 })->str,
                                               common)),
                     "unexpected");
    });
  }

This previously resulted in an internal error in add_to_variables_list.  That
is now fixed.


6/25/25  [EDGcpfe/20823,EDGcpfe/27477,EDGcpfe/28119]
Improvements to GNU/Clang vector operations and their constant-evaluation

A broad number of improvements have been made to the handling of vector type
operations, including:
  - better handling of Clang-style (attribute ext_vector_type) vector of bool,
  - accepting the %= (eok_remainder_assign) operation for vectors, and
  - improvements to the constant-evaluation of various vector operations.


6/25/25  [EDGcpfe/28025]
Add supporting command-line options for writing named modules

The front end now supports the following modules-related options:

  --create_module_interface file
  Write an EDG IFC module file for a module interface unit to file.

  --create_module_internal_partition file
  Write an EDG IFC module file for a module implementation unit to file.

  --module_interface
  Write an EDG IFC module file for a module interface unit in the current
  working directory; the filename is derived from the parsed module
  declaration.

  --module_internal_partition
  Write an EDG IFC module file for a module implementation unit in the current
  working directory; the filename is derived from the parsed module
  declaration.

The following options have been removed: --ms_mod_interface,
--no_ms_mod_interface, --ms_internal_partition, --no_ms_internal_partition.
The new options are only required if creating an EDG IFC module file is
desired.


6/20/25  [EDGcpfe/28241]
Add USE_EDG_NAMESPACE to the output of --dump_configuration

The USE_EDG_NAMESPACE configuration macro's value is now dumped when
--dump_configuration is specified.


6/20/25  [EDGcpfe/28210]
Build error in SSI configurations with no back end

In configurations with the (now-deprecated, see the entry for
EDGcpfe/25583) NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
option set to TRUE and BACK_END_SHOULD_BE_CALLED set to FALSE, the front
end could not be built successfully because of an unresolved reference to
read_memory_region.  This is now fixed.


6/18/25  [EDGcpfe/28232]
Clang compatibility: catastrophic error in spaceship_result_constant_expr

When using some Clang system headers a catastrophic error (in
spaceship_result_constant_expr) had occurred when lowering the C++20
spaceship operator.  Now fixed.


6/16/25  [EDGcpfe/28225]
C++-generating back end: expressions for non-type template arguments

The changes for EDGcpfe/27274 (in version 6.7) resulted in unconditionally
recording a backing expression for every non-type template argument and
putting out that backing expression (instead of the value of the
expression) for the template argument in every reference to that instance
whenever the context permitted.  In some complex cases involving very deep
nesting of template instantiations, however, the use of these backing
expressions turned out to have unacceptable effects on the size of the
generated code and the execution time to emit it, requiring exceedingly
long qualifiers in the names of entities appearing in the backing
expressions.  In view of this impact, the C++-generating back end has
reverted to using only the value of non-type template arguments unless the
presence of a name in the expression has an effect on the semantics of the
code (e.g., causing the instantiation of another template).  The
unconditional recording of backing expressions, however, is unchanged, in
order to support source analysis applications.  For example, with --c++11:

  constexpr int x = 1, y = 2, z = 3;
  template<int> struct S { };
  S<x + y> a; // Previously generated as S<x + y>, now as S<3>
  S<z> b;     // Previously generated as S<x + y> (i.e., using the backing
              // from the instance's first reference), now as S<3>


6/12/25  [EDGcpfe/26460]
C++26: '$', '@', and '`' characters

The prospective C++26 draft Standard (as specified in WG21 paper P2558R2)
has added the three characters '$', '@', and '`' to the basic character
set.  This change has little real-word impact, as there are no uses of
those characters in the language grammar, but the change means that they
are now subject to the restriction that a universal-character-name
appearing outside a string or character literal cannot designate a member
of the basic character set.  The front end has now been updated to
implement the new rules in C++26 mode.  For example, with --c++26 --strict:

  #define STR(x) #x
  const char *p = STR(\u0060) STR(\u0024) STR(\u0040);  // Now three errors


6/10/25  [EDGcpfe/28221]
Microsoft compatibility: user-defined string literals and
--no_const_string_literals

For compatibility with very old dialects of C++, the
--no_const_string_literals command-line option (similar to MSVC's
"/Zc:strictStrings-") causes string literals to have the type "array of X"
instead of the standard "array of const X".  However, the type of the first
parameter of a user-defined string literal operator must be "pointer to
const X", so the front end issued spurious "not found" errors with that
command-line option when user-defined string literals appear in the source.
This is now fixed.  For example, with --no_const_string_literals
--ms_c++20:

  int operator"" _X(const char *, size_t);
  int i = "abc"_X;   // Previously a spurious "not found" error, now okay


6/9/25   [EDGcpfe/28201]
Regression in Unicode file path support

In the 6.7 changes adding multi-threading support (EDGcpfe/27800) a regression
was introduced in the host environment file path processing.  This results in
the front end not being able to process files when the current working
directory or the temporary directory contains a Unicode character not
representable in the current code page.  This is now fixed.

Additionally, an issue where Unicode file names appeared in diagnostics with an
incorrect encoding has been resolved.


6/7/25   [EDGcpfe/28218]
C++-generating back end: dependent member alias templates as template arguments

In some complex cases when a dependent member alias template specialization
is used in a class template definition as a template argument and the
translation unit is compiled in Microsoft mode, the C++-generating back end
could put out incorrect template arguments for the alias template
specialization.  This is now fixed.


6/5/25   [EDGcpfe/28206]
Regressions in constant-evaluation of complex arithmetic

The changes for EDGcpfe/27820 (in version 6.7 of the front end) introduced a
regression in the constant-evaluation of many complex arithmetic operations.
For example, in GNU C++20 mode, the following example failed:

  #include <complex>
  int main() {
    constexpr std::complex<long double> z1(2.5, 3.5);
    constexpr std::complex<float> z2(z1);
    static_assert(z1.imag() == z2.imag());  // Previously failed.  Now okay.
  }

This is now fixed.


6/5/25   [EDGcpfe/24291]
CTAD from a brace-enclosed, cv-qualified instance of a class template

When deducing the type of a class template from a brace-enclosed element whose
type is an instance of that class template, initializer-list constructors are
omitted during the first phase of overload resolution.  Previously, the front
end failed to do this for a cv-qualified element type or when the element type
was denoted by a typedef name.  For example, with --c++17:

  #include <initializer_list>
  template<typename T>
  struct C {
    C(std::initializer_list<T>);
  };
  C<int> f(const C<int> &c) {
    return C{c};  // Previously a spurious error.  Now okay.
  }


6/5/25   [EDGcpfe/28118]
Optimized processing of #embed

The front end now has special processing for the case when a #embed
directive (see the entry for EDGcpfe/25948,EDGcpfe/27967) is the complete
brace-enclosed initializer for a variable that is an array of an integral
type, provided that the expansion of the #embed consists solely of a
comma-separated list of integer literals whose values can all be
represented in an unsigned char.  In such cases, the normal scanning and
parsing of the expanded list of constants is replaced by effectively
treating the construct as aggregate initialization from a string literal,
significantly reducing the processing time and IL size.

This optimization involves an IL CHANGE: instead of representing the
initializer as a ck_aggregate constant with sub-constants for the
individual values of the expansion, the initializer in such cases is
represented by a special ck_string constant, identified by the new flag
variant.string.embed_expansion being TRUE, of type "array of unsigned
char".  Note that such a ck_string constant can appear as the initializer
for any array of integral type; it is not limited solely to arrays of
character types.

In a related change, if PRESERVE_EMBED_DIRECTIVE_WHEN_OPTIMIZED is set to
TRUE (the default for C++-generating back end configurations), the
embed_expansion constant will contain a pointer,
variant.string.embed_directive, that points to a textual representation of
the macro-expanded form of the associated #embed directive, and the
C++-generating back end will put out that string as the value of the
constant.  In configurations in which
PRESERVE_EMBED_DIRECTIVE_WHEN_OPTIMIZED is FALSE, the constant will be put
out as the comma-separated list of values of the bytes comprising the
string value.


5/29/25  [EDGcpfe/27230,EDGcpfe/28189]
__cpp_constexpr_in_decltype

The C++ standardization committee's paper P0859R0 introduced very specific
rules determining when a (constexpr) function template or variable template
must be instantiated to be available for potential constant evaluation.  Those
rules, however, introduce incompatibilities by triggering instantiations that
lead to errors even though the instantiation is not actually used by the
constant evaluation.  The front end therefore implements a less stringent
approach to this problem, that avoids unneeded instantiation.  It now
nonetheless defines the feature macro __cpp_constexpr_in_decltype that
indicates support for P0859R0 because the front end's approach is a pure
extension of that paper (and better approximates the behavior of GCC and MSVC).


5/28/25  [EDGcpfe/28204]
GNU compatibility: Update builtin signatures to 14.3.0

GCC 14.3.0 added some new builtins declared by "#pragma GCC aarch64" for
"arm_acle.h" and "arm_sve.h".


5/26/25  [EDGcpfe/26510,EDGcpfe/26763,EDGcpfe/28158]
MSVC and Clang compatibility: substitution of conditional explicit specifiers

MSVC and Clang do not yet implement the resolution of Core issue 2369, which
mandates constraint checking before substitution.  However, MSVC and Clang 18+
substitute into the conditional explicit specifier of a constructor only after
checking the associated constraints.  For example, with --ms_c++20:

  template<bool B>
  struct A {
    static_assert(B);  // Previously a spurious error.  Now okay.
  };
  struct C {
    template<typename T> requires (sizeof(T) != sizeof(int))
    explicit(A<sizeof(T) != sizeof(int)>::v) C(T);
    C(long);
  };
  C c = 1;


5/23/25  [EDGcpfe/28199]
Type of nontype template argument deduced from array bound

Consider (in C++20 mode):

  template<typename T, bool B> int f(T(*)[B]) requires false;
  int arr[42][true];
  int r = f(arr);

The front end previously deduced a template argument type of a non-bool
integer type for B while resolving the call f(arr) (the erroneously deduced
type was the underlying integer type for bool, usually char).  In the example
above, with the changes for EDGcpfe/27180, this was visible in the diagnostic
output (which, e.g., rendered the template argument as "'\001'" instead of as
"true").  This is now fixed.


5/23/25  [EDGcpfe/26619,EDGcpfe/27100,EDGcpfe/27117,EDGcpfe/28102]
GNU C++ compatibility: removal of GNU min/max operators

Previously, the front end recognized the binary operators "<?" (min) and ">?"
(max) in GNU C++ mode.  However, g++ removed support for these operators in
version 4.3.  For example, with --c++14 --gnu_version=50500:

  template<int> bool b = false;
  template<int I> int v = b<I>?1:2;  // Previously a spurious error.  Now okay.


5/22/25  [EDGcpfe/28155]
C++-generating back end: unbounded recursion with friend function declaration

In some complex cases in which a friend function is declared with an
in-scope private type in one of its parameters, the C++-generating back
end could enter an unbounded recursion attempting to put out that function
parameter.  This is now fixed.  For example, with --c++20:

  template<typename T> struct A {
    using type = T;
  };
  template<typename T> using B = A<T>::type;
  template<typename> using C = int;
  template<typename T> class D {
    using E = C<B<T>>;
  };
  class F {
    class G {
      friend F f(G);   // G is private
    };
  public:
    using H = G;
    using I = D<H>;
    D<G> g() {}
  };


5/21/25  [EDGcpfe/27180]
Diagnostic improvements for constraint failures during overload resolution

The front end now provides more details about the nature of constraint
failures when overload resolution fails and some candidates were discarded
due to constraint violations.  As part of these improvements, some template
arguments that were previously rendered as "<expression>" in diagnostics are
now rendered with a more specific form (most often, integer values).  Finally,
the position of the "requires" keyword in a requires-clause was previously
incorrectly recorded: This is now fixed, and affects the position of some
diagnostics.


5/20/25  [EDGcpfe/27316,EDGcpfe/28183]
GNU/Clang compatibility: __FILE_NAME__ predefined macro

As of gcc version 12.1.0 and clang version 9.0.0, these compilers support
the __FILE_NAME__ predefined macro.  This macro is like the standard
__FILE__ macro except that the value is only the file name portion,
excluding any directory components of the file path.  The front end now
emulates this behavior in the relevant modes.  For example, compiling a
file specified as /x/y/z.c with --gnu_version=120100:

  const char *p = __FILE_NAME__;   // Equivalent to "z.c"


5/20/25  [EDGcpfe/28180]
GNU/Clang compatibility: __CHAR8_TYPE__ and __GCC_ATOMIC_CHAR8_T_LOCK_FREE
predefined macros

The front end has been updated to predefine the macros
__GCC_ATOMIC_CHAR8_T_LOCK_FREE in clang and gcc emulations and, for gcc
only, __CHAR8_TYPE__, when the C++20 char8_t type is supported and either
clang_version is at least 80000 or gnu_version is at least 90000.  For
example, the following code compiles without error with --c++20
--gnu_version=90100:

  #if !defined(__CHAR8_TYPE__) || \
      !defined(__GCC_ATOMIC_CHAR8_T_LOCK_FREE)
  #error Macros not defined
  #endif


5/20/25  [EDGcpfe/28161]
Enforcing 80-bit long double on Intel-based platforms

Typically the representation of a long double on an Intel-based platform is
an 80-bit floating point number.  This architecture is reflected in the
front end configuration by setting FP_LONG_DOUBLE_IS_80BIT_EXTENDED to TRUE.
The front end has now been changed to check that this option is correctly
configured for the host environment and abort with an assertion failure (in
float_pt_init) if an incorrect setting is detected.


5/19/25  [EDGcpfe/28166]
Assertion failure with invalid fixed/floating point suffix

In configurations in which USE_FLOAT128_FOR_HOST_FP_VALUE and
APPROXIMATE_QUADMATH are set to TRUE, the changes for EDGcpfe/27601 (in
version 6.7) could result in an abort with an assertion failure in
write_orig_source_line (but originating in str_to_float128) when a fixed-
or floating-point literal contains an invalid suffix.  This is now fixed.
For example, with --gnu_version=130200 --c18 --fixed_point:

  unsigned int u3 = 10.0U;   // Now an ordinary error, no longer aborts


5/19/25  [EDGcpfe/28184]
Hang on #pragma diagnostic

In certain cases, the use of #pragma diagnostic had caused the front end to
hang.  That is now fixed.  For example:

  #pragma diag_warning code_is_unreachable
  struct S {
    void f(int x) {
  #pragma diagnostic push
  #pragma diagnostic pop
      return;
      x = 10;
    }
  };


5/19/25  [EDGcpfe/28181]
Abort on unnamed function parameter pack

Previously, the expansion of a function parameter pack in a template
declaration that includes another unnamed function parameter pack could result
in an abort due to a null pointer indirection.  For example, with --c++20:

  int g(int);
  template<typename ... T>
  int f(T ...) requires
    requires (T ... t) { g(t ...); };  // Previously aborted, now okay.
  int i = f(1);


5/15/25  [EDGcpfe/28160]
Bad representation of variable template use in some GNU C++ modes

The changes for EDGcpfe/27177 (version 6.7 of the front end) caused the
front end to produce an incomplete representation of certain uses of
variable templates appearing in alias templates (in GNU C++ modes with
gnu_version < 13000).  This primarily manifested as incorrect output
generated by the C++-generating back end.  That issue is now fixed.


5/14/25  [EDGcpfe/20880,EDGcpfe/28176]
GNU/Clang compatibility: __builtin_isinf* builtins and NaNs

The __builtin_isinf* builtins had incorrectly returned true when presented
with NaN values of suitable types and now return false instead.  For example,
with --g++:

  static_assert(__builtin_isinf(__builtin_nanf("")) == false);
  static_assert(__builtin_isinf(__builtin_nansf("")) == false);


5/14/25  [EDGcpfe/28174]
C- and C++-generating back ends: diagnostic pragmas

The changes for EDGcpfe/27667 (in version 6.7) caused some (but not all) of
the EDG-specific diagnostic pragmas to be preserved in the code generated
by the C- and C++-generating back ends, even when the generated code target
is a compiler that does not recognize those pragmas.  This has now been
addressed by setting the "ignore_in_back_end" flag to TRUE in the pragma
descriptions for the pk_diag* pragmas when gcc_is_generated_code_target,
clang_is_generated_code_target, microsoft_dialect_is_generated_code_target,
or sun_is_generated_code_target is TRUE, causing the C- and C++-generating
back ends to omit the pragma in their output.  For example, in a
C++-generating back end configuration with GCC_IS_GENERATED_CODE_TARGET set
to TRUE:

  int f(void)
  #pragma diag_default = 123   // No longer appears in the generated code
  {
    return 1U;
  }


5/14/25  [EDGcpfe/19259,EDGcpfe/28050]
Assertion failure in lower_dynamic_init

Some initializations that involved the question mark operator had produced
an assertion error (in lower_dynamic_init) when lowered.  For example,
with --c++11:

  struct A {
    int y, z;
  };
  struct B {
    A a;
  };
  int f(int i) {
    B b{i > 2 ? A{1, i} : A{}};     // No longer fails an assertion.
    return b.a.z;
  }


5/12/25  [EDGcpfe/28165]
Qualified-type array prvalues

The front end previously erroneously accepted the following example

  using T = int[3];
  using CT = const int[3];
  T &&t = CT{ 1, 2, 3 };  // Previously accepted.  Now an error.

because it dropped the "const" qualification on the array prvalue that is
"CT{ 1, 2, 3}".  That is now fixed: The "const" qualification is preserved and
an error is issued on the attempted reference binding.


5/7/25   [EDGcpfe/28145]
C++14-mode matching of pointer to function types

Consider:

  template<class F> int g(F f) = delete;         // (1)
  template<class R, class P> int g(R (*f)(P));   // (2)
  template<class T> void ft(T) throw();
  using F = void(int const&);
  int r =  g(&ft<F>);  // Previously an error in C++14 mode.  Now okay.

In C++17, exception specifications are part of function types and the call
g(&ft<F>) therefore prefers (1) over (2), because (2) requires an adjustment
for the exception specification.  The front end previously also erroneously
applied that distinction in C++14.  Now, instead, the exception specification
does not affect the exact match, and (2) is preferred because it is the more
specialized template.


5/7/25   [EDGcpfe/28156]
Failure to update the type of a variable template instance with a deduced type

Consider, in GNU C++20 mode with gnu_version >= 110000:

  template<typename T> int v;
  template<typename T> auto v<T&> = 42;
  template<typename T, typename U> constexpr same_types = __is_same(T, U);
  static_assert(same_types<decltype(v<int&>), int>);

Previously, the static assertion failed because decltype applied to a
variable template specialization that is partially specialized with a deduced
type failed to instantiate the variable to actually deduce its type.  This is
a regression introduced in version 6.7 of the front end through the changes
for EDGcpfe/20755,EDGcpfe/20905.  That is now fixed.


5/4/25   [EDGcpfe/28147]
Interpreter object layout diagnostics

The interpreter uses a custom object layout model, and in some cases will
report layout failure diagnostics.  These diagnostics were sometimes wrong;
e.g., the diagnostic out an incomplete class and that for a class that is too
large for the interpreter were interchanged.  In other cases, the diagnostic
was unhelpful because it was a side effect of an earlier error that made
constant-evaluation impossible: In some of those cases, the additional error
is now inhibited.


5/2/25   [EDGcpfe/28076]
GNU compatibility: "malloc" attribute and multi-translation mode

The changes for EDGcpfe/24729 overlooked special treatment needed for the
"malloc" attribute when the attribute appears on corresponding declarations
across translation units in multi-translation unit mode.  Such situations then
triggered spurious correspondence errors.  That is now fixed.


5/1/25   [EDGcpfe/24779]
C++23: TARG_FIELD_ALLOC_SEQUENCE_EQUALS_DECL_SEQUENCE

The Cfront-based ABI version supported by the front end includes a relatively
obscure option enabled by setting the configuration macro
TARG_FIELD_ALLOC_SEQUENCE_EQUALS_DECL_SEQUENCE to FALSE: When that is the
case, nonstatic data members are not always allocated in the order in which
they are declared, but instead they are grouped by accessibility (a suggestion
that was made in the "C++ Annotated Reference Manual", by Stroustrup & Ellis).
C++23 has made that option nonstandard and the front end now issues a
discretionary command-line error if a C++23 (or later) mode is enabled in such
a configuration.  See committee paper P1847R4.


5/1/25   [EDGcpfe/28094]
Lambda expression and multi-translation unit mode 

When simultaneously compiling multiple translation units with a secondary
unit containing a lambda expression, it was possible to trigger an internal
error in check_correspondences (trans_copy.c).  For example:

  // TU1.cpp
  void g() {}

  // TU2.cpp
  auto lm = [](auto x, auto y) { return x+y; };

This is now fixed.


4/30/25  [EDGcpfe/28084,EDGcpfe/28144]
Variables in symbol_tbl.c mistakenly not recorded for PCH restoration

The variables template_cache_segment_table and constexpr_intrinsic_descr_table
defined with static lifetime in symbol_tbl.c were previously not recorded as
variables that need adjustments when loading precompiled headers.  This could
lead to memory corruption when loading precompiled headers.  An additional
change was also made to have constexpr_intrinsic_descr_table (a hash table)
not contain direct pointers into constexpr_intrinsic_descriptions (a static
table) and instead use indices to link the two data structures.


4/29/25  [EDGcpfe/28085]
IA-64 ABI: Tail-padding optimization with user-declared trivial special members

Consider:

  struct B {
    B(B const&) = default;
    B(B&&) = default;
    B& operator=(B&&) = default;
    int a;
    char b;
  };
  struct D: B {
    char c;
  };
  static_assert(sizeof(D) == (3*sizeof(int)));  // Previously failed.
                                                // Now okay.

The IA-64 ABI "reuses" tail padding of a base class for derived class fields
if the base class is not a C++03 "POD" type.  C++03, however, didn't support
"= default" definitions, which originally made it unclear whether B in the
example above is a POD type.  However, the consensus since then appears to be
that "= default" trivial special members should not make a class non-POD for
layout purposes, and the front end now implements that rule: The tail padding
of B above is no longer reused to allocate the member D::c, thus forcing the
size of D to be larger than just two int fields.  This change introduces an
ABI incompatibility and therefore requires ABI_COMPATIBILITY_VERSION >= 608.
(Recent versions of GCC accidentally fail the test above in C++20 mode, thus
causing an ABI break.  This has been reported to GCC maintainers who have
indicated they intend to restore the pre-C++20 behavior in all modes.)


4/29/25  [EDGcpfe/28130]
Backing expressions for folded __builtin_constant_p invocations

Folded __builtin_constant_p invocations previously did not include a backing
expression (causing, e.g., the C++-generating back end not to render them
other than as a constant result).  Now they do.


4/29/25  [EDGcpfe/28131]
Abort in find_innermost_namespace_scope_depth (in some configurations)

In configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, the
changes for EDGcpfe/27505 (in version 6.7) introduced a regression that could
trigger an internal error due to a failed assertion in
find_innermost_namespace_scope_depth when a trailing requires clause of a
templated member function triggered the instantiation of a variable template.
For example, with --c++20:

  template<typename T> constexpr bool v = true;
  template<typename T> struct C {
    static int f() requires v<T>;
  };
  namespace ns {
    int j = C<int>::f();  // Previously triggered an internal error.  Now okay.
  }


4/28/25  [EDGcpfe/27411,EDGcpfe/27612,EDGcpfe/28129]
Spurious ambiguity between built-in and user-declared comparison operators

Consider, in C++20 mode:

  class S {
    operator char*();
    operator void*();
    friend bool operator==(S, char);
  } s;
  bool r =  s != 0;  // Previously an error.  Now okay.

Previously, this resulted in a spurious ambiguity error due to a bug in the
implementation of overload resolution for C++20 comparison operators (which
involves, among other options, the potential rewriting of "!=" in terms of
"==").  That is now fixed.


4/27/25  [EDGcpfe/28095]
C++-generating back end: out-of-scope constexpr nontype template arguments

As described in the entry for EDGcpfe/26339, when a template is
instantiated using a local constexpr variable in a nontype template
argument and that instance is later referenced outside the scope of that
variable, the C++-generating back end often replaces the name of the
variable with its initializer expression in the subsequent reference.  This
replacement could lead to syntactic errors in the generated code if the
initializer is enclosed in braces.  For example, with --c++11:

  template <unsigned long> struct S;
  void f() {
    constexpr unsigned long f_num{64};   // #1
    using sf = S<f_num>;                 // #2
  }
  void g() {
    constexpr unsigned long g_num{64};
    using sg = S<g_num>;                 // #3
  }

In this example, the code at #2 instantiates S<64ul> using the local
variable f_num.  The code at #3 refers to S<64UL> but the template argument
recorded at its instantiation involves the out-of-scope variable f_num,
so the C++-generating back end substitutes the variable's initializer from
#1.  However, because the initializer was brace-enclosed, the reference was
previously put out as "S<unsigned long{64}>", which is syntactically
incorrect.  This is now fixed, and the C++-generating back end now uses a
C-style cast for the value: "S<(unsigned long)64>".


4/25/25  [EDGcpfe/24249,EDGcpfe/27959,EDGcpfe/28098,EDGcpfe/28134]
GNU compatibility: "#pragma GCC arm" and "#pragma GCC aarch64"

Some of the ARM-specific header files shipped by GCC don't contain the
declarations of the functions and types to be made available by those headers
in their source code, but instead rely on pragmas to inject those declarations.
The front end now supports "#pragma GCC aarch64" and "#pragma GCC arm"
constructs.


4/24/25  [EDGcpfe/24783,EDGcpfe/27875,EDGcpfe/28091]
C++23: alias-declarations as init-statements

The front end now accepts alias-declarations as init-statements in C++23 modes,
as specified by the committee's paper P2360R0.  This feature is also accepted
with a warning in pre-C++23 modes (which matches existing practice by GCC and
Clang).  The following example is therefore accepted in C++23 mode:

  int main() {
    float x[3] = { 1, 2, 3 };
    for (using I = int; I p: x) {}
    if (using I = int; I n = 1);
    switch (using I = int; I n = 3) {
      default:;
    }
  }


4/23/25  [EDGcpfe/28104]
C-generating back end: Bit field with explicitly-aligned typedef types

Consider, e.g., in GNU C mode:

  #include <stdio.h>
  typedef int PI __attribute__((aligned(1)));
  struct S {
    char c;
    PI x : 25;
  } s[2];
  char* byte(int n) { return (char*)&s[n]; }
  int main() {
    printf("%d\n", (int)(byte(1)-byte(0)));
    return 0;
  }

The front end correctly computes the layout of struct S, but the C-generating
back end has to drop the typedef name on bit field x.  This caused the front
end to previously render the bit field declaration as "signed int x : 25;",
which isn't equivalent to the original because it loses the reduced alignment
requirement that was carried by the typedef.  On many platforms, that caused
the program to print "8" instead of (the correct) "5".  This is now fixed when
the target C compiler is GCC, Clang, or MSVC: An explicit attribute is added
to force the alignment of the field in those cases.


4/23/25  [EDGcpfe/27872]
Microsoft compatibility: Static operator()

The changes for EDGcpfe/25514,EDGcpfe/26992 introduced the ability to declare
operator() as a static member function in C++23.  This is now also enabled with
--ms_cpp23 when microsoft_version >= 1944.  Previously, this feature was
accepted with a warning in non-C++23 Microsoft modes when
microsoft_version >= 1939; that condition has now been updated to be
microsoft_version >= 1944 to better match the expected direction of the MSVC
compiler.


4/22/25  [EDGcpfe/25856]
C++23: Local non-automatic variables in constant evaluation

In C++23 mode, the front end now accepts local non-automatic variables to be
initialized and evaluated as part of constant evaluation, if the variable can
be used as a constant-expression on its own.  For example:

  constexpr char hex_digit(int n) {
    thread_local constexpr char digits[] = "0123456789ABCDEF";
    return digits[n];
  }
  static_assert(hex_digit(10) == 'A');  // Now accepted in C++23 mode.

See committee paper P2647R1.  In Clang modes with clang_version >= 160000 this
feature is accepted with a warning in pre-C++23 modes.


4/22/25  [EDGcpfe/28123]
#elifdef/#elifndef in code being skipped

As noted in the entry for EDGcpfe/24782,EDGcpfe/25697,EDGcpfe/25898, the
#elifdef and #elifndef directives are only supported in certain language
versions and emulation modes.  In modes in which they are not enabled, they
have no effect and are simply ignored when processing text being skipped
by #if, #else, etc.  This behavior can be confusing, however, so the front
end has now been changed to issue a warning for these directives appearing
in text being discarded.  For example, with --c++20:

  #ifdef A
  // The following two lines are skipped and have no effect:
  #elifndef B   // Previously silent, now elicits a warning
  #error foo
  #endif


4/22/25  [EDGcpfe/28106]
Incorrect IL for zero-length array member initialization

Consider in GNU C++ mode:

  int N = 0;
  struct I {
    int x;
    I(): x(0) {}
    I(I const &orig): x(orig.x) { N++; }
  };
  struct S {
    int m;
    I i[0];
  };
  int main() {
    S s;
    S copy(s);
    return N != 0;
  }

Previously, the front end erroneously copied an array of one element for the
member S::i, even though that array has length zero.  This could lead to memory
corruption and/or aborts.  That problem is fixed now.



4/21/25  [EDGcpfe/28081]
C++-generating back end: typedefs in template arguments

In order to reduce the volume and complexity of the generated code, the
C++-generating back end generally replaced typedefs used as type template
arguments with their underlying types.  This decision was based on the
common situation where a template instance is often first referred to using
a member typedef at the end of a long chain of template instantiations that
simply pass through a type template argument passed to the top-level
template.  There was no benefit, however, from doing this replacement when
the typedef involved is not a class member and is not an instance of an
alias template, and in some cases the replacement code could trigger a bug
in g++.  For example, with --g++:

  template<typename> struct C;
  template<class, template<typename> class> struct U;
  template<template<typename> class D = C> struct S {
    using T = U<int, D>;
  };
  using M = S<>::T;
  template<typename> struct O { };
  struct L {
    void f(O<M> = O<M>{});   // Previously generated U<int,C> instead of M
  };

The code using the underlying type, "U<int,C>", resulted in g++ issuing a
spurious error when compiling the generated code.  This has now been fixed,
with the C++-generating back end no longer replacing non-member
non-alias-template typedefs with their underlying types.


4/21/25  [EDGcpfe/28086]
Failure to set the locale leads to multiple internal assertions

Previously, if the front end failed to set the locale of LC_NUMERIC to C an
internal assertion would be triggered.  Additionally, as the front end was not
yet fully initialized, this would lead to a subsequent internal assertion
caused by the first internal assertion.  Both of these errors are now addressed
and a normal catastrophic error is instead issued.


4/18/25  [EDGcpfe/27562]
Folding of logical and/or operations in C mode

In C++ mode, the front end generally folded expressions of the form
"0 && expr()" or "true || expr()" when the logical operator is known not to
be overloaded.  In C mode, however, this was not always the case.  Now, the
transformation is done more consistently in non-strict C modes.


4/17/25  [EDGcpfe/18917,EDGcpfe/23331,EDGcpfe/26620,EDGcpfe/26654,
          EDGcpfe/27561]
GNU/Clang compatibility:  __builtin_add_overflow, etc.

The front end can now fold calls to __builtin_add_overflow,
__builtin_sub_overflow, and __builtin_mul_overflow, as well as calls to the
various variants of those functions (like __builtin_add_overflow_p or
__builtin_umull_overflow).


4/17/25  [EDGcpfe/25948,EDGcpfe/27967]
C23, C++26: #embed/__has_embed

The front end now supports the #embed directive and the __has_embed
preprocessor operator, which were added to C23 by WG14 paper N3017 and have
been adopted for the upcoming C++26 Standard via WG21 paper P1967R14.  The
feature is enabled in C23 and C++26 modes, as well as when gnu_version is at
least 150000 or clang_version is at least 190000.  In addition to the
standard #embed parameters, the front end also accepts the clang::offset and
gnu::offset parameters in clang and GNU modes, respectively.  A new
command-line option, --embed_directory, has been added to specify the list
of directories to search for files named in #embed directories; it functions
essentially equivalently to --include_directory/-I.  For example, assuming a
file "x" containing the four bytes "abc\n" and with --c++26:

  unsigned char a[] = {
  #embed "x"   // Equivalent to the list 97, 98, 99, 10
  };


4/17/25  [EDGcpfe/24769,EDGcpfe/28109]
Clang compatibility: fold expressions

"Fold" expressions (a C++17 feature) are now accepted in any C++ language mode
when clang_version >= 60000.


4/17/25  [EDGcpfe/22318,EDGcpfe/24369,EDGcpfe/27900]
Abort on diagnostic for partially-specialized variable template

Consider, with --c++14:

  template<int I, int J> struct C { };
  template<typename T>   bool u;
  template<int I>        bool u<int[I]>;
  template<int I, int J> bool u<int[I][J]>;
  constexpr bool v1 = u<int[1]>;     // Previously output as
                                     // "u [with I=int [1]]" in the diagnostic.
  constexpr bool v2 = u<int[1][2]>;  // Previously triggered an internal error.

Previously, diagnostics referring to partially-specialized variable templates
used the template arguments for the primary template but the template parameter
names from the partial specialization declaration.  In cases where the partial
specialization has more template parameters than the primary template, this
would trigger an internal error in form_template_arg_info.  Now, variable
template specializations are output as template-ids in diagnostics (such as
"u<int [1]>" and "u<int [1][2]>" in the example above).


4/15/25  [EDGcpfe/28034]
Overload resolution with __fp16 argument

Consider:

  constexpr int f(float) { return 1; }
  constexpr int f(__fp16) { return 2; }
  constexpr __fp16 x = 0.0;
  static_assert(f(x) == 2);  // Previously ambiguous.  Now okay.

Previously, this was considered ambiguous because the implicit conversion from
__fp16 to float was treated as an "exact match".  Now, it is treated as a
promotion, but as a better promotion than promoting from __fp16 to double.
The latter distinction allows the following variation to still be accepted:

  constexpr int f(double) { return 1; }
  constexpr int f(float) { return 2; }
  constexpr __fp16 x = 0.0;
  static_assert(f(x) == 2);


4/15/25  [EDGcpfe/24785,EDGcpfe/25520,EDGcpfe/25858,EDGcpfe/27234,
          EDGcpfe/27348,EDGcpfe/28090]
C++23: operator[]

In C++23 mode, the front end now accepts a number of new features for user-
defined operator[] declarations:
  1) the operator can now have zero or more parameters,
  2) the operator can now be a static member, and
  3) the operator can now have parameters with default arguments.
See committee papers P2128R6, P2589R1, and the resolution of Core issue 2507,
respectively.


4/15/25  [EDGcpfe/28108]
GNU compatibility: Possible hang with _Pragma/#pragma diagnostic

With a mixture of _Pragma and #pragma diagnostic constructs, it was possible
to hang the front end.  For example, with --g++ -tused:

  #pragma    diagnostic push
  #pragma    diag_suppress = implicit_return_from_non_void_function
  #pragma    diagnostic pop
  template <class T> struct A {
    _Pragma("diagnostic push")
    _Pragma("diagnostic pop")
  };
  template <typename T> int foo(T) { } // intentional missing return
  void bar() {
    foo(1);
  }
  #pragma diagnostic push
  struct S {
    A<int> a;
  };
  #pragma diagnostic pop

This is now fixed.


4/15/25  [EDGcpfe/28105]
GNU compatibility: GCC 15 builtin updates

The builtin signatures for GCC 15 have been updated from the 20250413
pre-release snapshot.


4/14/25  [EDGcpfe/27060,EDGcpfe/28032,EDGcpfe/28071]
GCC compatibility: Treatment of alias templates as opaque

The changes for EDGcpfe/26857 (in version 6.7) primarily treated some alias
templates in base class specifiers as opaque.  Now, this special handling is no
longer specific to base class specifiers, and to more accurately emulate GCC,
only alias templates referring to non-dependent class types are treated as
opaque.  For example, with --c++11 --g++:

  struct B;
  template<typename T> using A = B;
  template<typename T>
  struct D : A<T> {  // Previously accepted in GNU C++ modes.
    using A<T>::A;   // Now also accepted in GNU C++ modes.
  };
  struct B { };
  D<void> d;


4/11/25  [EDGcpfe/28075]
Deduction failure for non-type template parameter of dependent pointer type

Previously, using a nullptr constant as the template argument for a non-type
template parameter of dependent pointer type could result in a spurious
deduction failure.  For example, with --c++11:

  template<typename> struct X {
    using type = int;
  };
  template<typename T, typename X<T>::type * = nullptr>
  struct C { };
  template<typename T> int f(C<T>);
  int i = f(C<int>());  // Previously a spurious error.  Now okay.


4/10/25  [EDGcpfe/25861,EDGcpfe/26070,EDGcpfe/27957]
C++23: Range-based-for loops and temporaries

C++23 made a change that extends the lifetime of temporaries arising in the
"range" expression of a range-based-for loop.  For example:

  int n = 0;
  struct S {
    ~S() { n = 1; }
    S const* begin() const { return this; }
    S const* end() const { return nullptr; }
  };
  S const& g(S const &p) { return p; }
  int main() {
    for (auto x : g(S{})) {
      return n;
    }
  }
    
Prior to C++23 this program returns 1 because the destructor of the temporary
generated by "S{}" is executed before the loop is entered and that destructor
sets n to 1.  In C++23, the temporary lives until the end of the loop and so
n will still be 0 when "return n;" is executed.


4/10/25  [EDGcpfe/27839]
C++-generating back end: Rendering of constant-folded class prvalue

Consider:

  struct A { constexpr explicit A(int) {} };
  struct B {
    constexpr explicit B(int) {}
    constexpr explicit B(const A&) {}
  };
  struct S {
    static constexpr A null_A{0};
    void f() {
       B x{0};
       x = B(null_A);  // Previously rendered as "x = {};".
    }
  };

The C++-generating back end previously did not render the assignment
correctly because the class prvalue "B(null_A)" was folded to a constant
without a backing expression representing how that constant was produced.
That is now fixed (a backing expression is now recorded for such cases).


4/10/25  [EDGcpfe/28078]
a_variable::constant_valued for variables with dependent "auto" type

The member field a_variable::constant_valued is set to TRUE for const variables
whose values can be used in constant expressions.  It is also set for variables
with template parameter types that might be const after substitution.
However, the front end previously also included variables with non-const "auto"
type appearing in templates in that latter category.  That is now fixed.  Note
that variables with "decltype(auto)" type are still treated as potentially
constant-valued since "decltype(auto)" may be deduced to a const type.


4/8/25   [EDGcpfe/23297,EDGcpfe/26242,EDGcpfe/26541,EDGcpfe/27026,
          EDGcpfe/28079]
Parsing of chained <=> operators

The front end previously parsed x <=> y <=> z as if it were x <=> (y <=> z)
instead of the correct (x <=> y) <=> z.  That is now fixed.


4/8/25   [EDGcpfe/28082]
Clang compatibility: __has_extension(datasizeof)

The changes in version 6.7 that added support for the datasizeof operator
(see the entry for EDGcpfe/27080) failed to update the __has_extension
operator accordingly.  This is now fixed.  For example, with
--clang_version=190000:

  #if !__has_extension(datasizeof)
  #error datasizeof not supported   // No longer fails
  #endif


4/7/25   [EDGcpfe/28072]
GNU/Clang compatibility: pack expansion in "format" attribute

The GNU/Clang format attribute is used to enable additional checking for
routines that have printf/scanf-like arguments.  Previously the front end
checked that the parameter corresponding to the value of the third argument to
the format attribute referred to an ellipsis parameter.  That check has now
been removed in Clang mode, which allows that parameter to be a pack expansion
(or other parameter).  For example, with --clang --c++11:

  template <class... T>
  int myprintf(char const*, T...) __attribute((format(printf, 1, 2)));


4/7/25   [EDGcpfe/27961]
Substitution failure for use of enclosing "this" in generic lambda declarator

Previously, a (possibly implicit) reference to an enclosing "this" pointer
appearing in an unevaluated context of a generic lambda declarator resulted in
a substitution failure.  For example, with --c++14:

  struct A {
    template<typename T> void g(T);
    void f() {
      [] (auto i) -> decltype(g(i)) { } (1);  // Previously a spurious error.
    }                                         // Now okay.
  };


4/7/25   [EDGcpfe/20625,EDGcpfe/21181,EDGcpfe/24947,EDGcpfe/26668,
          EDGcpfe/26839]
Memory region violation for unevaluated operands

Consider, with --c++14:

  template<int> struct C { };
  void g(int i) {
    [] (auto j) -> C<sizeof(i + j)> { return {}; };
  }

Previously, this example could trigger an abort in the front end due to a
violation of the rule that file-scope IL entries (in this case, the template
argument for C) cannot contain pointers to function-scope IL entries (in this
case, the a_variable entry representing i).  That is now fixed.


4/4/25   [EDGcpfe/28062]
Clang compatibility: Type traits helpers and member function types

Clang 19.x accepts member function cv-qualifiers and ref-qualifiers for the
type operands of type traits helpers.  The front end emulates that in
corresponding modes (GCC and MSVC had been accepting such constructs already
and the front end emulated that as well).  For example:

  static_assert(!__is_pod(int() &));  // Previously a syntax error in all
                                      // Clang modes.  Now okay when
                                      // clang_version >= 190000.


4/4/25   [EDGcpfe/21675,EDGcpfe/21867,EDGcpfe/27856]
Core issue 2356: Inheriting constructors in copy/move-like operations

The front end now implements the resolution of core issue 2356, which causes
inheriting constructors to be ignored for copy/move-like operations.  This
impacts fairly subtle overload situations.  For example:

  struct B {
    B(B&&);
    template<typename T> B(T&&);
  };
  struct D: B {
    using B::B;
    D(D const&);
    D(D&&) = default;
    struct X { X(X&&) = delete; } x;
  };
  D&& g();
  D d(g());  // Previously an error because the D::x subobject cannot be moved.
             // Now, the move constructors are considered non-viable and the
             // copy constructor of D is selected instead.


4/4/25   [EDGcpfe/28058]
Additional __builtin_... functions are constant-evaluated in some C modes

The front end now constant-evaluates calls to a few more GNU-style built-in
functions in C modes, including __builtin_COLUMN, __builtin_LINE,
__builtin_FILE, __builtin_FILE_NAME, __builtin_FUNCTION, and __builtin_FUNCSIG.
For example:

  char const *str = __builtin_FILE_NAME(); // Previously an error in GNU and
                                           // Clang C modes.  Now okay.


4/2/25   [EDGcpfe/27467]
Microsoft C++ compatibility: Core issue 1467

The front end previously disabled the resolution of core issue 1467 in
Microsoft C++ mode (see the entry for EDGcpfe/16802, etc.).  However, it
appears that MSVC implements a variant of that resolution: Rather than
universally preferring conversions to std::initializer_list instances, MSVC
appears to only prefer such conversions over any other user-defined conversion
sequence.  The front end now emulates that behavior.


4/2/25   [EDGcpfe/27668,EDGcpfe/27942]
Instantiation of variable template definition

The changes for EDGcpfe/20755,EDGcpfe/20905 (in version 6.7) introduced a
regression that caused a variable template specialization to not be defined
when that variable template specialization is used only on the left-hand side
of an assignment operator.  For example, with --c++14 -tused:

  template<int I> int var = I;
  int main() {
    var<1> = 1;  // Previously an undefined reference.  Now okay.
  }


3/27/25  [EDGcpfe/28067]
GNU compatibility: access past the of string in invalid asm

When parsing an invalid asm constraint string, the front end could run past
the end of the string, resulting in undefined behavior.  For example
(with --gcc):

  void f(int i) {
    asm ("foo\n" : "=a" (i) : "[foo" (i));
  }


3/26/25  [EDGcpfe/28045]
GCC compatibility: Constant-evaluation of type-generic bit counting builtins

The front end's constant evaluator now also handles the type-generic bit
counting builtins __builtin_clzg, __builtin_ctzg, __builtin_ffsg,
__builtin_parityg, and __builtin_popcountg.


3/26/25  [EDGcpfe/28066]
GCC-mode dependent-name lookup

Older versions of GCC consider declarations appearing lexically after the point
of lookup for dependent-name lookups and the front end emulates that behavior
(see the Changes entry of 4/19/05).  However, GCC 12 fixed that issue: The
front end has now been updated to no longer emulate the older GCC behavior in
GNU C++ modes when gnu_version >= 120000.


3/25/25  [EDGcpfe/21729,EDGcpfe/23795,EDGcpfe/25621,EDGcpfe/27008,
          EDGcpfe/27617,EDGcpfe/27909]
GCC compatibility: Core issue 532

The resolution of core issue 532 (originally implemented by the changes for
EDGcpfe/10974) affects the partial ordering of member and non-member templates
when they are jointly considered during overload resolution.  The changes for
EDGcpfe/14616 disabled support for the resolution of this core issue in GNU C++
modes because tests encountered at the time suggested that GCC behaved in a
corresponding manner.  However, it appears that
  (a) GCC 14 fully implements the resolution of core issue 532, and
  (b) prior versions of GCC implemented a variant of that resolution.
Regarding (b), it is not entirely clear what specific rules GCC followed prior
to GCC 14, but we have now implemented a tweaked version of the core issue 532
rules for GNU C++ modes with gnu_version < 140000: This tweak produces a closer
emulation of corresponding versions of GCC in practice.  Regarding (a), GNU-C++
mode now follows standard rules in this regard when gnu_version >= 140000.


3/25/25  [EDGcpfe/27990]
GNU compatibility: GCC 15 builtin updates

The builtin signatures for GCC 15 have been updated from the 20250323
pre-release snapshot.


3/25/25  [EDGcpfe/26543,EDGcpfe/27053,EDGcpfe/27851]
Spurious "expired storage" errors during constant evaluation

In somewhat complex cases involving union values, the front end occasionally
failed constant evaluation claiming an attempt to access "expired storage"
(i.e., objects the constant evaluator does not think are live anymore).  This
is now fixed.


3/24/25  [EDGcpfe/28054]
GNU compatibility: querying condition code in asm functions now supported

GNU's asm syntax apparently allows an output to be specified as "=@ccCOND",
which is a special case of "=" that allows you to query the result of a
condition code at the end of your assembly statement.  The front end
now supports this (when GNU_X86_ASM_EXTENSIONS_ALLOWED is TRUE).  For example
(with --g++):

  void f(int &i, bool b) {
    __asm__ __volatile__ (
        "lock; incb %[i]\n\t"
        : [i] "+m" (i), [result] "=@ccnz" (b)
        :
        : "memory"
    );
  }

This code is derived from one of the Boost library headers.


3/21/25  [EDGcpfe/28043]
C++-generating back end: types of explicit-object member functions

In some cases, the C++-generating back end could add the "this" keyword to
the parameter list in the type of an explicit-object member function, even
though the keyword can only be used in a declaration of such a function.
This is now fixed.  For example, with --c++23:

  template <typename T> constexpr bool v = true;
  struct S {
    void f(this S) {}
  };
  void g() {
    using X = decltype(&S::f);
    static_assert(v<X>);   // Previously generated as "v<void (*)(this S)>"
  }


3/20/25  [EDGcpfe/25499,EDGcpfe/27995]
C++23: initializing character arrays with UTF-8 literals

WG21 document P2513R3 changed the rules for initializing an array of char
or unsigned char so that a UTF-8 string literal is an acceptable
initializer.  The front end has now been updated accordingly.  Because the
paper was adopted as a defect report, this change applies in all modes that
support UTF-8 string literals.  For example, with --c++23:

  char s[] = u8"abc";   // Previously an error, now okay


3/20/25  [EDGcpfe/28044]
C++23: feature-test macro for std::bfloat16_t

The changes that enabled support for std::bfloat16_t (see the entry for
EDGcpfe/26466) inadvertently failed to add the predefined feature-test
macro, __STDCPP_BFLOAT16_T__.  That is now fixed.  For example, with
--c++23:

  #ifndef __STDCPP_BFLOAT16_T__
  #error bfloat16 not supported   // No longer fails
  #endif


3/18/25  [EDGcpfe/28033]
Constant-evaluation of __builtin_nan, __builtin_inf, and __builtin_signbit

The front end's constant evaluator has been improved to better handle some
additional built-in floating-point functions: __builtin_nan, __builtin_inf,
__builtin_signbit, and their variously-suffixed variants.


3/18/25  [EDGcpfe/23696]
C++-generating back end: Abort on conditional explicit construct

Consider (in C++20 mode):

  struct S {
    explicit(false) operator int() const;
  };
  S::operator int() const { return 42; }

This previously triggered an internal error in the C++-generating back end (in
function gen_routine_decl) because of a missing pseudo-attribute that must
describe the operand of the conditional explicit construct.  That is now fixed.


3/18/25  [EDGcpfe/28035]
Microsoft compatibility: __FUNCSIG__ format

In Microsoft mode, the front end now emulates MSVC more closely when
generating the string contents of the __FUNCSIG__ construct.  In
particular, it now includes the calling convention ("__cdecl" by default),
class and enumeration types are represented as elaborated type specifiers
(e.g., "class C" and "enum E" instead of simply "C" and "E"), and an empty
parameter list is rendered as "(void)" instead of "()".  For example, with
--microsoft:

  template <typename> constexpr auto f() {
    return __FUNCSIG__;
  }
  struct S;
  const char *p = f<S>();   // Previously equivalent to "auto f<S>()", now
                            // "auto __cdecl f<struct S>(void)"


3/18/25  [EDGcpfe/26547,EDGcpfe/27691]
Spurious "atomic constraint depends on itself" error

In some cases, the front end previously issued a spurious "atomic constraint
depends on itself" error during constraint checking.  For example, with
--c++20:

  template<typename T> auto f(T t) { t.g(); }
  template<typename T> requires
    requires (T t) { f(t); }  // Previously a spurious error.  Now okay.
  using A = T;
  template<typename> struct C { void g() { A<C> a; } };
  A<C<int>> a;


3/17/25  [EDGcpfe/27950]
Clang compatibility: Spurious error for scalable vector builtins in C mode

Some builtin definitions for scalable vector types incorrectly used the C++
bool type, resulting in spurious errors when using such a builtin function in C
mode.  For example, in an ARM64 configuration with --c --clang_version 180100:

  void f() {
    __builtin_sve_svundef2_b();  // Previously a spurious error.  Now okay.
  }


3/14/25  [EDGcpfe/27986]
Overload resolution failure in GNU/Clang modes with synthesized comparisons

In GNU and Clang C++ modes, the changes for EDGcpfe/12414 (implementing a GCC
overload resolution quirk) interacted erroneously with the various tie-breaking
overload resolution rules introduced for comparison operators in C++20.  That
could result in spurious errors, such as in the following case:

  template<typename T1, typename T2> bool operator==(T1 const& , T2 const&);
  struct S {
    template <typename > void operator==(S);
    template <typename U = int> int operator==(S const&) const;
    template <typename U = int> int operator!=(S const&) const;
  };
  S f();
  auto r = f() != f();  // Previously an error in GNU and Clang C++20 modes.

That is now fixed.  Furthermore, the changes for EDGcpfe/12414 no longer take
effect in Clang C++ modes (since Clang does not imitate GCC in that respect).


3/13/25  [EDGcpfe/27887]
Incorrect source position information for variable templates

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the identifier_range and
specifiers_range fields for a variable template were not set correctly.  For
example, with --c++17:

  template<typename T> T v = 0;

In this example, the identifier_range and the specifiers_range end position
were previously pointing to the "=" token.  That is now fixed.


3/13/25  [EDGcpfe/28031]
C++-generating back end, clang compatibility: __datasizeof

Version 6.7 added support for the clang __datasizeof operator (see
EDGcpfe/27080).  However, in cases where the operand of __datasizeof is
dependent, the C++-generating back end put out an error string instead of
the original operand.  This is now fixed.  For example, with --c++17
--clang_version=190000:

  template<typename T> int s = __datasizeof(T);  // Previously put out an
                                                 // error string instead of T


3/12/25  [EDGcpfe/28027]
Assertion failure in pop_object_lifetime_full 

In some fairly complex situations, the front end could abort with an assertion
failure in pop_object_lifetime_full (il.c) while checking whether a requires-
expression is satisfied.  That is now fixed.


3/12/25  [EDGcpfe/27847,EDGcpfe/27867,EDGcpfe/27894]
Partial-ordering of conditionally-explicit member function template

The front end previously often failed to establish partial ordering of member
templates when one of the templates is conditionally-explicit.  For example:

  template<typename> struct F { static const bool b = false; };
  template<typename> struct U;
  struct S {
    template<int = 0> S(int);  // (1)
    template<typename ...Ts> explicit(F<U<Ts...>>::b) S(Ts...);
  };
  S s(42);  // Previously ambiguous.  Now selects (1).

In this example, the first constructor is "more specialized" than the second,
but the front end failed to establish that because of the presence of the
dependent conditional "explicit" specifier.  That is now fixed.


3/11/25  [EDGcpfe/28008]
Configuration error checking for QUADMATH options

The front end previously would allow APPROXIMATE_QUADMATH and
USE_QUADMATH_LIBRARY to be set to TRUE when USE_FLOAT128_FOR_HOST_FP_VALUE is
FALSE.  This configuration is not valid and now results in a compile time error
when building the front end.

In version 6.7 changes made to improve memory safety (EDGcpfe/26704) resulted
in this invalid configuration printing floating point numbers incorrectly
(e.g., 1.0 would become 11.0).


3/11/25  [EDGcpfe/28018]
Missing reinitialization in character overflow handling

The changes for EDGcpfe/26451 in version 6.7 introduced several variables
in lexical.c used in reporting overflow errors in string literals.
However, the initialization for those variables in lexical_init() was
inadvertently placed within conditional compilation for DEBUG and
UNICODE_VULNERABILITY_DETECTION_SUPPORTED.  In configurations with
MAKE_FRONT_END_CALLABLE set to TRUE, this error could result in undefined
behavior on subsequent invocations of the front end as the values of those
variables from earlier calls would not be reinitialized.  This is now fixed.


3/10/25  [EDGcpfe/28015,EDGcpfe/28019]
Building the front end with conversion warnings enabled

A number of diagnostics had been emitted when building the 6.7 front end with
various compilers with various command-line options that enable conversion
warnings.  This change addresses a large number of them.


3/8/25   [EDGcpfe/28021]
Range check for literals with the signed size_t suffix

The integer literal 'z' suffix without 'u' specifies the signed type
corresponding to std::size_t (see the entry for EDGcpfe/23555).  The range
check for such literals restricted the acceptable values to be no larger
than the maximum positive value of that type.  However, this check was
incorrect for binary, octal, and hexadecimal literals, which allow a
negative value to be created via a large unsigned value in which the sign
bit is '1'.  This is now fixed.  For example, in a configuration in which
std::size_t is 64 bits and with --c++23:

  // Both literals are 2 to the 63rd power:
  auto i = 9'223'372'036'854'775'808z;   // error, value too large
  auto j = 0x8000'0000'0000'0000z;       // okay, specifies the most negative
                                         // value of the signed type


3/7/25   [EDGcpfe/27886]
Clang C++ compatibility: Vector conversions

Consider, in Clang C++ mode:

  using VD = double __attribute((vector_size(16)));
  using VL = long __attribute((vector_size(16)));
  int g(VD);  // (1)
  int g(VL);  // (2)
  struct X { operator VD(); };
  int r = g(X{});  // Previously ambiguous.  Now selects (1).

Clang permits implicit conversions between equal-sized vector types (such as
VD and VL above).  The front end previously erroneously always treated such
conversions as identity conversions when considered as a step in user-defined
conversions.  That caused the example above to be ambiguous, but candidate (1)
should be preferred over (2) since the standard conversion needed for (1) is
truly an identity and that for candidate (2) is not.  This is now fixed.


3/7/25   [EDGcpfe/28016]
Spurious failure to constant-evaluate base-to-derived casts

In some fairly involved cases, the front end incorrectly updated metadata in
the constant evaluator's representation of class/struct base subobjects.  That
could result in the constant evaluation of base-to-derived casts to fail, which
in turn could result in spurious errors about expressions not being constant
when they are required to be.  That is now fixed.  Certain changes in version
6.7 of the front end (e.g., for EDGcpfe/26745,EDGcpfe/26988,EDGcpfe/27516)
created new circumstances where this bug manifested, thus making it appear as a
regression.


3/7/25   [EDGcpfe/27949,EDGcpfe/28001,EDGcpfe/28013]
Clang compatibility: Additional changes for __builtin_elementwise_* and
__builtin_reduce_* builtins

Clang 16, 17, 18, 19, and 20 added some new __builtin_elementwise_* and
__builtin_reduce_* builtins for which special handling is required.


3/6/25   [EDGcpfe/27948]
Clang C++11 compatibility: constexpr constraints in system headers

In Clang C++11 mode, the front end now permits constexpr functions defined in
system headers to adhere to the more relaxed constraints of C++14 (and
sometimes even allows some C++20 relaxations, such as not requiring
initializers for local variables).  This matches the behavior of Clang.


3/6/25   [EDGcpfe/28011]
C++-generating back end: conditions with deduced types in template definitions

In some cases in which a condition appearing within a template definition
is declared with a deduced type, the C++-generating back end could put out
the name of the condition as the initializer expression cast to "auto"
instead of as the name itself.  (The addition of the cast to "auto" in such
cases was the result of the change in version 6.7 for EDGcpfe/27425, but
the incorrect use of the initializer instead of the condition name predated
that change.)  This is now fixed.  For example, with --c++20:

  template <typename> struct A {
    template <int> struct B { };
    struct C {
      enum { N };
    };
    void f() {
      if constexpr (constexpr auto v = C::N; v) {  // The condition name "v"
                                                   // was put out in 6.7 as
                                                   // "((auto)((C::N)))" and
                                                   // previously as "(C::N)"
        B<1u> b;
      }
    }
  };
  A<int> ai;


3/6/25   [EDGcpfe/27787]
C-generating back end: incorrect code generated for initializing VLAs

In configurations where LOWER_VARIABLE_LENGTH_ARRAYS is FALSE, the C-generating
back end had generated incorrect code when initializing certain VLAs.
For example, with --g++:

  int f(int n) {
    int a[n] = { 42, n };
    return a[0];
  }
  int main() {
    return f(2);  // Had returned 0, now 42.
  }


3/6/25   [EDGcpfe/27908]
Abort on recursive call of function with deduced return type

In certain cases where a function with a deduced return type is called
recursively, the front end could abort with a failed assertion in
finalize_deduced_return_type.  For example, with --c++14:

  template<typename T>
  auto g(T t) -> decltype(t(1L));
  template<typename T>
  auto f(T t) {
    g([] (auto a) { f(a); });  // Previously triggered an abort.  Now okay.
    return 1;
  }
  int i = f(1);


3/5/25   [EDGcpfe/27973]
C++-generating back end: compiler-generated co_return statement

In cases where the front end implicitly adds a compiler-generated co_return
statement in a coroutine, the C++-generating back end could abort with a
failed assertion in gen_statement_full.  This is now fixed.


3/5/25   [EDGcpfe/28010]
__builtin_copysign and infinities

The constant evaluator previously treated __builtin_copysign applied to
infinities as non-constant.  Now, such cases can be successfully constant-
evaluated.


3/5/25   [EDGcpfe/27989]
Abort on indirection through pointer outside of array bounds

In some modes and configurations, constant evaluation failed to diagnose
certain out-of-bound access to array elements.  In turn, this could lead to
aborts due to invalid memory accesses.  For example, in GNU C++ mode:

  constexpr char str[] = "12345";
  constexpr char const *p = str;
  constexpr char c = *(p-1);  // Previously could abort.  Now an error.

This problem was present in the constant evaluator (interpret.c) for a while,
but changes in version 6.7 of the front end caused different cases to trigger
this bug, thus making it appear as a regression.  This is now fixed.


3/5/25   [EDGcpfe/28009]
Folding of floating-point builtins had caused undefined behavior

As a result of a missing skip_typerefs, the folding of certain floating-point
builtin operations could have undefined behavior when operating on a constant
whose type contains a typeref.  For example (with --gnu_version 110000):

  using a = float;
  auto b = __builtin_signbit(a());


3/5/25   [EDGcpfe/27915]
C++-generating back end: decltype involving non-type template parameter

In certain cases in which a type member of a class template is defined using
a decltype whose operand involves a non-type template parameter, the
C++-generating back end could put out a use of that member of an instance
of the class template in a form that referred to an undeclared variable.  This
is now fixed.  For example, with --c++20:

  struct A { 
    int operator()() const;
  }; 
  template<auto F> struct B { 
    using type = decltype(F());
  }; 
  template<class> struct C { }; 
  void g() { 
    C<B<A{}>::type> cba;   // Previously generated using decltype involving
                           // an undeclared variable name
  } 


3/5/25   [EDGcpfe/27525]
GCC/Clang compatibility: Support va_list on ARM platforms

Previously, the predefined type used for va_list in GCC/Clang mode on ARM
platforms mode was the same as that on 64-bit x86 platforms (i.e., a
one-element array of struct __va_list_tag).  Now, the predefined type used for
va_list on ARM platforms is struct __va_list.


3/5/25   [EDGcpfe/28000,EDGcpfe/28002]
Typedef of unnamed enum accidentally made invisible in Microsoft bugs mode

The changes for EDGcpfe/24484,EDGcpfe/26840 interacted unexpectedly with the
changes for EDGcpfe/8651, causing a typedef of an unnamed enumeration type to
become invisible and the enumeration to instead have the name of the typedef.
For example, this resulted in the following being accidentally accepted in
Microsoft bugs mode:

  typedef enum {} E;
  double E = 1.0;  // Should be an error, but accidentally accepted in
                   // Microsoft bugs mode.

This also resulted in an undesirable IL change in cases like the following:

  typedef enum {} E;
  E x;

where in Microsoft bugs mode the representation of x pointed to the
representation of the enumeration type directly, whereas previously it pointed
to the representation of the typedef type.  This regression (introduced in
version 6.7 of the front end) is now fixed.


3/3/25   [EDGcpfe/27858]
C++_generating back end: explicit function template argument with local
variable

In cases when the first use of an instance of a function template uses an
explicit template argument that refers to a local variable, the
C++-generating back end put out the template argument using the value of
the variable instead of its name.  This is now fixed.  For example, with
--c++14:

  template <bool a> bool f();
  void g() {
    constexpr bool b = false;
    f<b>();   // Previously generated as f<false>()
  }


3/3/25   [EDGcpfe/27999]
GNU C compatibility: default mode is C23

When gnu_version >= 150000, the default version of the C standard emulated
is now C23 to match a similar change with GNU 15.0.0.


3/1/25   [EDGcpfe/27994]
C++-generating back end: incorrect dependent conversion operator name

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end produced invalid
output when naming the type in a dependent conversion operator.  This is
now fixed.  For example, with --strict:

  template<typename T> void f() {
    T t;
    t.operator typename T::X();   // Previously generated as t.T::operator X()
  }


2/28/25  [EDGcpfe/27791]
New compiler_generated field for a_statement

A new field, compiler_generated, has been added to a_statement to indicate that
a statement is compiler-generated (i.e., does not appear in the source of the
translation unit).  Often such statements can be identified by a NULL source
position (except that statements added by lowering are typically given a
source position).  No position information has been changed.

Additionally, in configurations that do lowering, a new flag,
lowering_generated, has been added to indicate that a statement was added
during the lowering process.


2/27/25  [EDGcpfe/25300,EDGcpfe/27874]
Access checking for implicit deduction guides

Previously, the front end did not grant an implicit deduction guide member
access privileges to its class during substitution, resulting in spurious class
template argument deduction failures.  For example, with --c++17:

  template<int I, int V> struct B { };
  template<int I>
  class C {
    static constexpr int v = I;
  public:
    C(int, B<I, v>);
  };
  C c{1, B<1, 1>{}};  // Previously a spurious error.  Now okay.


2/27/25  [EDGcpfe/24479]
Abort due to error node passed to lowering for nested generic lambda

Previously, a generic lambda declarator that referred to a parameter of an
enclosing generic lambda could result in an error node during substitution of
its conversion operator template.  In configurations that do IL lowering, this
later triggered an internal error in lower_type.  For example, with --c++14:

  int (*p)(int) = [] (auto o) {
    return [] (auto i) -> decltype(o + i) { return 0; };
  } (1);  // Previously triggered an internal error.  Now okay.


2/26/25  [EDGcpfe/27854]
C++-generating back end: unbounded recursion with inaccessible template args

In some complex cases involving templates instantiated with inaccessible
type template arguments, the C++-generating back end could enter an
unbounded recursion attempting to put out a reference to such a template
instance.  This is now fixed.


2/26/25  [EDGcpfe/27991]
Infinite loop on code with mismatched "diagnostic push/pop" directives

In code that has mismatched "diagnostic pop" entries (i.e., that don't match
a preceding "diagnostic push"), an infinite loop could occur when trying to
determine if a diagnostic should be issued.  For example, with --c++14:

  _Pragma("diagnostic pop");
  _Pragma("diag_suppress deprecated_entity");
  struct [[deprecated]] A {
    _Pragma("diagnostic pop");
  };
  A a;


2/25/25  [EDGcpfe/27834,EDGcpfe/27975]
Clang C compatibility: pass_object_size attribute

Support for the pass_object_size attribute has been improved in Clang C mode,
including disallowing taking the address of a function with a parameter that
is declared with the pass_object_size attribute.  For example:

  void f(void *p __attribute__((pass_object_size(0))));
  int main() {
    void (*pf)(void *) = f; // Previously aborted in Clang C mode.  Now an
  }                         // ordinary error.


2/25/25  [EDGcpfe/27943]
Abort on array access during constant evaluation (in some configurations)

The interpreter's object layout algorithm did not correctly account for
elements juxtaposed in an array.  In configurations where a host integer is
a 16-byte aligned integer type, this could result in access to misaligned
integers.  That is now fixed.


2/24/24  [EDGcpfe/27985]
GNU C compatibility: nullptr keyword

The C23 Standard adds support for the nullptr keyword and nullptr_t type
(see the entry for EDGcpfe/25950,EDGcpfe/26287,EDGcpfe/27445).  The release
candidate for gcc 15.1.0 recognizes the nullptr keyword (but defines
nullptr_t as a typedef in its <stddef.h> header) in non-C23 C modes if
nullptr has not been otherwise declared, and the front end has now been
changed accordingly when gnu_version is at least 150000.  For example, with
--gcc --gnu_version=150100:

  void *p = nullptr;   // Now accepted in non-C23 GNU C modes


2/25/25  [EDGcpfe/27958,EDGcpfe/27992]
C++-generating back end: Abort in gen_expr on enk_initializer node

The C++-generating back end sometimes aborted with an internal error in
gen_expr (cp_gen_be.c) on an enk_initializer node (which represents a constant-
folded dynamic initializer).  This was a consequence of constant-folding
accidentally introducing a loop in the expression structure of a variable
initializer.  For example:

  struct S {
    constexpr S(const int&) {}
  };
  template<typename> void g() {
    constexpr S s = S(1);  // Previously triggered an internal error.
  }

This regression is now fixed (it was introduced in version 6.7 by the changes
for EDGcpfe/27456).


2/25/25  [EDGcpfe/27960,EDGcpfe/27983]
Internal error in find_allocated_name_reference

In configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE, the
changes for EDGcpfe/27200 (in version 6.7) could result in an internal error
due to a failed assertion in find_allocated_name_reference.  For example, with
--c++11:

  using P = struct { int i; };
  void f(P *p) {
    p->~P();  // Previously triggered an internal error in some configurations.
  }           // Now okay.


2/24/25  [EDGcpfe/27977]
Missing skip_typerefs when scanning __builtin_complex with __fp16 arguments

The changes for EDGcpfe/27820 (in version 6.7) mistakenly omitted a
skip_typerefs thereby causing a spurious assertion failure in cases like this
(with --g++ --c++20):

  _Complex __fp16 f(__fp16 x) {
    return __builtin_complex(x, x);
  }

Note that lowering of the _Complex __fp16 type is still unsupported.


2/24/25  [EDGcpfe/27982]
C++-generating back end: use of type traits helpers in template arguments

The changes for EDGcpfe/25658 (in version 6.7) worked around the inability
of clang and g++ to mangle non-type template arguments containing an
invocation of a type traits helper.  However, the changes for EDGcpfe/26872
(also in version 6.7) introduced additional cases in the IL that could, for
more complex versions of the example shown in the entry for
EDGcpfe/25658, result in the C++-generating back end putting out such
non-type template arguments in spite of the earlier changes.  These
additional cases have now been addressed, allowing the generated code once
again to be compiled successfully by clang and g++.


2/20/25  [EDGcpfe/27871]
Microsoft C++23 mode: Optional parameter list in lambda declarator

The C++23 feature that permits the parameter list to be omitted in a lambda
without entirely omitting that declarator (see the entry for EDGcpfe/23965)
is now enabled by the --ms_c++23 command-line option when microsoft_version
is 1943 or greater.


2/20/25  [EDGcpfe/27938,EDGcpfe/27974]
GNU and Clang C++ compatibility: variable templates in C++11 mode

In GNU and Clang C++11 modes, the front end now accepts variable templates with
a warning.  Recent GCC libstdc++ headers rely on this extension.


2/20/25  [EDGcpfe/27972]
GNU/Clang compatibility: incorrect results when folding __builtin_ceil

The changes for EDGcpfe/24997 (in version 6.4) allowed for folding of the
ceil* family of builtins under certain circumstances.  The algorithm used for
folding values in the range [-0.0..1.0) had led to incorrect results and is
now fixed.  For example (with --g++):

  extern "C" double ceil(double);
  static_assert(ceil(0.5) == 1.0);


2/20/25  [EDGcpfe/27931]
Abort due to error node on pack expansion in requires expression

With the changes for EDGcpfe/27599 (in version 6.7), a pack expansion in a
requires expression of a trailing requires clause could produce an error
constant in the IL tree.  In configurations that do IL lowering, this later
triggered an internal error in lower_type.  For example, with --c++20:

  template<int I> constexpr int v = I;
  template<int ... Is> struct C { };
  template<int I> constexpr int i =
    []<int ... Is>(C<Is...>) requires requires { (1 + ... + v<Is>); } {
      return (1 + ... + v<Is>);
    } (C<1>());
  static_assert(i<0> == 2);  // Previously triggered an internal error. 
                             // Now okay.

Additionally, the front end now correctly substitutes requires expressions in
the trailing requires clauses of friend function template definitions.  For
example, with --c++20:

  struct B {
    static constexpr bool v = true;
  };
  template<typename = void>
  struct C {
    template<typename U>
    friend constexpr bool f(C, U) requires requires { U::v; } { return true; }
    template<typename U>
    friend constexpr bool f(C, U) requires requires { U::x; } { return false; }
  };
  static_assert(f(C<>{}, B{}));  // Previously ambiguous.  Now okay.


2/19/25  [EDGcpfe/27970]
GNU C++ compatibility: __is_invocable and __is_nothrow_invocable

In GNU C++ modes with gnu_version >= 150000 the front end now accepts the
__is_invocable and __is_nothrow_invocable intrinsics, which much simplify the
implementation of the std::is_invocable and std::is_nothrow_invocable traits.


2/13/25  [EDGcpfe/27940]
C-, C++-generating back ends: representation of large float literals

In configurations with USE_FLOAT128_FOR_HOST_FP_VALUE and
APPROXIMATE_QUADMATH set to TRUE, the changes for EDGcpfe/27601 (in version
6.7) resulted in some large float literals being rounded to a value that
cannot be represented in the float type when the literal appeared in the
output of the C- and C++-generating back ends.  This is now fixed.  For
example:

  float x = 3.402823466e+38F;   // Previously generated as 3.4028235E38F


2/12/25  [EDGcpfe/27918]
C++-generating back end: variable template with default lambda argument

In cases when a variable template is declared with a non-type template
parameter whose default argument is a lambda expression and an instance of
that template uses the default argument, the C++-generating back end could
abort with a segfault or put out the defaulted argument as an explicit
expression using an undeclared temporary name of the form __T12345678,
depending on the configuration.  This is now fixed.  For example, with
--c++20:

  template<class T, auto = []{}> int v = 1;
  int n1 = v<int>;   // Previously segfaulted or generated the second argument
                     // with an undeclared temporary name, now preserves the
                     // original source form


2/11/25  [EDGcpfe/25517,EDGcpfe/25844]
C++23 compatibility: "assume" attribute

The "assume" attribute has been introduced in C++23 and is now supported
in C++23 mode as well as when gnu_version >= 130000 or clang_version >= 190000
(as well as GNU and clang C modes).  See committee paper P1774R8.  The front
end checks the value of the expression in constexpr contexts, but any
additional processing is left to the back end.  For example, with --c++23:

  int f(int y) {
    [[assume(y == 42)]];
    return y;   // Back end may replace with "return 42;"
  }


2/10/25  [EDGcpfe/27870]
Microsoft compatibility: enable C++23 size suffixes

The integer literal size suffixes (see the Changes entry for EDGcpfe/23555)
are now enabled by the --ms_c++23 command-line option when
microsoft_version is 1943 or greater.


2/8/25   [EDGcpfe/27873]
Microsoft compatibility: enable C++23 lambda attributes

Lambda attributes (see the Changes entry for EDGcpfe/25076,EDGcpfe/26487) are
now enabled when microsoft_version >= 1944 and --ms_c++23 or later is
specified.


2/8/25   [EDGcpfe/27920]
Microsoft compatibility: build errors in standalone utility programs

Changes in version 6.7 of the front end incorrectly excluded the definition
of conv_wide_to_utf8 (in host_envir.c) in standalone utility programs like
edgcpdisp when compiling with MSVC, resulting in a linkage error.  The
conditional compilation directives in host_envir.c have now been corrected
and standalone utility programs can once again be built using MSVC.


2/8/25   [EDGcpfe/27921]
Microsoft compatibility: build errors with MSVC and /Zc:wchar_t-

Version 6.7 of the front end introduced (in util.h) two explicit
specializations of templates with the wchar_t type.  These explicit
specializations resulted in build errors when compiled by MSVC with the
/Zc:wchar_t- command-line option, which causes wchar_t to be treated as a
typedef for unsigned short instead of being a distinct type.  These build
errors have now been addressed.


2/7/25   [EDGcpfe/27860]
GNU compatibility: __builtin_index is now constexpr

The __builtin_index function is now folded in contexts where it can be
constant-evaluated.  For example, with --g++:

  static_assert(__builtin_index("xyzzy", 'a') == nullptr);


2/6/25   [EDGcpfe/27868]
C++-generating back end: incorrect packing alignment

In some complex cases, the code produced by the C++-generating back end
could include compiler-generated #pragma pack directives that resulted in
packing alignments in portions of the generated code that differed from
those in the original source.  This is now fixed


2/6/25   [EDGcpfe/27922]

GNU compatibility: vector_size attribute

The vector_size attribute is typically only applicable to integral and floating
scalars, but GNU allows pointer types (though Clang does not).  For example
(with --g++):

  int *x [[gnu::vector_size(16)]];


2/6/25   [EDGcpfe/27789]
GNU compatibility: implicit aliases for some builtin routines

For certain routines (namely, "abs", "ceil", and "strlen"), the front end will
create an implicit alias between these routines and their corresponding
builtin counterparts and then fold calls to these routines when applicable.
G++ (but not gcc or clang) apparently doesn't create an implicit alias when
the routine has a definition.  The front end now emulates that.  For example:

  #ifdef DEFINITION
  extern "C" double ceil(double) { return 1.0; }
  #else
  extern "C" double ceil(double);
  #endif
  int main() {
    return (int)ceil(0.0);
  }

If DEFINITION is not defined, g++, gcc, and clang all fold the call to
__builtin_ceil (an implicit alias for ceil).  If DEFINITION is defined, g++
does not alias the function to the builtin and instead calls the definition
of ceil.


2/6/25   [EDGcpfe/27904]
Clang compatibility: Clang 20 builtins

The front end has been updated with the latest builtin signatures from Clang
version 20 (based on the recently-released RC1).


2/6/25   [EDGcpfe/27919]
GCC/Clang compatibility: modal 8-bit floating-point type for ARM64 (IL CHANGE)

Support for the modal 8-bit floating-point type __mfp8 has been added.  This
new storage-only type has no built-in arithmetic operations defined and is made
available on GCC 15+ and Clang 20+ for ARM64 architectures.  It is represented
in the IL as tk_mfp8.


2/5/25   [EDGcpfe/27890]
C++-generating back end: use of inaccessible name in template argument

Consider the following example:

  template<int> struct A { };
  template<int N, const char* s> struct B {
    static constexpr int v{N * 2};
    A<v> g() const;
  };
  class C {
    static constexpr char s[] = "FOO";  // private
  public:
    B<16, s> f() {   // instantiates A<32>
      return B<16, s>();
    }
  };
  using D = A<32>;   // Previously generated as A<B<16, C::s>::v>

Because template arguments for a given template instance are recorded at
the first reference to that instance, "A<32>" in the last line was
previously put out as "A<B<16, C::s>::v>", even though "C::s" is
inaccessible at that point.  This is now fixed, and the template argument
is put out as the value 32 instead of as the original expression.


2/5/25   [EDGcpfe/27916]
GNU compatibility: __builtin_operator_new/__builtin_operator_delete

The builtins __builtin_operator_new and __builtin_operator_delete are now
enabled for GCC 15 and later.


2/4/25   [EDGcpfe/27864]
Unbounded loop on complex cases involving friend definitions

In some fairly complex situations, the linked list recording fixups for friend
definitions could end up with an unintended loop structure.  Subsequent
processing would then get stuck in an unbounded loop.  That is now fixed.


2/3/25   [EDGcpfe/27910]
Compilation error when building with MSVC version 17.8 or older

EDGcpfe/27255 (in version 6.7) introduced a compilation error when building the
front end with versions of Microsoft Visual Studio prior to version 17.9.  This
is now fixed.


2/3/25   [EDGcpfe/27907]
Regression in PCH creation on Windows

EDGcpfe/27777 (in version 6.7) introduced a crash when creating a PCH on
Windows.  This is now fixed.


1/31/25  [EDGcpfe/27707]
Non-type template parameter pack expansion in nested generic lambda

Previously, the front end failed to correctly expand non-type template
parameters in a pack expansion in a generic lambda involving template
parameters from different template depths.  For example, with --c++20:

  template<int ... Is>
  constexpr int f() {
    return []<int ... Js>(auto p) {
      return ((Is + Js) + ...);
    }.template operator()<1, 2>(0);
  };
  static_assert(f<10, 20>() == 33);  // Previously failed.  Now okay.


1/31/25  [EDGcpfe/23305,EDGcpfe/25188,EDGcpfe/27859]
Non-type template parameter pack expansion in friend function template

Previously, the front end failed to correctly expand non-type template
parameters in a pack expansion in a friend function template definition.  For
example, with --c++17:

  template<int I1, int I2>
  struct C {
    template<int ... Js>
    friend constexpr int f(C<Js...>) {
      return (Js + ...);
    }
  };
  static_assert(f(C<1, 2>()) == 3);  // Previously failed.  Now okay.


1/31/25  [EDGcpfe/26806,EDGcpfe/27822]
Internal error on substitution of dependent template arguments

Previously, the front end failed to substitute dependent template arguments
into a nested template-id that is itself used as a nested name qualifier.  This
could result in an abort with a failed assertion in equiv_template_arg_lists
when ordering function overloads by constraints.  For example, with --c++20:

  template<typename>
  struct B {
    template<typename T>
    struct N { using A = T; };
  };
  template<typename T> concept C1 = sizeof(T) != 0;
  template<typename T> concept C2 = C1<typename B<T>::template N<T>::A>;
  template<typename T> bool f() requires C2<T>;
  template<typename T> bool f() requires C2<T> && true;
  bool b = f<int>();  // Previously triggered an internal error.  Now okay.


1/31/25  [EDGcpfe/26709]
Discarded statement in the prototype instantiation of a constexpr if statement

Previously, when deferring function prototype instantiations (e.g., in GCC or
Clang mode), the front end sometimes incorrectly skipped the discarded
statement in the prototype instantiation of a constexpr if statement with a
non-dependent condition.  For example, with --c++17
--defer_parse_function_templates -tused:

  template<typename T>
  struct C {
    C() { f(); }
    void f() {
      if constexpr (false) {
        undefined_id;  // Previously skipped, now an error.
      }
    }
  };
  C<int> c;


1/30/25  [EDGcpfe/27880]
GNU compatibility: "cleanup" attribute

The cleanup attribute had been enabled only in GNU C modes and is now enabled
in GNU C++ modes as well.  Generally speaking it is preferred to use the
destruction mechanisms built into the C++ language and not the cleanup
attribute.  The timing of calls to cleanup routines (e.g., relative to
destructions) and interaction with exception handling is left to the back end.
Additionally, support of the cleanup attribute within a constexpr function
is not supported at this time.  For example, with --g++:

  extern "C" int printf(const char *,...);
  void clean_up(int *x) {
    printf("cleaned up\n");
  }
  int main() {
    int x __attribute__((__cleanup__(clean_up)));
    return 0;
  }


1/30/25  [EDGcpfe/27891]
GNU compatibility: Additional type traits

GCC 15 has added the __array_rank, __is_pointer, __is_unbounded_array, and
__is_volatile type traits; these are now enabled when gnu_version >= 150000.


1/30/25  [EDGcpfe/27898]
Microsoft compatibility: C++ features enabled by --ms_c++23

The change for EDGcpfe/27662 (in version 6.6) incorrectly enabled all
C++23 features when --ms_c++23 is specified on the command line, when it
should have enabled only those features implemented in the version of MSVC
corresponding to the value of microsoft_version.  This is now fixed.


-------------------------------------------------------------------------------
Version 6.7, January 29, 2025

1/28/25  [EDGcpfe/27889]
Compilation issues when building the runtime library with bfloat16 support

To support the bfloat16 type, the C-generating back end uses the __bf16 type in
generated C code.  Support for the __bf16 type varies widely by version and
architecture and some host compilers support the __bf16 type as a storage type
but can't perform operations on objects of __bf16 type.  For full support, the
host-based back end C compiler must be able to perform operations on such
types.  Setting HOST_COMPILER_SUPPORTS_BFLOAT16 to TRUE indicates that the
back end C/C++ compiler has full support for the __bf16 type.  Setting
HOST_COMPILER_SUPPORTS_BFLOAT16 to FALSE will unconditionally disable the
bfloat16 type support in the EDG runtime library (though not in the front end).
The default value of HOST_COMPILER_SUPPORTS_BFLOAT16 is set heuristically
based on the host compiler being used to compile the front end.


1/28/25  [EDGcpfe/27850]
GNU compatibility: GCC 15 builtins

The front end has been updated with the latest builtin signatures from
GCC version 15 (based on the 20250112 pre-release snapshot).


1/28/25  [EDGcpfe/27849]
MSVC compatibility: builtin signatures for ARM32 and ARM64

Builtin signatures have been added for MSVC on ARM32 and ARM64 architectures.


1/13/25  [EDGcpfe/27831]
Clang compatibility: Deduction from _Nullable types

Consider, in Clang mode:

  int g(char *_Nullable *p);
  template <typename T> int f(int (*pf)(T**)) {
    return pf(nullptr);
  }
  int x = f(&g);  // Previously failed deduction.  Now okay.

Previously, this failed template deduction because the front end expected the
_Nullable qualifier in the parameter type of g(...) to match a qualifier in
the parameter of pf (which doesn't actually include any qualifier).  That is
now fixed.


1/6/25   [EDGcpfe/27804]
Variable initialization bugs

Previously, in configurations with MAKE_FRONT_END_CALLABLE set to TRUE, several
variables were not always properly reinitialized resulting in previous
invocations affecting future front end behavior.  This is now fixed.


1/6/25   [EDGcpfe/26448]
Sporadic crash when forming a module id on a routine declared via typedef

Previously, in configurations where MODULE_ID_NEEDED and NEAR_AND_FAR_ALLOWED
are TRUE, the front end could crash in is_auto_type when a __far function is
the first defined function in the translation unit:

  void __far f() {}

This is now fixed.


1/6/25   [EDGcpfe/26442]
Sporadic crash when parsing function template declared via typedef

Previously, the front end could crash in decl_function_template when parsing a
function template declared via typedef:

  typedef void void_fn();
  template<typename> void_fn x;

This is now fixed.


1/3/25   [EDGcpfe/26231,EDGcpfe/27027,EDGcpfe/27828]
Evaluation of complex multiplication and division

The functions cx_multiply and cx_divide in float_pt.c yielded incorrect
results when the result address aliases one of the operand addresses.  This
situation arose with compound assignments.  For example (in GNU C++14 mode):

  constexpr double g() {
    __complex double z{0, 7};
    z *= z;             // Results in a call to cx_multiply where the result
    return __imag__ z;  // address is also the address of the first operand.
  }
  static_assert(g() == 0);  // Previously failed.  Now okay.

This is now fixed.


1/3/25   [EDGcpfe/27830]
C++-generating back end: free on uninitialized address

Previously, in a configuration where BACK_END_IS_CP_GEN_BE and
MAKE_FRONT_END_CALLABLE are both TRUE, calling fe_cleanup could free an
uninitialized address (if it was called without the back end first being
invoked).  In configurations with CHECKING set to TRUE, this results in an
assertion failure in free_general.  This is now fixed.


1/2/25   [EDGcpfe/27826]
GCC/Clang compatibility: Structured bindings and member accessibility

The changes for EDGcpfe/19601,EDGcpfe/20108 implemented the revised member
accessibility constraints for structured bindings as updated through the
standardization committee's paper P0969R0.  The revised rules now also apply
in Clang C++ modes with clang_version >= 80000.  Furthermore, in GNU C++ modes
protected member access is sometimes withheld.  For example:

  struct B {
  protected:
    int i, j;
  };
  struct D: B {
    int g() const {
      auto [x, y] = *this;  // Previously an error in all Clang modes.
      return x+y;           // Now an error in all GCC modes, but accepted
    }                       // in Clang modes with clang_version >= 80000.
  };


1/2/25   [EDGcpfe/27814]
Handling of [[hiding]] attribute

Consider:

  struct B { virtual void f() const {} };
  struct D {
    using B::B;
    [[hiding]] virtual void f() {}
  };

This previously aborted in find_unhiding_using_decl() (class_decl.c) due to an
unexpected interaction between the handling of the [[hiding]] attribute and
inheriting constructors.  That is now fixed.  Furthermore, the [[hiding]]
attribute now also inhibits the warning about the virtual function in the
derived class not overriding the virtual function of the same name in the base
class.


1/2/25   [EDGcpfe/27800]
Multi-threading Support

Multi-threading support has been added to the front end (enabled via the
MULTIPLE_THREAD_COMPILATION configuration macro).  This support allows for
multiple instances of the front end to coexist in the same process on separate
threads.  This may be desirable to customers that operate primarily on smaller
translation units where process startup costs may be a significant concern or
in configurations currently setting MAKE_FRONT_END_CALLABLE to TRUE that would
like to do more work in parallel.

Dividing compilation of a single translation unit across multiple threads
(e.g., something like running the interpreter on a separate thread while
parsing continues) remains unsupported and is not advised.

Similarly, there is not currently support for using multiple threads to process
the individual translation units when multiple source files are passed on the
command line (as is enabled when COMPILE_MULTIPLE_SOURCE_FILES or
COMPILE_MULTIPLE_TRANSLATION_UNITS is TRUE).  Thus, customers can spawn
multiple threads that can each process a command line containing multiple
source files; however, each translation unit specified on the same command line
will be processed serially (i.e., no effort has been made to allow "multiple
translation unit" mode to operate in parallel and there are no current plans to
do so).

The EDG implementation of multi-threading is unfortunately incompatible with
the current EDG precompiled header implementation due the difficulty of
reliably acquiring consistent memory addresses in a long-lived multi-threaded
process.  Thus, when MULTIPLE_THREAD_COMPILATION is TRUE, precompiled-header
creation is unconditionally abandoned.

Furthermore, for compatibility with multi-threading some changes may be
required to customer patches.  The majority of this support has been added by
marking all global variables as thread_local via conditional compilation; see
EDG_THREAD, EXTERN_THREAD, and STATIC_THREAD in basics.h for more information.
If you do not plan to set MULTIPLE_THREAD_COMPILATION to TRUE, no changes are
necessary outside of any usual merge conflict resolution (we apologize for any
merge conflicts and appreciate your understanding of this disruption if you are
such a customer).

Additionally, changes have been made to how the front end interacts with
non-thread safe process level details like the current working directory and
signal handlers.  The current working directory is now managed on a per-thread
basis and can be specified on the command line via a new --wdir option; the
front end no longer changes the process level current working directory via
chdir.  Signal handling when MULTIPLE_THREAD_COMPILATION is FALSE is unchanged;
however, no signal handlers are installed when MULTIPLE_THREAD_COMPILATION is
TRUE to allow customers to provide appropriate signal handling logic for their
application.

A new POSIX-compatible multi-threaded front-end daemon implementation has been
added (see src/cfe_daemon.c) and can be enabled by setting EDG_FRONT_END_DAEMON
to TRUE.  A corresponding client program has also been added for interacting
with the daemon (see util/cfe_daemon_client.c).

These were created primarily for internal testing and are initially released on
an "exposition only" basis to provide an example of what is possible with a
front end configuration where MAKE_FRONT_END_CALLABLE,
MULTIPLE_THREAD_COMPILATION, and CUSTOM_DEFAULT_OUTPUT_FILES are all TRUE.

Additionally, the daemon can be run with MULTIPLE_THREAD_COMPILATION set to
FALSE as an example of the front end being used in a background thread of a
single-threaded process.


12/24/24 [EDGcpfe/24533,EDGcpfe/24622,EDGcpfe/25528,EDGcpfe/27754]
Microsoft compatibility: Direct reference-binding via user-defined conversion

Consider, in a Microsoft mode with microsoft_version >= 1900:

  struct S {
    struct C {};
    operator C&();
    operator const C&() const;
    void g() {
      C const& c(*this);  // Previously ambiguous.  Now okay.
    }
  };

The front end emulates an old Microsoft-mode reference binding bug that makes
the example above ambiguous.  However, MSVC has since fixed that nonstandard
behavior and the front end now restores the corresponding standard behavior
when microsoft_version >= 1900.


12/20/24 [EDGcpfe/27821]
Sporadic crash when parsing an invalid class template specialization

Previously, the front end could crash when parsing a class template
specialization where a concept was named in place of a template, e.g.:

  template<class T>
  concept C = true;
  template<class T>
  class C<int> {};

This is now fixed.


12/20/24 [EDGcpfe/27820]
Sporadic crash when parsing __builtin_complex with a non-constant operand

Previously, the front end could crash when parsing __builtin_complex with
at least one non-constant operand, e.g.:

  double a = 1.0;
  _Complex double b = __builtin_complex(a, 0.0)

This is now fixed.


12/20/24 [EDGcpfe/27818]
Sporadic crash with an invalid enumeration base

Previously, the front end could crash when parsing an enumeration with an
invalid explicit base type, e.g.:

  template<typename> struct S { };
  enum E : S<> { zero; };

This is now fixed.


12/20/24 [EDGcpfe/27817]
Sporadic crash when parsing std ordering types

Previously, the front end could crash when parsing a standard library strong
ordering type that wasn't actually a type:

namespace std { int strong_ordering; }

This is now fixed.


12/20/24 [EDGcpfe/27798]
Correspondence issues with constrained templates

When support for C++20 constrained templates was added to the front end, we
failed to add corresponding support for cross-translation unit correspondence
checking.  This could result in spurious correspondence errors and even
internal errors (e.g., in function may_have_correspondence in trans_corresp.c).
Support for constrained template correspondence checking as now been added.


12/19/24 [EDGcpfe/27808]
Microsoft compatibility: #elifdef/#elifndef preprocessor directives

MSVC added support for the #elifdef and #elifndef preprocessor directives in
version 1940 (only with the /std:c++latest, /std:clatest, and, beginning
with version 1943, the /std:c++23 command-line options).  The front end now
supports those directives in the corresponding Microsoft versions and
language modes.  For example, with --microsoft_version=1940 --ms_c++latest:

  #ifdef A
  #define N 1
  #elifndef B
  #define N 2
  #else
  #define N 3
  #endif
  #if N != 2
  #error Feature not supported
  #endif


12/18/24 [EDGcpfe/27790]
GNU/Clang C compatibility: Address constant initializers

Consider, in GNU or Clang C modes:

  unsigned long var;
  const unsigned long pvar = (unsigned long)(&var);
  const unsigned long arr[] = { pvar };

Previously this was an error because "= { pvar }" is not a constant
initializer.  However, GCC and Clang accept this in their C modes.  The front
end now emulates that behavior.


12/18/24 [EDGcpfe/27812]
Preprocessor output is sometimes delayed

Previously, a call to fflush was missing when printing preprocessor output for
the current line (e.g., using the -E option).  This resulted in preprocessor
output appearing in different places in the output stream depending on the
underlying buffer flushing behavior of the preprocessor file output performed
by fprintf.  This is now fixed.


12/18/24 [EDGcpfe/27810]
Routine special function kind corruption

Previously, the front end improperly set the routine special kind on some
a_routine objects.  This could (as an example) manifest as a crash when
traversing alternative entry points for a constructor or destructor (due to the
value of alternate_entry_points being effectively uninitialized).


12/18/24 [EDGcpfe/27806]
IL allocation tracking fixes

In DEBUG builds the front end keeps track of the number of IL entries allocated
for each IL entry kind.  Several IL entry kinds were not properly being
tracked; this has been fixed and the underlying code has been simplified.

As a result of these changes, the IL table use report (shown when using -d1 or
higher, -d-space_used, or --set_flag=space_used) has been updated to exclude IL
entry kinds that have no associated allocations, use the names specified by
il_entry_kind_names, and the ordering specified by the an_il_entry_kind enum.


12/17/24 [EDGcpfe/27697]
Memory region violation with nontype template argument of class type

Consider, in C++20 mode:

  struct S {};
  template<S> void f() {}
  int main() {
    constexpr S s;
    f<s>();
  }

In some configurations, this example triggered an abort in the front end (e.g.,
while reading the corresponding IL file) due to a violation of the rule that
file-scope IL entries (in this case, the template argument in f<s>) cannot
contain pointers to function-scope IL entries (in this case, the a_variable
entry representing s).  That is now fixed.


12/17/24 [EDGcpfe/27805]
Makefile dependencies output is sometimes delayed

Previously, a call to fflush was missing when printing Makefile dependencies
(using the -M or --dependencies option).  This resulted in Makefile
dependencies appearing in different places in the output stream depending on
the underlying buffer flushing behavior of the preprocessor file output
performed by fprintf.  This is now fixed.


12/17/24 [EDGcpfe/27505]
Short-circuit substitution of atomic constraints in trailing requires clauses

Consider, with --c++20:

  template<int I>
  struct X {
    static_assert(I != 1);  // Previously an error.  Now okay.
  };
  template<int I>
  struct C {
    template<int J>
    struct D  {
      static int f() requires (I == J) || X<I>::v || X<J>::v;
    };
  };
  int i = C<1>::D<1>::f();

When performing satisfaction checking of a trailing requires clause, each
atomic constraint needs to be substituted and checked separately.  Previously,
for a non-template member function of a nested class template, the front end
substituted into the entire requires clause, which triggered the instantiation
of X<1> in the example above.  Now, each atomic constraint is checked
separately, and since the first disjunctive clause is satisfied, no further
substitutions are performed.


12/16/24 [EDGcpfe/19393,EDGcpfe/27724]
Compilation issues when rewriting Universal Character Names (UCNs)

In configurations that do lowering and have REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING
set to TRUE, the act of rewriting these UCNs (e.g., replacing '\' with '_')
had inadvertently overwritten the names used by the symbol table, resulting
in spurious errors in some cases.  For example, with --unicode=UTF-8 --c++20:

  auto f(double α, auto β) {
    return α*β;
  }
  int main(int argc, char** argv) {
      double α = 1.0;
      double β = 2.0;
      double x = f(α, β);  // Overwrote '\' in UCNs for α and β
      double y = f(α, β);  // Lookup failed for α and β here
      return 0;
  }


12/16/24 [EDGcpfe/23392,EDGcpfe/26778,EDGcpfe/27039]
Clang compatibility: __building_module macro operator

The front end now accepts the __building_module macro operator in clang
emulation mode.  The operator takes a single identifier as its operand and
expands to the value 1 if it appears in the definition of a module whose
name matches that identifier and to 0 otherwise.  For example, with
--clang:

  #if !__building_module(xyz)
  #error This file should only be used within module xyz.
  #endif


12/12/24 [EDGcpfe/27792]
Clang compatibility: __is_complete_type

The Clang-specific type-trait helper __is_complete_type (which was added by the
changes for EDGcpfe/12122,EDGcpfe/23794,EDGcpfe/23799) now produces a true
value for reference types and for function types.


12/11/24 [EDGcpfe/26819]
Clang/GCC compatibility: Incomplete arrays in unnamed namespaces

In Clang and GNU C++ modes, the front end now accepts

  namespace {
    extern int x[];
    int f() { return x[0]; }
  }

with a warning (without x ever being defined) to match the behaviors of GCC and
Clang.


12/11/24 [EDGcpfe/27743]
Handling of members of unnamed namespaces

Previously, members of unnamed namespaces did not acquire internal linkage in
Microsoft mode.  Now they do when microsoft_version >= 1922.


12/11/24 [EDGcpfe/27769]
P1825R0 changes treated as a DR

The Changes for EDGcpfe/21596 (see entry of 8/6/19) implemented the resolution
of the C++ standardization committee's P1825R0 in C++20 mode only.  However,
that paper was voted into the standard as a "defect resolution" (DR), which
implies that it should take effect in all applicable C++ modes.  The front end 
now enables those changes in all modes that support rvalue references.


12/10/24 [EDGcpfe/27788]
Custom IL display output file support

Previously, in configurations with NEED_IL_DISPLAY set to TRUE the front end
unconditionally directed the IL display output to stdout.  Customer
configurations that set CUSTOM_DEFAULT_OUTPUT_FILES to TRUE, can (and must) now
provide a function, default_il_display_output_file(), that returns the file
handle to be used.

Additionally, IL display output is now flushed immediately.  This fixes issues
with IL output appearing in different places in the output stream depending on
the underlying buffer flushing behavior of the preprocessor file output
performed by fprintf.


12/9/24  [EDGcpfe/27566]
Abort on inaccessible inherited constructor

Previously, the front end could abort with a failed assertion in
form_template_arg_info when attempting to use an inaccessible inherited
constructor, where the base class is a specialization of a class template with
a different template parameter list than that of the derived class.  For
example, with --c++11:

  template<int, typename>
  class A {
    A(int);
  };
  template<typename T>
  struct B : A<0, T> {
    using A<0, T>::A;
  };
  B<int> b(1);  // Previously aborted, now an ordinary error.


12/6/24  [EDGcpfe/27765]
Microsoft/GCC compatibility: Reference bindings in templates

MSVC and GCC accept cases such as:

  template<int> int &r = 42;  // Ordinarily an error.  Now okay in Microsoft
                              // and GNU modes.

even though binding a prvalue to a reference to non-const value type is
nonstandard.  The front end now matches that behavior in Microsoft and GNU
modes.


12/5/24  [EDGcpfe/27781]
Spurious error on __builtin_bit_cast with class template instance

The front end previously failed to instantiate the destination type
of a __builtin_bit_cast construct when needed.  This resulted in
spurious errors about the destination type's size not matching the
operand's size.  For example:

  template<typename T> struct S {
    char val[sizeof(T)];
  };
  auto r = __builtin_bit_cast(S<int>, 42);  // Previously an error.
                                            // Now okay.

This is now fixed.


12/5/24  [EDGcpfe/21420,EDGcpfe/27767]
__is_convertible_to and array decay

The front end previously did not consider array decay when evaluating the type
trait helper __is_convertible_to.  That is now fixed.  For example:

  static_assert(__is_convertible_to(int[], int*));  // Now accepted.


12/5/24  [EDGcpfe/27784]
Custom default output file implementation support

By default, the front end uses stderr for error output; error output can be
redirected (after command-line processing is complete) via the --error_output
command-line option.  Similarly, by default, the front end uses stdout for
preprocessor output; preprocessor output can be redirected via the --output or
-o command-line options.

A new configuration option, CUSTOM_DEFAULT_OUTPUT_FILES, can now be used to
override this default.  When this option is TRUE, customers can (and must)
provide the functions, default_error_output_file() and
default_preproc_output_file(), that return the file handles to be used for the
respective category of output.


12/4/24  [EDGcpfe/26220,EDGcpfe/26230,EDGcpfe/27764]
Spurious error on non-constexpr defaulted operator<=>

Consider:

  #include <compare>
  template<typename> struct X {};
  template<typename T>
    std::strong_ordering operator<=> (X<T> const&, X<T> const&);
  struct S {
    X<int> xi;
    friend auto operator<=>(S, S) = default;
  };

Previously, the front end issued a spurious error on the defaulted operator<=>
claiming it is a constexpr function calling the non-constexpr operator<=>
template.  That is now fixed.


12/4/24  [EDGcpfe/27777]
Modernize temporary file creation

The front end by default now uses operating system provided APIs to assist in
the creation of temporary files.  If such APIs are unavailable the previous
behavior can be restored by setting USE_HOST_TMPFILE_FACILITIES (a new
configuration macro) to FALSE.

This change also resolves an issue where temporary files with paths that
include unicode characters were not deleted on Windows systems.


12/3/24  [EDGcpfe/27774]
Clang compatibility: changing the encoding of a function name operator string

With the -fms-extensions command-line option, the clang compiler emulates
MSVC in allowing character string encoding prefixes like 'L' to be applied
to the function name operators to change the encoding of the function name
string.  However, the front end only enabled this functionality in
Microsoft mode, not in clang mode with --ms_extensions.  This is now fixed.
For example, with --clang_version=170000 --ms_extensions:

  #define M(X) L ## X
  #define N(X) M(X)
  void f() {
    N(__FUNCTION__);   // Previously resulted in an error that __LPREFIX is
                       // undefined; now equivalent to L"f"
  }

(As described in the entry for EDGcpfe/24385, some features enabled by
--ms_extensions are implemented in the front end using keywords, even
though gcc and clang do not reserve those identifiers.  This change adds
__LPREFIX, __UPREFIX, __lPREFIX, and __uPREFIX to the list of such keywords
in clang mode.)


12/3/24  [EDGcpfe/27746]
GNU and clang compatibility: _Float16 and complex floating point types

The front end previously had several issues with respect to the handling
of the 16-bit floating point types and with complex floating point types:

1. In clang mode, the front end previously treated std::float16_t and
_Float16 as distinct types, when the clang compiler interprets them as the
same.  For example, with --clang_version=160000:

  template<typename, typename> struct same_type {
    static constexpr bool val = false;
  };
  template<typename T> struct same_type<T, T> {
    static constexpr bool val = true;
  };
  auto cf = 0.0f16;
  static_assert(same_type<decltype(cf), _Float16>::val,
                "wrong type");   // Previously failed, now okay

2. The front end incorrectly treated the GNU and clang extended floating
point imaginary suffixes if16, if32, if64, if128, and ibf16 as user-defined
literal suffixes.  This is now fixed in the appropriate emulation modes.
(Note that g++ also treats these suffixes as user-defined literal suffixes
unless the -std=gnu++XX or -fext-numeric-literals command-line options are
specified; the front end emulates this via the --no_strict_gnu command-line
option.)  For example, with --gnu_version=140100 --no_strict_gnu:

  auto cf32 = 0.0if32;

and with --clang_version=180100:

  auto cf16 = 0.0if16;

3. 16-bit complex floating point types were not correctly lowered and could
result in assertion failures in, e.g., dump_initializer_part in C-generating
back end configurations.


12/3/24  [EDGcpfe/27770]
Internal error on variable template in multi-trans-unit mode

When compiling multiple translation units, an internal error could occur
(in record_cache_checksum) if a variable template was declared extern.
Now fixed.  This test case would cause the internal error if compiled with
an empty second translation unit.

  template <typename T> extern const bool v;


12/3/24  [EDGcpfe/27555]
Cross-translation-unit handling of diagnose_if attribute

The front end is now more lenient in multi-translation-unit modes when matching
declarations that include the Clang diagnose_if attribute (see the entry for
EDGcpfe/19533,EDGcpfe/22944,EDGcpfe/26974).


12/2/24  [EDGcpfe/27326,EDGcpfe/27729]
Abort on partial specialization declaration with dependent non-type template
parameter

The changes for [EDGcpfe/19237,EDGcpfe/25886,EDGcpfe/26582] (in version 6.6)
introduced a null pointer indirection in look_up_member_in_substituted_parent
in some cases where a primary template with a dependent non-type template
parameter is partially specialized.  For example, with --c++11:

  template<typename T>
  struct D {
    using type = T;
  };
  template<typename T, typename U, typename D<T>::type>
  struct C;
  template<typename U>
  struct C<int, U, 0>;  // Previously aborted, now okay.


11/29/24 [EDGcpfe/27629]
Assertion failure in make_projection_symbol

Previously, an ill-formed non-defining class declaration with a base-clause,
where one of the base classes declares a conversion operator, would trigger an
assertion failure in make_projection_symbol.  For example:

  struct B {
    operator bool();
  };
  struct D : B;  // Previously aborted.  Now an ordinary error.


11/29/24 [EDGcpfe/27733]
Microsoft compatibility: access checking on class-scope using-declarations

The changes for [EDGcpfe/18533,EDGcpfe/21125] (in version 5.1) relaxed access
checking in Microsoft mode on class-scope using-declarations that denote a
single function in an indirect base class.  However, the case where the
using-declaration denoted an overload set was not considered.  That case is now
also accepted in Microsoft mode.  For example, with --c++ --microsoft:

  class A {
    void f();
    void f(int);
  };
  struct B : A { };
  struct D : B {
    using B::f;  // Normally an access error, now accepted in Microsoft mode.
  };


11/26/24 [EDGcpfe/27759]
Clang compatibility: [[no_unique_address]]

The no_unique_address standard attribute is accepted in C++20 emulation modes
and is now also accepted when clang_version >= 90000.


11/25/24 [EDGcpfe/27749]
C++-generating back end: explicit template arguments and ADL

Prior to C++20, the name of a function template in a call in which the
template's declaration is found only via argument-dependent lookup (ADL)
could not have explicit template arguments because the name is not declared
as a template in the scope of the call, so the introductory '<' of such an
argument list would be interpreted as a less-than operator.  C++20 relaxed
that restriction; however, the C++-generating back end still suppressed
such template arguments, regardless of the language level.  As a result,
when an explicit template argument is required in an ADL-only call for a
non-deduced template parameter, the generated code could not be compiled.
This is now fixed, and function template argument lists are emitted as
needed in ADL-only calls in C++20 and later modes.  For example, with
--c++20:

  namespace N {
    template<int /* non-deduced */, typename T> int f(T) { return 0; }
    struct S { };
  }
  auto g() { return N::S{}; }
  auto x = f<0>(g());   // Previously omitted "<0>"


11/24/24 [EDGcpfe/27747]
Mangling the std::float16_t _Complex type

Support for mangling the std::float16_t _Complex type was inadvertently
omitted.  This has now been fixed.


11/21/24 [EDGcpfe/24986]
Incorrect diagnostic for imaginary long integer literal

The front end does not support complex integral types.  However, in clang
mode, it incorrectly treated an imaginary long integer literal suffix as a
user-defined literal suffix, resulting in either an incorrect diagnostic or
an unintended invocation of a user-defined literal operator.  This is now
fixed.  For example, with --clang_version=110000:

  void f() {
    2il;   // Previously incorrectly diagnosed as a missing user-defined
           // literal operator; now correctly reports that complex integral
           // types are not supported.
  }


11/13/24 [EDGcpfe/27709]
Abort in get_innermost_function_scope while substituting member alias

Consider:

  template<int N> using Arr = char*[N+1];
  template<typename> constexpr int vt = 0;
  struct X {
    template<int N> using MA = Arr<N>;
    template <class T> static void f() {
      constexpr int n = vt<T>;
      MA<n>{};
    }
  };
  void g() {
    X::f<Arr<0>>();
  }

This previously aborted in get_innermost_function_scope() (scope_stk.c).
That is now fixed.


11/13/24 [EDGcpfe/27718]
Spurious error on const static member without initializer in a template

Consider:

  template<typename T> struct S {
    static inline T const sm;
  };

Previously, this triggered an error about a missing initializer for the static
member.  That is now fixed.


11/13/24 [EDGcpfe/27726]
C++-generating back end: missing type name in deduced-type initializer

In some cases in which the type of a variable is deduced from an
initializer consisting of an explicit cast, the C++-generating back end
only put out the operand of the cast instead of the cast expression.  This
is now fixed.  For example:

  struct A {
    int i;
  };
  struct B {
    B(A) {}
  };
  auto a{ A{35} };   // Previously generated as "auto a{35};"
  B b(a);


11/13/24 [EDGcpfe/27723]
C++-generating back end: segfault in get_param_for_param_ref

In certain complex cases involving templates in which a type operator such
as decltype is applied to a function template function parameter, the
C++-generating back end could terminate with a segfault in
get_param_for_param_ref.  This is now fixed.


11/11/24 [EDGcpfe/27714]
Satisfaction result caching

Consider, in C++20 mode:

  template<typename>
  constexpr bool f() { return true; }
  template<typename T>
  struct B {
    template<int> static int g() requires (f<T>());
  };
  int i = B<int>::g<0>() + B<int>::g<1>();

Here, when checking the associated constraints for "B<int>::g<0>" and
"B<int>::g<1>", the front end previously only cached the result of substituting
the template arguments into the atomic constraint (i.e., "f<int>()"), but not
the final result of satisfaction checking after constant evaluation.  Now, the
final result is cached, and thus "f<int>()" is only evaluated once.


11/11/24 [EDGcpfe/27712]
SARIF result level incorrect

Previously, the front end would emit a non-standard SARIF level property value
("catastrophe") for catastrophic errors.  The closest corresponding standard
value ("error") is now used.


11/11/24 [EDGcpfe/27710]
C++-generating back end: incorrect dependent name qualifier

In some complex cases in which a dependent type name is used as a name
qualifier, the C++-generating back end could put out the qualifier as a
dependent name from an unrelated template.  This is now fixed.  For
example, with --gnu_version=110200 --c++20:

  template <typename T, typename... Us> using A = typename T::D<Us...>;
  template <unsigned> struct B;
  struct C {
    template <typename... Ts> using D = decltype(B<sizeof...(Ts)>::f);
  };
  template <typename... Ts> using E = A<C, Ts...>;
  template <typename T, typename U> void g(U u) {
    using F = decltype(+u);
    using G = typename F::G;   // Previously generated as A<C, T...>::G
  }


11/11/24 [EDGcpfe/27706]
Performance regression with hashing of dependent member names

The changes for EDGcpfe/22821,EDGcpfe/27314,EDGcpfe/27438 (not in a release but
distributed to some customers as a patch) introduced a problem with the way
dependent member names in nontype template arguments were hashed, causing a
performance issue with programs that make use of a large number of such
constructs.  For example:

  template<int> struct C;
  template<int> struct D { };
  template<int X, int Y>
  void f(D<C<X>::v> d1,   // Previously, the same hash value was used for both
         D<C<Y>::v> d2);  // "C<X>::v" and "C<Y>::v".


11/8/24  [EDGcpfe/26834]
Overflow in integer arithmetic involving constants

Consider, in a 32-bit signed int configuration:

  constexpr bool g() {
    int x = 2147483647 + 1;  // Previously a warning only.
    return true;
  }
  static_assert(g());  // Previously okay.  Now an error.

The front end previously folded the initializer of x (with a warning about
overflow) when it was parsed.  The evaluation of the call g() then succeeded
with x initialized to the result of the folded expression (a negative value).
The C++ standard does not permit integer overflow in constant evaluation,
however.  The front end therefore no longer records the folded result of the
addition as the initializer of x (although a warning is still issued), and
attempting to constant-evaluate the call g() now fails.  The old behavior is
retained in Microsoft modes with microsoft_version <= 1940.


11/7/24  [EDGcpfe/27531]
Constant-evaluation of parameters of requires-expressions

Consider in C++20 mode:

  template<typename T> concept C = requires (T v) { requires v.f() == 42; };
  template<C T> void g(T) {}
  struct S { constexpr int f() { return 42; } };
  int main() {
    g(S{});
  }

Previously, this elicited errors because the evaluation of the constraint C<S>
for g(S{}) failed to evaluate v.f().  That is now fixed.


11/6/24  [EDGcpfe/27685]
Assertion failure in compare_expressions for enk_const_eval_deferred

Previously, compare_expressions was not implemented for
enk_const_eval_deferred; this could result in an assertion failure for some
programs using std::source_location.  This functionality is now implemented,
resolving the assertion failure.


11/7/24  [EDGcpfe/27530]
Bit fields of enumeration type with explicit underlying type

Consider:

  enum E: int { zero, one };
  struct S { E bit:1; };
  constexpr S s = { one };
  static_assert(s.bit != one);  // Previously failed.  Now okay.

Previously, the bit field S::bit was treated as unsigned because that permits
both enumerator constants (zero and one) to be represented by the bit field.
Now, the explicit signedness of the underlying type of E overrides the attempt
at fitting the enumerator constants in the bit field representation, and thus
s.bit is a negative value, causing the assertion check to succeed where it
previously failed.


11/6/24  [EDGcpfe/27702]
Assertion failure in node_operands_have_correct_value_category

In some cases that use inlining, an assertion failure in
node_operands_have_correct_value_category could occur during the inlining
process.  For example:

  struct A {
    A(const char *a) : _a((0, a)) {}
    const char *_a;
  };
  void g(A);
  void f(char* x) {
    g(A(x));
  }


11/6/24  [EDGcpfe/26745,EDGcpfe/26988,EDGcpfe/27516]
Parenthesized aggregate initializers for ctor-initializers

Consider:

  struct I { int i; };
  struct S {
    S() : val(1) {}  // Previously an error.  Now okay in C++20 mode.
    I val;
  };

The changes for EDGcpfe/20913 added support for parenthesized aggregate
initialization in C++20 mode, but they overlooked the case of ctor-initializers
(such as "val(1)" in the example above).  That is now fixed.


11/6/24  [EDGcpfe/27428]
Incorrect expansion of sizeof... expression

When a sizeof... expression gets expanded with non-pack elements in addition to
a pack, the substituted expression previously did not include the non-pack
elements.  For example, with --c++11:

  template<bool B>
  struct C {
    static_assert(B, "Unexpected");  // Previously failed.  Now okay.
    using type = int;
  };
  template<typename... Us>
  using A = C<sizeof...(Us) != 0>;
  template<typename... Ts>
  typename A<int, Ts...>::type f();
  int i = f<>();


11/4/24  [EDGcpfe/27176,EDGcpfe/27361]
Microsoft compatibility: class type_info predeclaration

Previously, the front end predeclared class type_info only if ms_extensions
was TRUE, but it now depends on the value of ms_compat instead.  In addition,
this behavior is only emulated when type_info is configured to be declared
in the global namespace rather than in namespace std, e.g. with the
command-line option --set_flag=force_ms_type_info_not_in_namespace_std
(previously, it was predeclared in namespace std in some Clang modes).
Furthermore, when ms_compat is TRUE, the typeid operator is accepted even
when no complete class type_info is available (i.e., the program did not
include <typeinfo>).


11/1/24  [EDGcpfe/27696]
Nontype template arguments with a destructor

Consider, in C++20 mode:

  struct S {
    int i = 0;
    constexpr S(): i(0) {}
    constexpr S(S const &s): i(s.i) {}
    constexpr ~S() {}
  };
  template<S> struct X {};
  constexpr S s;
  X<s> xs;  // Previously an error.  Now okay.

Previously, the front end issued an error erroneously claiming that the nontype
template argument "s" is not constant.  That is now fixed.


10/31/24 [EDGcpfe/27694]
Storage class ignored on function redeclaration with qualified name

Consider:

  void g() {}
  static void ::g();  // Previously erroneously accepted.  Now an error.

The front end previously failed to report the conflicting storage class on
the redeclaration.  That is now fixed.


10/30/24 [EDGcpfe/25512,EDGcpfe/27677]
Implicit move of return value

Consider:

  struct U { U(int*); U(U&&); ~U(); };
  struct S { S(U); };
  S g() {
    U u{new int(42)};
    return u;
  }

Previously, the front end failed to treat "return u;" using move construction,
and thus it issued an error because the copy constructor of U is deleted.  Now
this case is accepted.  In C++23 mode, the front end now also implements the
changes described in the standardization committee's paper P2266R3.  It
causes some previously-valid cases to become invalid.  For example:

  struct S { S(); S(S&); };
  S g() {
    S s;
    return s;  // Valid in C++20 but invalid in C++23.
  }


10/30/24 [EDGcpfe/27695]
C++-generating back end: function name tokens in function templates

In configurations in which the definitions of function templates are
generated from the prototype instantiation IL, when a function template
definition contains a function name token (__func__, __PRETTY_FUNCTION__,
etc.), the C++-generating back end previously put out the generic function
name instead of the function name token.  This is now fixed.  For example,
with --microsoft:

  template<typename T> const char *f(T) {
    return __FUNCSIG__;   // Previously generated as
                          // return "const char *f<T>(T)",
                          // now preserves the original source form
  }


10/29/24 [EDGcpfe/27662]
Microsoft compatibility: Enabling C++23 features

A new command-line option, --ms_c++23, has been added to emulate the /std:c++23
option that Microsoft Visual Studio provides.  This option is only available
when microsoft_version >= 1943.


10/29/24 [EDGcpfe/25759,EDGcpfe/27606]
Substitution failures triggered by narrowing conversions in system headers

The front end usually suppresses diagnostics for narrowing conversions
appearing in system headers.  Consequently, narrowing conversions previously
didn't trigger substitution failures, which could result in overload resolution
issues.  That is now fixed.  For example, with --c++11:

  # 1 "syshdr" 3
  template<typename T, typename U>
  auto f(T t, U u, int) -> decltype(T{u}, void());
  template<typename T, typename U>
  int f(T t, U u, long);
  # 1 "file.cpp"
  int i = f(0.0f, 0.0, 0);  // Previously a spurious error if "f" was declared
                            // in a system header.  Now okay.


10/28/24 [EDGcpfe/19297,EDGcpfe/19874,EDGcpfe/25095,EDGcpfe/26236,
          EDGcpfe/26247,EDGcpfe/26655,EDGcpfe/27192,EDGcpfe/27446,
          EDGcpfe/27687]
Deduction from initializer list containing nested initializer list

Consider:

  #include <initializer_list>
  auto x = { {}, 42 };

The front end previously failed deduction on this case because of the nested
list inside the top-level braced list.  That is now fixed: x is deduced to be
of type std::initializer_list<int>.


10/28/24 [EDGcpfe/27181]
Microsoft compatibility: Size of base class with explicitly-specified alignment

Consider:

  struct B {
    alignas(16) int i;
  };
  struct D : B {
    int j;
  };

When calculating the size of a base class, MSVC ignores explicitly-specified
alignment requirements that are more strict than platform-specific defaults.
On ARM64 platforms, that default is 8 bytes, and thus the sizes of both B and D
are 16 bytes in the example above.  The front end now emulates this bug in
Microsoft mode.


10/24/24 [EDGcpfe/25755,EDGcpfe/25853,EDGcpfe/27195,EDGcpfe/27261,
          EDGcpfe/27545,EDGcpfe/27675]
Core issue 2619: Designators and direct-initialization

Consider, in C++20 mode:

  struct V { explicit V() {}; };
  struct S { V v; } s = { .v{} };  // Previously an error.  Now okay.

Previously, the front end treated all aggregate element initializations as
"copy initialization", which discards "explicit" constructors, and thus the
example above produced an error.  Core issue 2619 clarified that a designated
initializer using direct-list-initialization syntax (i.e., without an
intervening "=" token) is a form of "direct initialization", which does
consider explicit constructors (making the example above valid).  The front
end now implements that issue resolution.


10/23/24 [EDGcpfe/27658]
Constant evaluation of comparison of local array addresses

Consider:

  void g() {
    int arr[] = { 1, 2, 3 };
    static_assert(&arr[0] <= &arr[1]);  // Previously an error.  Now okay.
  }

Previously, the condition in the static_assert declaration was not considered
a valid constant expression.  Now it is (and produces a true value in this
case).


10/23/24 [EDGcpfe/27435]
Pack expansions in nested template arguments of concept-ids

Previously, the front end would issue a spurious error when a concept-id
appearing in a default argument contains a pack expansion in a nested template
argument.  For example, with --c++20:

  template<typename> struct B { };
  template<typename ...> concept X = true;
  template<typename ... Ts,
           bool = X<B<Ts> ...>>  // Previously a spurious error.  Now okay.
  void f();


10/23/24 [EDGcpfe/22136,EDGcpfe/27630]
Qualified elaborated type specifier in template friend declaration

When a qualified elaborated type specifier is used in a template friend
declaration, the front end previously did not look in namespaces made visible
by using directives.  For example:

  namespace ns {
    template<typename> class A;
  }
  using namespace ns;
  class C {
    template<typename>
    friend class ::A;  // Previously a spurious error.  Now okay.
  };


10/22/24 [EDGcpfe/16802,EDGcpfe/16899,EDGcpfe/19833,EDGcpfe/27148,
          EDGcpfe/27655]
Core issue 1467

The front end now implements the resolution to Core issue 1467 which causes
conversions of initializer lists to std::initializer_list parameters to be
preferred over other conversions.  For example:

  #include <initializer_list>
  constexpr int f(char) {return 1;}
  constexpr int f(const std::initializer_list<int>&) {return 2;}
  static_assert(f({'x'}) == 2, "CWG 1467 unimplemented");

This behavior is not implemented in Microsoft modes and in very early Clang
modes (clang_version < 30700).


10/22/24 [EDGcpfe/27679]
Microsoft compatibility: Explicit static data member specialization

Consider:

  template<typename T> struct X { static T *v; }; 
  template<> int* X<int>::v;     // Definition in MSVC.
  template<> int* X<int>::v;     // Error when ms_version < 1929,
                                 // but okay after that.
  int main() { X<int>::v = 0; }  // Okay: X<int>::v is defined.

Previously, the front end issued a redefinition error in Microsoft mode because
the explicit specializations are both treated as definitions in that mode.  The
second specialization is now treated as a redeclaration instead (and no longer
a definition).  The example is still a valid program because the first explicit
specialization is still treated as a definition (which is nonstandard Microsoft
behavior).


10/22/24 [EDGcpfe/27670]
Microsoft compatibility: Conversion from incomplete derived class

Consider:

  struct B {};
  struct D: B {
    static constexpr D *pd = nullptr;
    static constexpr decltype((B*)pd) pb1;  // (1)
    static constexpr B *pb2 = (B*)pd;       // (2)
  };

The resolution of Core issue 2310 makes the conversions in line (1) and (2)
invalid.  MSVC started diagnosing line (2) with version 19.27 (see also the
entry for EDGcpfe/22468), but it appears to still accept such conversions when
they are unevaluated (as in line (1)).  The front end now emulates that
behavior more closely.


10/21/24 [EDGcpfe/27648]
Floating-point to integer conversion in folded compound assignments

Consider:

  consteval unsigned g(float f) {
    unsigned r = 1;
    r -= f;
    return r;
  }
  static_assert(g(1.1) == 0);  // Previously an error.  Now okay.

Previously, the front end failed to evaluated the compound assignment to an
unsigned variable because the floating-point result of (float)r - f is
negative.  Now, the sign is checked after the rounding implied by the
conversion to the (unsigned) integer type.  In this example, the result is
zero and therefore a valid unsigned integer result.


10/21/24 [EDGcpfe/27669]
C++-generating back end: initializer for class template argument deduction

In some cases, the C++-generating back end incorrectly put out the
initializer for a class template argument deduction as a cast to the
template without arguments, resulting in code that could not be compiled.
This is now fixed, and the cast is omitted.  For example, with --c++20
--parse_templates:

  template<typename T> struct A {
    A(T);
  };
  template<typename T> struct B {
    void f() {
      A m(g());   // Previously generated as "A m(A(g()))"
    }
    int g();
  };


10/17/24 [EDGcpfe/27667]
Abort in C++-generating back end on diagnostic pragma

Consider, in C mode:

  int f(void)
  #pragma diag_default = 123 
  {
    return 1U;
  }

This previously triggered an internal error in configurations that record
source sequence entries (in function r_set_keep_in_il_on_sslist(...), in
il_walk.c).  That is now fixed.


10/17/24 [EDGcpfe/27217]
Lambdas in template argument lists and the C++-generating back end

Consider, in C++20 mode:

  template<int> class S {};
  template <int N> void g() {
    S<[](int n){ return n; }(42)>();
  }

This previously triggered an internal error in the C++-generating back end (in
bypass_prototyped_param_src_seq_entries) because no source sequence entries
were recorded for lambdas in template argument lists.  That is now fixed.


10/17/24 [EDGcpfe/26892]
Hang on printing excessively recursive template argument lists

Consider, with --c++ --pending_instantiations 50:

  template<typename, typename> struct A { };
  template<typename T, int N>
  struct C {
    typedef typename C<A<T, T>, N - 1>::type type;
  };
  template<typename T>
  struct C<T, 0> {
    typedef A<T, T> type;
  };
  C<int, 100>::type t;

This code creates a binary tree of class template specializations with a depth
of 100.  When hitting the instantiation limit of 50 however, the front end
would halt instantiation and attempt to print the type.  For the vast majority
of machines the textual rendering of this type is extremely CPU and RAM
intensive.

A new configuration macro, MAX_ERROR_TEMPLATE_ARG_DEPTH (defaulted to a fairly
permissive 6), has been added to control the maximum depth of a template
argument list in error messages.  As an example, the type name "A<B<int,
C<int>>>" with MAX_ERROR_TEMPLATE_ARG_DEPTH=1 will now print in diagnostics as
"A<B</* etc... */>>".


10/17/24 [EDGcpfe/27634]
Internal error in inactive_scope_lookup in GNU mode

When the front end is not deferring function prototype instantiations in GNU
mode, an internal error could occur in inactive_scope_lookup in some fairly
complex cases involving a using-declaration for a base-class member where the
base class has the same name as the class template.  For example, with --g++
--no_defer_parse_function_templates:

  template<class T> struct B;
  template<> struct B<void> {
    void f();
  };
  template<class T> struct B : B<void>, T {
    using B<void>::f;
    void g() {
      B::f();  // Previously triggered an internal error.  Now okay.
    }
  };


10/16/24 [EDGcpfe/27615]
Clang/GCC compatibility: Core issue 1813

When the front end originally implemented the resolution of Core issue 1813
(see the entry of 2/20/18 for EDGcpfe/19370), Clang and GCC did not implement
the same and the corresponding front end modes emulated that behavior.  Since
then, Clang (starting with version 7) and GCC (starting with version 10) have
added support for the Core issue 1813 resolution: The front end has been
adjusted to only emulate the older Clang/GCC behavior for corresponding values
of gnu_version and clang_version.


10/16/24 [EDGcpfe/27641]
Non-trailing function parameter packs

The resolution of Core issue 1388 (treated as a defect report against previous
C++ standards) requires that the types of non-trailing function parameter packs
never get deduced.  For example, with --c++11:

  template<typename>
  struct C {
    C(int);
  };
  template<typename ... Ts>
  int f(Ts ..., C<Ts ...>);
  int i = f<int>(1, 2);  // Previously a spurious error.  Now okay.


10/14/24 [EDGcpfe/27651]
C++-generating back end: extraneous parentheses in braced initializer lists

In some complex cases involving nested braced initializer lists, the
C++-generating back end could incorrectly add extraneous parentheses around
some elements, resulting in code that could not be compiled.  This is now
fixed.


10/10/24 [EDGcpfe/27644]
C++-generating back end, GNU compatibility: use of "typename" keyword

G++ has two bugs involving the "typename" keyword that result in spurious
errors that could be triggered by the code emitted by the C++-generating
back end.  One bug occurs when the "typename" keyword is used preceding a
reference to an alias template specialization that is not a member of a
dependent class type, such as:

  struct A {
    template<typename T, typename> using type = T;
  };
  template<bool, typename T, typename U> using i = typename A::type<T, U>;

The other bug is the inverse, where g++ requires the "typename" keyword in
a template definition preceding a reference to a non-dependent type, e.g.,

  template<typename> struct B { using type = const int; }; 
  template<typename> void f() {
    static_cast<B<__remove_cv(int)>::type &>(0);
  }

The C++-generating back end has been updated to avoid generating the
"typename" keyword in all emulations for code similar to the first case and
to add the "typename" keyword in the second case when
gcc_is_generated_code_target is TRUE.


10/9/24  [EDGcpfe/27636]
Unicode 16.0.0 characters

The front end now supports the Unicode 16.0.0 character set.


10/9/24  [EDGcpfe/27169]
Mangling of template parameters used for class template argument deduction

Template parameters used for class template argument deduction were incorrectly
mangled (resulting in names that could not be demangled) and are now
mangled properly.  For example (with --c++17):

  template <class T> struct S {
    S(T);
  };
  template <class T> decltype(S(T())) c();
  auto v = c<int>();


10/9/24  [EDGcpfe/27565]
Incorrect setting of ms_extensions in some modes

In configurations where DEFAULT_MICROSOFT_MODE is TRUE and --ms_compatibility
is specified on the command-line, the ms_extensions global variable had
inadvertently been set to FALSE.


10/9/24  [EDGcpfe/27589]
Ignoring deduction guides in back ends

A change has been made to the ignore_routine_in_back_end macro to return
TRUE for deduction guides (as they should be ignored by back ends).


10/9/24  [EDGcpfe/27628]
C++-generating back end, Clang compatibility: dependent calls to
__builtin_operator_new and __builtin_operator_delete

In configurations with ALL_TEMPLATE_INFO_IN_IL set to TRUE, the C++-generating
back end previously represented dependent calls to __builtin_operator_new and
__builtin_operator_delete as calls to "operator new" and "operator delete",
respectively.  For example, with --c++14 --clang_version 190100:

  auto l = [] (auto t, auto *p) {
    __builtin_operator_new(t);     // Previously generated as "operator new(t)"
    __builtin_operator_delete(p);  // Previously generated as
  };                               // "operator delete(p)"


10/7/24  [EDGcpfe/25496]
Constraint checking during class template argument deduction for nested class
templates

When checking constraints of constructors of nested class templates during
class template argument deduction (CTAD), the front end failed to substitute
enclosing template arguments, resulting in spurious deduction failures.  For
example, with --c++20:

  template<bool B> struct N {
    template<typename T> struct C {
      C(T) requires B;
    };
  };
  N<true>::C c(0);  // Previously a spurious error.  Now okay.


10/7/24  [EDGcpfe/27599]
Substitution of member template requires clauses in template heads

Previously, a requires clause in the template head of a member template was
instantiated together with the definition of the enclosing class template
specialization.  That in turn could result in spurious errors.  Now,
substitution into the requires clause of a template head is only performed
during constraint checking.  For example, with --c++20:

  template<typename U>
  struct A {
    template<typename T> requires (sizeof(U) > 1)  // Previously a spurious
    static int f(T t);                             // error.  Now okay.
    static int f(long);
  };
  int i = A<void>::f(0);


10/6/24  [EDGcpfe/27626]
C++-generating back end, Microsoft compatibility: template arguments in name
qualifiers naming the current template definition

MSVC has a bug that causes spurious error reports in certain complex cases
when the /std command-line argument specifies C++20 or newer and the name
of a class template is used in the template definition as a qualifier with
the template parameter list as its template arguments, e.g., something like

  template<typename T> class C { ... C<T>:: ... };

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end could produce such
constructs.  This is now fixed: the template argument list is suppressed in
such cases when msvc_is_generated_code_target is TRUE.


10/5/24  [EDGcpfe/27614]
C++-generating back end: abbreviated function templates with explicit template
parameters

In some cases involving abbreviated function templates that also have
explicit template parameter lists, the C++-generating back end could put
out an extraneous comma at the end of the parameter list, resulting in
errors when the generated code was compiled.  This is now fixed.  For
example, with --c++20:

  template<typename T>   // Previously generated as "<class T,>"
  constexpr auto f(T a, auto b) {
    auto l = []<int J = 0>() {
      return J;
    };
    return 1;
  }


10/4/24  [EDGcpfe/27604]
Microsoft compatibility: UCNs and native multibyte characters

When configured with NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE set to
TRUE, the front end in Microsoft emulation mode translated
universal-character-names appearing in narrow character and string literals
to the character encoding of the current locale (i.e., the current code
page on Windows systems).  This matches the default behavior of MSVC.  With
version 19.00 (Visual Studio 2015), however, MSVC added the /utf-8
command-line option.  With that option, MSVC represents UCNs in narrow
character and string literals as the specified Unicode character encoded as
UTF-8 and not the corresponding character in the current code page.  The
front end has now been changed to emulate this /utf-8 behavior when the
current source file is in a Unicode-based encoding.  For example, with
--microsoft --unicode_source_kind=UTF-8 and assuming that the current code
page is CP-1252:

  unsigned char b[] = "\u00A7";   // Previously put out as the two bytes
                                  // 0xA7 0x0, now as the three bytes
                                  // 0xC2 0xA7 0x0 (the UTF-8 encoding)


10/4/24  [EDGcpfe/27613]
Microsoft C++ compatibility: Casts in templates

The front end now accepts some invalid casts in Microsoft-mode templates
(including in non-permissive Microsoft modes).  For example:

  struct X {};
  struct Y {};
  template<typename T> X* f(Y *p) {
    return static_cast<X*>(p);  // Now accepted in Microsoft modes.
  }


10/4/24  [EDGcpfe/24538,EDGcpfe/27611]
Spurious error on designator into anonymous struct within a union

Consider, in a C++20 mode accepting nonstandard anonymous struct members:

  union U {
    struct { int x, y; };
  } u = { .x = 1, .y = 2 };  // Previously a spurious error.  Now okay.

Previously, this elicited a spurious error due to a flaw in the logic guarding
against multiple designators within a union.  That is now fixed.


10/3/24  [EDGcpfe/27622]
Crash during overload resolution diagnostics involving concepts

In rare cases, the front end could segfault during the construction of the
error message for an ec_concept_failed diagnostic.  This bug could also
manifest as an ec_concept_failed diagnostic with an incorrect template argument
list.  This is now fixed.


10/2/24  [EDGcpfe/27378]
Declared storage class for function template definition

When a function template definition was also a redeclaration, the front end
failed to record its "declared storage class".  For example:

  template<typename T> static f(T);     // (1)
  template<typename T> static f(T) {}   // (2)

Declaration (1) is not a definition, and so the associated declared storage
class (sc_static in this case) is recorded in the associated secondary source
sequence entry (when GENERATE_SOURCE_SEQUENCE_LISTS is TRUE).  Declaration (2)
is a definition, and therefore its declared storage class (sc_static) should
be recorded in the a_routine entry representing the prototype instantiation of
template f(T).  Previously, the front end failed to do so.  That is now fixed.


10/2/24  [EDGcpfe/27546]
Microsoft C++ compatibility: Dependent using-declarations in type contexts

Consider:

  template<typename T> struct D: T {
    using T::Type;
    void f(Type);  // Now accepted in (non-permissive) Microsoft C++ mode.
  };

This is invalid because the using-declaration does not include the "typename"
keyword, so Type is assumed not to be the name of a type.  MSVC, however,
accepts this case (even in its non-permissive mode) and the front end now more
consistently emulates that.


9/30/24  [EDGcpfe/26822,EDGcpfe/27602]
Handling of non-dependent concept-ids in templates

Consider:

  template<typename> concept C = true;
  template<bool> struct S { using type = int; };
  template<class T> requires requires { S<C<int>>::type{}; } int f(T);
  int r = f(0);

Previously, this failed deduction for the call "f(0)" because the front end
did not recognize C<int> as a non-dependent concept-id that can be evaluated.
That is now fixed.


9/29/24  [EDGcpfe/27510]
Tie-breaker for reference binding via user-defined conversion

Consider:

  using F = int();
  struct A {
    operator F&();
    operator F&&() = delete;
  } obj;
  F &rf = obj;  // Previously ambiguous.  Now okay (except in Microsoft mode).

Previously, the front end treated the conversion of obj to a reference-to-
function type as ambiguous.  However, the standard includes a tie-breaking
rule for these kinds of situations (preferring the conversion to the reference
type that matches the destination type).  This rule -- introduced by the
resolution of the C++ standardization committee's Core issue 1328 -- is now
implemented (but disabled in Microsoft C++ modes, which matches MSVC behavior).


9/29/24  [EDGcpfe/27518]
C++-generating back end, GNU compatibility: non-dependent types with nested
template arguments

Versions of g++ before 13.1.0 had a bug that resulted in spurious errors
when a template definition refers to a non-dependent type using a qualified
name in which the qualifier contains nested template arguments.  In
particular, g++ incorrectly considered the type to be dependent.  In
configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end could emit such
constructs in cases involving typedefs and/or alias template
specializations.  This is now fixed, with the C++-generating back end
adding otherwise-unneeded "typename" keywords in such cases when
gnu_target_version_number is less than 130000.  For example, with
--gnu_version=110400 --c++17:

  template <bool> using e = int;
  template <typename g, typename h> constexpr bool i = true;
  template <int> struct k;
  template <class> struct m { using ah = int; };
  template <class, class...> class F;
  template <class ao> class F<ao> { struct ax {}; };
  template <class, class ba> struct G {
    using r = typename m<ba>::ah;
    using bk = F<r>;
  };
  template <class bv> struct H {
    using bk = typename G<e<i<int, int>>, bv>::bk;
  };
  template <int> struct v {
    // The following type was previously put out as
    // "F<G<e<i<int, int>>,int>::r>::ax", triggering the g++ error.  It now
    // includes the "typename" keyword before "F" and "G".
    using d = H<int>::bk::ax;
  };


9/27/24  [EDGcpfe/27624]
Spurious error on self-referential constant-initialized array

Consider:

  enum E { e = 0 };
  struct B {
    constexpr B(E &r): r(r) {}
    E &r;
  };
  struct D: public B {
    static constexpr E N = e;
    constexpr D(E p): v(p), B(v) {}
    E v;
  };
  constexpr D arr[] = { D::N };  // Previously failed.

This example previously complained about the initializer of arr[] not being
constant (because the front end did not correctly handle the self-referencing
aspect of the result).  That is now fixed.


9/27/24  [EDGcpfe/27610]
Microsoft C++ compatibility: Default member initializers for zero-length fields

In Microsoft C++ modes, the front end now accepts the following:

  struct S {
    int arr[0]{};
  };

Previously, the default initializer "{}" elicited an error.


9/24/24  [EDGcpfe/27596]
Trailing requires clauses on explicit specializations of class template members

Consider, with --c++20:

  template<typename> concept X = true;
  template<typename T> struct C {
    template<typename U> void f(U) requires X<T>;
    void g(int) requires X<T>;
  };
  template<> template<typename U>
  void C<int>::f(U) requires X<int>;
  template<>
  void C<int>::g(int);

Previously, the explicit specializations for "f" and "g" had their
trailing_requires_clause IL fields pointing to the trailing requires clauses of
the corresponding in-class member declarations.  With the changes for
EDGcpfe/22821,EDGcpfe/27314,EDGcpfe/27438 (not in a release but distributed to
some customers as a patch), this pointed to the unsubstituted requires clause
of "f".  Now, the trailing_requires_clause field for the explicit
specialization of "f" points to the trailing requires clause of the explicit
specialization declaration, whereas the explicit specialization of "g" does not
have its trailing_requires_clause field set.


9/23/24  [EDGcpfe/27551,EDGcpfe/27593]
Microsoft compatibility: typedef and typename

In non-permissive Microsoft C++ modes, the front end no longer requires the
"typename" specifier for a dependent type name if it follows the keyword
"typedef".  For example:

  template<class T> auto f(T x) {
    typedef T::X X;  // Ordinarily an error.
                     // Now okay in all Microsoft C++ modes.
    return X(x);
  }


9/23/24  [EDGcpfe/27588]
Limit on constant-evaluated type size

Previously, the maximum size of an object allocated in the constant-evaluation
interpreter was 1MB (this is the size as needed by the interpreter, not the
size produced by sizeof).  That limit has now been raised to 1GB.


9/21/24  [EDGcpfe/27601]
C++-generating back end: large _Float128 values

In configurations in which USE_FLOAT128_FOR_HOST_FP_VALUE and
USE_HOST_FP_CONVERSION_ROUTINES are TRUE but USE_QUADMATH_LIBRARY is FALSE,
the C++-generating back end could put out very large 128-bit floating point
literals in a format that was both non-syntactic and failed to reflect the
actual literal value.  This is now fixed.  For example, with
--gnu_version=140200:

  auto x = 0x1.ffffffffffffffffffffffffffffp+16383Q;  // Previously put out
                                                      // as "inf.0Q"

Similarly, very large decimal 128-bit floating point literals in such
configurations were treated as "huge" but now preserve their correct value.
For example, with --gnu_version=140200:

  auto y = 1.189731495357231765085759326628007E4932Q;  // Value is preserved


9/20/24  [EDGcpfe/25696,EDGcpfe/27501]
Pack expansions in nested generic lambdas

Previously, the front end failed to expand an enclosing function parameter pack
that was captured by a generic lambda nested in another generic lambda.  For
example, with --c++17:

  int i = [] (auto ... a) {
    return [&] (auto b) {
      return [&] (auto c) {
        return (a , ...);  // Previously a spurious error.  Now okay.
      } (3);
    } (2);
  } (1);


9/17/24  [EDGcpfe/24862,EDGcpfe/27585]
Multi-TU field correspondence crash

When compiling multiple translation units involving complex default member
initializer expressions, the front end could abort with a failed assertion in
walk_entry_and_subtree.  This is now fixed.

Additionally, a closely related issue has been fixed.  The front end previously
would not diagnose when one translation unit had a default member initializer
and another translation unit was missing said default member initializer on the
corresponding field.


9/17/24  [EDGcpfe/18478,EDGcpfe/22305,EDGcpfe/27354]
Declaration matching for enums in Microsoft nonreal base classes

In Microsoft permissive mode, an out-of-class function definition with a
parameter of enum type where the enumeration is a member of a dependent base
class could result in a spurious incompatible declaration error.  For example,
with --ms_c++17:

  template<typename T> struct B {
    enum E { };
  };
  template<typename T> struct C : public B<T> {
    void f(enum B<T>::E);
  };
  template<typename T>
  void C<T>::f(enum B<T>::E) { }  // Previously a spurious error in Microsoft
                                  // permissive mode.  Now okay.


9/16/24  [EDGcpfe/27560]
GNU/Clang compatibility: __GLIBCXX_BITSIZE_INT_N_0 and __GLIBCXX_TYPE_INT_N_0

Recent versions of GNU and Clang predefine the macros __GLIBCXX_BITSIZE_INT_N_0
and __GLIBCXX_TYPE_INT_N_0 (to "128" and "__int128" respectively) in C++
modes when using -std=gnu++* (but not when using -std=c++*).  The front end
now emulates that behavior (in GNU/Clang emulation mode when --strict_gnu is
not specified and 128-bit integers are enabled).  Note that these macros may
previously have been added to the predefined_macros.txt file (perhaps by
earlier versions of the make_predef_macro_table tool) and those values should
be removed (as the front end will now set them dynamically).


9/10/24  [EDGcpfe/23480,EDGcpfe/27202,EDGcpfe/27224]
GNU/Clang C compatibility: Folding array subscripting

Consider, in C mode:

  int const arr[] = { 0, 1 };
  struct S { int i; } S s  = { arr[1] };

Ordinarily, this is an error because arr[1] is not constant.  However, it
appears that recent versions of GCC and Clang do accept such code.  The front
end now emulates that behavior.  (See also EDGcpfe/25484, upon which these
changes depend.)


9/10/24  [EDGcpfe/27580]
C++-generating back end: dependent types with template arguments

In some contexts when a dependent type with template arguments is used, the
C++-generating back end could produce code in which the template argument
list is omitted.  This is now fixed.  For example, with --gnu_version=120100:

  struct A;
  template <bool> using B = A;
  template <typename T> using D = typename T::e;
  template <typename T>
  struct F : B<__is_aggregate(D<T>)> {   // Previously omitted "<T>"
  };
  template <typename T> using G = T;
  template <typename T> struct H {
    H(H &) : G<T>() {   // Previously omitted "<T>"
    }
  };


9/9/24   [EDGcpfe/27579]
Clang compatibility: allow ext_vector_type on bool elements

Clang versions 15.0.0 and later allow the ext_vector_type attribute to apply
to bool types and now the front end does as well in the appropriate modes.
For example:

  typedef bool bool4 __attribute__((ext_vector_type(4)));
  bool4 v;


9/9/24   [EDGcpfe/27508]
GNU/Clang compatibility: #pragma weak

In configurations with PRAGMA_WEAK_ALLOWED set to TRUE, the front end already
accepted "#pragma weak ..." constructs, but just passed them through to the
back end.  The front end otherwise ignored the #pragma, in particular during
constant evaluation.  Now, in GCC and Clang compatibility modes, entities with
C linkage matching a "#pragma weak <c_name>" directive (where <c_name> is the
identifier naming the C-linkage entity) have their a_routine::is_weak or
a_variable::is_weak flag set to TRUE, and that affects address comparisons
during constant evaluation.  For example, in GNU C mode:

  int printf(char const*, ...);
  #pragma weak weak_func
  int weak_func(int p);
  int main() {
    if (weak_func != 0) {
      printf("Error.\n");
    } else {
      printf("Okay.\n");
    }
  }

Previously, this short program output "Error." because constant evaluation
folded "weak_func != 0" to true.  Now, the comparison is no longer folded and
run time evaluation selects the "Okay." output.


9/9/24   [EDGcpfe/27577]
C++-generating back end: lambdas with attributes and no parameter list

The output produced by the C++-generating back end omitted attributes
specified for lambdas with no function parameter list.  This is now fixed.
For example, with --c++23:

  auto f = [] [[foo]] { };   // Previously omitted "[[foo]]"


9/8/24   [EDGcpfe/27568]
C++-generating back end: generic lambdas with template parameter list and no
function parameter list

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end produced incorrect
code for a generic lambda with an explicit template parameter list and no
function parameter list.  In particular, the generated code for such
lambdas omitted the template parameter list and could in some cases put
out a use of one of the lambda's template parameters using the name of a
template parameter of an unrelated previous template.  This is now fixed.
For example, with --c++20:

  template <int> struct S {
    template <typename X> static int i;
  };
  template <typename> void f() {
    []<int I> {   // Previously omitted "<int I>"
      int a[I];   // Previously generated as "a[X]"
    };
  }


9/4/24   [EDGcpfe/26150,EDGcpfe/27553]
Microsoft C++/CLI compatibility: Standard vs. managed nullptr

In Microsoft C++/CLI mode, nullptr is distinct from the standard C++11 nullptr
literal (the standard semantics are instead associated with the Microsoft
__nullptr keyword).  One way in which this manifests is that typeid(nullptr)
is invalid in C++/CLI.  However, under some circumstances MSVC treats a
managed nullptr value as a standard nullptr, and the front end now emulates
that behavior more closely.  Specifically, in C++/CLI mode decltype(nullptr)
now produces the standard nullptr type (i.e., decltype(__nullptr)), and
template deduction from a managed nullptr value produces the standard nullptr
type.


9/5/24   [EDGcpfe/27564]
Microsoft compatibility: handling malformed universal character names

The front end previously issued an error when a universal character name
(i.e., \uxxxx or \Uxxxxxxxx) has fewer than the required number of
hexadecimal digits.  When a malformed UCN was specified in a command-line
macro definition, the error was transformed into a catastrophic
command-line error and the compilation was terminated.  MSVC, however, only
diagnoses these erroneous UCNs in identifiers, and simply discards the '\'
in character and string literals.  The front end's Microsoft mode has been
changed to do the same, issuing only a remark in the newly-accepted cases.
In addition, both gcc and clang only issue errors for such UCNs in program
text, accepting them on the command line, and the front end now does the
same in corresponding emulation modes.  For example, with --microsoft
-DX=\\ub (assuming a shell that passes "\\" as a single '\'), the following
is accepted without error:

  #define Q(Z) #Z
  #define Y(Z) Q(Z)
  void f() {
    char c = '\u';         // Equivalent to 'u'
    char buf1[] = "\ub";   // Equivalent to "ub"
    char buf2[] = Y(X);    // Equivalent to "ub"
  }

With --g++ -DX=\\ub, the front end issues errors for the three occurrences
of malformed UCNs in source text but not for the appearance on the command
line.


8/30/24  [EDGcpfe/27543]
Multi-TU assertion failure in mark_as_needed

In multi-TU modes an oversight resulted in a spurious assertion failure when
marking deleted constructors as needed.  This has been fixed.


8/29/24  [EDGcpfe/27361]
Clang compatibility: declarations for type_info

Some changes have been made to better emulate the behavior of Clang,
particularly with --ms_extensions and --ms_compatibility.  Specifically,
a change has been made to pre-declare std::type_info in Clang emulation mode
when --ms_compatibility is specified (but no longer in default Clang emulation
mode or when --ms_extensions is specified).  Also, a diagnostic is now given
in Clang emulation mode when typeid is used without previously including
<typeinfo>.


8/29/24  [EDGcpfe/27362]
--ms_extensions/--ms_compatibility and stack_referenced_include_directories

The global variable stack_referenced_include_directories should be set to
TRUE when emulating Microsoft's stack model of include files.  Previously
it was set to TRUE when emulating any Microsoft mode, or when --ms_extensions
or --ms_compatibility was specified on the command-line.  That didn't quite
match the Clang behavior (when the stack model is used only with
-fms-compatibility) or the GNU behavior (which doesn't emulate the stack model
at all).  The front end behavior has been updated to reflect this.


8/28/24  [EDGcpfe/27143]
Missing enclosing_routine and parent_scope on implicitly-declared coroutine
variables

Previously, the front end failed to set the "enclosing_routine" and
"parent_scope" fields in the source correspondences of the implicitly-declared
coroutine variables for the coroutine handle and the
initial-await-resume-called flag.


8/28/24  [EDGcpfe/27231]
Missing is_pack_element flag on substituted parameter type

Consider, with --c++11:

  struct C {
    int f(int);
  };
  template<typename ... Ts>
  struct D {
    template<typename T, int (T::*)(Ts ... args)>
    static int f(Ts ... ts);
  };
  int i = D<int>::f<C, &C::f>(1);

When calling the static member function template, the explicitly-specified
template arguments get substituted into the template parameter list.
Previously, that substitution failed to propagate the "is_pack_element" flag of
any already-expanded parameter types in nested function types.


8/28/24  [EDGcpfe/26875]
reinterpret_cast from std::nullptr_t

Previously, the front end issued a spurious error on a dependent
reinterpret_cast from a value of type std::nullptr_t.  For example, with
--c++14:

  template<typename T>
  T var = reinterpret_cast<T>(nullptr);  // Previously a spurious error.
                                         // Now okay.

Additionally, in Microsoft mode, a reinterpret_cast from a std::nullptr_t type
to a pointer or pointer-to-member type is now also accepted.  For example, with
--c++11 --microsoft:

  void *v = reinterpret_cast<void *>(nullptr);  // Now accepted in Microsoft
                                                // mode.


8/27/24  [EDGcpfe/25046,EDGcpfe/26255,EDGcpfe/27544]
Range-based for-loop initializer not constant evaluated

Consider:

  consteval int f() {
    int arr[] = { 1, 2, 3 };
    for (int k = 0; int x: arr)
      arr[k++] += 1;
    return arr[1];
  }
  static_assert(f() == 3);

Previously this failed, with a spurious diagnostic suggesting that k is a
run time variable.  This was due to the front end failing to evaluate the
"int k = 0;" of the range-based for-loop.  That is now fixed.


8/27/24  [EDGcpfe/27542]
C++-generating back end: template parameter name omitted as qualifier

In cases where a template parameter is unnamed in the first declaration of
a template but is named in the template's definition and then used in a
qualified name, the changes for EDGcpfe/27409 (not in a release, but
distributed in patch form) introduced a regression in which the
C++-generating back end omitted the qualifier in the generated code.  This
is now fixed.  For example:

  template <class, bool> void a();
  template <class T, bool> void a() {
    auto x = T::template f<bool>();   // Previously omitted "T::"
  }


8/27/24  [EDGcpfe/24216,EDGcpfe/25455,EDGcpfe/26447]
Access to uninitialized memory during constant evaluation with union values

Consider:

  struct S {
    constexpr virtual int f() { return 42; }
  };
  union U {
    int i;
    S s;
  };
  constexpr int g() {
    U u { .i = -1 };
    u.s = S();
    return u.s.f();
  }
  static_assert(g() == 42);

This example previously often resulted in an abort in adjust_virtual_callee
(interpret.c).  The cause of this abort was the assignment "u.s = S();", which
did not fully initialize the class value metadata associated with the newly-
activated subobject u.s.  The call u.s.f() then accessed that uninitialized
metadata.  This is now fixed.


8/26/24  [EDGcpfe/27541]
C-generating back end: negative results of bit operations

In cases where a bit operation (or, exclusive or, etc.) on constant values
produces a signed negative result, the C-generating back end previously put
out the folded constant value of the operation in hexadecimal notation,
resulting in the literal being interpreted as unsigned rather than signed
when the generated code was compiled.  This is now fixed, and such constants
are now put out in decimal notation.  For example:

  long one = 1L;
  int i = (0L ^ (-9L)) > one;  // Folded constant previously put out as
                               // "0xfffffffffffffff7L", now as "-9L"


8/26/24  [EDGcpfe/27262,EDGcpfe/27540]
GNU C++ compatibility: Trailing return types

When declaring a function with a trailing return type, the type preceding the
declaration must be just "auto".  However, GCC also accepts "const" and
"volatile" qualifiers on that "auto", and the front end now emulates that
behavior with a warning.  For example:

  auto const g()->int;  // Ordinarily an error, but now accepted in GNU C++
                        // mode with a warning.


8/26/24  [EDGcpfe/18955,EDGcpfe/27415]
Spurious error on template keyword following global namespace qualifier

Previously, the front end issued a spurious error when the template keyword
followed the global namespace qualifier.  For example, with --c++11:

  template<typename>
  struct S {};
  ::template S<void> s;  // Previously a spurious error.  Now okay.


8/23/14  [EDGcpfe/27534]
Referencing previously freed memory causes undefined behavior

When MAKE_FRONT_END_CALLABLE is TRUE the use of portable assemblies for
CPP/CLI processing had caused the inadvertent use of previously-freed memory,
resulting in undefined behavior.


8/23/24  [EDGcpfe/25990,EDGcpfe/26241,EDGcpfe/27252,EDGcpfe/27335,
          EDGcpfe/27447]
Parenthesized initialization of aggregates in new expressions

C++20 allows parenthesized initialization of aggregates (see the changes for
EDGcpfe/20913 in version 5.1).  However, for new expressions, this feature was
previously implemented only for array types in non-substitution contexts.  For
example, with --c++20:

  struct C {
    int i, j;
  };
  C *c = new C(1, 2);  // Previously a spurious error.  Now okay.


8/22/24  [EDGcpfe/27526]
Abort on friend function noexcept specification with exceptions disabled

With the changes for EDGcpfe/23420,EDGcpfe/26014,EDGcpfe/26353 (in version
6.5), the front end aborted with a null-pointer indirection in
scan_noexcept_arg when parsing a noexcept specification of a friend function
declaration in modes with exceptions disabled and where the exception
specification is not part of the function type.  For example, with --c++14
--no_exceptions:

  struct C {
    friend void f(const C &) noexcept(true)  // Previously aborted.  Now okay.
    {}
  };


8/20/24  [EDGcpfe/27513]
Abort on lowering delete operators

In configurations where IA64_ABI is FALSE and DELETE_CAN_BE_FOLDED_INTO_DTOR
and LOWERING_REMOVES_UNNEEDED_CONSTRUCTIONS_AND_DESTRUCTIONS are both TRUE,
missing skip_typerefs had caused undefined behavior in some cases in
lower_delete.  For example, with --c++17:

  struct B {
    ~B() noexcept(false) { }
  };
  using C = B;
  void f(C *c) {
    delete c;  // Previously triggered undefined behavior in some
  }            // configurations.


8/19/24  [EDGcpfe/27511]
Clang compatibility: __is_trivially_relocatable

In Clang C++ modes with clang_version >= 150000, the front end now supports the
__is_trivially_relocatable type traits helper.


8/15/24  [EDGcpfe/27282,EDGcpfe/26417]
Multi-TU memory region management fixes

A number of changes (across multiple areas in the front end) have been made to
improve stability and correctness when compiling under multi-TU mode.

A new validation system has been added under EXPENSIVE_CHECKING to ensure
symbols with associated IL entries resolve the translation unit (through
decl_scope) to the correct translation unit (i.e., the translation unit the IL
entry was allocated in).  Additional checks were added to ensure IL entries are
not retrieved, through symbols, from memory regions that have been freed.  In
configurations with EXPENSIVE_CHECKING set to TRUE, this checking can be very
slow and can therefore be disabled via --set_flag no_very_expensive_checking.


8/14/24  [EDGcpfe/25931]
GNU mode specifier attributes

Consider in GNU C++ mode:

  struct S {
    inline __attribute((unrecognized_attr)) S() {}
  };

The attribute in this example is a "specifier" attribute because it appears
among the declaration specifiers of the constructor.  However, since there is
no type among those specifiers, it cannot be associated with a specified type
and the front end "lost" the attribute even in configurations with the macro
RECORD_UNRECOGNIZED_ATTRIBUTES set to TRUE.  Now, such attributes are treated
as "prefix" attributes instead, which causes them to be associated with the
declared entity (the constructor in this case).


8/13/24  [EDGcpfe/16584,EDGcpfe/18624,EDGcpfe/22946,EDGcpfe/24587,
          EDGcpfe/25811]
Overload resolution with non-final parameter packs

Consider:

  template<typename T, typename ...Ts> int f(T, Ts..., int = 32);
  int r = f(42);  // Previously an error.  Now okay.

Previously, this resulted in an error because overload resolution did not
correctly handle function parameter packs that are followed by additional
parameters.  That is now fixed and the example is now accepted.


8/13/24  [EDGcpfe/27507]
Clang compatibility: Clang 19 intrinsics

A number of new type trait intrinsics are now available in Clang mode.
Specifically, __is_layout_compatible, __is_pointer_interconvertible_base_of,
__is_nothrow_convertible, and __reference_converts_from_temporary are now
enabled for Clang 19.  Additionally, __is_scoped_enum is now enabled for Clang
16.


8/12/24  [EDGcpfe/22821,EDGcpfe/27314,EDGcpfe/27438]
Substitution of member function template trailing requires clauses

Previously, a trailing requires clause of a member function template was
instantiated together with the definition of the enclosing class template
specialization.  That in turn could result in spurious errors.  Now,
substitution into the trailing requires clause is only performed during
constraint checking.  For example, with --c++20:

  template<typename U>
  struct A {
    template<typename T>
    static int f(T t) requires (sizeof(U) > 1);  // Previously a spurious
                                                 // error.  Now okay.
    static int f(long);
  };
  int i = A<void>::f(0);


8/9/24   [EDGcpfe/24661,EDGcpfe/25843]
GNU C++ compatibility: Functional-notation cast of braced initializer

Consider:

  #include <initializer_list>
  struct X { X(int); };
  struct S {
    S(int) = delete;
    S(std::initializer_list<X>);
  };
  S s = S({5});  // Now accepted in GNU C++ modes.

Ordinarily, the deleted S::S(int) constructor is preferred by overload
resolution, which causes the example to be invalid.  However, GCC prefers the
initializer-list constructor here, and the front end now emulates that
behavior.


8/8/24   [EDGcpfe/27485]
Spurious error on selection from a dependent expression naming a reference

Consider:

  template<typename T> void g(T &p) {
    decltype(p) &rp = p;
    rp->m;  // Previously an error.  Now okay.
  }

Previously, the front end issued a spurious error complaining the selection
rp->m was from a T& type instead of a pointer type (when, in fact, T could be
a pointer type).  That is now fixed.


8/8/24   [EDGcpfe/17472,EDGcpfe/24212,EDGcpfe/25603,EDGcpfe/27479]
Constraints on C-style variadic function arguments and designated initializers

In C++11, C-style variadic arguments of class type must be trivially copyable,
but the front end previously applied a more stringent constraint on such
arguments.  For example:

  #include <stdarg.h>
  struct S { int x = 42; };
  void g(char *fmt, ...) {
    va_list  ap;
    va_start(ap, fmt);
    S val = va_arg(ap, S);  // Previously an error.  Now accepted.
    va_end(ap);
  }

S here is trivially copyable, but the front end previously did not accept the
example.  Now it does.  A similar relaxation applies to designated
initializers.


8/7/24   [EDGcpfe/27463]
Values of _Float16 literals

The front end previously handled _Float16 literals incorrectly when their
values are close to the maximum representable value for the type.  In
particular, such hexadecimal _Float16 literals were incorrectly reported as
being out of range.  Also, in some configurations, large _Float16 decimal
literals were given incorrect values.  These issues are now fixed.  For
example:

  auto x = 0x1.ffb8p+15f16;   // No longer a spurious error
  auto y = 65501.0f16;        // Now has the correct value (i.e., rounded to
                              // 65504) in all configurations


8/5/24   [EDGcpfe/27458]
Compile time checking of front end arrays

Arrays with external linkage in the front end are now declared with
EXTERN_CONSTINIT_ARRAY and EXTERN_CONSTINIT_ARRAY_END.  These macros provide
compile time checks to ensure all array elements have been initialized
(replacing the previous runtime checking strategy).


8/2/24   [EDGcpfe/26602,EDGcpfe/27497]
Destructor instantiation not performed when using default member initialization

Previously, a template instantiation's destructor would not be instantiated
if the following conditions were met:

  // There must be a default member initialization that uses a class
  // template with a user defined destructor.
  template<typename T>
  struct X { ~X() {} };
  struct Y { X<int> z = {}; };
  // The TU must include only objects with dynamic storage duration for the
  // initializing type (Y).  If a destructor call for the initialized type (X)
  // is present (explicitly or implicitly -- via an object with static, thread,
  // or automatic storage duration), this bug does not occur.
  Y* alloc_y() { return new Y(); }

This is now fixed and the destructor is now (consistent with other
initialization mechanisms) always instantiated for default member
initialization.


8/1/24   [EDGcpfe/27469]
Parameter variables of generated comparison functions

The parameter variables of generated comparison function definitions failed to
record the a_variable::variant.assoc_param_type field.  That is now fixed.


8/1/24   [EDGcpfe/27489]
C++-generating back end: empty braced list in braced initializer

In some cases in which an empty braced list appears as part of an
initializer list, the C++-generating back end could omit the empty braces
in the generated code.  This is now fixed.  For example, with --c++11:

  struct A {
     A() = default;
     constexpr A(int i) noexcept: m(i) {}
     int m;
  };
  struct B {
     int i;
     A a;
     const char *s;
  };
  constexpr B f(const char *s) {
     return { 0, {}, s };   // Previously generated as { 0, s }
  }


7/31/24  [EDGcpfe/27466]
Spurious incomplete type error on GNU-mode static data member initializer

Consider, in GNU C++17 mode:

  template<typename> struct X {
    int i;
    X& f();
  };
  template<typename T> struct S {
     static inline X<T> x{42};
  };
  auto r = S<int>::x.f();

Previously, this elicited a spurious error claiming that X<int> is incomplete
while processing the initializer for S<int>::x.  That is now fixed.


7/31/24  [EDGcpfe/26750,EDGcpfe/27494]
Failure to destroy sub-arrays in constant evaluation

Consider, in C++23 mode:

  #include <string>
  template <typename T, int N> struct Array { T elems[N]; };
  constexpr bool g() {
    Array<std::string, 3> arr{"one", "two", "three"};
    return true;
  }
  static_assert(g());  // Previously an error.  Now okay.

Previously, this example resulted in a spurious error because the constant
evaluation interpreter only invoked the destructor for the first element of
the array subobject in arr.  That is now fixed.


7/31/24  [EDGcpfe/27491]
Type of floating point literals with f16 suffix

In non-GNU C++23 mode, the front end previously considered floating point
literals with the f16/F16 suffix to have the pre-C++23 _Float16 type
instead of the correct std::float16_t type.  This is now fixed.  For
example, with --c++23:

  decltype(0.0f16) x = 0.0;   // Previously accepted, now an error


7/31/24  [EDGcpfe/27468]
C++-generating back end: stack overflow with out-of-class template member
definition

In certain complex cases in which a member of a class template is defined
outside the class template definition and the type of the member involves a
name that is inaccessible to non-members, the C++-generating back end could
enter an unbounded recursion generating the member definition.  This is now
fixed.


7/30/24  [EDGcpfe/27455]
Microsoft-mode abort assigning a braced construct to a property field

Consider, in Microsoft C++ mode:

  struct S {
    void f(int);
    __declspec(property(put = f)) int prop;
  };
  void g(S &s) {
    s.prop = {};  // Previously aborted.  Now okay.
  }

Previously, this elicited an internal error in alloc_arg_list_elem_for_operand
(in exprutil.c).  That is now fixed.


7/30/24  [EDGcpfe/26252,EDGcpfe/27023,EDGcpfe/27454]
Lifetime of array prvalue during constant evaluation

When evaluating the array-to-pointer conversion of an array prvalue (which is
a somewhat unusual expression), the front end often recorded an incorrect
lifetime for the array, which in turn could lead spurious diagnostics (because
the array was erroneously treated as having expired).  That is now fixed.


7/30/24  [EDGcpfe/27409]
IA-64 ABI: Invalid mangled name generated for template parameter object

The IA-64 ABI mangled name for a template parameter object had inadvertently
contained the string "<templ-param-object>" in some cases and is now fixed.
For example (with --c++20):

  auto lambda = [](int) { return 0; };
  template<auto F, class T> using TA = decltype(F(T()));
  template<class T = int> TA<lambda, T> f();
  auto var = f();


7/30/24  [EDGcpfe/27175]
Negative offsets in __INTADDR__(...)

The changes for EDGcpfe/18070 introduced a regression in version 5.0 for
__INTADDR__(...) constructs that would produce a negative offset.  For
example, in C++11 mode:

  #define offsetof(T, member)  (__INTADDR__((&((T *)0)->member)))
  struct S {
    int  x[2];
  };
  int r = offsetof(struct S, x[-1]);

Prior to version 5.0, this example was accepted (with warnings), but more
recent versions issued an error.  The constant-evaluation interpreter has now
be updated to allow this case as well.  (See the changes for EDGcpfe/21926
for a related issue.)


7/30/24  [EDGcpfe/26483]
Clang compatibility: Additional builtins for Clang version 19.1.0

Additional builtin signatures have been added for Clang 19.1.0 (based on the
recently-released RC1).


7/30/24  [EDGcpfe/26486]
GCC compatibility: Incorrect builtin signatures for ARM

Previously, the builtin signatures for __builtin_coro_done and
__builtin_coro_promise were missing for GCC on ARM.  Additionally, the ARM NEON
vector type __Uint16x8_t was inadvertently recorded as __Uint16x4_t in the
signature definitions for 64-bit ARM platforms.  These are now fixed.


7/27/24  [EDGcpfe/26451]
C++26: Non-encodable character and string literals

C++ Committee paper P1854R4 makes it an error for character or string
literals to contain a character that cannot be represented in the literal's
character encoding.  The paper was adopted for C++26 and as a defect
report, i.e., applying to previous versions of C++ as well.  At this time,
the latest versions of g++, clang, and MSVC do not completely implement
these restrictions, so the front end applies them in strict mode with
appropriate relaxations in the various emulations.  For example, with
--c++23 --strict:

  int f = '\U0001F602';  // Previously a multi-character literal, now an error


7/26/24  [EDGcpfe/27249,EDGcpfe/27478]
Handling of inline static data members in class templates

An inline static data member is considered defined in a class template, and
its definition should only be instantiated when used.  Previously, the front
end instantiated inline static data members in class templates along with the
parent template class by default.  Consider:

  template<typename = void> struct S {
    S();
    static inline S s;
  };
  template<> inline S<>::S() {}  // Previously an error.  Now okay.

This previously elicited an error because "S<>::" triggered the instantiation
of S<void>, and the member S<void>::s was required to be complete before the
instantiation of S<void> was complete.  That is now fixed: The instantiation
of S<void>::s is not performed and thus its type need not be complete.


7/26/24  [EDGcpfe/26577,EDGcpfe/27396]
Abort on pack expansion in concept template argument list

Previously, the front end failed to correctly expand parameter packs when
disambiguating between a type-constraint and a concept-id, which could result
in an error type entry being inserted into the IL tree.  In some
configurations, that error type entry reached the mangling routines and
triggered an assertion failure in record_substitution_for_type.  For example,
with --c++20:

  template<typename ...> concept X = true;
  template<typename> struct C {};
  template<typename ... Us>
  void f() {
    X<C<Us> ...>;  // Previously triggered an assertion failure.  Now okay.
  }
  template void f<>();


7/25/24  [EDGcpfe/27408]
Fold-expressions in Microsoft nonreal base instantiations

In Microsoft mode, the front end performs "nonreal instantiations" of dependent
base class types (this is a process unique to Microsoft mode, used to better
approximate some behaviors of MSVC).  Previously, fold-expressions occurring
during that process resulted in spurious errors.  For example:

  template<typename T> struct S {};
  template<typename... Ts> struct B {
    static constexpr bool F = ((S<Ts>::m) || ...);
  };
  template<class T1, class T2> struct D: B<T1, T2> {};

Previously, that example triggered spurious errors in the attempted expansion
of the fold-expression while instantiating B<T1, T2> with generic T1 and T2
types.  That is now fixed.


7/25/24  [EDGcpfe/27405]
Spurious error on nested unions

Consider:

  union {
    union { int x = 42; };
  } u;  // Previously an error.  Now okay.

The front end previously erroneously concluded that the outer union's default
constructor is deleted.  That is now fixed.


7/24/24  [EDGcpfe/26322,EDGcpfe/26494,EDGcpfe/27098]
Abort on non-dependent specialization of constrained member template

Previously, when a template definition referred to a non-dependent
specialization of a constrained member template, the front end aborted with a
failed assertion in get_substitution_pairs_for_template_class (or, with the
changes for EDGcpfe/27472, in get_all_class_subst_pairs).  For example, with
--c++20:

  template<typename> concept X = true;
  template<typename>
  struct C {
    template<X> struct B {};
    B<int> b;  // Previously triggered an internal error.  Now okay.
  };


7/24/24  [EDGcpfe/27472]
Expansion of enclosing pack in constraint in out-of-class template definition

Previously, when a constraint in an out-of-class definition of a member
template referred to an enclosing parameter pack, that pack was not expanded
during constraint checking.  For example, with --c++20:

  template<int I, typename... Ts> concept X = sizeof...(Ts) == I;
  template<typename ... Vs>
  struct C {
    template<int J> struct D;
  };
  template<typename ... Us> template<int I>
  struct C<Us ...>::D {
    int f() requires X<I, Us ...>;
  };
  int i = C<int, char>::D<2>().f();  // Previously a spurious error.  Now okay.


7/23/24  [EDGcpfe/27456]
C++26: constexpr structured bindings

In C++26 mode, the front end now accepts constexpr structured bindings,
including the case of bindings for tuple-like types.  That support includes
allowing constexpr references to local variables.  For example:

  void f() {
    constexpr int i = 42;
    constexpr int const &r = i;  // Now accepted in C++26 mode.
    static_assert(r == 42);
  }

This implements the proposal in the standardization committee's paper P2686R4.
Since that paper has not been voted into the draft for the next standard, it
is possible that the feature will not actually make it in C++26 (although the
paper has progressed through most of the standardization process and is
expected to be approved in the relatively near future).


7/23/24  [EDGcpfe/27470]
Assertion failure in get_token_with_colon_separation

When parsing some asm constructs in GNU emulation mode, an assertion failure
(in get_token_with_colon_separation) had occurred in C23 mode.  For example
(with --gcc --c23):

  void f(const void *__config) {
    __asm__ ("ldtilecfg\t%X0" ::"m"(*((const void **)__config)));
  }


7/22/24  [EDGcpfe/27459]
Checking the argument count before validating deduced parameter types

The changes for EDGcpfe/26586 in version 6.6 caused the completeness of deduced
parameter types to sometimes be checked before ensuring that the number of
arguments matches the number of parameters.  A mismatch for the number of
arguments leads to a deduction failure, but checking the completeness of
deduced parameter types can lead to a hard error, and thus the change for
EDGcpfe/26586 introduced regressions in some cases.  That is now fixed.


7/22/24  [EDGcpfe/27465]
GNU compatibility: Update builtin signatures to 11.5.0

Two builtins (__builtin_ia32_ldtilecfg and __builtin_ia32_sttilecfg) were added
between GNU 11.4.0 and 11.5.0.  The builtin signatures have been updated
accordingly.


7/19/24  [EDGcpfe/27400]
Microsoft compatibility: __has_trivial_assign

Consider:

  struct S {
    S& operator=(S&) = default;
  };
  static_assert(__has_trivial_assign(S));  // Now fails in Microsoft mode.
 
S::operator= is a trivial copy assignment operator and so ordinarily the
static assertion in the above example succeeds.  MSVC, however, does not
accept the assertion because the parameter type of S::operator(S&) is S&
instead of the more common S const&.  The front end now emulates that behavior
in Microsoft bugs mode (but still marks the operator as trivial).


7/19/24  [EDGcpfe/27397]
Incorrect constant-evaluation of real-to-complex conversion

Consider, in GNU C++ mode:

  constexpr auto g() {
    float f{1};
    _Complex double cx{1};
    return cx / f;  // Previously incorrectly evaluated.  Now okay.
  }
  constexpr auto r = g();

This example previously failed to evaluate to a constant expression, due to
the incorrect evaluation of the implicit conversion of f from "float" to
"_Complex double".  That is now fixed.


7/19/24  [EDGcpfe/27389]
Incorrect handling of concept in unnamed namespace

Consider, in C++20 mode:

  namespace N {
    namespace {
      template <class, class> concept c = true;
    }
    class S {
      template<typename T> static constexpr bool b = N::c<T, T>;
    };
  }

The front end previously did not recognize the angle bracket following N::c
(while caching the initializer for S::b), instead treating it like a "less
than" operator.  That in turn resulted in misleading spurious errors.  That
problem is now fixed.


7/16/24  [EDGcpfe/25411,EDGcpfe/26809,EDGcpfe/27388]
Abort on unusual C++ coroutine type

In the unusual case of a coroutine with a non-class return type, the front end
was likely to abort in a call to select_overloaded_copy_constructor.  That is
now fixed.


7/11/24  [EDGcpfe/27091,EDGcpfe/27095]
GNU C++ compatibility: List-initialization in C++03 modes

The front end now accepts list-initialization constructs with a warning in GNU
C++03 modes.  Narrowing conversions are not checked (unlike C++11 mode).


7/11/24  [EDGcpfe/25950,EDGcpfe/26287,EDGcpfe/27445]
C23: nullptr keyword and nullptr_t type

The nullptr keyword and nullptr_t type, as described in C Committee
document N3042, are now enabled in C23 mode.  In addition, the nullptr
keyword (but not the nullptr_t keyword, to avoid collisions with
user-declared identifiers) is enabled in pre-C23 modes when the --nullptr
command-line option is specified (it was previously disallowed in C
language modes).  For example, with --c23:

  void *p = nullptr;
  void f(nullptr_t);


7/11/24  [EDGcpfe/27200]
Performance improvements for find_allocated_name_reference

Previously, find_allocated_name_reference performed a linear search on the list
of name references to check for duplicates, which could take a significant
amount of time with long lists.  This has now been addressed by using a hash
table for the duplicate entry check.


7/10/24  [EDGcpfe/27429]
C++-generating back end: differing default arguments in alias template and
underlying type

In cases where an alias template and a template appearing in its type-id
have differing default arguments, the output of the C++-generating back end
could sometimes replace a use of the alias template with its underlying
type while omitting the differing default template argument, thus referring
to an incorrect template instance.  This is now fixed.  For example, with
--c++17:

  struct A;
  template <typename, typename = A> struct B {
    using b = int;
    B(b);
  };
  template <typename T, typename U = int> using C = B<T, U>;
  template <typename T> C<T> f() {
    return C<T>(0);   // Previously generated as "(B<T>)0", which is equivalent
                      // to (B<T,A>)0 instead of (B<T,int>)0
  }


7/10/24  [EDGcpfe/27425]
C++-generating back end: template arguments using out-of-scope variables

In general, the IL for a template instance reflects the template arguments
used in the first reference to that instance.  When a non-type template
argument involves a local constexpr variable and a reference to that
instance appears in a different scope, the C++-generating back end attempts
to use the variable's initializer in place of the variable name in the
generated code.  In some cases involving braced initializers, however, the
generated code previously failed to make the type of the initializer
explicit, resulting in code that could not be compiled.  This is now fixed.
For example, with --c++17:

  template <bool B> constexpr bool b = B;
  template <typename T> constexpr bool f(const T&) {
    return true;
  }
  struct S {
    int i;
  };
  constexpr bool g1() {
    constexpr S s{ 1 };
    return b<f(s)>;     // Instance is b<true>, argument recorded as "f<s>"
  }
  constexpr bool g2() {
    return b<true>;     // Previously generated as b<f({1})>, now b<f(S{1})>
  }


7/9/24   [EDGcpfe/27287]
GNU/Clang compatibility: __c11_atomic_is_lock_free

The front end now folds certain calls to the built-in function
__c11_atomic_is_lock_free, in both C and C++ modes.


7/9/24   [EDGcpfe/27288]
GNU/Clang compatibility: array-to-pointer decay on sync builtins

A missing array-to-pointer decay had caused spurious errors when using an
array type as the first argument to some GCC/Clang builtins.  For example,
with --clang:

  void f() {
    _Atomic(int) i[2];
    __c11_atomic_init(i, 0);
    __c11_atomic_load(i, 0);
  }


7/9/24   [EDGcpfe/26511,EDGcpfe/27370]
C++-generating back end: pragmas in template definitions

In configurations in which template definitions are generated from the
prototype instantiation IL, pragmas appearing within template definitions
were omitted in the output of the C++-generating back end.  This is now
fixed.  For example, with --g++ in a configuration in which
INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL is TRUE:

  template <typename T> void f(T x) {
  // Previously omitted the following pragma:
  #pragma omp parallel for num_threads(8)
    for (int h = 0; h < x; h++) { }
  }
  void m() {
    f(16);
  }


7/8/24   [EDGcpfe/27433]
Missing generated constructor definition for constant evaluation

In somewhat unusual cases, the front end failed to produce a definition for a
generated copy constructor that is needed for constant evaluation.  That in
turn caused the constant evaluation to fail and errors to ensue.  This is now
fixed.


7/8/24   [EDGcpfe/27439]
Microsoft-mode abort on copy of closure object

Consider, in Microsoft mode:

  class C {
    template<typename T> C(T);
    using Alias = C&&;
    void f() {
      Alias([]{});  // Previously triggered an internal error.  Now okay.
    }
  };

This previously triggered an internal error in conv_glvalue_expr_to_prvalue.
The underlying reason for this is that in Microsoft mode, a lambda expression
(which is a prvalue) can be converted to a corresponding glvalue, but the
conversion back to a prvalue was (accidentally) not supported.  This particular
example exercises the back-and-forth conversion, thus triggering an internal
error.  This is now fixed.


7/8/24   [EDGcpfe/27266,EDGcpfe/27434]
Clang compatibility: __ext_vector_type__ attribute in alias declarations

The Clang-specific __ext_vector_type__ attribute was previously only allowed
on typedef declarations and is now also accepted on alias declarations.
For example, with --clang:

  using FourShorts = short __attribute__((ext_vector_type(4)));


7/6/24   [EDGcpfe/27430]
C++-generating back end: unnamed class/enum types in variable initializers

In cases where an unnamed class or enumeration type is used in the type of
a variable and the variable's initializer uses a decltype specifier
referring to that variable, the C++-generating back end previously put out
an undeclared temporary name (of the form __T12345678) in place of the
decltype specifier.  This is now fixed.  For example, with --c++17:

  char a[99];
  union {
    int i;
    const char *p;
  } &u = (decltype(u))a;   // Previously generated as "u = (__T12345678)a"


7/4/24   [EDGcpfe/27289]
Spurious error on assignment with dependent class member access expression

Consider, with --c++14:

  template<typename T> T g();
  template<typename T> struct A {
    int m;
    int f() {
      return g<A &>().A::m = 1;  // Previously a spurious error.  Now okay.
    }
  };
  int i = A<int>().f();

Because the left operand of the class member access expression is still
type-dependent at template definition time, its value category can't be
determined yet.  However, the front end previously treated the class member
access expression as a non-dependent xvalue of type "int", thereby eliciting an
error for using an xvalue on the left-hand side of an assignment operator.


7/3/24   [EDGcpfe/27390,EDGcpfe/27417]
Errors or aborts on Clang enable_if attribute

Some spurious errors and potential aborts during the evaluation of a Clang
enable_if attribute have been fixed.  For example:

  __attribute__((enable_if(true, ""))) unsigned f(int);
  template<int> struct S {
    static int s;
    static constexpr int N = f(s);  // Previously triggered a spurious error.
  };                                // Now okay.


7/3/24   [EDGcpfe/27422]
C++26: Deleting a pointer to an incomplete type

In C++26 mode, deleting a pointer to an incomplete type is now a discretionary
error instead of a warning.  For example:

  void f(struct S *p, struct S *q) {
    delete p;    // An error in C++26 mode.  A warning otherwise.
    delete[] q;  // Ditto.
  }

(This implements the C++ standardization committee's paper P3144R2.)


7/3/24   [EDGcpfe/27427]
Microsoft compatibility: -0 as a null pointer constant

It appears that MSVC accepts -0 as a null pointer constant even in its non-
permissive mode.  The front end now emulates that behavior in non-permissive
Microsoft modes.  (The same applies to expressions of the form +0 and ~~0.)


7/3/24   [EDGcpfe/27338]
Casts to incomplete types in substitution contexts

Consider, in C++20 mode:

  template<class T> constexpr bool x = requires (T x) { (struct c)x; };
  static_assert(!x<int>);

Previously, the front end issued an error because of the attempt to cast to an
incomplete (non-dependent) class type.  That error was issued when parsing the
variable template (i.e., before substituting the requires-expression) since the
cast can never be valid.  However, MSVC, GCC, and Clang all accept such code
and the front end therefore now also accepts it in nonstrict modes.


7/3/24   [EDGcpfe/27420]
GCC compatibility: class template argument deduction for alias templates

Consider, with --c++20 --g++:

  template<int, int> struct D;
  template<typename> struct C {};
  C() -> C<D<1, 2>>;
  template<int I> using A = C<D<I, +I>>;
  A a{};  // Now accepted in GNU mode.

When using the deduction guide to deduce the type of "a", the C++ Standard
requires the template arguments of the alias template to be deducible from the
return type of that deduction guide.  GCC considers the template arguments to
be deducible, even though substituting the deduced arguments into the alias
template yields a different type.  The front end now emulates that behavior.


7/3/24   [EDGcpfe/27406]
Abort on class template argument deduction for alias templates

In modes where the deduced type of a deduction guide can include CV qualifiers
or name an alias template specialization, forming the guides for an alias
template previously resulted in an incorrect variant access.  For example, with
--c++20 --g++:

  template<typename> struct C {
    C(int);
  };
  template<typename T> C(T) -> const C<void>;
  template<typename T> using A = C<T>;
  A a{1};  // Previously triggered an abort.  Now okay.


7/2/24   [EDGcpfe/27263]
Abort when using an array with a local element type as a template argument

Consider:

  template<typename T> inline T* get_ptr();
  template<typename T> T* g(T&) {
    using local_t = typename T::Type;
    constexpr auto N = T::Count;
    return get_ptr<local_t[N]>(); // Previously triggered an abort.  Now okay.
  }

Previously, this elicited an abort in the C++-generating back end (when calling
function form_array_declarator).  That is now fixed.


7/2/24   [EDGcpfe/27416]
Microsoft compatibility: macro expansion of pragma names

Except for standard pragmas, where the "STDC" string must be recognized
even if there is a macro definition for STDC in effect, it is
implementation-defined by the C and C++ Standards whether the preprocessing
tokens of a pragma directive are subject to macro expansion.  Previously,
the front end did not expand macros when determining the pragma name.  MSVC
does do so, however, even for STDC, so the front end has now been changed
to follow suit in Microsoft mode.  For example, with --microsoft:

  #define c pack(1)
  #pragma c
  struct e {
    char o;
    int r;
  };
  static_assert(sizeof(e) == 5);   // Previously failed, now okay


7/1/24   [EDGcpfe/27410]
Microsoft compatibility: _RESUMABLE_FUNCTIONS_SUPPORTED macro

The _RESUMABLE_FUNCTIONS_SUPPORTED macro is no longer defined when the
--ms_await_strict command-line option is specified.


6/28/24  [EDGcpfe/27407]
Unbounded loop in form_exception_specification

In some complex cases the front end could enter an unbounded loop in
form_exception_specification while putting out error diagnostics.  This is
now fixed.


6/25/24  [EDGcpfe/27393]
Clang compatibility: default to C++17 mode when emulating Clang 16.0.0

When emulating Clang 16.0.0 or later and no explicit C++ standard is
specified, the front end now uses C++17 mode by default.


6/21/24  [EDGcpfe/27270]
Spurious bitwise assignment in generated assignment operator

Consider:

  template<typename T> struct I { using Type = T; };
  struct X {
    X& operator=(volatile const X&) = delete;
    template<typename T = X>
        X& operator=(typename I<const T&>::Type);
  };
  struct S { X x; };
  int main() {
    S s;
    s = s;
  }

The copy assignment operator of S erroneously used bitwise assignment for its
subobject S::x when instead it should call an instance of the X::operator=
member template.  This regression, introduced by the changes for EDGcpfe/26518
in version 6.6 of the front end, is now fixed.


6/21/24  [EDGcpfe/27267]
Substitution of nested pack expansions

Previously, the front end failed to substitute into nested pack expansions
during template argument deduction.  For example, with --c++11:

  template<typename ...> struct C {};
  template<typename, typename> struct E {};
  template<typename T, typename ... Us> using A = C<E<T, Us> ...>;
  template<typename ... Ts, typename ... Us, typename = C<A<Ts, Us ...> ...>>
  int f(C<Ts ...>, Us ...);
  int i = f(C<int>{}, 0);  // Previously a spurious error.  Now okay.


6/21/24  [EDGcpfe/27391]
GNU compatibility: Update builtin signatures to 12.4.0

There were a small number of changes to builtin signatures between GNU 12.3.0
and 12.4.0 (builtins __builtin_ia32_ldtilecfg and __builtin_ia32_sttilecfg were
added for the x86-64 architecture, and the return types of __builtin_arm_ssat,
__builtin_arm_ssat16, and __builtin_arm_usat16 were changed to int for the
ARM32 architecture).  The builtin signatures have been updated accordingly.


6/20/24  [EDGcpfe/27364]
Assertion failure on ill-formed #pragma GCC visibility pragmas

An assertion failure (in process_immediate_pragmas) had triggered on some
ill-formed GCC visibility #pragmas as a result of the changes for EDGcpfe/26419
(in version 6.6).  Now fixed.  For example, with --g++:

  #pragma GCC visibility push(
  #pragma GCC visibility push(hidden


6/20/24  [EDGcpfe/25510]
C++23: Delimited escape sequences

C++ Committee paper P2290R3 added delimited escape sequences for octal
(\o) and hexadecimal (\x) numeric escapes and universal-character-names
(\u).  The front end now accepts these escape sequences in C++23 mode and
in GNU mode (when gnu_version is at least 130000) and clang_mode (when
clang_version is at least 140000).  For example, with --c++23:

  const char8_t *u = u8"\u{a01}";
  const char *o = "\o{123}";
  const char *x = "\x{ab}";


6/20/24  [EDGcpfe/27273]
Substitution of default template argument in template template argument

Consider, with --c++17:

  namespace ns {
    template<typename> struct D {};
    template<typename T, typename = D<T>>  // Previously a spurious error.
    struct C {};                           // Now okay.
  }
  template<template<typename> typename W, typename T>
  W<T> g();
  auto v = g<ns::C, int>();

Previously, when substituting into the return type of g, substitution of the
default argument of ns::C was performed in the context of the declaration of W
instead of the context of ns::C.  This is now fixed.


6/20/24  [EDGcpfe/27268]
C++-generating back end: constructors with reference to initializer_list

The C++-generating back end previously put out an extra set of braces when
a variable initializer is brace-enclosed and the parameter of the matching
constructor is a reference to an instance of std::initializer_list.  This
is now fixed.  For example, with --c++11:

  #include <initializer_list>
  struct S {
    S(const std::initializer_list<int>&);
  };
  S s{0};   // Previously generated as s{{0}}


6/19/24  [EDGcpfe/23516,EDGcpfe/27371]
Microsoft compatibility: dllexport and function instantiation

The front end previously instantiated member functions of template classes
that are marked dllexport (in Microsoft C++ mode).  It no longer does that.
For example:

  template<typename> struct __declspec(dllexport) S {
    void f() { undefined_id; }
  };
  S<int> si;  // Previously triggered an error.  Now okay.

This example previously elicited an error because S<int>::f() was instantiated
but that instantiation refers to an undeclared identifier.  Now the example
is accepted (S<int>::f() is not instantiated).


6/19/24  [EDGcpfe/27380]
Assignment to const-qualified lvalues in templates

Consider:

  template<class T> struct S {
    int *const p;
    void f() { p = 0; }  // Accepted in some C++ modes.
  };

The changes for EDGcpfe/15398 caused this example to be accepted in Microsoft,
GNU, and Clang C++ modes, despite "p = 0" being an invalid assignment to a
const lvalue.  Now that behavior has been restricted to clang_version < 100000
in Clang C++ mode and gnu_version < 140000 in GNU C++ mode.


6/19/24  [EDGcpfe/26889]
Pointer-to-member with zero-length array member type

In Microsoft C++ modes, the front end sometimes accepts zero-length array
types in class scopes.  Now it also accepts zero-length array types as the
member type for a pointer-to-member type.  For example:

  struct S {};
  typedef int (S::*PMZ)[0];  // Now accepted in Microsoft C++ mode.


6/19/24  [EDGcpfe/24484,EDGcpfe/26840]
Microsoft C++ compatibility: Unnamed enum types

The front end now emulates two nonstandard behaviors of MSVC related to
unnamed enum types that acquire a name for linkage purposes through a typedef.
First, in a case like:

  struct S {
    typedef enum { e } E;
    enum E x;  // Now accepted in Microsoft mode.
    void f() { decltype(e) *p = &x; }
  };

the elaborated type specifier "enum E" is now resolved to the unnamed enum
type that acquired E as a name for linkage purposes.  Second, in a similar
case where the elaborated type specifier appears in a function prototype scope,
a new type is entered into that prototype scope.  For example:

  typedef enum { e } E;
  void f(enum E x) {  // Now accepted in Microsoft mode, creating a new type.
    decltype(e) *p = &x;  // Error: Initializer has incompatible type.
  }


6/19/24  [EDGcpfe/27047]
Performance issue with hashing of template argument lists

Hashing of template argument lists has been further improved (see also the
entry for EDGcpfe/26048,EDGcpfe/26691), particularly for
instantiation-dependent template type arguments.


6/18/24  [EDGcpfe/23571,EDGcpfe/24860,EDGcpfe/25564,EDGcpfe/26798,
          EDGcpfe/27172]
Microsoft C++ compatibility: Friend class name injection

The changes for EDGcpfe/17455,EDGcpfe/17457 disabled friend name injection in
"non-permissive" Microsoft modes.  However, it appears that MSVC still performs
such injections in all modes for ordinary (non-template) friend class
declarations.  The front end has been updated to restore that behavior.


6/17/24  [EDGcpfe/27359]
Pragma not processed following FALSE constexpr if in template

If a template contained a constexpr if with a condition that evaluates to
FALSE and that is immediately followed by a a #pragma, the pragma was not
processed.  Now fixed.

  void g();
  template <typename T> inline void f() {
    if constexpr (0) {
      g();
    }
    #pragma test_next_statement
    for(int i = 0; i < 10; ++i) { g(); }
  }
  int main() {
    f<int>();
  }

6/14/24  [EDGcpfe/27321]
PCH may be created for header with errors

Consider the following code where a template instantiation results in an error:

  template <typename T>
  int foo() { return T::field; }    // error: int does not have a member field
  int doit() { return foo<int>(); }

If instantiate_before_pch_creation is TRUE, previously the PCH file would still
be created despite an error being emitted.  This is now fixed.


6/12/24  [EDGcpfe/25508]
C++23: Unencodable and multi-character wide character literals

C++ Committee paper P2362R3 specified that wide character literals
containing more than one character or a character that cannot be
represented in a single object of type wchar_t are ill-formed; previously
they produced implementation-defined values.  The front end now issues
discretionary errors for such constructs in strict C++23 mode and continues
to issue a warning in other modes.  For example, with --strict --c++23:

  wchar_t a = L'\U0001f926';   // Discretionary error if sizeof(wchar_t) == 2
  wchar_t b = L'ab';           // Discretionary error


6/12/24  [EDGcpfe/27193]
Substitution failure for nested template with default template arguments

Previously, the use of a nested template with default template arguments would
trigger a spurious substitution failure for a variadic function template.  For
example, with --c++11:

  template<typename T>
  struct C {
    template<typename = void> using A = int;
  };
  template<typename T, typename ... Us>
  typename C<T>::template A<> f(Us ...);
  auto v = f<int>();  // Previously a spurious error.  Now okay.


6/12/24  [EDGcpfe/27304]
Abort on substitution of dependent non-type template parameter type

In some cases involving an alias template, the substitution of explicit
template arguments could result in an abort due to a null pointer indirection
in get_template_arg_by_list_pos when substituting the type of a dependent
non-type template parameter.  For example, with --c++11:

  template<typename T, T> struct C {};
  template<typename T> using A = C<T, 0>;
  template<template<typename> class W, typename U> W<U> f(U);
  auto v = f<A>(1);  // Previously aborted.  Now okay.


6/11/24  [EDGcpfe/27363]
Raw string literals, trigraphs, and apparent line splices

In modes in which raw string literals and trigraphs are supported, the
front end previously did not correctly process a raw string literal in
which a line ends with the trigraph representation of a '\', i.e., "??/",
either producing an incorrect value for the raw string literal or aborting
with an assertion failure in conv_string_literal.  For example, with
--c++11:

  // Equivalent to "\?\?/\\\n\?\?", previously produced "\?\?"
  const char a[] = R"(??/
  ??)";


6/11/24  [EDGcpfe/27356]
Template arguments for dependent destructor name

Previously, the front end did not interpret a "<" in a dependent destructor
name as the delimiter of a template argument list.  For example:

  namespace ns {
    template<typename T>
    struct C {};
  }
  template<typename T>
  void f(ns::C<T> c) {
    c.~C<T>();  // Previously a spurious error.  Now okay.
  }


6/10/24  [EDGcpfe/27357]
Rename log2 function in util.h header

The util.h header that is part of the front end source code contained a log2
function template and a use of that template.  However, recent system headers
on macOS contain a similar log2 template that causes an ambiguity for the use
of log2 in util.h.  The version in util.h has been renamed to floor_log2 to
avoid the ambiguity.


6/7/24   [EDGcpfe/24778]
C++23: White space following backslash in line splice

C++ Committee paper P2223R2 specified that a backslash that is followed by
one or more white space characters before the line-ending newline is to be
considered a line splice.  The front end previously treated such sequences
as line splices only in GNU and clang modes, but they are now accepted in
all C++23 emulation modes.  In addition, in modes where such constructs
were recognized as line splices, the front end previously incorrectly
dropped the intervening white space characters from the value of a raw
string literal.  This is now fixed.  For example, lines 2 and 6 of the
following code end in a backslash followed by a space character, a
horizontal tab, a formfeed, and a newline; with --c++23, the code now
compiles without error:

  // Equivalent to "x\\ \t\f\ny"; previously omitted " \t\f":
  constexpr char x[] = R"(x\ 	
  y)";
  static_assert(sizeof(x) == 8 && x[4] == '\f');
  // Now equivalent to "int i = 00;":
  int i = 0\ 	
  0;


6/7/24   [EDGcpfe/27352]
Default member initializers and destructor instantiations

Consider, with --c++11:

  template<typename T> struct X {
    ~X() { sizeof(T); }
  };
  struct Undefined;
  struct S {
    X<Undefined> m = {};  // Previously an error.  Now okay.
  };

Previously, this elicited an error from the front end because the destructor
needed for the destruction of S::m was instantiated when parsing the default
member initializer.  Now, that instantiation is delayed until the destructor is
actually needed.  (See also the entry for EDGcpfe/24790,EDGcpfe/25149, which
covers the similar case for direct-list-initialization.)


6/6/24   [EDGcpfe/27350]
GNU compatibility: Spurious diagnostics for some function multiversion cases

Spurious diagnostics had been issued in some configurations when compiling
a case like this (with --gnu_version 50000):

    #pragma GCC target("xyzzy")
    void f() {}     // Had issued four diagnostics for an unknown target,
                    // now issues just one.


6/6/24   [EDGcpfe/27225]
Mangling for _Complex _Float32x and _Complex _Float64x

The mangling for _Complex _Float32x and _Complex _Float64x types had been
omitted previously (leading to an assertion failure in
mangled_encoding_for_type_full).  That has now been fixed.  For example
(with --gnu_version 130000):

  void f(_Complex _Float32x) {}
  void f(_Complex _Float64x) {}


6/4/24   [EDGcpfe/25980,EDGcpfe/26692]
Incorrect type for conditional operator

In some cases where the second and third operands of the conditional operator
are a cv-qualified glvalue of enum type and a prvalue of that enum type, the
front end previously used the promoted integral type as the result type.  For
example, with --c++11:

  enum E { E0, E1 };
  const E &e0 = E0;
  E e = true ? e0 : E1;  // Previously a spurious error.  Now okay.


6/3/24   [EDGcpfe/27177]
GNU C++ compatibility: Variable templates in alias template definitions

GCC appears to not always substitute nondependent template arguments in
variable templates if such a combination appears in an alias template
definition.  The detailed behavior of GCC is unclear (and depends on the
specific version of GCC), but the front end now accepts some of those cases
in GNU C++ modes with gnu_version < 130000.  For example:

  template<bool B> using Void = void;
  template<typename T, typename T::whatever> bool vart;
  template<typename> using Alias = Void<vart<int, 0>>;

This example is now accepted in some GNU C++ modes, even though the use of
vart<int, 0> is invalid.


6/3/24   [EDGcpfe/27315]
Microsoft compatibility: __declspec(no_sanitize_address)

The __declspec(no_sanitize_address) specifier is now accepted when it is
applied to functions or variables and microsoft_version >= 1928.  No action is
taken based on the presence of this specifier.


6/3/24   [EDGcpfe/27272]
GNU compatibility: Update builtin signatures to 13.3.0

Two builtins (__builtin_ia32_ldtilecfg and __builtin_ia32_sttilecfg) were added
between GNU 13.2.0 and 13.3.0.  The builtin signatures have been updated
accordingly.


5/31/24  [EDGcpfe/23333,EDGcpfe/24685,EDGcpfe/27190]
GNU compatibility: Extraneous parentheses in attribute string operands

The front end now accepts extraneous parentheses in string operands for
GNU-style attributes (providing they are matched).  For example (with --gcc):

  void f(void) __attribute__((visibility("hidden")));
  void g(void) __attribute__((visibility(("hidden"))));
  void h(void) __attribute__((visibility((((((("hidden")))))))));


5/31/24  [EDGcpfe/27296]
C++-generating back end: using-declarations for inaccessible types

In cases where the source code refers to an inaccessible type via an
accessible using-declaration, the code generated by the C++-generating back
end instead referred to the inaccessible type directly, resulting in code
that could not be compiled.  This is now fixed, and the generated code in
such cases also takes advantage of the accessible using-declaration.  For
example:

  class A {
    struct C { };   // private
  protected:
    typedef C OC;
  };
  struct B : A {
    using A::OC;    // public
  };
  void Test() {
    B::OC oc;       // previously generated as A::C
  }


5/30/24  [EDGcpfe/27255]
Improve support for 128-bit when INTEGER_VALUE_REPR_IS_A_HOST_INTEGER=1

The front end now prints all integer values via the util.h String_formatter
facility.  The signed, unsigned integer, and hex String_formatters have all
been rewritten to work with TYPE_FOR_AN_INTEGER_VALUE and
TYPE_FOR_A_SIGNED_INTEGER_VALUE of arbitrary bit counts.

A new configuration macro (HOST_HAS_INT128_EXTENSIONS) has been introduced for
control over the use of 128-bit native integer types.
HOST_HAS_INT128_EXTENSIONS should typically be set automatically based on the
value of the __SIZEOF_INT128__ macro.

This resolves build issues with 128-bit native integer types when
TYPE_FOR_AN_INTEGER_VALUE=__uint128_t and
TYPE_FOR_A_SIGNED_INTEGER_VALUE=__int128_t.

The following configuration macros are no longer used:
- PRINTF_FORMAT_FOR_HEX_INTEGER_VALUE
- PRINTF_FORMAT_FOR_HOST_LARGE_INTEGER
- PRINTF_FORMAT_FOR_HOST_LARGE_UNSIGNED
- PRINTF_FORMAT_FOR_SIGNED_INTEGER_VALUE
- PRINTF_FORMAT_FOR_UNSIGNED_INTEGER_VALUE


5/30/24  [EDGcpfe/27302]
Assertion failure when array bound exceeds targ_ptrdiff_t

Previously, the front end would fail to preserve array bound information after
lowering (if the array bound could not be represented by targ_ptrdiff_t),
resulting in a failed assertion in num_elem_node_from_count:

  struct A { ~A() {} };
  A y[~((unsigned long)0)];

This is now fixed.


5/30/24  [EDGcpfe/26810]
Microsoft compatibility: 64-bit targets and calling conventions

Consider, in Microsoft mode with a 64-bit target:

  int __stdcall __fastcall g();

Previously, this elicited an error.  However, for 64-bit targets the __stdcall,
__fastcall, and __cdecl calling convention are all equivalent to the default,
and thus MSVC accepts such code.  The front end now does as well.


5/30/24  [EDGcpfe/27291]
Recursive instantiation not performed when a warning is issued

A regression in template instantiation was introduced by the suppression
mechanism in EDGcpfe/10223 (in version 6.5); warnings could cause subsequent
recursive instantiations to be suppressed.  This resulted in the following
code:

  template<int X>
  int recurse() { return (0 << X * 1000) + recurse<X + 1>(); }
  template<>
  int recurse<5>() { return 0; }
  int x = recurse<1>();

only having the instantiation recurse<1> with recurse<2>, recurse<3>, and
recurse<4> being dropped.  This has now been fixed.


5/28/24  [EDGcpfe/27275]
Small _Float16 literal values

In some configurations the front end could abort (in fast_dec2bin_float16)
when processing a small _Float16 literal written with more digits than can
be represented by the _Float16 type.  This is now fixed.  For example, with
--c++23 --gnu_version=140100:

  _Float16 x = 6.103515625e-5F16;   // Previously aborted, now okay


5/22/24  [EDGcpfe/27274]
C++-generating back end: form of non-type template arguments

Previously the C++-generating back end put out most non-type template
arguments using their value rather than the expression that was evaluated
to obtain that value.  That has now been changed, and in general the
expression put out by the C++-generating back end for a non-type template
argument will be the one used in the first reference to the template
instance.  (An exception to this behavior is in cases where the expression
uses entities that are inaccessible or out of scope at the location of the
reference: since putting out the expression would result in an error, the
value will continue to be used.)  For example, with --c++11:

  constexpr int x = 1, y = 2, z = 3;
  template<int> struct S { };
  S<x + y> a; // Previously generated as S<3>, now S<x + y>
  S<z> b;     // Previously generated as S<3>, now S<x + x> (i.e., using
              // the form of the argument for S<3> from its first reference)


5/20/24  [EDGcpfe/27258]
Instantiations of templates in namespace with ELF visibility attribute

Consider, in GNU or Clang C++ modes:

  namespace  __attribute((visibility("default"))) N {
    template<typename T> void f(T) {}
    template<typename T> T v = T{};
  }
  template void N::f(int);
  template int N::v<int>;

Previously, the ELF visibility attribute on namespace N did not carry over to
the instances of the templates in N.  That is now fixed.


5/20/24  [EDGcpfe/27256]
Performance with large numbers of decimal integer literals

The process of extracting the value of a decimal integer literal that has
no digit separators and fewer characters than the maximum representable by
a_host_large_unsigned has been optimized.  For configurations in which
INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is TRUE, the performance difference is
minimal, but in configurations where that macro is FALSE, the improvement
will be significant when processing large numbers of literals.


5/18/24  [EDGcpfe/27250]
Incorrect _Float32 and _Float64 range checks

In some configurations, the front end reported spurious "out of range"
errors for very large or small _Float32 and _Float64 literal values.  This
is now fixed.  For example, with --gnu_version=140100:

  // No longer errors:
  _Float32 large = 3.40282346638528859811704183484516925e+38F32;
  _Float32 denorm = 1.40129846432481707092372958328991613e-45F32;


5/18/24  [EDGcpfe/27239]
C/C++-generating back ends: version numbers of target compilers;
new __EDG_BFLOAT16_ENABLING_POSSIBLE predefined macro with --building_runtime

The front end now accepts the command-line options --gen_c_clang_version,
--gen_c_gnu_version, and --gen_c_msvc_version to specify the version of the
clang, gnu, or MSVC compiler, respectively, for which the C/C++-generating
back end produces code.  (The existing --msvc_target_version command-line
option continues to be accepted for backward compatibility; its effect is
identical to --gen_c_msvc_version.)

In addition, when --building_runtime is specified, the front end now
predefines the macro __EDG_BFLOAT16_ENABLING_POSSIBLE, controlling whether
the run-time library is configured to support the bfloat16 type.  The
default value of the macro is determined by the specified target compiler
and version, but it can be redefined via command-line or other macro
definitions.


5/16/24  [EDGcpfe/27259]
C-generating back end: internal error on small floating point type and ellipsis

The C-generating back end incorrectly assumed all floating point types
shorter than double should be widened to double when passed to an ellipsis
and issued an internal error when it encountered an unwidened type in an
argument expression.  In fact, widening only applies to the float type and
not to other small floating point types.  This is now fixed.  For example,
with --gcc --gnu_version=140100:

  void f(int, ...);
  void g() {
    __bf16 x;
    f(0, x);   // Previously caused an internal error
  }


5/16/24  [EDGcpfe/27248]
Clang compatibility: spurious instantiation for __builtin_operator_delete

Previously, if __builtin_operator_delete was named using an unparenthesized,
unqualified id, the front end would perform argument dependent lookup to find
the corresponding deallocation function.  This could trigger template
instantiation of any types used in function arguments.  For example, with
--c++11 --clang_version 180100:

  struct A;
  template<typename T>
  struct C {
    T t;  // Previously a spurious error as A is still incomplete when
          // instantiated from below.
  };
  void f(C<A> *c) {
    __builtin_operator_delete(c);
  }


5/15/24  [EDGcpfe/19215,EDGcpfe/24168,EDGcpfe/27138]
Clang compatibility: C++11 features in C++03 modes

In Clang C++03 mode, the front end now accepts ref-qualifiers on member
function declarations, range-based "for" statements, and "auto" type specifiers
in C++03 mode (with a warning).  In addition, some dependent calls to GNU
built-in functions are now assumed to be foldable after instantiation in C++03
mode (previously, they were only assumed to be foldable in modes that allow
constexpr functions).  The changes to accept "auto" type specifiers also
improve disambiguation in modes that accept "auto" both as a storage class
specifier and as a type specifier.


5/15/24  [EDGcpfe/27157]
Assertion failures when remapping default member initializers in multi-TU mode

Previously, template code with a default member initializer could result in a
spurious assertion failure in trans_copy.c:

  // shared.h
  using a_size_type = unsigned long long;
  template<typename T>
  struct foo { a_size_type x = 0; };
  inline void bar(foo<int> x) {}
  // tu-a.cpp
  #include "shared.h"
  foo<int> z;
  // tu-b.cpp
  #include "shared.h"

Similarly, certain complex cases involving default member initializers and
default arguments could result in a spurious IL entry representing the lifetime
of the default argument in the default member initializer:

  // shared.h
  struct type_with_dtor { ~type_with_dtor(); };
  template<typename T>
  struct type_with_def_arg { type_with_def_arg(T a = T()); };
  struct type_with_def_init { type_with_def_arg<type_with_dtor> val{}; };
  // tu-a.cpp
  #include "shared.h"
  // tu-b.cpp
  #include "shared.h"

This is now fixed.


5/14/24  [EDGcpfe/27240,EDGcpfe/27246]
GNU C++ compatibility: bf16 floating-point suffix

Although formally only part of C++23, g++ began accepting the bf16
floating-point suffix in all language versions beginning with version 13.1,
and the headers released with gcc version 14.1 include a use of that
suffix.  The front end has now been updated to accept this usage in g++
mode when gnu_version is at least 130000.  For example, with
--gnu_version=140100:

  typedef __decltype(0.0bf16) __bfloat16_t;   // Previously an error, now okay


5/15/24  [EDGcpfe/24907,EDGcpfe/26639]
Substitution of nested pack in requires-expression

A pack of a nested template would previously fail to be expanded in a
requires-expression during substitution.  For example, with --c++20:

  template<typename U> struct C { };
  template<typename T> struct D {
    template<typename ... Us> requires requires { typename C<Us ...>; }
    struct N { };
  };
  D<char>::N<short> n;  // Previously a spurious error.  Now okay.


5/14/24  [EDGcpfe/25321,EDGcpfe/25688]
GNU compatibility: __builtin_shufflevector

The __builtin_shufflevector intrinsic is now enabled in GNU emulation mode when
gnu_version >= 120000.  Furthermore, a call to __builtin_shufflevector can
now take pack expansions.


5/14/24  [EDGcpfe/27242]
GNU compatibility: GNU 14.1.0 type trait intrinsics

A number of new type trait intrinsics are now available when gnu_version >=
140000.  Specifically, __is_array, __is_member_object_pointer,
__is_member_function_pointer, __is_reference, __is_object, __is_member_pointer,
__is_bounded_array, and __type_pack_element had all been previously implemented
in Clang mode and are now enabled in GNU emulation mode.  __is_scoped_enum is
a new type trait intrinsic.


5/13/24  [EDGcpfe/24350,EDGcpfe/27184]
Microsoft compatibility: undeclared base class of class template

In Microsoft permissive mode, the base class of a class template can still be
undeclared at the point of template definition.  For example:

  template<typename T>
  struct C : B {};  // Now accepted in Microsoft permissive mode.
  struct B {};


5/8/24   [EDGcpfe/27216]
Spurious error on pack expansion in nested generic lambda

A generic lambda containing a pack expansion that references packs from both an
enclosing real instantiation and the generic lambda would previously elicit a
spurious error.  For example, with --c++14:

  int g(int, int);
  template<typename ... Ts>
  inline int f(Ts ... t) {
    return [] (auto ... p) {
      return g(Ts{p} ...);  // Previously a spurious error.  Now okay.
    } (t ...);
  }
  auto i = f(1, 2);


5/8/24   [EDGcpfe/27236]
GNU compatibility: GCC 14.1.0 builtins

The front end has been updated with the latest builtin signatures from
GCC version 14.1.0.


5/7/24   [EDGcpfe/20755,EDGcpfe/20905]
Use of variable template specialization in unevaluated context

Consider:

  template<typename> struct I;
  struct S {
    template<typename T> static I<T> v;
    using N = decltype(v<int>);
  };

Previously, this elicited an error because S::v<int> was fully instantiated,
thus requiring a complete type.  Now, uses of variables in unevaluated contexts
no longer systematically trigger full instantiation and the example above is
accepted.


5/3/24   [EDGcpfe/27229]
Clang compatibility: --ms_compatibility issue with va_list type

In Microsoft emulation mode, the default type for va_list or __builtin_va_list
is char*, and now it's also char* when using --ms_compatibility.


5/2/24   [EDGcpfe/26215,EDGcpfe/26329]
Builtins for ARM32 and ARM64 architectures

The tool that generates the builtin signature table in builtin_defs.h has been
updated to also handle ARM32 and ARM64 architectures.  To avoid any slowdown
due to the number of architecture-specific builtins, the builtin signature
table has been split into a common table and architecture-specific tables with
32-bit and 64-bit variants.


5/1/24   [EDGcpfe/27199]
Microsoft-mode instantiation point of exception specifications

The changes for EDGcpfe/20840 caused exception specifications for member
function templates to be instantiated early in Microsoft modes.  That behavior
is now limited to modes with microsoft_version < 1920.


4/30/24  [EDGcpfe/27223]
C++-generating back end: complex 128-bit floating point type

The changes for EDGcpfe/26221 (in version 6.5) inadvertently resulted in
the complex 128-bit floating point type being represented using the
std::float128_t typedef in the output of the C++-generating back end, even
in modes in which that typedef is not defined.  This is now fixed.  For
example, with --gnu_version=100100:

  using complex128 = __float128 __complex__;   // Previously generated as
                                               // std::float128_t __complex__


4/30/24  [EDGcpfe/27222]
Spurious "throw()" warning on use of builtins in C++20 mode

Previously, the front end issued a spurious warning about the use of "throw()"
in C++20 mode when calling non-throwing builtin functions.  For example, with
--c++20 --clang_version 180100:

  void f() {
    __builtin_unreachable();  // Previously a spurious warning.  Now okay.
  }


4/29/24  [EDGcpfe/27146]
GNU compatibility: predefined types for ARM NEON builtins

On ARM platforms, GCC predefines additional types to be used with ARM-specific
builtins (named __builtin_aarch64_simd_* for 64-bit platforms and
__builtin_neon_* for 32-bit platforms).  Additionally, NEON vector types
__simd64_* and __simd128_* are now also predefined on ARM32 platforms.


4/29/24  [EDGcpfe/27201]
GNU compatibility: incorrect reuse of temporaries when lowering statement
expressions

In configurations that do lowering, the lowering of a GNU statement expression
within a larger full expression had triggered a reuse of temporary variables
that could result a temporary variable being reused prematurely (with undefined
behavior at runtime).  For example, with --g++:

  int same(const int& a, const int& b) {
    return a == b;
  }
  int bug(int a, int b) {
    return same(({ a; }), int(b));  // Same temporary used in some configs.
  }
  int main() {
    return bug(123, 0);   // Should return 0, but had returned 1 in some cases.
  }


4/25/24  [EDGcpfe/27198]
Treat constexpr variable initializers as immediate contexts

Previously, the invocation of a consteval function as subexpression of a
constexpr variable initializer was required to be successfully constant-
evaluated on its own.  Now, it is sufficient for that invocation to be
successfully constant-evaluated as part of the constant-evaluation of the
initializer as a whole.  For example:

  #include <vector>
  consteval std::vector<int> g() { return {1,2,3}; }
  constexpr int n = g()[1];

Previously, this example failed because the call "g()" on its own produces
a vector with some dynamically allocated storage that is not deallocated as
part of the call.  Now it succeeds because the evaluation of the initializer
as a whole runs the destructor for the temporary produced by the call "g()".


4/24/24  [EDGcpfe/27194]
Microsoft compatibility: decltype(__uuidof(...))

The Microsoft __uuidof operator produces an lvalue of type _GUID const.
Previously, the front end therefore produced a reference type when the
decltype operator is applied to a use of the __uuidof operator.  However,
it appears MSVC instead produces the non-reference type _GUID const.  The
front end now emulates that behavior.


4/22/24  [EDGcpfe/27147]
Assertion failure from source location builtins in default member initializers

A regression was introduced in EDG 6.4 that resulted in an unevaluated source
location builtin expression making it to lowering and a subsequent assertion
failure in lower_expr_full ("lower_expr: bad kind").  This occurred when the
source location builtin appears in a lambda used as part of a default member
initializer, e.g.:

  struct function { template <typename _Functor> function(_Functor); };
  struct operators_repository {
    function u = [] { __builtin_LINE(); };
  };

This is now fixed.


4/22/24  [EDGcpfe/27187]
Assertion failure on friend function redeclaration in class template

In some cases where a friend function is defined in one class template and also
declared in another class template, instantiating that friend function could
result in a failed assertion in scan_function_body.  For example, with --c++20:

  template<int I> struct C2;
  template<int I>
  struct C1 {
    friend int f(C1, C2<I>) { return 1; }
  };
  template<int I>
  struct C2 {
    friend int f(C1<I>, C2);
  };
  int i = f(C1<0>(), C2<0>());  // Previously triggered an assertion failure.
                                // Now okay.


4/21/24  [EDGcpfe/27179]
Abort with multi-line raw string literal as macro argument

In some cases, passing a multi-line raw string literal as a macro argument
could result in an abort with a failed assertion in macro_invocation.  This
is now fixed.  For example, with -E --g++:

  #define M1(D) 2
  #define cat(A, B) cat2(A, B)
  #define cat2(A, B) A##B
  #define M2(D)
  #define M3(A) XXX(A)
  #define M4(A) M3(cat(M,M1(x))(A))
  M4(R"(X
  )")   // Previously aborted, now okay


4/20/24  [EDGcpfe/27182]
Microsoft compatibility: apparent function call in preprocessor expression

The MSVC preprocessor accepts function-call syntax in preprocessor
expressions with only a warning, even when the "function name" is not
defined as a function-style macro.  The front end has now been changed to
emulate this non-standard behavior in Microsoft mode; the value of the
putative function call is assumed to be 0L and the remaining preprocessor
tokens following the call are discarded.  For example, with --microsoft:

  #if nonexist(1)   // Previously an error, now a warning in Microsoft mode
  #endif


4/18/24  [EDGcpfe/27135]
Abort on CTAD involving aggregate class with dependent base

Consider, in C++20 mode:

  template<int V> struct Val { static constexpr int value = V; };
  template<typename V> struct S: public Val<__is_constructible(V)> {};
  static_assert(S(1), "");  // Previously aborted.  Now an error.

Previously this aborted while the front end tried to generate an implicit
deduction guide for the aggregate template S.  That is now fixed.


4/17/24  [EDGcpfe/26056,EDGcpfe/27168]
Nondependent static_assert conditions in templates

When a static_assert condition is nondependent and has a false value within a
template definition, an error is no longer issued at that point.  An error will
still be issued if the template is instantiated.  This implements the proposal
in the standards committee's paper P2593R1, which was folded into the
resolution of Core issue 2518.  For example:

  template<typename T> struct S {
    static_assert(false, "Do not instantiate");  // No longer an error when
  };                                             // the template is parsed.
  S<int> s;  // Triggers an error due to the failing static_assert.

In older Microsoft, GNU, and Clang modes, the prior behavior is preserved
(thereby more closely emulating the behavior of the corresponding versions of
MSVC, GCC, and Clang, respectively).


4/16/24  [EDGcpfe/27115]
Assertion failure when lowering some aggregate constants

In certain modes, the lowering of an aggregate constant with a designated
initializer that initializes a type with a field with a [[no_unique_address]]
attribute, had caused an assertion failure (in
advance_aggregate_position_to_next_member or in some cases
fill_out_aggregate_ptr_to_data_member_initialization) and is now fixed.
For example, with --c++17 --gnu_version=100000:

  struct A {};
  struct B {
    [[no_unique_address]] A a;
    int i;
  };
  void f() {
    auto b = B { .i = 512 };
  }
  auto b = B { .i = 512 };


4/16/24  [EDGcpfe/27174]
Spurious unbounded recursive rewrite of comparison

Consider:

  struct X { X(int X::*) {} };
  struct S {
    friend bool operator<(S, X);
  };
  template<class U, class V> S operator<=>(U const&, V const&);
  int r = S{} < 0;

Previously, this elicited an error due to the front end erroneously entering
an unbounded sequence of recursive rewrites for the less-than operator.  That
is now fixed.


4/16/24  [EDGcpfe/27142]
Spurious "too many arguments" error on empty pack expansion

Consider, with --c++11:

  template<int> struct D {
    template<typename U> using X = U;
  };
  template<int I, typename ... T> struct C {
    template<typename>
    using A = typename D<I>::template X<int, T ...>;  // Previously a spurious
  };                                                  // error.  Now okay.
  C<0> c;

When the member declarations for C<0> are instantiated, the template arguments
for D<0>::X (i.e., <int, T ...>) are matched against the corresponding template
parameter list (i.e., <typename U>).  Even though T is an empty pack in this
instantiation, this previously elicited a spurious "too many arguments" error.
That is now fixed.


4/15/24  [EDGcpfe/25261,EDGcpfe/26579]
GCC/Clang compatibility: functionally-equivalent member templates in class
template instantiations

The changes made for EDGcpfe/18549 (see entry of 7/11/18) approximated the
behavior of GCC and Clang by not folding non-dependent sub-expressions after
encountering a dependent sub-expression.  However, in cases where the
non-dependent sub-expression preceded any dependent part, this approach did not
work.  Instead, the front end now doesn't consider dependent template parameter
or function parameter types to be equivalent when checking for redeclarations
in class template instantiations.  For example, with --g++:

  template<bool>
  struct C {};
  template<int I>
  struct A {
    template<bool B>
    void f(C<I == 1 && B>);
    template<bool B>
    void f(C<I == 2 && B>);  // Now accepted in GNU and Clang modes
  };
  A<0> a;


4/15/24  [EDGcpfe/27167]
Explicit function template specialization could lead to undefined behavior

Missing skip_typerefs had caused undefined behavior when explicitly
specializing a function template that was originally declared using an alias
template.  For example, with --c++11:

  template<typename T> using fn_t = T(T);
  template<typename T> fn_t<T> f;
  template<>
  int f(int) {
    return 0;
  }
  auto v = f(1);


4/14/24  [EDGcpfe/27171]
C++26 mode

The front end now accepts a new "--c++26" command-line option (as does the
eccp.sh script).  This option will enable features for the standard under
development (which is expected to be completed in 2026).  For now, it sets
the value of the global variable std_version to 202600 and the value of the
predefined __cplusplus macro to 202600L; those values will eventually be
updated to match the official __cplusplus value when the forthcoming standard
is approved.  A new macro cpp26_mode is also available in the front end to
test whether it runs in C++26 mode.


4/12/24  [EDGcpfe/27158]
Multi-TU correspondence checking of maybe_unused and GNU unused

Previously, when considering attribute correspondence for the [[maybe_unused]]
or [[gnu::unused]] attributes in multi-TU mode the front end would complain
if the attribute was present in one translation unit but not another.

  // shared.h
  void foo(int);
  // tu-a.cpp
  #include "shared.h"
  void foo([[maybe_unused]] int);
  // tu-b.cpp
  #include "shared.h"

This has been changed and the front end no longer reports this as a conflict.


4/11/24  [EDGcpfe/27144]
Temporary not lifetime-extended because of multilevel lvalue adjustment

When a temporary is bound to a reference, its lifetime is extended to the scope
of the reference.  One function involved in that is find_top_temporary (in
overload.c) which looks in the expression tree for a potential temporary node
whose lifetime should be extended.  That function previously considered the
possibility that an lvalue-adjustment node appears on top of the temporary, but
it was sometimes possible for multiple such adjustment nodes to exist.  This
is now fixed both by avoiding known cases of multiple lvalue adjustments (they
are now collapsed into a single adjustment) and by making find_top_temporary
more robust (it can now skip over multiple adjustments).


4/11/24  [EDGcpfe/27083]
Layout of [[no_unique_address]] fields in the IA-64 ABI

In the IA-64 ABI, a [[no_unique_address]] field of class type X allows the
subsequent field to be allocated in the tail padding of X.  The front end, 
however, failed to take virtual base classes into account when computing
where the tail padding of the [[no_unique_address]] field starts.  For example:

  struct V { short h;};
  struct D : virtual V {
    long x;
    int y{};
  };
  struct X {
    [[no_unique_address]] D n;
    short z;
  };

Previously, member X::z was erroneously placed at the same offset as the
virtual base V of member X::n.  That is now fixed.  In addition, in cases
without virtual base classes, the C-generating back end failed to reuse
the tail padding in the generated C code.  In an example similar to the
one above,

  struct D {
    long x;
    int y{};
    // sizeof(int) bytes of tail padding, assuming sizeof(long) > sizeof(int)
  };
  struct X {
    [[no_unique_address]] D n;
    short z;
  };

X::z should have been allocated in the tail padding of the preceding D
subobject but was erroneously placed after it.  This also is now fixed.


4/11/24  [EDGcpfe/26872]
Equivalence of dependent alias template specializations

Previously, the front end did not consider a dependent alias template
specialization to be equivalent to the aliased type when that type was
cv-qualified.  Now it is considered equivalent if the alias template is not
constrained and the aliased type names all template parameters (in other cases,
the types are still considered to be distinct as substitution into the alias
template could result in additional substitution failures).  For example, with
--c++11:

  template<typename> class C {};
  template<typename T> using A = const C<T>;
  template<typename T> struct B {
    void f(C<A<T>>);
  };
  template<typename T>
  void B<T>::f(C<const C<T>>) {}  // Previously a spurious error.  Now okay.


4/10/24  [EDGcpfe/27028]
Microsoft compatibility: Ambiguous call to extern "C" functions

Consider:

  struct S {};
  typedef long (*F)();
  extern "C" {
     F f(S*);
  }
  namespace N {
    extern "C" F f(S*);
    void g(S *p) {
      f(p);  // Previously ambiguous in Microsoft C++ mode.  Now okay.
    }
  }

This previously elicited an ambiguity error in Microsoft C++ mode.  It is now
accepted.


4/9/24   [EDGcpfe/26317,EDGcpfe/27052]
C-generating back end abort with [[no_unique_address]] field

Consider:

  struct S {
    int i;
    bool j = true;
  };
  struct B {
    [[no_unique_address]] S s;
  };
  struct D: B {} d;

This previously aborted in the C-generating back end (a failing assertion check
in dump_struct_union_definition).  That is now fixed.


4/8/24   [EDGcpfe/22609,EDGcpfe/27086]
Type deduction fails for GNU template static data member with unspecified bound

Consider:

  template<typename T> struct X {
    static constexpr int arr[] = { 1, 2, 3 };
  };
  int main() {
    for(auto i: X<int>::arr) {}  // Previously failed in GNU C++ mode.
  }                              // Now okay.

In GNU C++ modes, a static data member initializer in a template class is not
instantiated until the member is used.  This caused deduction to fail in the
example above.  That is now fixed by instantiating the initializer for a case
like this a little earlier.


4/8/24   [EDGcpfe/25484]
GNU C compatibility: Constant aggregate variables in initializers

In C mode, initializers for static-lifetime variables must be constant.  GCC
treats as constant some uses of const variables and the front end already
emulated this to an extent (see, e.g., the entry for EDGcpfe/14216).  Now, in
GNU C modes with gnu_version >= 80000, this behavior extends to more const
variable types, including aggregate variables.


4/7/24   [EDGcpfe/26857]
GCC compatibility: Treat some alias templates as opaque

Consider:

  struct S {};
  template<typename> using A = S;
  template<typename T> struct D: A<T>::B {};  // Now accepted in GNU C++ modes.

This example is invalid because A<T> has no member B.  However, GCC appears not
to diagnose such cases (presumably because it treats A<T> as opaque).  The
front end now emulates that behavior to some extent in GNU C++ modes (but not
Clang modes).


4/6/24   [EDGcpfe/27132]
Unbounded loop in Microsoft mode

In some cases involving a cast applied to a comma expression, the front end
created an expression node using itself as an operand, which in turn was likely
to trigger an unbounded loop during IL traversal.  For example:

  char* g(unsigned long &x, char *str) {
    return str ? str : (char*)(x = 0, 0);  // Previously triggered an unbounded
  }                                        // loop in Microsoft mode.

This is now fixed.


4/4/24   [EDGcpfe/27093]
Support for ARM scalable and NEON vector types (IL CHANGE)

Support for ARM's scalable and NEON vector types has been added.  For ARM64
targets, GNU makes NEON vector and polyvector types available as predefined
typedefs, while Clang supports them via the "neon_vector_type" and
"neon_polyvector_type" attributes.  These NEON vector types are represented as
tk_vector types with a kind field to distinguish between the different vector
kinds (the is_ext_vector_type flag has been replaced with a kind of vk_ext).
Scalable vector types are represented as tk_scalable_vector types.


4/3/24   [EDGcpfe/19086,EDGcpfe/26821,EDGcpfe/26870,EDGcpfe/26896]
Cast to incomplete type in decltype construct

The front end now accepts some casts to an incomplete type within a decltype
construct if that cast appears in a template.  The details of which cases are
accepted depend on the C++ dialect that is selected.  For example:

  struct S;
  template<typename T> struct X {
    decltype(S(T{0})) *p1;  // Accepted in Microsoft, Clang, and GCC modes.
    decltype(X<T>(0)) *p2;  // Accepted in all C++ modes.
  };


4/2/24   [EDGcpfe/19116,EDGcpfe/26835]
Microsoft compatibility: Missing "template" prefix in member selection

In Microsoft modes, the prototype instantiations of templates are frequently
deferred to approximate MSVC's behavior of not parsing templates in their
generic form.  However, that is not possible in some configurations that
require that prototype instantiations be recorded in the IL.  In Microsoft bugs
mode, the front end now also uses a simple heuristic to recognize some common
cases where a member selection of the form "x.m<args>" should have been
"x.template m<args>"; in such cases it accepts the former as if it were the
latter.


4/2/24   [EDGcpfe/27037]
C++-generating back end: deduced-type constexpr initialization

In some cases involving a variable declared with a deduced type in which the
initialization is performed by a constexpr constructor call, the
C++-generating back end put out an incorrect form of the initializer.  This
is now fixed.  For example, with --c++11:

  struct A {
    int x;
    constexpr A(int xx) : x(xx) { }
  };
  void f() {
    static constexpr auto a{A{15}};   // Previously generated as "a{15}"
  }


4/2/24   [EDGcpfe/27025]
GNU compatibility: Ref-qualifiers on parameter declarations

GCC accepts declarations such as:

  void g(int () &&);  // Invalid (and meaningless) ref-qualifiers.  Now
                      // accepted in GNU C++ mode with a warning.

In GNU C++ mode, the front end now emulates this behavior with a warning.


4/1/24   [EDGcpfe/19533,EDGcpfe/22944,EDGcpfe/26974]
Clang compatibility: Attributes pass_object_size and diagnose_if

The front end now provides limited support for the Clang attributes diagnose_if
and pass_object_size.  The diagnose_if attribute is parsed and recorded, but
otherwise ignored.  The pass_object_size attribute is recorded and some of its
semantic restrictions are enforced, but the implicit argument that it implies
is not currently materialized by the front end.  The primary goal of this
initial support is to enable parsing certain system headers that make use of
these features.


3/28/24  [EDGcpfe/27030]
Spurious "pack not expanded" error on use of type alias

In some cases, the use of a type alias that refers to an alias template
containing an expansion of an enclosing template parameter pack could result in
a spurious "parameter pack ... was referenced but not expanded" error.  For
example, with --c++11:

  template<int> struct D {
    template<typename T, typename ... TT> using B = T;
  };
  template<int I, typename ... TT> using B = typename D<I>::template B<TT ...>;
  template<typename> struct X;
  template<typename ... TT> struct C {
    using BB = B<0, TT ..., void>;
    X<BB> *x;  // Previously a spurious error.  Now okay.
  };


3/28/24  [EDGcpfe/27126]
Clang compatibility: __reference_constructs_from_temporary builtin

The __reference_constructs_from_temporary builtin is now available in Clang
emulation mode when clang_version >= 180000.


3/27/24  [EDGcpfe/27111]
Abort in subobject_is_initialized

In some fairly complex cases involving a cast to a base class lvalue, followed
by a copy of that lvalue and an attempt to cast the result prvalue back to the
derived class, the constant evaluation interpreter could abort in the function
subobject_is_initialized.  That is now fixed.


3/26/24  [EDGcpfe/27120]
C++-generating back end: CTAD, lambdas, and constexpr constructors

In cases where the template argument for a class template is deduced from a
lambda expression and the resulting temporary object is produced by and
passed to a constexpr constructor, the C++-generating back end could put
out the deduced class type using an undeclared temporary name (of the form
__T12345678) as an explicit template argument.  This is now fixed.  For
example, with --c++17:

  template<typename T> struct A {
    constexpr A(const T &a) {}
  };
  template<typename T> struct B {
    constexpr B(const T &a) {}
  };
  void f() {
    auto a = A(B([] {}));  // Previously generated as:
                           // A(((B<class __T12345678>)([]{})))
  }


3/26/24  [EDGcpfe/27116]
C++-generating back end: unbounded recursion with cv-qualified template
argument

In certain complex cases involving cv-qualified template type arguments,
the C++-generating back end could enter an unbounded recursion.  (In
configurations with EXPENSIVE_CHECKING set to TRUE, a "Recursive qualifier"
internal error was issued instead.)  This is now fixed.


3/19/24  [EDGcpfe/27107]
Clang compatibility: allow floating-point types in some atomic builtins

It appears that Clang versions 13.0.0 and later now allow certain
floating-point types as the first argument to the __atomic_add_fetch,
__atomic_sub_fetch, __atomic_fetch_add, and __atomic_fetch_sub builtins.
The front end now emulates that when clang_version >= 130000.  For example:

  double f(double* addr, double value) {
    return __atomic_fetch_add(addr, value, 0);
  }


3/14/24  [EDGcpfe/27103]
GNU compatibility: builtin signatures for the "cmpccxadd" target

Builtin signatures were added for the "cmpccxadd" target (which affects
only GNU emulation modes when gnu_version >= 130100).


3/14/24  [EDGcpfe/24511,EDGcpfe/25768,EDGcpfe/26155,EDGcpfe/26885,
          EDGcpfe/26911,EDGcpfe/27099]
GNU compatibility: Comparison of integer vector types

Consider, in GNU C++ mode:

  using u32x8 [[gnu::vector_size(32)]] = unsigned int;
  u32x8 test(u32x8 x) {
    return (x & 0x7FFFFFFF) == 0;  // Previously an error.  Now okay.
  }

Previously this elicited an error complaining that the return value of the test
function does not match its return type.  That is now fixed.  (The exact
behavior of GCC is somewhat surprising, and earlier attempts at emulating it
relied on incorrect conclusions.  The emulation now produces a result type for
vector comparisons that is distinct from vector types that can be declared by
the programmer directly.)


3/13/24  [EDGcpfe/27101]
GNU C++ compatibility: typedefs in system headers for _Float* types

Even though g++ treats the _Float* type names (see the entries for
EDGcpfe/26221 and
EDGcpfe/18316,EDGcpfe/22881,EDGcpfe/26290,EDGcpfe/26308,EDGcpfe/26332) as
built-in, it allows typedef declarations for them to appear in system
headers.  The front end previously issued an "invalid combination of type
specifiers" error for such declarations, regardless of their location, but
now ignores them in system headers when compiling in g++ mode.  For
example, with --g++:

  # 2 "foo.h" 3 4
  typedef __float128 _Float128;   // Previously an error, now okay


3/13/24  [EDGcpfe/25658]
C++-generating back end: use of type traits helpers in template arguments

In some cases, when a template argument in the original source involves an
alias template, the C++-generating back end put out the template argument
using the underlying type of the alias instead of the alias itself.  When
that underlying type involves a type traits helper, clang and g++ cannot
compile the generated code, complaining that the resulting name cannot be
mangled.  For example, with --c++11 --clang:

  template <bool X> struct A { static const bool m = X; };
  template <bool> struct B { typedef void Tp; };
  template <bool...> struct C;
  template <bool... Bs> using D = A<__is_same(C<>, C<Bs...>)>;
  template <class...> class E;
  template <class... c> typename B<D<c::m...>::m>::Tp o(E<>&, E<>&) {} // #1
  template void o(E<>&, E<>&);

The C++-generating back end previously put out the template argument for
B in the line marked #1, D<c::m...>::m>, as

  A<__is_same(C<>, C<(c::m)...>)>

which violated the restriction on mangling names involving type traits
helpers.  This is now fixed, and the argument is put out using the same
alias template as in the original source.


3/13/24  [EDGcpfe/27092]
Equivalence of expressions containing pack expansions

Previously, the front end incorrectly considered expressions that only differ
in their pack expansions to be equivalent.  For example, with --c++11:

  template<typename T> T z();
  template<typename ... TT>
  void f(decltype(x(y(z<TT>()...)))) {}
  template<typename ... TT>
  void f(decltype(x(y(z<TT>())...))) {}  // Previously a spurious error.
                                         // Now okay.


3/11/24  [EDGcpfe/27089]
Clang compatibility: Additional builtins for Clang version 18.1.0

Additional builtin signatures have been added for the recently-released
18.1.0 version of Clang.


3/11/24  [EDGcpfe/27088]
Incorrect use of wrong member of variant union

A change in version 6.2 introduced code that could inadvertently reference
an uninitialized member of the a_type::variant union, causing undefined
behavior, and is now fixed.


3/8/24   [EDGcpfe/23733,EDGcpfe/23807,EDGcpfe/27082]
GNU/Clang compatibility: noexcept mismatch on extern "C" functions

Consider in GNU or Clang C++17 modes:

  # 101 "/system/header.h" 2 3 4
  extern "C" {
    extern void sysfunc(int*) noexcept(true);
  }
  namespace N {
    extern "C" void sysfunc(int*);  // Previously an error.  Now okay.
  }

This situation where an extern "C" function was redeclared in a different
namespace with a non-matching exception specification occurs in some system
headers used with Clang and GCC.  The front end now accepts such system
headers.


3/8/24   [EDGcpfe/25092,EDGcpfe/27070,EDGcpfe/27081]
GNU/Clang compatibility: explicit(bool) enabled in pre-C++20 modes

The explicit(bool) feature (see the Changes entry for EDGcpfe/20042) is now
enabled (with a warning) when emulating GNU 9.0.0 or Clang 10.0.0 or later
versions.  For example:

  struct A { explicit(true) A() {} };  // Now accepted with a warning in
                                       // later GNU and Clang modes.


3/6/24   [EDGcpfe/27080]
Clang C++ compatibility: __datasizeof

In Clang C++ modes with clang_version >= 180000, the front end now supports the
__datasizeof operator, which acts like the traditional sizeof operator except
that for the IA-64 ABI it doesn't include tail padding for some class types.
For example, in Clang C++17 mode with common IA-64 ABI configurations:

  struct S {
    S();  // The constructor enables the tail padding exemption.
    long long l;
    char c;
  };
  static_assert(sizeof(S) == 16);
  static_assert(__datasizeof(S) == 9);

No mangling is provided for this operation (since Clang appears not to have
implemented that at this time).


3/5/24   [EDGcpfe/25451,EDGcpfe/27020,EDGcpfe/27054]
Abort in find_subobject_for_interpreter_address

In fairly complex cases involving union constructors, constant evaluation could
abort with an internal error in find_subobject_for_interpreter_address.  That
class of problems is now fixed.


2/29/24  [EDGcpfe/27049]
Build issue with EDGcpfe/26965

In EDGcpfe/26965 general memory management was improved.  However, a typo
resulted in a build error when MAKE_FRONT_END_CALLABLE=1.  This is now fixed.


2/29/24  [EDGcpfe/26115,EDGcpfe/27050]
Constraint normalization of parenthesized constraint expressions

In configurations with PARENS_IN_IL set to TRUE, the front end previously
failed to normalize parenthesized constraint expressions.  For example, with
--c++20:

  template<typename>
  concept C1 = true;
  template<typename T>
  concept C = (C1<typename T::A> || C1<typename T::B>);
  struct D {
    using A = int;
  };
  static_assert(C<D>);  // Previously failed in some configurations.  Now okay.


2/29/24  [EDGcpfe/26978,EDGcpfe/27051,EDGcpfe/27055]
Abort on substitution of function-scope templated type alias

A type alias declared in a templated function can later be used in a
substitution context (e.g., a requires expression).  The front end, however,
did not record the information needed for substitution processing of any
contained expression.  This could result in aborts due to failed assertions
and/or other kinds of incorrect behavior.  For example, with --c++20:

  template<int I>
  struct C {};
  template<auto I>
  void f() {
    using A = C<+I>;
    static_assert(requires { A{}; });  // Previously triggered an internal
                                       // error.  Now okay.
  }
  template void f<1>();


2/27/24  [EDGcpfe/26945]
Crash during deduction guide correspondence checking in multi-TU mode

In version 6.6 (EDGcpfe/26418), support for deduction guide correspondence
was added to multi-TU mode.  When resolving the correspondence of overloaded
deduction guides such as the following:

  template<class T> struct foo { };
  template<class T> foo(T) -> foo<T>;
  template<class T> foo(T, T) -> foo<T>;

a crash occurred.  This has now been fixed.


2/27/24  [EDGcpfe/23282]

Consider:

  #include <initializer_list>
  #include <iostream>
  struct S {
    S() { std::cout << "default\n"; }
    S(S const&) { std::cout << "copy\n"; }
    S(S&&) { std::cout << "move\n"; }
    S(std::initializer_list<S>) { std::cout << "initializer list\n"; }
  };
  int main() {
    S x = S { S() };
  }

The standards committee's resolution of Core issue 1467 caused this example to
ignore the initializer-list constructor and thus (taking copy elision into
account) this example would invoke only a default constructor.  This was
deemed undesirable and the subsequent resolution of Core issue 2137 restored
the invocation of the list-initializer constructor (in addition to the default
constructor invoked for "S()").  The front end now implements that resolution
in its default mode and in GNU C++ modes (GCC never implemented the effects of
the resolution of Core issue 1467 for this case).  The old behavior is
maintained in Clang and Microsoft modes, however.


2/27/24  [EDGcpfe/26999]
Microsoft compatibility: Move-construction from user-defined conversion result

Consider:

  struct C1 {
    C1(const C1 &);
    C1(int);
  };
  struct C2 {
    C2(C2 &&);
    C2(int);
  };
  struct D {
    operator C1() const;
    operator C2() const;
    operator int() const;
  };
  C1 c1{D{}};  // Accepted in Microsoft modes and nonstrict C++17 modes.
  C2 c2{D{}};  // Accepted in nonstrict C++17 modes, but ambiguous in recent
               // Microsoft modes.

The standard makes both conversions in the above example ambiguous.  However,
the Microsoft compiler has always preferred the class-type conversion, and
following common modern practice by other compilers, the front end started to
accept these cases in all nonstrict C++17 modes (see the changes for
EDGcpfe/26151,EDGcpfe/26260).  But starting with version 19.00, the Microsoft
compiler no longer applies that practice if the destination class has a move
constructor.  The front end now emulates that Microsoft-specific behavior.


2/26/24  [EDGcpfe/20939]
Address template arguments in C++17

Consider:

  template<int const*> struct X {};
  int const n = 5;
  X<&n+1-1> x;  // Previously an error.  Now okay.

C++17 made this example valid (through paper N4268; see also the changes for
EDGcpfe/18747), but the front still issued an error for it.  That is now fixed.


2/23/24  [EDGcpfe/26829]
Mangling of array indexing

The front end previously did not always correctly mangle the names of function
template instances that involved multi-level array subscripts or subscripting
the first element (position zero).  For example:

  template<int&> void g() {}
  int arr2[3][4];
  int x = (g<arr2[2][3]>(), 0);  // Previously the second subscript was not
                                 // recorded in the mangled name of the
                                 // instance of g.

That is now fixed.


2/22/24  [EDGcpfe/20203]
Diagnosing "mutable mutable" in lambda expressions

The changes for EDGcpfe/17690,EDGcpfe/17995 introduced a regression in version
4.14 of the front end causing it to no longer diagnose a repeated "mutable"
specifier in a lambda expression.  For example:

  auto lm = []() mutable mutable { return 1; };  // Now an error again.

That is now fixed.


2/22/24  [EDGcpfe/27002]
Spurious error for non-dependent co_await in template-dependent coroutine

Previously, a co_await expression with a non-dependent operand appearing in a
coroutine with a dependent function type elicited a spurious error.  For
example, with --c++20:

  #include <coroutine>
  struct A {
    struct promise_type {
      A get_return_object();
      std::suspend_never initial_suspend();
      std::suspend_never final_suspend() noexcept;
      void unhandled_exception();
      void return_void() {}
    };
  };
  auto l = [] (auto) -> A {
    co_await std::suspend_always{};  // Previously a spurious error.  Now okay.
  };


2/21/24  [EDGcpfe/27031]
GNU-mode abort on invalid call in template

Consider, in GNU C++17 mode:

  template<typename... Ts> struct S {
    template<typename C> S(C *obj, void (C::*pmf)(Ts ...ps)) {
      pmf(1);
    }
  };

The call pmf(1) is invalid, but the front accepts the syntax in GNU-mode
templates.  However, it previously aborted due to an error attempting to
constant-evaluate the erroneous call.  That is now fixed.


2/20/24  [EDGcpfe/26739]
Abort on conversion of lambda with explicit-this parameter

Consider:

  auto lm = [](this auto self, int x) { return 42; };
  int (*pf)(decltype(lm), int) = lm;  // Previously aborted.  Now okay.

This example previously aborted in type_change_constant_full (folding.c) with
an internal error.  That is now fixed.


2/20/24  [EDGcpfe/25514,EDGcpfe/26992]
C++23: Static operator()

In C++23 modes, the front end now accepts static operator() member functions.
Lambda expressions can also be marked "static" to indicate that their
associated call operator is a static member function.  This language extension
was added to C++23 via WG21 paper P1169R4.  In some GNU modes (with
gnu_version >= 120000), some Clang modes (with clang_version >= 160000) and
some Microsoft modes (with microsoft_version >= 1939), these extensions are
also accepted with a warning when C++23 is not enabled.


2/19/24  [EDGcpfe/27013]
Incorrect destruction of variadic init-captures

Consider:

  struct Z {
    bool z;
    Z(): z(false) { }
    ~Z() { z = (z != 0) throw : true; }
  };
  template<typename... Ts> void sink(Ts... ts) { }
  template<typename... Ts> auto capture(Ts... ts) {
    return [...us = ts]() { sink(us...); };
  }
  int main() {
    Z x;
    auto y = capture(0, x);
  }

Previously this aborted with an uncaught exception because the front end
inadvertently recorded two destructions of the captured Z value.  In other
cases, the problem could manifest as missing destructions.  Those issues are
now fixed.


2/16/24  [EDGcpfe/27014]
Spurious syntax errors after instantiation of a typeid construct

The changes for EDGcpfe/25657,EDGcpfe/26023,EDGcpfe/26101 introduced a
regression in version 6.6 where certain instantiations of typeid constructs
containing a pack expansion resulted in subsequent spurious syntax errors.
That problem is now fixed.


2/14/24  [EDGcpfe/27010]
C++-generating back end: internal error with macro definition before catch

In some C++-generating back end configurations, a macro definition
appearing before a catch clause could result in an internal error (in
check_for_and_take_source_seq_entry).  This is now fixed.  For example:

  void f() {
    try { }
  #define M
    catch(int y) { }   // Previously resulted in an internal error
  }


2/13/24  [EDGcpfe/26048,EDGcpfe/26691]
Performance issue with hashing of class types and dependent decltypes

The front end previously only used the fully-qualified names (excluding
enclosing functions or template arguments of enclosing class templates) for
computing the hash value of class types.  It also ignored any dependent
decltype operands.  This could lead to a significant number of hash collisions
for template argument lists and thus result in poor performance.


2/8/24   [EDGcpfe/25513,EDGcpfe/25845]
C++23: Named Unicode character escapes

As described in WG21 paper P2071R2 and modified by core issue 2640, the
front end now accepts named Unicode character escapes in C++23 modes.  In
GNU and clang C++ emulation, the feature is accepted in all language
versions when gnu_version is at least 130000 or clang_version is at least
150000, respectively.  For example, with --c++23:

  const char *p = "0\N{DIGIT ONE}2";   // Equivalent to "012"


2/6/24   [EDGcpfe/26994]
Range-based for-loops in constexpr functions

A range-based for-loop causes the synthesis of an iterator variable.  When that
variable appears in a constexpr function, it is subject to the same rules as
ordinary user-defined variables.  Prior to C++23, the variable has to have a
literal type, but the front end previously failed to lift that restriction in
C++23 modes.  Furthermore, in constexpr function template instances, violating
the rule in pre-C++23 modes should have silently made the instance behave like
an ordinary non-constexpr function, but the front end erroneously issued a
diagnostic in such cases.  Both those issues are now fixed.


2/6/24   [EDGcpfe/26961]
Incorrect handling of subsumption with OR-ed constraints

Consider, in GNU C++20 mode:

  template<typename T, typename U> concept Same = __is_same_as(T, U);
  template<typename T> concept A = Same<T, float>;
  template<typename T> concept B = Same<T, double>;
   
  template<typename T> struct S {};
  template<typename T> requires A<T> || B<T> struct S<T> {};
  template<typename T> requires A<T> struct S<T> {};
   
  S<float> s;

In this example, the last partial specialization S<T> is more specialized than
the prior partial specialization (which ORs two constraints) and should thus
be selected for S<float>.  However, the front end previously failed to
correctly order the two partial specializations.  That is now fixed.


2/6/24   [EDGcpfe/26995]
Incorrect lowering of some ternary operators could lead to undefined behavior

In cases where a return statement returns the value of a "?" operation and that
expression qualifies for two optimizations (namely the copy elision
optimization for a class prvalue "?" operation and the expression is within a
function that returns its value via a copy constructor) the resulting lowered
code had inadvertently discarded the value of the expression, resulting in
incorrect code and likely undefined behavior at run time.  For example (with
--c++11):

  struct A {
    int value = 42;
    A() = default;
    A(const A &) = default;
    A(A &&);
  };
  A f(const A a) {
    return true ? a : A{};    // Previously the returned value was undefined.
  }
  int main() {
    return (f(A{}).value != 42);
  }


2/6/24   [EDGcpfe/24190,EDGcpfe/24576,EDGcpfe/26799]
Spurious redeclaration error with template friends

An unqualified friend declaration usually declares the name in the innermost
enclosing namespace scope as a hidden member.  In cases where the friend
declaration depends on template parameters of an enclosing class template, this
could result in redeclaration errors when the friend is instantiated.  For
prototype instantiations, the front end therefore declares these template
friends in the class scope.  This, however, can result in redeclaration errors
with other class members.  In modes where friend name injection is disabled,
the friend declaration now gets suppressed in the prototype instantiation.  For
example, with --c++11:

  template<typename>
  struct C {
    template<typename> friend struct A;
    struct A;  // Previously a spurious error.  Now okay in modes where friend
               // name injection is disabled.
  };


2/1/24   [EDGcpfe/26980]
Excessive time walking deeply nested local scopes

In some configurations, the IL walk process to maintain "needed" flags spent
excessive time traversing local scopes (unnecessarily revisiting some scopes
repeatedly).  This has now been optimized.


1/31/24  [EDGcpfe/26975]
C++-generating back end: sizeof expression with local static variable

When a sizeof expression refers to a local static variable whose type is an
unnamed class or enumeration, the C++-generating back end replaced the
expression operand with a type operand whose name was an undeclared
temporary (of the form __T12345678), resulting in generated code that could
not be compiled.  This is now fixed.  For example:

  void f() {
    static const struct {
      int i;
    } a[] = {
      1, 2
    };
    unsigned int b[sizeof(a)];   // Previously "sizeof(const __T12345678[2])"
  }


1/30/24  [EDGcpfe/26983]
Unbounded loop in class type property queries from outside the front end

Attempting to call certain class type query functions (like is_pod_class) from
outside the front end could result in executing an unbounded loop in function
set_active_using_list_scope_depths (in scope_stk.c).  That is now fixed.


1/30/24  [EDGcpfe/25868]
Propagation of consteval

The standardization committee's paper P2564R3 clarifies that some constexpr
functions calling consteval functions that cannot be immediately constant-
evaluated should themselves become consteval.  For example:

  consteval int g(int x) { return 2*x; }
  template<typename T> constexpr T f(T p) {
    return g(p);  // Previously an error.  Now okay.
  }
  static_assert(f(1) == 2);

Previously, this was an error because g(p) cannot be immediately evaluated
(because p is unknown).  Now, f<int>(int) becomes implicitly consteval and the
example is accepted (because a consteval call within a consteval function need
not be immediately evaluated).


1/29/24  [EDGcpfe/26982]
GNU C compatibility: gcc version support for _Float* types

In some configurations, the changes for EDGcpfe/26982 (in version 6.6) only
enabled use of the _Float* types for gcc mode but resulted in an assertion
failure when a literal uses one of the floating-point suffixes
corresponding to _Float* types.  This is now fixed.  For example, with
--gcc --gnu_version=70000:

  _Float32 f32 = 0.0f32;   // Previously an assertion failure in some
                           // configurations, now handled correctly


1/29/24  [EDGcpfe/11866,EDGcpfe/26355.EDGcpfe/26704]
Replace sprintf calls with memory safe C++ code and associated fixes

The front end no longer uses sprintf calls.  All prior sprintf calls have been
replaced by either an instance of EDG's Allocated_string or a call to snprintf
(sprintf_s for Windows host systems) where appropriate.

Additionally, as part of this work, db_symbol now uses a dynamically-sized
buffer.  Thus, db_symbol now works for symbol names that require more than
1000 characters and in more situations with low stack space.


1/29/24  [EDGcpfe/21278,EDGcpfe/25457]
Microsoft compatibility: __is_convertible_to

In Microsoft C++ modes, the __is_convertible_to type traits helper previously
took a Microsoft-mode anachronism into account that allows an lvalue reference
to a non-const class type to bind to a class rvalue.  However, starting with
version 19.00, the Microsoft compiler does not do so.  For example:

  struct C {};
  C &c = C();  // Anachronism still accepted in permissive Microsoft mode.
  static_assert(!__is_convertible_to(C, C &), "Unexpected");
                  // Previously failed in permissive Microsoft mode due to the
                  // anachronism illustrated above.  Now okay.


1/25/24  [EDGcpfe/26781]
Backing expressions for conversions of constant values

Consider:

  unsigned short x;
  void g() {
    x = 10000*10000;
  }

The front end constant-folds the multiplication 10000*10000 and truncates its
value to fit in x (with a warning).  Previously, the backing expression for
that constant represented the multiplication, but not its result prior to the
type change (i.e., the backing expression did not include the value 100000000).
Now, the intermediate constant result (prior to the cast) is represented in the
backing expression.


1/25/24  [EDGcpfe/25224,EDGcpfe/26158]
Abort on _Generic construct with GNU statement expression

Consider, in GNU C11 mode:

  void g(void) {
    _Generic(0, int : 0, default : sizeof({}));
  }

This previously aborted in configurations involving the C++-generating back end
with IL_SHOULD_BE_WRITTEN_TO_FILE set to 1 (or TRUE).  The abort was due to an
inconsistent representation of the source sequence entries for the statement
expression within the _Generic construct.  That is now fixed.


1/24/24  [EDGcpfe/26968]
Miscellaneous build/configuration issues

A number of build issues in certain configurations or with certain host
compilers have been addressed.


1/23/24  [EDGcpfe/26674]
C++-generating back end: incorrectly-omitted explicit template argument

In some cases, the C++-generating back end could omit a required explicit
template argument in a function call, resulting in code that could not be
compiled.  This is now fixed.  For example, with --c++17:

  template<typename T> constexpr int f() {
    return 0;
  }
  template<typename T, int I> struct A {
    template<typename U> A(const U&) { }
    using TP = T;
  };
  template<typename T> A(const T&) -> A<float, f<T>()>;
  void g() {
    A a{0};
    using X = decltype(a);
    typename X::TP t = 0.0F;   // Previously incorrectly generated as
                               // A<float,f<>()>::TP", now as
                               // A<float,f<int>()>::TP"
  }


1/23/24  [EDGcpfe/26971]
IA-64 ABI: Layout of [[no_unique_address]] fields

For some fairly complex cases, the front end did not correctly lay out fields
in the presence of [[no_unique_address]] fields.  Some of these mistakes were
due to a regression introduced by the changes for EDGcpfe/26693 in version 6.6
of the front end (but some other issues were preexisting).  All known layout
errors due to [[no_unique_address]] fields are now fixed.


1/23/24  [EDGcpfe/26972]
End position of expression nodes resulting from template substitution

In some configurations with EXTRA_SOURCE_POSITIONS_IN_IL, the end position for
nodes corresponding to id-expressions (e.g., expressions that name a variable)
could be erroneous.  That is now fixed.


1/22/24  [EDGcpfe/26598,EDGcpfe/26866]
Matching of constrained out-of-class member template declarations

Previously, the front end failed to match an out-of-class member template
definition with its declaration if the class was constrained using a requires
clause in its template header.  For example, with --c++20:

  template<typename> struct B;
  template<typename T> requires true
  struct B<T> {
    template<int> struct N;
  };
  template<typename T> requires true
  template<int> struct B<T>::N {};  // Previously a spurious error.  Now okay.


1/21/24  [EDGcpfe/26946]
C++-generating back end: explicit specialization of pure virtual function

The C++-generating back end previously erroneously added "= 0" to the
declaration of an explicit specialization of a pure virtual member function
of a class template.  This is now fixed.  For example:

  template<typename T> struct S {
    virtual void f() = 0; 
  };
  template<> void S<int>::f();   // Previously generated as "f() = 0;"


1/19/24  [EDGcpfe/26962]
Microsoft compatibility: Ambiguous member access and using-declarations

The changes for EDGcpfe/16204,EDGcpfe/26719 (with the additional fix of
EDGcpfe/26854) have been generalized to handle disambiguation via using-
declarations in multiple classes along the derivation path of an ambiguous
base class.


1/19/24  [EDGcpfe/26965]
Rewrite front end general memory management

The general memory management facility of the front end has been rewritten to
improve performance and reduce maximum memory usage.


1/19/24  [EDGcpfe/26783]
Microsoft compatibility: commas in variadic macro arguments

The changes for EDGcpfe/25674 (in version 6.5) introduced a regression that
caused incorrect expansion of some macros involving commas in variadic
macro arguments when emulating the traditional Microsoft preprocessor.
This is now fixed.  For example, with --microsoft --no_ms_std_preprocessor:

  #define A(x)         B x
  #define B(x, y)      C y
  #define C(...)       D(__VA_ARGS__, 1)
  #define D(x, y, ...) y
  #define E(x)         A x
  #define M            ((5, (((6 , 7), ()), 8, 9)))
  int i = E(M);   // Previously expanded to 8, now 1


1/17/24  [EDGcpfe/25870]
C23: Use of deprecated attribute on enumerator

Use of the new C23 "deprecated" attribute on an enumerator had failed to
trigger an applicable diagnostic in C23 mode.  For example:

  enum E {
    e [[deprecated]]
  };
  enum E x = e;   // Now issues a warning with --c23.


1/16/24  [EDGcpfe/26954]
Stable C and C++ unique identifiers for debug modes

The front end will now generate stable identifiers for temporary variables when
-d0 is used for C and C++ generating back ends as an additional troubleshooting
aid.


1/15/24  [EDGcpfe/18976,EDGcpfe/21888,EDGcpfe/24613,EDGcpfe/26723,
          EDGcpfe/26774]
Matching of template template parameters containing parameter packs

According to the standard, a template template argument A also matches a
template template parameter P containing a parameter pack if each of A's
template parameters matches the corresponding template parameter of P.  The
front end, however, did not allow this more lenient matching during
substitution of deduced function template arguments.  For example, with
--c++11:

  template<typename>
  struct A { };
  template<template<typename, typename...> class C, typename T, typename... U>
  int f(C<T, U...>);
  int i = f(A<int>());  // Previously a spurious error.  Now okay.


1/11/24  [EDGcpfe/26944]
GCC and MSVC compatibility: Member function types in type trait helpers

When parsing type trait helpers, the front end now accepts cv-qualifiers and
ref-qualifiers on function type operands in non-Clang modes.  For example:

  static_assert(!__is_trivially_copyable(int()&));
    // Previously an error.  Now accepted in non-Clang modes.
                                                    

1/11/24  [EDGcpfe/26929]
Abort on optimization of virtual call involving default arguments

Consider, in GNU, Clang, or Microsoft mode:

  template<typename> struct B {
    virtual void f(int = 0) const;
  };
  struct C: B<int> {
    void f(int) const;
  };
  template<typename T> struct D: C {
    using B<T>::f;  // Nonstandard, but accepted by other compilers.
  };
  int main() {
     D<int> di;
     di.f();  // Previously elicited an abort during lowering.  Now okay.
  }

The front end previously aborted in lowering because of invalid IL being
generated.  This invalid IL was a consequence of attempting to optimize the
virtual call di.f() when the default argument of the statically-determined f
(B<int>::f in this case) has not been instantiated yet.  This is now fixed.


1/11/24  [EDGcpfe/26943]
C++-generating back end: issues with Microsoft-related target compilers

There are two flags used by the C++-generating back end to control the
generated code in Microsoft-mode compilations:
microsoft_dialect_is_generated_code_target and
msvc_is_generated_code_target.  The former allows the generated code to
contain Microsoft-specific language features, while the latter causes the
C++-generating back end to assume that the target compiler is actually some
version of MSVC and to work around certain bugs and idiosyncrasies of that
implementation.  Previously, when msvc_is_generated_code_target is FALSE but
microsoft_dialect_is_generated_code_target is TRUE, the C++-generating back
end incorrectly put out the __alignof keyword as __ALIGNOF__.  This is now
fixed.  In addition, the front end accepts the --msvc_target_version
command-line option, but it failed to make the reasonable inference that
specifying that option should also result in setting
msvc_is_generated_code_target to TRUE.  That omission has also been fixed.

(Note that when CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT is set to TRUE,
compiling in Microsoft mode results in
microsoft_dialect_is_generated_code_target being set to TRUE, with the
value of msvc_is_generated_code_target being taken from the value of the
MSVC_IS_GENERATED_CODE_TARGET configuration macro.)


1/11/24  [EDGcpfe/26879]
C++-generating back end: type of argument for "auto" template parameter

In certain cases involving alias templates and nontype template parameters
with a deduced type, the C++-generating back end could generate code with
different semantics from the original source.  For example, with --c++20,

  template<auto> struct A {
    template<class...> using X = A;
  };
  template<int i> using B = A<i>;
  template<class... Ts> using C =
    typename B<sizeof...(Ts)>::template X<Ts...>;   // #1
  void f() {
    C<>() = A<0>();   // #2
  }

In the generated code, the C++-generating back end put out the type-id at
#1 using the underlying type of B as the qualifier instead of B itself:

  typename A<sizeof...(Ts)>::template X<Ts...>

However, in  the original source, there is an implicit conversion from
size_t to int for the argument of B, but the generated code omitted that
conversion, resulting in different deduced types for the "auto" parameter
of A, and the assignment at #2 failed because of incompatible types.  This
is now fixed: the implicit conversion is represented in the generated code
by an explicit cast:

  typename A<(int)sizeof...(Ts)>::template X<Ts...>


1/11/24  [EDGcpfe/26797]
Enclosing pack expansion in abbreviated member function template declaration

Previously, an abbreviated member function template declaration naming an
enclosing template parameter pack would abort with a failed assertion in
find_placeholder_arg_for_pack (scope_stk.c).  For example, with --c++20:

  template<typename ...> struct A {};
  template<typename ... T> struct C {
    static int f(A<T ...>, auto);
  };
  int i = C<int>::f(A<int>(), 1);  // Previously triggered an internal error.
                                   // Now okay.


1/10/24  [EDGcpfe/26922,EDGcpfe/26955]
Generated copy constructor with inaccessible subobject constructor

Consider:

  class C {
    C(C&) = default;  // Private copy constructor with trivial copy semantics.
  };
  struct S {
    C c;
  };
  void f(S &p) {
    S s(p);  // Failed to issue an error with version 6.6.  Now fixed.
  }

The generated copy constructor of S should be a deleted constructor because
S does not have access to the copy constructor of C.  However, the changes for
EDGcpfe/26518 introduced a regression in version 6.6 of the front end causing
it to fail to mark the generated copy constructor of S as deleted.  That is
now fixed.  A similar issue occurred with the move constructor of S and that
is now also fixed.


1/10/24  [EDGcpfe/26921]
Clang/GCC compatibility: __is_trivial

Consider:

  struct S {
    S() = delete; 
    bool flag = false;
  };
  static_assert(!__is_trivial(S));  // Previously failed in some modes.
                                    // Now okay.

Type S is a nontrivial class type both because its default constructor is
deleted (which makes it ineligible) and because it has a default member
initializer (which makes the default constructor nontrivial).  Clang and GCC
typically do not disqualify a class from being trivial if its default
constructor is deleted and the front end already emulates that behavior in its
respective emulation modes.  However, default member initializers do make the
class nontrivial for GCC and Clang and the front end now emulates that as well.


1/9/24   [EDGcpfe/26916]
GNU C++14 compatibility: Incomplete variable template types

In GNU C++14 mode, the front end now accepts variable templates declared with
an incomplete class type.  For example:

  struct S;
  template<typename> S v;  // Ordinarily an error.  Now accepted in GNU C++14
                           // mode.


1/9/24   [EDGcpfe/26941]
Preserve typedefs in symbol headers for conversion operators

In version 6.6 (EDGcpfe/26831) a change was made to how symbol headers are
generated for type conversion operators.  Prior to this change the
conversion operator type included in the operator's symbol header was
partially dealiased depending on configuration
(DEFAULT_DISPLAY_TEMPLATE_TYPEDEFS_IN_DIAGNOSTICS) and its associated
command line switches.

The change made in 6.6 attempted to make the operator symbol header name
consistently use a dealiased type regardless of diagnostics settings.  However,
this was never correctly performed for types in the std namespace.

Following customer feedback, this has been reverted to the previous 6.5
typedef-dealiasing rules (equivalent to
DEFAULT_DISPLAY_TEMPLATE_TYPEDEFS_IN_DIAGNOSTICS=FALSE).  This can be observed
in the following example where a diagnostic had referred to the conversion
operator as "src_ty::operator dest_typedef" in 6.5 and "src_ty::operator
dest_ty**" in 6.6:

  struct dest_ty {};
  using dest_typedef = dest_ty**;
  struct src_ty {
    template<int>
    operator dest_typedef() { return nullptr; }
  };


1/9/24   [EDGcpfe/26939]
Do not dealias typedefs inside of inline namespaces in std

In version 6.6 (EDGcpfe/26831) the front end added improved support for
diagnostics including typedef types.  This improved support excludes typedefs
inside of the std namespace from being dealiased.  However, inline namespaces
within the std namespace were not included.  Consider how the diagnostic
message type place holder is substituted for the following simplified libc++
code:

  namespace std { inline namespace v1 {
    template <class _CharT>
    class basic_string;

    using string = basic_string<char>;
  } }

  int x = std::string(); // previously: no suitable conversion function
                         // from "std::v1::string"
                         // (aka "std::v1::basic_string<char>") to "int" exists
                         // now: no suitable conversion function from
                         // "std::v1::string" to "int" exists


1/9/24   [EDGcpfe/26920]
Clang C++ compatibility: __is_trivially_equality_comparable

In Clang C++ mode with clang_version >= 170000 the front end now supports the
type trait helper __is_trivially_equality_comparable.  It produces a true
value if its type operand designates a type whose "==" semantics are known to
match C's memcmp comparison function (i.e., byte-for-byte equality checking).
In particular, it produces a true value for non-enum integer types and for
class types with a defaulted operator==, no virtual functions or virtual bases,
no padding, and all subobjects that are themselves byte-for-byte comparable.
For example:

  struct S {
    int i;
    bool operator==(S const&) const = default;
  };
  static_assert(__is_trivially_equality_comparable(S));
  struct E {
    bool operator==(E const&) const = default;
  };
  static_assert(!__is_trivially_equality_comparable(E));

In this example, E is empty but is padded to have a size of one byte: Since the
content of padding bytes is not generally known, comparing the bytes of an E
value using memcmp is not equivalent to invoking E::operator== (which would
always return true).


1/8/24   [EDGcpfe/26919]
Implement __builtin_FILE_NAME() and changes to file name builtins

Clang 17 added a new __builtin_FILE_NAME() builtin function.  This function
returns the file name without any qualifying path (i.e., it's just the file
name).  This function is now implemented in Clang mode.

Additionally, for closer conformance with other compiler implementations of
__builtin_FILE() and __builtin_source_location(), the EDG front end now returns
the file name with path qualification.


1/5/24   [EDGcpfe/26924]
Clang C++11 compatibility: Statements in constexpr function templates

The changes made for EDGcpfe/26319, which cause statements other than return
statements to be accepted in GNU-C++11-mode constexpr function templates, have
been extended to apply to Clang C++11 mode with clang_version >= 30300.
Furthermore, a warning is now issued when that extension is relied on.


1/5/24   [EDGcpfe/26927]
Incorrect constant-evaluation of comparison of certain addresses

Consider:

  constexpr bool is_same_object(const int &x, const int &y) {
    return &x == &y;
  }
  constexpr bool is_not_same_object(const int &x, const int &y) {
    return &x != &y;
  }
  int i = 0;
  static_assert(is_same_object(i, 42) == false, "");
    // Previously failed (wrong result).  Now okay.
  static_assert(is_not_same_object(i, 42), "");
    // Previously failed to constant-evaluate.  Now okay.

When comparing a run-time address (such as that of i in the example) with a
constant-evaluated address (e.g., the address of the temporary created for 42
in the example), the == operator incorrectly produced a true result.  In
similar circumstances, the != operator incorrectly failed constant-evaluation
(the addresses are known to be distinct).  That problem is now fixed.


1/5/24   [EDGcpfe/26027,EDGcpfe/26926]
GNU/Clang-mode abort on constant pointer arithmetic with zero-sized types

Consider, in GNU or Clang C++ modes:

  typedef int Z[0];
  constexpr bool g() {
    auto arr = new Z[2];
    auto d = arr[1];
    return true;
  }
  bool a = g();

Previously this aborted with an internal error in get_array_pos (interpret.c)
due to the subscripting of an array with zero-sized elements.  That is now
fixed.


1/4/24   [EDGcpfe/26918]
Abort on by-reference capture of array in GNU/Clang mode

Consider:

  int main() {
    int arr[5][5];
    auto lambda = [&arr]() {
      int x = arr[1][1];
    };
  }

The changes for EDGcpfe/26341 introduced a regression in version 6.6 of the
front end causing the example above to abort with an internal error in
get_runtime_array_pos (interpret.c).  That is now fixed.


1/2/24   [EDGcpfe/25475,EDGcpfe/26903]
Spurious GNU-mode incomplete-type error for static data member of template

Consider, in GNU C++ mode:

  template<typename> struct S {
    constexpr static int arr[]{};
    static long const L = sizeof(arr);
    static void f() { long length = L; }
  };
  void g() { S<void>::f(); }

Previously, this triggered an error in GNU C++ mode complaining that the type
of arr is incomplete.  That is now fixed.


12/30/23 [EDGcpfe/26913]
C++-generating back end: undefined behavior with MAKE_FRONT_END_CALLABLE

The changes for EDGcpfe/26339 (in version 6.6) introduced a global variable
that was not properly reinitialized in C++-generating back end
configurations in which MAKE_FRONT_END_CALLABLE is TRUE, potentially
leading to undefined behavior caused by use of invalid pointers from
previous invocations of the front end.  This is now fixed.


12/22/23 [EDGcpfe/26898]
Clang C++ compatibility: __nullptr

Clang appears to accept __nullptr as a synonym for the C++11 nullptr keyword,
but also accepts it in pre-C++11 modes.  The front end now emulates that
behavior Clang modes.


12/22/23 [EDGcpfe/26908]
Internal error on __constinit in pre-C++20 GNU modes

An incorrectly-written assertion check in the front end caused it to fail that
assertion in pre-C++20 GNU mode when a default-initialized __constinit variable
has a nontrivial destructor.  For example:

  struct S { ~S(); };
  __constinit S s;  // Previously triggered an internal error in some modes.

That is now fixed.


12/20/23 [EDGcpfe/26900]
Microsoft bugs compatibility: &(X::Y) pointer-to-member formation

Consider, in Microsoft C++ mode:

  template<typename> using Void = void;
  struct S {
    int& f();
  };
  template<typename, typename = void> constexpr bool Cond = false;
  template<typename T> constexpr bool Cond<T, Void<decltype(&(T::f))>> = true;
  static_assert(Cond<S>);

The static assertion should fail, because the partial specialization of Cond
fails substitution since &(T::f) with T=S is not valid (&T::f would create a
pointer-to-member constant, but the parentheses are not permitted).  MSVC,
however, does accept the case and the front end now emulates that behavior in
Microsoft bugs mode.


12/20/23 [EDGcpfe/26894]
Erroneous deletion of a default constructor due to a const member

Consider:

  struct S {
    int i;
    template<typename...> S();
  };
  template<typename> struct W {
    S s;
  };
  struct X {
    W<int> const w;
  };
  X x;  // Previously an error.  Now okay.

Previously, the front end issued an error claiming the default constructor of
X is deleted due to an error in the algorithm determining whether a class type
is const-default-constructible. That is now fixed.  Furthermore, older versions
of Clang previously did not consider the const-default-constructible property
in this context and the front end emulated that (see the Changes for
EDGcpfe/23439).  Clang 15, however, addressed that and the front end now
matches the current Clang behavior when clang_version >= 150000.


12/20/23 [EDGcpfe/26764]
Matching of template template parameters with auto-type non-type parameters

Consider, with --c++17:

  template<int> class A;
  template<template<auto> class P> int f();
  int i = f<A>();  // Previously an error. Now okay.

According to the rules in [temp.arg.template], this is currently ill-formed as
the template parameter is not at least as specialized as the template argument.
Most implementations, however, accept this, and it is anticipated that the C++
committee will eventually relax that rule for auto-type non-type template
parameters in a similar way to unconstrained template template parameters (see
committee paper P1616R1).  The front end has therefore been changed to also
accept this.


12/19/23 [EDGcpfe/26687]
C++-generating back end: aggregate initializers in function template
definitions

In configurations in which function template definitions are generated from
the prototype instantiation IL, the front end could abort with an assertion
failure in gen_initializer_constant when the source contains an aggregate
initializer appearing before the function declarator.  This is now fixed.
For example, with --c++14:

  struct C { int a[3]; int i; };
  struct B { C c[3]; };
  struct A { B b[3]; };
  template<typename T, int N>
  decltype(A{ 9 , 1 , 0 , N }, T()) f(T t) {  // Previously aborted
    return t;
  }


12/29/23 [EDGcpfe/26902]
Correct memory management bugs with null and zero-sized allocations

Previously, the front end could end up with unusable memory blocks in the front
end memory pool if free_fe is called with a NULL value or alloc_fe was called
for a zero-sized allocation.  This is now fixed.

Additionally, downstream memory issues where the wrong values were read from a
precompiled header have been fixed.

Furthermore, the behavior of deallocation functions in general has been
updated to consistently and correctly handle deallocation of NULL values.


12/19/23 [EDGcpfe/26899]
Allow --time_limit command-line option in configurations where DEBUG == 0

Previously the --time_limit command-line option was only enabled in
configurations where DEBUG == 1.  Now the --time_limit command-line option is
enabled regardless of the setting of DEBUG.


12/19/23 [EDGcpfe/26867]
Template parameter pack in requires clause of friend template declaration

Previously, the front end considered a requires clause for a friend template
declaration containing a parameter pack in some contexts to be incompatible
with the corresponding out-of-class declaration.  For example, with --c++20:

  template<typename ...> concept C = true;
  struct A {
    template<typename ... T>
    requires (C<T> && ...)
    friend class B;
  };
  template<typename ... T>
  requires (C<T> && ...)  // Previously a spurious error.  Now okay.
  class B;


12/19/23 [EDGcpfe/26775]
Abort on generic lambda with function parameter pack that is an expansion of an
outer pack

Previously, the front end failed to correctly expand the elements of a function
parameter pack that is an expansion of an outer pack, resulting in a failed
assertion in scan_function_body (func_def.c).  For example, with --c++14:

  template<typename ... T>
  auto f() {
    return [](auto, T ...) { };  // Previously triggered an abort.  Now okay.
  }
  auto l = f<short, int>();


12/18/23 [EDGcpfe/26874]
GNU compatibility: Extended asm "g" ("general") constraint

Consider, in GNU mode:

  struct S { operator int(); };
  void g() {
    S s;
    __asm__("" : "+g,x"(s));
  }

Ordinarily, operands in GNU-style extended asm constructs that are of class
type are converted to an arithmetic type if possible (which is the case here
for operand s).  However, that is not done for "memory operands" as determined
by the operand constraints.  Previously, the "g" constraint was not treated as
a memory operand, and thus the conversion to int was applied, but that means
that the operand becomes a prvalue which triggers an error since the "+"
constraint requires mutability.  That is now fixed: The "g" (for "general")
constraint is now recognized as indicating a (potential) memory operand,
thereby inhibiting the implicit conversion to an arithmetic type.


12/18/23 [EDGcpfe/26854]
Microsoft compatibility: Ambiguous member access and using-declarations

The changes for EDGcpfe/16204,EDGcpfe/26719 contained an error causing some
cases accepted by MSVC to still fail.  For example (in Microsoft C++ mode):

  struct B { void f() const; };
  struct B1: B {}; 
  struct B2: B {}; 
  struct D: B1, B2 {
    using B1::f;  // MSVC uses this to disambiguate access to D::f.
  };
  struct X: D {
    using D::f;
  };
  struct E: D {};
  void f(E *p) {
    p->f();  // Still considered ambiguous because of bug induced by the
  }          // using-declaration in X (which is not actually related to E).

That bug is now fixed.


12/18/23 [EDGcpfe/26869]
Function-style macros with '#' not followed by a parameter name

In a function-style macro definition, the C and C++ Standards require that
the stringize operator, '#', be followed by a parameter name, and the front
end reports an error when that requirement is violated.  Some compilers do
not enforce that rule, however, when preprocessing assembly code
(designated by the file suffix ".S") and simply copy the '#' into the
expanded text when the macro is invoked.  Although the front end does not
directly support preprocessing assembly code or sensitivity to the suffixes
of source files, it has now been updated to allow emulating this behavior,
treating this error as discretionary and, when its severity is reduced,
producing that same expanded text when such a macro is invoked.  For
example, with -E --diag_suppress=exp_macro_param:

  #define M(x) # 3   // No error reported
  M(abc)             // Expands to "# 3"


-------------------------------------------------------------------------------
Version 6.6, December 18, 2023

12/1/23  [EDGcpfe/26831]
Show the underlying type in type placeholder diagnostics

The front end previously would fulfill diagnostic messages using type
placeholders like the following:

  ec_example;;"the example type is %t"

as something like:

  error: the example type is "typedef_type<int, other_typedef_type>"

This has been changed, so that when an alias is detected the front end now
displays the underlying type, e.g.:

  error: the example type is "typedef_type<int, other_typedef_type>"
         (aka "tuple<int, float>")

As an additional note, typedefs in the std namespace are excluded from this
behavior.  This means that if "std::string" is appears in a diagnostic the
underlying type will not be displayed, i.e., things like "std::string" (aka
"std::basic_string<char>") will not appear.

As a matter of implementation quality, the front end's previous behavior for
DISPLAY_TEMPLATE_TYPEDEFS_IN_DIAGNOSTICS (and the associated command line
switches) no longer affect type placeholders.  However, other instances of
types in front end output (such as those in an instantiation backtrace) are
still affected by this option.


12/1/23  [EDGcpfe/26842]
C++23 mode update

The front end now sets the value of the global variable std_version and the
value of the predefined __cplusplus macro to 202302 in C++23 mode (in
correspondence with the value specified by the Draft International Standard).

Additionally, the front end configuration macro DEFAULT_CPP_MODE now accepts
202302 for use of C++23 mode by default.


12/1/23  [EDGcpfe/26698]
Experimental reflection support

The front end now includes optional experimental support for reflection
features along the lines of the C++ standardization committee's evolving
paper P2996.  This support is considered "experimental" because:
  1) it is known to be incomplete,
  2) it currently does not work correctly with the C++-generating back end,
  3) it has only been lightly tested, and
  4) it may be drastically revised or removed altogether depending on how
     the P2996 proposal progresses through the standardization process.
To enable access to these experimental features, the configuration macro
REFLECTION_ENABLING_POSSIBLE must be set to TRUE.  When that is the case,
reflection support can be enabled with the command-line option
--set_flag=reflection or by setting the configuration macro
DEFAULT_REFLECTION_ENABLED to TRUE.  Along with the front end implementation
proper also comes a new standard-like header "meta.stdh": It is recommended
that this be placed in a directory such that it can be included with:

  #include <experimental/meta>


11/30/23 [EDGcpfe/26759]
Multi-line comments on multiple-inclusion guards

The front end reduces compilation overhead by recognizing common patterns
of preprocessor directives that enclose the contents of a header file and
suppressing the inclusion of the header altogether if the guarding
condition is not satisfied.  The changes (in version 6.5) for
EDGcpfe/24782,EDGcpfe/25697,EDGcpfe/25898 introduced a bug in this
processing that could result in incorrectly suppressing or performing an
inclusion when the guarding preprocessor directive ends in a multi-line
comment.  For example, given a header file x.h,

  #ifdef M  /* Multi-line comment.
    */
  typedef int I;
  #endif

and a source file,

  #include "x.h"
  #define M
  #include "x.h"
  I i;   // Relies on the second #include for the definition of "I"

the front end could previously incorrectly suppress the second inclusion of
"x.h" and thus fail to define the type I, resulting in a spurious error.
This regression is now fixed.


11/29/23 [EDGcpfe/26664]
Expansion of nested init capture pack (IL CHANGE)

Previously, the front end would repeatedly expand only the first element of an
init capture pack that was captured in a nested lambda.  As part of this
change, the a_lambda_capture field captured.init_capture_field, a union member,
points to the field of the init capture for any such indirect capture.  For
example, with --c++20:

  template <typename ... T> constexpr int f(T ... t) {
    return [...c = t] {
      return [c...] {
        return (c + ...);
      }();
    }();
  }
  static_assert(f(1, 2) == 3);  // Previously a spurious error.  Now okay.


11/28/23 [EDGcpfe/26700]
C++-generating back end: ambiguities with type-transforming intrinsics

In some complex examples, the C++-generating back end put out a
type-transforming intrinsic (see the entry for EDGcpfe/26193) in a position
where syntactic disambiguation would result in treating the intrinsic name
as the start of an expression instead of the start of a type, leading to
syntax errors when compiling the generated code.  This is now fixed; the
generated code now uses the type resulting from application of the
intrinsic in place of the intrinsic construct in contexts that would result
in incorrect disambiguation.


11/28/23 [EDGcpfe/24472]
GCC compatibility: Parameterized incomplete base classes

Consider:

  struct I;
  template<typename> using A = I;
  template<typename T> struct D: A<T> {};  // Now accepted in GNU modes.

The base class specifier A<T> is parameterized, but it resolves to a known
incomplete class I, which is an error.  However, GCC accepts such cases and
the front end now emulates that behavior in GNU C++ modes.


11/27/23 [EDGcpfe/26814]
GCC compatibility: Using-declarations and dependent base classes

Consider:

  struct E {};
  template<typename BT> struct D: BT {
    using E::x;  // Previously an error in all modes.
  };             // Now okay in GNU C++ modes.

This is invalid C++ because E has no member x.  However, GCC accepts the
example, presumably under the assumption that BT might instantiate to a type
named E (although attempting to instantiate D with such a type still results
in an error with GCC).  The front end now emulates this behavior.


11/27/23 [EDGcpfe/26569,EDGcpfe/26743]
Subobjects as nontype template arguments

Prior to C++20, the standard required a nontype template argument of pointer or
reference type to refer to a complete object.  This restriction has been
removed in C++20 and a nontype template argument can now also refer to a
subobject.  For example, with --c++20:

  template<int &> struct C { };
  struct B {
    int i, j;
  } b;
  C<b.j> c;  // Previously a spurious error.  Now okay.


11/22/23 [EDGcpfe/26808]
Divide by zero

A missing skip_typerefs had caused a division by zero floating-point exception
on cases where the underlying type of a vector has a typeref (with --clang):

  using my_char = char;
  using vec __attribute__((vector_size(4))) = my_char;
  auto x = ~vec{1, 2, 10, 20};


11/21/23 [EDGcpfe/26742]
Expansion of constrained template type parameters

Previously, the front end never considered a type-constraint to be expandable,
even if it included a template argument list containing an unexpanded template
parameter pack.  For example, with --c++20:

  template<typename T, typename U>
  concept C = sizeof(T) == sizeof(U);
  template<typename ... T>
  struct B {
    template<C<T> ... U>
    static int f(U ...);
  };
  auto v = B<char, int>::f('a', 2);  // Previously a spurious error.  Now okay.


11/20/23 [EDGcpfe/26795]
Microsoft C compatibility: Statement expressions and __extension__

In Microsoft C mode with microsoft_version >= 1939 the front end now accepts
GNU-style statement expressions as well as the __extension__ keyword.  Both
features no longer require GNU_EXTENSIONS_ALLOWED to be configured TRUE.


11/20/23 [EDGcpfe/26770]
C++-generating back end: parenthesized aggregate initialization

Given the following declaration, with --c++20,

  auto a = new int[][2] ( { 1 }, { 2, 3 } );

the C++-generating back end previously generated this as:

  auto a = new int[][2] { 1, 2, 3 };

omitting the braces around the nested aggregates and replacing the outer
parentheses with braces.  This has now been fixed, and the generated code
correctly reflects the syntax used in the original source.


11/17/23 [EDGcpfe/25799]
Microsoft and GNU compatibility: Nondependent decltype constructs in templates

Consider:

  template<bool> int v;
  template<typename> bool b = v<b<decltype(0)>>;

Ordinarily, this is an error because because b<decltype(0)> is clearly not a
valid template argument (e.g., it is not constant).  However, it is now
accepted in Microsoft C++ modes and in GNU C++ modes with gnu_version < 130000
(to match the behavior of the corresponding compilers).  This is achieved by
treating the nondependent decltype(0) construct as dependent in some template
contexts.


11/16/23 [EDGcpfe/26756]
Position information for synthesized call to comparison function

Consider:

  #include <compare>
  struct S {
    int i;
    friend std::strong_ordering operator<=>(S, S) = default;
  };
  void g(S x, S y) {
    for(; x != y; ) {}
  }

The expression x != y is rewritten in terms of a call to a compiler-generated
operator==.  Previously, the position range recorded for that call node
extended from the beginning of the "!=" token to the semicolon token
(inclusive).  Now it correctly starts at the x token and ends at the y token.


11/16/23 [EDGcpfe/26800]
Spurious error on constexpr defaulted default constructor

In somewhat complex cases, the front end issued a spurious error on a defaulted
constructor declared constexpr because it erroneously considered a constructor
in a base class to be inaccessible despite that constructor having protected
accessibility.  That problem is now fixed.


11/16/23 [EDGcpfe/26793]
Permit invalid dependent string initializers

Consider:

  template<typename T> struct S {
    T const str[1] = "*";
  };

This is invalid because the literal "*" requires two characters and str only
has one.  However, Clang, GCC, and MSVC do not diagnose this case.  The front
end now emulates that behavior in the corresponding modes.


11/15/23 [EDGcpfe/26758]
Memory corruption on interpretation of lifetime-extended temporary

Under certain circumstances a pointer in the interpreter state used to manage
the handling of lifetime-extended temporary objects could be left dangling.
Sometimes, that resulted in memory corruption and unpredictable aborts later
on.  That is now fixed.


11/15/23 [EDGcpfe/25416,EDGcpfe/26780]
Abort on use of type of designator constant

Previously, designators in aggregate constants were represented by constant
entries of kind ck_designator and with a null type field.  However, the front
end occasionally queries the type of a_constant entries independently of the
entry kind, and that easily resulted in aborts due to null pointer dereference.
To address such issues, designator constants are now assigned the void type.


11/15/23 [EDGcpfe/26138]
Spurious Microsoft-mode error on in-class constexpr static data member

Consider, in Microsoft mode:

  template<typename> struct S {
    template<typename> static constexpr int N = 0;
  };
  template<typename T> struct X: S<T> {};

In Microsoft mode, this previously triggered spurious errors suggesting a
missing initializer for N.  That is now fixed.


11/15/23 [EDGcpfe/26683]
Spurious floating-point underflow indications when -ffast-math is used

The GNU compiler supports a -ffast-math option that enables a number of
optimizations to support faster floating-point operations at run time.  These
optimizations alter the semantics of the IEEE 754 floating-point operations
(e.g., subnormals, NaNs, infinities and signed zeros are eliminated) so it
is advised not to use this option when compiling and linking the front end.

In certain cases, the linking of an application containing the front end
(e.g., as a library) might occur with the -ffast-math command-line option
causing the resulting executable to be linked with crtfastmath.o, which alters
the MXCSR register at process startup.  A change has been made to suppress
the generation of spurious underflow errors in this case.


11/15/23 [EDGcpfe/26773]
GNU-mode abort on nonstandard subscript operation in a template

Consider:

  typedef void (*error_callback)();
 
  template<int T> struct S {
    static void (*pf)();
    void f() {
      pf[0] = 0;  // Previously aborted in GNU C++ mode.  Now okay.
    }
  };

The subscripting of pf is invalid since pf is a pointer-to-function type.
However, GCC accepts it in templates.  In GNU mode, however, the front end
previously aborted with an internal error in type_pointed_to (types.c) while
attempting to emulate GCC's behavior.  That is now fixed (the example is now
accepted in GNU C++ mode).


11/15/23 [EDGcpfe/21120,EDGcpfe/26099]
Microsoft-mode abort on nonreal member using-declaration

Consider:

  struct B { int b; };
  template<typename T> struct C: public T { };
  template<int, typename T = B> struct D: C<T> { using C<T>::b; };
  template<int N> struct X: D<N> {};

In Microsoft mode, this previously caused the front end to abort with an
internal error in create_member_using_declaration (in class_decl.c).  This
occurred while performing a "nonreal base class instantiation" (a process that
is specific to Microsoft mode).  This issue is now fixed.


11/15/23 [EDGcpfe/24256,EDGcpfe/26665]
Partial specialization with constrained placeholder non-type template parameter

Previously, the front end did not consider a partial specialization with a
non-type template parameter of constrained placeholder type to be more
specialized than the primary template.  For example, with --c++20:

  template<class T> concept C = true;
  template<auto> struct B;
  template<C auto V>
  struct B<V> { };  // Previously a spurious error.  Now okay.


11/14/23 [EDGcpfe/26786]
Clang compatibility: Incorrect feature test macro name

The Clang-specific cxx_generic_lambdas feature test macro had inadvertently
been misspelled as cxx_generic_lambda and is now fixed.


11/13/23 [EDGcpfe/26771]
C++-generating back end: block-scope names in template arguments

The changes for EDGcpfe/20557 (not in a release, but widely distributed in
patch form) revealed a preexisting but previously unlikely problem in the
handling of block-scope names in template arguments.  In some cases, an
out-of-scope name could appear in a template argument in the output of the
C++-generating back end.  This is now fixed.  For example, with
--gnu_version=130200:

  template<typename> struct A { };
  void f() {
    {
      enum B { z };
      A<__underlying_type(B)> x;
    }
    {
      enum C { z };
      A<__underlying_type(C)> y;   // Previously generated as
                                   // A<__underlying_type(B)>, now A<int>
    }
  }

Both __underlying_type(B) and __underlying_type(C) resolve to "int", so
both mentions of A refer to the same instance.  Because that instance was
first instantiated with __underlying_type(B), the same template argument
was previously erroneously used in the type of "y".  Now the C++-generating
back end checks that the names in the template argument are usable in the
current context and, since that is not the case in the type of "y", puts
out the name of the instance using the resolved type, "int", as the
template argument.


11/13/23 [EDGcpfe/26707]
C++-generating back end: incorrect replacement of dependent typedef

In some complex cases, the C++-generating back end replaced a use of a
dependent typedef with the underlying type of an unrelated dependent
typedef from a different context, resulting in incorrect generated code.
This is now fixed.


11/2/23  [EDGcpfe/26757]
GNU C++ compatibility: Inheriting from classes with a flexible array member

In GNU C++ mode, the front end previously always diagnosed inheriting from a
class with a flexible array member when gnu_version >= 60000.  Now, such
derivations are accepted if the derivation does not introduce data members.
For example:

  struct B { int n; int x[]; };
  struct D: B {};  // Now accepted in GNU C++ modes.

The diagnostic for inheriting from classes with a flexible array member or
inheriting from a union has also been changed to be more specific.


11/1/23  [EDGcpfe/22470,EDGcpfe/26748,EDGcpfe/26751]
Spurious errors on defaulted members with an explicit exception specification

Consider:

  struct S {
    S();
    ~S() noexcept(false);
  };
  struct X {
    X();
    ~X() noexcept(false) = default;
    S const s;
  };
  X x;

This previously triggered a spurious error about the destructor of X being
deleted.  That is now fixed.


10/27/23 [EDGcpfe/24342]
Type traits applied to array types

Some type traits applied to array types failed to take into account the
underlying element type.  For example:

  struct C { ~C(); };
  static_assert(!__has_trivial_destructor(C[8]));  // Previously failed.
                                                   // Now okay.

This is now fixed.


10/26/23 [EDGcpfe/24232]
Include the type in incomplete type diagnostics

Previously, the front end did not include the type in incomplete type
diagnostics:

  class foo;
  foo x;

  error: incomplete type is not allowed

This has now been changed to include the type:

  error: incomplete type "foo" is not allowed

Additionally, note that this change modifies the error codes
ec_incomplete_type_not_allowed and ec_ptr_or_ref_to_incomplete_type.  The error
codes ec_ptr_to_incomplete_class_type_not_allowed and
ec_incomplete_type_expr_not_allowed also have been retired.


10/24/23 [EDGcpfe/26710]
--incognito and --no_incognito command-line options

The front end now supports --incognito and --no_incognito to enable or disable
incognito mode respectively.  While in incognito mode, the front end will
attempt to conceal the fact that it is the EDG front end.  This can be useful
when encountering code that incorrectly special cases the EDG front end, e.g.,

  #ifdef __EDG__
    static_assert(false, "The EDG front end does not support constexpr if");
  #else
    if constexpr (foo()) { /* ... */ }
  #endif /* __EDG__ */

Additionally, the front end can be set to incognito mode by default by changing
the DEFAULT_INCOGNITO configuration macro to TRUE.


10/24/23 [EDGcpfe/24564]
Linkage of const-qualified variable templates

The resolution of Core issue 2387 clarified that only non-inline non-template
variables of non-volatile const-qualified type get internal linkage.  For
example, with --c++17:

  template<int I>
  inline const int i = I;  // i<0> previously had internal linkage, now it has
                           // external linkage
  const int j = i<0>;

Additionally, in configurations where GENERATE_SOURCE_SEQUENCE_LISTS is TRUE,
the declared_storage_class of variable templates was previously not set.  Both
issues are now fixed.


10/23/23 [EDGcpfe/26501]
Stack overflow with consteval default argument in decltype specifier

Previously, the following would result in a stack overflow:

  template <class F>
  constexpr auto invoke(F &&f) -> decltype(static_cast<F &&>(f)()) {
      return static_cast<F &&>(f)();
  }

  void test() {
    invoke([](std::source_location = std::source_location::current()) {});
  }

This is now fixed.


10/21/23 [EDGcpfe/26636]
Microsoft compatibility: _MSVC_EXECUTION_CHARACTER_SET predefined macro

In Microsoft emulation mode when microsoft_version >= 1929, the
_MSVC_EXECUTION_CHARACTER_SET predefined macro is now set.  The value of the
predefined macro is determined by the value of the new configuration macro
DEFAULT_MSVC_EXECUTION_CHARACTER_SET and defaults to 1252 (which is the
ANSI Latin 1 code page).  Note that this change only sets the predefined macro
(and there is no change to the execution character set of the front end).


10/20/23 [EDGcpfe/26734]
Evaluation of consteval functions

Consider, in C++20 mode:

  consteval void g() {}
  consteval auto f() { return &g; }
  static_assert(f() == f());  // Previously an error.  Now okay.

Previously, the front end constant-evaluated each call f() independently,
triggering spurious errors because the address of a consteval function is not
permitted as part of the result of a top-level constant-expression.  However,
in this case the top-level constant-expression is "f() == f()", whose result
does not include the address of g().  The problem is now fixed (and the
example is now accepted).


10/19/23 [EDGcpfe/26712]
Show previous definitions in redefinition errors

Previously, when issuing a redefinition error, the front end did not display
the location of the previous definition:

  void foo() {}
  void foo() {}

  error: function "foo" has already been defined

The previous definition position is now included:

  error: function "foo" has already been defined
     (previous definition at line 1)

Additionally, note that ec_function_redefinition and ec_redefinition have been
retired.  Diagnostics for these redefinitions are now issued via either
ec_already_defined_with_pos or ec_already_defined.


10/18/23 [EDGcpfe/26228,EDGcpfe/26298]
Substitution of requires expressions

Previously, the front end always performed substitution into a requires
expression in a dependent context, causing some constraints to be spuriously
satisfied.  Additionally, the front end previously only substituted the
innermost template arguments into nested requirements.  Both issues are now
fixed.  For example, with --c++20:

  template<typename T, bool B = true>
  struct A {
    T t;
    int f(int) requires (!requires { t.i; });
    template<typename U> int g(U) requires requires { requires B; };
  };
  int i = A<int>().f(0);  // Previously a spurious error.  Now okay.
  int j = A<int>().g(0);  // Previously a spurious error.  Now okay.


10/18/23 [EDGcpfe/26139]
Substitution of member functions

Previously, the front end failed to substitute member functions.  For example,
with --c++20:

  template<typename T> struct A {
    static constexpr T f() { return true; }
    static int g() requires (f());
  };
  int i = A<bool>::g();  // Previously a spurious error.  Now okay.


10/16/23 [EDGcpfe/24745,EDGcpfe/26662]
Stringized __VA_OPT__

The front end previously incorrectly disallowed use of the __VA_OPT__
preprocessing operator as the operand of the stringize ("#") operator.  This
is now fixed.  As part of this change, the front end now more accurately
emulates MSVC by not recognizing the __VA_OPT__ operator when emulating the
traditional preprocessor.  For example, with --c++20:

  #define M(x, ...) x #__VA_OPT__(,) #__VA_ARGS__
  const char *p = M("a");    // Expansion is "a" "" ""
  const char *p = M("a", b)  // Expansion is "a" "," "b"


10/16/23 [EDGcpfe/26722]
Spurious error on comparison to nullptr during constant evaluation

Consider (in C++17 mode):

  constexpr bool f() {
    int x[10]{};
    return x + 10 != nullptr;
  }
  static_assert(f());

The front end previously issued a spurious error about f() not producing a
constant value.  That is now fixed.


10/16/23 [EDGcpfe/23676]
Implicit type context for requires-expression parameters

Consider, in C++20 mode:

  namespace N { template<typename T> int f(typename T::type); }
  template<typename T> int N::f(T::type);  // Previously an error.  Now okay.

The changes for EDGcpfe/20270 missed this case: Redeclaring a function or
function template with a qualified name causes the parameter declarations to
be in an "implicit type context".  That is now fixed.


10/12/23 [EDGcpfe/26720]
Implicit type context for requires-expression parameters

Consider, in C++20 mode:

  template<typename T> concept C = requires(T::X x) { ++x; };

The front end previously issued a spurious error on that example because it
failed to recognize that the parameter declaration of a requires-expression is
an implicit type context (i.e., no "typename" prefix is needed for T::X).
That is now fixed.


10/12/23 [EDGcpfe/16204,EDGcpfe/26719]
Microsoft compatibility: Ambiguous member access and using-declarations

Consider:

  struct B { int f(); };
  struct C1: B {};
  struct C2: B {};
  struct D: C1, C2 { using C2::f; } d;
  int r = d.f();  // Ambiguous, but now accepted in Microsoft bugs mode.

This is an error in standard C++ because it attempts to access a member (B::f)
of an ambiguous base class.  MSVC, however, resolves the ambiguity through the
using-declaration that guided the lookup.  The front end now emulates that
behavior.


10/11/23 [EDGcpfe/24700,EDGcpfe/26716]
Spurious failure of or-ed constraints

Consider, in C++20 mode:

  template<typename T> concept C = T::value || true;
  static_assert(C<int>);

This previously failed due to incorrect logic in handling or-ed constraints.
That is now fixed.


10/10/23 [EDGcpfe/26717]
Variable template redeclaration error improvements

Previously, given the following source:

  struct foo {
    template<typename T>
    static T x;
  };

  int foo::x = 0;

the front end would report:

  line 6: error: variable template "foo::x" has already been defined
    int foo::x = 0;
             ^

This has been changed (for improved clarity) to:

  line 6: error: declaration is incompatible with variable template
                 "foo::x" (declared at line 3)
  int foo::x = 0;
           ^


10/9/23  [EDGcpfe/26701]
GNU-mode abort on function pointer addition in function template signature

Consider:

  double g(double);
  template<typename> auto f(double) -> decltype(1 + g);

This previously triggered an internal error in GNU C++11 mode due to a failed
assertion in set_pointer_operand_is_second_flag (expr.c).  That is now fixed.


10/9/23  [EDGcpfe/26715]
Clang-mode tweak to folding of reinterpret_cast-like construct

Consider:

  long var = (long)"text";

The changes for EDGcpfe/26198 (in version 6.5) caused the front end to treat
the initializer as dynamic in Clang mode.  A change has been made to make it
a static initialization instead (as it was in version 6.4).


10/8/23  [EDGcpfe/26706]
Assertion failure in record_substitution_for_type on type-returning traits

The front end had failed an assertion check (in record_substitution_for_type)
in configurations that do IA-64 mangling when using type-dependent type-
returning traits.  For example (with --clang_version 160000):

  template<typename T> __remove_cv(T) f(T);
  auto x = f(1);


10/6/23  [EDGcpfe/26663]
Constant-destruction and mutable members

Consider, in C++20 mode:

  struct S {
    mutable int x = 1;
    constexpr ~S() { auto r = this->x; }
  };
  constexpr S s;  // Previously accepted.  Now an error.

This example is invalid because the destructor for s, which must implement
constant-destruction since s is a constexpr variable, accesses a mutable
member (whose value could conceivably change at run time between its
initialization and destruction).  The front end previously failed to diagnose
this.  That is now fixed.


10/6/23  [EDGcpfe/26686]
Abort on pack expansion in requires-expression

Consider:

  template<typename... T> bool g(T... t) {
    return requires { f(t...); };
  }
  int r = g();

This previously aborted due to a failed assertion in find_variable_for_pack
(scope_stk.c).  That is now fixed.


10/5/23  [EDGcpfe/21200,EDGcpfe/26657,EDGcpfe/26690]
Substitution of GNU/clang type-transforming intrinsics

The changes for EDGcpfe/26193 added front end support for a number of
type-transforming intrinsics such as __remove_cv and __add_pointer.  However,
these intrinsics were not handled during template substitution.  For example,
with --c++11 --clang:

  template<typename T> __add_pointer(T) f(T);
  auto v = f(1);  // Spurious error.  Now okay.


10/5/23  [EDGcpfe/20557]
Type equivalence of dependent type-transforming intrinsics

Previously, the front end ignored type-transforming intrinsics such as
__underlying_type and __add_pointer when comparing dependent types, which could
result in spurious errors.  For example, with --c++11:

  template<typename T> struct C { };
  template<typename T> void f(C<__underlying_type(T)>) { }
  template<typename T> void f(C<T>) { }  // Previously a spurious redefinition
                                         // error.  Now okay.


10/4/23  [EDGcpfe/26708]
Clang compatibility: #pragma STDC FENV_ACCESS

Clang version 12.0.0 and later now support:

  #pragma STDC FENV_ACCESS ON

The front end no longer gives a discretionary error on this when
clang_version >= 120000.


10/3/23  [EDGcpfe/26693]
Excessive layout time for large array member

Consider:

  struct E {};
  struct S {
    E x[1000000000];
  };

With the IA-64 ABI, this previously took an excessive amount of time to compile
because the front end examined each array element in turn for possible layout
conflicts (even though there is no potential conflict in this case).  That is
now fixed.


9/29/23  [EDGcpfe/26310]
Performance with deeply-nested class hierarchies (IL CHANGE)

Consider, with --c++ --pending_instantiations 500:

  template<int N> struct C : C<N-1> { };
  template<> struct C<0> { };
  C<400> c;

Previously, this created more than 10 million a_derivation_step entries to
represent the derivation paths for all possible base class derivations.  Now,
a_derivation_step entries can be shared between paths, so instead of pointing
to a unique NULL-terminated path, a_base_class_derivation points to a sub-list
bounded by path and path_tail.  In configurations with EXPENSIVE_CHECKING set
to TRUE, checking the path consistency can still be very slow in these cases
and can therefore now be disabled via --set_flag no_very_expensive_checking.

Additionally, the front end now maintains a list of direct base classes in
declaration order and an additional flag for each base class, signifying if
there is an all-public derivation.


9/25/23  [EDGcpfe/26679]
Clang compatibility: Add Clang 17.0.1 builtin signatures

Builtin signatures have been updated to reflect Clang 17.0.1 builtins.


9/22/23  [EDGcpfe/25541,EDGcpfe/26642]
Variable template declared with "inline" not marked as such

Consider:

  template<typename T> inline constexpr bool vt = true;

The front end previously failed to reflect the presence of the "inline" keyword
in the IL.  That, e.g., resulted in the C++-generating back end not rendering
the keyword in its output.  That bug is now fixed.


9/21/23  [EDGcpfe/24461,EDGcpfe/26638]
Spurious "declared but never referenced" warnings in templates

The front end sometimes considered local variables in templates not to be
referenced even though they potentially are.  This caused some spurious
warnings to be issued in such contexts.  That is now fixed.


9/15/23  [EDGcpfe/25076,EDGcpfe/26487]
C++23: Add support for attributes in lambda-expressions

The C++23 standard allows attributes in lambda-expressions; such attributes
appertain to the function call operator of the lambda.  These attributes are
now accepted in C++23 mode as well as in later GNU and Clang emulation modes.
For example (with --c++23):

  auto a = [] [[noreturn]] (auto z) { throw z; };
  auto b = [] <class T> [[noreturn]] (T z) { throw z; };

See WG21 document P2173R1 for more information.


9/13/23  [EDGcpfe/26666]
C++-generating back end: parameter names in redeclarations of alias templates

In configurations and modes in which the C++-generating back end puts out
template definitions using the string form of the template (as opposed to
generating them from their prototype instantiation IL), the generated code
was incorrect in cases where an alias template is redeclared using a
different template parameter name from that in the original template
definition.  This is now fixed.  For example, with --microsoft --c++11:

  template<typename> struct A { };
  template<typename T> using B = A<T>;
  template<typename U> using B = A<U>;  // Previously put out as "A<T>"


9/13/23  [EDGcpfe/26153,EDGcpfe/26653]
Assertion failure in unscan_attributes

An assertion failure in unscan_attributes had occurred in some Clang emulation
modes as a result of the changes for EDGcpfe/25930 (in version 6.5).  That
is now fixed.  For example, with --clang_version=70500:

  template <typename T> struct A {
    struct X {};
    void f() __attribute__((warn_unused_result)) {}
  };
  struct B {
    __attribute__((visibility("default"))) A<int>::X Foo();
  };


9/13/23  [EDGcpfe/26667]
Unicode 15.1.0 characters

The front end now supports the Unicode 15.1.0 character set.


9/7/23   [EDGcpfe/26466]
C++23: std::bfloat16_t type

The std::bfloat16_t type is now supported by the front end in C++23 modes
(see the entry for EDGcpfe/25100,EDGcpfe/25170,EDGcpfe/25515).  Because of
currently-limited compiler support for a native bfloat16 type, the internal
representation of bfloat16 values is a host "float".  (See the comments in
float_type.h for the FPT_BFLOAT16 case for a more complete discussion of
the rationale for this choice.)  For example, with --c++23:

  using bf16_t = decltype(0.0bf16);   // Previously treated as std::float32_t
  using f32_t = decltype(0.0f32);
  template<typename> struct S {};
  template<> struct S<f32_t> {};
  template<> struct S<bf16_t> {};     // Previously a redefinition, now okay


9/2/23   [EDGcpfe/26631]
Abort in substitution of requires-expression in certain contexts

Consider, in C++20 mode:

  template<typename> struct X;
  template<> struct X<int> {
    template<typename U> explicit(requires(U p) { p; }) X(U);
  };
  X<int> x{ 0 };  // Previously aborted.  Now okay.

This example previously aborted with an internal error in get_expr_rescan_info
(exprutil.c, "missing default rescan info").  That is now fixed.


9/1/23   [EDGcpfe/26611]
GNU and Microsoft C++ compatibility: auto-deduction in templates

Consider in C++17 mode:

  #include <initializer_list>
  template<typename> void g() {
    auto [b] = {};
  }

This is ordinarily an error because deduction of "auto" from "{}" is invalid.
However, GCC and MSVC accept this because they do not perform full deduction
in templates.  The front end accepted this in the corresponding modes if
deferral of prototype instantiations is enabled, but not otherwise.  Now, such
cases are accepted in GNU and Microsoft C++17 modes even when prototype
instantiations are not deferred.


9/1/23   [EDGcpfe/26630]
Corrupted PCH files on Windows when file is greater than 4GB

PCH files on Windows could be corrupted when their size exceeds 4GB.  Now
fixed.


8/31/23  [EDGcpfe/26610]
GNU and Clang C compatibility: Overlong string initializers

The diagnostic severity of character arrays initialized with overlong strings
is now reduced to a warning in Clang and GNU C modes.  For example:

  char const str[1] = "xyz";  // Now accepted with a warning in some modes.

In such cases, the string initializer is truncated to the length of the
destination array (the terminating null character is lost).


8/31/23  [EDGcpfe/26612]
Abort on call to deleted member in SFINAE context

Consider, in C++14 mode:

  template<typename T> struct S {
    static auto f(int const&) = delete;
  };
  template <typename T> decltype(S<T>::f(42)) h(T);
  int h(int);
  void g() {
    h(43);  // Previously triggered an assertion failure.  Now okay.
  }

This previously triggered an assertion failure in func_call_expr (because an
error is expected for a call to a deleted function, but in a SFINAE context
such a diagnostic is inhibited).  That is now fixed.


8/31/23  [EDGcpfe/26640]
GNU and Microsoft compatibility: Casting of pointer-to-member values

Consider, in Microsoft or GNU C++20 modes:

  struct B {};
  using PM = void (B::*)();
  struct C: B {};
  struct D: C { int f(); };
  static constinit const PM pm = (PM)static_cast<int (C::*)()>(&D::f);
      // Previously an error.  Now accepted in some modes.

Ordinarily this is an error because the C-style cast is a reinterpret-like
cast and such casts are not permitted in constant expressions.  However, GCC
and MSVC do accept this example.  The front end now approximates that behavior.
(Note that before the changes for EDGcpfe/26198 the front end erroneously also
accepted this example.  In some sense this could therefore be considered a fix
for a regression introduced in version 6.5 of the front end.)


8/29/23  [EDGcpfe/25906]
GNU compatibility: decltype(auto) and type qualifiers

The GNU compatibility changes for EDGcpfe/17385 (which permit type qualifiers
to appear alongside decltype(auto)) are now limited to GNU C++ modes with
gnu_version < 110000.  This corresponds to GCC 11.x dropping that behavior.


8/29/23  [EDGcpfe/26615]
C++-generating back end: template arguments involving member function calls

In some cases when a template instance is first named in a class definition
and one of the template arguments involves a call to a member function of
that class, the C++-generating back end put out a subsequent reference to
that template instance using a template argument in which the member
function call was written using "this->", even though the reference appears
outside the class definition.  This is now fixed.  For example, with
--c++11:

  template <typename> struct B {
    int f() { return 0; }
  };
  template <typename T> struct A {
    using U = int;
    U &u();
    auto r() -> B<decltype(u())>;       // First reference to B<int &>
  };
  template int B<A<float>::U &>::f();   // Template argument for B previously
                                        // put out as "decltype(this->u())",
                                        // now as "int &"


8/29/23  [EDGcpfe/26613]
Uninitialized statement position in error cases

A return statement returning a braced-initializer-list without a terminating
semicolon could have an uninitialized end position (in configurations with
EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE).  For example:

  struct S { int x; };
  S f() {
    return { 0 }  // Missing semicolon.  The end position recorded for the
  }               // statement was previously generated from an uninitialized
                  // value.

That is now fixed: The recorded end position is now a valid token position
even in this error situation.


8/29/23  [EDGcpfe/26614]
GNU C compatibility: Type of some bit-field expressions

Consider, in GNU C11 mode:

  extern int printf(char const*, ...);
  struct {
    unsigned u: 8;
  } s;
  int main() {
    printf("%s\n", _Generic((s.u),
                            unsigned char: "uchar",
                            unsigned int: "uint",
                            default: "unknown"));
  }

GCC treats a bit field whose width exactly matches that of an integer type
(8 bits for char types, 16 bits for short types, etc.) as if they are fields
of that type.  That type might be different from the type the bit field is
declared with.  In the example above, the bit field is declared as "unsigned",
but the type of s.u is "unsigned char" (the signedness is carried over).
Thus, the output of this program is "uchar".  The front end now emulates that
behavior.


8/28/23  [EDGcpfe/26629]
Symbol table tuning

Two changes have been made to tune the main symbol table used for name lookup.
First, the length of the main array (which is a prime number) has been
increased from 16381 to 262133 to accommodate very large input sources.
Second, the hash function previously only hashed up to 9 characters of any
identifier.  That could lead to pathological behavior when the input contained
large numbers of identifiers following a certain pattern where the chosen 9
characters do not change.  Now, the hash function uses all characters of the
identifiers it is applied to.


8/28/23  [EDGcpfe/26596]
Spurious error in GNU mode on aggregate initialization in template

Consider, in GNU C++17 mode:

  struct B { int x, y, z; };
  struct D: B {};
  template<typename T> int f(T) {
    D d = { 1, 2, 3 };  // Previously an error.  Now okay.
    return d.y;
  }
  int main() {
    f(42);
  }

The changes for EDGcpfe/25550 introduced a regression in version 6.5 of the
front end, causing this example to elicit a spurious error in GNU modes
(claiming excess initializer elements).  That is now fixed.


8/25/23  [EDGcpfe/26360]
C++-generating back end: form of non-type template arguments

When there are multiple references to a template instance involving a
non-type template argument, the C++-generating back end could use a
different form for the argument in subsequent references from that used in
the initial reference.  In general, the initial reference reflects the
constant expression appearing in the source, while subsequent references
used the value of the constant expression.  When compiling the generated
code with g++, this difference could result in g++ failing to match an
out-of-class definition of a member template with its declaration in the
class.  The front end has now been changed to put out the original source
form of the constant expression in all references to the template instance
whenever possible, using the constant value only when names appearing in
the expression are out of scope or inaccessible.  For example:

  template <unsigned, unsigned, typename> struct A { };
  template <typename T> struct B {
    template <unsigned N> A<0, N, T>* f();   // int 0 converted to unsigned
  };
  template <typename T> template <unsigned N>
  A<0, N, T>* B<T>::f() {   // Previously put out as "A<0U, N, T>"
    return 0;
  }


8/25/23  [EDGcpfe/26587]
Template-dependence of calls to nonstatic member functions

Consider:

  struct X {};
  struct Y {};
  struct C {
    X f() const;
    Y f();
  };
  void g(X);
  void g(Y);
  template<typename T> struct S {
    T t;
    void h() const {
      g(t.C::f());  // Previously recorded as nondependent, triggering an
    }               // error during real instantiation.
  };
  int main() {
    S<C> d;
    d.h();
  }

The front end previously recorded the call g(t.C::f()) as nondependent because
the dependence of t on the template parameter T was ignored.  During the real
instantiation of S<C> that resulted in the wrong member of C being selected and
a spurious conversion error to be emitted.  That is now fixed.


8/25/23  [EDGcpfe/24031,EDGcpfe/25546,EDGcpfe/26439,EDGcpfe/26621]
Object lifetime information for coroutines

Consider, with --c++20:

  #include <coroutine>
  struct C {
    ~C();
  };
  std::task<int> coro() {
    C c1, c2;    // Previously aborted during lowering.  Now okay.
    co_return 0;
  }

Previously, the front end did not correctly transfer object lifetime
information when transforming the coroutine body, as described in
[dcl.fct.def.coroutine].  In configurations that do IL lowering, this later
triggered an internal error in lower_dynamic_init (lower_init.c).  That is now
fixed.


8/25/23  [EDGcpfe/26624]
Abort on in-class explicit specialization with deduced type

The changes for EDGcpfe/25751 (in version 6.5) introduced a regression for an
in-class explicit specialization of a static data member template with a
deduced type.  Previously, this triggered an internal error in
generic_cast_operand (exprutil.c).  For example, with --c++14:

  struct C {
    template<typename T> static const auto v = false;
    template<> const auto v<int> = true;  // Previously aborted.  Now okay.
  };


8/23/23  [EDGcpfe/20107,EDGcpfe/23736,EDGcpfe/23925,EDGcpfe/24509,
          EDGcpfe/24617,EDGcpfe/25465,EDGcpfe/26248,EDGcpfe/26570]
GNU/Clang/Microsoft compatibility: Structured bindings and language modes

In GNU C++ mode with gnu_version >= 70000 and Clang C++ mode with
clang_version >= 40000, the front end now accepts structured binding
declarations with a warning in C++11 and C++14 modes.  Furthermore,
in GNU C++ mode with gnu_version >= 70000, Clang C++ mode with
clang_version >= 160000, and Microsoft modes that accept structured
bindings, lambdas capturing structured bindings are accepted with a
warning when C++20 mode is not enabled.


8/23/23  [EDGcpfe/26623]
GNU compatibility: raw string literals in C mode

Although raw string literals are a C++ feature, gcc has accepted them since
version 5.1 in non-strict C mode (i.e., with a default language standard or
with -std=gnu*, but not with -std=c*).  The front end has now been updated
to support them in the relevant GNU C modes as well.  For example, with
--gcc --gnu_version=50100 (but not with --strict_gnu or, e.g., --c11, which
set strict gnu mode - see EDGcpfe/18999,EDGcpfe/23905,EDGcpfe/23995):

  const char *str = R"(test")";   // Previously an error, now okay


8/23/23  [EDGcpfe/26622]
C++-generating back end: init-capture with brace-enclosed initializer

The C++-generating back end previously incorrectly added an extra set of
braces in some cases where the initializer of a lambda init-capture is
enclosed in braces, resulting in code that could not be compiled.  This is
now fixed.  For example, with --c++17:

  template<typename> void f();
  template<typename T> void g() {
    [x{f<T>}]{};   // Previously generated as "[x{{f<T>}}]{}"
  }


8/22/23  [EDGcpfe/26564]
GNU compatibility: gcc version support for _Float* types

The changes for EDGcpfe/26221 and
EDGcpfe/18316,EDGcpfe/22881,EDGcpfe/26290,EDGcpfe/26308,EDGcpfe/26332
added support in the front end for various _Float* types in gcc and g++
modes when gnu_version is at least 130000.  This version test is correct
for g++ mode; however, gcc began supporting these types in version 7.0.0.
The front end has now been updated to use the correct version test when
emulating gcc.  For example, with --gcc --gnu_version=70000:

  _Float32 f32 = 0.0f32;   // Previously an error, now okay


8/21/23  [EDGcpfe/26601]
Incorrectly generated copy/move constructor for lambda with init capture pack

Consider, with --c++20:

  struct C {
    constexpr C() = default;
    constexpr C(const C &o) : i(o.i) { }
    int i{1};
  };
  struct X {
    C c{};
  };
  constexpr auto f(auto ... x) {
    auto l = [... cx = x]() { return (cx.c.i + ...); };
    return l;
  };
  static_assert(f(X(), X())() == 2);  // Previously an error.  Now okay.

Here, the lambda inside "f" contains an init capture pack that is expanded in
its body.  However, when the definition of the move constructor for the
lambda's closure type was generated, the first member of the pack wasn't
copied, leading to uninitialized reads later on, either at run time or constant
evaluation time.  That is now fixed.


8/21/23  [EDGcpfe/26584]
C++-generating back end: CTAD with lambda and constexpr constructor

In some cases involving class template argument deduction (CTAD) where the
constructor being invoked is constexpr, the C++-generating back end
incorrectly transformed a function-style cast into a C-style cast.  When
the initializer is a lambda expression, the generated code could not be
compiled: because the lambda closure type has no name, the generated code
used an undeclared temporary name (of the form __T12345678) as the template
argument in the cast.  This is now fixed.  For example, with --c++20:

  template<typename T> struct S {
    T m;
    constexpr S(const T &a) : m(a) { }
  };
  void f() {
    auto s = S([]{});  // Previously generated as (S<class __T12345678>)([]{})
  }


8/17/23  [EDGcpfe/19237,EDGcpfe/25886,EDGcpfe/26582]
Partially-specialized non-type template argument involving a template parameter

The resolution of Core issue 1315 (treated as a defect report against previous
C++ standards) removed a restriction on a partially-specialized non-type
argument expression to not involve a template parameter of the partial
specialization.  For example, with --c++:

  template<int I, int J> struct A;
  template<int I>
  struct A<I, I*2> { };  // Previously a spurious error.  Now okay.


8/16/23  [EDGcpfe/26595]
C++-generating back end: Calls to explicit-this member functions

The C++-generating back end previously did not correctly render calls to
explicit-this member functions.  That is now fixed.


8/16/23  [EDGcpfe/26586]
Deduced incomplete class parameter type not always treated as a SFINAE failure

Consider:

  template<typename T> T&& val();
  template<typename T> struct W {};
  template<typename T> void g(T);
  template <typename T, typename = decltype(g<T>(val<T>()))>
    int f(W<T>);  // (1)
  template<typename T>
    int f(W<T>);  // (2)
  struct I;
  int main() {
     W<I const> wi;
     f(wi);  // (3)  Previously an error in some GNU modes.  Now okay.
  }
  struct I { virtual int p() const = 0; };  // Abstract.

Normally, candidate (1) is discarded for the call (3) because it involves
deducing a call to g(T) with a parameter of incomplete type I.  However, in
some GNU C++ modes, the candidate (1) was discarded too late, causing a hard
error to be issued when type I is later completed as an abstract class type.
That is now fixed.


8/15/23  [EDGcpfe/26583]
Spurious errors on use of C++23 explicit-this members

Consider (in C++23 mode):

  struct B {
    void f(this B &self) {}
  };
  struct D: B {
    void g() { this->f(); }  // Previously an error.  Now okay.
  };

Previously, this elicited an error because the object argument in this->f() was
tested as if it were a prvalue, and that cannot match the type B& of the C++23
explicit-this parameter.  Also, for the example:

  struct B {
    template<typename T> void f(this T &self) {}
  };
  struct D: B {
    void g() { f(); }  // Previously an error.  Now okay.
  };

the front end incorrectly synthesized an implicit object argument of type B
after (correctly) deducing T to be type D.  That resulted in a spurious error
since B cannot be implicitly converted to D.

Both these bugs are now fixed.


8/14/23  [EDGcpfe/26585]
Microsoft compatibility: __builtin_FUNCSIG

The new builtin __builtin_FUNCSIG is now recognized when emulating Visual
Studio 19.35 or later.  It returns the same value as the Microsoft-specific
macro __FUNCSIG__ does (which is a textual representation of the enclosing
function's signature).  Note that the string values returned by
__builtin_FUNCSIG/__FUNCSIG__ may not match those generated by Visual Studio.


8/14/23  [EDGcpfe/26580]
Corruption of start/end_of_curr_token

A change in version 6.5 introduced a regression that resulted in values of
start_of_curr_token and end_of_curr_token being reused in a context where
they're no longer valid.  This is not known to affect the front end in any end
user facing way, though it may affect customers that have made source level
modifications which depend on the value of start_of_curr_token or
end_of_curr_token.


8/14/23  [EDGcpfe/26508]
Microsoft compatibility: Looking up qualified names in templates

In permissive Microsoft modes, dependent name processing is disabled and all
qualified names appearing in templates are looked up in the instantiation
context.  However, in non-permissive Microsoft modes, dependent name processing
is enabled which normally causes namespace-qualified names to be looked up at
the point of template definition.  However, even in non-permissive modes MSVC
defers the lookup of some non-dependent qualified names to the point of
instantiation.  For example:

  template<typename T> T &&declval();
  template<typename T> struct A {};
  template<typename T> void f(A<T> const&);
  template<typename T> struct B {
    int g() noexcept(noexcept(::f(declval<B<T>>())));  // Previously an error.
  };                                                   // Now okay.
  template<typename T> void f(B<T> const&);
  int i = B<int>().g();

When the exception specification operand in B<int> is instantiated, the lookup
::f should only find the first declaration of ::f, and since that is not a
match for the call it should elicit an error.  However, MSVC accepts this
example because it defers the lookup of ::f to instantiation time.  The front
end now emulates that behavior.


8/10/23  [EDGcpfe/26213]
__is_trivially_copyable and constrained special members

Consider:

  template<typename T> concept C = true;
  template<typename T> concept D = C<T> && true;
  template<typename T> struct X {
    X(X<T> const&) requires D<T> = default;
    X(X<T> const&) requires C<T>;  // (1)
  };
  static_assert(__is_trivially_copyable(X<int>));

Previously, the front end failed the static assertion because the copy
constructor declared by (1) is nontrivial.  However, (1) should not be
considered in determining trivial copyability because the defaulted constructor
of X<int> (which is trivial) is more constrained and thus always preferred.
That is now fixed: The assertion is now accepted.


8/10/23  [EDGcpfe/26575]
Pack expansion failure for concept used in requires clause

In some fairly specific cases where a requires expression includes a parameter
declaration clause and that requires expression is used in a concept
constraining a function template, expansion of a requirement parameter pack
could fail if the function template also contains an identically-named function
parameter pack.  That regression (introduced in version 6.5 with the changes
for EDGcpfe/25609,EDGcpfe/26117) is now fixed.  For example, with --c++20:

  void f(int);
  template<typename ... T>
  concept C = requires(T ... t) { f(t ...); };
  template<typename ... T> requires C<T ...>
  int g(T ... t);
  int i = g(1);  // Previously a spurious error.  Now okay.


8/9/23   [EDGcpfe/26540]
Pack expansions over requires-expressions

Consider:

  template<int I, typename T> void g(T);
  template<typename T, typename... Ts> struct S {
    template<class U, int... I> static constexpr bool v =
                     (requires(const S& c, const U& u) { ::g<I>(c); } && ...);
  };
  static_assert(S<int, int>::v<int, 1, 2>);  // Previously failed.  Now okay.

This previously failed because of some subtle interaction between ordinary
variadic template instantiation and the substitution of requires-expressions.
That is now fixed.


8/9/23   [EDGcpfe/26572]
Spurious "error: not a class or struct name" diagnostics

Previously, the front end would emit a spurious additional error when an
invalid alias template is used in a base specifier:

   template<typename C>
   struct A {};

   template<typename AT>
   using A_alias = typename A<AT>::X; // errors on instantiation

   struct B : A_alias<int> { // previously, a spurious additional error
   };

This is now fixed.


8/9/23   [EDGcpfe/26339]
C++-generating back end: template arguments involving local constexpr variables

In general, the IL for a template instance reflects the template arguments
used in the first reference to that instance.  When such template arguments
involve a local variable, the C++-generating back end could produce
erroneous output when generating references to the template instance in
contexts outside the scope of the local variable.  This is now fixed.  For
example, with --c++17:

  struct A {
    int a;
    constexpr A() : a{} {}
  };
  template <auto> struct B {};
  template <typename> struct C {};
  auto f() {
    constexpr auto a = A{};
    return B<a>{};
  }
  void g() {
    C<decltype(f())> c;  // Previously generated as C<B<A{0}>>, now C<B<A{}>>
  }


8/9/23   [EDGcpfe/20656,EDGcpfe/26160,EDGcpfe/26449]
Equivalence of alias templates

The direction of Core issue 1286 specifies that an alias template is equivalent
to the aliased template if the template parameter lists (including default
arguments) are equivalent and the template argument list consists of a list of
identifiers naming each template parameter in the order they appear in the
template parameter list.  For example, with --c++11:

  template<typename> class C;
  template<typename T> using A = C<T>;
  template<template<typename> class>
  class B { };
  B<A> b = B<C>{};  // Previously a spurious error.  Now okay.


8/8/23   [EDGcpfe/26565]
Constraints and surrogate function calls

A value of class type that has a user-defined conversion to a pointer-to-
function type can be used as the target of a call expression.  Such calls are
sometimes called "surrogate function calls" (see also the entry of 8/10/99).
Previously, the front end failed to check template constraints before selecting
such calls.  That is now fixed.  For example:

  using FP = int(*)(int);
  template<bool B> struct S {
    operator FP() requires B;
  };
  int r = S<false>{}(0);  // Previously accepted despite the constraint on
                          // S::operator FP() not being satisfied.  Now an
                          // error as expected.


8/4/23   [EDGcpfe/26557]
IL write-read error on coroutine function template

In C++-generating back end configurations with ALL_TEMPLATE_INFO_IN_IL set to
TRUE, a coroutine function template could trigger an IL write-read error due to
a dangling object lifetime pointer for the implicitly-generated goto statement
following a co_return statement.  That is now fixed.  Additionally, the
final-suspend label will now also be created for coroutines with a dependent
promise type.  For example, with --c++20:

  #include <coroutine>
  template<typename T>
  std::task<void> f(T) {
    co_return;  // Previously triggered an IL write-read error.  Now okay.
  }


8/2/23   [EDGcpfe/26299]
CTAD failure involving parameter pack expansion in alias template

In some fairly complex cases where an implicit deduction guide involves a
parameter pack expansion in an alias template, class template argument
deduction (CTAD) could fail when the class template was first declared with a
forward declaration.  For example, with --c++20:

  template<typename...> struct B {
    using type = int;
  };
  template<typename... TT> struct C;
  template<typename... TT> struct C {
    template<typename> using A = typename B<TT ...>::type;
    template<A<int> = 0> C(TT ...);
  };
  C c{1};  // Previously a spurious error.  Now okay.


8/2/23   [EDGcpfe/26300]
Spurious failure to pass an argument via user-defined conversion

Consider:

  struct S {
    S(int) {}
    operator int() const volatile { return 0; }
  };
  void f(S) {}
  int main() {
    volatile S a{0};
    f(a);  // Previously a spurious error in some modes.  Now okay.
  }

Previously, the call f(a) elicited a spurious error.  That is a regression
introduced by the changes for EDGcpfe/25746 (in version 6.5).  That is
now fixed.


8/1/23   [EDGcpfe/24171,EDGcpfe/24573,EDGcpfe/26140,EDGcpfe/26267]
Cv-qualification of non-type template parameters

The C++ Standard requires that top-level cv-qualifiers are ignored when
determining the type of a non-type template parameter.  However, naming a
non-type template parameter of class type denotes an lvalue of const-qualified
type.  Previously, top-level cv-qualifiers were not ignored, and, during
prototype instantiations, an lvalue representing a non-type template parameter
of class type was not const-qualified.  For example, with --c++20:

  struct B { };
  void f(B &) = delete;
  void f(const B &);
  template<const int I, B V>
  void g(decltype(I) &i) {
    i = 0;  // Previously a spurious error.  Now okay.
    f(V);   // Previously a spurious error.  Now okay.
  }


7/31/23  [EDGcpfe/25594]
C++-generating back end: CTAD involving member templates

When forming a type specified in the original source using class template
argument deduction (CTAD), where the class template is a class member, the
C++-generating back end previously incorrectly treated the type specifier
as dependent and thus needing to be prefixed by the "typename" keyword.
This has now been fixed.  For example, with --c++17:

  struct A {
    template <typename T> struct B {
      B(T);
    };
  };
  A::B ab{0};   // Previously generated as "typename A::B"


7/31/23  [EDGcpfe/26555]
Build error when IA64_ABI is 0 and ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS is 1

The front end had failed to build when the configuration macro IA64_ABI == 0
and ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS == 1.  Now fixed.


7/31/23  [EDGcpfe/26402]
Incorrect handling of operands of function type in decltype construct

Consider:

    template<typename T> T val();
    template<typename T> struct IsRef {
      static constexpr bool value = false;
    };
    template<typename T> struct IsRef<T&> {
      static constexpr bool value = true;
    };
    typedef void (*FP)(int);
    using X = decltype(*val<FP&>());  // (1)
    static_assert(IsRef<X>::value);   // Previously failed.  Now okay.

The operand of the decltype construct in line (1) is an lvalue (of function
type) and thus the result of the construct should be a reference type.
However, previously the front end did not handle operands of function type
correctly in this context and X was instead made to be a function type.  That
in turn caused the static assertion to fail.  That is now fixed.


7/31/23  [EDGcpfe/26554]
C++-generating back end, GNU compatibility: array designated initializers

Prior to version 4.7.0, g++ only accepted a nonstandard syntax for
designated initializers.  The C++-generating back end previously used this
syntax unconditionally when targeting g++.  However, for array element
designators, this syntax can produce initializers that resemble malformed
lambda expressions and thus resulted in errors when the generated code was
compiled.  This is now fixed and the C++-generating back end only emits the
older syntax when gnu_target_version is less than 40700.  For example, with
--g++:

  int a[] = {[0] = 0};   // Previously generated as "[0](0)"


7/28/23  [EDGcpfe/26552]
Abort in prep_reference_initializer_operand on incomplete-type argument

Consider:

  struct I;
  template<typename> struct S {
    auto f()->I;
    void f(I const&);
    auto g()->decltype(f(f()));
  };

This previously failed an assertion in prep_reference_initializer_operand (in
overload.c), triggering an internal error.  That is now fixed.


7/28/23  [EDGcpfe/26512]
Use of incomplete types in function template declarations

Consider:

  template<typename> struct S {
    static bool f(S);
    template<typename T> friend auto g(S p)->decltype(S::f(p)) {
      throw 42;
    }
  };
  S<int> si;  // Ordinarily, S::f(p) would be an error because S is still
              // incomplete, but this is generally accepted.

During the instantiation of S<int>, the call S::f(p) is invalid because p has
the still-incomplete type S<int> but it requires a glvalue-to-prvalue
conversion.  The front end previously (correctly) diagnosed this.  However,
common practice is to accept this example.  The diagnostic is therefore no
longer issued in nonstrict modes.


7/28/23  [EDGcpfe/26419]
Hang on GCC target pragma with multiple string arguments

Previously, passing multiple string arguments to the GCC target pragma had
caused the front end to hang.  A change has been made to enable string literal
concatentation when parsing GCC pragmas so the following is now accepted in
GNU emulation modes:

  _Pragma("GCC push_options")
  _Pragma("GCC target \"sse2,ssse3\" \",sse4.1,sse4.2\" \",pclmul,aes\"")
  void f() {}
  _Pragma("GCC pop_options")


7/28/23  [EDGcpfe/26514]
Microsoft compatibility: partial ordering of constrained function templates

Consider, with --ms_c++20:

  template<typename T, typename U>
  void f(T *, U);
  template<typename T, typename U>
  char f(T, U *) requires true;
  char c = f("", "");  // Normally ambiguous.  Now okay in Microsoft mode.

According to the rules in [temp.func.order], constraints should only be
considered if deduction succeeded both ways as described in
[temp.deduct.partial].  However, the Microsoft compiler appears to also
consider constraints in cases where deduction did not succeed both ways.  The
front end now emulates that behavior in Microsoft mode.


7/28/23  [EDGcpfe/26336]
Partial ordering of constrained function templates with trailing parameter pack

Consider, with --c++20:

  template<typename T> requires true
  int f(T);         // #1
  template<typename T, typename ... U> requires true
  int f(T, U ...);  // #2
  int i = f(1);  // Previously ambiguous.  Now okay.

Although function template #1 is more specialized than #2 according to the
rules in [temp.deduct.partial] due to #2 having a trailing function parameter
pack, the front end previously considered constraints, and as neither is more
constrained than the other, the call was treated as ambiguous.  That is now
fixed.


7/27/23  [EDGcpfe/26529]
Abort in node_operands_have_correct_value_category on eok_lvalue node

In some configurations, certain template definitions could trigger an assertion
failure in node_operands_have_correct_value_category (il.c) for an rvalued
eok_lvalue node.  That regression (introduced in version 6.5 by the changes for
EDGcpfe/26197) is now fixed.


7/27/23  [EDGcpfe/26532]
Statements in constexpr function templates

In C++11, constexpr function bodies mostly permit only a single return
statement.  It appears, however, that most implementations do not issue an
error on a violation of that constraint in a constexpr function template that
is never instantiated (Clang issues a warning; GCC and MSVC are silent).  The
front end's diagnostic for those cases has therefore been weakened to a
warning in nonstrict modes.  (See also the entry for EDGcpfe/26319: In some
GCC modes, even real instantiations of such cases are not diagnosed.)


7/27/23  [EDGcpfe/26542]
GNU compatibility: Update builtin signatures to 13.2.0

There were a small number of changes to builtin signatures between
GNU 13.1.0 and 13.2.0 (some uses of _Float128 were replaced by __float128).
The builtin signatures have been updated accordingly.


7/27/23  [EDGcpfe/26537]
Missing cases in disp_local_expr_node_ref

Some missing cases for a switch statement in disp_local_expr_node_ref had
resulted in the string "**BAD LOCAL-EXPR-NODE-REF KIND**" being emitted in
some IL displays.  Those are now fixed.


7/27/23  [EDGcpfe/26526]
Deducing the type of a non-type template parameter used as a template template
parameter argument

C++17 allows the type of a non-type template parameter to be deduced from the
type of a non-type template argument.  However, the changes for
EDGcpfe/25949,EDGcpfe/26013 in version 6.5 (see entry of 2/22/23) introduced a
regression for cases where the non-type template parameter to be deduced is
used as an argument for a template template parameter.  For example, with
--c++17:

  template<int> struct A { };
  template<typename T, T I, template<int> class TT>
  int f(TT<I>);
  int i = f(A<1>{});  // Previously a spurious error.  Now okay.


7/26/23  [EDGcpfe/26060,EDGcpfe/26203,EDGcpfe/26533]
Spurious copy-constructor invocation on braced-initializer argument

Consider:

  struct B { ~B(); };
  struct D: B {
    D() = default;
    D(D const&) = delete;
  };
  void g(D = {});  // Previously an error.  Now okay.

Previously, in pre-C++17 modes, the initialization of the parameter with {}
forced a copy constructor invocation.  That in turn triggered an error because
D's copy constructor is deleted.  That is now fixed.


7/26/23  [EDGcpfe/26525]
Implement predefined macro definition for _M_X64 and _M_AMD64

The front end previously defined _M_AMD64 and _M_X64 via the
predefined_macros.txt file (by default for predefined_macros.txt generated by
make_win_predef_macro).  This has been changed and the front end now internally
sets _M_X64 and _M_AMD64 for x86_64 targets in Microsoft mode and when using
Microsoft extensions in Clang mode.


7/25/23  [EDGcpfe/26531]
Uninitialized read on expression end position

The changes in EDGcpfe/26457 (not in a release but distributed to some
customers as a patch) resulted in an uninitialized read of expression end
positions for expressions using C++ functional-notation type conversions (e.g.,
"int(1.5)") to perform aggregate initialization on a class type that captures
the value given by reference.  For example:

  struct class_type {
    int &val;
  };

  int x = 0;
  int y = (class_type(x), 0 );
        /* ^^^^^^^^^^^^^ */

Previously, this expression's end position could be an uninitialized value.
This is now fixed.


7/25/23  [EDGcpfe/26530]
Incorrect handling of pointer arithmetic with unsigned value

Consider:

  using U = decltype(sizeof(42));
  constexpr int arr[] = { 3, 5, 9 };
  static constexpr int get(U i) {
    return *(arr-i);
  }
  static_assert(get(-2) == 9, "");

The front end previously accepted this, failing to recognize that the
evaluation of "arr-i" (with i a very large unsigned value resulting from the
conversion of -2) is not a valid core constant expression.  That is now fixed.


7/25/23  [EDGcpfe/26527]
Non-literal parameter and return types for constexpr functions

C++23 no longer requires a function declared "constexpr" to have literal-type
parameters and a literal return type (this is one consequence of paper
P2448R2).  The front end therefore no longer diagnoses such cases in C++23
mode.  Furthermore, GCC never diagnosed non-literal parameter and return types
for constexpr lambda call operators, and the front end now emulates that.
For example:

  struct N { N() {}; };
  void g() {
    N r = []() constexpr -> N {  // Now accepted in C++23 modes and in
      return N{};                // GNU C++11 modes.
    }();
  }


7/25/23  [EDGcpfe/23275,EDGcpfe/25037,EDGcpfe/26189]
Spurious 'argument list for variable template is missing' error during
substitution

When substitution resulted in a variable template without a template argument
list, the front end would previously always issue a diagnostic instead of
letting substitution fail.  For example, with --c++14:

  template<typename T> auto f() -> decltype(T::v);
  template<typename T> int f();
  struct A {
    template<typename> static int v;
  };
  int i = f<A>();  // Previously a spurious 'argument list for variable
                   // template "A::v" is missing' error.  Now okay.


7/25/23  [EDGcpfe/26520]
Abort on dependent noexcept expression during substitution

Consider, with --c++11:

  template<bool B>
  struct C { };
  template<typename T, typename U>
  int f(U, C<noexcept(U())>);
  int i = f<int>(1, C<true>());

When substituting the explicitly-specified template arguments into the function
template declaration, the noexcept operator remains a dependent expression.
Previously, however, that dependent noexcept operator was not correctly
represented, which could in turn lead to an abort due to a null pointer
indirection in f_identical_types (types.c).  That is now fixed.


7/24/23  [EDGcpfe/26521]
Clang compatibility: builtin signatures with vectors of __bf16 or unsigned int

The tool that generates the builtin signature table in builtin_defs.h didn't
correctly handle vectors of type __bf16 or unsigned int.  That has been
corrected.


7/24/23   [EDGcpfe/26518]
Triviality of defaulted copy constructor or copy assignment operator

Consider:

  struct S {
    S(S&) = default;
  };
  static_assert(__is_trivially_copyable(S), "");  // Previously failed.
                                                  // Now okay.

The changes for EDGcpfe/14360 intentionally caused this example to fail.
However, that appears no longer to match the C++ standard and that change has
therefore been overturned.


7/21/23  [EDGcpfe/26503]
Spurious error with capture of init-capture in nested lambda constraint

Consider, in C++20 mode:

  auto f = [i = 1]() {
    auto g = [&i]<class F>(F f) requires requires (F f) { f(i); } {};
  };

This previously triggered a spurious error claiming the init-capture i could
not be captured in the context of the requires-expression body.  That is now
fixed (and the example is thus accepted).


7/21/23  [EDGcpfe/26495]
Inherited constructor only called in a constraint

Consider, in C++20 mode:

  struct B {
    unsigned u;
    constexpr B(unsigned x): u{x} {}
  };
  struct D: B {
    using B::B;
  };
  template<typename T> concept C = static_cast<T>(1).u == 1;
  template<C T> void g(T) {}
  void f(D x) {
    g(x);
  }

Previously, this triggered a spurious error claiming the constraint couldn't
succeed because the inherited constructor D::B(int) lacks a definition.  That
is now fixed.


7/20/23  [EDGcpfe/26349]
Access checking for enumeration-qualified enumerators

As clarified by committee paper P1787R6, access checking should not be
performed for enumeration-qualified enumerators as they are considered to be
members of the enumeration.  For example, with --c++11:

  struct B {
  protected:
    enum E { E1 };
  };
  struct D : B {
    using B::E;
  };
  auto e = D::E::E1;  // Previously a spurious error. Now okay.


7/20/23  [EDGcpfe/24585,EDGcpfe/26502]
Abort on class-scope enumerator using-declaration

C++20 allows a using-declaration in class scope to also name enumerators.
However, the front end previously aborted with an internal error in
access_for_symbol (symbol_tbl.c) when such a declaration was named in a derived
class.  For example, with --c++20:

  enum E { E1 };
  struct B {
    using E::E1;
  };
  struct D : B {
    void f() {
      E1;  // Previously triggered an internal error.  Now okay.
    }
  };


7/18/23  [EDGcpfe/26507]
Erroneous folding of mutable member in GNU C++ mode

The changes for EDGcpfe/26197 in version 6.5 of the front end allowed const
variables of non-integral types to be used in constant expressions.  However,
that change failed to account for mutable subobjects of const variables.
For example:

  struct S {
    mutable int x;
  };
  S const z[] = { 1 };
  void foo(int * r) {
    *r = 10 + z[0].x;  // Previously erroneously folded to "*r = 10;".
  }                    // Now no longer folded.

That regression is now fixed.


7/18/23  [EDGcpfe/25157]
Requires-expressions in friend function template constraints

Previously, the front end did not correctly substitute a requires-expression in
a friend function template constraint, resulting in the constraint not being
considered unsatisfied.  For example, with --c++20:

  template<class T> struct A {
    template<typename U> requires requires { typename U::type; }
    friend void f(A, U) { }  // #1
  };
  int f(A<int>, long);       // #2
  int i = f(A<int>(), 1);    // Previously a spurious error as #1 was called.
                             // Now calls #2.


7/18/23  [EDGcpfe/26467]
Non-type template parameter of typedef type in friend function template
constraint

Previously, the front end failed to check the satisfaction of a constraint on a
friend function template involving a non-type template parameter declared with
a typedef type.  For example, with --c++20:

  using int_t = int;
  template<typename> struct A {
    template<int_t N> requires (N != 0)
    friend int f(A);
  };
  int i = f<1>(A<int>());  // Previously a spurious error.  Now okay.


7/17/23  [EDGcpfe/26506]
Extended position information in enk_initializer node

In some cases folding a dynamic initializer entry produces a backing expression
representation that uses an enk_initializer node.  Previously, no extended
position information was recorded in such nodes (when the configuration macro
EXTRA_SOURCE_POSITIONS_IN_IL is set to TRUE).  That is now fixed.


7/17/23  [EDGcpfe/26497]
String form of template definitions with embedded _Pragma operators

In template definitions containing _Pragma operators, the string form of
the template in the IL previously represented the _Pragma operator as the
equivalent #pragma directive.  In C++-generating back end configurations in
modes in which the definitions of templates are put out from the string
form instead of from the prototype instantiation IL (e.g., Microsoft mode
or with --no_parse_templates), this transformation produced incorrect code
when the operator is followed by other code on the same line, as the
additional code became part of the #pragma directive line.  This is now
fixed: _Pragma operators are preserved in the string form of template
definitions.  For example, with --microsoft:

  extern void g();
  template<typename>
  void f() {
    _Pragma("warning(disable : 4996)") g();   // Previously generated as
                                        // #pragma warning(disable : 4996) g();
  }


7/14/23  [EDGcpfe/26496]
__is_layout_compatible and qualified array types

The front end previously failed to ignore qualifiers on array types when
evaluating the Microsoft-mode __is_layout_compatible intrinsic.  That is now
fixed.  For example (in Microsoft C++20 mode):

  static_assert(__is_layout_compatible(const int[3], int[3]));
    // Previously failed.  Now okay.


7/14/23  [EDGcpfe/26483]
node_includes_glvalue_to_prvalue_conv

The change for EDGcpfe/26197 in version 6.5 of the front end required some
adjustments regarding which glvalue expression nodes are "rvalueable" (i.e., a
conversion to a prvalue can be represented simply by clearing the is_lvalue
and is_xvalue flags).  One consequence of that change was that the function
node_includes_glvalue_to_prvalue_conv behaved in some surprising ways.  For
example:

  void v();
  void g(bool b) {
    b ? v() : v();
  }

In version 6.5, node_includes_glvalue_to_prvalue_conv would produce TRUE for
the expression b ? v() : v(), even though that is not really meaningful for
expressions of type "void".  Another example:

  struct S { S(char const*); };
  void g(bool b) {
    int x;
    x = b ? 7 : throw S("xyz");
  }

In version 6.5, node_includes_glvalue_to_prvalue_conv would produce TRUE for
for the conditional expression (b ? 7 : throw S("xyz")), even though 7 is
always a prvalue (not requiring a conversion) and throw-expressions aren't
glvalues either.  Now, these cases (and others) have been restored to produce
the original results (i.e., for both examples there is no implied glvalue-to-
prvalue conversion).


7/14/23  [EDGcpfe/26098,EDGcpfe/26492]
Microsoft-mode abort on out-of-class definition mismatch

Consider (in Microsoft C++17 mode) the following example, which reflects a
situation that can occur from inconsistently expanding the STDMETHOD and
STDMETHODIMP macros in the Microsoft Windows SDK:

  class C {
    virtual __declspec(nothrow) long __stdcall f(int const i);
  };
  long __stdcall C::f(int i) {}  // Previously aborted.  Now okay.

This previously triggered an internal error in decl_parameter.  That is now
fixed.


7/13/23  [EDGcpfe/26462,EDGcpfe/26481,EDGcpfe/26486]
Clang compatibility: Assertion failure in get_attribute_link

The changes for EDGcpfe/25472 (in 6.5) had resulted in an assertion failure in
get_attribute_link when the using_if_exists attribute was applied to a
template, for example (with --clang --c++14):

  template <class T> void f(T t);
  namespace N {
    using ::f __attribute__((using_if_exists));
  }

These changes also address an issue that such attributes were not emitted
in C++-generating back end configurations.


7/13/23  [EDGcpfe/26484]
Incorrect processing in form_exception_specification

The code in form_exception_specification incorrectly accessed the field
an_exception_specification::noexcept_arg when the copy_from_prototype flag
is TRUE, even though that field is only valid when the flag is FALSE.
Although this routine is not believed to be called by the front end under
these conditions, such a call could result in incorrect output or an abort
due to indirection through an invalid pointer.  This is now fixed.


7/13/23  [EDGcpfe/25634]
Unicode 15.0.0 characters

The front end now supports the Unicode 15.0.0 character set.


7/12/23  [EDGcpfe/26489,EDGcpfe/26493]
C++-generating back end: GNU/clang type-transforming intrinsics

The changes for EDGcpfe/26193 added front end support for a number of
type-transforming intrinsics such as __remove_cv and __add_pointer.
However, these calls were omitted from the output of the C++-generating
back end.  This is now fixed.  For example, with --clang --c++23:

  template<typename T> struct remove_cv {
    using type = __remove_cv(T);   // Previously generated as "using type = T"
  };


7/11/23  [EDGcpfe/24649,EDGcpfe/25625,EDGcpfe/26293]
Bad access checking for protected member in nondependent call in a template

Consider:

  template<typename T> struct R {
  protected:
    template<typename U> T& operator=(const U& other);
  };
  struct D: R<D> {
    using R<D>::operator=;
  };
  template<typename> void f() {
    D d;
    d = 0; // Previously a spurious access error when instantiated.
  }        // Now okay.
  void g() {
    f<int>();
  }

Previously, the access checking performed for the call to D::operator= in the
expression "d = 0;" considered the operator from the perspective of the base
class R<D> instead of the derived class D: That resulted in a spurious access
error.  That is now fixed.


7/7/23   [EDGcpfe/26464]
Default C- and C++-generating back end generated code targets

When building a C- or C++-generating back end configuration of the front
end, if no generated code target is explicitly set and the configuration
macro EDG_WIN32 is TRUE, the front end previously defaulted to setting MSVC
as the generated code target.  However, the logic in targ_def.h could also
result in setting a different compiler as the default generated code
target, based on the compiler being used to build the front end, with a
resulting build failure due to the inconsistent settings.  This has now
been fixed.  In C-generating back end configurations, the logic in
targ_def.h now defaults the target to be the compiler used to build the
front end and only chooses MSVC in EDG_WIN32 configurations if the build
compiler is not recognized.  In C++-generating back end configurations, the
default is to set CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT to TRUE
regardless of the build compiler.


7/7/23   [EDGcpfe/26488]
Abort on pragma following attribute

Consider, in GNU mode:

  __attribute__((noreturn))
  #pragma GCC push_options
  #pragma GCC optimize("O0")
  static void f(void) {}

In C++-generating back end configurations this previously triggered an abort
(null pointer indirection) in function r_set_keep_in_il_on_sslist (il_walk.c).
That is now fixed.


7/7/23   [EDGcpfe/26482]
Abort on nontype template argument involving default member initializer

Consider in C++20 mode:

  struct X {
    int y = (delete new int(42), 0);  // Introduces an object lifetime.
    int z;
    consteval operator int() { return z; }
  };
  constexpr int N = 42;
  template<template<int> class TT> void f(TT< X{.z = N} > );
  template<int> struct I {};
  void f() {
    I<N> v;
    f<I>(v);
  }

The handling of the substituted template argument X{.z = N} previously
triggered an internal error in i_copy_dynamic_init (caused by the presence of
an object lifetime entry in the representation of X{.z = N}).  That is now
fixed.


7/7/23   [EDGcpfe/26479]
IA-64 ABI: Assertion failure in mangled_encoding_for_builtin_operation

The current vendor-specific IA-64 ABI mangling for builtin operations was
limited to 100, resulting in an assertion failure in
mangled_encoding_for_builtin_operation when trying to mangle a builtin
represented by an enumerator whose value was greater than 99.  The
vendor-specific mangling (and demangling) have now been extended to handle
this case (leaving existing manglings undisturbed).


7/7/23   [EDGcpfe/26036,EDGcpfe/26082,EDGcpfe/26121]
Constraint checking when synthesizing copy/move constructors

Previously, the front end failed to check the associated constraints of
non-template constructors during overload resolution for synthesized copy/move
constructors.  For example, with --c++20:

  template<int>
  struct B {
    B(const B&);
    B(B &&) requires false;
  };
  struct D : public B<0> { };  // Previously a spurious error.  Now okay.
  D &&g();
  D d(g());


7/7/23   [EDGcpfe/26373,EDGcpfe/26395]
Microsoft/Clang: template constraint checking when synthesizing copy/move
special members

In modes where template constraints are not checked during template argument
deduction (i.e., Microsoft and Clang modes), the front end previously failed to
check template constraints during overload resolution for synthesized copy/move
special members.  For example, with --ms_c++20:

  struct B {
    B(const B&);
    template<typename T> requires false
    B(T &&);
  };
  struct D : public B { };  // Previously a spurious error.  Now okay.


7/6/23   [EDGcpfe/26468]
[[no_unique_address]] and the Cfront-based ABI

The entry for EDGcpfe/20019,EDGcpfe/20423 describes how fields with empty
class type and the no_unique_address attribute are treated as empty base
classes for the purposes of layout in the Cfront-based ABI.  However, the
logic for that previously only covered configuration variants that enable the
empty base class optimization: In other variants of the Cfront-based ABI no
offset was generated for such fields.  That is now fixed: If the empty base
optimization is not enabled, the no_unique_address attribute is effectively
ignored.


7/6/23   [EDGcpfe/26458]
GNU-mode abort on invalid construct

Consider, in GNU C++20 mode:

  template<typename T> struct X {
    struct N { T x; };
    alignas(__alignof__(N::x)) int i; 
  };
  void f();
  X<f()> s;  // Previously sometimes aborted.  Now an ordinary error.

This example produces several errors, but in some configurations it eventually
also produced an internal error in extract_node_from_operand (exprutil.c).
That internal error is now avoided and an ordinary error is issued instead.


7/6/23   [EDGcpfe/26452]
GNU C++ compatibility: auto(x) and auto{x}

The C++23 feature allowing functional-notation casts to type "auto" is now
accepted with a warning in non-C++23 GNU C++ modes when gnu_version >= 120000.
(See also the entry for EDGcpfe/25075.)


7/6/23   [EDGcpfe/26435]
Abort on CTAD with non-type template parameter in requires clause

Previously, a requires clause referring to a non-type template parameter could
cause an internal error in transfer_arg_operand_for_template_arg (expr.c)
during class template argument deduction.  For example, with --c++20:

  template<int> concept C = false;
  template<typename T, int I = 0>
  struct D {
    D(T) requires (!C<I>);  // Previously triggered an internal error.
  };                        // Now okay.
  D d(0);


7/5/23   [EDGcpfe/26261]
Trivial copy/move initialization of [[no_unique_address]] member

Consider, in C++20 mode:

  struct A {
    unsigned u;
    A(): u(0x11111111) {}
    A(A &&a): u(a.u) { a.u = 0x33333333; }
    A(A const &a): u(a.u) {}
  };
  struct E {};
  struct C {
    A a;
    [[no_unique_address]] E e;
  };
  int main() {
    C x{C{}}; // Use move constructor
    return (int)x.a.u;
  }

The move constructor synthesized for C notionally "copies" the embedded empty
data member e.  When using the C-generating back end, however, that translated
to an actual byte copy from the source, which corrupted the eventual result.
That has been fixed in IL lowering: Any trivial copy of an optimized empty
class data member is now dropped from the IL.


7/4/23   [EDGcpfe/24353,EDGcpfe/24386,EDGcpfe/24492,EDGcpfe/24598,
          EDGcpfe/26367]
Substitution of alias template containing a function parameter pack

Previously, substitution of an alias template containing a function parameter
pack incorrectly marked the parameter as a pack element.  This could result in
spurious declaration matching errors.  For example, with --c++11:

  template<typename ... B> using P = void (*)(B ...);
  struct C {
    template<typename ... A>
    void f(P<A ...>);
  };
  template<typename ... A>
  void C::f(void (*)(A ...))  // Previously a spurious error.  Now okay.
  { }


7/4/23   [EDGcpfe/24665,EDGcpfe/26480]
Substitution for call to member function of class template

Consider, with --c++20 --g++:

  template<typename T> struct C {
    char g(T);
    int f() requires (sizeof(g(1)) == 1);
  };
  int i = C<int>().f();  // Previously a spurious error.  Now okay.

Previously, the front end failed to substitute the member function g during
constraint checking, causing the constraint to not be satisfied.  That is now
fixed.


7/1/23   [EDGcpfe/26456,EDGcpfe/26478]
C++-generating back end, GNU compatibility: __is_convertible

The GNU and Clang compilers use different builtin function names for the same
function (__is_convertible in GNU and __is_convertible_to in Clang).  The
changes for EDGcpfe/26276 had added __is_convertible in GNU modes, but when
using the C++-generating back end, this was inadvertently translated to
__is_convertible_to in the generated C++ code.  Now fixed.


6/30/23  [EDGcpfe/26341]
Clang/GCC compatibility: constexpr member functions and by-reference capture

Consider:

  struct I {
    constexpr operator int() const { return 42; }
  };
  void f(I p) {
    [&] { constexpr int N = p; };
  }

The initialization of N effectively requires the constant-evaluation of an
expression like __closure.__ref_p.operator int().  It is unclear in the C++
standard whether that is a valid constant expression, but the front end
previously always treated it as invalid.  However, GCC and Clang accept it
and the front end now emulates that behavior in the corresponding modes.


6/30/23  [EDGcpfe/26129]
Abort when using a local variable as a template argument in a lambda

Consider the following invalid example:

  template<int> void f() {}
  int main() {
    int N = 2;
    [&](){ f<N>(); }();  // Error: N is not constant.
  }

This previously triggered an internal error in get_lambda_for_scope_depth (in
scope_stk.c).  That is now fixed (an ordinary error is now issued).


6/29/23  [EDGcpfe/26465]
Better build diagnostic for NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE

The configuration option NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is
only supported by the front end when it is built using relatively recent
versions of Microsoft Visual Studio (see the comments in host_envir.h
explaining the setting and the reason for the restriction).  Previously
the requirement for Microsoft Visual Studio was enforced via a test for
EDG_WIN32 with a subsequent test for the requisite version.  However,
because it is now possible for EDG_WIN32 to be TRUE when building the
front end with compilers other than MSVC, the version test and associated
#error text have been updated to make the requirement for Visual Studio
explicit.


6/28/23  [EDGcpfe/26457]
Unexpected column positions for eok_call expression

Previously, some expression transformations (such as those performed on a call
to a function returning a reference) would result in the IL source position
information for the expression being erroneously overwritten.  This is now
fixed.


6/28/23  [EDGcpfe/26454]
Build failures on some platforms when MICROSOFT_EXTENSIONS_ALLOWED is TRUE

Previously, on platforms with size_t types that did not correspond to uint32_t
or uint64_t (e.g., Mac OS) the front end would fail to build in configurations
where MICROSOFT_EXTENSIONS_ALLOWED is TRUE.  This is now fixed.


6/28/23  [EDGcpfe/26418]
Deduction guide correspondence in multi-TU mode

Previously, two equivalent deduction guides, e.g.:

  template <typename, typename> class a;
  template <typename b> a() -> a<b, b>;

compiled in two TUs in multi-TU mode would fail.  Support for deduction guide
correspondence in multi-TU mode has been implemented.  This is now fixed.


6/23/23  [EDGcpfe/19810,EDGcpfe/20667,EDGcpfe/25807,EDGcpfe/26254]
GNU/Clang compatibility: spurious "call through incomplete class" warning

The warning added for EDGcpfe/15754 (see entry of 12/4/14) to improve
compatibility with GCC/Clang did not accurately match the behavior of GCC and
Clang, as the example provided was not actually accepted by GCC or Clang.
Instead, GCC and Clang accept some cases because they consider some expressions
involving "this" to be template-dependent (see EDGcpfe/16428).  The warning
ec_call_through_incomplete_class_type has therefore been removed.  For example,
with --c++11 --g++ --no_defer_parse_function_templates:

  struct C {
    int operator () () const;
    template<int I>
    static auto f(const C &c) -> decltype(c());  // Previously a spurious
                                                 // warning.  Now okay.
  };
  int i = C::f<0>(C());
  struct D;
  template<typename> void f(D const &d) {
    d();  // Previously a warning.  Now an error.
  }


6/23/23  [EDGcpfe/20691,EDGcpfe/26425]
Missing diagnostic on defining a type in a range-for-declaration

The front end previously accepted the following example in C++11 mode and the
C++ generating back end would then segfault on the type definition in the
range-for-declaration:

  struct R {
    const int *begin(), *end();
  };
  void f(R r) {
    for (struct S { S(int) { } } s : r) { } // Previously accepted.
                                            // Now an error.
  }

The standard, however, does not allow a type to be defined in a
range-for-declaration.  This is now fixed: A diagnostic is issued.


6/22/23  [EDGcpfe/26288]
Abort on coroutine with non-trivially destructible automatic variables with
exceptions disabled

With exceptions disabled, the front end previously passed an incorrect entity
pointer to bind the object lifetimes in a coroutine function body to.  This
could result in failed assertions, IL write-read errors, or potentially
segfaults.  For example, with --c++20 --no_exceptions:

  #include <coroutine>
  struct my_task {
    struct promise_type {
      my_task get_return_object();
      std::suspend_never initial_suspend();
      std::suspend_never final_suspend() noexcept;
      void return_void();
      void unhandled_exception();
    };
  };
  my_task f() {
    struct C {
      ~C() { }
    } c;
    co_return;
  }


6/22/23  [EDGcpfe/26390]
Implicit instantiation of coroutine promise_type constructor

Consider, with --c++20:

  #include <coroutine>
  template<typename T>
  struct my_task {
    struct promise_type {
      promise_type(int) { }
      my_task get_return_object() { return { }; }
      std::suspend_never initial_suspend() { return { }; }
      std::suspend_never final_suspend() noexcept { return { }; }
      void return_void() { }
      void unhandled_exception() { }
    };
  };
  my_task<int> f(int) { co_return; }

Here, the front end finds a viable promise_type constructor for an argument
list of "int" and selects that constructor for constructing the promise object
of the coroutine.  However, it previously did not mark the selected function as
referenced and thus did not instantiate the function.  That is now fixed.


6/22/23  [EDGcpfe/25849,EDGcpfe/26229,EDGcpfe/26377]
Nested template arguments with associated constraints in subsumption checking

Consider, with --c++20:

  template<typename T> struct X;
  template<typename T> concept C0 = true;
  template<typename T> concept C1 = C0<X<T>>;
  template<typename T> concept C2 = C0<X<T>> && true;
  template<typename> struct P;
  template<C1 C> struct P<C> { };
  template<C2 C> struct P<C> { };
  P<int> p;  // Previously a spurious error.  Now okay.

Previously, the front end could not decide between the two partial
specializations of P when instantiating P<int> because it additionally compared
the associated constraints in the substituted nested template arguments of
C0<X<T>> and therefore failed to see that C2<T> subsumes C1<T>.  That is now
fixed.


6/21/23  [EDGcpfe/26403]
C++-generating back end: global-scope variable as bit-field width

When the width of a bit-field begins with a global-scope qualifier, the
C++-generating back end failed to insert a space between the colon
delimiting the width expression and the global-scope qualifier.  This is
now fixed.  For example, with --c++11:

  constexpr int x = 1;
  void f() {
    int x;
    struct S {
      unsigned i : ::x;   // Previously generated as "i:::x", which is
                          // incorrect, equivalent to "i :: : x"
    };
  }


6/21/23  [EDGcpfe/26251]
C++-generating back end: lambda as initializer in init-statement

Given an init-statement in which the initializer is a lambda expression,
the C++-generating back end previously put out a typedef declaration
following the init-statement giving the closure type a temporary name (of
the form __T12345678).  Such a declaration is not permitted by the syntax
of C++ and is now suppressed.  For example, with --c++17:

  void f() {
    // Previously included "typedef decltype(l) __T1234578;" in the
    // generated code before the call to l():
    switch (auto l = []{return 0;}; l())
      {}
  }


6/21/23  [EDGcpfe/26262]
C++-generating back end: crash with non-public name as template argument

In C++-generating back end configurations, the front end sometimes entered
an unbounded recursion when attempting to put out a template-id in which a
template argument refers to a non-public class member.  This is now fixed.
For example, with --c++17:

  template <typename T> struct A { using type = T; };
  template <typename T> using B = typename A<T>::type;
  template <int> struct S {};
  class C {
    static constexpr int I = 0;   // private
    using SI = S<I>;
    void f() {
      B<SI>{};                    // resulted in crash with unbounded recursion
    }
  };


-------------------------------------------------------------------------------
Version 6.5, June 21, 2023

6/19/23  [EDGcpfe/26437]
Constexpr static data members

C++17 (via WG21 paper P0386R2) made constexpr static data members
implicitly inline and removed the previous requirement that such members
have an explicit initializer in the class definition; a constexpr default
constructor in the type of such members is sufficient.  The front end now
follows these rules in C++17 and later modes.  For example, with --c++17:

  struct S {
    constexpr S() : i(0) { }
    int i;
  };
  struct X {
    constexpr static S s;   // Previously an error, now accepted in C++17 mode
  };


6/16/23  [EDGcpfe/26428]
Pragmas attached to namespace aliases

A change in version 6.4 introduced a regression that prohibited a pragma
from attaching to a namespace alias and has now been fixed.  For example:

  namespace N {}
  #pragma test_next_decl
  namespace A = N;


6/13/23  [EDGcpfe/25509,EDGcpfe/25966]
C23/C++23: Labels in compound statements

The changes in P2324R2 (C++23) and N2508 (C23) now allow a label to be the
last item in a compound statement.  Additionally, C23 now allows a declaration
to be labeled.  The front end had previously issued a warning (or error, in
strict mode) for these constructs and now accepts them in the appropriate
modes.  For example:

  void f() {
  first:  // No diagnostic in C23 mode.
    int x = 0;
  last:   // No diagnostic in C23 mode or C++23 mode.
  }


6/7/23   [EDGcpfe/26404]
Segfault in alloc_or_dealloc_routine_from_new_delete

In configurations where NEW_CAN_BE_FOLDED_INTO_CTOR or
DELETE_CAN_BE_FOLDED_INTO_CTOR are TRUE, a missing skip_typerefs had caused
a segfault on this example (with --c++20):

  template <typename> struct A {};
  template <typename T> struct A<T &> {
    typedef T t;
  };
  template <typename T> concept C = requires { new T; };
  template <typename T> A<T>::t f(T &&);
  struct E {
    E();
  };
  template <typename T> struct B {
    B() requires C<T>;
    B(T);
  };
  E e;
  B b { f(e) };


6/6/23   [EDGcpfe/26385]
Corruption in evaluation of __builtin_memcmp

The constant-evaluation of __builtin_memcmp sometimes performed an out-of-
bounds access when the operands included the address of a member array.  That
is now fixed.


6/5/23   [EDGcpfe/10223]
Invalid recursive templates no longer instantiate infinitely

Consider the following invalid code:

  template<typename T>
  void foo(T) noexcept(foo([](T a, T b) {a + b;} )) {
  }

  void g() {
    foo([]{return 0;});
  }

Previously, this would result in an infinite recursive instantiation and
accompanying diagnostics.  This is now fixed.


6/5/23   [EDGcpfe/26345]
Expansion of integral diagnostic fill-ins

A new diagnostic fill-in, %u, can now be used in error_msg.txt for diagnostics
that need to emit unsigned integers (up to 64 bits).  Additionally, the front
end now supports up to 64-bit signed integers when using %d.


5/31/23  [EDGcpfe/26274]
GNU compatibility: GCC 13.1.0 builtins

The front end has been updated with the latest builtin signatures from
GCC version 13.1.0.


5/31/23  [EDGcpfe/22778]
Overload resolution failure diagnostics

The front end has been modified to provide additional notes in overload
resolution failure diagnostics.  Whether these notes are emitted is controlled
by the global variable add_match_nodes, whose default value is controlled by
the configuration macro DEFAULT_ADD_MATCH_NOTES.  Command-line options
--add_match_nodes/--no_add_match_notes can override this default.  Assuming
the additional notes are enabled, the example

  template<typename T> int f(T);
  template<typename T> T f(int, int);
  auto r = f<void>(42);

now elicits the following diagnostics:

  "fail.cpp", line 3: error: no instance of overloaded function "f" matches the
            argument list
              argument types are: (int)
    auto r = f<void>(42);
             ^
  "fail.cpp", line 2: note: number of parameters of function template
            "f<T>(int, int)" does not match the call
    template<typename T> T f(int, int);
                           ^
  "fail.cpp", line 1: note: substituting explicit template arguments "<void>"
            for function template "f(T)" failed
    template<typename T> int f(T);
                             ^

It is expected that these notes will evolve in forthcoming versions (for
example, the last note in the above example should eventually be more
descriptive about the reason for the substitution failure).  For customers
recording front end output for regression testing, we recommend first building
the front end with DEFAULT_ADD_MATCH_NOTES set to 0 and once that is
validated, enable the feature by switching DEFAULT_ADD_MATCH_NOTES to 1.


5/30/23  [EDGcpfe/18316,EDGcpfe/22881,EDGcpfe/26290,EDGcpfe/26308,
          EDGcpfe/26332]
GNU compatibility: _Float32x and _Float64x floating-point types

In GNU modes with gnu_version >= 130000, the front end now supports the
_Float32x and _Float64x floating-point types.  Although they are distinct
types, _Float32x and _Float64x have the same representation as double and
long double, respectively.  In addition, the f32x/F32x and f64x/F64x
floating-point literal suffixes are recognized and give literals the
_Float32x and _Float64x types, respectively.  For example, with
--gnu_version=130100:

  _Float32x x = 1.0f32x;   // Now accepted with gnu_version >= 130000


5/26/23  [EDGcpfe/26219]
GNU/Clang compatibility: compile-time execution of __builtin_copysign*

The __builtin_copysign, __builtin_copysignf, and __builtin_copysignl routines
can now be invoked at compilation time in GNU and clang emulation modes.


5/25/23  [EDGcpfe/26368]
Access to uninitialized memory in interpreter (do_constexpr_condition_cleanup)

In some cases, the front end could access uninitialized memory in the function
do_constexpr_condition_cleanup of the constant-evaluation interpreter, after
interpretation failed.  For example:

  struct S;
  S* g();
  void f() {
    []() {
        if (auto s = g(); true) {}
    }();
  }

Here, after failing to evaluate g() (and, thus, failing to initializing s),
the interpreter's cleanup process attempted to access the contents of s despite
it not being initialized.  That is now fixed.


5/24/23  [EDGcpfe/26058]
is_local_to_function incorrectly set to FALSE for friend function parameter

Consider (in C++11 mode):

  template<bool>
  struct A {
    friend void f(A a) noexcept(true) { }
  };
  void g(A<true> o) {
    f(o);
  }

As the noexcept specification is only instantiated when needed, the front end
needs to recreate the function prototype scope for the delayed instantiation.
Previously, this prototype scope was not recreated with the same scope number
as the original scope.  That in turn caused is_local_to_function of the friend
function parameters to be set to FALSE.


5/24/23  [EDGcpfe/23420,EDGcpfe/26014,EDGcpfe/26353]
Parsing of friend function noexcept specification in complete class context

The C++ Standard requires the noexcept specification of a member declaration to
be a complete class context.  Previously, the front end only treated the
noexcept specification of non-friend declarations as such.  Now this also
applies to friend declarations.  For example, with --c++11:

  struct B {
    friend void f(B) noexcept(v);  // Previously a spurious 'identifier "v" is
                                   // undefined' error.  Now okay.
    static constexpr bool v = true;
  };


5/23/23  [EDGcpfe/26276,EDGcpfe/26291]
GNU compatibility: additional type traits for GCC 13.1.0

The __is_convertible, __is_nothrow_convertible,
__reference_constructs_from_temporary, __reference_converts_from_temporary, and
__remove_reference type traits have been implemented in GNU emulation mode
when gnu_version >= 130000.

While implementing these type traits it was found that, contrary to our claims
in the entry for EDGcpfe/23402, GCC implements the resolution of Core issue
2267.  The behavior of the front end was adjusted to match in the corresponding
modes.


5/22/23  [EDGcpfe/24940,EDGcpfe/25601,EDGcpfe/26354]
Abort in push_template_instantiation_scope

A number of situations could result in an assertion error when pushing an
instantiation scope for rescanning purposes.  For example, in Clang C++20 mode:

  template<typename T> decltype(T::f()) g(T);
  template<typename T> struct S {
    static void f() requires __is_pointer(T) || requires(T x) { x.f; };
  };
  void h() { g(S<S<int*>>()); }  // Previously triggered an internal error
                                 // while substituting the constraint for
                                 // S<int*>::f().

That is now fixed.


5/17/23  [EDGcpfe/25657,EDGcpfe/26023,EDGcpfe/26101]
Expression operands of typeid

Previously, the expression operand of a typeid operator was parsed by default
as an evaluated operand, even when it was not of a polymorphic type.  The front
end did perform some compensations if it turned out that no evaluation is
needed, but some side effects of the processing -- like the instantiation of
used entities -- remained.  That could result in spurious errors.  For example:

  #include <typeinfo>
  template<typename> struct X;
  template<typename T> struct S {
    X<T> *px;
    S f() { *px >> 2; return *this; }
  };
  void g() {
    S<char> sc;
    (void)typeid(sc.f());
  }

Previously, this triggered the instantiation of S<char>::f() -- even though the
reference to that function is not evaluated -- and subsequently an error
because "*px >> 2" is not valid during that instantiation.  Now the example is
accepted because the front end processes the operand of typeid as a true
unevaluated operand.


5/16/23  [EDGcpfe/23765,EDGcpfe/26324]
Performance issue with recursively defined class templates

Consider, with --c++ --pending_instantiations 100:

  template<typename, typename> struct A { };
  template<typename T, int N>
  struct C {
    typedef typename C<A<T, T>, N - 1>::type type;
  };
  template<typename T>
  struct C<T, 0> {
    typedef A<T, T> type;
  };
  C<int, 100>::type t;

This creates a binary tree of class template specializations with a depth of
100.  Previously, however, for several type traversals (like checking for error
types), the whole tree was traversed (with exponential complexity).  Now these
traversal results are cached for each class type in its class type supplement
in contains_error, contains_error_cached, contains_unnamed_namespace_type,
contains_unnamed_namespace_type_cached,
does_not_contain_parentless_lambda_in_default_argument, and
does_not_contain_deprecated_or_unavailable_type (a small IL CHANGE), resulting
in linear complexity for these traversals.


5/8/23   [EDGcpfe/26319]
GNU C++11 compatibility: Statements in constexpr function templates

Consider:

  template<typename T> constexpr int f(T p) {
    p += 1;  // Now accepted in some GNU C++11 modes.
    return p;
  }
  int r = f(42);

Ordinarily, this is an error in C++11 modes because only return statements
are permitted in C++11 constexpr functions; technically, the standard does not
require a diagnostic in such cases, but most implementations do emit one.
GCC 12.x and later accept such templates and silently treat them as
non-constexpr.  The front end now emulates that behavior in GNU C++11 modes
with gnu_version >= 120000.


5/5/23   [EDGcpfe/26302]
Inconsistent handling of subobject initialization status in constant evaluation

Consider:

  struct S {
    int i[2];
    constexpr S() { i[0] = '1'; }
  };
  constexpr S s;  // Previously erroneously accepted.

  struct P { int x; int y; };
  struct X {
    P c[2];
    constexpr T() { c[0].x = c[0].y = c[1].x = c[1].y = 0; }
  };
  constexpr X x;  // Previously a spurious error.

During constant evaluation, the front end sometimes did not correctly
determine whether the result of the evaluation was fully initialized.
For variable s above, s.i[1] is not initialized and should thus elicit an
error.  Previously, however, it was accepted.  Conversely, variable x is
fully initialized but the front end previously claimed otherwise.  Those
issued are now fixed.


5/5/23   [EDGcpfe/26306]
Abort on invalid local linkage-specification

Consider:

  typedef struct { int i; } Int;
  void g(Int);
  void f(int i) {
    extern "C" {  // Invalid local linkage-specification.
      Int I = { .i  = i };
      g(I);
    }
  }

The linkage-specification is invalid in a local scope and that is correctly
diagnosed by the front end.  However, in configurations with the macro
EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE, this example resulted in an internal
error.  That is now fixed.


5/4/23   [EDGcpfe/26193]
Clang compatibility: Type-transforming intrinsics (IL CHANGE)

In Clang modes, the front end now accepts a number of type-transforming
intrinsics.  For example:

  using X = __add_pointer(int);  // Same as: using X = int*;

The intrinsics initially being supported are __add_lvalue_reference,
__add_pointer, __add_rvalue_reference, __decay, __make_signed,
__make_unsigned, __remove_all_extents, __remove_const, __remove_cv,
__remove_cvref, __remove_extent, __remove_pointer, __remove_reference_t,
__remove_restrict, and __remove_volatile.

These intrinsics are represented using a_type/tk_typeref entries.  To
accommodate a possibly large number of such intrinsics in the future, a number
of mutually-exclusive flags (e.g., is_decltype and is_alias) have been
replaced by a new "kind" field in the a_type::variant.typeref sub-structure.


5/4/23   [EDGcpfe/24890]
Incorrect lookup in lambda expression in static data member template
initializer

Previously, when a generic lambda expression was used in the initializer of a
static data member template, lookup skipped the template parameter scope of
that static data member template.  For example, with --c++17:

  struct C {
    template<int I>
    static inline auto l = [] (auto j) {
      return I + j;  // Previously a spurious 'identifier "I" is undefined'
    };               // error.  Now okay.
  };
  auto v = C::l<1>(1);


5/3/23   [EDGcpfe/21894,EDGcpfe/24057,EDGcpfe/24481,EDGcpfe/25350,
          EDGcpfe/26292]
Microsoft compatibility: Exception specifications and defaulted members

Consider:

  struct X { X() noexcept(false); };
  struct S {
    X x;
    S() noexcept(true) = default;
  };
  S s;  // Previously an error in Microsoft modes.  Now okay when
        // microsoft_version >= 1928.

Older versions of MSVC considered the default constructor of S to be deleted
because its explicit exception specification doesn't match the implied one.
However, starting with version 19.28 MSVC handles such cases in a standard way
and the front end now emulates that in Microsoft C++ modes with
microsoft_version >= 1928.


5/2/23   [EDGcpfe/26268]
GNU/Clang compatibility: Address of weak variable

Previously, the front end did not allow taking the address of a weak variable
during constant evaluation.  Now, that is allowed (which matches the behavior
of GCC and Clang).


5/2/23   [EDGcpfe/26264]
Abort on template-id in conditional operator with throwing branch

Consider:

  bool b;
  template<typename> int f();
  template<typename> auto g()->decltype(b? f<int> : throw 0);
    // Previously aborted.  Now okay.

This previously aborted in extract_node_from_operand (in exprutil.c, with
message "converting unexpected operand kind").  That is now fixed.


5/2/23   [EDGcpfe/26301]
new/delete mismatch in constant expressions

Consider, in C++20 mode:

  constexpr bool f() {
    delete new int[42];
    return true;
  }
  static_assert(f());  // Previously okay.  Now an error.

The call to f() is invalid because a non-array delete-expression is used to
deallocate storage acquired with an array new-expression.  Previously, the
front end failed to catch that mismatch.  Now it does (resulting in an error
for the example above).


5/2/23   [EDGcpfe/25550]
Spurious error on nondependent aggregate with dependent braced initializer

Consider (in C++20 mode):

  struct B { int x, y; };
  struct D: B {};
  int r = [](auto p) {
            D d = { p.x, p.y };  // Previously an error.
            return p.x+p.y;
          }(D{ 1, 2 });

Previously this produced an error about there being too many initializers
because the front end could not match the (dependent) braced initializer with
the (nondependent) type D.  In some cases, the spurious error was a
regression introduced by the changes for EDGcpfe/22003,EDGcpfe/23814 in
version 6.3 of the front end.  This is now fixed.


4/28/23  [EDGcpfe/24594,EDGcpfe/26275]
Nonstandard implicit conversion from scoped enum type

In Microsoft C++ mode and in the GNU C++ mode with gnu_version between 50000
and 59999, the front end now accepts (with a warning) scoped enum type values
as initializers for unrelated enumerator constants.  For example:

  enum class X { x };
  enum class Y { y = X::x };  // Now accepted with a warning in some modes.


4/28/23  [EDGcpfe/24643,EDGcpfe/24654,EDGcpfe/25000]
Spurious substitution failure for __integer_pack

When explicit template arguments are substituted into the function type,
function parameter packs cannot be fully expanded yet, meaning that the size of
such a pack will still be dependent after this initial substitution.  However,
an __integer_pack construct with a dependent argument was previously considered
a substitution failure.  For example, with --c++11 --g++:

  template<typename T, T ...>
  struct S { };
  template<typename ... T>
  auto f(T ...) -> S<int, __integer_pack(sizeof ... (T))...>;
  auto v = f<int>(1, 2);  // Previously a spurious error.  Now okay.


4/27/23  [EDGcpfe/26198]
reinterpret_cast in constant-expressions

A number of relatively minor changes have been made to the handling of
reinterpret_cast (and reinterpret-like casts) in constant expressions.  Mostly,
this causes more such constructs to be accepted in GNU C++ modes.  In some
cases, it causes them to be diagnosed in non-GNU modes where previously they
were erroneously accepted.  For example:

  extern int x;
  using size_t = decltype(sizeof(int));
  constexpr size_t arr[] = { 1, (size_t)&x };
      // Previously accepted in most modes.  Now an error by default because
      // the cast is reinterpret_cast-like.
  constexpr size_t r = arr[0];
      // Previously rejected in all modes.  Now accepted in some GNU C++ modes.


4/27/23  [EDGcpfe/22613]
Hang during recovery of code containing a C++20 abbreviated template

Previously, the front end would hang indefinitely when attempting to recover
from an unexpected "{" (when a declaration is otherwise expected) followed by a
C++20 abbreviated template, e.g.:

  namespace {
    { /* ... */ }
    void f ( auto ) { }
  }

This is now fixed.


4/27/23  [EDGcpfe/26221]
GNU compatibility: _Float32, _Float64, and _Float128 types

Version 13.1.0 of gcc supports the floating-point types _Float32, _Float64,
and _Float128 in both C and C++.  In C++ modes, the types are synonyms for
the C23 extended floating-point types std::float32_t, std::float64_t, and
std::float128_t, respectively (see
EDGcpfe/25100,EDGcpfe/25170,EDGcpfe/25515).  Also, g++ does not enforce the
restrictions against lossy conversions required for the extended
floating-point types.  The front end has now been changed to emulate these
behaviors in GNU modes when gnu_version >= 130000 (_Float128 is supported
only when FLOAT128_ENABLING_POSSIBLE is configured as TRUE).  For example,
with --gnu_version=130100:

  _Float32 x = 0.0;   // Now accepted in both gcc and g++ modes


4/27/23  [EDGcpfe/25817]
Skipping discarded substatements of constexpr if containing less-than operator

In modes where non-class templates are not parsed (e.g., permissive Microsoft
mode), the front end would sometimes fail to correctly skip the discarded
substatements of a constexpr if during instantiation.  For example, with
--ms_c++17:

  template<int> struct X { };
  template<bool B>
  void f() {
    if constexpr (B) {
      int X = 0;
      bool b = X < 0;
    }
  }  // Previously a spurious 'expected a "}"' error.  Now okay.
  template void f<false>();


4/27/23  [EDGcpfe/19798,EDGcpfe/19950,EDGcpfe/20260,EDGcpfe/23304,
          EDGcpfe/24614,EDGcpfe/25463,EDGcpfe/25624,EDGcpfe/25804,
          EDGcpfe/26282]
Inaccessible member function during substitution

Previously, when a member with a dependent name resolved to a using declaration
during substitution, accessibility of the using declaration was not considered.
This could result in substitution failure when the underlying function was not
accessible.  For example, with --c++11:

  struct B {
    int f();
  };
  template<typename T>
  struct D : private T {
    using T::f;
  };
  template<typename T>
  auto g(D<T> d) -> decltype(d.f());
  int i = g(D<B>());  // Previously a spurious error.  Now okay.


4/27/23  [EDGcpfe/24033,EDGcpfe/24311,EDGcpfe/26184]
Excessive stack usage during IL walks

In some cases the IL walk needs to do a full walk for the "next" pointer, but a
recursive walk can result in very deep call stacks.  In these cases, the walk
is now performed in an iterative way.  Furthermore, non-optimized builds don't
tend to reuse stack space for local variables that are only used in separate
code paths.  To reduce stack usage in those cases, local variables are now only
used in immediately-invoked lambda expressions.


4/26/23  [EDGcpfe/26279]
Change to suppress pragma processing when flushing tokens

A change has been made to suppress pragma processing when flushing tokens
during an error recovery.


4/26/23  [EDGcpfe/26149]
IL write-read error on inherited constructor with default argument

Consider:

  struct A { ~A(); };
  template<typename T> struct X { X(int, T, A = A()); };
  template<typename T> struct Y : public T { using T::T; };
  struct S {
    X<double> x{1, 1.0};
    Y<X<double>> y{1, 1.0};
  };

Previously, this triggered an IL write-read error (which is an internal error).
That is a regression introduced in version 6.4 of the front end by the changes
for EDGcpfe/25087.  It is now fixed.


4/26/23  [EDGcpfe/25936]
Microsoft C++ compatibility: support parsing typeid when no_rtti is set

Consider, in Microsoft C++ mode:

  #include <typeinfo>

  void foo() {
    auto& ti1 = typeid(int);
  }

In recent MSVC releases, typeid is parsed even when MSVC's runtime type
information support is disabled (via passing /GR-).  To match this behavior,
the above code is now accepted in Microsoft mode when --no_rtti is passed as a
command-line option.


4/25/23  [EDGcpfe/25908]
Microsoft C++ compatibility: overriding __declspec(nothrow) member functions

Consider, in Microsoft C++17 mode:

  struct B {
    virtual __declspec(nothrow) void f();
  };
  struct D: B {
    void f();  // Previously a warning or error.  Now silently accepted.
  };

In recent Microsoft C++17 modes, __declspec(nothrow) causes the member function
to be treated as a noexcept function.  That in turn would ordinarily make
overriding with a non-noexcept function an error (or, in some Microsoft C++
modes, a warning).  However, it appears Microsoft compilers do not report such
a mismatch and the front end now emulates that behavior.


4/25/23  [EDGcpfe/25907]
Microsoft C++ compatibility: enumerator constant overflow

Consider:

  enum E: int { x = 32768, y = 0x80000000 };

In Microsoft mode, the overflow of initializer for y is warned about (see also
the entry for EDGcpfe/12251), but in later processing the front end also issued
an error about it.  That error is now no longer issued.


4/24/23  [EDGcpfe/26269]
Abort on array with local bound in alias template substitution

Consider:

  template<typename> struct S;
  template<typename T, int N> using AS = S<T[N]>;
  template<int N> void g() {
    constexpr int Count = N;
    AS<int, Count> as;  // Previously aborted.  Now okay.
  }

Previously this aborted in make_bound_expr_referenceable_from_file_scope (in
declarator.c) with an internal error.  That is now fixed.


4/21/23  [EDGcpfe/20257,EDGcpfe/23741,EDGcpfe/25214,EDGcpfe/26249]
Clang/GNU C++ compatibility: Default bit field initializers

In Clang and GNU C++11 compatibility modes (with, respectively, clang_version
at least 60000 or gnu_version at least 80000) the front end now accepts
default bit field initializers even if C++20 mode is not enabled (with a
warning).  For example:

  struct S {
    int i:4{2};  // Now accepted with a warning in some GNU/Clang C++11 modes.
  };


4/21/23  [EDGcpfe/26002,EDGcpfe/26265]
_Atomic as an array qualifier

In C11 mode, the changes for EDGcpfe/25245 introduced a regression in version
6.4 of the front end, causing it to no longer accept _Atomic as a C-style array
qualifier.  For example:

  extern void f (int [_Atomic]);  // Now accepted by version 6.4 in C11 mode.

That is now fixed.


4/21/23  [EDGcpfe/26266]
C++-generating back end: dependent function calls with designated initializers

In cases in which the argument in a dependent function call is an initializer
list that uses designated initializers, the C++-generating back end previously
inserted an extraneous comma between the designator and the initializer
expression.  This is now fixed.  For example, with --c++20:

  template<typename> struct A {
    char c;
  };
  template<typename T> struct B {
    static void f(const A<T>&) {}
    template<typename> void g() {
      f({.c = ' '});   // Previously generated as "{.c = , ' '}"
    }
  };


4/21/23  [EDGcpfe/26151,EDGcpfe/26260]
Move-construction from user-defined conversion result

Consider:

  struct D {
    D(int);
  };
  struct S {
    operator D();
    operator int();
  };
  void f(S s) {
    D d{s};  // Previously ambiguous.  Now okay in nonstrict C++17 modes.
  };

The standard makes the above example ambiguous and the front end previously
issued a diagnostic for that case in all C++ modes.  However, common modern
practice by other compilers is to accept that case in C++17 mode because
conversion via S::operator D() elides the move-constructor invocation of D and
thus can be seen as a "more direct" initialization of d.  The front end now
implements that practice in non-strict modes.  (This is closely related to the
changes for EDGcpfe/22154,EDGcpfe/22884,EDGcpfe/25383.  It is also covered by
the standardization committee's paper P2828R0.)



4/19/23  [EDGcpfe/26197]
GCC compatibility: Non-integral const variables

Consider:

  struct S {
    explicit constexpr S(float const& a) : v(a) {}
    float v;
  };
  S const x{0};
  constexpr S y{x};  // Now accepted in GNU C++11 modes.

Ordinarily, this is an error because x is not potentially-constant (it is
neither constexpr nor of a const integral type).  However, GCC appear to treat
as potentially-constant const variables of non-integral types and the front end
now emulates that behavior.  The example above is therefore now accepted in
GNU C++11 modes.


4/19/23  [EDGcpfe/26181]
Failed constraint check for explicitly-specified template arguments

The changes for EDGcpfe/25848 (not in a release but distributed to some
customers as a patch) introduced a regression for checking the constraints of a
function template with explicitly-specified template arguments.  For example,
with --c++20:

  template<typename ... T> int f(T ... t) requires(sizeof...(T) > 1);
  int i = f<int>(1, 2);  // Previously a spurious error.  Now okay.


4/18/23  [EDGcpfe/26256]
Abort on ambiguous user-defined conversion

The changes for EDGcpfe/22154 introduced a regression in version 6.3 causing
some ambiguous conversion cases to lead to an abort due to a null pointer
indirection in overload.c (function match_with_udc_to_constructor_class).
For example:

  struct S {
    S(float);
    S(short);
  };
  struct R {
    operator float() const;
    operator double() const;
  };
  void g() {
    R s;
    static_cast<S>(s);  // Previously aborted.  Now an ordinary error.
  }

That is now fixed.


4/18/23  [EDGcpfe/26259]
GNU compatibility: STDC pragmas

The front end previously erroneously failed to recognize the C99 and C++11
STDC pragmas in GNU emulation modes.  This is now fixed.  For example, with
--g++ --c++11:

  #pragma STDC FENV_ACCESS DEFAULT   // Now correctly accepted


4/18/23  [EDGcpfe/26258]
Conditional operation on vector defined with typedef element type

The front end previously issued a spurious "incompatible types" error for a
conditional operator in which the condition is a vector and the operands
are vectors defined with a typedef as the element type.  This is now fixed.
For example, with --c++17 --gnu_version=120100:

  typedef float xxx;
  typedef xxx vf __attribute__ ((vector_size (64)));
  vf f(vf a, vf b) {
    return (a < b) ? a : b;   // Previously a spurious error, now okay
  }


4/18/23  [EDGcpfe/26052]
Abort on out-of-class partial specialization of static data member template

Previously, the front end aborted with a failed assertion in
enclosing_class_type for an out-of-class partial specialization declaration of
a static data member template.  For example, with --c++14:

  template<typename T>
  struct C {
    template<typename U>
    static T s;
  };
  template<typename T> template<typename U>
  T C<T>::s<U *> = 1;  // Previously aborted during instantiation.  Now okay.
  int i = C<int>::s<int *>;


4/18/23  [EDGcpfe/26216]
Uninitialized memory access for ill-formed structured binding declaration

When parsing an ill-formed structured binding declaration where the
decl-specifiers denote a function type, the front end would previously attempt
to access uninitialized memory.  For example, with --c++17:

  using fn_t = void();
  fn_t [ v ] = 0;


4/17/23  [EDGcpfe/26217]
Default arguments for non-type template parameters of reference to auto type

When using a default template argument for a non-type template parameter of
reference to auto type, the front end previously checked whether the type of
the default template argument was valid as a non-type template parameter type
instead of the deduced template parameter type.  For example, with --c++17:

  struct B { B(); };
  B b;
  template<auto &v = b>
  int f() { return 0; }
  int i = f();  // Previously a spurious error.  Now okay.


4/14/23  [EDGcpfe/26088]
Representation of static assertions (IL Change)

In block scopes, static_assert constructs trigger the emission of an stmk_decl
entry, but that entry previously did not refer back directly to a
representation of the construct.  Instead, in configurations with
GENERATE_SOURCE_SEQUENCE_LISTS a source sequence entry would point to an entry
of type a_static_assertion.  Now, the "entities" list associated with the
stmk_decl entry for a static assertion will have its first entry refer to an
entry of type a_static_assertion describing the construct.


4/13/23  [EDGcpfe/25472,EDGcpfe/26223]
Clang attribute using_if_exists

The changes for EDGcpfe/25243,EDGcpfe/25501 (see entry of 8/3/22) allowed the
front end to recognize the Clang "using_if_exists" attribute, but they did not
cause the attribute to have any effect.  Now, the attribute inhibits an error
that otherwise would be issued for a non-existing identifier.  For example:

  namespace N {};
  using N::X __attribute((using_if_exists));  // Previously an error because X
                                              // is not declared.  Now okay.

In such cases, no IL is recorded for the using-declaration (e.g., they are not
rendered by the C++-generating back end).


4/13/23  [EDGcpfe/24660,EDGcpfe/24941,EDGcpfe/26120,EDGcpfe/26234,
          EDGcpfe/26235]
Incorrect synthesis of move-assignment operator

Consider:

  struct B {};
  struct D: B {
    using B::operator=;
    D& operator=(D&);
  };
  struct S {
    D d;
  };
  void f(S s) {
    s = S{};  // Previously an error.  Now okay.
  }

Previously, the move-assignment operator of S was not synthesized because the
inherited assignment operators of D were not considered.  In turn, that caused
the assignment "s = S{}" not to find a matching operator=.  That is now fixed.


4/12/23  [EDGcpfe/26119]
Correspondence of declarations with trailing requires clause

A using declaration in class scope only adds those declarations from a base
class that do not correspond to (and thus would conflict with) other
declarations in the class.  However, the front end previously did not take
trailing requires clauses into account when checking whether declarations
correspond.  For example, with --c++20:

  struct B { };
  template<typename T> struct D : B {
    D() requires (sizeof(T) > sizeof(char));
    using B::B;  // B's default constructor was not inherited.
  };
  D<char> d;     // Previously a spurious error.  Now okay.


4/11/23  [EDGcpfe/24656,EDGcpfe/24926,EDGcpfe/25916]
__is_constructible for aggregate initialization in C++20 mode

Previously, an aggregate with a member of non-aggregate class type that does
not have a viable constructor would not cause the __is_constructible type
trait helper to fail.  For example, with --c++20:

  struct X {
    X(const char *);
  };
  struct C {
    X x;
  };
  static_assert(!__is_constructible(C, int));  // Previously failed.  Now okay.


4/6/23   [EDGcpfe/26201]
Microsoft-mode regression in handling of user-defined conversions

The changes for EDGcpfe/25746 (not yet in a release but distributed as a patch)
introduced a regression in some Microsoft modes when the initialization of an
aggregate member requires a user-defined conversion.  For example:

  struct V { V(); };
  struct X { V elem[1]; };
  struct S { operator V() const; };
  S g();
  X f() {
    return X{g()};  // Previously failed in Microsoft C++17 mode.
  }                 // Now okay.


4/6/23   [EDGcpfe/26191]
Clang C++ compatibility: Out-of-order designators

C++20 permits designated initializers but requires any designators to appear
in the same order as the declaration order of the members they designate.
Clang does not impose this constraint and the front end previously emulated
that by silently accepting code that contains out-of-order designators.  Now,
a warning is issued.  For example:

  struct S { int i, j, k; } s = { .j = 1, .i = 2 };
    // Ordinarily an error in C++20 mode.  Now a warning in Clang C++20 mode.


4/5/23   [EDGcpfe/21469,EDGcpfe/24285,EDGcpfe/26180]
Variables of a class type with a defaulted default constructor

Consider, in strict C++11 mode:

  struct S {
    int x = 0;
    int y = 0;
  };
  S const s;  // Previously a spurious error.  Now okay.

Previously, this elicited an error because S has no user-provided constructor
(or a warning in nonstrict modes).  However, the language allows such cases
because all the data members of S have a default initializer.  The front end
now correctly inhibits the diagnostic in such situations.  This implements the
resolution of Core issue 2366.


4/5/23   [EDGcpfe/25306,EDGcpfe/25869]
Spurious substitution failures when forming implicit deduction guides

Consider, in C++17 mode:

  template<typename ... T>
  struct B {
    static_assert(sizeof ... (T) != 0, "Unexpected");
    static constexpr int v = 0;
  };
  template<typename ... T>
  struct C {
    template<int = B<T ...>::v, typename = C>
    C(T ...);
  };
  C c{ 1, 2 };  // Previously a deduction failure.  Now okay.

When forming an implicit deduction guide for the user-declared constructor of
C, the front end previously instantiated B<T>, causing the static_assert to
fail.  Additionally, the use of the current instantiation in the second
template default argument caused substitution to fail.  Both issues are now
fixed.


4/5/23   [EDGcpfe/26218]
C++-generating back end: ellipsis-only functions in C mode

In configurations in which ALLOW_ELLIPSIS_ONLY_PARAM_IN_GENERATED_C is set
to FALSE when generating code for a C translation unit, the C++-generating
back end previously omitted the ellipsis in the declaration of a function
whose parameter list contains only an ellipsis.  Although needed for the
C-generating back end, this transformation was incorrect for the
C++-generating back end, where the output is intended to match the input as
nearly as possible.  This is now fixed.  For example, with --c23:

  void f(...);   // Now correctly output with the ellipsis


4/4/23   [EDGcpfe/24743,EDGcpfe/25586,EDGcpfe/26172]
Spurious error in C++20 mode on initialization of aggregate

Consider, in C++20 mode:

  struct D { int x, y, z; };  // Aggregate.
  struct S  { operator D() const; };
  void g(S p) {
    D d(p);  // Previously an error.  Now okay.
  }

Although C++20 allows parenthesized aggregate initialization, "D d(p);" is not
such an initialization; instead, it is a direct initialization via the user-
defined conversion from S to D.  Previously, however, the front end failed to
consider that possibility and instead issued a spurious error when attempting
a match according to the aggregate initialization rules (i.e., matching p to
member x of D).  That is now fixed.


4/4/23   [EDGcpfe/23475,EDGcpfe/25708]
Clang C compatibility: Promotion and overload resolution

In Clang C mode, the "overloadable" attribute enables overloading function
names.  However, the front end previously did not distinguish integral
promotion from other implicit integral conversions in C mode, thus rendering
ambiguous certain cases that Clang accepts in its C mode.  For example:

  void __attribute((overloadable)) g(int);
  void __attribute((overloadable)) g(unsigned);
  void f(char c) {
    g(c);  // Previously ambiguous.  Now okay.
  }

That is now fixed.


4/4/23   [EDGcpfe/25637]
Abort in mangling after Microsoft-mode "nonreal instantiation"

Consider:

  template<typename, typename> struct E {};
  template<template<typename...> class TT, typename... Ts> struct X {
    using Type = TT<Ts...>;
    operator Type() & { return Type{}; }
  };
  template<typename T1, typename T2> struct S: X<E, T1, T2> {};

This example previously caused an error type entry to silently (i.e., without
associated diagnostic) be inserted in the IL tree for the "nonreal
instantiation" performed in Microsoft mode for X<E, T1, T2>.  In some
configurations, that error type entry reached the mangling routines and
triggered an internal error.  That is now fixed (by not emitting an error
entry if there is no actual error).


4/4/23   [EDGcpfe/26209]
Clang compatibility: Suppress __GXX_RTTI predefined macro

The Clang compiler suppresses a definition of the __GXX_RTTI macro when
-fms-compatibility is specified and now the front end also suppresses that
definition in Clang emulation mode when --ms_compatibility is specified.


4/3/23   [EDGcpfe/26210]
Address of consteval functions during concept evaluation

Consider:

  consteval void g() {}
  consteval bool f() {
    decltype(auto) pg = &g;
    return true;
  }
  template<typename T> concept C = f();
  static_assert(C<void>);  // Previously an error.  Now okay.

Previously, this elicited a spurious error in the processing of C<void> with a
message indicating that "&g" cannot be interpreted.  That is now fixed.


4/3/23   [EDGcpfe/26206]
Abort on abbreviated member template with default argument

Consider (in C++20 mode):

  struct S {
    void f(int = 0, auto ...) {}
  };

Previously, this aborted with an internal error in add_to_routine_fixup_list.
That is now fixed.


4/2/23   [EDGcpfe/18475,EDGcpfe/24365,EDGcpfe/24662,EDGcpfe/26073,
          EDGcpfe/26204]
GNU and Clang compatibility: __fp16 type

The __fp16 type has now been added in relevant GNU and Clang emulation modes.
The layout of the __fp16 type is the same as _Float16 (though it is mangled
differently).  The __edg_fp16__ type (see the Changes entry for EDGcpfe/25179)
has now been removed and builtin signatures that previously used the
__edg_fp16__ type have been updated to use the __fp16 type.


3/31/23  [EDGcpfe/25764]
Parsing error on CTAD cast in template argument list

Consider (in C++17 mode or later):

  template<typename T> struct S {
    constexpr S(T) {}
    constexpr int f() const { return 1; }
  };
  template<int I> int g();
  int i = g<S{""}.f()>();

Previously, the front end issued an error on the opening brace of S{""} --
which is a cast relying on class template argument deduction (CTAD) --
expecting a closing angle bracket instead.  That is now fixed.


3/30/23  [EDGcpfe/26195]
Reference members in unions

Unions cannot contain reference members in C++, but the front end previously
only diagnosed violations of that rule in its strict mode.  Now, they are
diagnosed with a discretionary error in all C++ modes except Cfront modes and
early Microsoft C++ modes.


3/30/23  [EDGcpfe/26199]
Invalid clang version command-line option

Specifying a too-large clang version number on the command line previously
resulted in a failed assertion in expand_version_string.  It is now
reported as a command-line error.


3/29/23  [EDGcpfe/25676]
C++-generating back end: inaccessible member constants in template arguments

When the first reference to a template instance has a template argument
that uses a member constant that is not public, the code put out by the
C++-generating back end for subsequent references to that instance used
that same member constant, even in contexts in which the member is
inaccessible.  This is now fixed.  For example, with --c++11:

  template<typename> struct A { };
  class B {
    static constexpr int x = 10;   // private member constant
    A<int[x]> ba;                  // instantiates A<int[10]>
  };
  struct C {
    static constexpr int y = 10;
    A<int[y]> ca;   // Previously generated as A<int[B::x]>, now A<int[10]>
  };


3/29/23  [EDGcpfe/25089,EDGcpfe/25779]
GNU compatibility: Core issue 1601

Consider:

  enum E: char { e };
  constexpr int f(int) { return 0; }
  constexpr int f(char) { return 1; }
  static_assert(f(e) == 1, "");

The changes to support Core issue 1601 (see the entry for EDGcpfe/18779)
excluded GNU C++ mode since, at the time, GCC did not yet implement the
resolution for that core issue, which in turn caused it to fail the
static_assert in the example above.  GCC 10.x, however, corrected that and
the front end now emulates that behavior in GNU C++14 modes with
gnu_version >= 100000.


3/29/23  [EDGcpfe/25992]
Explicit static data member specialization that introduces constexpr

Consider:

  template<typename T> struct V {
    static const V<T> zero;
    constexpr V(): x() {}
    constexpr V(const V&) = default;
    T x;
  };
  template<> constexpr V<int> V<int>::zero = {};
  constexpr V<int> vi = V<int>::zero;  // Previously an error.  Now okay.

Previously, the front end failed to record the constexpr-ness of V<int>::zero,
which in turn triggered an error in the definition of vi.  That is now fixed.


3/29/23  [EDGcpfe/26118,EDGcpfe/26122]
Spurious lifetime error on some self-referencing constant-evaluation results

The changes for EDGcpfe/18466 etc. did not cover some more complex variants of
the example in the corresponding entry.  An additional tweak now covers those
new variants as well.


3/27/23  [EDGcpfe/18058,EDGcpfe/22588,EDGcpfe/25791,EDGcpfe/26107]
Constant evaluation of integer conversions

In some cases, the front end did not correctly evaluate certain integer-to-
integer conversions.  For example:

  template<typename T> static constexpr int to_int(T data) {
    return static_cast<int>(data);
  }
  static_assert(to_int<long long>(4294967254LL) == -42);
      // Previously failed.  Now okay.

That problem (due to incorrect sign-extension) is now fixed.


3/27/23  [EDGcpfe/23786,EDGcpfe/25812,EDGcpfe/26137]
Abort in pop_object_lifetime_full on tuple-based structured binding

When a structured binding relies on finding the get<N> accessor through
argument-dependent lookup and the result of the accessor requires nontrivial
destruction, the front end previously aborted in pop_object_lifetime_full.
That is now fixed.


3/27/23  [EDGcpfe/26183]
C23: value of __STDC_VERSION__

In anticipation of the adoption of the next version of the ISO C Standard,
the front end now defines the macro __STDC_VERSION__ to have the value
202311L in C23 mode.  For example, with --strict --c23:

  int i;
  static_assert(__STDC_VERSION__ == 202311L, "Bad version number.");


3/27/23  [EDGcpfe/25609,EDGcpfe/26117]
Incorrect expansion of function parameter pack in trailing requires clause

Function parameter packs were not expanded correctly in trailing requires
clauses, resulting in spurious substitution failures during constraint
checking.  For example, with --c++20:

  int g(int);
  template<typename ... T> int f(T ... t) requires requires { g(t ...); };
  int i = f(1);  // Previously a spurious error.  Now okay.


3/27/23  [EDGcpfe/21407]
Incorrect expansion of function parameter pack in trailing return type

A function parameter pack was not always expanded correctly when explicit
template arguments were provided for the function, resulting in spurious
substitution failures.  For example, with --c++11:

  struct C {
    static int g();
  };
  template<typename T, typename ... U>
  auto f(T t, U ... u) -> decltype(C::g(u ...));
  int i = f<int>(1);  // Previously a spurious error.  Now okay.


3/24/23  [EDGcpfe/26110]
Constant-evaluation of subscripting into multidimensional array

Consider:

  const int x[4][5] = {0};
  constexpr int const *p = &x[2][3];  // Previously an error.  Now okay.

Previously, this elicited a spurious error claiming the x[2][3] subscript is
out of bounds.  That is now fixed.


3/24/23  [EDGcpfe/26176,EDGcpfe/26179]
Error handling of __has_c_attribute and __has_cpp_attribute

The front end previously failed to diagnose ill-formed uses of
__has_cpp_attribute and __has_c_attribute (in C++ and C modes,
respectively) when the name is not immediately followed by a left
parenthesis.  Also, diagnostics for ill-formed uses of __has_c_attribute
previously referred to __has_cpp_attribute.  finally, diagnostics for
ill-formed uses of these operators previously gave an incomplete list of
contexts in which they may appear.  These issues are now fixed.  For
example, with --c23 --strict:

  int __has_c_attribute;   // Now elicits a correct diagnostic


3/23/23  [EDGcpfe/26177]
C23 compatibility: Accept attributes with leading and trailing underscores

The C23 standard allows attributes to have optional leading and trailing
sets of underscores, e.g., "__attr__" is treated as "attr".  For example,
with --c23:

  [[__deprecated__]] int i;   // Now accepted.


3/23/23  [EDGcpfe/25938,EDGcpfe/26054]
C23: Implement typeof and typeof_unqual operators

As described in WG14 papers N2927 and N2930, typeof can now be used to declare
a type from either an existing type or an expression.  Similarly, typeof_unqual
can be used to declare a type from either an existing type or an expression
with type qualifiers removed.  For example:

  const int        a;
  typeof(a)        b;  // equivalent to "const int b;"
  typeof_unqual(a) c;  // equivalent to "int       c;"

The --[no_]c23_typeof command-line option explicitly enables or disables this
feature, regardless of the C version and dialect being emulated.


3/23/23  [EDGcpfe/26175]
Lambdas using local references to global objects

Consider:

  int v;
  int g() {
    int &r = v;
    return []{ return r; }();  // Previously an error.  Now accepted.
  }

Previously, this triggered an error because the local variable r is used
without being captured in the lambda expression.  Now, however, it is accepted
because the reference binding resolves to a constant address.


3/23/23  [EDGcpfe/24775,EDGcpfe/25887]
C23, C++23 compatibility: Allow duplicate attributes

Both C23 and C++23 now allow duplicate attributes to be specified (see
WG14 paper N2557 and WG21 paper P2156R1).  The latter paper was approved
as a defect report so this change applies to all C++ versions.
For example, with --c++14:

  [[deprecated, deprecated]] int i;   // Now accepted (previously an error).


3/22/23  [EDGcpfe/26053]
Microsoft compatibility: Add --ms_c23 command-line option

The front end now accepts the --ms_c23 command-line option to enable the
features associated with the upcoming MSVC /std:c23 command-line option.


3/22/23  [EDGcpfe/26169]
Clang compatibility: Clang 16.0.0 builtins

The builtin_defs.h file has been updated to reflect the availability of
these new builtins when clang_version >= 160000.


3/21/23  [EDGcpfe/26162]
Ctl-Z appearing in a command-line or predefined macro definition

In configurations with READ_SOURCE_IN_BINARY_MODE_FOR_MSDOS set to TRUE,
the changes for EDGcpfe/24920 (in version 6.4) introduced a regression in
Microsoft mode when a ctl-Z (0x1a) appears at the start of a token in a
macro definition appearing on the command line or in the predefined macros
file, resulting in dereferencing a NULL pointer.  This is now fixed.


3/21/23  [EDGcpfe/26171,EDGcpfe/26200]
GNU and Clang compatibility: Add __bf16 type

Newer Clang and GNU versions (11.0.0 and 10.0.0 respectively) accept the 16-bit
floating-point __bf16 type in C and C++ modes and now the front end accepts it
as well those emulation modes.  The ARM variants of these compilers were the
first to implement the new type with support following later in the x86
versions (but the type is enabled by the front end regardless of target).  The
format is the same as the std::bfloat16_t type that was added as an extended
floating-point type in C++23 mode (see the Changes entry for
EDGcpfe/25100,EDGcpfe/25170,EDGcpfe/25515).


3/21/23  [EDGcpfe/26170]
Digit separators in #elif expressions

In modes in which digit separators are accepted, the front end previously
did not recognize them in numeric literals appearing in the expression of a
#elif directive.  This is now fixed.  For example, with --c23:

  #if 0
  #elif 0b0'111 == 7   // Previously a spurious error
  int i;
  #endif


3/21/23  [EDGcpfe/26154]
Member alignments of extended floating point types

When support for the C++23 extended floating point types was added to the
front end (see the entry for EDGcpfe/25100,EDGcpfe/25170,EDGcpfe/25515),
the values for their alignments as members of classes were not set.  The
result of this omission could be incorrect sizes and alignments of classes
and class members, as well as aborts in some configurations.  This is now
fixed.  For example, with --c++23:

  typedef decltype(0.0f16) f16_t;
  template<typename T> struct S {
    T t;
  };
  S<f16_t> s16;


3/21/23  [EDGcpfe/26097]
Microsoft compatibility: "typeid" and "__uuidof" address constants as template
arguments

Previously, the front end only accepted a "typeid" address constant as a
template argument for a reference template parameter in pre-C++17 Microsoft
modes.  Now, a "typeid" address constant is accepted in all Microsoft modes,
and a "__uuidof" address constant is accepted in Microsoft mode as well as in
Clang mode with Microsoft extensions enabled.  For example, with --ms_c++17:

  #include <typeinfo>
  struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) C;
  template<const _GUID &> struct A;
  A<__uuidof(C)> *a;  // Previously an error.  Now okay.
  template<const std::type_info &> struct B;
  B<typeid(int)> *b;  // Previously an error.  Now okay.


3/21/23  [EDGcpfe/26081]
Abort in compare_expressions for "function call" to a variable

A "function call" expression to a variable of class type with an overloaded
function call operator appearing in a dependent decltype could trigger an abort
in compare_expressions.  Additionally, template arguments of variable template
specializations were not compared in these cases, which could result in
spurious redefinition errors.  For example, with --c++14:

  struct C {
    int operator () (int = 0);
  };
  template<typename T> C c;
  template<typename T> using F = T;
  template<typename T, F<decltype(c<T *>(1))>>
  void f(T) { }
  template<typename T, F<decltype(c<T &>(1))>>
  void f(T) { }  // Previously a spurious redefinition error.  Now okay.
  template<typename T, F<decltype(c<T>())>> void g(T) { }
  template<typename T, F<decltype(c<T>())>> void h(T) { }


3/21/23  [EDGcpfe/19338,EDGcpfe/22788,EDGcpfe/25109]
Spurious error for functional notation cast with empty pack expansion

Previously, the front end issued a spurious error for a functional notation
cast to an instantiated non-class type from an expression list consisting of a
single expression and an additional empty pack expansion.  For example, with
--c++11:

  template<typename T, typename ... U>
  T f(T t, U ... u) {
    return T(t, u ...);  // Previously a spurious error.  Now okay.
  }
  template int f(int);


3/20/23  [EDGcpfe/26167]
Element constant of parenthesized aggregate initialization incorrectly marked
as being enclosed in braces

Consider, in C++20 mode:

  struct S {
      S() = default;
      S(const S& other);
  } s;
  struct X { S m; } x(s);

The last line declares variable x with a parenthesized aggregate initializer
whose element is copy constructed from a constant-folded version of s.
However, that constant was previously erroneously marked as being explicitly
enclosed by braces.  That is now fixed.


3/20/23  [EDGcpfe/23294,EDGcpfe/26114]
Constant-evaluation of relational operators applied to null pointer values

Consider (in C++14 or later mode):

  constexpr bool test(int const *const &x, int const *const &y) {
    return x<=y;
  }
  constexpr const int* ptr = nullptr;
  static_assert(test(ptr, ptr));  // Previously an error.  Now okay.

Previously, this example triggered an error claiming "test(ptr, ptr)" does not
have a constant value.  That is now fixed.


3/20/23  [EDGcpfe/26134]
Regression in handling of user-defined conversions

The changes for EDGcpfe/25746 (not yet in a release but distributed as a patch)
introduced a regression in C++14 and earlier modes in some cases like the
following (which can occur with the old std::auto_ptr template):

  template<typename T> struct R {
    explicit R(T*);
  };
  template<typename T> struct S {
    S();
    S(S&);
    S(R<T>);
    template<typename U> operator R<U>();
  };
  void f() {
    throw S<int>();  // Previously failed claiming S<int> has no suitable
 }                   // copy constructor (in C++14 and earlier modes).
                     // Now okay.

That is now fixed.


3/17/23  [EDGcpfe/23174,EDGcpfe/26000,EDGcpfe/26001,EDGcpfe/26157]
Clang-mode vector conversions

In Clang mode, the front end now accepts implicit conversions between any two
vector types of equal size (in bytes).  In particular, there is no requirement
that the underlying element types of the source and destination be related.


3/17/23  [EDGcpfe/26136]
Abort on default argument of inherited constructor

In some cases where a class template inherited a constructor with a
non-trivially destructible temporary in one of its default arguments, the front
end would abort in i_copy_dynamic_init if that class template was instantiated
from within a template argument list.  For example, with --c++17:

  struct A {
    ~A();
  };
  struct B {
    B(A = A());
  };
  template<typename T>
  struct C : B {
    using B::B;
  };
  template<unsigned> struct X {};
  X<sizeof(C<int>)> x;


3/16/23  [EDGcpfe/22330]
GNU C++14 compatibility: asm declarations in constexpr functions

In C++20, asm declarations are permitted in constexpr function.  GCC 10.x and
later also accepts them -- with a warning -- in C++14 (and C++17) modes.  The
front end now emulates that in the corresponding GNU C++ modes when
gnu_version >= 100000.


3/16/23  [EDGcpfe/21202]
GNU C++11 mode and __builtin_is_constant_evaluated()

Calls to __builtin_is_constant_evaluated() in GNU C++11 mode were previously
not successfully folded, which resulted in spurious errors.  That is now fixed.


3/15/23  [EDGcpfe/26130]
C++-generating back end: unbounded recursion with inaccessible typedefs

The C++-generating back end failed to consider friend relationships when
checking the accessibility of names used in template arguments.  In some
complex situations, this omission could result in unbounded recursion when
the back end looked for an accessible substitute for a template argument
for a template that was originally instantiated with an inaccessible
argument.  This is now fixed.


3/15/23  [EDGcpfe/26077]
Regression in field initializers using source location builtins

The changes for EDGcpfe/22336 in version 6.4 (see entry of 10/20/22) introduced
a regression in cases where the source location builtins are used as part of
the constructor, for example:

  struct X {
    X(unsigned l = __builtin_LINE()) {}
  };

if this type is used as a default member initializer using any form of brace
initialization:

  struct Y {
    Y() {}
    X x = {};
  };
  // OR
  struct Y {
    Y() {}
    X x{};
  };

Previously, calls to source location builtins inside of such a case were not
properly transformed for the individual constructors.  In configurations in
which lowering is done, this could result in a request for an unresolvable
constant, resulting in an abort in lower_expr_full.  This is now fixed.


3/15/23  [EDGcpfe/26148]
Uninitialized constant could result in undefined behavior

The changes for EDGcpfe/21042 (in version 6.4) introduced an uninitialized
constant that could cause undefined behavior when using the
__builtin_choose_expr builtin.  Now fixed.  For example, with --gcc:

  const int x = __builtin_choose_expr(1, 2, (void)0);


3/15/23  [EDGcpfe/26147]
Memory leak

The changes for EDGcpfe/23703 (in version 6.3) allocated a local constant
without releasing it in some error conditions.  Now fixed.


3/14/23  [EDGcpfe/24449,EDGcpfe/25680]
Clang compatibility: support _Atomic class types

Previously, support for _Atomic class types was disabled in Clang mode as Clang
may add additional padding and stricter alignment requirements to these types.
The front end now emulates that behavior.  A new configuration macro,
TARG_SIZEOF_LARGEST_ATOMIC, has been added to control what types are affected.
For example, with --c++11 --clang:

  struct C {
    char c1, c2, c3;
  };
  using AC = _Atomic C;  // Previously not supported.  Now okay.
  static_assert(sizeof(AC) == 4 && alignof(AC) == 4, "Unexpected");


3/14/23  [EDGcpfe/26133]
Add Initial SARIF Support

The front end now has initial support for SARIF (Static Analysis Results
Interchange Format) output.  The output mode can be changed for a single run
via the --output_mode flag ("text" for traditional output or "sarif" for SARIF
based output). The default output mode of the front end can be changed as well
via the DEFAULT_OUTPUT_MODE configuration macro (with om_text and om_sarif
respectively).

More information about SARIF can be found here: https://www.sarif.info/


3/6/23   [EDGcpfe/26108]
Microsoft compatibility: commas in variadic macro arguments

The changes for EDGcpfe/25674 (not in a release but distributed to some
customers as a patch) introduced a regression in some cases involving
commas appearing in variadic macro arguments when emulating the traditional
Microsoft preprocessor.  This regression manifested when processing the
Boost concept_check.hpp header.  This is now fixed.


3/6/23   [EDGcpfe/26041]
Lifetime extension through synthesized variables

Range-based for-loop constructs cause the front end to synthesize implicit
(i.e., compiler-generated) reference variables.  These variables may end up
being bound to temporaries in a way that extends the lifetime of those
temporaries.  Previously, the synthesized variable was not marked as extending
the lifetime of a temporary, which caused the constant-evaluation interpreter
to sometimes fail for spurious reasons.  That is now fixed.


3/6/23   [EDGcpfe/25426]
Incorrect move from lvalue for class with trivial copy constructor

For a class with a trivial copy constructor, a functional notation cast with a
braced init list of an lvalue of the class type would incorrectly call the move
constructor on that lvalue.  For example, with --c++14:

  struct C {
    constexpr C() = default;
    constexpr C(const C &) = default;
    constexpr C(C &&c) { c.moved = true; }
    bool moved = false;
  };
  constexpr bool f(C c) {
    C{c};                              // Previously called C::C(C&&).
    return !c.moved;
  }
  static_assert(f({}), "Unexpected");  // Previously failed.  Now okay.


3/3/23   [EDGcpfe/18466,EDGcpfe/25763,EDGcpfe/25765,EDGcpfe/25766]
Spurious lifetime error on some self-referencing constant-evaluation results

Consider:

  struct S {
    void *p;
    constexpr S(): p(this) {}
    constexpr S(S const &orig) : p(orig.p) {}
  };
  constexpr S g() { return S(); }
  constexpr S r = g();

Previously, this resulted in a spurious error about attempting to access
expired storage during constant evaluation.  That is now fixed.


3/1/23   [EDGcpfe/26105]
Microsoft compatibility: using enum declarations enabled

C++20 using enum declarations (see the Changes entry for EDGcpfe/21586) are
now enabled in Microsoft emulation mode when microsoft_version >= 1924 and
--ms_c++20 or --ms_c++latest is specified.


2/28/23  [EDGcpfe/26103]
Spurious diagnostic on false requires-expression

Consider, in C++20 mode:

  template<typename T> constexpr int f() noexcept { return 0; }
  template<typename T> requires (f<T>() != 0) void g(T);
  template<typename T> concept C = requires(T &t) { g(t); };
  template<C> struct P {};
  template<typename T> struct X {};
  template<C T> X(T) -> X<int>;
  template<typename T> auto h() {
    return requires { X(P<T>()); };  // Previously elicited an error.
  }                                  // Now okay.
  auto r = h<int>();

Previously, an error was issued because the deduction for X(P<T>()) fails.
However, such a failure in a requires-expression should only cause that
expression to yield a false value and not trigger a diagnostic.  That is now
fixed.


2/27/23  [EDGcpfe/25762]
Substitution of pack expansion

  template<typename T, typename... Ts> void g(T, Ts...);
  template<typename> struct X {
    template<typename U, typename... Us>
      int f(U u, Us... us) requires requires {
        g(u, us...);
      };
  };
  auto r = X<int>().f(1);

Previously, this failed to resolve the call X<int>().f(1) because somewhere
during the substitution of the requires-expression the variadic nature of the
argument us was lost.  That is now fixed (and the example is now accepted).


2/27/23  [EDGcpfe/17557,EDGcpfe/26089]
Vector operations with cv-qualifier differences

A change has been made to ignore cv-qualifier differences in the types of
operands of a vector operation.  For example:

  void f(      int __attribute__((vector_size(16))) a,
         const int __attribute__((vector_size(16))) b) {
    (void)(a + b);
  }


2/27/23  [EDGcpfe/15596,EDGcpfe/24928]
Exception specification of inherited constructor templates

Previously, the front end did not generate exception specifications for
inherited constructor template specializations.  For example, with --c++11:

  struct B {
    template<typename T> B(T) noexcept;
  };
  struct D : B {
    using B::B;
  };
  static_assert(noexcept(D(1)), "Unexpected");  // Previously failed.
                                                // Now okay.


2/24/23  [EDGcpfe/26095]
C++-generating back end: member typedef in conversion operator name

In cases where a conversion operator is declared using a member typedef
as the target type, the C++-generating back end used that member typedef
name without qualification in a function-style call to the conversion
operator, relying on the fact that the object expression in a member
access expression implicitly establishes the lookup scope for the member
name.  However, clang and MSVC do not look in the class of the object
expression when looking up the type in a conversion operator name and thus
reported spurious errors on the generated code.  This is now fixed; when
generating code for clang or for the Microsoft dialect, the member typedef
in such cases is put out using a qualified name.  For example, with
--clang --c++11:

  struct S {
    typedef int *IP;
    operator IP();
  };
  void f() {
    typedef int *P;
    S s;
    int *p = s.operator P();   // Previously generated as "operator IP",
                               // now as "operator S::IP" in some modes
  }



2/24/23  [EDGcpfe/26061]
Spurious unsatisfied constraint errors for friend function templates

A friend function template declared in a class template has the nesting depth
of its template parameters updated when the enclosing class template is
instantiated.  However, a requires clause in the template declaration was
previously not updated to use the new template parameter nesting depth,
resulting in spurious errors due to that constraint not being satisfied.  For
example, with --c++20:

  template<unsigned N> concept C = N > 1;
  template<typename> struct D
  {
    template<unsigned N> requires C<N>
    friend int f(D, const char (&)[N]);
  };
  int i = f(D<int>{}, "Hello");  // Previously a "template constraint not
                                 // satisfied" error.  Now okay.


2/23/23  [EDGcpfe/26008,EDGcpfe/26045]
Regression in expr_range values for some call-expressions

The changes for EDGcpfe/22336 in version 6.4 (see entry of 10/20/22) introduced
a regression where the IL is missing the expr_range source position information
for function call expressions (i.e., IL enk_operation expressions with eok_call
operation variant) wrapped in enk_temp_init expressions; this is now fixed.


2/22/23  [EDGcpfe/25881,EDGcpfe/26087]
Regression in non-consteval functions using source location builtins

The changes for EDGcpfe/22336 in version 6.4 (see entry of 10/20/22) introduced
a regression in cases where the source location builtins are directly used as
default arguments for functions that aren't consteval, for example:

  unsigned get_line(unsigned l = __builtin_LINE()) {
    return l;
  }

if this function is used as a default member initializer:

  struct foo {
    unsigned l = get_line();
    foo() = default;
  };

Previously, calls to source location builtins inside of such a case were not
folded to constants and instead appeared directly in the IL.  In configurations
in which lowering is done, this could result in an abort in lower_expr_full.
This is now fixed.


2/22/23  [EDGcpfe/25963]
Clang builtin function signatures

The tool that builds the builtin_defs.h header file had a couple of bugs that
had resulted in incorrect function signatures for some builtin functions
(mostly those with vector types).  Now fixed.


2/22/23  [EDGcpfe/25949,EDGcpfe/26013]
Regression in template template argument matching

The changes for EDGcpfe/24912 in version 6.4 (see entry of 3/23/22) introduced
a regression in some cases involving template template arguments.  For example:

  template<typename... Ts> struct X {};
  template<template <typename U, typename V> class> struct S {};
  S<X> sx;  // Previously an error claiming X is not a match for the
            // corresponding template template parameter.  Now okay.

That is now fixed.


2/21/23  [EDGcpfe/26085]
C11: Duplicate typedefs

C11 adopted the C++ rule that a typedef can be re-defined if it doesn't change
the underlying type.  Previously, the front end issued a warning (by default)
or error (in strict mode) for such cases.  That is now fixed.  For example:

  typedef int Int;
  typedef int Int;  // Previously triggered a diagnostic in C11 mode.
                    // Now accepted without any diagnostic.


2/20/23  [EDGcpfe/24368,EDGcpfe/26039]
Clang and Microsoft compatibility: Variables of nonliteral types

The changes for EDGcpfe/23852,EDGcpfe/24368 caused the front end to accept
certain nonliteral type variables in constexpr functions that are template
functions (see the entry of 10/5/22), at least in some Microsoft and Clang
modes.  It turns out that Clang and MSVC also permit this in friend functions
defined during class template instantiations.  For example:

  template<typename T> struct D { ~D() {} };
  template<typename T> struct S {
    friend constexpr int f(S<T> s) {
      D<T> d;      // Previously an error in non-C++23 modes.  Now okay
      return 42;   // in many Clang and Microsoft non-C++23 modes.
    }
  };
  int r = f(S<int>{});

The front end now emulates this behavior (in Microsoft mode, the emulation is
approximate in that MSVC disallows some cases accepted by Clang, and the front
end's behavior is more similar to Clang's).


2/20/23  [EDGcpfe/25427]
Call in constraint expression treated as nondependent

If a constraint contained a dependent function call, the call was correctly
marked as dependent during the prototype instantiation but could later be
marked as non-dependent when rescanning the constraint during substitution.
This could cause spurious errors due to unsatisfied template constraints.  For
example, with --c++20:

  template<typename T> T f(T);
  template<typename T> using A = decltype(f(T{}));
  template<typename> concept C = true;
  template<typename T> requires C<A<T>>
  struct B {
    static void g() requires C<A<T>>;
  };
  auto l = [] () {
    B<int> b1;
    B<int *> b2;  // Previously a spurious "template constraint not satisfied"
  };              // error.  Now okay.


2/19/23  [EDGcpfe/18844,EDGcpfe/25659,EDGcpfe/26079]
Integral constant expression conversions

Consider:

  struct X {
    constexpr operator long() const { return 12; }
    explicit constexpr operator int() const { return 12; }
  };
  constexpr X x{};
  struct S {
    int i: x;               // Previously ambiguous.  Now okay.
  };
  struct alignas(x) S { };  // Previously ambiguous.  Now okay.
  enum E { e = x };         // Previously ambiguous.  Now okay.


The standard specifies that non-explicit user-defined conversions to integer
types are considered for bit field lengths, alignas operands, and enumerator
constant values.  The front end previously also considered explicit conversion
functions, resulting in an ambiguity for the example above.  That is now fixed.
Furthermore, it appears that the Microsoft compiler does consider explicit
conversion functions for bit-field lengths, but it treats the bit-field length 
context as a conversion to the specific type "int", which also resolves the
ambiguity (and the front end now emulates that nonstandard behavior).


2/17/23  [EDGcpfe/23555]
C++23: "z" integer literal suffix

As described in WG21 paper P0030R8, the front end now accepts in C++23 mode
the integer literal suffix "z" or "Z", giving the literal the type
std::size_t (if the suffix also includes "u" or "U") or the signed integer
type corresponding to std::size_t (if the "u/U" suffix is omitted).  The
"z/Z" suffix is also accepted in GNU and clang C++ modes with gnu_version
>= 110000 or clang_version >= 130000, respectively.  For example, with
--c++23:

  static_assert(sizeof(1uz) == sizeof(sizeof(0)));


2/16/23  [EDGcpfe/26049]
Position information of parameters in Microsoft mode

The changes for EDGcpfe/15165, etc., could cause the position information
recorded in a function parameter to reflect the position of an earlier
declaration, while the name recorded in the a_param_type entry reflects that
of a later definition. For example:

  class S {
    __declspec(nothrow) int f(char *p);
  };
  int S::f(char *p_str) {  // Recorded name was "p_str", but the associated
    return 0;              // position was that of "p" above.
  }

That is now fixed.  In the example above, the primary parameter information
recorded for the function S::f is that of p_str (with the correct associated
position).


2/16/23  [EDGcpfe/26063]
Clang compatibility: Adjust __fp16 return types in clang builtins

Prior to the implementation of a 16-bit floating-point type, any clang builtin
whose return type was "__fp16" had been mapped to the "short" type.  Builtin
signatures have now been changed to use the "__edg_fp16__" type (which is a
typedef for _Float16).  The "__fp16" clang-specific type is not yet
implemented.


2/15/23  [EDGcpfe/26064]
max_exponent for _Float16 set incorrectly

The value of max_exponent for the _Float16 type (see the entry for
EDGcpfe/20094,EDGcpfe/20264,EDGcpfe/25494) was not initialized to the
correct value, i.e., 16.  This is now fixed.


2/15/23  [EDGcpfe/26050]
Abort on CTAD with constrained template parameter

When forming an implicit deduction guide for a class template declared with a
constrained template parameter, the type constraint was not correctly
substituted.  If the concept was declared with a variadic template parameter,
this would result in an abort in check_type_constraint.  For example, with
--c++20:

  template<typename T, typename ... U> concept C = true;
  template<C<int> T> struct D {
    D(T) { };
  };
  D d{1};  // Previously aborted.  Now deduced as D<int>.


2/14/23  [EDGcpfe/24647,EDGcpfe/25452]
Constant-evaluation involving empty base classes

Empty base classes are often trivially initialized (because they have no data
members or base classes to initialize), but if a constructor did not include
such an empty base class in its mem-initializer list, the constant-evaluation
of that constructor left corresponding subobjects uninitialized.  That in turn
could lead to spurious constant-evaluation failures or even aborts.
For example (in C++17 mode):

  template<typename U> struct V {
    constexpr bool f() {
      auto &d = static_cast<U&>(*this);
      return false;
    }
  };
  template<typename T> struct D: V<D<T>> {
    constexpr D(T t) {}
  };
  struct S {};
  template<typename T> constexpr bool g(T &&t) {
    D<S>{t}.f();
    return true;
  }
  static_assert(g(S{}));  // Previously failed.  Now okay.

Previously, the constant-evaluation of g(S{}) failed because the static_cast in
V<S>::f() did not consider *this (which is an empty base of D<S>) to be
initialized.  That is now fixed.


2/14/23  [EDGcpfe/26038]
Structured bindings referencing temporaries

When a reference variable is bound to a temporary, it extends the lifetime of
that temporary to the lifetime of the variable.  In the IL, that is indicated
by the flag extends_lifetime in the corresponding a_variable entry.  However,
this flag was previously not set in such situations if the variable represents
a structured binding.  (This could manifest as spurious constant-evaluation
errors in some cases.)  That is now fixed.


2/13/23  [EDGcpfe/25987]
Missing initialization in constant-evaluation interpreter

A low-level field in the memory management structures for the constant-
evaluation interpreter was not correctly initialized.  That is now fixed.


2/13/23  [EDGcpfe/24130,EDGcpfe/24244,EDGcpfe/24802,EDGcpfe/25124,
          EDGcpfe/26033,EDGcpfe/26034]
Constraint not checked on user-defined conversion

Consider (in C++20 mode):

  template<typename T> struct X {
    operator bool() requires false;
  };
  template<class R> concept C = requires(R r) { (bool) r; };
  static_assert(!C<X<int>>);  // Previously failed.  Now okay.

This example previously failed because the front end failed to check the
constraint on X<T>::operator bool().  That is now fixed.


2/13/23  [EDGcpfe/26031]
Abort on constant-evaluation of dynamic_cast of uninitialized object

Consider (in C++20 mode):

  struct V { virtual void f(); };
  struct A: V { };
  struct B: V { constexpr B(A*); };
  struct D: B, A { constexpr D(): B(this) {} };
  constexpr B::B(A* a) {
    (void)dynamic_cast<B*>(a);
  }
  constexpr D d;

The dynamic_cast operation in the B::B(A*) constructor is invalid when called
during the construction of d because the A subobject that is passed in is not
initialized.  The constant-evaluation interpreter failed to check that case,
resulting in an abort in do_constexpr_dynamic_cast.  That is now fixed.


2/13/23  [EDGcpfe/25901]
Core issue 2664: Deduction failure in CTAD for alias templates

The resolution of Core issue 2664 clarified that when forming deduction guides
for an alias template, a deduction failure for the return type of the deduction
guide is treated as deducing an empty set of template arguments.  For example,
with --c++20:

  template<typename T> struct C {
    template<typename U> C(U);
  };
  template<typename T> C(T) -> C<T *>;
  template<typename T> using A = C<T>;
  A a{1};  // Previously a deduction failure.  Now deduced as A<int *>.


2/7/23   [EDGcpfe/25890]
C23: Obsolescent keywords

As described in WG14 papers N2764 and N2934, the following keywords are now
considered obsolescent features: _Alignas, _Alignof, _Bool, _Static_assert,
_Thread_local, and _Noreturn.  The C23 standard recommends using the following
new keywords instead (respectively): alignas, alignof, bool, static_assert,
thread_local, and [[noreturn]].

Use of the obsoleted spellings now yields a warning in strict mode and a
remark in other C23 modes.  These diagnostics are suppressed in system header
files and are issued only once per translation unit.


2/7/23   [EDGcpfe/25874]
C23: Enable _Static_assert with no message

As described in WG14 paper N2265, the single argument version of _Static_assert
is now enabled in C23 mode.  The single argument version of _Static_assert is
also enabled in later clang modes (it was already enabled in later GNU modes --
see the Changes for EDGcpfe/24198).


2/6/23   [EDGcpfe/25872]
C23: Allow [[maybe_unused]] on labels

As described in WG14 paper N2662, the front end now accepts the maybe_unused
attribute on labels (and suppresses a warning about unused labels when
appropriate) in C23 mode.  Note that the C++ standard does not allow the
maybe_unused attribute to appertain to labels though most implementations
allow it.  An error is now given in strict C++ mode and silently accepted in
other C++ modes.  For example, with --c23:
  
  void f() {
    [[maybe_unused]]  // Previously an error or warning depending on the mode.
      label:          // Previously a warning about an unused label.
      return;
  }


2/3/23   [EDGcpfe/25809]
Abort on dependent substitution of constexpr if statement

A substitution of a constexpr if statement with dependent template arguments,
which can occur in an unevaluated context of an alias template, previously
resulted in an internal error in add_to_constexpr_if_cache_hash_table.  For
example, with --c++20:

  template<bool B>
  using A = decltype([] () {
    if constexpr (B) return 1;  // Previously an internal error.  Now okay.
    else return 2; } ());
  template<bool B> using AA = A<B>;


2/2/23   [EDGcpfe/26012]
C++-generating back end: conditional expressions in concepts

The C++-generating back end previously failed to enclose a conditional (?:)
expression in parentheses when it appears as the expression in a concept
definition, as required by the syntax of the construct.  This is how fixed.
For example, with --c++20:

template<typename T> concept foo = sizeof(T) == 4;
// Previously incorrectly generated without the parentheses:
template<typename T> concept DummyC = (foo<T> ? foo<char> : foo<float>);


2/1/23   [EDGcpfe/24782,EDGcpfe/25697,EDGcpfe/25898]
C++23/C23/GNU/clang compatibility: #elifdef/#elifndef preprocessor directives

As described in WG21 paper P2334R1 and WG14 paper N2645, the front end now
accepts the #elifdef and #elifndef preprocessor directives in C++23 and C23
modes, as well as in GNU C and C++ modes with gnu_version >= 120000 and
clang C and C++ modes with clang_version >= 130000.  For example, with
--c++23:

  #define B
  constexpr int i =
  #ifdef A
  5
  #elifndef B
  10
  #else
  15
  #endif
  ;   // Initializes i with 15
  static_assert(i == 15);


1/30/23  [EDGcpfe/25507]
C++23: #warning

As described in WG21 paper P2437R1, the #warning directive is now supported
in strict C++23 mode.  (It was already available in all non-strict modes.)
For example, with --strict --c++23:

  #warning This is a warning.  // Issues a warning and continues processing


1/30/23  [EDGcpfe/25770]
Deduction failure for non-type template parameter of dependent type

In cases involving nested instantiations, an explicitly specified non-type
template argument could be converted to the corresponding parameter type of the
outer instantiation, resulting in spurious deduction failures.  For example,
with --c++14 -tused:

  template<typename T, T, typename F>
  int g(F f) {
    return f(1);
  }
  int i = g<int, 0>([] (auto) {
    return g<long, 1>([] (auto) {  // Previously a spurious error.  Now okay.
      return 0; });
  });


1/30/23  [EDGcpfe/25576,EDGcpfe/25717]
GNU compatibility: Substitution failure for two-operand conditional operator

Previously, the first operand with a conversion to "bool" already applied was
used as the implicit second operand during substitution of a GNU two-operand
conditional operator.  This could cause spurious substitution failures due to
invalid conversions.  For example, with --c++11 --g++:

  enum E { E0, E1 };
  template<E e> struct C { };
  template<E e> C<e ?: E0> f();
  using type = decltype(f<E1>());  // Previously a spurious error.  Now okay.


1/26/23  [EDGcpfe/25998]
Missing inter-token spaces in preprocessor output

In some obscure cases involving macro processing, the preprocessor output
(e.g., via the -E command-line option) could contain tokens that must be
separated by a space but were instead incorrectly concatenated.  This is
now fixed.  For example, with -E:

  #define M1(x)         L##x
  #define M3  M1("B")
  #define M4(a)  a
  auto x = M4(M1("A")M3);   // Previously produced L"A"L"B", now L"A" L"B"


1/26/23  [EDGcpfe/17059,EDGcpfe/18006,EDGcpfe/19579,EDGcpfe/20728,
          EDGcpfe/21691,EDGcpfe/24011,EDGcpfe/25159,EDGcpfe/25240,
          EDGcpfe/25577]
Substitution failures for nested alias templates

Previously, substitution failures for nested alias templates were not
considered to be in the immediate context and could therefore result in
spurious errors.  For example, with --c++11:

  template<class T> struct B {
    template<class U>
    using C = typename U::type;  // Previously a spurious error.
  };
  template<class T, class U> typename B<T>::template C<U> f(T, U, int);
  template<class T, class U> int f(T, U, long);
  int i = f(1, 2, 3);


1/25/23  [EDGcpfe/25672]
Microsoft compatibility: incorrect concatenation of macro arguments

When emulating the traditional Microsoft preprocessor, the front end
previously ignored white space occurring in nested macro expansions within
macro arguments and consequently concatenated tokens that MSVC keeps
separate.  For instance, in the following example (with --microsoft
--c++11) the space appearing between the macro invocations in the expansion
of M3 should have prevented the concatenation of the expansions of M1("A")
and M1("B") in the expansion of M4 but failed to do so:

  #define M1(x)         L##x
  #define M2(x)
  #define M3  M2("X") M1("B")
  #define M4(a)  a
  auto x = M4(M1("A")M3);  // Previously expanded to L"A"L"B", with the second
                           // L being an invalid user-defined literal suffix

This is now fixed.


1/24/23  [EDGcpfe/25981]
Constant-evaluation abort on use of dependent class type

In somewhat complex (usually invalid) situations, the front end could abort
with an invalid memory access (e.g., a null pointer indirection) because the
constant-evaluation interpreter attempted to evaluate an object whose class
type (possibly a closure class) is dependent.  That is now fixed.


1/24/23  [EDGcpfe/17783,EDGcpfe/21995,EDGcpfe/25971]
Incorrect pack expansion for nested template argument lists

In some cases involving nested template argument lists, parameter packs would
repeatedly expand to their first element, resulting in spurious errors during
overload resolution.  For example, with --c++11:

  template<typename T1, typename T2> T2 f(T1, T2);
  template<typename T> T g();
  template<typename T> struct D { using type = T; };
  template<typename... A> struct C {
    template<typename T> auto h() -> decltype(f(g<typename D<A>::type>()...));
  };
  long *l = C<int, long *>().h<int>();  // Previously a spurious error.
                                        // Now okay.


1/23/23  [EDGcpfe/25011]
Pack expansion deduction context leak

Prior to this change, deduce_one_parameter when short circuiting deduction of a
parameter pack would leak pack deduction contexts into subsequent scopes.  This
resulted in assertion failures in end_potential_pack_expansion_context,
update_template_param_symbol, and abandon_potential_pack_expansion_context.
Additionally, in some cases this leak caused subsequent erroneous diagnostics
which referenced incorrect source locations.


1/23/23  [EDGcpfe/25712]
C++-generating back end: brace-enclosed capture-init

When the initializer for a lambda capture-init is enclosed in braces, the
C++-generating back end sometimes incorrectly doubled the braces.  This is
now fixed.  For example, with --c++14:

  struct S {
    S();
    S(const S&);
  };
  void f() {
    S s;
    [s{s}] {};   // Previously generated as [s{{s}}]
  }


1/23/23  [EDGcpfe/25897]
Temporaries initialized with aggregate constants

Consider:

  constexpr int const& g(int const (&arr)[2], int i) { return arr[i]; }
  int f(int const (&arr)[2]) { return g(arr, 0); }
  void func(int *p_result) {
    for (int k = 0; k < 10; ++k) {
      using arr = int[2];
      int x = f(arr{});    // (1)
      *p_result += x;
    }
  }

Line (1) passes a constant aggregate value ("arr{}") by reference-to-const to
function f, which requires a temporary to bind the reference parameter to.
That temporary should be stored in mutable local storage, initialized with the
constant value arr{} (i.e., two zero elements).  Unfortunately, the front end
performed slightly too aggressive constant-evaluation on the temporary, causing
it to be eliminated and later re-created as a mutable static-storage temporary
(which IL lowering turns into a static variable).  That is now fixed.


1/20/23  [EDGcpfe/25978]
Issues with consteval and lowering

Prior to this change, consteval functions were not lowered, but that had caused
various problems (assertion failures, IL write-read errors, inconsistent IL,
etc.) with embedded non-consteval functions, such as non-consteval lambdas
that required lowering.  A change has been made to lower consteval functions to
avoid such changes.  Back ends should continue to ignore these routines (as
indicated by ignore_routine_in_back_end).  For example, with --c++20:

  auto x = [](int _x) consteval {
    auto y = [_y=_x]() {
      auto z = []() {return 0;};
        return _y;
    };
    return y();
  };
  int a = x(29);


1/19/23  [EDGcpfe/25900]
C23: #warning

As described in WG14 paper N2686, the #warning directive is now supported
in strict C23 mode.  (It was already available in all non-strict modes.)
For example, with --strict --c23:

  #warning This is a warning.  // Issues a warning and continues processing


1/19/23  [EDGcpfe/25969]
Missing error on consteval call failure

Consider:

  struct S {
    double x;
    template<typename T> consteval S(T) {}
  };
  void g() {
    new S(S{""});
  }

This should elicit an error because the constructor call implied by S{""} does
not produce a valid constant result despite the constructor being consteval
(the constructor fails to initialize the member x).  The front end previously
failed to issue that error (this failure was in part due to the enclosing
constructor call being elided).  That is now fixed.


1/19/23  [EDGcpfe/25964]
C++-generating back end, Microsoft compatibility: co_await keyword

The C++-generating back end previously put out the keyword for the
coroutines "await" operation using the pre-standardization spelling
"__await" when msvc_is_generated_code_target is TRUE.  MSVC since version
19.00 has accepted the standard spelling "co_await" and recent versions no
longer accept the old spelling.  The C++-generating back end has now been
updated to use the older spelling only when msvc_target_version_number is
less than 1900.


1/18/23  [EDGcpfe/25891]
C23: __has_c_attribute

As described in WG14 paper N2553, the front end now supports in C23 mode
the macro operator __has_c_attribute.  Given the name of an attribute, the
value of the operator is 0 if the attribute is not supported in the current
emulation mode.  If a supported attribute is part of the C23 Standard, the
(long int) value is the six-digit year and month when the attribute was
accepted by the C Standard Committee; otherwise, the value is 1.  For
example, with --c23:

  #if __has_c_attribute(noreturn) >= 202202L
  [[noreturn]] void f();
  #else
  #error The noreturn attribute is not supported.
  #endif


1/18/23  [EDGcpfe/25959]
C++-generating back end: designated initializers and aggregate base classes

In some cases in which a designated initializer is used with an aggregate
class that has a base class, the code generated for the value of the
designated initializer could refer to the type of the base class instead of
to the type of the field being initialized.  This is now fixed.  For
example, with --c++20:

  struct B
  { };
  struct C
  { };
  struct A : B {
    C c;
  };
  decltype(A{ .c = C() }) a;   // Previously generated as B() instead of C()


1/18/23  [EDGcpfe/19794,EDGcpfe/25955]
C23: digit separators

As described in WG14 paper N2626, the anticipated C23 Standard adopts the
digit-separator syntax of C++14.  The front end previously inadvertently
accepted digit separators in all C modes.  This error has now been
corrected, and digit separators are now accepted in C only with the --c23
or --digit_separators command-line options or when microsoft_version is at
least 1900.  For example, with --strict --c23:

  int i = 12'345;   // Now accepted in C23 mode, rejected in earlier C modes


1/17/23  [EDGcpfe/25945]
C23: ellipsis-only variadic functions

As described in WG14 paper N2975, the front end now accepts in C23 mode
function declarations in which the parameter list consists solely of an
ellipsis.  For example, with --strict --c23:

  void f(...) { }   // Now accepted in C23 mode


1/17/23  [EDGcpfe/25944]
C23: __VA_OPT__

As described in WG14 paper N3033, the front end now accepts the __VA_OPT__
preprocessor operator in C23 mode.  For example, with --c23:

  #define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
  F(a, b, c)  // replaced by f(0, a, b, c)
  F()         // replaced by f(0)


1/17/23  [EDGcpfe/25343,EDGcpfe/25363,EDGcpfe/25365,EDGcpfe/25366,
          EDGcpfe/25585]
Spurious errors for class template argument deduction for aggregates

Various aspects of this language feature, such as non-trailing parameter packs,
brace elision, designated initializers, and deduction from string literals,
were not handled correctly.  For example, with --c++20:

  struct B { int i; int j; };

  template<typename T, typename ... U>
  struct C : U ... {
    B b;
    T t;
  };
  C c{ 1, 2, 'c' };  // Previously a deduction failure.
                     // Now deduced as C<char>.

  template<typename T, int N>
  struct D {
    T arr[N];
  };
  D d{ .arr = "Hello" };  // Previously a deduction failure.
                          // Now deduced as C<char, 6>.


1/16/23  [EDGcpfe/25941]
C23: Trigraphs disabled

As described in WG14 paper N2940, the front end no longer accepts trigraphs
in C23 mode.  Trigraphs can continue to be used via the --trigraphs
command-line option.  For example, the front end will issue an error with
--strict --c23:

  int i = ??-0;   // Now an error in C23 mode


1/16/23  [EDGcpfe/25935]
C23: Unicode-based identifier syntax

As described in WG14 papers N2836 and N2939, in C23 mode the front end by
default now determines which characters can be used in an identifier
according to the specification found in Unicode Annex 31.  As mentioned in
the description of the corresponding C++23 feature (EDGcpfe/24774), the
previous behavior can be restored via use of the --old_id_chars
command-line option.  The front end also uses the previous specification
when emulating clang versions before 140000, as well as all versions of the
Microsoft and GNU compilers.  For example, the following will elicit an
error with --strict --c23:

  int a\u200cb;  // Unicode ZWNJ is not a valid identifier character in C23


1/16/23  [EDGcpfe/25918]
C23: __has_include

As described in WG14 paper N2799, the front end now supports the
__has_include preprocessor operator in C23 mode.  For example, with --c23:

  #if __has_include(<optionalh.h>)   // Now accepted in C23 mode
    #include <optionalh.h>
  #endif


1/16/23  [EDGcpfe/25894]
C23: Binary integer literals

As described in WG14 paper N2549, the front end now accepts binary integer
literals in C23 mode.  For example, with --c23:

  int i = 0b00001111;   // Now accepted in C23 mode


1/16/23  [EDGcpfe/25889]
C23: UTF-8 character literals

As described in WG14 paper N2418, the front end by default now accepts
UTF-8 character literals in C23 mode.  These literals have type unsigned
char, in contrast to char in C++17 and char8_t in C++20.  This support can
be explicitly controlled using the --[no_]utf8_char_literals command-line
option.  For example, with --c23:

  unsigned char c = u8'x';   // Now accepted by default in C23 mode


1/13/23  [EDGcpfe/25923]
C++-generating back end: dependent conversion operators

Consider the following example, to be compiled with --c++17
--gnu_version=120100:

  template <typename> class g;
  template <typename c> using d = g<c>;
  template <typename b> void f() {
    d<b> a;
    a.operator typename d<b>::e<>();
  }

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end previously put out
the call to the conversion operator on the next-to-last line using
fully-qualified names, i.e., as:

  a.g<b>::operator typename g<b>::template e<>();

Although the generated code is correct, g++, beginning with version 12.1,
reported spurious errors when compiling it.  As a result, the
C++-generating back end now suppresses the qualification of the operator
name (but not the target type) in such calls when
gcc_is_generated_code_target is TRUE and gnu_target_version_number is
120100 or larger.


1/12/23  [EDGcpfe/25911]
Abort on invalid std::construct_at invocation

The front end previously failed to check certain preconditions on the
arguments to a constant-evaluated std::construct_at invocation, which could
lead to aborts.  For example, in C++20 mode:

  namespace std { using size_t = decltype(sizeof(42)); }
  void *operator new(std::size_t, void *p) { return p; }
  namespace std {
    template<typename T, typename ...Args>
    constexpr void construct_at(void *p, Args &&...args) {
      new (p) T((Args&&)args...);
    }
  }
  int var = (std::construct_at<int>(&var, 1), 42);
    // Previously aborted (usually with a null pointer indirection).
    // Now okay.

That is now fixed.


1/12/23  [EDGcpfe/25928]
Incorrect substitution of built-in operators in constraints

Consider, in C++20 mode:

  struct X { ~X(); };
  template<typename...> union U {};
  template<typename T, typename... Unused>
  union U<T, Unused...> {
    ~U() = default;
    ~U() requires(__has_trivial_destructor(U<>));
    T bp;
  };
  U<X> var;  // Previously an error.  Now okay.

The front end previously did not correctly substitute the constraint on the
non-defaulted destructor of U, which resulted in a spurious error claiming that
the destructor of U is deleted (which would be true if only the defaulted
destructor were declared).  That is now fixed.


1/12/23  [EDGcpfe/25921]
Abort on some uses of enable_if attribute

Consider (in Clang C++ mode):

  __attribute((enable_if(true, ""))) bool f(double);
  float x = 0;
  auto r = f(x);  // Previously aborted.  Now okay.

This previously triggered an internal error in conv_glvalue_to_prvalue (in file
exprutil.c).  This regression, which was introduced into version 6.4 by the
changes for EDGcpfe/23647, is now fixed.


1/12/23  [EDGcpfe/25930]
Loss of attributes on some conversion member functions in Clang emulation mode

As a result of the changes for EDGcpfe/25243,EDGcpfe/25501 (in version 6.4),
attributes of some member conversion functions were mistakenly dropped.
This issue had only occurred in Clang emulation mode and is now fixed.  For
example (with --clang):

  template <typename T> struct A {
    __attribute__((__visibility__("hidden"))) operator T& ();
  };


1/9/23   [EDGcpfe/22395]
GNU C++ compatibility: Closure types and literal types

C++17 introduced "constexpr lambdas", and along with that feature closure types
that are literal types.  However, GCC treated closure types as literal types
by default until GCC 8.x.  For example:

  constexpr auto lm = [](int i) { return i; };
    // Now accepted in GNU C++14 mode when gnu_version < 80000.

The front end now emulates that behavior.


1/6/23   [EDGcpfe/25884]
GNU C++ compatibility: Relaxed checking for abstract class types

The changes for EDGcpfe/25234 in version 6.4 introduced a regression causing
the front end to fail to report certain invalid uses of prvalues of abstract
class type.  For example, in GNU C++ mode with gnu_version >= 110000:

  struct S { virtual void f() = 0; };
  S g();
  S h() {        // Previously failed to be diagnosed.  Now an error again.
    return g();  // Ditto.
  }

That is now fixed.


1/6/23   [EDGcpfe/15947,EDGcpfe/19055,EDGcpfe/23762,EDGcpfe/25879]
GNU/Clang C++ compatibility: Explicit lambda template parameters

In GNU C++14 modes (with gnu_version >= 40900) and Clang C++14 modes (with
clang_version >= 90000) the front end now accepts explicit lambda template
parameters, which are only standard in C++20 mode.  A warning is issued on
the first occurrence of the feature.

  auto lm = []<typename T>(T) {};  // Now accepted in some C++14 modes.


1/5/23   [EDGcpfe/24182,EDGcpfe/25880]
GNU C++ compatibility: Nontrivial class types in statement expressions

Consider (in GNU C++ mode):

  template<typename T> struct N {
    N();
    union { T value; };
  };
  struct S { S(); };
  void g() {
    ({ N<S> v; });  // Previously an error.  Now okay.
  }

The front end does not allow the definition of a class with nontrivial copy
semantics to be defined in a statement expression.  The implementation of that
constraint unintentionally also included instantiations of template classes
while parsing a statement expression, which cause the example above to give an
error.  That is now fixed.


12/28/22 [EDGcpfe/25882]
C++-generating back end: omitted aggregate initializers

In cases where a designated initializer results in default-initializing one
or more elements of an aggregate preceding the designated element, the
C++-generating back end previously terminated the initializer list at the
first such default-initialized element.  This is now fixed.  For example,
with --c++20:

  struct S {
    int m1;
    int m2;
    int m3;
  };
  S x = { .m1 = 1, .m3 = 3 };  // Previously only initialized m1


12/26/22 [EDGcpfe/25851]
C++-generating back end: missing "final" specifier in class template definition

In configurations and emulations in which class template definitions are
put out from the string form of the definition (i.e., not generated from
the prototype instantiation IL), the generated code for a class template
declared as "final" in the original source was missing the "final"
specifier.  This is now fixed.  For example, with --microsoft:

  template<typename T> class A final { };  // Previously omitted "final"


12/21/22 [EDGcpfe/25674]
Microsoft compatibility: commas in variadic macro arguments

As described in the entry for EDGcpfe/23821, the traditional Microsoft
preprocessor usually treats commas appearing in variadic macro arguments as
ordinary text, not delimiting macro arguments if the variadic argument is
used as an argument to another macro when the original expansion is
rescanned.  Under some circumstances, however, such commas do delimit macro
arguments in a subsequent macro invocation.  The front end previously
failed to recognize one of the patterns that results in argument-delimiting
commas, leading to warnings about too few arguments in a macro invocation
and incorrect macro expansions.  This is now fixed.  For example, with
--microsoft -E:

  #define M(a,b) b = a
  #define M1(x) M
  #define M2(args) M1 args
  #define M3(...) M2((foo))(__VA_ARGS__)
  M3(5, int i);   // Previously expanded to "= 5, int i", now "int i = 5"


12/21/22 [EDGcpfe/25860]
GNU C++ compatibility: signedness specifiers and 128-bit

In GNU C++ mode, the front end emulates the GNU predeclared typedefs __int128_t
and __uint128_t.  Normally, the signedness specifiers "signed" and "unsigned"
aren't valid on typedefs, but GCC does accept them in some circumstances.  To
improve GNU C++ compatibility, the front end therefore now allow "signed" on
the __int128_t typedef and "unsigned" on the __uint128_t typedef, but only in
GNU-C++-mode type-id contexts.  For example:

  auto r = (signed __int128_t)42;  // Now accepted in GNU C++ modes.
  signed __int128_t x = 42;        // Still an error (matches GCC behavior).


12/21/22 [EDGcpfe/24973]
Assertion failure in lower_ctor_init

In some cases, an assertion failure (in lower_ctor_init) had occurred when
initializing certain fields in C++14 mode.  For example (with --c++14):

  struct B {
    B() {}
    int v;
  };
  struct D : B {};
  struct A {
    D d1{};
    D d2{};
  };
  A a;


12/20/22 [EDGcpfe/20142,EDGcpfe/21012,EDGcpfe/25683]
Instantiation of discarded substatement in constexpr if

During the instantiation of an enclosing templated entity, the front end
incorrectly instantiated the discarded substatement of a "constexpr if" with a
non-dependent condition.  For example, with --c++17:

  template<bool B, class R, class T> R f(T t) {
    return [] (auto v) {
      if constexpr (B) return T::v;  // Previously a spurious error.  Now okay.
    } (t);
  }
  template void f<false>(int);


12/19/22 [EDGcpfe/21220]
Spurious error on _Alignas

In some cases where _Alignas followed an attribute, a spurious error had been
given.  For example, with --gcc --c11:

  const __attribute__((used)) _Alignas(4) int a = 1;


12/19/22 [EDGcpfe/18601,EDGcpfe/19811,EDGcpfe/21859,EDGcpfe/21999,
          EDGcpfe/25532,EDGcpfe/25816]
Core issue 2061: extension of namespace defined in inline namespace

The resolution of Core issue 2061 allows a namespace defined in an inline
namespace to be extended from the enclosing namespace.  For example, with
--c++11:

  inline namespace inl {
    namespace ns { template<class> struct A; }
  }
  namespace ns {                    // Extends inl::ns
    template<> struct A<void> { };  // Previously a spurious error.  Now okay.
  }

The front-end now implements that resolution (except in Microsoft bugs mode).


12/19/22 [EDGcpfe/25866]
Front end compilation error when MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is FALSE

In configurations where MICROSOFT_EXTENSIONS_ALLOWED is TRUE and
MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is FALSE, the front end failed to compile
(with a diagnostic given in ifc_modules.c).  Now fixed.


12/17/22 [EDGcpfe/20015,EDGcpfe/20271]
C++20: Lambdas in unevaluated contexts

WG21 paper P0315R4, which was adopted as part of the C++20 Standard,
removed the previous prohibition of lambdas appearing in unevaluated
contexts.  The front end now accepts lambda expressions in such contexts in
C++20 and later modes.  For example:

  typedef decltype([]{}) C;   // Previously an error, now okay in C++20 mode


12/16/22 [EDGcpfe/25848]
Timing of template constraint checking during overload resolution

When constrained templates were first specified in the draft standard, the
template constraints on a function template were checked after deduction
completed and the deduced arguments were substituted through the function
type.  Until now, that is how the front end implemented things.  The
resolution of Core issue 2369, however, changed the specification such that
constraints should be checked before substituting deduced arguments through
the type of a function template candidate.  That is now implemented, except
in Microsoft and Clang modes (since neither MSVC nor Clang appear to
implement Core issue 2369 at this time).

The standard also specifies that the arguments for nondeducible parameters
should be matched after the template constraints are checked, but the front
end currently performs the matching for nondependent parameters before even
attempting deduction.  That discrepancy is expected to be addressed in the
near future.


12/14/22 [EDGcpfe/25093,EDGcpfe/25795]
Type equivalence for nested template-ids and error types

The front end previously considered template-ids with a dependent
decltype-specifier as a nested name specifier that only differed in the
decltype-specifier to be equivalent.  For example, with --c++11:

  template<class T> void f(typename decltype(T::A)::template N<int>)
  { }
  template<class T> void f(typename decltype(T::B)::template N<int>)
  { }  // Previously a spurious redefinition error.  Now okay.

A similar problem also existed for error types appearing in alias templates.
In more complex cases, these problems could result in crashes during template
substitution.


12/13/22 [EDGcpfe/25850]
Requires-expressions with parameters

The front end previously did not correctly handle the parameters of a C++20
requires-expression.  That could result in spurious and/or missing substitution
failures.  For example:

  template<typename T> concept C1 = requires (T *t) {
    { requires (T u) { true; } };
    *t;
  };
  template<typename T> concept C2 = requires (T *t) {
    { requires (T u) { true; } };
    1 * t;
  };
  template<C1> void f1();
  template<C2> void f2();
  void g()
  {
    f1<int>(); // Previously a spurious error.  Now okay.
    f2<int>(); // Previously erroneously accepted.  Now an error.
  }

That is now fixed.


12/9/22  [EDGcpfe/23759,EDGcpfe/25277,EDGcpfe/25650,EDGcpfe/25838]
GNU C++ compatibility: Defaulted exception-specification compatibility

The changes for EDGcpfe/20918 (which implement the C++ standardization
committee's P1286R2) carved out some exceptions, including GNU C++ modes that
do not enable C++20.  Now, all GNU C++ modes with gnu_version >= 100000
support the changes of P1286R2.  For example:

  struct X { X() noexcept(false); };
  struct S {
    X x;
    S() noexcept(true) = default;
  };
  S s;  // Previously an error in all GNU C++11 modes because S::S() was
        // considered deleted.  Now okay when gnu_version >= 100000.


12/9/22  [EDGcpfe/25689]
GNU compatibility: "unavailable" attribute

The "unavailable" attribute is now available in GNU emulation modes when
gnu_version >= 120000.  These changes also modify the original changes for
the "unavailable" attribute (see the Changes entry for EDGcpfe/23647) to 
make the implementation similar to the "deprecated" attribute (the main
difference being that the "deprecated" attribute elicits a warning and the
"unavailable" attribute results in an error if the entity is subsequently
referred to).

Additionally, the clang-specific attribute_unavailable_with_message and
attribute_deprecated_with_message feature tests (with __has_extension) have
been implemented.


12/9/22  [EDGcpfe/25825]
Default initialization of static data member with template class type

The front end previously failed to consistently complete the type of static
data members, which could result in invalid initializers.  For example:

  template<typename> struct X {
    int x;
    X(): x(10) {}
  };
  struct S {
    inline static X<int> xi;  // Previously, xi was not correctly initialized.
  };

That is now fixed.


12/8/22  [EDGcpfe/25829]
Unbounded recursion during overload resolution

Consider (in C++11 mode):

  template<typename> struct P;
  template<typename T> struct P<T const&> { using Type = T&; };
  template<typename T> T const& constify(T&) noexcept;
  struct X {
    int const& f() const;
    template<typename ...Ts>
      auto f(Ts &&...ps) -> typename P<decltype(f(ps...))>::Type;
  };
  int g(X x) {
    x.f() = 42;
  }

Previously, this triggered unbounded recursion in some configurations or a
spurious error about excessive recursive instantiation.  That is now fixed.


12/8/22  [EDGcpfe/25832]
Dummy variable for empty function parameter pack expansion

The changes for EDGcpfe/24711 (in version 6.4 of the front end) introduced a
"dummy" static parameter variable for empty function parameter pack expansions.
In some configurations, such compiler generated entries ended up both on the
associated function scope's "variables" list and on the orphaned variables
list.  That situation could cause problems for certain back ends.  That problem
is now fixed.


12/7/22  [EDGcpfe/25833]
Spurious error on default operator<=> for template class

Consider:

  #include <compare>
  struct S {
    bool operator==(S s) const;
    bool operator<(S s) const;
  };
  template<typename T> struct X {
    S s;
    std::strong_ordering operator<=>(X const&) const = default;
  };
  X<int> x;
  auto r = x <=> x;  // Previously an error.  Now okay.

Previously, this resulted in a spurious error claiming operator<=> is deleted.
That is now fixed.


12/6/22  [EDGcpfe/25584]
GNU C++ compatibility: Floating-point template parameters

In GNU C++20 mode, the front end now accepts floating-point template
parameters when gnu_version >= 110000.


12/6/22  [EDGcpfe/24224,EDGcpfe/25747]
GNU C++ compatibility: Instantiation of in-class initializers

In GNU C++ mode, the front end instantiates the in-class initializer of a
static data member when that member is used instead of when the enclosing
class is instantiated.  A tweak has been made to more consistently do so;
previously, the initializer was not instantiated even in cases where GCC
would do so.


12/6/22  [EDGcpfe/25834]
Unicode-based identifier syntax in GNU, clang, and Microsoft emulation

The changes for EDGcpfe/24774 implemented C++ Committee document P1949R7,
basing the determination of which characters are allowed in identifiers on
the Unicode standard.  Because this document was adopted as a defect report
applying to earlier versions of C++, the change applied universally,
allowing the previous behavior via the --old_id_chars command-line option.
Because of varying adoption of P1949R7 among emulated compilers, however,
the front end now determines applicability of those changes based on the
version of the emulation dialect: clang versions before 140000, as well as
all versions of Microsoft and GNU emulations, now implement the older
character classification.  For example:

  void *to_\U00010185_and_beyond = nullptr;  // Now accepted in Microsoft,
                                             // GNU, and older clang modes


12/5/22  [EDGcpfe/21595,EDGcpfe/22681,EDGcpfe/25461]
C++: Class template argument deduction for alias templates

The C++20 feature that extends class template argument deduction to include
alias templates (described in committee paper P1814R0) is now implemented.

  template <typename T> struct C {
    C(T);
  };
  template <typename T> using A = C<T *>;
  A a = "Hello"; // A<const char> deduced

This feature is also enabled in Microsoft mode when microsoft_version >=
1927 and --ms_c++20 (or --ms_c++latest) is specified.


12/2/22  [EDGcpfe/25453]
Representation of typeid operator [IL CHANGE]

Previously, the enk_typeid representation did not represent a nondependent
operand expression if the typeid operation does not need to be computed at run
time.  Among other things, this prevented the C++-generating back end from
reliably rendering certain expressions of the form typeid(<expr>).  The
representation has now been revised to record the expression whenever it is
specified, thus also allowing reliable rendering by the C++-generating back
end.  This change also corrected some constant-evaluation cases, such as:

  #include <typeinfo>
  struct B1 { virtual void f(); };
  struct B2 {};
  struct D: B1, B2 {} d;
  template<typename T> constexpr T f(T x) {
    return typeid(d), x;
  }
  int x[f(37)];  // Previously accepted.  Now an error in pre-C++20 modes.

Previously, the typeid was considered a constant in all modes.  Now, it is
(correctly) treated as a core constant expression in C++20 (and later) modes
only.


12/1/22  [EDGcpfe/25780]
Abort elicited by checking for duplicate captures in a nested lambda

The changes for EDGcpfe/25246 (in version 6.4) included a bug that caused the
front end to sometimes fail an assertion check in diagnose_duplicate_capture
after looking for duplicate captured in a nested lambda.  For example:

  template<typename Fn, typename Out, typename... In>
  struct W {
    W (Fn fn): fn(fn) {}
    virtual void call (In... in) { fn(in...); }
    Fn fn;
  };
  template<typename> class F;
  template <typename Out, typename... In>
  struct F<Out(In...)> {
    template<typename Fn> F(Fn fn) {
      W<Fn, Out, In...> tmp(fn);
    }
  };
  void f(F<void(int)>); 
  void g(int x, int y) {
    f( [x = x, y = y](auto) { [x, y]() {}; } );  // Previously triggered an
  }                                              // internal error.  Now okay.

That is now fixed.


12/1/22  [EDGcpfe/25801]
C++-generating back end: call to non-dependent member of dependent class

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end previously added
an "&" operator to the name of the function in a call to a static member
function of a dependent class.  In most cases, this superfluous operation
was harmless, but the code was ill-formed if the member function is
overloaded.  This is now fixed, and the "&" is suppressed in such cases.
For example:

  template<typename T> struct S {
    static void f(int) {}
    static void f(double) {
      f(42);   // Previously generated as (&f)(42)
    }
  };


11/30/22 [EDGcpfe/24631]
Microsoft C++ compatibility: Rvalue reference binding

The changes for EDGcpfe/15137 (in version 4.10 of the front end) enabled the
emulation of an MSVC bug regarding the binding of an rvalue reference to a
converted lvalue.  It appears that MSVC 19.29 fixed this nonstandard behavior
and the front end now matches that.  For example:

  void g(char const*&);
  void g(char const*&&);
  void f() {
    g("Message");  // Previously an error in all Microsoft modes.
  }                // Now okay if microsoft_version >= 1929.


11/30/22 [EDGcpfe/25808]
GNU/Clang compatibility: abi_tag attribute on friend definition

A spurious error had been given on a friend declaration that is a definition
with an abi_tag attribute.  Now fixed.  For example, with --gnu_version 110000:

  template <class T> struct A {
    __attribute__((__abi_tag__("v15000"))) friend A f() {}
  };


11/30/22 [EDGcpfe/24910,EDGcpfe/24982]
GNU C++ compatibility: typename-qualified lookups

The changes for EDGcpfe/18326 attempt to emulate GCC behavior whereby the
lookup of a class-qualified name preceded by the keyword "typename" ignores
names that don't designate types.  Sometimes, however, that caused the front
end to ignore non-tag-types, resulting in spurious errors.  That issue is now
fixed.


11/28/22 [EDGcpfe/23173,EDGcpfe/24085,EDGcpfe/25551,EDGcpfe/25750]
Spurious error on non-compound discarded statements

The front-end failed to correctly skip over non-compound discarded statements
containing braces during instantiation.  For example, with --c++17:

  auto v = [](auto i) {
    if constexpr (false) int{-1}*i;  // Previously a spurious error.  Now okay.
    return 0;
  } (0);


11/28/22 [EDGcpfe/25751]
C++-generating back end: initializer for in-class explicit specialization

An in-class explicit specialization of a static data member template always had
its initializer_in_class flag set to FALSE, causing the C++-generating back end
not to emit the initializer.  For example, with --c++14 --clang:

  struct C {
    template<int I> static const int i = I;
    template<> static const int i<0> = -1;  // Previously generated without the
                                            // initializer
  };


11/23/22 [EDGcpfe/24131,EDGcpfe/24367,EDGcpfe/25703]
Microsoft compatibility: floating-point template parameters

A change has been made to accept floating-point template parameters in
Microsoft emulation mode when microsoft_version >= 1926 and --ms_c++20 or
--ms_c++latest is specified.  Note that floating-point template parameters
continue to be accepted when emulating early Microsoft versions (i.e.,
microsoft_version <= 1300).


11/23/22 [EDGcpfe/25693]
Clang compatibility: Additional changes for __builtin_elementwise_* and
__builtin_reduce_* builtins

Clang 15.0.0 added some new builtins for which special handling is required
(__builtin_elementwise_add_sat, __builtin_elementwise_sub_sat,
__builtin_reduce_add, and __builtin_reduce_mul).  Now fixed.


11/23/22 [EDGcpfe/25627]
Ignoring top-level qualifiers on calls to __builtin_shuffle

A change has been made to ignore top-level qualifiers for arguments of
__builtin_shuffle.  For example, with --gnu_version=90300:

  typedef int   VI __attribute__((vector_size(4)));
  typedef float VF __attribute__((vector_size(4)));
  void f(const VF *a1, VF *a2, VI m) {
    (void)__builtin_shuffle (*a1, *a2, m);  // Now compiles
  }


11/22/22 [EDGcpfe/25597]
Remove unneeded runtime check for calls to operator new

In cases where initialization is required of memory allocated by an allocation
function, lowering had inserted a runtime check to ensure that the result of
the allocation function was non-NULL.  Now the front end omits that check for
cases that have undefined behavior (i.e., when a throwing allocation routine is
invoked and when the routine has a non-allocating form).  For example (with
--c++14):

  #include <new>
  void* operator new[](size_t) {
    return nullptr;       // Undefined behavior
  }
  void f() {
    int buffer[4];
    new (buffer) int{42};  // Okay (now more efficient)
    new (nullptr) int{42}; // Had been okay, now causes a segfault at runtime
    new int[2]{1,2};       // Ditto
  }


11/18/22 [EDGcpfe/25802]
C++-generating back end: gcc mode, typedefs, and volatile return types

The changes for EDGcpfe/22074 (in version 6.1) addressed a problem in GNU C
mode by changing unnamed struct types to have a generated tag name (of the
form __T12345678).  While harmless in a single translation unit and in
early C modes, if the same struct appears in multiple translation units
(e.g., via a header file), it would typically be given different tag names
in each TU, violating the type compatibility rules of C99 and later
standards.  This problem has been resolved by addressing the original
problem in a different way.  The example for EDGcpfe/22074, with --gcc,
was:

  typedef struct { int i; } S;
  volatile S f(void);  // generated as "struct __T12345678 f(void);"

The original change was to use the generated name as the tag name for the
unnamed struct in the generated code so that the generated return type
would match the struct declaration.  The new approach is to preserve the
typedef (but not the superfluous "volatile" qualifier) in the return type
and to leave the struct as unnamed:

  typedef struct { int i; } S;
  S f(void);


11/18/22 [EDGcpfe/25796]
a_src_seq_secondary_decl::first_declaration for variable declarations

The field first_declaration in a_src_seq_secondary_decl is now also set for
entries representing the initial declaration of a variable (including that of
a static data member).


11/18/22 [EDGcpfe/25798]
Spurious lifetime expiration during constant evaluation

Consider (in C++20 mode):

  struct P;
  struct C { P *p = nullptr; };
  struct P { C *c = nullptr; };
  struct I {
    constexpr I(C *c) { f(c); }
    constexpr I(const I &i) { f(i.p->c); }
    constexpr void f(C *pc) { p = pc->p; }
    P *p = nullptr;
  };
  struct V {
    constexpr V() { c.p = new P{ &c }; }
    constexpr ~V() { delete c.p; }
    C c;
  };
  constexpr bool cond(I) { return true; }
  constexpr bool g() {
    V v;
    I i = I(&v.c);
    return cond(i);
  }
  static_assert(g());

A bug in the constexpr interpreter caused the lifetime of the variable v during
the evaluation of the call to g() to be ended too soon.  In turn, that caused
the use of i in the call cond(i) to be considered non-constant because it was
mistakenly treated as accessing expired storage.  That is now fixed.


11/18/22 [EDGcpfe/25670]
C++-generating back end: function reference argument to decltype(auto)
non-type template parameter

When a reference to a function is passed to a decltype(auto) non-type
template parameter, the C++-generating back end previously generated
incorrect code for the template argument.  In particular, it replaced the
reference with the name of the function to which the reference is bound.
This change meant that the function-to-pointer decay applied to the
argument, giving the non-type template parameter a different type in the
generated code than it has in the source code.  This has now been fixed by
enclosing such arguments in parentheses, preventing the function-to-pointer
decay from occurring.  For example, with --c++17:

  #include <typeinfo>
  using TIR = const std::type_info &;
  template <typename T> constexpr TIR x(T &t) { return typeid(t); }
  template <decltype(auto) F> constexpr TIR y() { return typeid(F); }
  int f();
  int (&r)() = f;
  static_assert(&x(f) == &y<r>());   // Previously generated as "y<f>",
                                     // causing the assertion to fail in the
                                     // generated code.  Now "y<(f)>".


11/18/22 [EDGcpfe/25569]
Missing cast in lowered code for __builtin_is_corresponding_member

The lowered code generated for some invocations of the
__builtin_is_corresponding_member builtin was missing a cast, resulting in code
that could be problematic for a back end.  For example (with
--gnu_version=120000):

  template <class T1, class T2, class C1, class C2>
  constexpr bool f(C1 T1::*t1, C2 T2::*t2) {
    return __builtin_is_corresponding_member(t1, t2);
  }
  struct A {} A::*a;
  struct B {} B::*b;
  bool x = f(a, b);


11/18/22 [EDGcpfe/25611]
Build issues with MAKE_FRONT_END_CALLABLE

In configurations where MAKE_FRONT_END_CALLABLE and BACK_END_SHOULD_BE_CALLED
are TRUE but BACK_END_IS_C_GEN_BE and BACK_END_IS_CP_GEN_BE are both FALSE,
a compilation error (in cfe.c) had occurred because back_end was not declared.
That is now fixed.

Also, in configurations where MAKE_FRONT_END_CALLABLE and USE_EDG_NAMESPACE
are TRUE, the definition of EDG_MAIN had been "edg_main" but the
declaration had been "edg::edg_main", leading to linker errors.  The
definition has now been changed to be "edg::edg_main".


11/18/22 [EDGcpfe/25805]
Constant-evaluation of dynamically-allocated array of length 1

The front end did not always treat a dynamically-allocated array of length 1
correctly during constant evaluation.  As a result, it sometimes treated as
non-constant expressions that are constant expressions.  For example, in C++20
mode:

  constexpr bool g() {
    auto obj = new int[1]{42};
    auto p = obj;
    p += 1;
    delete[] obj;
    return true;
  }
  static_assert(g());  // Previously a spurious error.  Now okay.

That is now fixed.


11/17/22 [EDGcpfe/25777]
Clang compatibility: __builtin_coro_* routines

Prior to version 13.0.0 of Clang, the builtin signatures for all of the
__builtin_coro_* routines had been successfully extracted by the tool used to
do the extractions, but beginning with Clang version 13.0.0 the
__builtin_coro_* builtins are available only in C++20 mode.  The tool has been
modified appropriately and those builtins are now available in later Clang
modes (unconditionally).


11/16/22 [EDGcpfe/25775]
C-mode implicitly-declared functions

Consider:

  int main() {
    return f();
  }

which is allowed in some C modes despite f() not being declared.  Previously,
the routine entry created for f() did not reflect that it is implicitly
declared.  Now its compiler_generated flag is set to TRUE.


11/16/22 [EDGcpfe/25800]
Initialization of avail_param_types

The changes for EDGcpfe/21589,EDGcpfe/22350,EDGcpfe/22466,EDGcpfe/22465 (see
entry of 4/20/21) introduced a translation-unit-dependent variable
avail_param_types, but failed to initialize that variable in situations
involving multiple translation units or precompiled header files.  That is now
fixed.


11/15/22 [EDGcpfe/25746]
Unbounded recursion while looking for a user-defined conversion

Consider:

  struct B { const int (&raic)[2]; };
  struct C: B {};
  struct D: B, C {};
  D d = { D(), {{1, 2}} };  // Previously aborted.  Now a plain error.

This example previously sent the front end into an unbounded recursion (and
thus eventually an abort) while looking for a user-defined conversion (from
type D to type B const).  That is now fixed.


11/10/22 [EDGcpfe/25789]
Segfault in fseek with --il_display

In configurations that use the C-generating back end, adding --il_display
(or --set_flag skip_il_read) to the command-line options had resulted in a
segfault in fseek when called by read_memory_region in certain cases.  Now
fixed.


11/2/22  [EDGcpfe/25476]
Clang compatibility: --ms_compatibility and commas in variadic macro arguments

As noted in the entry for EDGcpfe/16179, the traditional Microsoft
preprocessor has a nonstandard treatment of commas appearing in variadic
macro arguments, such that passing __VA_ARGS__ to another macro when the
expansion is rescanned only passes a single argument, regardless of the
presence of commas in the text of __VA_ARGS__.  The clang preprocessor in
-fms-compatibility mode only implements a very limited version of this
nonstandard processing, treating a single comma that appears alone with no
other text in __VA_ARGS__ as a single argument, rather than two empty
arguments, but in all other cases gives commas their standard meaning.
Previously, the front end fully emulated the Microsoft preprocessor in
clang mode with --ms_compatibility.  For example:

  #define M(x) --> x <--
  #define V(...) M(__VA_ARGS__)
  #define M2(x, y) x + y
  #define V2(...) M2(__VA_ARGS__)
  V( , )
  V2(x, y)

The clang preprocessor with -E -fms-compatibility accepts this example
without error and produces

  --> , <--
  x + y

and the front end with -E --clang --ms_compatibility now does so as well.
By contrast, MSVC and the front end in Microsoft mode warn about too few
arguments in the invocation of M2 and produce

  --> , <--
  x, y +

passing the string "x, y" to M2 as a single argument instead of two.


11/2/22  [EDGcpfe/25776]
Abort on capturing of explicit-this parameter

Consider, in C++23 mode:

  void f() {
    bool b = false;
    auto lm = [&](this auto&&) {
      [&](auto&&) { return b; };  // Previously triggered an internal error.
    };                            // Now okay.
  }

Previously, this triggered an internal error in this_param_value_expr (il.c).
That is now fixed.


11/2/22  [EDGcpfe/25773]
Uninitialized call frame field when constant-evaluating a statement expression

In GNU modes, the constant evaluation interpreter failed to initialize a field
of the "call frame" structure created for the evaluation of a GNU statement
expression.  That is now fixed.


11/1/22  [EDGcpfe/25088]
C++-generating back end: constrained parameters in abbreviated function
templates

The C++-generating back end previously failed to put out constraints
appearing in the auto parameters of abbreviated function templates.  This
is now fixed.  For example, with --c++20:

  template <typename T> concept large = (sizeof(T) > sizeof(char));
  int g(large auto a);   // Previously generated as "int g(auto a);"


10/31/22 [EDGcpfe/25757]
Spurious error on deduced initializer_list cast

Consider, in C++17 mode:

  #include <initializer_list>
  struct S { ~S(); };
  void g(S x) {
    std::initializer_list{ x };  // Previously an error.  Now okay.
  }

This previously elicited an error during the deduction of the template argument
for std::initializer_list (complaining that an expression must have a constant
value).  That is now fixed.  (This was a regression introduced in version 6.3
of the front end by the changes for EDGcpfe/25537,EDGcpfe/25660.)


10/29/22 [EDGcpfe/21344]
Microsoft compatibility: commas in variadic macro arguments

As described in the entry for EDGcpfe/23821, the traditional Microsoft
preprocessor usually treats commas appearing in variadic macro arguments as
ordinary text, not delimiting macro arguments if the variadic argument is
used as an argument to another macro when the original expansion is
rescanned.  Under some circumstances, however, such commas do delimit macro
arguments in a subsequent macro invocation.  The front end previously
failed to recognize one of the patterns that results in argument-delimiting
commas, leading to warnings about too few arguments in a macro invocation
and incorrect macro expansions.  This is now fixed.  For example, with
--microsoft -E:

  #define CAT(x, y) x ## y
  #define A(x, ...) CAT(x, 2)(__VA_ARGS__)
  #define M(...) A(M, __VA_ARGS__)
  #define M2(x, y) x + y
  M(abc, def)   // Should expand to "abc + def", previously gave "abc, def +"


10/28/22 [EDGcpfe/25453]
C++-generating back end: qualifier for inherited static data member

In configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE,
the C++-generating back end sometimes used the base class name qualifier to
refer to an inherited static data member in the generated code, even though
the static data member is referred to using a derived class name qualifier
in the source code.  (In configurations with
DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to FALSE, static data members are
always referred to using the class of which they are a direct member as the
qualifier, but in configurations where it is TRUE, the source qualifier
should be reproduced in the generated code.)  This is now fixed.  For
example, with --c++17:

  template<typename> struct A {
    static constexpr bool val = true;
  };
  template<typename T> struct B : A<T> { };
  static_assert(B<int>::val);   // Previously generated as A<int>::val


10/28/22 [EDGcpfe/25745]
IL write-read error after initializer folding

In some complex situations the front end could abort with an IL write-read
error after the initializer of a static-lifetime variable with a nontrivial
destructor was successfully folded (in configurations with the configuration
macro IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE).  That problem, which was
observed in some tests based on the Boost libraries, is now fixed.


10/27/22 [EDGcpfe/25632]
Attributes applied to a template type parameter substituted by a routine type

Consider (e.g., in Clang mode):

  template<typename T> struct S {
    using X = T;
    using Y = T [[nodebug]];
  };
  S<int(int)> sf;

Previously, the front end applied the attribute ([[nodebug]]) directly to the
representation of the function type int(int).  That is incorrect, since that
type is also used in S<int(int)>::X, which does not carry the attribute.  The
problem was particularly visible with the C++-generating back end, which
rendered the type of variable sf as "S<int(int) [[nodebug]]>" (that syntax is
not accepted by Clang).  This is now fixed (by layering a typeref entry on top
of the routine type and attaching the attributes to that typeref entry).


10/27/22 [EDGcpfe/25471]
Error in handling of template-id in nontype template argument

Consider:

  template<typename> struct X {};
  template<template<typename> class TEMPL, typename T>
    TEMPL<T> f(const T&);                   // (1)
  template<template<typename> class TEMPL>
    TEMPL<float> f(const float&);           // (2)
  template <typename T, X<T>(F)(T const&)> 
    int g();                                // (3)
  int r = g<int, &f<X>>();  // Previously an error.  Now okay.

When processing &f<X> as a nontype template argument, the front end prematurely
reduced it to candidate (2), even though (1) is also a potential match (and, in
fact, the correct match when deducing against the second template parameter of
(3)).  That problem -- which caused a deduction failure and an error in this
case -- is now fixed.  (This was a regression introduced by the changes for
EDGcpfe/18315 in version 4.14 of the front end.)


10/26/22 [EDGcpfe/24575,EDGcpfe/25618]
Parent scope of partial specializations of variable templates

Consider:

  namespace {
    namespace N {
      template<typename> bool trait;
    }
    template<typename T> bool N::trait<T*> = true;
  }

Previously, the front end erroneously recorded the parent scope of the partial
specialization to be the unnamed namespace when instead it should match the
primary template's parent scope.  That in turn caused the C++-generating back
end to fail to emit the "N::" name qualifier in its rendering of the partial
specialization.  That is now fixed.


10/26/22 [EDGcpfe/25729]
C++-generating back end: parenthesized braced-init-list initializers

When the initializer for a variable is a parenthesized braced-init-list,
the C++-generating back end sometimes incorrectly omitted the braces.  This
is now fixed.  For example, with --c++11:

  struct {
    long a;
    long b;
  } b({0, 0});  // Previously generated as "b((0), (0))"


-------------------------------------------------------------------------------
Version 6.4, October 25, 2022

10/20/22 [EDGcpfe/22336]
Full support for std::source_location builtins

Full support has been added for the builtins required for std::source_location
when compiling against libstdc++ and the Microsoft standard template library.

These include (for libstdc++) __builtin_source_location(), and (for the
Microsoft STL) __builtin_LINE(), __builtin_COLUMN(), __builtin_FILE(),
and __builtin_FUNCTION().

Please note, these builtins return standard-compliant EDG-specific source
location values in all modes; they do not currently support emulation of the
source location values returned by Clang, GCC, or MSVC.


10/19/22 [EDGcpfe/25739]
Use of incorrect routine type variant for function template declared via
typedef

If a function template was declared via a typedef, an incorrect type
variant could be accessed.  This could potentially result in incorrect
behavior (although that was not observed on this test case).  Now fixed.

  int f();
  template <typename> decltype(f) g;
  template <typename> int g(){}
  int main() {
    g<int>();
  }


10/19/22 [EDGcpfe/25736]
Use of incorrect base class variant

Some uses of the variant field of the base class entry could make use of the
incorrect variant field.  This could result in an abort or other incorrect
behavior.  Now fixed.


10/18/22 [EDGcpfe/25100,EDGcpfe/25170,EDGcpfe/25515]
C++23: extended floating-point types

The front end now supports in C++23 modes the additional floating-point
types and macros described in WG21 committee document P1467R9, which is
expected to be part of the upcoming C++23 Standard.  A new file in the
include_c++ directory named stdfloat.stdh provides the typedef members of
namespace std for the <stdfloat> header.  Note that the std::bfloat16_t
type is not supported at this time, and std::float128_t is supported if and
only if the non-standard __float128 type is supported.  std::float16_t is
implemented with the same internal representation as the non-standard
_Float16 type (see EDGcpfe/20094,EDGcpfe/20264,EDGcpfe/25494).  For
example, with --c++23:

  #include <stdfloat>
  std::float64_t x = 23.9f64;


10/18/22 [EDGcpfe/11090]
setjmp function name is configurable for lowered exception handling

The front end previously only supported use of the "setjmp" function for use by
exception lowering when DO_FULL_PORTABLE_EH_LOWERING is set to TRUE.  Now,
TARG_SETJMP_FUNC can be used to specify an alternative function name to use.

Additionally, this configuration macro is now used to call the glibc "_setjmp"
function on Linux by default.


10/16/22 [EDGcpfe/22994,EDGcpfe/25160,EDGcpfe/25371,EDGcpfe/25644]
Rudimentary support for ARM32 and ARM64 processors

Although the front end can be manually configured to support most any
processor, it has out-of-the-box support for both 32-bit and 64-bit versions
of the x86 line of processors.  A change has been made to automatically
detect whether the front end is being compiled on a host ARM32 or ARM64
compiler (under Linux, MacOS, or Windows), and, in the absence of explicit
target configuration, configure the front end to match the host compiler
configuration.

Two new configuration macros, TARG_SUPPORTS_ARM32 and TARG_SUPPORTS_ARM64 (and
corresponding global variables targ_supports_arm32 and targ_supports_arm64)
have been added to support this.  The TARG_SUPPORTS_X86_64 configuration
macro (and associated global variable) continue to indicate that the target
architecture is 64-bit x86 and when none of these configuration
macros/variables are set, no specific target is selected, which effectively
defaults to 32-bit x86.

As always, these configuration macros provide just a starting point for the
target configuration and customers should ensure that the configuration
(as shown by --dump_configuration) accurately reflects their target by
explicitly setting configuration macros where necessary.

No ARM builtins are available at this time.


10/14/22 [EDGcpfe/25583]
Deprecation of TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS

The front end currently supports configurations in which the source
sequence list contains entries for implicitly-instantiated instances of
templates, as if the definition of the instantiated entity had appeared in
the source code; these are called "SSI mode" configurations.  A major use
of SSI mode has been with the C++-generating back end, where the instances
would be included in the generated code as explicit specializations.
However, there are many cases in which implicit instantiations cannot be
validly represented as explicit specializations and must be suppressed,
reducing the usefulness of the feature.  Even in non-C++-generating back
end configurations, there are contexts in which implicit instantiation
results in instances that cannot be correctly ordered with respect to each
other.

In view of these considerations, these configurations are being deprecated
with a view to eliminating support for them in upcoming releases, and to
call attention to this fact, new configuration macros are now required in
order to continue using SSI mode.  C++-generating back end configurations
are particularly problematic and will be disabled soon.  As a transition
aid, the configuration macro TEMPORARILY_EXTEND_USE_OF_SSI_CP_GEN_BE can be
defined to enable this usage in this release.  Other SSI-mode
configurations can be supported for the time being by defining
ALLOW_ENABLING_OF_SSI_MODE.


10/13/22 [EDGcpfe/25710]
Memory corruption due to constant-evaluation of GNU array designators

In some situations, the constant-evaluation of an array designator in GNU C++
mode could result in memory corruption.  That is now fixed.


10/13/22 [EDGcpfe/25694]
C++-generating back end: Abort on nondependent cast in template

Consider, in GNU C++ mode:

  template<typename> struct S { operator long() const; };
  template<typename> void g(S<int> p) {
    (void)long(p);
  }

Although the cast is nondependent, in GNU C++ mode it is treated as a "generic
cast" (i.e., without performing complete semantic analysis) because it appears
in a template and doing so improves GCC compatibility.  However, the C++-
generating back end performs some basic value category checks that failed in
this case (with an internal error) because the expression node for p in
"long(p)" was left to be an lvalue.  Now it is forced to a prvalue to avoid
that issue.


10/13/22 [EDGcpfe/21443,EDGcpfe/21723]
C-generating back end: Extraneous tokens in generated code

In some configurations, the C-generating back end sometimes produced code
that could not be compiled because of the presence of the tokens ",'\0'" at
some points in the initialization of struct members.  This is now fixed.
For example, with --c++20:

  struct A {
    union U1 {} u1;
    [[no_unique_address]] union U2 {} u2;
    unsigned int bf : 10;
    ~A() {}
  };
  struct B : A {
    A *ap{};
  };
  void f() {
    B b{};
  }


10/13/22 [EDGcpfe/25704]
Error in constant-evaluation of local variable in recursive call

In some cases, accessing a local variable in a recursive function call during
constant-evaluation could produce a wrong result and/or a spurious evaluation
failure.  That is now fixed.


10/13/22 [EDGcpfe/25707]
Error in constant-evaluation of __builtin_memcmp for certain array operands

The following example previously failed the static_assert due to an error in
the implementation of constant-evaluation for __builtin_memcmp:

  struct S {
    constexpr S(char const *ptr): buf() {
      len = __builtin_strlen(ptr);
      for (unsigned i = 0; i != len; i++) { buf[i] = ptr[i]; }
    }
    size_t len = 0;
    char buf[16];
  };
  constexpr bool equal_S(S const &s, char const *ptr) {
    return __builtin_memcmp(s.buf, ptr, 4) == 0;
  }
  static_assert(equal_S(S{ "abcd" }, "abcd"), "Unexpected");
      // Previously failed.  Now okay.

That is now fixed.


10/12/22 [EDGcpfe/25118]
Abort in find_placeholder_arg_for_pack while deducing class template arguments

Consider:

  template<typename ...Ts> struct S {
    template<typename ...Us> S(Us &&...);
  };
  template<typename ...Ts> struct D: S<Ts...> {
    template<typename ...Us> D(S<Us...> &&);
  };
  void f(D<int> p) {
    D d = p;  // Previously aborted.  Now okay.
  }

This previously aborted in find_placeholder_arg_for_pack (templates.c) due to
an incomplete synthesis of the associated deduction guide.  That is now fixed.


10/12/22 [EDGcpfe/25673]
Abort on capture of init-capture

Consider:

  template<typename T> void f() {
    [c = T()](auto *p) {
      auto v = p;
      [&]() { v->f(c); };  // Previously aborted.  Now okay.
    };
 }

Previously, this case caused the front end to abort with a null pointer
indirection in find_lambda_capture (expr.c).  That is now fixed.


10/10/22 [EDGcpfe/25179]
_Float16 types in builtin signatures

Now that the front end supports the _Float16 type (in some modes), builtin
signatures that had previously used _Float16 are no longer mapped to use
an EDG-specific replacement type (__edg_fp16__).  The __edg_fp16__ type
continues to be used for clang's __fp16 type (as yet unimplemented in the
front end).


10/10/22 [EDGcpfe/25616]
Spurious substitution failure of static data member

Consider, in C++20 mode:

  template<typename> struct S {
    template <bool> struct N {
      static constexpr bool cond = true;
      friend constexpr bool operator==(const N &, const N &) requires cond {
        return true;
      }
    };
  };
  bool g(S<int>::N<true> p) {
    return p != p;  // Previously an error.  Now okay.
  }

The friend operator== was previously discarded during constraint checking
because the substitution of "cond" in the requires clause (which is really
S<int>::N<true>::cond in this case) spuriously failed.  That is now fixed.


10/7/22  [EDGcpfe/24624,EDGcpfe/25470]
Substitution of class-type nontype template parameters

The front end previously failed to substitute class-type nontype template
parameters.  For example, with --c++20:

  template<int> struct C { };
  template<int I, C<I>> constexpr bool v = false;
  template<C<1> C1> constexpr bool v<1, C1> = true;
  static_assert(v<1, C<1>{}>, "Unexpected");  // Previously failed.  Now okay.


10/6/22  [EDGcpfe/25537,EDGcpfe/25660]
Abort on deduction involving class-type nontype template parameter

Consider, in C++20 mode:

  template<int> struct Str {};
  template<int> void f() {}
  template<Str> void f() {}
  void g() { f<0>(); }

This previously aborted due to an attempt at emitting a spurious diagnostic
without an available source position.  The following example:

  template<typename T> struct S {};
  template<S> void f() {}
  void g() {
    S<char> s;
    f<s>();
  }

also aborted with an attempt to dereference a null expression stack pointer.
Those problems are now fixed.


10/5/22  [EDGcpfe/25590]
C++-generating back end: CTAD in cast with constexpr constructor

In cases where a cast expression relies on class template argument
deduction and the constructor of the class template that is used is
constexpr, the C++-generating back end sometimes explicitly included the
template arguments in the type in the cast expression in the generated
code.  This is now fixed.  For example, with --c++17:

  template<typename T> struct S {
    constexpr S(T) { }
  };
  void f() {
    S{0};   // Previously generated as S<int>{0}
  }


10/5/22  [EDGcpfe/23852,EDGcpfe/24368]
Clang and Microsoft compatibility: Variables of nonliteral types

Consider, in C++17 or C++20 mode (but not C++23 mode):

  template<typename T> struct D { ~D() {} };
  template<typename T>
  constexpr T f(T i) {
    if (i < 0) {
      D<T> d;  // Variable of nonliteral type.
      return 0;
    }
    return i;
  }
  static_assert(f(42) == 42);

The presence of a variable of nonliteral type makes f<int>(int) unusable for
constant evaluation in non-C++23 modes.  However, it appears that MSVC 19.30
and many Clang versions accept the example as is.  The front end now emulates
that behavior in the corresponding emulation modes.


10/5/22  [EDGcpfe/24483,EDGcpfe/24620]
User-defined string literal operator and class template argument deduction

The addition in C++20 of nontype template parameters of class type (see the
changes for EDGcpfe/20033 etc.) also introduced a new user-defined string
literal operator template form.  The front end's initial implementation,
however, failed to handle class template argument deduction for that form.
For example:

  using S = decltype(sizeof(42));
  template<S N> struct FixedStr {
    char str[N] = {};
    constexpr FixedStr(char const (&arr)[N]) {
      for (size_t i = 0; i < N; ++i) str[i] = arr[i];
    }
  };
  template<FixedStr str> constexpr auto operator""_fstr() {
    return str;
  }
  constexpr auto s = "abc"_fstr;

Previously, this example elicited a few errors, including a diagnostic about
the template parameter list of operator""_fstr.  Now this example is accepted.


10/3/22  [EDGcpfe/25459]
C++-generating back end: parenthesization of rewritten comparisons

When a comparison operation is rewritten as a call to a three-way
comparison operator function, the C++-generating back end previously
determined the precedence of the expression with respect to the operation
of which it is a subexpression as if it were a function call instead of the
original operator.  This incorrect precedence sometimes resulted in the
expression being put out without needed parentheses.  This is now fixed.


10/3/22  [EDGcpfe/20952,EDGcpfe/21043,EDGcpfe/23601,EDGcpfe/23732,
          EDGcpfe/23971,EDGcpfe/24086,EDGcpfe/24563]
Support for in-class explicit template specializations

The resolution of Core issue 727 allows explicit template specializations to
also be declared in class scope (previously, this was only allowed in Microsoft
and Sun modes).  Because it was adopted as a defect report, the new rules apply
to all C++ versions.  For example, with --c++03 --strict:

  struct C {
    template<class T> struct B { };
    template<> struct B<void> { };  // Previously an error.  Now okay.
  };


10/3/22  [EDGcpfe/23505]
Microsoft compatibility: Static data member specialization declaration

The Microsoft compiler always treats an explicit specialization of a static
data member of a class template as a definition, but, prior to version 1910, it
does not do so for an explicit specialization of a static data member template.
For example, with --ms_c++14 --microsoft_version=1903:

  struct C {
    template<int I>
    static const int var;
  };
  template<>
  const int C::var<0>;  // Previously a spurious error "requires an
                        // initializer".  Now okay.


9/30/22  [EDGcpfe/20094,EDGcpfe/20264,EDGcpfe/25494]
GNU/Clang compatibility: _Float16

Beginning with version 7.1 for C and 12.1 for C++, gcc has supported on at
least some platforms the _Float16 keyword to designate the IEEE 16-bit
floating point type.  Clang has had support for _Float16 in both C and C++
since version 6.0.  The front end now supports this data type in the
corresponding emulation modes.  If the front end is built with
USE_SOFTFLOAT set to TRUE, the internal representation of _Float16 values
will be the SoftFloat float16_t type.  In non-SoftFloat configurations, the
front end will use the host compiler's _Float16 data type if
HOST_HAS_FLOAT16_TYPE is TRUE (which is set automatically if the build
compiler defines __FLT16_MANT_DIG__, as both gcc and clang do when they
support the type).  Otherwise, the internal representation of _Float16
values will use the host "float" type.  For example, with
--clang_version=60000:

  _Float16 x = 1.0f16;   // Now accepted in some emulation modes


9/27/22  [EDGcpfe/25631]
C23 and GNU/Clang C compatibility: Unnamed parameters

In C, unnamed parameters are not permitted in function definitions, but that
restriction is expected to be lifted in the forthcoming C23 standard.  GCC and
Clang have already lifted the restriction with their respective version 11.x.
The front end therefore now reduces the corresponding diagnostic (ordinarily a
discretionary error) to a warning in GNU C mode with gnu_version >= 110000 and
Clang C mode with clang_version >= 110000.  Furthermore, in C23 modes the
diagnostic is now omitted altogether.  For example:

    void f(int) {}  // Now accepted by default in some GCC and Clang C modes,
                    // as well as in all C23 modes.


9/22/22  [EDGcpfe/25656]
C++-generating back end: friend declarations of deleted functions

The C++-generating back end incorrectly added "=delete" in a friend
declaration naming a function that is declared as deleted.  This is now
fixed.  For example, with --c++11:

  void f() = delete;
  struct S {
    friend void f();   // Previously generated with "=delete"
  };


9/22/22  [EDGcpfe/25613]
C++-generating back end: enumerators in C mode

In some cases, the C++-generating back end could abort with a segmentation
fault when processing a use of an enumeration constant in C mode.  This is
now fixed.  For example, with --c:

  enum E { Z };
  void f() {
    switch (Z) {
      case Z: ;   // Previously aborted with a segmentation fault, now okay
    }
  }


9/22/22  [EDGcpfe/25605]
Clang compatibility: Clang 15.0.0 builtins

The builtin_defs.h file has been updated to reflect the availability of
these new builtins when clang_version >= 150000.


9/20/22  [EDGcpfe/25653]
Abort due to missing "declared type" on generated comparison functions

In configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE the front
end previously failed to record the "declared type" of generated comparison
functions.  That in turn resulted in an abort in the C++-generating back end
(due to a failing assertion check in gen_routine_decl).  That is now fixed.


9/20/22  [EDGcpfe/25397,EDGcpfe/25630]
Abort after folding of some initializers

Consider in GNU C++20 mode:

  void g() {
    const bool b = __builtin_is_constant_evaluated();
    const float e = __builtin_is_constant_evaluated();
  }

Previously, this aborted due to a null pointer indirection because the folding
of the initializer caused the associated "dynamic initializer" entry to lose
its associated variable.  That is now fixed.


9/20/22  [EDGcpfe/22032,EDGcpfe/24268,EDGcpfe/25205,EDGcpfe/25617]
Clang and GNU C++ mode compatibility: Designated field initializers

The front end previously disallowed designated field initializers for non-POD
class types in Clang and GNU C++ modes that do not enable C++20 (in C++20 such
initializers can be valid).  Now, the C++20 rules apply in GNU C++ modes with
gnu_version >= 80100 and in all Clang C++ modes.  For example:

  struct S { S(char const*); };
  struct V {
    int i;
    S s;
  };
  V v{ .s = ""};  // Previously an error in Clang and GNU modes that don't
                  // enable C++20.  Now okay (except for earlier GNU modes).


9/20/22  [EDGcpfe/25525]
Disabling char8_t support in Microsoft C++20 mode

Previously, the --no_char8_t command-line option had no effect in Microsoft
C++20 mode.  This is now fixed.  For example, with --ms_c++20 --no_char8_t:

  const char *s = u8"";  // Previously an error.  Now okay.


9/16/22  [EDGcpfe/25615]
Abort on static data member template initializer

Consider:

  struct V {
    template<typename> static constexpr bool value = true;
  } v;
  struct S {
    template<typename T> static constexpr bool value = v.value<T>;
  };

Previously, this aborted due to a null pointer indirection in
scan_template_argument_list, while scanning the template argument list for
"v.value<T>".  That is now fixed.


9/16/22  [EDGcpfe/25643]
GNU compatibility: Folding of some pseudo-function operands

The front end previously did not fold some operands of __builtin_constant_p
and __builtin_choose_expr as aggressively as GCC's front end.  Our
implementation has been updated to more closely match GCC in this regard.
For example:

  void g() {
    typeof((char[__builtin_choose_expr(
                   __builtin_constant_p(
                               1 ?: __builtin_types_compatible_p(int, long)),
                   0,
                   (void)0)]){}) var;
  }

Previously this failed to compile because the operand of __builtin_constant_p
did not get folded, which caused that pseudo-function to produce a "false"
result.  Now, the code is accepted.


9/16/22  [EDGcpfe/25547]
Spurious error for default argument with nested template argument lists

When ">>" is used at the end of a default argument to terminate two template
argument lists, a spurious error was issued.  For example:

  template<typename T> struct C { };
  template<typename T> int v = 0;
  void f(int i = v<C<int>>);  // Previously a spurious error.  Now okay.


9/16/22  [EDGcpfe/25606]
Incorrect constant-evaluation of __builtin_memcmp

Consider:

  struct V {
    char const *data;
    size_t size;
    constexpr V(char const *s) : data(s), size(__builtin_strlen(s)) {}
  };
  struct S {
    char *data = nullptr;
    size_t size = 0;
    constexpr S(V sv) : data(new char[sv.size]), size(sv.size) {
      for (auto i = size_t{ 0 }; i < sv.size; i++) { data[i] = sv.data[i]; }
    }
    constexpr ~S() { delete[] data; }
    friend constexpr bool operator==(S const &s, V v) {
      return s.size == v.size && __builtin_memcmp(s.data, v.data, s.size) == 0;
    }
  };
  constexpr bool g() {
    V const v{"Content here."};
    S s{v};
    return s == v;
  }
  static_assert(g());  // Previously triggered a compilation error.  Now okay.

This previously failed due to the implementation of __builtin_memcmp not
correctly determining the length of storage pointed to by its operand if that
storage was dynamically allocated.  That is now fixed.


9/15/22  [EDGcpfe/23944]
Abort in i_copy_dynamic_init during aggregate initialization

In very rare cases, when the front end is copying a subobject's initialization,
an abort could occur in i_copy_dynamic_init due to expecting a subobject
lifetime to be associated with the copied initializer that is not present.  For
example:

  template <typename _Tp>
  struct allocator
  {
    ~allocator();
  };
  template <typename _CharT, typename _Alloc>
  struct basic_string
  {
    _Alloc _M_dataplus;
    basic_string(const _CharT *, const _Alloc &p2 = _Alloc());
  };
  struct Foo
  {
    basic_string<char, allocator <char>> separators = "";
  };
  struct Bar
  {
    Foo foo = {};
  };
  void test (const Bar & = {}); // Abort triggered here

This is now fixed.


9/15/22  [EDGcpfe/25386]
Abort on dependent alias template-id in decl-specifier

A dependent template-id for an alias template denoting a dependent elaborated
type specifier or, in Microsoft mode, a member class of a dependent base class
resulted in a segmentation fault in coalesce_template_class_reference when the
template-id appeared in a decl-specifier of a template declaration.  For
example, with --c++14:

  template<typename T>
  using CI = class T::I;
  template<typename T> CI<T> fn();  // Previously aborted.  Now okay.


9/15/22  [EDGcpfe/25523]
Microsoft C++ compatibility: Triviality of deleted default constructor

In Microsoft mode, a deleted default constructor is never treated as "trivial".
For example, with --microsoft:

  struct D {
    D() = delete;
    D(int);
  };
  static_assert(!__has_trivial_constructor(D), "Standard");
    // Now accepted in Microsoft mode


9/14/22  [EDGcpfe/25596]
Diagnostic for mismatched printf/scanf arguments

The front end issues a warning (or sometimes a remark) when the type of an
argument for printf/scanf-like functions doesn't match the type implied by the
format string if that format string is a literal.  Previously, the diagnostic
did not mention the types involved.  Now the expected type and the actual type
are reported in the diagnostic.


9/14/22  [EDGcpfe/24306,EDGcpfe/25404]
Closure conversion to function pointer and noexcept

The front end previously failed the assertion in the following example:

  auto lambda = [] {};
  static_assert(noexcept((void(*)())(lambda)), "Unexpected");

However, the resolution of Core issue 1722 clarified that the implied
conversion function for a non-capturing lambda-expression's closure is
noexcept and thus that example is valid.  The front end now implements that
clarification.


9/14/22  [EDGcpfe/25638]
Clang C compatibility:  __builtin_choose_expr

Support for the special built-in function __builtin_choose_expr is now also
enabled in Clang C mode (previously, it was limited to GNU C mode).


9/12/22  [EDGcpfe/25544]
Diagnostics for compiler-generated function calls

Consider:

  struct C { };
  int *begin(C, int);
  int *end(C, int);
  void f(C c) {
    for (int i : c) { }
  }

Previously, this would result in errors without a source position about too few
arguments in a function call.  Now, the error messages point to the initializer
of the range-based for statement, complaining that no suitable "begin" and
"end" functions are found.


9/9/22   [EDGcpfe/22061,EDGcpfe/25587]
GNU C++ compatibility: Falsely dependent member selections

The front end previously emulated an old bug in GCC whereby an expression like
"this->x" in a member function of a class template was treated as dependent
even though x is a member of the current instantiation and therefore considered
nondependent by the standard.  (See the changes for EDGcpfe/10800.)  GCC fixed
this bug in its version 4.7.1: The front end now matches that behavior by
limiting the emulation to GNU C++ modes with gnu_version < 40700.  Previously,
this behavior also applied to Clang modes, but now it is limited to non-Clang
modes.  Furthermore, the changes for EDGcpfe/16412,EDGcpfe/16428 slightly
changed in Clang mode: An explicit or implicit use of "this" in an argument no
longer makes the call dependent if ordinary lookup of an unqualified name finds
a candidate.


9/7/22   [EDGcpfe/21042,EDGcpfe/23680,EDGcpfe/25595]
Unevaluated subexpressions of type void in GNU C-mode constant expressions

Consider, in GNU C mode:

  char buf[__builtin_choose_expr(1, 2,(void)3)];

Previously, the front end diagnosed an error claiming that the third operand of
__builtin_choose_expr ("(void)3", which is unevaluated) is not constant.  Now,
such examples are accepted in GNU modes, to match the behavior of GCC.


9/6/22   [EDGcpfe/25602]
GNU C++ compatibility: array designated initializers in C++20

The C++20 Standard supports designated initializers for non-static data
members but not for array elements; see EDGcpfe/20003,EDGcpfe/20119.
However, g++ in C++20 mode does not enforce this restriction, and the front
end has now been changed to follow suit in the corresponding emulation mode.
For example, with --g++ --c++20:

  int x[] = { [0] = 5 };   // Previously an error, now accepted


9/5/22   [EDGcpfe/24435]
Non-standard feature warning suppression with MAKE_FRONT_END_CALLABLE

In configurations where MAKE_FRONT_END_CALLABLE is TRUE, some warnings for use
of non-standard features were incorrectly suppressed in successive invocations
of the front end.  This problem also occurred when compiling multiple
translation units in a single invocation of the front end.


8/24/22  [EDGcpfe/15165,EDGcpfe/19247,EDGcpfe/21823,EDGcpfe/25560]
Microsoft compatibility: __declspec(nothrow) and noexcept

In Microsoft C++ modes, __declspec(nothrow) applied to a function now implies
"noexcept".  For example:

  __declspec(nothrow) void g() {}
  void (*f)() noexcept = g;  // Previously an error.  Now okay.


8/22/22  [EDGcpfe/25533]
GNU/clang compatibility: default template arguments on class member templates

Clang and, as of version 6.1, g++ allow adding default template arguments
on an out-of-class definition of a member template of a non-template class.
The front end has now been changed to accept this usage in the relevant
emulation modes.  This also appears to be allowed by the current wording
of the C++ Standard, so it is also accepted with --strict; however, there
is some doubt as to whether that permission was intentional or accidental,
so such default arguments are still diagnosed as an error in default mode,
as well as Microsoft mode and for gnu_version < 60000.  For example, with
--gnu_version=60100:

  struct S {
    template<typename> static int f();
  };
  template<typename=int>   // Default argument now accepted in some modes
  int S::f() { return 0; }


8/22/22  [EDGcpfe/25555]
Abort on init-capture in nested lambda

Consider:

  void g(auto fn) {
    [=] { auto lam1 = [f = fn]() {}; };
  }
  int main() {
    g([](){});  // Previously triggered an abort.  Now okay.
  }

Previously this triggered an abort due to a null pointer indirection in
find_lambda_capture (class_decl.c) during the instantiation of g.  That is now
fixed.


8/22/22  [EDGcpfe/25562]
C++-generating back end: incorrect builtin in generated code

Uses of __is_assignable_no_precondition_check were previously put out as
__is_trivially_copy_assignable in the output of the C++-generating back end.
For example, with --microsoft_version=1932 --ms_c++20:

  template<typename _T>
  constexpr bool check = __is_assignable_no_precondition_check(_T, const _T);
  static_assert(!check<int>, "");


8/22/22  [EDGcpfe/25384]
Microsoft compatibility: commas preceding empty variadic macro expansions

As described in the entry for EDGcpfe/17519, the traditional Microsoft
preprocessor suppresses commas in macro expansions that appear before an
empty variadic macro expansion.  The change for EDGcpfe/17519, however,
resulted in the deletion of some commas that the Microsoft preprocessor
does not delete.  In particular, the deletion does not occur when the empty
variadic macro expansion results from omitting the replacement text in the
macro definition.  For example, with -E --microsoft:

  #define CAT_(X, ...)  X ## __VA_ARGS__
  #define CAT(X, ...)   CAT_(X, __VA_ARGS__)

  #define EVAL_(X, ARGS) X ARGS
  #define EVAL(X, ...) EVAL_(X, (__VA_ARGS__))

  #define EAT(...)  /* nothing */

  EVAL(CAT, a, EAT(x) b)  // Previously expanded to "a b", now to "ab"

Previously, the empty expansion of "EAT(x)" resulted in incorrectly
deleting the comma following "a", which in turn resulted in passing "a b"
as a single argument to the CAT macro.  This is now fixed.


8/17/22  [EDGcpfe/24377,EDGcpfe/25527]
Constrained "decltype(auto)" nontype template parameters

The front end now accepts:

  template<typename> concept C = true;
  template<C decltype(auto)> struct X;

Not accepting that variation of nontype template parameters declared with a
placeholder type was an oversight.  Furthermore, the front end now also
correctly diagnoses some constrained "auto" nontype template parameters where
is previously failed to do so.  For example:

  template<typename> concept C = false;
  template<C auto = 42> struct S {};
  S<> s;  // Previously erroneously accepted.  Now okay.


8/16/22  [EDGcpfe/21159,EDGcpfe/24861,EDGcpfe/25474]
GNU C++ compatibility: Substitution of nondependent type aliases

Consider:

  template<bool> using Int = int;
  template<typename> struct X;
  template<typename U, Int<X<U>::f> = 0> int operator<<(int, U);
  struct C {};
  int r = 0 << C{};  // Normally an error.  Now okay in GNU C++ mode.

Normally, this should elicit an error because the substitution of X<U>::f fails
(since template X has no definition).  However, it appears that GCC does not
perform the substitution of X<U>::f in Int<X<U>::f> because alias template Int
aliases a nondependent type (int, in this case).  It is not entirely clear when
GCC fails to perform such substitutions, but the front end now emulates that
behavior in GNU C++ mode to cover all the cases we are currently aware of.


8/16/22  [EDGcpfe/25540]
C++-generating back end: implicit return in handler of function try block

The IL includes explicit stmk_return statements wherever the language rules
specify an implicit return.  The C++-generating back end generally
suppresses these implicit return statements in the IL so that they do not
appear in the generated code.  However, it failed to do so in the handlers
of function try blocks.  This failure resulted in errors in a
value-returning function when the generated code was compiled by g++, which
accepts an implicit return with a warning in such cases but issues an error
for an explicit return with no operand.  This is now fixed.  For example,
with --g++:

  int f() try {
    throw 0;
  } catch (...) {
    // implicit return, previously generated as "return;"
  }


8/15/22  [EDGcpfe/25285]
C++-generating back end: direct-list-initialization of non-static data members

In some modes, the C++-generating back end failed to put out the outer
braces for a default member initializer that is a braced initializer list,
effectively concatenating the member name with the initializer.  This is
now fixed.  for example, with --c++17:

  struct A { };
  struct B {
    A a{ A{} };   // Previously generated as "A aA{}"
  };


8/15/22  [EDGcpfe/25388]
Nondependent alias templates in prototype instantiations

Consider:

   template<typename> concept C = true;
   template<C T> constexpr T g(T t) { return t; }
   template<typename T> struct S {
     using Type = unsigned;
     void f(Type x) {
       g(x);  // Nondependent call.
     }
   };

The call g(x) is nondependent because the type of x is known during the
prototype instantiation of S<T>::f.  However, the front end did not correctly
handle this case: It attempted to substitute S<T>::Type in the wrong context,
which resulted in an internal error in a call to get_template_arg_by_list_pos.
That is now fixed.


8/15/22  [EDGcpfe/25530]
Microsoft mode regression with __restrict parameter

The changes for EDGcpfe/24520 (in version 6.3) introduced a regression in
Microsoft mode.  For example:

  using F = void (void *__restrict);
  using F = void (void *);  // Previously an error.  Now okay.

The changes for EDGcpfe/24520 caused the front end to consider the redefinition
of F to be incompatible with the original definition of F, which in turn caused
the front end to emit an error on the redefinition.  However, it appears that
MSVC ignores the __restrict qualifier such contexts.  The front end now
emulates that behavior in Microsoft mode.


8/12/22  [EDGcpfe/25485]
Assertion failure in mangled_simple_id

The mangling of a captured "this" had caused an assertion failure in
mangled_simple_id.  That is now fixed.  For example (with --c++14):

  template <class> bool v;
  template <class T> struct A {
    typename T::X mf() {
      [&]() { v<decltype(mf())>; };
    }
  };


8/11/22  [EDGpcfe/24430]
Elimination of initk_deducing

The front end previously represented variables in the process of having their
type deduced as temporarily having an "initialization kind" initk_deducing.
That was used to detect circular dependencies.  However, some customer tools
built on top of the front end need to have access to the original
"initialization kind" during that process.  To accommodate such tools, the
initk_deducing state has been eliminated, and the circular dependencies are
detected using another mechanism.


8/4/22   [EDGcpfe/25130]
Microsoft compatibility: comma deletion with empty __VA_ARGS__

The traditional Microsoft preprocessor omits from a macro expansion a comma
that is pasted to, or simply followed by, an empty __VA_ARGS__ variadic
macro argument.  This comma deletion is non-standard.  The previous
implementation of the --ms_std_preprocessor command-line option followed
the standard specification in this regard and always included the comma in
the macro expansion.  However, MSVC still performs the comma deletion
preceding the paste operator (##) even with the /Zc:preprocessor
command-line option, although not when the paste operator is omitted.  The
front end now emulates this behavior.  For example, with --microsoft:

  void f(int);
  #define M1(x, ...) f(x, ## __VA_ARGS__)
  #define M2(x, ...) f(x, __VA_ARGS__)
  void g() {
    M1(1);  // Now expands to f(1) in both preprocessor modes
    M2(1);  // Expands to f(1) in traditional mode, f(1,) in standard mode
  }


8/4/22   [EDGcpfe/25246]
Spurious duplicate capture error on nested lambda

Consider (in C++14 mode):

  struct S {
    int i;
    void f() {
      [tmp = 0, this]{
        [tmp, this]{ this->i = 0; };  // Previously elicited spurious errors.
      };                              // Now okay.
    }
  };

Previously, the inner capture of "this" was erroneously reported as a duplicate
capture, and an additional spurious error was emitted about "this" not being
captured by the inner lambda expression.  That is now fixed.


8/3/22   [EDGcpfe/24949]
Spurious error with explicit template argument and dependent return type

The front end previously issued a spurious "no instance of function
template matches" error in cases where the function template's return type
depends on a variadic template parameter whose corresponding template
argument is explicitly specified.  This is now fixed.  For example, with
--c++11:

  template<typename... Ts> auto f(Ts&&... ts) -> decltype(int(ts...));
  int i = f<int>(0);   // Previously an error, now okay


8/2/22   [EDGcpfe/25243,EDGcpfe/25501]
Clang compatibility: "using_if_exists" attribute

Clang has added a "using_if_exists" attribute that appears in a non-standard
location for attributes on a using-declaration.  Such attributes are now
parsed (and attached to the using-declaration), but are not currently acted
upon.  For example, with --clang_version 100000:

  struct A {};
  namespace N {
    using ::A __attribute((using_if_exists));   // Now okay.
  }
  using ::foo __attribute((using_if_exists));   // Still an error (since foo
                                                // has not been declared).

In addition, the clang __has_extension(cxx_attributes_on_using_declarations)
macro now returns true to indicate that syntactic acceptance of attributes
on using declarations is accepted (though the semantics are not yet
implemented).


8/2/22   [EDGcpfe/25421]
Class template deduction with an ambiguous base class

Consider:

  template<typename...> struct B {};
  struct C1: B<int> {};
  struct C2: B<int> {};
  struct D: C1, C2 {};
  template<template<typename...> typename TT, typename... As>
    int f(TT<As...>*);
  auto x = f<B>((D*)0);  // Previously a deduction failure.  Now deduction
                         // succeeds but an ambiguity error is issued for the
                         // D*-to-B<int>* conversion.

Previously, this test case reported that no candidate "f" matches the call in
the initializer for x because B<int> being an ambiguous base class of D caused
deduction for the call "f<B>((D*)0)" to fail.  Although it is not entirely
clear what the standard requires here, it appears that other implementations do
not fail deduction in that case (i.e., they successfully deduce TT=B and
As=<int>): The front end now matches that behavior.  In this case, that means
that an error is issued that B<int> is an ambiguous base class when trying to
convert (D*)0 to B<int>* (but in more complex cases, this may instead cause an
enclosing level of deduction to fail).


8/1/22   [EDGcpfe/25111]
Abort in template_arg_list_is_dependent_full on dependent variadic template
argument

Consider:

  template<typename...> struct X { };
  template<template<typename...> class TT> struct W {
    template<typename... Ts> using Templ = TT<Ts...>;
  };
  template<typename T, typename... Args>
    typename T::template Templ<Args...> f(Args...) { return {}; }
  auto r = f<W<X>>();  // Previously aborted.  Now okay.

Previously this aborted due to a null pointer indirection in templates.c (in
function template_arg_list_is_dependent_full) due to the incorrect handling of
a dependent variadic template argument.  That is now fixed.


7/29/22  [EDGcpfe/25083]
GNU C++ compatibility: Nonstandard using-directive lookup and friend injection

The front end emulates various nonstandard GCC behaviors that affect lookup in
the presence of using-directives and friend declarations (see, e.g., the entry
for EDGcpfe/18114).  It appears that with GCC version 6.x, those nonstandard
behaviors have been removed, and the front end now limits the former GCC
behavior emulation to GNU C++ modes with gnu_version < 60000 in this regard.
In particular, that causes the front end to accept the following example with
--gnu_version=60100:

  namespace N {
    struct S { void operator()() const {} };
    S f{};
  }
  using namespace N;
  struct X {
    template<typename T> friend void f() {}
  };
  int main() {
    f();  // Previously ambiguous with --gnu=60100.  Now okay.
  }


7/29/22  [EDGcpfe/24711]
Nested variadic templates and empty function parameter pack expansions

Consider (in C++17 mode):

  template<typename... Ts> inline bool g(Ts ...ps) {
    return [&](auto &... xs) {
             return ((xs < ps) && ...);  // Previously an error.  Now okay.
           }();
  }
  bool r = g();

When g<>() is instantiated (with an empty pack), there is no longer a parameter
"ps" to refer to, but the prototype instantiation of the nested generic lambda
still referred to that name.  Previously, this resulted in a spurious error.
That is now fixed.


7/29/22  [EDGcpfe/25291]
C++-generating back end: protected member access

The C++-generating back end previously failed to consider protected access
when determining the accessibility of a name when generating code.  In some
complex cases involving protected member types, this omission could result
in an invalid substitution of a typedef in place of the member type.  This
is now fixed.


7/28/22  [EDGcpfe/23617,EDGcpfe/25129,EDGcpfe/25468,EDGcpfe/25873]
C23 compatibility: Attributes

As described in papers N2335, N2554, N2267, N2448, N2270, N2334, N2408, and
N2764, the C++ attribute syntax has been adopted by C and the following
attributes are now accepted in C23 mode: "deprecated", "fallthrough",
"maybe_unused", "nodiscard", and "noreturn" (and its alias "_Noreturn").
The behavior of these attributes is identical to the C++ versions.

In addition, attributes with standard syntax are now enabled in GCC mode when
gnu_version >= 100000 and in Microsoft mode when microsoft_version >= 1934.


7/28/22  [EDGcpfe/23617,EDGcpfe/25129,EDGcpfe/25468]
C23 mode

In preparation for the next version of the C standard, currently referred
to as C23, the --c23 command-line option has been added to enable C23 mode.
This option currently has the same effect as --c18.


7/28/22  [EDGcpfe/25495]
C++-generating back end: trailing requires-clause with function-call operand

The C++-generating back end failed to enclose the operand of a trailing
requires-clause in parentheses when it consists of a single function call,
resulting in code that could not be compiled.  This is now fixed.  For
example, with --c++20:

  template<typename> constexpr bool f() { return true; }
  template<typename T> void f() requires (f<T>()) { }  // Previously omitted ()
                                                       // around f<T>()


7/27/22  [EDGcpfe/21479,EDGcpfe/24646,EDGcpfe/25478]
Spurious error on use of deleted defaulted move constructor

Consider:

  struct S {
    S(int);
    S(S const&);
    S(S&&) noexcept(false) = default;
  };
  S g() {
    return 42;  // Previously an error in GNU C++11 and C++14 modes.
  }             // Now okay.

Previously, that elicited an error about an elided constructor being deleted
in GNU C++11 and C++14 modes (but not GNU C++17 mode, because mandatory copy
elision rules masked the issue in that case).  That error was spurious,
however, since a deleted defaulted move constructor must be ignored altogether
(by the resolution of Core issue 1402, which the front end generally already
implemented but this particular context was overlooked).  This problem also
existed (for more complex cases) in other C++11 and C++14 modes.  That is now
fixed: The move constructor is now ignored and instead the (elided) copy
constructor is considered instead.


7/27/22  [EDGcpfe/25483]
C++-generating back end: aggregate constant initialization

In some cases involving aggregate constant initialization, the
C++-generating back end generated code that could not be compiled because
it represented a conversion as a C-style cast instead of a
functional-notation cast.  This is now fixed.  For example, with --c++11:

  struct A {
    struct B { int arr[2]; };
    constexpr A(const B &br) : b(br) {};
    B b;
  };
  constexpr A a(A::B({{}}));  // Previously generated as a((A::B)({{}}))


7/27/22  [EDGcpfe/25436]
Microsoft C++ compatibility: Evaluation of constexpr dllimport function

Consider (in Microsoft C++ mode):

  template<typename T> struct B {
    constexpr B(T) {}
  };
  template<typename T> struct D: B<T> {
    constexpr D(T p) : B<T>(p) {}
  };
  extern template struct __declspec(dllimport) D<int>;
  constexpr D<int> d{42};  // Previously an error.  Now okay.

Previously, this elicited an error from the front end because the "extern
template" directive with the dllimport attribute was interpreted as a signal
not to instantiate the members of D<int>.  Now, such instantiations are
performed when needed for constant evaluation, which makes this example valid.


7/27/22  [EDGcpfe/25399]
Microsoft and GNU compatibility: Implicit reversed comparison operator template

Consider:

  #include <compare>
  template<typename T> struct X {
    template<typename U> std::strong_ordering operator<=>(X<U> const&);
  };
  auto b = X<float>{} <=> X<double>{};  // Now accepted in GNU and Microsoft
                                        // C++20 modes.

This example is ambiguous because X<float>::operator<=><double> and
X<double>::operator<=><float> (with reversed operands) are equally good
matches.  However, MSVC and GCC accept the case, and the front end now does
also in Microsoft and GNU C++20 modes.


7/22/22  [EDGcpfe/22611,EDGcpfe/24625,EDGcpfe/25401]
Abbreviated variadic function templates in class templates

Consider:

  template<typename ...Ts> struct S {
    S(auto ...p) {} 
  };
  S<int> si{42};  // Previously triggered an error.  Now okay.

Previously, this resulted in an error whose root cause was that the parsing of
the variadic constructor during the instantiation of S<int> was incorrect (it
was parsed as a default constructor instead of as an abbreviated constructor
template).  That is now fixed.


7/21/22  [EDGcpfe/25337]
VLAs in GNU statement expressions

Previously, the front end never accepted VLAs in GNU statement expressions.
That limitation is there primarily because it interferes with certain C-mode
IL representations, particularly when VLA_DEALLOCATIONS_IN_IL is configured to
TRUE.  Now, VLAs are accepted in GNU statement expressions in any mode where
the global variable vla_deallocations_in_il is FALSE (in particular, in all
GNU C++ modes).


7/20/22  [EDGcpfe/25006]
Incorrect handling of trailing requires-clause

Consider:

  struct S {
    template<typename> class N {
      static constexpr bool Cond = true;
    public:
      void f() requires Cond {}
    };
  };
  int main() {
    S::N<int> sni;
    sni.f();
  }

Previously, this triggered a spurious error because the substitution of the
trailing requires-clause occurred in a context that was not treated as a
member of S::N<int>, and had no access to the Cond member.  That is now fixed.


7/19/22  [EDGcpfe/25445]
C++-generating back end: hang with inaccessible conversion operator name

The C++-generating back end previously entered a non-terminating loop when
attempting to generate the name of a user-defined conversion operator where
the type is an inaccessible typedef whose underlying type is an accessible
typedef.  This is now fixed.  For example:

  typedef int T;
  class B {
    typedef T priv;   // priv is private, T is accessible
  public:
    operator priv();
  };
  struct D : B {
    using B::operator int;   // previously resulted in a hang
  };


7/19/22  [EDGcpfe/19491,EDGcpfe/25473]
Clang C compatibility: _Generic selector operand

In Clang C mode, the first operand of _Generic constructs now undergoes the
usual operand transformations (which, e.g., drops top-level "const" from the
type or performs array-to-pointer decay).  This was already the case in other
modes that accept the C _Generic construct.  For example:

  void g(void) {
    int a[1];
    _Generic (a, int*: 0, int const*: 0);  // Previously an error in Clang
  }                                        // C mode.  Now okay.


7/18/22  [EDGcpfe/25440]
C++-generating back end: dependent default type template arguments

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end sometimes failed to
perform template argument substitution in a template argument resulting
from a default template argument.  In particular, if a type template
argument of an instance is derived from a default template argument
referring to a preceding template parameter and the instance is named
inside a template definition, the C++-generating back end failed to
substitute the template argument for the parameter used in that argument.
This is now fixed.  For example, with --c++14:

  template<int> struct S {
    template<typename T, typename U = T> static constexpr int i = 0;
    void f() {
      int j = i<int>;  // Previously generated as "i<int, T>" instead of
                       // "i<int, int>"
    }
  };


7/18/22  [EDGcpfe/25346]
Circular atomic constraints

Consider:

  struct X {
    template<class T> X &operator<<(const T &);
  };
  template<typename T, typename U>
    concept Outable = requires(U &s, T const &x) { s << x; };
  template<typename T>
    void operator<<(X &x, const T &o) requires (!Outable<T, X>) {
    x << 0;  // Error now caught earlier.
  }

This example is ill-formed because the constraint that must be checked for
the expression x << 0 depends on itself (via the concept Outable, which will
recursively substitute the non-member operator<< candidate).  Previously, the
front end caught this via a general mechanism that limits the number of
recursive substitutions.  If the limit is set too high, however, that can
result in aborts due to running out of space on the system call stack.  Now,
the front end reports the circularity as soon as it finds that an atomic
constraint (the requires-expression in this case) is recursively substituted
with the same template arguments.


7/13/22  [EDGcpfe/25280]
C++-generating back end: non-type template parameters with dependent function
types

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end produced incorrect
code when the type of a non-type template parameter is a dependent function
type and that template parameter is passed as an argument to an "auto&"
non-type template parameter.  This is now fixed.  For example, with
--c++17:

  template<typename c> using e = c();   // e is "function returning c" type
  template<auto&> int t;
  template<typename h, e<h> T> void j() {
    t<*T>;   // Previously omitted "*" in generated code
  }


7/12/22  [EDGcpfe/25335]
Clang compatibility: __builtin_preserve_access_index

The clang __builtin_preserve_access_index builtin returns the type of its
first argument -- a change was made to that effect.  For example, with
--clang_version 100000:

  struct A {
    int m;
    double d;
  };
  void f(A *ap) {
    int i = __builtin_preserve_access_index(ap->m);
    double d = __builtin_preserve_access_index(ap->d);
  }


7/12/22  [EDGcpfe/25252]
CTAD issue with variadic constructors

Class template argument deduction (CTAD) could fail in some cases where
a class template constructor had a function parameter that was a pack
expansion.  Now fixed.

  template <class T> struct A {};
  template <typename T1, typename ...Ts> struct B {
    B(const A<T1> &t, const A<Ts> &...ts) {}
  };
  void f(A<int> p1, A<double> p2) {
     B b(p1, p2);
  }


7/12/22  [EDGcpfe/25296]
Internal error when lowering certain pointer arithmetic expressions

In configurations where LOWER_VARIABLE_LENGTH_ARRAYS is TRUE, lowering of
certain pointer arithmetic expressions had caused an internal error (in
type_pointed_to).  For example, with --vla:

  void f(bool b) {
    b += &b;
  }


7/12/22  [EDGcpfe/25423]
Assertion failure in define_default_version_of_routine

In configurations that use lowering and have the
IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS configuration macro set to TRUE,
an assertion failure in define_default_version_of_routine had occurred when
lowering any deleting or delegating destructor.  This regression was introduced
in version 5.0 by the changes for EDGcpfe/18957.


7/12/22  [EDGcpfe/25412]
Assertion failure in deferred_check_unused_result_attr

Use of the "warn_unused_result" attribute on a typedef had caused an assertion
failure in deferred_check_unused_result_attr and is now fixed.  For example,
with --g++:

  typedef void *(__attribute__((warn_unused_result)) *F)();


7/12/22  [EDGcpfe/25420]
Assertion failure in lower_dynamic_init for nested lambdas

In configurations that use lowering, the front end had aborted with an
assertion failure in lower_dynamic_init when (1) a lambda is nested within
another lambda, (2) the inner lambda captures a constexpr variable and a
non-constexpr variable, (3) the outer lambda is a generic lambda, and (4) the
outer lambda is invoked.  Now fixed.  For example:
 
  void f(int, int);
  void g() {
    int a = 3;
    constexpr int b = 4;
    auto lam = [=](auto) {
                            [=](){ f(a, b); };
                         };
    lam(2);
  }


7/5/22   [EDGcpfe/25357]
Incorrect source position for unnamed namespace extension

In configurations in which GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, the
secondary source sequence entry for an unnamed namespace extension
incorrectly indicated the source position of the first unnamed namespace
definition instead of the location of the extension.  This error could be
observed in the #line directives generated by the C++-generating back end.
This is now fixed.  For example:

  namespace { }
  int i;
  namespace { }  // Previously designated as starting on line 1


7/1/22   [EDGcpfe/23306,EDGcpfe/24748,EDGcpfe/25063]
Literal types and constexpr friends of class templates

Consider:

  template<typename T> struct S {
    friend constexpr T f(T x) { return x; }
  };
  struct X: S<X> { X() { } };  // Not a literal type.
  auto r =  f(X{});  // Previously an error.  Now usually a warning.

The C++ standard makes this invalid because f(X) is declared constexpr but its
return type X is not a literal type.  The standard makes an exception for
instances of function templates and for members of class template instances,
but this is neither of those cases.  It is expected that the committee will
eventually relax that rule and, in nonstrict modes, the front end now issues
only a warning on this case.


7/1/22   [EDGcpfe/25413,EDGcpfe/25429]
Loss of type qualifier for folded call

Consider:

  struct S {
    void f() = delete;
    int f() const;
  };
  constexpr S const g() { return {}; }
  auto x = g().f();  // Previously a spurious error.  Now okay.

Previously, the front end accidentally dropped the "const" qualifier on the
result of calling g() in the process of folding that call.  That in turn
resulted in an error because it caused the incorrect member S::f() to be
selected in the initialization of x.  This is now fixed.


6/30/22  [EDGcpfe/25280]
C++-generating back end: Function type for non-type template parameter via
alias template

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end previously put out
incorrect code when the type of a non-type template parameter is specified
via an alias template denoting a dependent function type.  For example,
with --c++17:

  template<typename c> using e = c();   // e denotes a function returning c
  template<auto &> int f;
  template<typename h, e<h> F> void j() { f<*F>; }

The C++-generating back end previously generated the last line as:

  template<typename h, e<h> *F> void j() { f<F>; }

adding "*" in the template parameter type and omitting it in the template
argument.  This is now fixed.


6/29/22  [EDGcpfe/24536,EDGcpfe/25430]
Spurious errors when using dependent constexpr variable as template argument

Consider:

  template<int> int g();
  template<int N> constexpr int Val = N;
  template<int N = 0, class = decltype(g<Val<N>>())> int f();
  int r = f();  // Previously an error.  Now okay.

This example previously resulted in a spurious substitution failure because
the substitution of Val<N> resulted in a representation that the front end
failed to match to a nontype template parameter of scalar type (int, in this
case).  That is now fixed.


6/28/22  [EDGcpfe/24147,EDGcpfe/25105,EDGcpfe/25410]
Trailing requires-clause on abbreviated function template

Consider:

  int f(auto p) requires (sizeof(p)<100);

Previously this triggered a spurious error claiming the requires clause is not
valid in that context, followed by an internal error in exprutil.c.  That is
now fixed.


6/28/22  [EDGcpfe/25437]
Cfront ABI: mangling of routine constants

A change has been made in configurations that use the Cfront ABI to mangle the
parameters of routine constants (similar to what is done in the IA-64 ABI) to
avoid potential mangling collisions as in this case (with --c++17):

  void f(double) { }
  void f(int) { }
  template <auto T> void func() { }
  void g() {
    constexpr void (*fptr1)(double) = f;
    constexpr void (*fptr2)(int) = f;
    func<fptr1>();
    func<fptr2>();
  }

The previous behavior can be retained by setting ABI_COMPATIBILITY_VERSION
to a value less than 604.


6/28/22  [EDGcpfe/25207]
GNU C++ compatibility: Incomplete-type operands in templates

Consider:

  struct I;
  template<typename T> void g(I *p) {
    p[2].x = 42;  // Now accepted in all GNU C++ modes.
  }

The expression p[2] is normally an error because p is a pointer to an
incomplete class type.  However, GCC accepts such expression in templates, and
that is why the option --defer_parse_function_templates is often enabled by
default in GNU C++ modes (and indeed why that option was initially introduced).
A change has now been made to accept this example (and some like it) in GNU C++
modes even when deferral of prototype instantiations is turned off (e.g., with
the option --no_defer_parse_function_templates).


6/27/22  [EDGcpfe/25299]
C++-generating back end, GNU C++ compatibility: casting dependent
pointer-to-member-function to function pointer

The g++ compiler accepts a nonstandard conversion of a
pointer-to-member-function to an ordinary function pointer.  In
configurations in which template definitions are generated from the
prototype instantiation IL, when the source code applies this conversion to
a dependent member function, the C++-generating back end previously
generated incorrect code for the operand of the cast.  This is now fixed.
For example, with --g++:

  template <typename> struct S {
    int f();
    bool g() {
      return ((void*)(this->*(&S::f)) ==
              (void*)(&S::f));  // Previously generated as
                                // (void*)((*(0))).*(&S::f)))
    }
  };


6/27/22  [EDGcpfe/25274]
GNU compatibility: Deducing "T&" to "this"

Older versions of GCC included a nonstandard behavior that caused them to match
a parameter of type T& (where T is a template parameter) to a "this" argument
(which is normally invalid since "this" is a prvalue), but in doing so GCC
deduced T to be a const type.  The changes for EDGcpfe/9874 made the front end
emulate this behavior in all GNU and Clang C++ modes.  Now that emulation is
limited to non-Clang GNU modes with gnu_version < 40900.  For example:

  template<typename T> void g(T&);
  struct S {
    void f() {
      g(this);  // Now an error in Clang modes and in GNU C++ modes with
    }           // gnu_version >= 40900.  Still accepted in other GNU C++
  };            // modes.


6/24/22  [EDGcpfe/25259]
Assertion failure in map_token_numbers_to_cache_pointers after auto parameters

Consider in C++20 mode:

  template<typename T> struct S {
    template<typename U> void f(auto x) noexcept(true);
  };

This previously failed an assertion in map_token_numbers_to_cache_pointers
(leading to an internal error) because the handling of the noexcept specifier
in a function template declared both with an ordinary template parameter and
an "auto" parameter caused the front end to unnecessarily duplicate a data
structure.  That is now fixed.


6/22/22  [EDGcpfe/25233]
C++-generating back end: assertion failure on pack expansion with member access

When the type of the object expression in a member access expression is a
pack reference, the C++-generating back end could abort with an assertion
failure in push_class_name_context.  This is now fixed.  For example, with
--c++11 --parse_templates:

  struct S {
    template <typename... Ts> void f(Ts &&... ts) {
      g(static_cast<decltype(ts)&&>(ts).t...);  // Previously failed assertion
    }
    template<typename... T> void g(T...){}
  };


6/22/22  [EDGcpfe/25235]
C++-generating back end: members of class templates as template arguments

In some configurations, when an instance of a template is first referred to
in the body of a class template using a member of that class template as a
template argument, the C++-generating back end could put out a subsequent
reference to that template instance in which the argument is represented by
a qualified name referring to the class template's parameters, even though
those parameters are no longer in scope.  This is now fixed.  For example,
with --c++14:

  template <int> struct A { };
  template <typename T> struct B {
    static constexpr int N = 42;
    auto fun() { return A<N>{}; }
  };
  using X = A<42>;  // Previously generated as A<B<T>::N>


6/22/22  [EDGcpfe/25422]
Assertion failure in mangled_encoding_for_type_full with vector types

In some C++-generating configurations that have MANGLE_ALL_NAMES set to TRUE,
mangling of a vector of template types had resulted in an assertion failure
(in mangled_encoding_for_type_full).  Now fixed.  For example, with --g++:

  template <typename T> struct A {
    typedef T t __attribute__((vector_size(sizeof(T) * 4)));
    static A a(t);
  };
  A<short> x;


6/21/22  [EDGcpfe/25169]
Microsoft compatibility: Invalid calls in templates

Consider:

  template<typename T> struct S {
    void f(S &x) {
      [x](auto) { x.g<int>(T{}); };
    }
    template<typename U, typename = typename U::X>
    void g(U) {}
  };
  void f(S<int> si) {
    si.f(si);  // Normally an error.  Now okay in Microsoft modes.
  }

This is normally an error, because the instantiation of S<int>::f(S&) includes
an invalid call to S<int>::g<int>(int) (because its defaulted second template
argument is invalid when U = int).  Microsoft compilers, however, do not
diagnose this when the (nondependent) call is inside a template (a generic
lambda in this case).  The front end now emulates that behavior in Microsoft
mode.


6/21/22  [EDGcpfe/25340]
Microsoft compatibility: "for each" statements in C++/CLI and C++/CX modes

The "for each" statement had been inadvertently disabled in some Microsoft
emulation modes (e.g., with --no_ms_permissive) and is now unconditionally
enabled in C++/CLI and C++/CX modes.


6/18/22  [EDGcpfe/24657,EDGcpfe/25409]
Nonconstant destruction and constinit variables

The changes for EDGcpfe/24840 (in version 6.3) were incomplete in that they
didn't handle default initialization of constinit variables with nonconstant
destruction.  For example (C++20 mode):

  struct S { ~S(); };
  constinit S s1{};  // Accepted since version 6.3.
  constinit S s2;    // Previously a spurious error.  Now okay.

That oversight is now fixed.


6/17/22  [EDGcpfe/23647]
Clang compatibility: Attribute "unavailable"

The front end now implements support for the Clang attribute "unavailable" and
handles functions marked with that attribute as "deleted" functions.  Unlike
the "= delete" construct, the attribute is also accepted in C mode.


6/17/22  [EDGcpfe/23647]
Clang compatibility: Parameter-dependent enable_if attributes

Support for the Clang enable_if attribute has been improved so that most uses
involving parameter-dependent conditions are now handled as expected.  For
example:

  struct S {
    template <int N> S(const char (&rs)[N])
        __attribute((enable_if(__builtin_strlen(rs) == N-1, "Error!")));
  };
  S s("xyz");   // Previously an error because the enable_if condition
                // could not be constant-evaluated.  Now okay.

See also the entry for EDGcpfe/17738.


6/17/22  [EDGcpfe/25414]
GNU compatibility: "inline" asm-qualifier for asm statements

Since GCC 7.5.0, the "inline" asm-qualifier has been accepted on asm statements
and the front end now also accepts it.  For example:

  int main() {
    asm inline ("");
    asm __inline ("");
    return 0;
  }


6/16/22  [EDGcpfe/25352]
Multiple translation units: Spurious error with unnamed enums

When compiling multiple translation units where two different unnamed enums
were used to instantiate a template in the same TU, the front-end would
incorrectly attempt to make the two enums correspond to each other, resulting
in a spurious "had a different meaning" error.  For example, if the primary
TU contains (with an empty secondary TU):

  struct X {
    template<typename T> X(T);
  };
  void conv_func(X, X);
  enum { E1 };
  enum { E2 };
  template<typename>
  inline void func() {
    conv_func(E1, E2); // Triggers spurious "had a different meaning" error
  }
  auto fn = func<int>;

This is now fixed.


6/14/22  [EDGcpfe/25407]
Abort in scan_ctor_arguments on ellipsis constructor

Consider:

  struct S { S(...) = delete; };
  bool b = __is_constructible(S, double, int);

The ellipsis constructor is technically a trivial default constructor of S, and
the call to __is_constructible triggers the processing of a call to that
constructor with a synthesized argument list.  The fact that it is a trivial
default constructor previously triggered an internal error due to a spurious
assertion.  That behavior was a regression introduced in version 6.1 of the
front end by the changes for EDGcpfe/17387,EDGcpfe/21970,EDGcpfe/22117.  This
is now fixed.


6/13/22  [EDGcpfe/25395]
C++-generating back end: injected-class-name in partial specializations

The C++-generating back end previously put out uses of the
injected-class-name of a class template partial specialization using a
template-id, i.e., referring to the template with the template parameters
as a template argument list.  Although correct, some compilers issue
spurious errors for this usage, so the C++-generating back end has been
changed to refer to the injected-class-name using just the template name in
such cases.  For example:

  template<typename, typename> struct S;
  template<typename T> struct S<T, T> {
    S(S&) = default;  // Parameter previously generated as "::S<T, T>&"
  };


6/13/22  [EDGcpfe/25355]
GNU C++ compatibility: Compound assignment with pointer to void or function

Consider, in GNU C++ modes:

  void g(void *v, int (*f)(), int x) {
    v += x;  // Previously an error.  Now accepted when gnu_version >= 40400.
    f += x;  // Ditto.
  }

The front end already permitted ordinary addition and subtraction operations
on void* and pointer-to-function values in GNU C++ modes with gnu_version >=
40400 (see the entry for EDGcpfe/11204).  That now also applies to the
corresponding compound assignment operators.


6/13/22  [EDGcpfe/25389]
Spurious error in multi-translation unit mode with abi_tag attributes

In some cases, a spurious error (attribute "abi_tag" is missing in another
translation unit) had been issued in cases where the abi_tag attribute
was implicitly added during the mangling process.  Now fixed.


6/11/22  [EDGcpfe/25314]
Clang compatibility: __has_warning built-in macro

The front end now supports the clang __has_warning built-in macro, which
takes a character string literal designating a command-line warning option
as its argument.  Because there is no one-to-one correspondence between the
clang and front end diagnostics, the result of the macro is always 0.  For
example, with --clang:

  #if __has_warning("-Wformat")
    #error Will never trigger in the front end
  #endif


6/10/22  [EDGcpfe/22154,EDGcpfe/22884,EDGcpfe/25383]
Spurious ambiguity in C++17-mode cast

Consider:

  struct S;
  struct D {
    explicit D(S const&);
  };
  struct S {
    operator D() const = delete;
  };
  void g(S p) {
    static_cast<D>((S const)p);  // Previously ambiguous in C++17 mode.
  }                              // Now okay.

The changes for EDGcpfe/19122 introduced a regression in version 5.1 of the
front end causing the example above to diagnose a conversion ambiguity between
the converting constructor of D and the conversion function of S.  That is now
fixed.


6/9/22   [EDGcpfe/25385]
GNU/Clang compatibility: Mixed signed/unsigned vector operations

GCC and Clang accept mixed signed/unsigned vector operations and the front end
now emulates that behavior.  The result of such an operation is generally of
the unsigned vector type.  For compound assignment with such mixed types, the
left-hand side must be the unsigned vector type.  For example:

  typedef unsigned VU1 __attribute__ ((vector_size(4)));
  typedef int VS1 __attribute__ ((vector_size(4)));
  void g(VU1 uv, VS1 sv) {
    uv = uv + sv;  // Now okay.
    uv += sv;      // Ditto.
    sv += uv;      // Still an error.
  }


6/9/22   [EDGcpfe/25390]
Abort on constrained partial specialization of variadic class template

Consider:

  template<typename...>
    struct S { };
  template<typename T, typename U> requires requires { 0; }
    struct S<T, U> {};
  S<int> z;  // Previously triggered an abort.  Now okay.

This previously aborted with a null-pointer indirection (in types.c, function
is_instantiation_dependent_type_or_cli_generic_param) while testing whether the
constrained partial specialization is a match for S<int>.  Other similar cases
could result in spurious errors.  That is now fixed.


6/7/22   [EDGcpfe/25236]
__is_assignable with conversion operator template in source type

In cases where the __is_assignable type traits helper is invoked with a
target type that cannot be assigned a value of the source type and the
source type has a conversion operator template, the front end could produce
an instance of that conversion operator template with an error type as the
result type.  In configurations that mangle names, that could result in an
assertion failure in record_substitution_in_type.  For example, with
--gnu_version=110200 --c++14:

  template <int v> struct A {
    static constexpr bool val = v;
  };
  template<typename T> struct B : A<__is_constructible(T)> { };
  template <typename T, typename U>
  struct C : A<__is_assignable(T, U)> { };

  template <bool> using enable_if_t = int;

  struct D {
    template <typename T, typename = enable_if_t<B<T>::val>>
      operator T();
  };
  struct E {
    template <typename S, enable_if_t<C<int, S>::val> * = nullptr>
      void f(S);
  };

  D d;
  E e;
  void g() {
    e.f(d);
  }

This previously resulted in an instance of D::operator T() where T was an
error type.  This is now fixed.


6/6/22   [EDGcpfe/23303,EDGcpfe/23611,EDGcpfe/23668,EDGcpfe/23888,
          EDGcpfe/23931,EDGcpfe/23961,EDGcpfe/24603,EDGcpfe/24702,
          EDGcpfe/24722,EDGcpfe/24942,EDGcpfe/25107,EDGcpfe/25362]
Friend functions of class templates and noexcept specifiers

Consider:

  template<bool B> struct X {};
  template<bool B> struct S {
    X<B> x;
    friend constexpr bool operator==(S const &left, S const &right)
      noexcept(noexcept(left.x == right.x)) {  // Previously an error.
      return left.x == right.x;
    }
  };
  S<true> s;

The friend function of S<true> is not invoked.  The front end therefore doesn't
instantiate the body of that function and hence doesn't issue an error on the
return expression, even though that expression would produce an error due to
the lack of an operator== for X.  However, the front end previously did process
the operand of the noexcept specifier of the friend declaration as part of
instantiating S<true>, and that then triggered an error.  Now, the noexcept
specifier is not parsed until the function is used.


6/6/22   [EDGcpfe/25387]
IL display utility: dependent template-ids as qualifiers

In some cases, the IL display utility dropped template arguments from a
dependent template-id used as a qualifier.  This is now fixed.  For
example, with --c++11 --il_display:

  template<bool, typename T> using A = bool;

  template<typename T> int f(T);

  template <typename T> using B = decltype(f<T>(0));

  template <typename T, A<B<T>::v, bool> = true> void g(T&) { }

In the resulting IL display, references to B<T>::v omitted the "<T>"
template argument.  This is now fixed, and such references are now put out
as "B<T#(1,1)>::v", where "#(1,1)" are the template parameter coordinates
of "T".


6/2/22   [EDGcpfe/25382]
C++-generating back end: unbounded recursion with alias template

In some cases similar to those addressed by EDGcpfe/25091,EDGcpfe/25098
but more complex, the C++ generating back end could overflow the call stack
with an unbounded recursion when generating code involving alias templates
and/or typedef members of class templates.  This is now fixed.

The recursion in this particular case involved generation of class
qualifiers in a qualified name.  To facilitate diagnosis of potential future
problems of this sort, code has been added to gen_class_qualifier in
EXPENSIVE_CHECKING configurations to detect such unbounded recursion and
abort the compilation before stack exhaustion occurs.


6/2/22   [EDGcpfe/25073,EDGcpfe/25229,EDGcpfe/25356]
Spurious incomplete type error on template-dependent rvalue-reference cast

Consider:

  template<typename> struct S {
    template<typename T> auto f(S p) -> decltype(static_cast<T&&>(p));
      // Previously an error during the instantiation of S<int>.  Now okay.
  };
  template struct S<int>;

Previously, the front end issued an error about p being of incomplete type
S<int> in the cast static_cast<T&&>(p) even though the cast is to a dependent
type T&& (which isn't necessarily an rvalue reference type).  That is now
fixed.


6/1/22   [EDGcpfe/24480,EDGcpfe/24528,EDGcpfe/25359]
Assertion failure in deduce_class_template_args

Consider, in C++ 17 mode:

  template<typename T> struct W { W(T inner); };
  struct S {
    int f();
    template<typename ... T> void vf(T ... args) {
      W w{ f() };  // Previously aborted.  Now okay.
    }
  };

The declaration of variable w relies on class template argument deduction, but
the front end code intended to handle template-dependent initializations did
not cover all cases (including this one), which then resulted in failing an
assertion check in deduce_class_template_args (overload.c).  That caused an
internal error for the example above.  That problem is now fixed.


5/31/22  [EDGcpfe/25272]
Internal error in move_sses_out_of_class_if_otherwise_invalid in Clang/GNU mode

In some configurations with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
set to TRUE, certain cases involving static data members in class templates
could trigger an internal error in move_sses_out_of_class_if_otherwise_invalid
in Clang and GNU modes.  For example:

    template <int I> struct A {
      template <int> struct B {
        static constexpr unsigned get() { return 80U; }
      };
      static constexpr unsigned X = B<I>::get();
      template <int> struct C {
        static constexpr unsigned get() { return 40U; }
      };
      static constexpr unsigned Y = C<I>::get();
      static_assert(0 <= X * Y);
    };
    template struct A<0>;

During the instantiation of A<0>, this previously triggered the internal error.
That is now fixed.


5/31/22  [EDGcpfe/25241]
Position of eok_ref_indirect for captured-variable rewrite

Consider:

  void f() {
    int v;
    auto lm = [&]{
      v = 0;
    };
  }

The changes for EDGcpfe/24716 introduced a regression in version 6.3 of the
front end wrt. the position that is recorded for the eok_ref_indirect node that
is synthesized during the rewrite of the captured variable v in "v = 0".  Prior
to the changes of EDGcpfe/24716, that position was the position of v itself,
but after those changes it was the position of the "current token" at the time
of the rewrite (which in this case is the semicolon following "v = 0").  That
is now fixed: The position is now again that of v in "v = 0".


5/31/22  [EDGcpfe/24312,EDGcpfe/25381]
Abort after evaluation of lifetime-extended temporary with destructor

Consider in GNU C++11 mode:

  struct S {
    S(int) {}
    ~S() {}
  };
  void g() {
    ({ auto &&rr = S(1); rr; });  // Previously aborted due to memory
  }                               // corruption.  Now okay.

The front end attempts to constant-evaluate the GNU statement expression, but
fails to evaluate the initializer for rr in part because the destructor for S
is not constexpr.  This failure was not propagated to the enclosing evaluation,
however, causing the constexpr interpreter to continue evaluation even though
rr is not actually initialized.  That in turn resulted in memory corruption and
an abort.  This problem is now fixed.


5/31/22  [EDGcpfe/25334]
Mangling of requires expressions

When generating mangled names for code that uses concepts, neither of the
ABIs require mangling of a requires expression, but in some non-C-generating
configurations where MANGLE_ALL_NAMES is TRUE, an assertion failure had
occurred.  The assertion failure has been replaced by a discretionary error
(which is emitted only once per compilation).  For example (with --c++20):

  template<class T, T t> struct A {
    static constexpr T value = t;
  };
  template<class T, T t> constexpr T A<T, t>::value;
  template<bool t> using B = A<bool, t>;
  template<class T> struct S { };
  template<class T>
    requires __is_enum(T)
    struct S<T>
    : B<!requires(T t, void(*f)(int)) { f(t); }>
    { };


5/30/22  [EDGcpfe/25143]
Spurious errors with generic lambda nested in variadic template

The front end could produce spurious errors when a generic lambda using
"auto" parameters (instead of, or in addition to, an explicit template
parameter list) expands a parameter pack from a containing variadic
template.  For example, with --c++17:

  template<typename F, typename ... Args> struct Result {
    static F &fun;
    using X = decltype(fun(Args{}...));   // #1
    using type = int;
  };

  template<typename F, typename ... Args>
  typename Result<F, Args...>::type g(F, Args...) {
    return 42;
  }
  template<typename ... Ps>
  int v = g([](Ps..., auto)->int { return 42; }, 42, true);

  int r = v<int>;

The front end previously incorrectly reported on the line marked #1 that
no instance of the lambda matched the argument types.  This is now fixed.


5/27/22  [EDGcpfe/25210]
Microsoft C++ compatibility: postfix ++/-- overloading

Consider:

  struct S { S operator++(); };
  int main() {
    S s;
    s++;  // Ordinarily an error but previously accepted in all Microsoft C++
  }       // modes.  Now an error when microsoft_version >= 1900.

In standard C++, overloading a postfix operator ++ or -- requires an operator
that accepts an additional int argument (e.g., by adding "S operator++(int)"
as a member of struct S above).  Thus the example above is not valid C++.
However, earlier Microsoft compilers supported an old anachronism where a
prefix operator++/operator-- (i.e., one without the extra parameter) was also
considered for postfix operations and the front end emulated that in all
Microsoft modes.  Now that emulation is limited to Microsoft C++ modes with
microsoft_version < 1900 since MSVC 19.00 stopped supporting the anachronism.
  

5/27/22  [EDGcpfe/25364]
Rename "concat" macro to "EDG_CONCAT"

The "concat" macro (in basics.h) has been renamed to "EDG_CONCAT" to avoid
potential conflicts.


5/27/22  [EDGcpfe/25378]
GCC compatibility: GCC 9.5.0 builtins

The builtin_defs.h file has been updated to reflect the availability of
these new builtins when gnu_version == 90500.


5/26/22  [EDGcpfe/25374]
Support Windows paths on non-Windows systems

The latest work on modules has exposed a need for being able to handle Windows
paths on non-Windows systems, where WINDOWS_PATHS_ALLOWED and
BACKSLASH_IS_ALSO_DIR_SEPARATOR are typically set to FALSE.  The front end now
provides analogous booleans - windows_paths_allowed and
backslash_is_also_dir_separator that are used instead.  The configuration
macros now instead set the default value of these variables, rather than
directly controlling behavior.  This allows for dynamically changing the
behavior of routines that need to discriminate between Windows and non-Windows
paths (e.g., when handling a module file that was produced on Windows), while
still retaining original behavior elsewhere.


5/26/22  [EDGcpfe/25126,EDGcpfe/25318]
GNU compatibility: Layout-compatibility and pointer-interconvertibility traits

With the release of GCC 12.1.0, new builtins were added to support the
layout-compatibility and pointer-interconvertibility traits defined in
committee paper P0466R5.  The front end had previously provided support for
these traits in Microsoft mode (see the original Changes for EDGcpfe/22295) and
then reimplemented them (see the Changes entry for EDGcpfe/23851 et al.) and
have now implemented them (with different names and signatures) in GNU
emulation mode (when gnu_version >= 120100).  Some additional tweaks were also
made to the existing implementation to be more standard-conforming.


5/26/22  [EDGcpfe/25370]
GNU compatibility: Comparison of floating-point vector types

Consider in GNU C++14 mode:

  typedef long double __attribute((vector_size(16))) VLD;
  auto f(VLD x, VLD y) {
    return x < y;  // Error in some modes.
  }

The result type of "x < y" must be a vector of integer type whose element
types have the same width as the operand element types ("long double" in this
case).  Previously, if no such type exists, an internal error was triggered.
Now, an ordinary error is issued instead.


5/25/22  [EDGcpfe/25251]
Abort with local requires-expression with parameters

In some configurations and modes, the front end could abort with an internal
error in push_or_repush_object_lifetime (il.c, "parent is in file scope memory,
 new olp is not").  For example:

  struct V { unsigned n; };
  struct X {
    template<typename T>
    static constexpr void f() {
      if constexpr (requires (const T &t) { V(t); }) {  // Previously sometimes
        return;                                         // aborted.  Now okay.
      }
    }
  };

That is now fixed.


5/23/22  [EDGcpfe/25225]
Microsoft C++ compatibility: By-value passing of const class object

Consider:

  struct R {};
  struct S {
    S(S&);
    operator const R() const;
  };
  int  g(S);         // (1)
  int  g(R const&);  // (2)
  extern S const sc;
  int r = g(sc);  // Normally an error.  Now okay in Microsoft C++ modes.

Ordinarily, this is an error because candidate (1) is considered by standard
C++ to be an exact match for the argument sc of type S const.  However, passing
sc that way is invalid because the copy constructor of S takes a reference to
non-const S.  Microsoft compilers, however, take this constructor mismatch into
account during overload resolution, thus discarding candidate (1).  Candidate
(2) is called instead (it matches via a user-defined conversion).  The front
end now emulates that behavior in Microsoft mode.


5/18/22  [EDGcpfe/22662,EDGcpfe/23699,EDGcpfe/25336]
GNU compatibility: Mixed scalar-vector operations

In GNU modes the front end accepted mixed scalar-vector operations only if the
vector element type matched the scalar type exactly.  Now, such operations are
also accepted if those types differ.  For example:

  typedef float V4F __attribute__((vector_size(16)));
  float g(V5F rgb) {
    rgb *= 255;  // Previously an error.  Now okay.
    return rgb[0];
  }


5/17/22  [EDGcpfe/25341]
Microsoft compatibility: Copy-elision after user-defined conversion

Consider in C++17 mode:

  struct D {
    D() = default;
    D(D const&) = delete;
  };
  struct S { operator D(); };
  D d(S{});  // Previously an error in Microsoft mode.  Now okay if
             // microsoft_version >= 1933.

Earlier versions of the Microsoft compiler did not perform copy elision when
transferring the result of the S::operator D() conversion to d, and the front
end emulated that behavior.  However, MSVC 19.33 does perform that elision and
the front end now matches that when microsoft_version >= 1933.


5/17/22  [EDGcpfe/25338]
Abort in determine_function_viability

In some complex cases involving inherited constructors and default arguments
the front end could abort in determine_function_viability with an internal
error ("no param, no default arg", in overload.c).  That is now fixed.


5/17/22  [EDGcpfe/24818]
Access checking with using-declarations

In some cases, the front end incorrectly handled access checking for class
members in inheritance hierarchies containing member using-declarations,
either reporting spurious access errors or failing to report legitimate
access violations.  This is now fixed.  For example:

  struct B1 { int i; };
  struct B2 : B1 {
    friend void f();
  private:
    using B1::i;
  };
  struct D : B2 { };
  struct E : D { };
  struct Ptr {
    E* operator->();
  };
  Ptr p;
  void f() {
    p->i;   // Previously incorrectly reported access error for "i"
  }


5/16/22  [EDGcpfe/25323]
Use of out-of-scope variable in scan_expr_list

The function scan_functional_notation_type_conversion sometimes set up an
expression stack pointer to a block-scope variable (of type a_decl_parse_state)
and later caused that pointer to be dereferenced in scan_expr_list after
leaving the block scope in which that variable was defined.  This problem
(discovered by a static analysis tool) resulted in undefined behavior.  That is
now fixed.


5/13/22  [EDGcpfe/25322]
Constant-evaluation of a constexpr variable with mutable member

Consider (in C++14 mode):

  struct S {
    mutable int x;
    int y[100];
    int z;
  };
  constexpr S s = { 1, 2, 3 };
  int main() {
    if (s.y != 0) return 1;
  }

The front end attempts to constant-evaluate s.y, but the handling of the
mutable member x when loading the value of s for that expression contained a
bug that subsequently resulted in an access beyond the bounds of the
representation of the value of s in the interpreter.  That could result in
arbitrary results and/or aborts.  That bug is now fixed.


5/13/22  [EDGcpfe/25311,EDGcpfe/25328]
GNU C++11 compatibility: __extension__ prefix for member using-declaration

In GNU C++11 mode, the front end now accepts the __extension__ prefix for
member using-declarations.  For example:

  struct S {
    __extension__ using T = int;  // Previously an error.  Now accepted in
  };                              // GNU C++11 modes.


5/13/22  [EDGcpfe/25324]
Performance issue due to checking of duplicate friendship

Consider:

  template<typename T> struct S {
    template<typename> friend class S;
  };

Every instantiation S<X> of S is added as a befriending class to every other
instantiation of S.  That in itself is a quadratic process, but an additional
inner loop checking for duplicate friendship actually resulted in a cubic
process overall.  In situations with many instances of S, this resulted in
prohibitive processing times.  A change was made to avoid the cubic process;
we hope to address the quadratic process in the future.


5/12/22  [EDGcpfe/25298]
GNU compatibility: Additional __float128 builtins

Previously the tool that created the builtin table had eliminated all builtins
whose signature contained a reference to a __float128 type.  That restriction
has been eliminated and as a result additional builtins have been enabled.


5/12/22  [EDGcpfe/25292]
GNU compatibility: Incorporate GCC 12.1.0 builtins

New builtin function signatures from GCC 12.1.0 have been incorporated.
In conjunction with this change, builtins that use the _Float16 type have
been mapped to a 16-bit floating-point type (i.e., binary16).  The _Float16
type has not been implemented yet.


5/11/22  [EDGcpfe/25075]
C++23: auto(x) and auto {x}

In C++23 mode, the front end now accepts functional-style casts to type "auto",
which primarily has the effect of converting glvalues to prvalues, including
decaying array and function glvalues to pointer prvalues.  For example:

  struct S {};
  S& g();
  int f(S&);  // (1)
  int f(S&&); // (2)
  int x = f(g()),        // Calls (1).
      y = f(auto(g()));  // Calls (2), materializing a temporary.

This feature was added to C++23 through the standardization committee's
paper P0849R8.  The macro __cpp_auto_cast is defined with the value 202110L
when the feature is enabled.


5/10/22  [EDGcpfe/24436,EDGcpfe/25294]
Implicit closure conversion in conditional operator in Microsoft modes

The changes for EDGcpfe/20909,EDGcpfe/24300,EDGcpfe/24540 failed to handle
conditional operators.  That caused the following example to fail in Microsoft
C++ modes:

  auto f1 = [](int a, int b) { return a < b; };
  auto f2 = [](int a, int b) { return a > b; };
  auto r = true ? f1 : f2;  // Previously ambiguous in Microsoft C++ modes.
                            // Now okay.

That is now fixed.


5/10/22  [EDGcpfe/25282]
Implicit function declarations and source sequence entries (IL CHANGE)

In C mode, when a function is implicitly declared because of an apparent call,
the front end created a source sequence entry for that declaration and marked
that entry with the "implicit_decl" flag to make sure the entry was otherwise
ignored (in configurations with GENERATE_SOURCE_SEQUENCE_LISTS).  However, that
still could result in surprises (in part because the source sequence entry
could appear among entries associated with an expression).  Now, the front end
no longer generates that entry at all since it does not actually represent a
source-level declaration.  That is an IL CHANGE.


5/10/22  [EDGcpfe/25295]
Type trait helpers and requires-clauses

Consider in C++20 mode:

  template<typename T> T f() requires __is_class(T); // Previously an error.
                                                     // Now okay.

Previously, this elicited an error because "__is_class(T)" is not a so-called
"primary expression" (as required by the standard).  However, GCC and Clang
both accept such cases as an extension and the front end now does so also in
its nonstrict modes.


5/9/22   [EDGcpfe/25284]
C++-generating back end: dependent opaque enumeration values as non-type
template arguments

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end put out dependent
values of an opaque enumeration type using a cast to the enumeration type.
This unnecessary cast could interfere with template argument deduction.
For example, with --c++11:

  enum E : int;
  template<E> struct A { };

  template<typename T> struct B {
    template<E e> void f(A<e>) { }  // Previously generated as A<(E)e>
  };

  void g() {
    B<int> bi;
    bi.f(A<(E)0>{});  // Previously failed because of cast in f's declaration
  }


5/9/22   [EDGcpfe/25287]
Inherited initializer list constructor templates

Consider:

  #include <initializer_list>
  template<typename U> struct B {
    template<typename T> B(std::initializer_list<T>, U = U{});
  };
  template<typename T> struct D: B<T> {
    using B<T>::B;
    D();
  };
  D<int> d{1, 2, 3};  // Previously an error.  Now okay.

Previously, the front end failed to see that an initializer list constructor is
being inherited by D<int>, and as a result the initializer-list initialization
was not successfully resolved and a spurious error resulted.  That is now fixed
and the example is now accepted.


5/6/22   [EDGcpfe/25281]
Very large macro definitions

The front end did not correctly handle extremely large macro definitions
(several million bytes or more, at a minimum, depending on the exact
contents of the replacement text).  Depending on the definition and the
configuration, the results could range from incorrect macro expansions to
assertion failures.  This is now fixed, with the macro definition size
limited only by available memory.


5/6/22   [EDGcpfe/25245]
Clang compatibility: Nullability qualifiers on array parameters

The changes for EDGcpfe/16527,EDGcpfe/16916 added support for "nullability
qualifiers" on pointer types in Clang modes.  However, Clang also permits these
in array parameter declarators.  For example:

  void f(int [_Nonnull]) {}  // Previously an error.  Now okay in Clang modes.

That is now also emulated by the front end in Clang modes.


5/6/22   [EDGcpfe/25242]
Spurious error on constant-evaluation access of derivation with no data

Consider:

  template <typename T> constexpr void g(T) {}
  template<typename T> struct B {
    constexpr B() : c{} {
      g(*static_cast<T*>(this));  // (1)
    }
    char c;
  };
  struct D : B<D> {};
  constexpr D d = D{};  // Previously an error.  Now okay.

Previously, this triggered an error because the evaluation of line (1) required
the copying of a class value of type D that was not technically completely
initialized (since the constructor of D itself had not completed).  Now, such
code is accepted because D has no actual data of its own.


5/6/22   [EDGcpfe/21959,EDGcpfe/25279]
Qualified unnamed bit field types

The resolution of Core issue 2229 has made const/volatile-qualified types
invalid for unnamed bit fields.  Most compilers appear not to enforce this
constraint, but Clang does.  The front end now issues a discretionary error
when the constraint is violated in strict mode or in Clang modes with
clang_version >= 70000.  In other modes, a warning is issued.  For example:

  struct S {
    int const : 5;  // Now a warning or discretionary error, depending on
  };                // the mode.


5/6/22   [EDGcpfe/25283]
Microsoft-mode braced default argument

Consider in C++20:

  void f(auto p, int q = {}) {}  // Now also accepted in Microsoft C++20 mode.

The changes for EDGcpfe/22610,EDGcpfe/24792,EDGcpfe/25267 eliminated an abort
on the default argument and caused the example to be accepted is default C++20
mode.  However, in Microsoft C++20 mode, a spurious error was issued.  That is
now also fixed.


5/5/22   [EDGcpfe/25275]
Comparison against NaN values

Consider (in GNU C++ modes):

  constexpr float g() { return __builtin_nan(""); }
  static_assert(g() != 0.0f, "");  // Previously an error.  Now okay.

Previously, the front end treated any comparison against a not-a-number (NaN)
constant as non-constant, and thus the static_assert above failed due to its
condition not being constant.  Now, comparisons against non-NaN values are
always treated as not-equal and the example above is accepted.


5/5/22   [EDGcpfe/25276]
Incorrect constant-evaluation of vector-fill operation

Consider, in GNU C++ mode:

  typedef short __attribute__((vector_size(2))) VS1;
  VS1 S1, S2 = S1 + 1;

The literal 1 in "S1 + 1" is represented as a vector-fill operation and gets
folded by the constant-evaluation interpreter.  However, the interpreter did
not use a correct vector length for that operation, which resulted in somewhat
arbitrary constant values appearing in the IL.  That is now fixed.


5/5/22   [EDGcpfe/25271]
Spurious constant-evaluation error on generic GNU-mode initializer

Consider, in GNU C++14 mode:

  struct S {
    char c;
    constexpr S() : c{'a'} {}
    constexpr S(char c) : c{c} {}
  };
  template<typename> constexpr void g() {
    constexpr S sa[]{'a'};              // (1)
    static_assert(sa[0].a == 'a', "");  // Previously an error.  Now okay.
  }

In GNU C++ mode, the initializer in (1) is not matched to the destination type.
That makes it impossible for the constant-evaluator to correctly evaluate the
static_assert expression that follows, and previously that resulted in a
spurious assertion failure.  Now, the static_assert condition is essentially
treated as dependent during the prototype instantiation of g() and thus no
error is emitted.


5/5/22   [EDGcpfe/24382,EDGcpfe/25266]
GNU compatibility: Enable VLAs with --ms_extensions

A change has been made to enable VLAs in GNU and Clang emulation modes when
using --ms_extensions.


5/4/22   [EDGcpfe/25226]
Abort or spurious error on Microsoft-mode new-expression

Consider in Microsoft C++ mode:

  struct S {
    union {
      int const ic ;
      int i;
    } u;
  };
  auto p = new S;  // Previously triggered an internal error.  Now okay.

Previously, this aborted with an internal error in expr.c (in function
prep_new_object_init_no_initializer, with message "scan_new_operator: non-POD
class has neither actual nor assumed ctor").  That is now fixed.  In some other
cases, the problem manifested as a spurious error instead of an internal error.


5/4/22   [EDGcpfe/25082]
C++-generating back end: template parameter names with generic nested lambda

In configurations in which the definition of a template is generated from
the prototype instantiation IL, the presence of a nested generic lambda
with an explicit template parameter list could cause subsequent uses of the
template parameters of the containing template to be put out as the names
of the corresponding parameters of the nested generic lambda instead of
their correct names.  This is now fixed.  For example, with --c++20
--parse_templates:

  template <typename T> bool test = true;
  template <typename U> constexpr void f() {
    auto l = []<typename LT>() {};
    if constexpr (test<U>);   // Previously generated as test<LT>
  }


5/3/22   [EDGcpfe/23030,EDGcpfe/25062,EDGcpfe/25269]
Failure to fold __builtin_choose_expr expression

Consider in GNU C mode:

  void g(void) {
    static char buf[__builtin_choose_expr(1, 2, 3)];  // Previously an error.
  }                                                   // Now okay.

The front end previously failed to fold the call to __builtin_choose_expr,
which in turn triggered an error.  That is now fixed.


5/3/22   [EDGcpfe/22610,EDGcpfe/24792,EDGcpfe/25267]
Abort on default argument for template declared with abbreviated syntax

The front end previously aborted (null pointer indirection in function
prescan_function_default_arg_expr, in class_decl.c) when processing a default
argument for a function template declared with abbreviated syntax.  For example
(in C++20 mode):

  void f(auto p, int q = {}) {}  // Previously aborted.  Now okay.

That is now fixed.


5/2/22   [EDGcpfe/25234]
GNU C++ compatibility: Relaxed checking for abstract class types

C++20 relaxed the rules requiring that a function return type or parameter type
be not abstract (see the entry for EDGcpfe/20032,EDGcpfe/21890).  However, GCC
and Clang did not yet implement those revised rules.  GCC 11.x, however, has
since implemented that relaxation for return types and the front end now
emulates that behavior when gnu_version >= 110000.


4/28/22  [EDGcpfe/25256]
C++-generating back end: missing qualification for scoped enumerators

In some cases in which the source code refers to a scoped enumerator, the
C++-generating back end omitted the necessary enumeration name qualifier in
the generated code.  This is now fixed.  For example, with --c++20:

  enum class E { z, o };
  template<typename> struct A {
    template<E> int h();
  };
  template<typename T> struct B : A<T> {
    void g() {
      int j = this->template h<E::z>();  // Previously omitted "E::"
    }
  };


4/26/22  [EDGcpfe/19782]
Assertion failure in walk_entry.h

In certain configurations and with certain command-line options, a source
file in which an explicit argument is passed to a pointer or reference
non-type template argument, the front end could abort with an assertion
failure in walk_entry.h.  This is now fixed.


4/26/22  [EDGcpfe/19783]
Pointers to subobjects as nontype template arguments for function templates

The C++ Standard requires that the argument for a nontype template
parameter of type pointer or reference to object must designate a complete
object.  The front end previously failed to enforce that rule for pointers
in explicit template arguments for function templates.  This is now fixed.
For example, with --c++11:

  struct B { };
  struct D : B {} d;
  template <const B*> void f();
  void g() {
    constexpr B *bp = &d;
    f<bp>();  // Previously incorrectly accepted, now an error
  }


4/25/22  [EDGcpfe/25074,EDGcpfe/25227]
Value of __cpp_concepts feature-test macro

As specified in WG21 committee document P2493R0, the value of the
__cpp_concepts feature test macro has been changed to 202002L to reflect
implementation of the features in document P0848R3 ("Conditionally Trivial
Special Member Functions").


4/24/22  [EDGcpfe/25232]
Performance with large number of splices in a single logical source line

The front end previously exhibited poor performance when processing a file
in which a single logical source line consists of many (more than a few
thousand) physical lines spliced together.  This is now fixed.


4/22/22  [EDGcpfe/25204]
Clang compatibility: __builtin_elementwise_* and __builtin_reduce_*

The new builtins added by EDGcpfe/25178 for clang 14.0.0 compatibility also
introduced some new clang vector builtins (i.e., __builtin_elementwise_* and
__builtin_reduce_*) that required some additional changes to the front end.


4/15/22  [EDGcpfe/25213]
Nonreal class template instantiations and virtual function override ambiguities

The function report_virtual_function_ambiguities was previously invoked for
nonreal class template instantiations (such as prototype instantiations).  This
was not needed and could in some cases involving template parameter packs
result in invalid memory accesses.  The function is now only called for
nontemplate classes and for real class template instantiations.


4/15/22  [EDGcpfe/25087]
Inheriting constructors with default arguments

The changes for EDGcpfe/24210 in version 6.3 introduced a regression by
deferring the propagation of inherited default arguments: In some complex
cases, that deferral went past the point at which the default arguments are
needed for the resolution of a constructor invocation.  That is now fixed.


4/12/22  [EDGcpfe/25200]
Omitted "template" keyword in template type parameter default argument

The front end previously always interpreted a "<" following a dependent
qualified name appearing in a template type parameter default argument as
the "less than" operator when the "template" keyword does not appear.  MSVC
and g++, however, interpret it as the beginning of a template argument
list.  The front end now does the same in the corresponding emulation
modes.  In the following example, the front end previously issued errors
with --microsoft (with both --ms_permissive and --no_ms_permissive) and
--g++ but now accepts it:

  template<typename U> struct H {
      template <typename T = int> struct A { };
  };
  // "H<V::A<>" was previously considered an error in Microsoft and g++ modes:
  template <typename V, class Q = typename H<V>::A<> > struct C { };


4/8/22   [EDGcpfe/25209]
Handling of uninitialized aggregate class objects in C++20 constant evaluation

Consider:

  struct S { int x, y; };
  constexpr S xchange(S p) {
    S r;  // Uninitialized (okay in C++20).
    r.x = p.y;
    r.y = p.x;
    return r;
  }
  constexpr S s = xchange(S{ 1, 2 });  // Previously an error.  Now okay
                                       // in C++20 mode.

Prior to C++20, local variable declarations in constexpr functions had to
include an initializer.  In C++20 that is no longer required, but for aggregate
class variables the front end failed to treat such variables as initialized
even if none of their subobjects remain uninitialized.  In the example
above that meant an error was issued because the "return r;" statement was
mistakenly thought to return an uninitialized object.  That is now fixed.


4/7/22   [EDGcpfe/25208,EDGcpfe/15949]
Removal of enum "tags" in favor of enums with fixed underlying types

The front end used an enum "tag" paradigm where most enumerations were declared
with a tag + typedef combination, where the enumeration itself contained the
"tags", but data structures used the associated typedef.  This was necessary
prior to the switch to C++11 (in version 6.0) as there was no way to control
the underlying type of the enumeration.  This paradigm has been eliminated in
favor of enums with fixed underlying types for increased type safety.
Redundant casts to the enum have been retained to avoid unnecessary merge
conflicts, and the following additional types have been removed, in addition to
the global renaming of all "tag" enums (replacements in parentheses):

 - a_byte_attribute_kind     (an_attribute_kind)
 - a_byte_attribute_family   (an_attribute_family)
 - a_byte_attribute_location (an_attribute_location)
 - a_byte_il_entry_kind      (an_il_entry_kind)
 - a_small_token_kind        (a_token_kind)
 - a_decl_modifier           (a_decl_modifier_set)

In addition, the TYPE_FOR_A_SMALL_TOKEN_KIND configuration macro has been
removed and the default setting of NUM_BITS_FOR_NAME_LINKAGE has been increased
from 2 to 3.  A new configuration macro - NUM_BITS_FOR_EXPR_NODE_KIND - has
been added, as some compilers need an_expr_node_kind declared in a special way
to be able to achieve a better layout of the an_expr_node struct.


4/7/22   [EDGcpfe/25201]
Variable template "referenced" flag

The a_template IL entry and its prototype instantiation were previously not
marked as having been referenced when an instance of a variable template is
referenced.  This failure resulted in spurious "declared but never
referenced" warnings for static data member templates appearing in unnamed
namespaces.  The "referenced" flag for these IL entries is now correctly
maintained.  For example:

  namespace {
  struct S {
    template<typename T> static constexpr auto v = true;
  };
  static_assert(S::v<int>, "");  // Previously did not suppress the
                                 // "never referenced" warning for S::v<T>
  }


4/6/22   [EDGcpfe/20055,EDGcpfe/20157,EDGcpfe/20168,EDGcpfe/20170,
          EDGcpfe/23813,EDGcpfe/24944]
Implicit deduction guides for nested class templates

Consider (in C++17 mode):

  template<typename T> struct X {
    template<typename U> struct N { N(U); };
    X() {
      N v(0);  // Previously an error.  Now okay.
    }
  };
  struct S {};
  X<S> xs;

A strict reading of the C++ standard makes the use of class template argument
deduction for the declaration "N v(0);" invalid.  However, core issue 2471 was
opened to review that and the committee's core working group appear inclined
to make that example valid.  Furthermore, GCC already accepts such examples.
The front end also accepts the case (in C++17 and later modes); previously, it
issued an error due to a failure to construct the associated implicit deduction
guide.


4/1/22   [EDGcpfe/24640,EDGcpfe/25019]
Incorrect handling of reference binding in SFINAE constant-expressions

The changes for EDGcpfe/17211 introduced a regression in Microsoft mode for
certain complex situations involving binding a reference in a constant-
expression context during template deduction (SFINAE).  The problem occurred
in particular in some uses of the Boost.asio library.  It is now fixed.


4/1/22   [EDGcpfe/23023,EDGcpfe/24612]
Microsoft compatibility: Default initializers for anonymous union members

Consider:

  struct S { S() {} };
  class C {
    union { S s{}; };
  } c;  // Now valid in Microsoft C++ modes with microsoft_version >= 1927.

The default initializer for anonymous union member C::s makes this valid, but
earlier versions of the Microsoft compiler did not accept this case.  MSVC
19.27, however, fixed that and the front end now emulates that behavior in
corresponding Microsoft modes (i.e., when microsoft_version >= 1927).


4/1/22   [EDGcpfe/25103]
Abort after lookup ambiguity for certain operators

Consider:

  struct B1 {
    bool operator==(B1 const&) const;
  };
  struct B2 {
    bool operator==(B2 const&) const;
  };
  struct D: B1, B2 {} d;
  bool operator==(D const&, D const&);
  auto r = d == d;  // Previously aborted.  Now an ambiguity error.

The processing of "d == d" previously resulted in a segmentation fault in
reverse_binary_match_descriptions (overload.c).  That is now fixed.  The front
end now treats this case as an ambiguity because the lookup of operator== in
D is ambiguous.  Although that appears to be what the standard requires, the
standard wording is not 100% clear about it, and some implementations behave
differently.  The issue has been raised with the C++ standardization committee.


3/31/22  [EDGcpfe/25194]
C++-generating back end: parenthesized expressions in "for" statements

The C++-generating back end previously emitted the condition and increment
expressions of a "for" statement enclosed in redundant parentheses when
they are operator-notation function calls.  Although correct, these
parentheses interfered with some uses of the generated code, so they are
now suppressed.  For example:

  struct I {
    void operator++();
    bool operator<(const I&);
  };
  struct S {
    I& begin();
    I& end();
  } s;
  void f() {
    for (I i = s.begin();
         i < s.end();     // Previously generated as (i < s.end())
         ++i)             // Previously generated as (++i)
      { }
  }


3/31/22  [EDGcpfe/25180]
Constant-evaluation of pointer-to-member values

The constexpr interpreter previously did not always correctly reconstruct
pointer-to-member a_constant entries after computing their values.  This became
more prominent after the changes for EDGcpfe/22472,EDGcpfe/23539,EDGcpfe/23840
in version 6.3 (which caused more pointer-to-member expressions to be evaluated
successfully) and thus resulted in regressions in that version of the front
end.  For example:

  struct A { int m; };
  struct B : A {};
  struct C {
    virtual ~C();
  };
  struct D : C, B {
    void mf(int);
  };
 int g(void (B::*)());
 int r = g( (void(B::*)()) (void(B::*)(int)) &D::mf);

The casts in the argument to the call to g were evaluated by the interpreter,
but the latter failed to record the "casting_base_class" field in the
a_constant entry representing the evaluation's final result.  That is now
fixed.


3/31/22  [EDGcpfe/24925]
Unions with const members and default constructibility

Consider:

  template<typename T> struct DefaultConstructible {
    template<typename U, typename = decltype(U())> static char test(int);
    template<typename> static int test(...);
    static constexpr bool value = sizeof(test<T>(0)) == sizeof(char);
  };
  struct S {
    union {
      const int n;
    } u;
  };
  static_assert(!DefaultConstructible<S>::value, "Error");
                                          // Previously failed.  Now okay.

Struct S is not default-constructible because it contains a union with members
that are all "const" and are not const-default-constructible.  The front end
previously failed to establish that, in turn causing the static_assert in the
example to fail.  That is now fixed.


3/31/22  [EDGcpfe/25158]
Assertion failure in lower_question_operand

The changes for EDGcpfe/20535,EDGcpfe/23410 (in version 6.2) introduced
a couple of regressions (one in lower_question_operand) for cases like the
ones below.  Now fixed:

  const int a = 1;
  const int b = 2;
  void f(bool x) {
    x ? (*((volatile int*)0) = a) : b;
    0 ? (*((volatile int*)0) = a) : b;
    1 ? (*((volatile int*)0) = a) : b;
  }


3/31/22  [EDGcpfe/22219]
Concatenation involving UTF-encoded and ordinary string literals

Consider a source file with UTF-8 encoding like the following:

  char16_t s[] = u"X" "Y";

where X and Y represent Unicode characters whose UTF-8 encoding requires
more than one byte.  For the result of the concatenation, the front end
previously produced a string in which the first character was the correct
UTF-16 representation of X but the succeeding characters were simply the
bytes of the UTF-8 encoding of Y, each widened to 16 bits.  This is now
fixed, resulting in a string equivalent to u"XY".


3/30/22  [EDGcpfe/24287]
Concatenation involving UTF-8 string literals, function name identifiers

According to the C++ Standard, it is permitted to concatenate a string
literal with a literal prefix with an unprefixed string literal, in either
order; the result has the type and value implied by the prefixed literal.
The front end previously reported spurious errors, however, in C++20 mode
when concatenating a UTF-8 string literal with an unprefixed literal,
although the same code compiled successfully in C++17 mode.  This
difference resulted from the fact that in C++17, a UTF-8 string literal had
the same character type as an unprefixed string literal, while in C++20 the
character type of a UTF-8 string literal is char8_t, a distinct type.  This
is now fixed.  For example, with --c++20:

  auto s1 = u8"a" "bc";  // Previously an error, now okay (same as u8"abc"
                         // with literal type "array of 4 const char8_t")
  auto s2 = "x" u8"yz";  // Previously an error, now okay (same as u8"xyz"
                         // with literal type "array of 4 const char8_t")

In addition, in Microsoft mode, the function name identifiers such as
__FUNCTION__ can be concatenated with string literals.  In the IL, the
resulting string constant previously had an incorrect value for the field
variant.string.literal_kind.  This is now fixed.  For example, with
--microsoft --c++20:

  void f() {
    auto nm = __FUNCTION__ ".';   // Equivalent to "f."
  }

Finally, the IL display output previously failed to include the value of
the variant.string.literal_kind field.  This has now been added, with the
literal kind displayed in human-readable form.


3/29/22  [EDGcpfe/24991]
Assertion failure in get_enclosing_template_params_and_args

In certain complex cases involving nontype template arguments that are
functions with parameter packs the front end could abort with a failed
assertion in get_enclosing_template_params_and_args.  This is now fixed.


3/29/22  [EDGcpfe/24578]
GNU/Clang compatibility: __is_trivial

Consider:

  struct B {
    B() = default;
    B(int = 0);
  };
  struct D: B {};
  static_assert(!__is_trivial(D), "Unexpected!");  // Now an error in
                                                   // GNU/Clang mode.

D is not a "trivial class" because its default constructor is deleted (because
the underlying default construction of B is ambiguous).  However, Clang and GCC
do no implement that rule yet (the definition of "trivial class" has changed
over time).  The front end now emulates GCC and Clang in the corresponding
modes.


3/29/22  [EDGcpfe/24572]
Out-of-range C UTF-16 character constants

In the C11 and later standards, a UTF-16 character constant that cannot be
represented in a single 16-bit code unit has an implementation-defined
value, typically the low-order 16 bits.  The front end, however, previously
followed the C++ rules, in which such a character literal is an error.
This is now fixed.  For example, with --c11:

  int c = u'\x1f680';  // Previously an error, now okay


3/26/22  [EDGcpfe/25178]
Clang compatibility: Incorporate clang 14.0.0 builtins

New builtin function signatures from clang 14.0.0 have been incorporated.
In conjunction with this change, builtins that use the _Float16 type have
been mapped to a 16-bit floating-point type (i.e., binary16) as are builtins
with the __fp16 type.


3/25/22  [EDGcpfe/25168]
Concatenation and inert macros

According to the C and C++ Standards, a macro name appearing inside the
expansion of an invocation of that macro is not a recursive invocation of
the macro.  However, when the macro name appears as the last token in the
replacement and that replacement is the right-hand operand of the ##
concatenation operator, the front end incorrectly invoked the macro a
second time.  This is now fixed.  For example, with --c++11:

  #define A x.y.A
  #define B(...) C(__VA_ARGS__)
  #define C(z, ...) f(z ## __VA_ARGS__)

  void g() {
    B(i, e->A);  // Should be "f(ie ->x . y . A", previously expanded to
                 // "f(ie ->x . y . x . y . A"
  }


3/25/22  [EDGcpfe/25153]
Lowering of <=> operator applied to pointer operands

Consider:

  #include <compare>
  void *p1 = nullptr, *p2 = nullptr;
  auto r = p1 <=> p2;  // Previously lowered to just an equality check.

Previously, the front end incorrectly lowered the spaceship applied to all
pointer operands to just an equality check, instead of handling object pointers
(including void*) as a three-way comparison.  That is now fixed.


5/23/22  [EDGcpfe/25166]
C++-generating back end: assertion failure with lambda variable

The C++-generating back end sometimes aborted with an assertion failure in
gen_paren_or_brace_dynamic_init when a variable is initialized with a
lambda expression.  This is now fixed.  For example, with --c++11:

  void f() {
    int i;
    auto l{[&i]{}};  // Previously aborted
  }


3/23/22  [EDGcpfe/24912]
Spurious deduction match

Consider:

  template<typename ... Ts> struct X {
    static_assert(sizeof...(Ts) != 1);
  };
  template<typename T> int g(T);
  template<typename E> int g(X<E>);  // (1)
  X<int, int> xii;
  int r = g(xii);  // Previously triggered an error.  Now okay.

Previously, the front end's deduction process for call g(xii) incorrectly
matched xii with X<E>, thus causing the instantiation of X<int>, which in turn
leads to a failing static assert.  This was a regression introduced by the
changes for EDGcpfe/17558,EDGcpfe/19264 in version 5.0.  That is now fixed.


3/21/22  [EDGcpfe/24352,EDGcpfe/24727]
Spurious ambiguity error on conversion function template

Consider:

  template<typename...> struct X {};
  template<typename T, typename U> struct X<T, U> {
    template<typename T> operator X<T>() = delete;
    template<typename T> operator X<T>() const;
    template<typename T> X<T> f() const {
      return operator X<T>();  // (1)
    }
  };
  X<int, char> xic;
  X<int> xi = xic.f<int>();

Previously, the instantiation of line (1) resulted in a spurious ambiguity
error regarding the conversion function template.  That is now fixed.


3/21/22  [EDGcpfe/23960]
Explicit template argument list in overloaded nontype template argument to an
rvalue reference parameter pack

The front end previously issued a spurious error when an explicit template
argument list is used to select one member of an overload set as a nontype
template argument for a template parameter pack that is an rvalue
reference.  This is now fixed.  For example:

  template<typename... _Ts> void f(_Ts&& ...);

  int g(int);
  template<int> int g(int);

  void h() {
    f(g<0>);  // selects template g from overload set; previously an error
  }


3/20/22  [EDGcpfe/25051]
C++-generating back end: dependent function non-type template arguments

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end could add an "&" to
a dependent function used as a non-type template argument, even when there
is no "&" in the original source.  This is now fixed.  For example:

  template<typename T, T> struct b;
  template<typename T> struct c {
    static T f() {
      b<T, f> d;  // Previously generated as b<T, &f>
    }
  };


3/18/22  [EDGcpfe/25125]
Microsoft compatibility: Enabling additional features

Two changes have been made to be more compatible with later versions of
Visual Studio.  Two C++23 features ("Deducing this" -- see EDGcpfe/24781, and
"if consteval" -- see EDGcpfe/24773) are now enabled when --ms_c++latest is
specified and microsoft_version >= 1932.

Additionally, a new command-line option, --[no_]ms_stdc, is introduced to
emulate the /Zc:__STDC__ Visual Studio command-line option.  When --ms_stdc
is specified, the __STDC__ macro is defined to the value 1 (and is left unset
when --no_ms_stdc is specified).  See also the DEFINE_STDC_IN_MICROSOFT_MODE
configuration macro for the default behavior.


3/18/22  [EDGcpfe/23943]
Assertion failure in type_is_lambda_in_default_argument

An assertion failure (in type_is_lambda_in_default_argument) had occurred
during the mangling of some lambdas that occur in default arguments and is now
fixed.  For example (with --c++14):

  struct B {
    virtual ~B() = default;
  };
  template <typename T> struct D : B { };
  template <typename T> D<T> f(const T&) {
    return D<T>();
  }
  void foo(const B& xxx = f([](){})) {}


3/17/22  [EDGcpfe/23962]
Member functions in unnamed namespaces referenced in unevaluated contexts

The front end previously issued a "declared but never referenced" warning
for class member functions (but not for nonmember functions) declared in an
unnamed namespace and referenced only in an unevaluated context.  This is
now fixed, and member functions are treated like nonmember functions with
respect to these warnings.  For example:

  namespace {
  struct S {
    void f() { }
  };
  typedef decltype(S().f()) v;  // Previously did not suppress the "never
                                // referenced" warning for S::f
  }


3/15/22  [EDGcpfe/24790,EDGcpfe/25149]
Default member initializers and destructor instantiations

Consider:

  template<typename T> struct X {
    X(T*);
    ~X() { sizeof(T); }
  };
  struct Undefined;
  struct S {
    X<Undefined> m{nullptr};  // Previously an error.  Now okay.
  };

Previously, this elicited an error from the front end because the destructor
needed for the destruction of S::m was instantiated when parsing the default
member initializer.  Now, that instantiation is delayed until the destructor
is actually needed.


3/14/22  [EDGcpfe/25150]
GNU C++ compatibility: Flexible array members

The changes for EDGcpfe/22387 (see entry of 10/20/20) introduced a GNU C++-mode
regression in version 6.2 for the following case:

  struct B { int i; };
  struct D: B {
    int x[];  // Previously an error in GNU C++ mode.  Now okay.
  };

In C, a flexible array member cannot be the only direct member of a struct, and
that restriction was accidentally carried over to GNU C++ mode by the changes
of EDGcpfe/22387.  That is now fixed: Inherited members are also considered.


3/11/22  [EDGcpfe/25146]
keep_restrict_in_signatures not being initialized properly

The changes for EDGcpfe/24520 (in version 6.3) did not initialize the global
variable keep_restrict_in_signatures properly, which could cause spurious
errors in configurations where MAKE_FRONT_END_CALLABLE is TRUE and a C program
was compiled before a C++ program (within the same process).  Now fixed.


3/11/22  [EDGcpfe/19139,EDGcpfe/24638,EDGcpfe/24919]
Range-based for iteration driven by arithmetic types

Consider:

  struct S {
    struct It {
      operator int&();
      int operator*() const;
    };
    It begin(), end();
  };
  void g() {
    for (int x : S{}) {}  // Previously an error.  Now okay.
  }

Previously, the example resulted in an error because the "iterator increment"
operation implied by the range-based for loop only considered user-defined
operator++ implementations or the increment operator being applied to a pointer
type.  In this example, however, it is validly applied to type int (after a
user-defined conversion from type S::It).  That is now fixed.


3/10/22  [EDGcpfe/23957]
GNU C++ compatibility: Value category of conditional operator

Consider:

  struct S { S(S&&) = delete; };
  void g(bool b, S s) {
    S &&rr = b ? (S&&)s : throw "except";  // Previously an error in some
  }                                        // GNU C++11 modes.

The conditional expression in this example is an xvalue, but in GNU C++11 modes
with gnu_version < 100000 it was previously treated as a prvalue, and thus
triggered an error for attempting to call the move constructor of S.  That is
now fixed.  (GCC versions prior to 10.x exhibit some nonstandard value category
behavior in related cases, and the front end continues to handle those cases
like GCC in the matching GCC modes.)


3/9/22   [EDGcpfe/25139]
Spurious const qualification of temporary in lowered variable initialization

Lowering of aggregate constants can sometimes result in the creation of a
temporary variable to hold the aggregate constant and in some cases that
variable had been erroneously const-qualified, resulting in diagnostics when
compiling the generated C code.  For example (with --clang_version 110100):

  struct S { int i[3]; };
  int *p = (S){ {1, 2, 3} }.i;


3/9/22   [EDGcpfe/25138]
Multiple compilations with Unicode vulnerability checking

The changes for EDGcpfe/24995 failed to reinitialize certain static
variables for successive translation units, likely leading to aborts and
other incorrect behavior.  This is now fixed.


3/8/22   [EDGcpfe/25131]
C++-generating back end: Variadic construction arguments

Consider:

  struct S { int i; };
  template<typename... Ts> S h(Ts ...ps) {
    S x(ps...);  // Previously misrendered as "S x(ps);"
    return x;
  }
  template S h();

The front end previously did not correctly record that the argument to the
initialization of x is a pack expansion.  In turn, that caused the C++-
generating back end to erroneously leave out the pack expansion ellipsis.
That is now fixed.


3/7/22   [EDGcpfe/25134]
C++-generating back end: Selecting from compound literals

Consider in Clang C++ mode:

  struct S { int i[3]; };
  int *p = (S){ {1, 2, 3} }.i;

The processing of the initializer for p previously caused the initializer as a
whole to be marked as a compound literal, which resulted in the C++-generating
back end mis-rendering that initializer.  That is now fixed.


3/7/22   [EDGcpfe/24844]
Missing copy elision after user-defined conversion

In relatively obscure cases, the front end failed to perform copy elision on
an initialization with the result of an implicit call to a conversion operator
if the destination (class) type was expressed using a typedef-name.  That is
now fixed.


3/7/22   [EDGcpfe/25081]
C++-generating back end: abort with constexpr variable template with CTAD type

The changes for EDGcpfe/22747 in version 6.2 caused an assertion failure in
gen_variable_decl in C++-generating back end configurations when a variable
template is declared with the constexpr specifier and a type that uses
class template argument deduction.  This is now fixed.  For example, with
--c++17:

  template <typename = int> struct S {
    constexpr S(void *) { }
  };
  template <typename> constexpr S s { nullptr };  // Previously aborted


3/4/22   [EDGcpfe/24911]
Inheriting deleted constructors

In some relatively complex cases, inheriting a deleted constructor resulted in
the front end treating the "inherited constructor" as non-deleted.  That is now
fixed.


3/4/22   [EDGcpfe/24219]
IA64-ABI: Inheriting constructors with alternate entry points

In configurations with IA64_ABI and DO_IL_LOWERING set to TRUE, the generation
of alternate entry points for inheriting constructors would copy the
"is_inheriting_ctor" field, but not the pointer to the inherited constructor.
This could cause any calls to "get_inh_ctor_originator" for this alternate
entry point to segfault.  For example:

  struct a {
    typedef int b;
  };
  template <class> struct c : a {};
  template <typename...> class d {
  public:
    template <class e> d(e, typename c<e>::b = 0);
  };
  using f = d<>;
  struct g : f {
    using f::f; // Generated alternate entry point routine has NULL originator
  };
  void h(g) { h(0); }

This is now fixed.


3/4/22   [EDGcpfe/20942,EDGcpfe/24610,EDGcpfe/24934,EDGcpfe/24946]
Matching of variadic template template parameters

Consider:

  template<template<typename...> class X> int f();
  template<typename, int> struct S {};
  int r = f<S>();  // Previously accepted.  Now an error.

The front end previously failed to notice that the <typename, int> parameter
kinds of struct S cannot match the <typename...> parameter list of the
corresponding parameter.  That is now fixed.


3/3/22   [EDGcpfe/24845]
Coroutines: unneeded copy with operator co_await() returning prvalue

When the class type of the operand of a co_await expression has an operator
co_await() member function that returns a prvalue, the front end previously
created an explicit temporary for use in the co_await expression and copied
the result of the operator co_await() call to that temporary.  This
unnecessary copy operation has now been been eliminated, and the co_await
expression uses the result of the operator co_await() call directly.


3/3/22   [EDGcpfe/25127]
Multiple translation units: Assertion failure with variable templates

When compiling multiple translation units that use variable templates, where
the primary TU contained a declaration only while a secondary TU contains an
initializer, the front end could encounter an assertion failure in
check_correspondences, due to a lacking canonical source correspondence entry.
For example, if the primary TU contains:

  namespace std {
    template <class...> bool d;
  }

and a secondary TU contains:

  namespace std {
    template <class...> bool d = d<>;
  }

this would trigger an abort.  This is now fixed.


3/3/22   [EDGcpfe/24905]
Nontype template arguments bound to a reference

In some cases, a template-dependent nontype template argument bound to a
reference was folded to a constant and then erroneously implicitly cast to a
corresponding pointer type.  That resulted in the C++-generating back end
incorrectly rendering the argument.  For example:

  template<typename T> struct S {
    static inline T const V{};
    template<unsigned> struct N;
  };
  template<auto const&, unsigned> struct XX {};
  template<typename T> template<unsigned I> struct S<T>::N {
    template<auto const &F> using X = ::XX<F, I>;
    X<S::V> Z;  // Previously misrendered as "X<&S::V>".  Now okay.
  };


3/2/22   [EDGcpfe/24868]
Variables defined in unnamed namespaces and never referenced

The front end warns about variables defined in unnamed namespaces but never
referenced, because such variables have internal linkage and thus cannot be
referenced from other translation units and thus might represent an
oversight on the part of the programmer.  The front end has now been
changed to issue a remark instead of a warning if the initialization of
such a variable has side effects, since it is possible that the programmer
defined the variable solely for the side effects.  For example:

  struct S {
    S();
  };
  namespace {
    S xx;  // Previously a warning, now a remark, because the initialization
           // has a side effect (calling the constructor)
  }


3/2/22   [EDGcpfe/25110]
GNU compatibility: __builtin_ia32_serialize builtin

The __builtin_ia32_serialize builtin is now available (when gnu_version >=
110100).


3/2/22   [EDGcpfe/24574,EDGcpfe/25115]
GNU C++ compatibility: Decay of static data member array in template

Consider:

  template<typename T> struct S {
    static constexpr int arr[] = { 0, 1, 2 };
  };
  int main() {
    return S<void>::arr[1] != 1;  // Previously returned 1.  Now returns 0.
  }

IN GNU C++ mode, the instantiation of S<void> does not automatically trigger
the instantiation of the static data member S<void>::arr.  Instead, that member
is instantiated on demand.  However, in this case, the front end failed to
perform that instantiation when the subscript operator implicitly triggered the
"decay" of S<void>::arr to a pointer to int value.  As a result, the IL did not
reflect the correct initialization of S<void::arr and code generated from it
produced invalid results.  That is now fixed.


3/2/22   [EDGcpfe/24975]
C++-generating back end: missing "typename" in dependent using-declaration

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end failed to use the
"typename" keyword in a dependent using-declaration naming a type.  For
example:

  template<typename> struct A {
    using type = int;
  };
  template<typename T> struct B : A<T> {
    using typename A<T>::type;  // Previously omitted "typename" in generated
                                // code, resulting in an error in the
                                // instantiation of B<int>
  };
  B<int> bi;


2/28/22  [EDGcpfe/22304]
"needed" flag for inline constexpr variables

The definition of an inline constexpr variable is not needed in a
translation unit that uses only its value.  In configurations with
MAINTAIN_NEEDED_FLAGS set to TRUE, however, the front end previously
unconditionally set the "needed" flag for inline constexpr variables,
regardless of whether the definition is required in the current translation
unit or not.  A change has been made so that the "needed" flag is set only
if the definition is required.  For example, with --c++17:

  struct S {
    static constexpr bool b = false;  // Implicitly inline
  };
  bool f() {
    return S::b;  // Uses only the value, does not make S::b "needed"
  }


2/28/22  [EDGcpfe/25091,EDGcpfe/25098]
C++-generating back end: unbounded recursion with alias template

In certain complex cases, the C++-generating back end could overflow the
call stack with an unbounded recursion when generating code involving an
alias template.  This is now fixed.  For example:

  template<typename T> using A = T;
  template<typename T> A<T> f(T);
  struct B {
    void g() { f(c.d); }
  private:
    struct C {
      struct D { } d;
    } c;
    friend struct E;
  };
  struct E {
    using T = B::C::D;  // Previously caused unbounded recursion involving
                        // A<B::C::D>
  };


2/24/22  [EDGcpfe/25059]
Microsoft compatibility: string literal concatenation in comment _Pragma

MSVC performs string literal concatenation, as well as substitution of
function name variables, inside the string operand of a comment _Pragma
directive.  The front end previously did not do so but has now been changed
to emulate the Microsoft compiler's processing.  For example, with
--microsoft:

  void foo() {
    _Pragma("comment(linker, \"/EXPORT:\" __FUNCTION__ \"=\" __FUNCDNAME__)")
  }

previously resulted in an error expecting a ")" at the __FUNCTION__ token
but now is accepted and is equivalent to

  void foo() {
    _Pragma("comment(linker, \"/EXPORT:foo=_Z3foov\")")
  }


2/22/22  [EDGcpfe/25102]
Placeholder constraints and structured bindings

The front end previously failed to check placeholder constraints on a
structured binding declaration initialized with an array.  For example:

  template<typename T> concept C = sizeof(T) > sizeof(int[1]);
  void g() {
    int x[] = { 42 };
    C auto [e] = x;   // Previously accepted.  Now an error.
  }

That is now fixed.


2/22/22  [EDGcpfe/23851,EDGcpfe/24514,EDGcpfe/25002,EDGcpfe/25070]
Microsoft compatibility: layout builtins

The builtins originally introduced by the changes for EDGcpfe/22295 have
been reworked.  The __builtin_is_pointer_interconvertible_base_of and
__builtin_is_layout_compatible builtins have been removed.  In Microsoft mode,
the following builtins have been added: __is_layout_compatible,
__is_pointer_interconvertible_base_of, __is_corresponding_member, and
__is_pointer_interconvertible_with_class.


2/22/22  [EDGcpfe/25101]
Instantiation of variable templates initialized with requires-expressions

Consider:

  template<typename T> bool x = requires { typename T::X; };
  auto z = x<int>;  // Previously a spurious syntax error.  Now okay.

Previously, the instantiation of x<int> triggered a spurious syntax error about
a missing semicolon.  That is now fixed.


2/22/22  [EDGcpfe/25097]
Spurious error with default concept arguments

The front end previously ignored default concept arguments in some situations,
leading to spurious errors.  For example:

  template<typename, typename U = int> concept C = sizeof(U) > 1;
  C auto x = 1;  // Previously a spurious error claiming the constraint
                 // failed.  Now okay.

That is now fixed.


2/21/22  [EDGcpfe/25030]
Regression: Abort when re-declaring builtin __va_list_tag

In version 6.3 of the front end, additional checking was added when pushing a
scope for a class/struct/union to ensure that it was not overwriting an
already-created scope.  In some configurations (where a builtin __va_list_tag
struct is generated), this caused an abort when processing a re-declaration of
__va_list_tag.  For example:

  struct __va_list_tag {  // Previously triggered an abort
    unsigned int gp_offset;
    unsigned int fp_offset;
    char *overflow_arg_area;
    char *reg_save_area;
  };

This represents an error state that was previously missed, and the front end
now issues a diagnostic instead of aborting.  Note that this may still appear
to be as a regression, as this was silently accepted.


2/18/22  [EDGcpfe/25020]
Handling of anonymous union member initialization

The constant-evaluation interpreter sometimes severely mishandled the
initialization of anonymous union members.  That could lead to invalid results
or internal errors.  For example:

  struct X {
    constexpr X(): i(0), p(&i) { }
    int i;
    int *p;
  };
  struct S {
    constexpr C(): x() { }
    union {
      X x;
    };
  };
  S s;  // Previously triggered an internal error.  Now okay.

This is now fixed.  (This particular example previously triggered an internal
error in find_subobject_for_interpreter_address, in interpret.c.)


2/16/22  [EDGcpfe/24916]
Abort after class prvalue is converted to a glvalue

The front end sometimes converts a class prvalue to a glvalue.  The process to
do this did not always record the information needed to allow SFINAE processing
(in contexts potentially subject to SFINAE).  As a consequence, some (fairly
complex) cases aborted with an internal error in get_expr_rescan_info (in
exprutil.c).  That is now fixed.


2/15/22  [EDGcpfe/25077]
Missing error on member function modifier applied to member function templates

Consider:

  struct S {
    template<typename T> int f(T) final;  // Previously okay.  Now an error.
  };

The front end previously did not diagnose the meaningless "final" modifier in
this example (and similarly with other modifiers, like "override").  That is
now fixed.


2/14/22  [EDGcpfe/25069]
Microsoft and GCC compatibility: Field selection from prvalue

The changes for EDGcpfe/24655 in version 6.3 of the front end introduced a
regression in Microsoft C++ mode causing the front end to no longer allow
taking the address of an expression that is a field selection from a prvalue.
For example:

  struct S { int i; };
  S f();
  int *p = &f().i;  // Now accepted again in Microsoft mode.
                    // No longer accepted in GNU C++ mode with
                    // gnu_version >= 40600.

This is now accepted again in Microsoft modes.  Furthermore, this is no longer
accepted in GNU C++ modes with gnu_version >= 40600 (to match the behavior of
corresponding GCC versions).
  

2/13/22  [EDGcpfe/25068]
Command-line option to dump keyword-style command-line options

To allow, for example, the bash "complete" command to be used to complete
front end command-line options, the --dump_command_options has been added
to the front end.

To use this option with bash (for example) say:

  complete -W "`$EDG_BASE/bin/edgcpfe --dump_comm`" edgcpfe

This allows (modulo possible configuration differences) you to type
"edgcpfe --no_v<tab><tab>" and have displayed:

  --no_variadic_macros     --no_variadic_templates  --no_vla

This was added to the front end rather than eccp so that this could be used
by those who don't use eccp.  This functionality can be used with eccp (or
other drivers) by just replacing edgcpfe with eccp in the "complete" command.


2/11/22  [EDGcpfe/22972,EDGcpfe/25039]
GNU and Microsoft C++ compatibility: "this" in constant expression contexts

GCC and MSVC appear to accept the use of "this" in constant expression contexts
even when the C++ standard doesn't permit it.  For example:

  struct C { static int const value = 42; };
  struct S {
    C *p;
    int g(int x) {
      switch (x) {
        case p->value: return 1;  // Now accepted in Microsoft and GNU modes.
        default: return 0;
      }
    }
};

The front end now more closely emulates that behavior in its respective GNU and
Microsoft C++ modes.


2/11/22  [EDGcpfe/25066]
--no_il_lowering and IL_SHOULD_BE_WRITTEN_TO_FILE

Previously the --no_il_lowering command-line option was only available in
configurations where IL_SHOULD_BE_WRITTEN_TO_FILE was TRUE.  That restriction
has been lifted.


2/10/22  [EDGcpfe/24993]
Regression on folded GNU statement expression

The changes for EDGcpfe/23803 introduced a regression in version 6.3 of the
front end, causing it to sometimes corrupt the list of scopes under a block
scope if a folded GNU statement expression appeared in that block scope.  This
manifested as an IL write-read internal error.  For example:

  void g(int);
  void f(int a) {
    g(({ int x = a; x; }));
    g(({ int y = 0; y; }));  // This GNU statement expression is folded,
    if (1) { int b; }
  }

In this example, the second GNU statement expression is folded, but that
process caused the block scope B containing "int b;" to be dropped from the
list of scopes B belongs to (which is a list associated with the top-level
function scope of f).  That is now fixed.


2/10/22  [EDGcpfe/25036]
Regression on templates with __restrict parameters in Microsoft mode

The changes for EDGcpfe/24520 introduced a regression in version 6.3 of the
front end, causing it to fail to substitute function templates with __restrict
qualifiers in some cases.  For example:

  template<typename T> int f(T const *__restrict) { return 42; }
  template int f<double>(double const *__restrict);  // Previously an error.
 
That is now fixed.


2/9/22   [EDGcpfe/25034]
Microsoft compatibility: Temporary elision

Consider:

  struct X {};
  struct S {
    S(S const&) = delete;  // (1)
    S(X&);                 // (2)
    void g() {
      S(X{});              // (3) Previously an error.  Now okay.
    }
  };

In Microsoft C++ mode, the front end previously treated the expression in line
(3) as an invocation of the constructor in line (1) applied to the implicit
conversion of X{} to S via a call to the constructor in line (2).  Since the
constructor in line (1) is deleted, this resulted in an error.  Now, the call
to the constructor in line (1) is elided and the example is accepted (with
warnings since the example relies on the nonstandard behavior of binding an
rvalue to a reference to non-const X).  That matches the behavior of the
Microsoft compiler.


2/9/22   [EDGcpfe/25028,EDGcpfe/25071]
Abort on constant-evaluation of default constructor call

Consider:

  struct V {
    constexpr V(): i(0) {}
    constexpr V(const V &v): i(v.i) {}
    int i;
  };
  struct C { V v; };
  struct X { C c[2]; };
  X g() {
    X x;  // Previously triggered an abort.  Now okay.
    return x;
  }

While attempting to constant-evaluate default construction of the local
variable, the front end triggered an abort due to a null-pointer indirection.
That regression, introduced by the changes for EDGcpfe/22130,EDGcpfe/24225 in
version 6.3, is now fixed.


2/9/22   [EDGcpfe/25050]
Static initialization and reinterpret_cast

Consider:

  class C {};
  char x[sizeof(C)];
  C *p = reinterpret_cast<C*>(x);  // Previously dynamic initialization in
                                   // C++11 mode.  Now static initialization.

In C++11 (and later), the evaluation of a reinterpret_cast causes an
expression not to be a so-called "core constant expression".  Hence, the
initializer of p is not a constant expression and thus p has "dynamic
initialization" according to the standard.  However, implementations are
permitted to implement this initialization as a static ("constant")
initialization, and many implementations do.  The front end now handles this
reinterpret_cast specially in this context to produce a constant initializer
even in C++11 (and later) modes.  (See also the changes for EDGcpfe/22057,
which handle a related case.)


2/8/22   [EDGcpfe/25052]
C++-generating back end: Deduction guides

Consider, in C++17 mode:

  template<typename...> struct Keys {
    template<typename... Vs> struct Vals {
      Vals(Vs const &... args) {}
    };
    template<typename... Vs> Vals(Vs const&...) -> Vals<Vs...>;
      // Previously rendered twice.
  };
  void g() {
    (Keys<char, void>::Vals(1, 2)); // Previously dropped the "<char, void>".
  }

The C++-generating back end previously mis-rendered this example in two places.
First, the deduction guide member template was rendered twice (without a
separating semicolon).  Second, the cast expression relying on class template
argument deduction did not render the template arguments on the qualifier of
the template name (i.e., "Keys::Vals" instead of "Keys<char, void>::Vals").
Both problems are now fixed.


2/8/22   [EDGcpfe/24882]
Clang C++ compatibility: Unqualified name lookup in noexcept-specifiers

In some GNU C++ modes, the front emulates a GCC bug relating to the lookup of
names in noexcept-specifiers (see the Changes entry for EDGcpfe/22861).  Clang
appears to emulate that behavior specifically for the lookup of the identifier
"swap" in the context of std::pair appearing in a system header: The front end 
now also matches that Clang behavior in Clang modes.


2/7/22   [EDGcpfe/19699,EDGcpfe/20389,EDGcpfe/20877,EDGcpfe/21467,
          EDGcpfe/21670,EDGcpfe/22964,EDGcpfe/24627,EDGcpfe/24742]
Spurious warnings on some uses of constexpr if

When using the C++17 constexpr if feature, a spurious warning (missing return
statement at end of non-void function) had been given on cases like the
following (with --c++17 -tused):

  template <typename T> int f(T t) {
    if constexpr (false)
      return 1;
    else
      return 0;
  }
  int x = f(0);


2/4/22   [EDGcpfe/24980]
C++-generating back end: members of class templates as base class specifiers

As described for EDGcpfe/24527, g++ has a bug that causes it to emit
spurious errors in some cases when the name of a class template appears as
a qualifier in a qualified name inside that class template.  In addition to
the case given in that entry, the bug also applies when the qualified name
is used as a base class specifier.  The C++-generating back end previously
produced such names for a nested class whose base is also a member of the
same class template, triggering the bug.  This is now fixed, and the
qualifier is omitted in such cases when gcc_is_generated_code_target is
TRUE.  For example:

  template <typename T> class foo {
    template<typename U, bool test> class bar;
    template<typename U> class bar<U, true> :
      public bar<U, false> { };   // previously put out as foo<T>::bar
  };


2/2/22   [EDGcpfe/24970]
C++-generating back end: qualifier using member typedef of class template

In configurations in which template definitions are generated from the
prototype instantiation IL, some complex template code could result in
incorrect generated code for qualified names appearing in a class template
definition.  In particular, a qualified name in a class template definition
in which the qualifier is a dependent typedef member of that class template
could be put out using a specialization of an unrelated alias template
in place of the original typedef name.  This is now fixed.


2/2/22   [EDGcpfe/24724]
Use of [[no_unique_address]] fields with type aliases caused undefined behavior

A missing skip_typeref had caused undefined behavior (particularly in
Cfront configurations) when using fields declared with type aliases and the
[[no_unique_address]] attribute.  For example (with --c++20):

  struct empty {};
  using T1 = empty;
  using T2 = empty;
  struct A {
    [[no_unique_address]] T1 a;
    [[no_unique_address]] T2 b;
  } x;


2/1/22   [EDGcpfe/24546,EDGcpfe/24819]
IA-64 ABI: [[no_unique_address]] layout

In IA-64 ABI configurations, fields with the [[no_unique_address]] attribute
and empty class types were not assigned the correct layout in cases with
three or more consecutive fields of the same type.  For example (with --c++20
--g++):

  struct C {};
  struct A {
    [[no_unique_address]] C a1;
    [[no_unique_address]] C a2;
    [[no_unique_address]] C a3;
  };
  static_assert(__builtin_offsetof(A,a1) == 0);   // Okay.
  static_assert(__builtin_offsetof(A,a2) == 1);   // Okay.
  static_assert(__builtin_offsetof(A,a3) == 2);   // Had previously failed.


1/31/22  [EDGcpfe/22685,EDGcpfe/23919,EDGcpfe/24378,EDGcpfe/24409]
Spurious pack expansion error on nested alias template with empty expansion

A spurious "pack expansion does not make use of any argument pack" error
could be issued if a variadic class template contained an alias template
definition that made use of an empty pack expansion of the enclosing
class template.  Now fixed.

  template <typename T, T... I> struct A {
    template <T N> using B = A<T, I..., N>;
  };
  A<int> a;


1/22/22  [EDGcpfe/25025]
Assertion failure with raw literal operator in a template

In configurations that create the string form of template definitions, the
changes for EDGcpfe/19745 in version 5.0 resulted in an assertion failure
in add_token_to_string when a template definition contains a user-defined
literal that refers to a raw literal operator (i.e., one with a single
const char* parameter).  This is now fixed.  For example, with --c++17:

  int operator ""_xx(const char *);
  template<typename> void f() {
    5_xx;  // Previously an assertion failure
  }


1/21/22  [EDGcpfe/24924]
Use of __func__ (and similar) in lambda expressions

Consider:

  auto g() { return [&](const char* s = __func__){ return s; }(); }
        // Previously an error.  Now okay.

Previously, this elicited an error because the front end did not treat __func__
as appearing in the function scope of g().  That is now fixed.  (Other similar
identifiers, like __FUNCTION__, are handled similarly.)


1/21/22  [EDGcpfe/24901]
C++-generating back end: Template-id with dependent qualifier

Consider:

  template<int> auto g();
  template<typename T> struct S {
    template<auto V> int f() {
      return g<T::template Z<V>>();
    }
  };

Previously, the C++-generating back end rendered "T::template Z<V>" as
"T::template Z" (dropping the template arguments).  That was due to the IL
recorded for the prototype instantiation of that expression missing the
representation of the template argument.  That is now fixed.


1/20/22  [EDGcpfe/25009]
Constant-evaluation of capturing lambda expressions

The implementation of constant-evaluation of lambda expressions contained a bug
that triggered invalid results in some cases where a captured variable is
declared with a typedef type or a cv-qualified type.  Some changes made in
version 6.3 of the front end increased the likelihood of this bug manifesting.
This is now fixed.


1/20/22  [EDGcpfe/20663,EDGcpfe/24933]
Spurious error in nonreal using declaration in Microsoft mode

Consider:

  template<typename, typename> struct P;
  template<template<typename...> class X, typename... Ts> struct B {
    using R = X<Ts...>;
  };
  template<typename T, typename U> struct D: public B<P, T, U> {};

Previously, this produced a spurious error in Microsoft C++11 mode, complaining
that there were too few template arguments in "X<Ts...>".  This is now fixed.
(The error occurred during the so-called nonreal instantiation of B<P, T, U>, a
process unique to Microsoft modes, and during which type information is often
imprecise.)


1/20/22  [EDGcpfe/25016]
GNU/Clang compatibility: default C standard

A change has been made set the default C standard based on the version of
GNU/clang being emulated.  When clang is emulated, C17 is selected when
clang_version >= 110000 and C11 is selected when clang_version >= 30600.
When GNU is emulated, C17 is selected when gnu_version >= 80000 and C11
is selected when gnu_version >= 50000.


1/19/22  [EDGcpfe/24774]
C++23: Unicode-based identifier syntax

WG21 document P1949R7, which was adopted by the C++ Standard Committee for
C++23 and as a Defect Report against previous C++ standards, uses the
definitions of the XID_Start and XID_Continue categories from Unicode
Standard Annex #44 to specify which extended characters can validly appear
in an identifier.  The front end has now been changed to use these Unicode
categories by default in all C++ modes; the classification used when
scanning identifiers can be explicitly specified via the
--[no_]old_id_chars command-line option.  For example, the following was
previously accepted with --c++11 --strict but now results in an error
unless --old_id_chars is specified:

  int a\u200cb;  // Unicode ZWNJ is no longer a valid identifier character


1/18/22  [EDGcpfe/24494]
GNU C++ compatibility: Initializers for flexible array members

In GNU C++ mode with gnu_version >= 60000, the front end now accepts aggregate
initializers for flexible array members with trivial destruction.  For example:

  struct X { int i; };
  struct Y {
    int i;
    X x[];
  };
  Y y = {0, {0}};

(The front end already accepted such cases in Microsoft modes: See the entry
of 9/1/04.)


1/18/22  [EDGcpfe/25003]
Abort on attempt to constant-evaluate a defaulted default constructor

Consider:

  struct A { A(); };
  A::A() = default;
  struct B { A a; };
  B b;

The definition of b requires the front end to attempt to constant-evaluate the
default constructor of B, and thus the defaulted default constructor of A.
Previously, the front end incorrectly marked the latter default constructor as
constexpr, and in some configurations that later resulted in an internal error
in scope_for_routine (il.c).  This regression, introduced in version 6.3 by the
changes for EDGcpfe/22722,EDGcpfe/24336,EDGcpfe/24639, is now fixed (the
constructor is no longer implicitly marked as constexpr).


1/18/22  [EDGcpfe/24992]
Bad "packed" struct layout in C modes

The changes for EDGcpfe/24023 in version 6.3 introduced a regression in the
layout of certain C-mode "packed" struct types in certain configurations.
That is now fixed.


1/18/22  [EDGcpfe/24234]
GNU/Clang compatibility: linkage of extern "C" functions in unnamed namespaces

The changes for EDGcpfe/18674 (in version 6.1) changed the name linkage for
extern "C" functions in unnamed namespaces to internal linkage rather than
external.  That is consistent with the standard, but it appears that GNU
and clang give such entities external linkage so a change has been made to
use external linkage when emulating GNU and clang.  For example (with --c++14):

  namespace {
    extern "C" void f(void) { } // now external linkage in GNU and clang modes
  }


1/17/22  [EDGcpfe/24971]
Abort in corresponding_param_type on deduction guide declaration

Consider:

  template<typename> struct S {
    S(int i = 0) {}
  };
  S(int i = 0) -> S<int>;  // Previously aborted.  Now okay.

The default argument on the deduction guide previously led the front end to an
abort (caused by a null pointer indirection) in corresponding_param_type (in
class_decl.c) in configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to
TRUE.  That is now fixed.


1/16/22  [EDGcpfe/24997]
GNU compatibility: folding of __builtin_ceil/ceilf/ceill

A change has been made to fold calls to __builtin_ceil, __builtin_ceilf, and
__builtin_ceill and to allow constexpr compilation of such calls.  For
example, with --g++:

  extern "C" double ceil(double);
  const char N = ceil(3.1);
  int a[N];
  static_assert(N == 4.0);


1/13/22  [EDGcpfe/24990]
C++-generating back end: inline static data members

In cases where a static data member is defined outside the class as an
inline variable, the C++-generating back end incorrectly put out the
"inline" specifier in both the in-class declaration and the out-of-class
definition, resulting in two definitions of the static data member.  This
is now fixed.  For example, with --c++17:

  struct S {
    static int i;  // Previously generated with the "inline" specifier
  };
  inline int S::i = {};


1/11/22  [EDGcpfe/24935]
Unicode source vulnerability checking and precompiled headers

Using the Unicode source vulnerability checking feature described in
EDGcpfe/24810,EDGcpfe/24829 with a precompiled header could result in
aborts or other problems.  This is now fixed.  In addition, the processing
of identifiers was originally performed only on UTF-encoded files; this is
now extended to ASCII-encoded identifiers regardless of the file encoding,
in order to detect confusable spellings of identifiers declared in system
headers and the like.


1/11/22  [EDGcpfe/24959]
Spurious parsing error in __INTADDR__ construct

In C++11 (and later) modes, the EDG-specific __INTADDR__ construct was not
always parsed correctly.  For example:

  struct S { void *m; };
  template<unsigned N> void f();
  void g() {
    f<((unsigned)__INTADDR__(&(((S*)0)->m)))>();  // Previously sometimes
  }                                               // issued a spurious error.


In this example, scanning the __INTADDR__ construct accidentally skipped past
the closing angle bracket.  That is now fixed.


1/10/22  [EDGcpfe/24923,EDGcpfe/24968]
Abort in num_template_levels_of

The changes for EDGcpfe/24623 in version 6.3 introduced a regression causing
the front end to trigger an abort in num_template_levels_of on certain
abbreviated out-of-class member template definitions.  For example:

  struct S {
    template<int> void f(auto x);
  };
  template<int> void S::f(auto x) {}  // Previously aborted in C++20 mode.
                                      // Now okay.

That is now fixed.


1/10/22  [EDGcpfe/24953]
Explicit-this member functions

The changes for EDGcpfe/24781 (for version 6.3) introduced explicit-this member
functions.  A number of bugs were found in that implementation:
  - a diagnostic was missing for virtual functions declared with an explicit
    "this" parameter,
  - a diagnostic was missing for attempting to form the address of an
    explicit-this member without using "&" or without using a qualified
    name, and
  - an indirect call was sometimes treated as a direct call to an
    explicit-this member if folding recovered the callee of the indirect
    call.
Those issues are now fixed.


1/5/22   [EDGcpfe/24966]
Incorrect value for __builtin_memcmp during interpretation in GNU mode

As a result of the changes for EDGcpfe/24283 (in version 6.3), the interpreter
had returned 0 when __builtin_memcmp was invoked with two arguments that
pointed to two different locations within the same object (only in GNU
emulation mode).  Now fixed.  For example (with --g++ --c++14):

  constexpr const char* a = "abcdef";
  static_assert(__builtin_memcmp(a, a+1, 2) < 0);


1/4/22   [EDGcpfe/24945]
Internal error in rescan_reusable_cache

In some configurations with DEBUG set to TRUE, the reusable token cache for a
function template declaration could accidentally be marked as "not reusable".
That in turn could then cause an assertion failure in rescan_reusable_cache.
That is now fixed.


1/4/22   [EDGcpfe/24965]
Type of decimal integer literals with no suffix

The changes for EDGcpfe/24363 changed the type of some decimal integer literals
with no suffix in many Microsoft modes.  However, the analysis of how MSVC
behaves was incorrect.  For example, the type of the literal 2147483648 (too
large to fit in a signed 32-bit representation but not for an unsigned 32-bit
representation) was made to be "int" in most Microsoft modes, but MSVC really
treats it as unsigned long.  The front end has been adjusted accordingly.
Furthermore, this behavior is now limited to target configurations where int
and long have the same size and that size is smaller than that of long long
(which is the case in the Microsoft ABIs).


1/3/22   [EDGcpfe/24961]
Abort in base_class_rvalue_expr

The changes for EDGcpfe/18083 (in version 6.3) introduced a regression in some
cases involving a constexpr conversion function, causing the front end to abort
with an internal error in base_class_rvalue_expr (il.c).  For example:

  struct B {
    int i;
    enum class E : int {};
    constexpr operator E() const {
      return static_cast<E>(i);
    }
    template<E> static constexpr bool f() {
        return true;
    }
  };
  struct D: public B {};
  constexpr D d{42};
  static_assert(D::f<d>());  // Previously triggered an abort.  Now okay.

In this example, the problem occurred while overload resolution checked whether
the template argument d can be converted to the type E of the corresponding
template parameter: That requires tentatively converting a class lvalue as a
constant using an inherited conversion function, which the front end did not
handle correctly.  That problem is now fixed.


12/26/21 [EDGcpfe/24952]
Array bound underflow in accum_quoted_string

The changes for EDGcpfe/24810,EDGcpfe/24829 (in version 6.3) resulted in
accum_quoted_string reading the character immediately preceding the start
of an array when processing the string result of __FUNCTION__ and related
constructs.  This has now been fixed.


12/23/21 [EDGcpfe/24954]
C++-generating back end: members of class templates as nontype arguments

As noted in the entry for EDGcpfe/24527 (in version 6.3), g++ has a bug
that results in spurious errors when a member of a class template used as a
nontype template argument is referenced using a qualified name.  To work
around that bug, the C++-generating back end was changed to avoid name
qualification in such contexts.  However, this change was overly broad; g++
appears to have difficulty only if the member is referred to directly
inside its own class, and the change caused a regression, suppressing
necessary name qualification in certain cases.  For example, with --g++
--c++17:

  template<int> struct A { };
  template<typename> struct B {
    template<typename> struct C;
    static constexpr int i = 0;
  };
  template<typename T> template<typename U> struct B<T>::C {
    A<B<T>::i> i;   // Previously generated as "A<i>"
  };
  B<int>::C<int> bici;

The generated code was incorrect because it both referred to the name "i"
and declared it in the same class scope, which is an error.  This is now
fixed; the C++-generating back end now suppresses name qualification in
nontype template arguments only when the name is a direct member of the
class in which the template argument appears.


12/22/21 [EDGcpfe/24939]
C++-generating back end: dependent destructor calls

In order to work around a bug in g++, the C++-generating back end
previously added the template arguments of the class type to the name of a
dependent destructor being invoked; see EDGcpfe/14675.  However, g++ only
requires/accepts the template arguments when the destructor is named in a
class template instance that is different from that of the destructor's
class but both are instances of the same class template.  The C++-generating
back end has now been changed to emit a template argument list only when it
is actually needed.  For example:

  namespace N {
  template <typename> struct S { };
  }
  template <typename T> void f(N::S<T> s) {
    s.~S();  // Previously generated as "s.~S<T>()"
  }


12/22/21 [EDGcpfe/24915]
Internal error in unlink_src_seq_entries after error on static data member

In configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE, the front
end sometimes aborted with an internal error in unlink_src_seq_entries after
an error was encountered during the processing of the declaration of a static
data member.  That is now fixed.


12/21/21 [EDGcpfe/24937]
C++-generating back end: inaccessible conversion type-ids

The changes for EDGcpfe/24713 (in version 6.3) caused a regression in some
cases in which a conversion function is declared in its class using an
inaccessible name and then invoked using the function call syntax.
Previously, the C++-generating back end used an accessible synonym for the
inaccessible type name in the generated code.  After the change, the call
was generated using the inaccessible type name with which the conversion
function was declared.  This is now fixed, and an accessible name is once
again used in such calls.  For example:

  template <typename> struct A;
  template <typename T> struct B {
  private:
    typedef T type;
  public:
    operator type();
  };
  template <> struct A<char> : B<char> {};
  void f() {
    typedef char c;
    A<c> ac;
    ac.operator c();  // Generated in version 6.3 as "operator type()", now
                      // once again as "operator char()"
  }


12/21/21 [EDGcpfe/24921]
GCC compatibility: Warning on narrowing

The changes for EDGcpfe/24213 reduced the severity of some narrowing errors to
just narrowing warnings in some GCC-mode cases.  In some cases, however, no
diagnostic was issued at all: A tweak has been made to issue a warning in those
cases as well.


12/21/21 [EDGcpfe/24936]
C++-generating back end: parentheses in a non-type template argument

The changes for EDGcpfe/24697 (in version 6.3) caused a regression in the
output of the C++-generating back end for expressions in a non-type
template argument appearing in a local scope.  Previously such expressions
were folded to a constant value; after the change, the original expression
was used.  However, the generated code failed to add parentheses when needed
to prevent a "," or ">" operator from being interpreted as the end of the
argument or argument list.  This is now fixed.  For example:

  template<int I> struct S { };
  void f() {
    S<(4 > 1)> s1;  // S< 1 > in 6.2, S< 4 > 1 > in 6.3, now S<( 4 > 1)>
  }


12/21/21 [EDGcpfe/24938]
Pack expansion in nonreal instantiation of alias template

Consider:

  template<typename> struct B;
  template<typename R, typename ... Ps> struct X {
    template<typename> using A = B<R(Ps...)>;
    template<typename F>
      X(F&&) noexcept(A<F>::template f<F>()) {}
  };

During the prototype instantiation of X, the front end performs a nonreal
instantiation of A<F> in the noexcept operand and the resulting type is
recorded as the qualifier in "A<F>::template f<F>".  Previously, that nonreal
instantiation failed to represent the pack expansion of Ps in the definition
of A, which in turn caused the C++-generating back end to render the noexcept
operand as "B<R(Ps)>::template f<F>()" (which is invalid).  That is now fixed:
The operand is now rendered as "B<R(Ps...)>::template f<F>()".


12/20/21 [EDGcpfe/24927]
Spurious error on const-qualified array-type parameter in template

Consider:

  template<typename T> void f(int v, T const* const arr[]) {
    arr += v;
  }
  int main() {
    float const *x[12];
    f<float>(3, x);
  }

Version 6.3 introduced a regression causing this example to be rejected with a
spurious error about the parameter arr not being modifiable (the regression was
introduced by the changes for EDGcpfe/22040,EDGcpfe/22338,EDGcpfe/24390).  That
is now fixed.


12/16/21 [EDGcpfe/24193]
Storage class and COMDAT grouping of lambda alternative entry point

The implicit conversion operator created for a lambda that doesn't capture
any local variables (see the Changes entry for EDGcpfe/10612) was not being
given the same storage class as the lambda call operator that it referred to.
Additionally, in configurations that do lowering and use the IA-64 ABI,
the conversion operator routine was not being placed in the same COMDAT group
as the call operator.  Both of those are now fixed.  For example:

  struct A {
    void (*m_fun)(void*);
    void mf () {
      m_fun = [](auto){};
    }
  };
  void f(A *p) {
    p->mf();
  }


12/14/21 [EDGcpfe/24922]
Assertion failure when macro arguments are omitted

In configurations with FULLY_RESOLVED_MACRO_POSITIONS set to TRUE, with
certain complex macros the front end could abort with a failed assertion in
macro_invocation when a macro invocation provides fewer arguments than
required by the macro being invoked.  This is now fixed.


12/13/21 [EDGcpfe/24920]
Microsoft compatibility: control-Z and end-of-file

In text mode input on Windows, the control-Z character 0x1a is treated as
an end-of-file marker.  However, in program source, MSVC recognizes the
character as representing the end of a file only if it appears where a
token is expected; within comments and literals, it has no special meaning.
When configured with READ_SOURCE_IN_BINARY_MODE_FOR_MSDOS set to TRUE,
however, the front end always treated that character as an end-of-file
marker, regardless of the context.  This has now been fixed.  For example,
with ^Z representing the 0x1a character, the front end in that
configuration previously reported that the comment was not closed at the
end of the file but now compiles the file without error:

  /* The character ^Z is not an end-of-file marker inside a comment. */


-------------------------------------------------------------------------------
Version 6.3, December 13, 2021

12/6/21  [EDGcpfe/24739]
Coroutines: Coroutine frame variables with unset 'is_local_to_function' field

The front-end's generation of the variables for a coroutine frame (e.g., the
'promise' variable or the copied coroutine parameters) failed to set the
'is_local_to_function' field in their source correspondences.  This could lead
to the incorrect impression that these were global variables, and has now been
fixed.


12/3/21  [EDGcpfe/24810,EDGcpfe/24829]
Unicode source code vulnerabilities

As described in paper www.trojansource.codes/trojan-source.pdf, C and C++
Unicode-based source code is vulnerable to several exploits, including:
  - use of bidirectional formatting codes in comments and strings
  - use of zero-width characters in strings
  - use of homoglyphs - distinct characters whose visual appearance is
    identical - in identifiers
  - use of zero-width characters in identifiers
In all these cases, malicious code can be visually disguised to appear
innocuous.  The front end can now detect and warn about the Unicode
constructs employed in these exploits.  The new configuration macro
UNICODE_VULNERABILITY_CHECKING_SUPPORTED (which defaults to TRUE if
UNICODE_SOURCE_SUPPORTED is TRUE and must be FALSE otherwise) controls
whether this capability is included.  Checking only applies to UTF-encoded
Unicode source and header files and is controlled by the global variable
check_unicode_security, which defaults to FALSE and can be explicitly set
via the --[no_]check_unicode_security command-line option.


11/29/21 [EDGcpfe/24026]
Coroutines: Missing lifetime information and inverted conditional logic

The front-end's generated body for a coroutine was not associating the lifetime
object with the final_suspend label (similarly with any generated goto
statements for that label).  In addition, the logic for checking the initial
suspend state unfortunately had inverted the conditional check for re-throwing
exceptions from the construction of the coroutine frame.  This is now fixed.


11/29/21 [EDGcpfe/24179]
Copy-elision on result of user-defined conversion

Consider:

  template<typename T> auto v() noexcept -> T&&;
  template<typename S, typename D> struct Q {
    template<typename T> static void f(T) noexcept;
    decltype(f<D>(v<S>())) *p;
  };
  class N {
    N(N const &) {}  // Private.
  };
  struct X {
    operator N() const;
  };
  auto r = Q<X&, N>{};  // Previously an error.  Now okay.

Previously, the substitution of f<D>(v<S>()) (with S = X& and D = N) failed
because the front end failed to elide the copy constructor in binding the
parameter of f<D> (of type N, in this case) to the result of the user-defined
conversion of v<S>() (an lvalue of type X, in this case) to an rvalue of type
N.  That is now fixed.


11/26/21 [EDGcpfe/24848]
Incorrect end position for integral constant in-class field initializers

The front end would provide incorrect end-position information for in-class
field initializers when that initializer is an integral constant.  For example:

  int foo();
  class C
  {
    int l = 10;    // Previously incorrect end position
    int m = foo(); // Already correct end position
  };

This is now fixed.


11/22/21 [EDGcpfe/24864]
Matching a forwarding reference expressed with an alias template

Consider:

  template<typename T> using X = T;
  template<typename T> void f(X<T>&&) {}
  template void f(int&);  // Previously a spurious error.  Now okay.

Previously, this elicited an error because the type matching algorithm for
declarative cases like this did not account for the possibility of the
template parameter being placed under an alias template.  That is now fixed.
(Note that the similar cases involving template argument deduction from a call
expression already handled this correctly.)


11/19/21 [EDGcpfe/24865]
Spurious error on requires-expression in prototype instantiation

Consider:

  template<typename T> concept C = sizeof(T) < 100;
  template<typename T> auto f() {
    static_assert(requires { requires C<typename T::Type>; });
  }  // Previously an error.  Now okay.

The front end previously issued an error attempting to evaluate the dependent
requires-expression and not finding a constant result.  That is now fixed.


11/19/21 [EDGcpfe/24850]
IA-64 ABI: Incorrect use of a "cookie" in overaligned array allocation

In the IA-64 ABI configuration, a "cookie" is sometimes allocated to store
the number of elements in a dynamically-allocated array.  In some cases
(involving overaligned types with trivial destructors) this cookie was being
inadvertently added to the allocation and not accounted for on the deallocation
resulting in undefined behavior.  For example (with --c++17):

  struct alignas(64) A {
    int x{0};
  };
  int main() {
    A* a = new A[2];
    delete[] a; // Undefined behavior in IA-64 configs at runtime previously
    return 0;
  }


11/18/21 [EDGcpfe/24836]
Spurious failure to match noexcept specifier of function template parameter

Consider (in C++17 mode):

  bool const B = 0;
  template<int N>  void f(void (&f)() noexcept(N + B));
  template<> void f<0>(void (&)() noexcept(0+B));  // Previously a spurious
                                                   // error.  Now okay.

Previously, the front end failed to match the explicit specialization f<0> to
its template because it failed to match the noexcept specifiers of the
parameter types.  That is now fixed.


11/18/21 [EDGcpfe/24476,EDGcpfe/24548]
Nested capture of "this" in default member initializer

Consider:

  struct S {
    int f();
    int arr[1]{
      [this]{
        return [this]{ return f(); }();  // Previously a spurious error.
      }()                                // Now okay.
    };
  };

The front end previously complained that the call to f() (equivalent to
this->f()) is invalid, mistakenly suggesting "this" is not captured.  That
is now fixed.


11/18/21 [EDGcpfe/19293]
Use of "this" in evaluated context in non-capturing lambda

Consider:

  struct S {
    int f();
    auto g() { return []{ sizeof(f()); }; }  // Previously an error.
  };                                         // Now okay.

The call "f()" requires a "this" selector.  That resulted in an error claiming
"this" is not captured, but that capture isn't needed in an unevaluated context
(in this case: a sizeof operand).  That is now fixed.


11/18/21 [EDGcpfe/24676]
Use of uninitialized bits when creating floating-point hash value

The change made for EDGcpfe/21041,EDGcpfe/22138 was incomplete and would leave
some unused bits in a floating-point value uninitialized in some configurations
leading to an fp_hash value that was not deterministic.


11/17/21 [EDGcpfe/24263,EDGcpfe/24726]
Lambdas, capturing "this", and calls to mixed static/nonstatic overload sets

Consider (in C++14 mode):

  struct S {
    void f();
    template<typename T> static void f(T);
    void g() {
      auto x = [](auto p) { f(p); }; // Previously an error.  Now okay.
    }
  };

Previously, the front end required "this" to be captured in the lambda because
the dependent call f(p) selects a candidate from an overload set that includes
a nonstatic member.  That is now fixed and the example is now accepted as long
as the selected member is a static member.


11/17/21 [EDGcpfe/24859]
C++-generating back end: type operators involving local lambdas

The changes for EDGcpfe/23814,EDGcpfe/24260 (not in a release but
distributed to some customers as a patch) caused the C++-generating back
end to generate certain cases of type operators involving local lambda
expressions as references to undefined classes with temporary names (of the
form __T12345678) instead of the original type operator.  This is now
fixed.  For example, with --c++17:

  void f() {
    auto l = []() { return []() {}; };
    using T = decltype(l());  // Previously generated as "class __T12345678"
    int i = sizeof(T);        // Previously an error due to incomplete type
  }


11/16/21 [EDGcpfe/23965]
C++23: Lambda declarators

Prior to C++23, a lambda could omit its "lambda declarator" altogether, and
that would be equivalent to that declarator being "()" without any additional
specifiers or trailing return types.  So:

  auto lm1 = []{};                      // Okay: Equivalent to "[](){}".
  auto lm2 = []()->int { return 42; };  // Okay.
  auto lm3 = []->int { return 42; };    // Previously always an error.  Now
                                        // accepted in C++23 mode, meaning
                                        // "[]()->int { return 42; }".

In C++23, that rule was relaxed by the standardization committee's paper
P1102R2, which specifies that if the parenthesized parameter clause is omitted
it is as if "()" appeared in that syntactic location instead.  The front end
now implements that behavior in C++23 mode.


11/12/21 [EDGcpfe/24828]
GNU C++20 compatibility: if consteval

GCC 12.x will apparently accept "if consteval" in C++20 mode with a warning.
The front end now emulates that behavior when gnu_version >= 120000.


11/12/21 [EDGcpfe/20067,EDGcpfe/22198,EDGcpfe/24846]
Internal error in copy_tokens_from_cache on static data member template

Consider:

  namespace N {}
  struct S {
    template<typename T>
      static constexpr bool N = N::undefined<int, T>;
  };      // Previously an internal error.  Now an ordinary error.

This code is invalid because it refers to the nonexistent name N::undefined.
Previously, however, examples like this one caused the front end to abort (in
C++11 mode) with an internal error in copy_tokens_from_cache due to poor error
recovery.  That is now fixed.


11/12/21 [EDGcpfe/24811]

Consider in C++17 mode (where exception specifications are part of the function
type):

  void (*p)() noexcept;
  void (**pp)() = &p;  // Previously accepted.  Now an error.

Previously, this was accepted because the exception specification of pp is not
more restrictive than that of &p.  However, that rule only applies to pointer-
to-function and reference-to-function conversions.  For pointer-to-pointer-to-
function types, the underlying exception specifications must match.  That is
now enforced, and thus the example above now results in an error.


11/11/21 [EDGcpfe/24793]
C++-generating back end: dependent template-ids naming variable templates

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end incorrectly
inserted an "&" when forming a dependent template-id naming a static data
member template.  This is now fixed.  For example, with --c++14:

  template<bool> struct A { };
  template<typename T> struct B {
    template<typename U> static const bool b = sizeof(T) < sizeof(U);
  };
  template<typename T> struct C {
    using x = A<B<T>::template b<T>>;  // Previously generated as
                                       // A<&B<T>::template b<T>>
  };


11/11/21 [EDGcpfe/24815]
Lambda expressions and decltype

Consider:

  void g() {
    [=]{
      int x = 42;
      decltype(&x) p;
      *p = 42;  // Previously a spurious error.  Now okay.
    }();
  }

Previously, the decltype construct erroneously treated x as having a "const"
type (it was mistakenly treated as being capture by the -- non-mutable --
lambda expression).  That in turn resulted in a spurious error.  That is now
fixed.


11/11/21 [EDGcpfe/24809]
GNU C __auto_type and cv-qualifiers

The front end issued a spurious error when the GNU C __auto_type specifier is
combined with cv-qualifiers.  For example (in some GNU C modes):

  void g(int i) {
    __auto_type const x = i;  // Previously a spurious error.  Now okay.
  }

This is now fixed.


11/11/21 [EDGcpfe/24840]
Nonconstant destruction and constinit variables

The front end previously issued an error for constinit variables whose
initialization is constant but whose destruction is not constant.  For example:

  struct X { int i; ~X(); };
  constinit X x{ 42 };  // Previously an error.  Now okay.

That is now fixed.  In cases like these, the initializer for the variable will
point to a dynamic initialization entry (a_dynamic_init), but that entry will
represent constant initialization (e.g., it will have kind dik_constant).


11/11/21 [EDGcpfe/24822]
Spurious error on alignas in class template

A spurious error had been given on a member definition that used alignas in a
class template definition and is now fixed.  For example (with --c++14):

  template <class T> struct A {
    struct alignas(64) B {} b;
  };
  A<int> a;


11/5/21  [EDGcpfe/22130,EDGcpfe/24225]
Spurious constant-evaluation errors on some aggregate copy operations

Consider:

  struct X {
    constexpr X(int i): i(i) {}
    constexpr X(X const &x): i(x.i) {}
    int i;
  };
  struct S {
    X m[1];
  };
  constexpr X x{1};
  constexpr S s{x};
  constexpr S c = s;  // Previously an error.  Now okay.

Previously, the front end failed to evaluate the copy constructor of the
aggregate type S for the initialization of c.  That is now fixed.


11/5/21  [EDGcpfe/24831]
Uninitialized data used when displaying error message

When a file cannot be opened the reason given for not being able to open the
file had been based on uninitialized data in some cases, resulting in incorrect
or incomplete diagnostics.


11/3/21  [EDGcpfe/24781]
C++23: Explicit-this member functions

In C++23 mode, the front end now accepts member functions with an explicit
"this" parameter.  This also applies to lambda expressions, which therefore can
be made recursive.  For example:

  constexpr auto lm = [](this auto &self, int i)->int {
                        return i>1 ? i*self(i-1) : 1;
                      };
  static_assert(lm(9) == 362880);

This feature was added to the working paper for the next standard by the
standardization committee's paper P0847R7.


11/3/21  [EDGcpfe/24750]
C++-generating back end, clang compatibility: __int128

When clang is the generated code target, the C++-generating back end
previously put out the name of the 128-bit integer type using the built-in
typedef name "__int128_t".  This resulted in uncompilable code for the
unsigned and explicitly-signed variants, since "signed" and "unsigned"
cannot be applied to a typedef name.  This is now fixed, and the
C++-generating back end now uses the name "__int128" in all variants of the
128-bit integer type.  For example, with --c++14 --clang_version=120000:

  signed __int128 i;  // Previously generated as "signed __int128_t"


10/29/21 [EDGcpfe/24808]
Shadowing of template parameters

The front end now accepts, with a warning, declarations like:

  template<typename T> T T(T) {}

in Clang C++ mode.


10/28/21 [EDGcpfe/24777]
Compilation cost of prototype instantiation of complex alias templates

In some complex situations, the function alias_prototype_instantiation could
spend excessive time establishing which of the template parameters are actually
used in the aliased type (via function template_param_used_in_type).  For
cases where this was observed, that cost has now been reduced to produce near-
instantaneous compilation times.
 

10/28/21 [EDGcpfe/24780]
C++23: More relaxed constexpr function definitions

In C++23 mode, constexpr function definitions can now contain goto statements,
label declarations, and variables of static or thread storage duration or of
nonliteral type.  A constant-evaluation cannot, however, evaluate such a
construct.  For example:

  constexpr int f(int p) {
    if (p == 1) {
      return 42;
    } else {
      static int x = 42;  // No longer an outright error in C++23.
      return 41;
    }
  }
  static_assert(f(1) != 0);  // Okay in C++23.
  static_assert(f(2) != 0);  // Still an error in C++23.

This feature was added to the working paper for the next standard by the
standardization committee's paper P2242R3.


10/28/21 [EDGcpfe/24805]
Alternative tokens

The front end now accepts alternative tokens (digraphs like "<:" and
alternative operator spellings like "bit_and") by default in C++11 mode.  This
new behavior can be disabled with the --no_alternative_tokens command-line
option.


10/28/21 [EDGcpfe/24773]
C++23: if consteval/if not consteval

In C++23 mode, the front end now accepts the "if consteval" and "if not
consteval" constructs (the latter can also be written "if !consteval").
For example:

  consteval int f(int i) { return i; }
  constexpr int g(int i) {
    if consteval {
      return f(i);  // Not an error even though i is not a constant
                    // expression because this is a consteval context.
    }
    return 0;
  }
  static_assert(g(42) == 42);

This feature was added to the working paper for the next standard by the
standardization committee's paper P1938R3.


10/28/21 [EDGcpfe/24800]
C++23 mode

The front end now accepts a new "--c++23" command-line option (as does the
eccp.sh script).  This option will enable features for the standard under
development (which is expected to be completed in 2023).  For now, it sets
the value of the global variable std_version to 202300 and the value of the
predefined __cplusplus macro to 202300L; those values will eventually be
updated to match the official __cplusplus value when the forthcoming standard
is approved.  A new macro cpp23_mode is also available in the front end to
test whether it runs in C++23 mode.


10/25/21 [EDGcpfe/24490]
GCC and Clang compatibility: Range of integer literals

When 128-bit integer types are enabled (i.e., when INT128_EXTENSIONS_ALLOWED is
configured to TRUE), the front end previously sometimes assigned those types to
very large integer literals.  For example:

  auto r = 0x10000000000000000;  // Previously r had type __int128.

However, Clang and GCC never assign a 128-bit type to an integer literal.  GCC
issues a warning on the case above and gives the literal type int.  Clang
emits an error and continues with type unsigned long long for the literal.  The
front end now emulates those behaviors in its respective emulation modes (with
a discretionary error in Clang mode).


10/25/21 [EDGcpfe/24520]
Microsoft compatibility: __restrict parameters

The front end previously ignored top-level __restrict qualifiers on parameter
types when comparing function types.  Now, such qualifiers matter in Microsoft
modes.  For example:

  template<typename, typename>
    struct is_same { static const bool value = false; };
  template<typename T>
    struct is_same<T,T> { static const bool value = true; };
  using type = float *__restrict;
  void g(type) {
    static_assert(!is_same<decltype(g)*, void (*)(float*)>::value, "");
      // Now accepted in Microsoft C++ modes.
  }

Furthermore, a new command-line option --keep_restrict_in_signatures causes the
front end to keep the restrict qualifier in a_param_type::type even when
remove_qualifiers_from_param_types is TRUE (this causes the restrict qualifier
to be incorporated in the mangled name, which matches the behavior of the
Microsoft compiler).  A --no_keep_restrict_in_signatures option is also
available.


10/21/21 [EDGcpfe/24343,EDGcpfe/24663]
Subsumption checking

A bug was found in the algorithm computing C++20 constraint subsumption.  For
example:

  template<typename T> struct X {};
  template<typename T> concept A = true;
  template<typename T> concept B = A<X<T>>;
  template<typename T> concept C = B<T>;
  template<typename T> concept D = C<T> && true;
  template<typename T> struct S;
  template<typename T> requires C<T> struct S<T> { };
  template<typename T> requires D<T> struct S<T> { };
  S<int> s;  // Previously an ambiguity error.  Now okay.

Previously, the front end could not decide between the two partial
specializations of S when instantiating S<int> because it failed to see that
D<T> subsumes C<T>.  That is now fixed.


10/21/21 [EDGcpfe/24719]
C++-generating back end: namespace-qualified dependent template-ids

In configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE,
the C++-generating back end failed to add the "template" keyword in a
dependent namespace-qualified template-id.  This is now fixed.  For
example, with --c++14:

  template <typename... Ts> class A {};
  namespace N {
  template <typename D, int I> struct B { };
  }
  template <typename... Ts> struct C {
    template <int I> A<int> get() {
      // Previously omitted "template" in the generated code:
      return (*this).N::template B<A<int>, I>::get();
    }
  };


10/20/21 [EDGcpfe/24771]
Incorrect handling of invalid substitution for auto&

Consider:

  enum E { e };
  template<auto&> int g();                             // (1)
  template<E...> constexpr bool g() { return true; }   // (2)
  static_assert(g<e>());  // Previously an error.  Now okay.

Previously, the front end did not fail deduction for candidate (1) despite it
requiring (invalid) binding of an lvalue reference to a prvalue.  After (1) was
selected, the front end then issued an error about the binding being invalid.
Now, candidate (1) fails deduction and candidate (2) is selected instead.


10/19/21 [EDGcpfe/22220]
Spurious type category error in dependent nontype template argument

Consider:

  template<typename T> struct W {};
  struct I;
  int const i = -1;
  inline int const& g(W<I>) { return i; };
  template<typename T, int const* = &g(W<T>())> struct S {};
    // Previously an error.  Now okay.

Previously, the front end emitted an error on &g(W<T>()) claiming that the
call to g did not produce an lvalue.  That is now fixed.


10/15/21 [EDGcpfe/24788]
Spurious substitution failure on cast

In some situations, where a constexpr dependent call is explicitly converted
to a nondependent type, the front end could fail a substitution in GNU, Clang,
and Microsoft C++ modes.  For example: 

  template<bool> struct EnableIf {};
  template<> struct EnableIf<true> {
    using Type = int;
  };
  template<typename To, typename From>
  constexpr bool check_conv() {
    return sizeof(To) == sizeof(From);
  }
  template<typename To, typename From,
           typename EnableIf<bool(check_conv<To, From>())>::Type = 0>
  To conv(From x) {
    union { From from; To to; } converter = { x };
    return converter.to;
  }
  long r = conv<long>(1.2);  // Previously an error.  Now okay.

Here the substitution of "bool(check_conv<To, From>())" was previously not
correctly handled, causing the "conv" candidate to be erroneously discarded.
That is now fixed.


10/15/21 [EDGcpfe/24565,EDGcpfe/24751]
Abort due to error node passed to lowering on some GNU-mode C++ constexpr cases

In some relatively complex cases involving the late instantiation of a GNU C++
static data member specialization triggered by constant-evaluation
(specifically, by a call to instantiate_member_constant in the interpreter)
the front end silently produced an error constant that was integrated into the
final IL tree.  In configurations that do IL lowering, this later triggered an
internal error.  That is now fixed.


10/15/21 [EDGcpfe/24740]
C++-generating back end: explicit specializations of constexpr function
templates

As noted in the description of the change for EDGcpfe/20871, implicit
instantiations of constexpr function templates are not required to satisfy
the requirements for a constexpr function, but explicit specializations
must do so.  In configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, the
C++-generating back end addressed that issue by suppressing the "constexpr"
specifier on a generated explicit specialization if that template instance
was never successfully interpreted during the compilation (which would have
guaranteed that the explicit instantiation is a valid constexpr function).
However, that resulted in erroneous code in some cases where an instance of
a constexpr function template is called from another constexpr function but
neither function is called in a constant context.  For example, with
--c++11:

  template<typename T> constexpr bool f(const T &v) {
    return (v == 0.0);
  }
  constexpr float g(const float a, const float b) {
    return f(a) ? a : ((a <= b) ? a : b);
  }

Here, the generated explicit specialization of f<float> was previously
declared without the "constexpr" specifier because f<float> is never called
in a constant context.  As a result, the definition of g was ill-formed
because it contained an unconditional call to the non-constexpr function
f<float> and thus could never be called in a constant context.  To avoid
this type of problem, the C++-generating back end now suppresses generated
explicit specializations of constexpr function templates when the
corresponding instance was not successfully interpreted during compilation.


10/15/21 [EDGcpfe/24768]
Constant-evaluation of empty run-time object

Consider:

  struct E {} e;
  constexpr void f(E) {}
  constexpr bool g(E const &e) {
    f(e);
    return true;
  }
  static_assert(g(e), "");  // Previously an error.  Now okay.

Previously, the call g(e) did not evaluate to a constant expression because
initializing the parameter of f(E) with the value of the run-time variable e
was not considered constant.  However, e is an empty class type with trivial
copy semantics, and there is therefore no actual access to run-time storage.
The interpreter now takes that into account, allowing this example to be
accepted.


10/15/21 [EDGcpfe/24767]
PCH and mangling of "abi_tag" attributes

The GNU-specific "abi_tag" attribute (see the Changes entry for EDGcpfe/15897)
is used to annotate the mangling of certain objects.  However, those
annotations were omitted when using a precompiled header (PCH) file.  For
example (with --gnu_version 80000 --pch):

  // File: test.cpp
  #include "mystring"
  std::string foo() {
    std::string s;
    return s;
  }

  // File: mystring
  namespace std {
    inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { }
  }
  namespace std {
    namespace __cxx11 {
      struct string {};
    }
  }

When using the IA-64 ABI, the mangled name for "foo" is "_Z3fooB5cxx11v" but
when using a PCH file "_Z3foov" had been generated.  With this change,
"_Z3fooB5cxx11v" is used in both cases.  This change also affects the
Cfront ABI mangling.


10/14/21 [EDGcpfe/24701]
C++-generating back end: alias templates with dependent type-ids

In some cases in which the type-id of an alias template involves a
dependent alias template specialization, the C++-generating back end used
the underlying type of the alias template specialization instead of the
alias template specialization itself, which could result in generated code
that could not be compiled.  This is now fixed.  For example,

  template <class...> struct a;
  template <int I> struct b {
    using c = void;
  };
  template <class... Ts> using d = b<sizeof...(Ts)>;
  // Previously put out using b<sizeof...(a<Ts>)>::c instead of d<a<Ts>...>::c:
  template <class... Ts> using e = typename d<a<Ts>...>::c;


10/13/21 [EDGcpfe/24716]
Lambda captures

The mechanism used by the front end to handle lambda captures has been reworked
to avoid implicit captures of constant-valued variables when only the constant
value of those variables is needed.  For example:

  int f() {
    constexpr int N = 42;
    auto L = [&](){ return N; };  // N is no longer captured.
    return L();
  }

Previously, the front end captured the constexpr variable N as soon as the
identifier N was encountered in the return expression.  Now, the decision about
whether to capture N (and create a corresponding field in the closure) is
delayed slightly and ultimately that decision is negative: N is not captured
because it is a constant-valued variable only used as a prvalue.


10/11/21 [EDGcpfe/24753]
Clang compatibility: add builtin function signatures for clang 13.0.0

The signatures for builtin functions have been updated to include those for
version 13.0.0 of clang.


10/7/21  [EDGcpfe/24697]
Representation of operand of alignas

Consider:

  void g() {
    constexpr auto N = alignof(int);
    alignas(N) char buf[sizeof(int)];
    (void)buf;
  }

Previously, the representation of the operand of alignas(N) was a constant
representing the integer value of N, with no backing expression recording that
that value was obtained from the expression "N".  As a consequence, the C++-
generating back end rendered the alignas construct as "alignas(4U)" or similar
(depending on the actual value of N).  This limitation was due to the alignas
representation being stored in file-scope memory while the operand expression
is stored in function scope memory.  Now, in such situations, the backing
expression is recorded indirectly using the a_local_expr_node mechanism, which
in turn allows the C++-generating back end to render the original expression.


10/1/21  [EDGcpfe/24738]
Folding of __builtin_expect and __builtin_expect_with_probability

Consider in GNU C++14 mode:

  extern int a;
  extern int b;
  void g() {
    if (__builtin_expect_with_probability(&a + 1 != &b, 1, 0.0001)) {
      __builtin_unreachable();
    }
    // ...
  }

The invocation of __builtin_expect_with_probability was previously folded by
the front end, which made the hint intended by the intrinsic invisible to back
ends.  Now such invocations are no longer folded, unless a constant result is
required or the invocation is part of the constant-evaluation of an enclosing
invocation.


10/1/21  [EDGcpfe/24734]
GNU statement expressions in C++11 constexpr functions

Consider in GNU or Clang C++11 mode:

  constexpr int f() {
    return ({ int x = 1; x; });  // Previously an error.  Now okay.
  }

C++11 only permits a single return statement in a constexpr function.  However,
the front end incorrectly also included statements embedded in GNU statement
expressions within that return statement when enforcing that constraint.  That
caused this example to be treated as an error.  That is now fixed.


10/1/21  [EDGcpfe/24412,EDGcpfe/24602]
Handling of __is_signed in Clang modes

In Clang mode, the identifier __is_signed was previously treated as a keyword
until it appears as a declarator immediately following decl-specifiers that
include "static", "bool", and "const" (see the entry for EDGcpfe/12122, etc.).
However, this processing introduced a bug causing "__is_signed" to sometimes be
treated as a qualified identifier even when it was not actually qualified.
For example:

  template<typename> struct E {
    enum { e = 1 };
  };
  template<typename T> struct S {
    static_assert(E<T>::e, "");
    static const bool __is_signed = (T)(-1) < 0;  // Previously an error in
  };                                              // Clang mode.  Now okay.

Additional spurious errors could also occur when a token spelled "__is_signed"
appeared more than once in the same template.  To avoid those problems,
"__is_signed" is now treated as an identifier (not a keyword) by default and it
is contextually turned into a keyword if it appears in an expression context
followed by a parenthesized type name.


9/30/21  [EDGcpfe/24729]
GNU compatibility: arguments to the "malloc" attribute

The front end now supports arguments to the GNU "malloc" attribute
(used in some later GNU header files).  For example (with --g++):

  void foo(void *);
  void bar(void *);
  void *f(void) __attribute((malloc));
  void *g(void) __attribute((malloc(foo)));
  void *h(void) __attribute((malloc(bar,1)));


9/29/21  [EDGcpfe/24732]
Spurious not-a-constant error in template-dependent context

Consider:

  struct S {
    constexpr char operator[](int) const { return 0; }
  };
  template<typename T> struct X {
    static constexpr S x = T(); 
    static_assert (x[0] != 1, "");  // Previously an error. Now okay.
  };

The front end previously treated the expression "x[0] != 1" as not template-
dependent, and consequently required it to produce a constant result.  However,
constant-evaluation of that result failed (resulting in a spurious error) since
the value of x is template-dependent.  That is now fixed.


9/28/21  [EDGcpfe/24712]
Clang compatibility: __VA_OPT__ in C mode

Beginning with version 12.0.0, clang accepts the __VA_OPT__ preprocessor
operator (see EDGcpfe/20002) in both C and C++ without regard for the
language version.  The front end has now been changed to do the same in the
relevant emulation modes.  For example, with --clang_version=120000 --c:

  #define M(x,...) x __VA_OPT__(,) __VA_ARGS__
  M(a,b)   // Now produces "a , b"


9/28/21  [EDGcpfe/24725]
Spurious GNU-mode ambiguity on member overloaded with using-declaration

The changes for EDGcpfe/21627 introduced a regression (in version 6.0) in some
GNU C++ modes in situations where a member template is overloaded with a member
projected by a using-declaration when the originating base is a template class
and the derived class is not.  This resulted in spurious ambiguity errors.
For example:

  template<typename> struct B {
    template<typename T> void f(T);
  };
 
  struct D: public B<D> {
    using B<D>::f;
    template<typename T> int f(T);
  } d;
  auto r = d.f(42);  // Previously an ambiguity error in GNU C++11 modes.  
                     // Now okay when gnu_version >= 70000.

That is now fixed: The example is accepted in GNU C++11 modes with gnu_version
>= 70000 (GCC versions corresponding to lower gnu_version values emit the same
ambiguity errors as the front end does).


9/28/21  [EDGcpfe/17877,EDGcpfe/24408]
Tokens introducing expressions

The front end's list of tokens that can introduce an expression previously
missed several entries.  This could lead to spurious errors.  For example:

  struct S {
    static const bool value = __is_trivially_constructible(int);
  };                           // Previously an error.  Now okay.

This is now fixed.  The affected tokens are __assume, __builtin_addressof,
__builtin_offsetof, co_await, co_yield, __is_assignable, __is_destructible,
__is_nothrow_assignable, __is_nothrow_destructible,  __is_trivially_assignable,
__is_trivially_constructible, __is_trivially_destructible, and __noop.


9/23/21  [EDGcpfe/24721]
Constexpr dynamic_cast during construction

In some cases, the constexpr interpreter did not correctly handle dynamic_cast
during the construction of a subobject.

  struct L { virtual void fl(); };
  struct B: L {};
  struct R { virtual void fr(); };
  struct C: L, R { L *c = dynamic_cast<L*>(static_cast<R*>(this)); };
  struct D: B, C { }; 
  constexpr D d{}; 
  static_assert(d.c == (C*)&d);  // Previously failed.  Now okay.

Previously this failed because the dynamic_cast was treated as ambiguous even
though L is not an ambiguous base of *this during the construction of C.  That
is now fixed.


9/22/21  [EDGcpfe/24214,EDGcpfe/24471]
Logical operators folded despite dependent second operand

Consider:

  template<bool> struct E {};
  template<bool B>
    using AU = typename E<B>::undef;
  template<bool F(int)>
    auto f() -> AU<0 && F({})>;  // Previously an error.  Now okay.

The front end previously folded the expression "0 && F({})" despite F being a
template parameter.  That in turn, caused AU<false> to be instantiated early,
which in turn triggered a spurious error.  That is now fixed.


9/22/21  [EDGcpfe/24211]
Self-referencing constant-expressions

Consider:

  struct S {
    int i;
    constexpr S(): i{} {}
  };
  struct X {
    constexpr X(): p(&u.i) {}
    S u;
    int *p;
  };
  struct Y: X {
    constexpr Y() {}
  };
  constexpr Y y;  // Previously an error.  Now okay.

A bug in the interpreter's management of storage lifetime caused some cases
like these that produce a constant result with an internal address constant
that refers to the result itself to mistakenly be diagnosed as non-constant.
That is now fixed.


9/20/21  [EDGcpfe/24713]
C++-generating back end: definition of user-defined conversion operators

In some configurations, the C++-generating back end failed to use the
necessary qualification for the type named in a user-defined conversion
operator definition appearing outside its class.  This is now fixed.  For
example:

  struct A { };
  struct B {
    typedef int A;
    operator ::A();
  };
  B::operator ::A() {  // Previously generated as "operator A", incorrectly
                       // referring to B::A instead of ::A
    return ::A();
  }


9/20/21  [EDGcpfe/24715]
__VA_OPT__ and expansion of macro arguments

The preprocessor previously failed to expand a macro argument passed to an
ellipsis if __VA_ARGS__ does not appear in the macro definition.  However,
the use of __VA_OPT__ in the definition should also trigger expansion of
such macro arguments.  This is now fixed.  For example, with --c++20:

  #define Z() /* nothing */
  int f();
  #define M(...) f(__VA_OPT__(,))
  int i = M(Z());   // Previously erroneously expanded to "f(,)" because
                    // the argument to M was not treated as empty


9/17/21  [EDGcpfe/18907,EDGcpfe/24687]
Microsoft compatibility: __declspec(thread) and dynamic initialization

In Microsoft modes, the front end previously never allowed a __declspec(thread)
to have non-constant initialization.  For example:

  struct S { ~S(); };
  __declspec(thread) S s;  // Previously always an error.  Now okay in
                           // Microsoft mode with microsoft_version >= 1900.

Now that constraint has been lifted when microsoft_version >= 1900.


9/17/21  [EDGcpfe/24683]
IL write-read error on some local requires-expressions

In some configurations, a local requires-expression with more than one
parameter could result in an IL write-read error (which triggers an abort).
For example:

  bool g() {
    return requires(int a, int b) { 0; };  // Previously aborted in some
  }                                        // configurations.  Now okay.

That is now fixed.


9/17/21  [EDGcpfe/23503,EDGcpfe/24030,EDGcpfe/24710]
Abort on array new-expressions in Clang mode with Microsoft extensions

Microsoft mode handles array new-expressions specially (such a new-expression
might use a non-array operator new in Microsoft mode).  The front end's support
for Clang mode with Microsoft extensions treated that behavior inconsistently,
which resulted in internal errors.  For example:

  void g() {
    new char[1];  // Previously aborted with --clang --ms_extensions.
  }               // Now okay.

That is now fixed.


9/15/21  [EDGcpfe/24682,EDGcpfe/24703]
GNU C++20 compatibility: Comparison disambiguation

Consider:

  struct S {
    S();
    operator int() const;
  } s;
  bool operator==(S const&, char const*);  // (1)
  bool operator==(char const*, S const&);  // (2)
  auto r = (s == 0);  // Previously ambiguous in C++20 modes.  Now accepted
                      // in GNU C++20 mode.

For the expression "s == 0" there are three "==" candidates in C++20 mode:
declaration (1), declaration (2) with reversed arguments, and the built-in
equality operator.  The built-in candidate is a better match for the second
operand ("0") while it's a worse match for the first (which requires a user-
defined conversion).  That makes that expression invalid.  It is also invalid
in C++17 since that just drops declaration (2) from the candidate set.
However, GCC accepts the case in both C++17 and C++20 modes.  We already
emulated GNU C++17 mode by discarding the built-in candidate on the grounds
that the "worst" conversion it involves (a user-defined conversion) is worse
than any conversion needed for the other candidates.  Now, that tie-breaker
has been tweaked to also discard the reversed candidate in this case.


9/15/21  [EDGcpfe/24706]
Abort during instantiation of requires-expressions

In some configurations instantiating a function template containing a requires-
expression could lead to memory corruption and aborts because the corresponding
prototype instantiation of the function template was discarded too early.  That
is now fixed.


9/14/21  [EDGcpfe/24696]
GNU C++20 compatibility: Friend templates and requires expressions

Consider:

  template<typename> requires true struct X {
    template<typename> friend struct X;
  };
  X<int> x;  // Now okay in GNU C++20 mode.

Ordinarily, this example is invalid because the friend template does not have a
requires-clause that is compatible with the original (enclosing) declaration of
struct X.  GCC, however, accepts this particular case and the front end now
follows suit in corresponding GNU C++ modes.


9/14/21  [EDGcpfe/24521]
Incorrect disambiguation of pointer-to-member declaration with attributes

Consider:

  struct S {};
  void g() {
    int (S::*pm [[]]);  // Previously an error.  Now okay.
  }

The front end's "expression vs. declaration" disambiguation parser previously
did not handle attributes following the "*" in a pointer-to-member declarator
construct.  That caused the statement in the example above to be parsed as an
expression, which in turn resulted in spurious errors.  That is now fixed.


9/14/21  [EDGcpfe/24695]
IL write-read error on pseudo-destructor node

Consider:

  using INT = int;
  void g() {
    int i;
    decltype(i.~INT()) *p;
  }

In configurations with IL_SHOULD_BE_WRITTEN_TO_FILE this previously triggered
an IL write-read error.  That is now fixed.


9/14/21  [EDGcpfe/23619]
Lambda using constant-valued variable not capturable due to an enclosing lambda

Consider:

  int f() {
    constexpr int N = 42;
    return [](){ return [=](){ return N; }(); }();
  }    // Previously a spurious error.  Now okay.

The example is valid because the inner lambda only uses the constant value of N
and thus N need not actually be captured.  Previously, however, the front end
produced a spurious error complaining that the outer lambda prevents capturing
of N by the inner lambda.  That is now fixed.


9/10/21  [EDGcpfe/24690]
NUM_BITS_FOR_CHARACTER_KIND

The front end assumes that NUM_BITS_FOR_CHARACTER_KIND is at least 3 (to encode
at least 5 different character kinds), but previously it did not enforce that
configuration constraint.  Now a preprocessor error is triggered if the
configured value is too small.


9/10/21  [EDGcpfe/24690]
Failure to consider explicit conversion operators in copy/move context

Consider:

  struct X {
    template<typename T> operator T();
    template<typename T, typename = int> explicit operator T();
  };
  struct S {
    S(S const&);
    S(S&&);
  };
  S s(X{});  // Previously accepted.  Now an ambiguity error.

Previously, the front end incorrectly ignored the explicit conversion operator
template of X when resolving the initializer of s.  Now, that explicit operator
is considered, causing the initialization to be ambiguous (an error message is
emitted).


9/9/21   [EDGcpfe/24689]
Modules and precompiled headers

The front end previously could abort in various ways when a compilation
uses a precompiled header containing an import directive.  This is now
fixed.


9/7/21   [EDGcpfe/24677]
Spurious failure to fold a call to a GNU built-in function in template

The front end previously issued a spurious error about the argument to a call
to a GNU built-in not being constant when that argument was template-dependent.
For example:

  template<typename T> constexpr unsigned long long g() { return sizeof(T); }
  template<typename T> struct S {
    static constexpr bool B = __atomic_always_lock_free(g<T>(), 0);
        // Previously triggered an error about g<T>() not being constant.
  };    // Now okay.

That is now fixed.


9/1/21   [EDGcpfe/24143]
Invalid substitution of template-id results in bad IL

In some fairly complex cases, the substitution of a template-id representing a
specialization of a nonreal variable template could cause the front end to
produce bad IL instead of failing substitution.  That in turn was likely to
result in an internal error during further processing (e.g., when attempting
to emit a diagnostic that names the variable template specialization).  This
problem manifested itself in uses of recent Boost libraries and is now fixed.


9/1/21   [EDGcpfe/24588]
Performance issue with VLAs in some configurations

In some cases when VLA support is enabled and backing expressions are
recorded, there could be a performance issue with arrays that have very
complex bound expressions as a result of complex expansions from template
instantiations.  Now fixed.


8/31/21  [EDGcpfe/23469]
Multiple translation units: nonreal variables in secondary translation units

In configurations with CHECKING set to TRUE, compiling multiple translation
units could result in an assertion failure in check_correspondences,
processing a nonreal variable resulting from an instantiation in a
secondary translation unit.  This is now fixed.


8/30/21  [EDGcpfe/24653,EDGcpfe/24666]
Failure to fold concept-id referring to static data member in GNU C++20 modes

Consider:

  template<typename> struct X {
    static const bool Val = false;
  };
  template<typename T> concept C = X<T>::Val;
  static_assert(!C<int>);  // Previously an error in GNU C++20 mode.  Now okay.

In GNU C++ mode, in-class static data member initializers are typically
instantiated on demand.  The logic to evaluate concept-id values, however, did
not force the instantiation of X<int>::Val in this case, however, and as a
result a spurious error was emitted claiming that X<T>::Val is a run-time value
for T = int.  That is now fixed.


8/30/21  [EDGcpfe/19736,EDGcpfe/24652]
Incorrect conversion classification when taking the address of an overload set

Consider:

  using F = void();
  int g(int const&, F* const&);                          // (1)
  template<typename U1, typename U2> int g(U1&&, U2&&);  // (2)
  template <typename T> void f();
  int r =  g(1, &f<int>);  // Previously an error.  Now okay.

Previously, the front end issued an overload resolution ambiguity error on this
example because it (correctly) identified that the first argument (literal 1)
better matches declaration (2), but incorrectly decided that the second
argument (&f<int>) was a better match for (1) than for (2).  In fact, both (1)
and (2) are equivalent matches for &f<int>.  That is now fixed and candidate
(2) is selected for the call to g. 


8/30/21  [EDGcpfe/15597,EDGcpfe/24644]
Incorrect handling of lambda expressions in noexcept queries

Consider:

  static_assert(noexcept([]() { return 0; }));  // Previously failed.
                                                // Now okay.

The front end previously failed this assertion because it erroneously treated
all lambda expression (which represent a class type initialization) as
potentially throwing an exception.  That is now fixed.


8/30/21  [EDGcpfe/24655]
Microsoft compatibility: Rvalue-reference qualifiers

Consider:

  struct S {
    void f() &&;
  };
  S g();
  void h() {
    g().f();  // Previously an error in Microsoft modes.  Now okay.
  }

The call g().f() previously resulted in a spurious error about f() not being
applicable to lvalues.  This was a consequence of the front end emulating a
Microsoft behavior that permits assigning to and taking the address of certain
class rvalues (e.g., the expression &g() is valid in the context above).  This
is now fixed.


8/27/21  [EDGcpfe/24650]
GNU compatibility: __VA_OPT__

Beginning with version 8.1.0, gcc accepts the __VA_OPT__ preprocessor
operator (see EDGcpfe/20002) in both C and C++ without regard for the
language version.  The front end has now been changed to do the same in the
relevant emulation modes.  For example, with --gnu_version=80100 --c++11:

  #define M(x,...) x __VA_OPT__(,) __VA_ARGS__
  M(a,b)   // Now produces "a , b"


8/26/21  [EDGcpfe/24158]
C++-generating back end: parenthesized compound literals

In configurations that set PARENS_IN_IL to TRUE, the C++-generating back
could put out a parenthesized compound literal incorrectly, using duplicate
casts to the literal type.  In some cases, the generated code could not be
compiled successfully.  This is now fixed.  For example, with --gcc:

  struct I {
    int i;
  };
  struct S {
    struct I* ip;
  };
  static struct S s[1] = {
    ((struct I[1]){})  // Previously generated as
                       // (((struct I [1])(((struct I [1]){})))),
                       // erroneously casting to an array type.
  };


8/26/21  [EDGcpfe/15587,EDGcpfe/23976]
Microsoft C++ compatibility: Exception specifications

In Microsoft C++ mode, exception specifications are often ignored by the front
end.  Previously, that process was a little too aggressive: A few tweaks have
been made to more closely emulate the Microsoft compiler.  For example:

  struct S {
    ~S() throw(int);
  };
  static_assert(!noexcept(S{}), "Error");  // Previously failed in Microsoft
                                           // modes.  Now okay.


8/26/21  [EDGcpfe/24609]
Structured binding fails to see inherited get<> template

In some cases, the front end's structured binding mechanism failed to take
inherited get<> members into account; this could result in spurious errors.
That is now fixed.


8/26/21  [EDGcpfe/24623]
Abbreviated out-of-class member function template definitions

Consider:

  template<typename T> struct S {
    void f(auto);
  };
  template<types T> void S<T>::f(auto) {}  // Previously an error.  Now okay.

Previously, the process to implicitly add a level of template parameterization
for the out-of-class definition of S<T>::f did not work correctly, resulting in
a spurious error.  That is now fixed.


8/25/21  [EDGcpfe/24626]
Derived-to-base rvalue reference conversion of prvalue

Consider:

  template<typename T> struct B {
    constexpr auto f() && {
        return static_cast<T&&>(*this);  // (1)
    }
  };
  struct D : B<D> {};
  constexpr auto r = D{}.f();

This previously failed because the interpreter complained about the cast in
line (1) attempting to cast to D&& from an object whose complete dynamic type
is B.  That turned out to be caused by the representation of that cast not
reflecting the reference-casting nature of the operation (both the source and
the cast node were prvalues).  That is now fixed: Both the source and cast node
are now marked as xvalues.


8/24/21  [EDGcpfe/22722,EDGcpfe/24336,EDGcpfe/24639]
Generated constexpr constructor incorrectly treated as non-constexpr

Consider:

  template<typename> struct B { bool b = false; };
  struct S  {
    constexpr S() = default;  // Previously an error.  Now okay.
    B<int> bi;
  };

Previously, the generated default constructor of B was treated as non-constexpr
when checking the validity of the "constexpr" specifier on the constructor of S
(this problem was in part triggered by the presence of a default member
initializer in B).  That is now fixed.


8/24/21  [EDGcpfe/24217,EDGcpfe/24632]
Internal error on substitution of default friend operator

Consider in C++20 mode:

  template<typename T> requires requires(const T& x) { x == x; }
    void g();
  template<typename> struct X {
    friend bool operator==(X const&, X const&) = default;
  };
  int main() {
    g<X<int>>();
  }

Previously this aborted in form_exception_specification_for_generated_function
(class_decl.c) because that function erroneously assumed that only class
members can be defaulted.  This is now fixed.


8/24/21  [EDGcpfe/24537]
GNU compatibility: "GCC" pragmas

"GCC" pragmas (i.e., pk_gcc) had been treated as immediate pragmas (i.e.,
pbk_immediate), but that led to problems in a case like this:

  template<class T> struct A {
     A();
      int m;
  };
  #pragma GCC diagnostic push
  template<class T> A<T>::A() : m(0) {}
  #pragma GCC diagnostic pop

Here, the token caching mechanism used when parsing the template definition of
A<T>::A() caused the second pragma to be ignored.

A change has been made to separate "GCC" pragmas into both immediate
pragmas (now pk_gcc_immediate) and "next token" pragmas (now pk_gcc_next_token)
with all "GCC diagnostic" pragmas being classified as pk_gcc_next_token,
allowing them to be acted upon properly.


8/23/21  [EDGcpfe/23250,EDGcpfe/24616]
Microsoft C++ compatibility: dllimport classes and constexpr constructors

Consider in Microsoft C++ mode:

  struct __declspec(dllimport) X {
    constexpr X() = default;  // Previously an error.  Now okay.
  };
  constexpr X x{};

Previously, this resulted in an error because a statically initialized variable
of type X could be difficult to implement if X has virtual functions (see also
the entry for EDGcpfe/15237).  Now, the error is only issued if the class whose
defaulted constructor is marked "constexpr" has virtual member functions.


8/23/21  [EDGcpfe/24630]
Substitution of in-class static data members in constraints

Consider:

  template<unsigned N> struct V {
    constexpr static unsigned L = N;
    void f() requires (L >= 1) {}
  };
  void g(V<1> v) {
    v.f();  // Previously an error.  Now okay.
  }

Previously, this failed spuriously because the substitution of L in the
requires-clause was not handled correctly (it caused a spurious substitution
failure).  That is now fixed.


8/23/21  [EDGcpfe/23804]
Incorrect handling of --error_limit in some complex template cases

The front end suppresses diagnostics during a real instantiation if the
diagnostic had already been issued during a prototype instantiation.
That processing could produce some unexpected results in some complex
cases when using the --error_limit option.  Now fixed.


8/20/21  [EDGcpfe/24189]
Multiple translation units: default member initializers in class templates

When compiling multiple translation units, the front end could abort with a
failed assertion in prepare_for_trans_unit_copy if a class template has a
non-static data member with a default member initializer and the template
is not instantiated in the primary translation unit but is instantiated in
a secondary translation unit.  This is now fixed.  For example, with
--c++11, the front end aborted if both translation units contain the
declarations

  template<typename> struct A {
    int i = 0;
  };
  template<typename> struct B {
    A<int> ai;
  };

and the second translation unit additionally contains the declaration

  B<int> bi;


8/17/21  [EDGcpfe/24607]
C++-generating back end: Out-of-scope variable used in template argument

The changes for EDGcpfe/22003,EDGcpfe/23814 (not in a release but sent to
some customers as a patch) introduced a regression that caused the
C++-generating back end to put out some non-type template arguments using
a variable that is not in scope at that point.  This is now fixed.  For
example, with --g++:

  template<bool> struct A {
    static void g();
  };
  struct B {
    void h(char* a) {
      if (a != 0) {
        constexpr bool b = false;
        A<b>::g();
      }
      A<false>::g();  // Previously generated as "A<b>::g()"
    }
  };


8/16/21  [EDGcpfe/18083]
Contextually converted constant expressions and inherited conversion functions

Consider:

  struct B {
    int b = 1, c;
    constexpr B(int x) : c() {}
    constexpr operator int() { return b+c; }
  };
  struct D : B {
    constexpr D(int x) : B(x) { }
  };
  char arr[D(1)];  // Previously an error.  Now okay.

The expression D(1) is "contextually converted" to the size_t type and that
process has to produce a constant.  Previously, the front end did not correctly
handle inherited conversion operators (like D::operator int() in that example
above) in that process.  As a result, the front emitted spurious errors on the
example above (and other similar examples).  That is now fixed.


8/13/21  [EDGcpfe/21800,EDGcpfe/22042,EDGcpfe/22818,EDGcpfe/24405]
GNU compatibility: Braced initializers and vector expressions

Consider (in GNU C++11 modes):

  typedef float V __attribute__((__vector_size__(16)));
  struct S { operator V(); };
  V av[1] = { S() };  // (1) Previously an error.  Now okay.
  V v = { av[0] };    // (2) Previously an error.  Now okay.

Previously, the front end did not consider user-defined conversions when
attempting to initialize an aggregate element of vector type itself (instead
of initializing each element of the vector).  For line (1), this resulted in
an error because expression S() was matched with the element type (float) of
the vector.  That is now fixed.

Also, previously, a top-level braced initializer for a vector was always
assumed to be an aggregate initializer (i.e., initializing the elements of the
destination vector one by one).  This caused line (2) to be rejected.  Now,
the special case where the braced initializer encloses a single element of the
destination vector type is handled specially and line (2) is thus accepted.


8/12/21  [EDGcpfe/24527]
C++-generating back end: members of class templates as nontype arguments

In configurations in which class template definitions are generated from
the prototype instantiation IL, the C++-generating back end put out a
non-type template argument naming a member of the current class template
using a qualified name.  In some cases, a bug in g++ resulted in a spurious
error complaining about using "this" in a constant expression when
compiling generated code containing such a qualified name.  This has now
been addressed by suppressing the qualification in such cases when
gcc_is_generated_code_target is TRUE.  For example, with
--gnu_version=90100 --c++17:

  template<auto &, int> auto f1();
  template<typename T> struct N {
    static void S(typename T::t m) { }
    void f2() {
      f1<S, int>();  // Previously generated using "N<T>::S", triggering
                     // the spurious g++ error
    }
  };


8/12/21  [EDGcpfe/24600]
Constraints on alias templates

The front end sometimes failed to check constraints on alias templates during
substitution.  For example:

  template<typename T> requires false using A = T;
  template<typename T> A<T> f(T);
  template<typename T> int f(T);
  int r = f(42);  // Previously ambiguous.  Now okay.

That is now fixed.


8/12/21  [EDGcpfe/24599]
Spurious error due to failure to account for default template arguments

Consider:

  template<typename, typename = int> struct X {};
  template<typename T> T f(T*);
  template<typename ... Ts> using F = decltype(f<Ts...>(nullptr));
  template<typename... Ts> struct S {
    template<template<typename...> class TT = X,
             F<TT<Ts>...>* = nullptr>
      S() {}
  };
  S<float> sf;  // Previously an error.  Now okay.

Previously, this failed to substitute the default constructor of S<float>
because the substitution of TT<Ts> with TT = <X> and Ts = <float> (producing
X<float>) did not correctly account for the default template argument of X.
That is now fixed.  This was a regression introduced in version 4.11 by the
changes for EDGcpfe/16587.


8/10/21  [EDGcpfe/24266]
Constant-evaluation of address comparisons

The constexpr interpreter previously sometimes misevaluated address comparisons
of certain values with distinct types.  For example:

  constexpr bool g(int *x, int const *y) { return x == y; }
  static_assert(g(nullptr,nullptr), "");  // Previously failed.  Now okay.

That is now fixed.


8/10/21  [EDGcpfe/24043]
Abort in set_src_seq_secondary_decl_fields on C++17 inline static data member

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured to
TRUE, the front end could abort in set_src_seq_secondary_decl_fields when
processing the instantiation of an inline static member defined inside its
class.  For example:

  struct S { template <class T> static inline T N = 100; };
  int main() {
    int i;
    i = S::N<int>;  // Previously triggered an internal error.
  }

That is now fixed.


8/10/21  [EDGcpfe/20909,EDGcpfe/24300,EDGcpfe/24540]
Microsoft compatibility: Closure conversion functions

Consider in Microsoft mode:

  auto p = +[]{};  // Previously an error in Microsoft mode.  Now okay.

Microsoft-mode closure types can have multiple conversion functions to account
for calling conventions.  Under ordinary overload resolution rules that makes
the example above ambiguous.  The front end has now been updated to prefer the
conversion function to a pointer-to-function type with __cdecl or "default"
calling convention.  This preference is for closure types only.  The following
example remains ambiguous:

  using F1 = void (*)();
  using F2 = void (__vectorcall *)();
  struct S {
    operator F1();
    operator F2();
  } s;
  auto p = +s;  // Still ambiguous.


8/10/21  [EDGcpfe/24597]
Microsoft C++ compatibility: Linkage of variables with duplicate definitions

In Microsoft modes the front end accepts (with a warning) the following
nonstandard example (see the entries for EDGcpfe/15048 and EDGcpfe/23004):

  int const N;              // (1)
  extern int const N = 42;  // (2) Accepted with a warning in Microsoft modes.

In this example, the original definition (1) has internal linkage and the front
end previously retained that linkage even after processing definition (2).
Now, the definition of the variable is updated to be external.  This is, for
example, revealed through the use of certain attributes.  If definition (2)
above is replaced by:

  extern __declspec(selectany) int const N = 42;  // Previously an error.
                                                  // Now accepted

the front end previously emitted an error because "selectany" doesn't apply to
variables with internal linkage.  Now it is accepted since variable N is
treated as having external linkage after processing the duplicate definition.


8/10/21  [EDGcpfe/24596]
auto parameters in explicit instantiations and specializations

In C++20 mode, the front end previously failed to diagnose auto parameters in
explicit instantiation directives and explicit specialization declarations.
For example:

  template<typename T> void g(T) {}
  template void g(auto);  // Previously erroneously accepted.

That is now fixed.


8/9/21   [EDGcpfe/24526]
Warnings about pointless unsigned integer comparisons

If u is an unsigned variable, the front end warns about comparisons like u<0
that are pointless.  The front end also disables that warning in some cases
of the form "cond && u<0" where cond is a false-valued constant.  However, the
warning was still issued if any overloaded operator&& had been seen (since such
an operator invocation wouldn't short-circuit the evaluation of the second
operand if it were selected).  On balance, however, that exception was found
not to be helpful: The front end now inhibits the warning even if an overloaded
operator&& might be selected.  A similar change affects pointless unsigned
comparisons guarded with an || operator.


8/9/21   [EDGcpfe/17977,EDGcpfe/18960,EDGcpfe/19153,EDGcpfe/20794,
          EDGcpfe/22026]
GNU C++ compatibility: Abbreviated function templates in pre-C++20 modes

The front end now accepts abbreviated function template syntax (a C++20
feature that was added to the language along with constrained templates and
concepts) in GNU C++14 (and later) modes with gnu_version >= 40900.
For example:

  auto next(auto p) { return ++p; }  // Now accepted in more GNU modes.


8/6/21   [EDGcpfe/23004]
Microsoft C++ compatibility: Duplicate definition of variables

In Microsoft modes the front end already accepts (with a warning) the following
nonstandard example (see the entry for EDGcpfe/15048):

  int x;
  extern int x = 3;  // Duplicate definition accepted with a warning in
                     // Microsoft modes.

Now, such cases are also accepted if the second declaration uses a linkage-
specification:

  int x;
  extern "C++" int x = 3;  // Now also accepted in Microsoft C++ mode.


8/6/21   [EDGcpfe/24590]
Invalid lowering of dynamic_cast of constant null pointer

The change for EDGcpfe/23648 (in version 6.2) introduced a bug such that a
dynamic_cast applied to a null pointer constant was lowered to the original
null pointer value instead of a null pointer value of the type indicated by
the dynamic_cast operation.  That is now fixed.


8/6/21   [EDGcpfe/24315]
Position of default case in C11 _Generic construct

The default case in a C11 _Generic construct is represented by an expression
node of kind enk_type_operand with a null variant.type_operand.type pointer.
Previously, the position field in those nodes was not correctly recorded.
That is now fixed.


8/4/21   [EDGcpfe/24042]
Microsoft Windows compatibility: non-ASCII temporary directory name

The temporary directory used by the front end can be specified using the
TMPDIR (or, on Windows, TMP) environment variables.  Previously, the value
of these environment variables was fetched using getenv, which assumes that
the value is represented using ordinary characters.  This resulted in
incorrect behavior on Windows when the directory name contains extended
characters.  The front end now accommodates such names by using _wgetenv to
fetch these values when EDG_WIN32 and UNICODE_SOURCE_SUPPORTED are both TRUE.


8/4/21   [EDGcpfe/24442]
Microsoft compatibility: spurious error when using --parse_templates

In Microsoft mode, when parsing nonclass templates, a spurious error
could occur when a name that is intended to name a class template
refers to an injected class name of a dependent base class.  This occurs
in permissive Microsoft mode because lookup does consider dependent
base classes in that mode.  A change has been made to ignore dependent
base classes for lookups within template function bodies.

  template <typename> class A {};
  template <typename T> struct B : A<T> {
    B(): A<T>::A() {
      A<T> a;
    };
  };


8/3/21   [EDGcpfe/24525]
Internal error on substitution of static_cast involving default argument

In some cases, rescanning an operand that was originally a non-dependent
static_cast relying on a constructor with a default argument resulted in an
internal error in make_cast_rescan_operands (exprutil.c).  For example:

  struct X { X(int, int = 1); };
  template<typename T> decltype(T{}, static_cast<X>(2)) f(T&&);
  auto r = f(3);  // Previously triggered an abort.  Now okay.

That is now fixed.


8/3/21   [EDGcpfe/24568]
Assertion failure in diag_pragma/diagnostic_pragma

The changes to diagnostic #pragma processing (see the Changes entry for
EDGcpfe/5372 et al.) could result in assertion failures when processing
certain #pragma constructs.  For example:

  struct A {
    void f() {
  #pragma diag_suppress code_is_unreachable
      if (false) {  }
  #pragma diag_default code_is_unreachable
    }
  };

This is now fixed.


8/2/21   [EDGcpfe/22040,EDGcpfe/22338,EDGcpfe/24390]
Const/volatile qualification of function template parameters

Consider:

  template<typename T> int f(T);
  template<typename T> int f(T const p) {
    p += 42;  //  Now an error.  Previously erroneously accepted.
    return p;
  }

Previously, the type of the parameter p was derived from the first declaration
of the template (which is non-const) and thus the line p += 42 was erroneously
accepted (even when the template is instantiated).  That is now fixed.


8/2/21   [EDGcpfe/24416]
Internal error when disambiguation causes instantiations

In configurations that generate source sequence lists, an internal error
could occur (in push_scope_full) if disambiguation of a file scope
declaration causes certain kinds of other instantiations.  Now fixed.

  template <typename T> using A = int;
  template <typename T> struct B {
    using X = int*;
    template <typename U> using C = A<U>;
  };
  void f(typename B<int>::X);


7/30/21  [EDGcpfe/24376]
More informative diagnostic for missing "}"

Previously when the front end encountered a premature end of file when a
closing right brace is required, it only reported that a "}" was expected.
The front end has now been changed to indicate the opening left brace
corresponding to the missing closing brace.  For example, the diagnostic
for the following code now contains a note designating the "{" on the first
line:

  extern "C" {
    int i;  // File ends here with no "}"


7/30/21  [EDGcpfe/24363]
Type of decimal integer literals with no suffix

Consider:

  constexpr auto x = 0x80000000;
  constexpr auto y = 2147483648;  // Decimal version of 0x80000000
  static_assert(sizeof(x) == sizeof(int), "");  // (1)
  static_assert(x == -2147483648, "");          // (2)
  static_assert(sizeof(y) == sizeof(int), "");  // (3)
  static_assert(y == -2147483648, "");          // (4)

assuming a 32-bit representation of type int.  Ordinarily, the type of x and y 
cannot be int, because the initializer does not fit in that representation.
Microsoft's compiler (MSVC), however, will always give x type int and thus
satisfy assertions (1) and (2).  It will often also satisfy assertions (3) and
(4), except starting with MSVC 19.24 when permissive mode is off, and starting
with 19.28 when "c++latest" mode is enabled.  The front end now emulates these
behaviors in its corresponding modes.


7/30/21  [EDGcpfe/24167]
__has_unique_object_representations and incomplete template classes

Consider:

  template<typename> struct S { int i; };
  static_assert(__has_unique_object_representations(S<int>));
      // Now okay with MSVC and GCC, but not with Clang.

Previously, the front end did not force the instantiation of a template class
passed to the __has_unique_object_representations type trait helper (see also
the entry for EDGcpfe/17964,EDGcpfe/17999), and thus the assertion check
failed.  Now, that instantiation is forced, except in Clang mode.


7/30/21  [EDGcpfe/24165]
Empty expansion of throw-specification accidentally dropped in Microsoft mode

Consider:

  template<typename... Ts> int f() throw(Ts...);
  int (*pf)() throw() = f<>;  // Previously an error in Microsoft mode.
                              // Now okay.

Previously, the empty expansion of "throw(Ts...)" in Microsoft mode caused the
whole throw-specification to be dropped instead of handled as "throw()".  That
in turn caused an error about incompatible exception specifications to be
emitted.  That is now fixed.


7/30/21  [EDGcpfe/24375]
Diagnostic for an attempt to explicitly specialize an alias template

The diagnostic previously issued for an attempt to explicitly specialize an
alias template was a somewhat cryptic "expected an identifier" designating
the "using" keyword.  This has now been changed to a more descriptive
message referring to the beginning of the declaration.  For example, with
--c++14:

  template<typename T> using U = void;
  template<> using U<int> = int;  // Now a more informative error message


7/29/21  [EDGcpfe/24473]
Spurious warning for static data member of unnamed namespace class template

In g++ and clang modes, the front end sometimes issued a spurious
"referenced but not defined" warning for a static data member of an
instance of a class template that is defined in an unnamed namespace.  This
is now fixed.  For example, with --g++:

  namespace {
    template <typename T> struct S {
      static const T m = 0;
    };
  }
  int f(const int &v = S<int>::m) {  // Previously caused "referenced but not
                                     // defined" warning for S<int>::m
    return v;
  }


7/29/21  [EDGcpfe/24519]
Abort on failure to substitute an explicit call to a conversion function

Consider:

  struct S {
    S(S const&) = default;
    template<class R> requires (!requires(R r) { r.operator S(); })
      S(R &&) {}
  };
  S g(S s) {
    return s;  // Previously triggered an abort.
  }

Previously this triggered an abort (a null pointer indirection) in
get_locator_for_rescanned_selection_second_operand (expr.c) during the
substitution of "r.operator S()" in the requires-expression.  That is now
fixed.


7/29/21  [EDGcpfe/24486]
Spurious "no effect" warning on fold-expression

The front end previously emitted spurious "expression has no effect" warnings
for some fold expressions.  For example:

  struct S {} s;
  template<typename... Ts> void g(Ts ...args) {
    (s << ... << args);  // Previously a spurious warning.
  }

The "no effect" warning was emitted for this example even though an overloaded
operator<< used for the substituted fold-expression could well have side
effects. That is now fixed (i.e., the warning is no longer emitted in these
cases).


7/28/21  [EDGcpfe/23954,EDGcpfe/24560]
Assertion failure in lower_reuse_value_expr with co_await expression

Although coroutine constructs currently are not lowered, the intent is they
should be usable in configurations that do lowering; they simply remain
unchanged in the lowered IL.  In certain cases, however, the IL for a
co_await expression could result in an assertion failure in
lower_reuse_value_expr.  This is now fixed.


7/27/21  [EDGcpfe/23803]
Source sequence entries and folded GNU statement expressions

In configurations with IL_SHOULD_BE_WRITTEN_TO_FILE, GNU_EXTENSIONS_ALLOWED,
and GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE, the front end could abort with
an IL write-read error when a GNU statement expression was eliminated from the
IL due to folding.  For example:

  constexpr int f(int x) { return x; }
  int g() {
    return f(({ 0; }));
  }

In some configurations the GNU statement expression "({ 0; })" was folded to a
simple zero constant and the expression was not kept in a backing expression.
That resulted in IL write-read errors.  That is now fixed.


7/27/21  [EDGcpfe/24372]
GNU C++ compatibility: Injected class names

Consider:

  struct S {} *p = new S::S;

This is normally invalid because "S::S" denotes the (implicitly-declared)
constructors of S rather than the injected class name.  However, in GNU C++
mode, this was previously always accepted.  Now, that GNU-C++-mode behavior is
limited to modes with gnu_version < 40500.


7/27/21  [EDGcpfe/24542]
Abort during rescanning of enk_variable nodes

The deduction of generic lambda invocations in local contexts can require the
front end to "rescan" (i.e., substitute) enk_variable nodes.  Version 6.2 of
the front end introduced a bug in this process that could lead to memory
corruption and aborts for somewhat complex uses of generic lambda expressions.
That is now fixed.


7/27/21  [EDGcpfe/24379]
Diagnostic for unused declarations in members of an unnamed namespace

The front end issues diagnostics for unused members of an unnamed namespace
(or a namespace nested within an unnamed namespace) because they are known
to not be used elsewhere.  This processing was incorrectly applied to
declarations such as local variables of members of an unnamed namespace,
which had the effect of disabling the more extensive checking that would
otherwise be done later (e.g., to suppress warnings on variable declarations
with side-effects).  The special processing is now done only for namespace
scope members of an unnamed namespace.  Other declarations are handled the
same way as if they were in a named namespace.

  template <typename T> struct A { A(T); };
  namespace {
    template <typename T> void f(T in) {
       A<T> xxx(in);  // warning no longer issued on this declaration
    }
  }
  struct B { };
  int main() { f(B{}); }


7/26/21  [EDGcpfe/24558]
Error in subsumption algorithm

Consider:

  template<typename T> concept A = true;
  template<typename T> concept B = true;
  template<typename T> concept C =  A<T> && B<T>;
  template<typename T> struct S;
  template<B T> struct S<T> {};  // (1)
  template<C T> struct S<T> {};  // (2)
  S<int> s;

(2) is more specialized than (1) because constraint C<T> subsumes constraint
B<T> and the reverse is not true.  However, an error in the algorithm
determining subsumption caused "the reverse" also to be considered true, which
in turn caused the front end to consider (1) and (2) ambiguous matches for
S<int>.  That is now fixed.


7/23/21  [EDGcpfe/24489]
C++-generating back end: inaccessible static data member as template argument

The changes for EDGcpfe/23723 (not in a release but sent to some customers
as a patch) caused a regression in which the C++-generating back end could
emit a template argument expression naming an inaccessible static data
member.  This is now fixed.  For example, with --c++14:

  template<typename, int> struct A { };
  class B {
    static constexpr int num = 0;  // private
    template<typename T> using AT = A<T, num>;
    AT<int> data;  // Instantiates A<int, 0>
  };
  A<int, 0> x;  // Previously generated as A<int, B::num>


7/23/21  [EDGcpfe/24550]
a_host_large_integer and a_host_large_unsigned

Previously, a_host_large_integer and a_host_large_unsigned were aliases for
types long and unsigned long when INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is
configured to FALSE.  On some platforms (e.g., 64-bit Windows) that caused
surprises because long is a 32-bit type but address arithmetic is done with
64-bit values.  For example, it revealed bugs in the constexpr interpreter,
which offsets host pointers with expressions involving a_host_large_integer:

  constexpr bool always_true() {
    int x[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int *p = x + 9;
    return p[-2] != 42;
  }
  static_assert(always_true());

In this example, the constant-evaluation of p[-2] could produce a corrupt host
address in some configurations.  That is now fixed by having, respectively,
a_host_large_integer and a_host_large_unsigned be aliases for ptrdiff_t and
size_t when INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is FALSE.


7/20/21  [EDGcpfe/24351]
C++-generating back end, Microsoft compatibility: dependent conversion
operators

MSVC has a bug that causes it to issue a spurious error when a reference to
a dependent conversion operator uses an explicitly-qualified name.  The
C++-generating back end previously put out such references, thus triggering
the bug.  This has now been addressed by omitting the explicit qualifier
for such references when msvc_is_generated_code_target is TRUE.  For
example, with --microsoft_version=1928 --parse_templates:

  template <typename T> struct S {
    template <typename U> operator S<U>() noexcept;
  };
  struct A { };
  template <typename T> void f() {
    S<A> sa;
    auto x = sa.operator S<T>();  // Previously generated as
                                  // sa.::S<A>::operator S<T>()
  }
  void g() {
    f<A>();
  }


7/19/21  [EDGcpfe/22810,EDGcpfe/24503]
GNU compatibility: In-class direct-initialization of a static data member

Consider:

  struct S {
    explicit constexpr S(int) {}
  };
  template<int> struct X {
    static constexpr S s{1};  // Previously an error in GNU C++ mode.
                              // Now okay.
    void f() { S r = s; }
  };
  template struct X<42>;

Previously, this triggered an error in GNU C++ modes claiming that the explicit
S::S(int) constructor cannot be used, because the front end incorrectly treated
"S{1}" as copy-list-initialization (when it is direct-list-initialization).
That is now fixed.


7/15/21  [EDGcpfe/24487]
Disqualify inline variables as candidates for module ID

When searching for a candidate for the module ID (used to ensure unique names),
the front end had previously considered inline variables, but no longer
does so.


7/15/21  [EDGcpfe/24415]
Segfault in mark_entry

A segfault in mark_entry had occurred when mangling certain abi_tags
(involving alias templates for function return types).  For example (with
--gnu_version 90300):

  namespace std {
    inline namespace __cxx11 __attribute__((__abi_tag__("cxx11"))) {}
  }
  template <class T> using X = T(int);
  struct S {
    friend X<void> f;
  };


7/14/21  [EDGcpfe/18931,EDGcpfe/23843,EDGcpfe/24515]
Failure to bind a no-throw function address from an overload set

Consider:

  int g(int);
  int g() noexcept;
  int (&rf)() = g;  // Previously an error.  Now okay.

Previously, the front front end required g() to have a type identical to the
type referred to by rf and thus this example was rejected because the exception
specification on the source and destination types did not match.  That is now
fixed and the example is now accepted.


7/13/21  [EDGcpfe/24512]
Multiple translation units: dependent inheriting constructors

When compiling multiple translation units, the front end could issue a
spurious "had a different meaning" error for a class template containing a
using-directive inheriting constructors of a dependent base class.  This is
now fixed.  For example, the following code resulted in a spurious error
when included in two different translation units:

  template<typename _Tp> struct A { };
  template<typename T, bool = A<T>::v> struct B { };
  template<typename> struct C;
  template<typename T, typename U> struct C<T U::*> : B<T U::*> {
    using B<T U::*>::B;  // Previously a "had a different meaning" error
  };


7/8/21   [EDGcpfe/24497]
GNU/Clang compatibility: Standard attributes with leading and trailing "__"

Attribute names that begin and end with "__" now have those underscores
stripped (in GNU and Clang emulation modes) when those attribute names appear
in a standard attribute context (previously such stripping only occurred in a
GNU-specific __attribute(()) context).  For example (with --g++ --c++20):

  int y [[__deprecated__]];
  [[__nodiscard__]] int f() { return 0; }
  struct S {
    [[__no_unique_address__]] int x;
  };

The use of [[__no_unique_address__]] in the GNU 11.1.0 <tuple> header had
caused a segfault at runtime when using std::thread::join.


7/7/21   [EDGcpfe/24495]
C++-generating back end: braced member initializers with explicit
brace-notation casts

In some cases in which the value of a default member initializer using the
braced form is an explicit cast that also uses brace notation, the
C++-generating back end omitted the outer braces, resulting in a syntax
error when the generated code was compiled.  This is now fixed.  For
example:

  struct A {
    constexpr A(float) { }
  };
  struct B {
    A m{ A{0.0F} };  // Previously generated as "m(A{0.0F})"
  };


7/7/21   [EDGcpfe/24488]
C++-generating back end, Microsoft compatibility: matching explicit
specializations of function templates

MSVC has a bug that sometimes fails to match an explicit specialization of
a function template with its primary template if the explicit
specialization relies on template argument deduction rather than explicit
template arguments.  In C++-generating back end configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, when
msvc_is_generated_code_target is TRUE a generated explicit specialization
was put out without an explicit template argument list if none of the
references to that template instance in the original source uses explicit
template arguments.  The generated C++ code could thus trigger the MSVC
bug.  This has now been addressed by putting out explicit template
arguments for all generated explicit specializations of function templates
when msvc_is_generated_code_target is TRUE.  (This was already the case
when clang_is_generated_code_target is TRUE; see EDGcpfe/21339.)  For
example, the explicit specialization for the function template "f" in the
following code resulted in a C2912 "not a specialization of a function
template" error when MSVC compiled the generated code:

  template<typename T, int V> struct A { };
  template<typename T, int V, typename = A<T, V>> struct B { };
  template<typename T, int V> B<T, 2*V> f(B<T, V>&);
  void g() {
    B<int,8> bi8;
    f(bi8);
  }


7/6/21   [EDGcpfe/24496]
C++-generating back end: variadic alias templates

The changes for EDGcpfe/22430 (in version 6.2) introduced a regression for
some cases involving variadic alias templates, causing the C++-generating
back end to use the underlying type of the alias template specialization
instead of the alias template itself, resulting in generated code that
could not be compiled.  This is now fixed.  For example,

  template <class...> struct a;
  template <int I> struct b {
    using c = void;
  };
  template <class... Ts> using d = b<sizeof...(Ts)>;
  // The following was previously generated as "b<sizeof...(a<Ts>)> ::c":
  template <class... Ts> using e = typename d<a<Ts>...>::c;


7/2/21   [EDGcpfe/23742]
Multiple translation units: dependent call to variable member of unnamed
namespace

In some cases when compiling multiple translation units, the front end
issued a "had a different meaning" error for a templated declaration
involving a dependent function call when the function name resolves in the
template definition context to a variable that is a member of an unnamed
namespace.  Such variables have internal linkage and thus are not the same
entity in different translation units, resulting in the diagnostic.
Although this usage is a violation of the C++ Standard's "one definition
rule," the front end has now been changed to accept this usage in some
cases.  For example, when the following code appears in more than one
translation unit, the call to the variable "x" no longer results in an
error on the declaration of the member function template d::f:

  struct h {};
  namespace {
    auto x = h{};
  }
  struct d {
    template <typename e> auto f(e bz) -> decltype(x(bz));
  };


6/28/21  [EDGcpfe/24022]
IL support for coroutine get_return_object_on_allocation_failure

The alloc_failure_gro_call member of the a_coroutine_descr IL entry
contains a pointer to an expression node for a call to the promise type
member get_return_object_on_allocation_failure (if such a member exists).
According to the C++ Standard, this function is to be invoked as if by an
expression of the form

  T::get_return_object_on_allocation_failure()

where T is the promise type.  Previously, however, the expression tree for
this node called the function as if by an expression of the form

  t.get_return_object_on_allocation_failure()

where t is the promise object.  In addition, the front end incorrectly
imposed several restrictions on the declaration of this function that are
not required by the Standard.  These issues are now fixed.


6/25/21  [EDGcpfe/24349]
Microsoft compatibility: using-directives vs class templates

Emulating early versions of MSVC (see the entry of 11/11/03), the front end
previously accepted (in microsoft_bugs mode) cases in which a
using-directive ambiguates the name of a class template, e.g.:

  namespace N {
    template <int I> class X {};
  }; 
  using namespace N;
  template <class T> class X {};
  X<int> xi;  // uses ::X

More recent versions of MSVC now issue an error for this code, so the front
end no longer accepts it with microsoft_version >= 1400.  This change also
affects the output of the C++-generating back end, which previously failed
to preserve qualification appearing in the original source needed to
disambiguate such cases.  That omission is now also fixed.


6/24/21  [EDGcpfe/24460]
GNU and Microsoft compatibility: std::align_val_t is predeclared

Microsoft and g++ allow the use of std::align_val_t without including <new>.
We now emulate this behavior in Microsoft and g++ modes when aligned operator
new is supported.

  std::align_val_t x;

6/23/21  [EDGcpfe/23366]
Assertion failure with nested co_yield

The front end previously aborted with an assertion failure in
i_copy_expr_tree when the source contains a nested co_yield expression.
This is now fixed.  For example, with --c++20:

  #include <coroutine>
  template <typename T> struct my_generator {
    struct promise_type {
      my_generator<T> get_return_object() { return {}; }
      std::suspend_never initial_suspend() { return {}; }
      std::suspend_never final_suspend() noexcept { return {}; }
      void unhandled_exception() {}
      auto yield_value(T value) {
        struct awaiter {
          bool await_ready() const noexcept { return true; }
          void await_suspend(std::coroutine_handle<>) const noexcept {}
          int await_resume() const noexcept { return 0; }
        };
        return awaiter{};
      }
      void return_void() {}
    };
  };
  my_generator<int> f() {
    co_yield 3, co_yield 4;  // Previously aborted
  }


6/23/21  [EDGcpfe/24431]
End-position of variable initializer involving constructor call

Consider:

  template<typename> struct X { X() noexcept(1); };
  struct S {
    X<int> xi;
  };
  void f() {
    S *s = new S();
  }

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the end position recorded for the
initializer of s was erroneous because the delayed scanning of the noexcept-
specifier of X::X() failed to fully restore the lexical state prior to the
scanning.  That is now fixed.


6/23/21  [EDGcpfe/23769]
Abort after defaulted operator<=> with a noexcept-specifier

Consider:

  #include <compare>
  template <bool NE> struct S {
    [[nodiscard]] auto operator<=>(S const&) const noexcept(NE) = default;
  };
  S<true> x;  // Previously aborted.  Now okay.

Previously, this aborted with an internal error in decl_member_function.
That is now fixed.


6/23/21  [EDGcpfe/23999]
Incorrect handling of __builtin_LINE, etc., in default arguments

Consider:

  consteval int f(unsigned int = __builtin_LINE()) {
    return 42;
  }
  void g(int = f()) {}  // Previously an error.  Now okay.

Previously, the front end issued an error because it never folded calls to
__builtin_LINE (or __builtin_COLUMN, __builtin_FILE, or __builtin_FUNCTION) if
such calls appeared in a default argument: In this case that produces an error
because f() is consteval and therefore must produce a constant result when it
appears in the default argument of the non-consteval function g().  That is now
fixed: The constant-evaluation of these built-in functions is now deferred in a
default argument only if that argument is for a consteval function.


6/22/21  [EDGcpfe/24457]
Spurious error for promise constructor with coroutine reference parameter

The front end previously reported a spurious error ("no default constructor
exists for class") for the promise type of a coroutine with a reference
parameter.  This is now fixed.  For example, with --c++20:

  #include <coroutine>
  struct A { };
  struct promise_type {
    promise_type(int);
    A get_return_object();
    auto initial_suspend() { return std::suspend_always{}; }
    auto final_suspend() noexcept { return std::suspend_always{}; }
    void unhandled_exception();
    void return_void() {}
    auto yield_value(int value) {
      return std::suspend_always{};
    }
  };
  template<typename R> struct std::coroutine_traits<R, int&> {
    using promise_type = promise_type;
  };
  A f(int& i) { co_return; }  // Previously a spurious error


6/22/21  [EDGcpfe/24399]
Implicit deduction guides and template constraints

Class template argument deduction (a C++17 feature) relies on "implicit
deduction guides", which are templates that are synthesized from the
declarations of class templates and their constructors and constructor
templates.  These implicit deduction guides have template parameters
that are distinct from those of the associated class templates and
constructors, but the front end previously failed to update any constraints
(a C++20 feature) associated with those class templates and constructors to
account for the new template parameters.  That could result in the deduction
process producing erroneous substitutions of the constraints, which likely
resulted in aborts later on.  That problem is now fixed.


6/22/21  [EDGcpfe/23920]
Internal error when a coroutine returns a non-class type

The front end previously aborted with an internal error (in
determine_dynamic_init_for_class_init) when the return type of a coroutine
is not a class type.  This is now fixed.  For example, with --c++20:

  #include <coroutine>
  struct promise_type {
    promise_type(int);
    int get_return_object();
    auto initial_suspend() { return std::suspend_always{}; }
    auto final_suspend() noexcept { return std::suspend_always{}; }
    void unhandled_exception();
    void return_void() {}
    auto yield_value(int value) {
      return std::suspend_always{};
    }
  };
  template<typename R> struct std::coroutine_traits<R, int> {
    using promise_type = promise_type;
  };
  int f(int i) { co_return; }  // Previously caused an internal error


6/21/21  [EDGcpfe/24400]
Spurious "pack not expanded" error on use of alias template

In some cases, the use of an alias template instance that refers to a
template parameter type that is a template parameter pack could result
in a spurious "parameter pack ... was referenced but not expanded"
error.  Now fixed.

  template <int> struct A { template <class U, class> using C = U; };
  template <class... Ts>
    using D = typename A<sizeof...(Ts)>::template C<Ts...>;
  template <class... Ts> struct E { D<Ts..., bool> d; };
  E<bool> e;


6/21/21  [EDGcpfe/23988,EDGcpfe/24109,EDGcpfe/24261,EDGcpfe/24441]
Microsoft compatibility: static data member in in-class specialization

The front end aborted (in decl_static_data_member) if an in-class
specialization of a class template declared a static data member.
Now fixed.

  template <typename T> struct A {
    template <typename U> struct B;
    template <> struct B<int> {
      static T t;
    };
  };


6/21/21  [EDGcpfe/24454]
Microsoft compatibility: value of _MSVC_LANG for --ms_c++latest

In accordance with new versions of Visual Studio, the front end now sets
the value of _MSVC_LANG to 202004L when --ms_c++latest is specified with
microsoft_version >= 1929.


6/18/21  [EDGcpfe/24061]
Assertion failure generating diagnostic output involving inheriting constructor

The changes to the implementation of inheriting constructors for
EDGcpfe/17687 (in version 6.1) introduced a regression resulting in a
failed assertion (in form_template_arg_info) for cases in which a
diagnostic is issued and the trace of instantiation contexts includes an
inheriting constructor.  This is now fixed.  For example, compiling the
following code with --c++14 --remarks -tused previously aborted attempting
to display a remark noting the use of a temporary in the call to f:

  template<typename T> void f(T &&);
  template <typename T, typename U> struct B {
    B(T) {
      f(T{}); // Previously caused an abort displaying a remark
    }
  };
  template <typename> class D : B<int, int> {
    using B::B;
  };
  template <typename T> void bar(T t) {
    D<char> d(t);
  }
  void foo() {
    bar(0);
  }


6/17/21  [EDGcpfe/23029,EDGcpfe/24157,EDGcpfe/24262]
Inheriting copy/move constructors with default arguments

The changes to the implementation of inheriting constructors for
EDGcpfe/17687 (in version 6.1) introduced a regression for cases in which a
class copy/move constructor that has a default argument is inherited by a
derived class.  This is now fixed.  For example, with --c++14:

  struct B {
    B(const B&, int = 0) { }
  };
  class D : B {
    using B::B;
    void f(const D &d) {
      D x(d, 1);  // Previously an error, "no instance of constructor matches"
    }
  };


6/16/21  [EDGcpfe/24324]
Constexpr comparison of pointers into dynamically-allocated storage

In C++20, constexpr evaluation can involve dynamic allocation.  Previously, a
bug in the constexpr address comparison code could result in an internal error
(in find_subobject_for_interpreter_address) when comparing pointers to a class
type subobject into such dynamically-allocated storage.  For example:

  struct S { int value; };
  constexpr bool g() {
    S *p = new S[10];
    bool r = p <= p + 10;  // Previously triggered an internal error in
    delete[] p;            // C++20 mode.  Now okay.
    return r;
  }
  static_assert(g());

That problem is now fixed.


6/15/21  [EDGcpfe/24202]
Microsoft and Clang C++ compatibility: Partial specializations in deductions

Consider (in C++11 modes):

  template<typename T, typename U> struct S {};
  template<typename T> struct S<T, T> {};
  template<typename T, typename U> struct S<T*, U*> {};
  template<typename ... Ts> using V = void;
  template<typename T, typename U = void> struct X {};
  template<typename T> struct X<T, V<typename S<T, T>::type>>;
  X<int*> xpi;  // Now accepted in Clang and Microsoft C++ modes.
  S<int*, int*>::undefined u = "hello";
                // Still an error.

Clang and MSVC accept the code above.  The definition of xpi is normally an
error because it requires resolving S<int*, int*> to a partial specialization
but the partial specializations of S are ambiguous for these arguments.  Now,
however, the front end treats that ambiguity as a deduction failure and thus
the primary template of X is selected for X<int*>.  Clang and MSVC appear to
essentially ignore the declaration of u after that, presumably due to an
inconsistent internal state: The front end does not attempt to emulate that
aspect of this example, and thus an error is still emitted for the declaration
of u.


6/15/21  [EDGcpfe/24417,EDGcpfe/24423]
Inheriting initializer-list constructors

Following the changes for EDGcpfe/24210, the front end failed to mark
inheriting constructors that have std::initializer_list parameters as being
initializer-list constructors and their classes as having an
initializer-list constructor.  This omission resulted in incorrect overload
resolution when an inherited initializer-list constructor in a class
template has a default argument.  This is now fixed.  For example, with
--c++11:

  #include <initializer_list>
  template <typename T> struct B {
    B(std::initializer_list<T>, int = 1);
  };
  template <class T> struct D : public B<T> {
    using B<T>::B;
  };
  D<int> di{0};  // Previously an error, "no instance of constructor matches"


6/10/21  [EDGcpfe/24385]
Properly emulate supported keywords of -fms-extensions

Previously, in both GNU and Clang mode when specifying --ms_extensions to
emulate -fms-extensions, the front end recognized a number of
Microsoft-specific keywords that are not recognized by the emulated compiler
(e.g., __try, __except, etc. for GCC; __clrcall, __event, etc. for Clang).
This is now fixed, and the front end now only adds the keywords supported by
the respective compiler when --ms_extensions is specified.

There are some notable exceptions where GCC and Clang implement a
Microsoft-specific language extension without the use of a keyword.  Until we
can reevaluate this decision, we will continue to support these language
features as keywords when --ms_extensions is specified.

The specific keywords for GCC mode are: __if_exists, __if_not_exists, and
__declspec.

The specific keywords for Clang mode are: __assume, __noop, __except, __w64,
__int16, __int64, and __unaligned.


6/9/21   [EDGcpfe/23094]
Coroutine promise type with overloaded return_value member functions

In cases in which a coroutine promise type has overloaded return_value
member functions, the front end could abort with a segfault.  This is now
fixed.


6/9/21   [EDGcpfe/24404]
Performance with large multi-line raw string literals

A change has been made to improve the performance of the front end when
processing multi-line raw string literals.  For very large literals
(containing tens of thousands of lines), the improvement could be
significant.


6/8/21   [EDGcpfe/24192]
GCC 11.x compatibility: Default to C++17

In GCC 11.x GNU changed the default C++ mode to C++17.  We now emulate this
behavior, and GNU C++ mode with gnu_version >= 110000 now defaults to C++17.


6/8/21   [EDGcpfe/24359]
MS Compatibility: Support "msvc" attribute namespace

The "msvc" attribute namespace is now recognized.  In addition, the front end
now recognizes (and does no further processing for) the "known_semantics" (when
microsoft_version >= 1927) and "noop_dtor" (when microsoft_version >= 1928)
attributes within that namespace.


6/4/21   [EDGcpfe/23670]
Spurious Clang-mode error on use of overloaded templates

Consider:

  struct S {
    template<typename T> S(T&);
    template<typename T> S(T&&);
    S();
  };
  struct R { R(); };
  const R r;
  S s(r);  // Previously an ambiguity in some Clang C++11 modes.  Now okay.

In GNU C++11 modes with gnu_version < 40900 this is ambiguous.  However, the
front end also treated Clang modes in the same way when gnu_version < 40900.
That is now fixed: The case is now always accepted in Clang C++11 modes.


6/4/21   [EDGcpfe/24283]
GNU compatibility: Result of __builtin_memcmp in interpreter

In cases where the first and second arguments to the __builtin_memcmp routine
point to the same object, GNU appears to return 0 regardless of the size
specified and the front end now emulates that.  The following example (with
--g++ --c++14) is now accepted even though the size is longer than the
length of the input strings:

  constexpr const char *a = "abc";
  constexpr const char *b = a;
  static_assert(__builtin_memcmp(a, b, 99) == 0);


6/3/21   [EDGcpfe/24370]
C++-generating back end: variables with dependent deduced types

In configurations in which the C++-generating back end generates template
definitions from the prototype instantiation IL, the C++-generating back
end produced incorrect code using an undeclared temporary name (of the form
__T12345678) for the declaration of a variable whose type is deduced from a
dependent initializer expression.  This was a regression introduced by the
changes for EDGcpfe/23498 in version 6.2 and is now fixed.  For example,
with --c++17 --g++:

  template<typename T> T&& f(T&);
  template<typename T> void g() {
    T t;
    auto x(f(t));  // Previously generated as "x(__T12345678(f(t)))"
  }


6/3/21   [EDGcpfe/23771]
Microsoft compatibility: Trivial copyable structs with const members

Consider:

  struct X {
    int i;
    X() = default;
  };
  struct S {
    const X x;
  };
  static_assert(__is_trivially_copyable(S), "");
  static_assert(__is_trivial(S), "");

In Microsoft mode with microsoft_version >= 1927, both assertions now pass,
whereas previously they both failed.  Having the first assertion succeed is
an improvement since S is indeed trivially copyable.  However, S is not a
"trivial class" because its (implicit) default constructor is deleted; we
thus emulate a bug of the Microsoft compiler for that case.


6/3/21   [EDGcpfe/24303]
Inert macro names appearing in diagnostic output with macro positions

When a macro name appears in its own expansion, it is marked as "inert" and
treated as a simple identifier.  If the use of that identifier results in a
diagnostic, the front end could abort with a segfault in configurations in
which diagnostic output includes macro context information.  For example,
with --microsoft --c99 --macro_positions_in_diagnostics, the following
resulted in a segfault attempting to display a warning about the implicit
declaration of the function "bar" (the inert macro name):

  #define bar2(a) bar(a)
  #define bar(a) bar2(a)
  #define foobar(a) bar(a)
  void f(void) {
    foobar(1);  /* Previously caused a segfault displaying the macro
                   invocation stack. */
  }


6/3/21   [EDGcpfe/24364]
Standard attribute "maybe_unused" diagnostics and compatibility

Consider:

  namespace {

  [[maybe_unused]] const int z = 1;

  void foo() {
    [[maybe_unused]] const int y = 1;
  }

  }  // namespace

Previously, the front end would report warnings for unused variables even if
annotated with the "maybe_unused" standard attribute.  This is now fixed, and
warnings are no longer emitted for these variables.

Additionally, two compatibility issues have been fixed.  For both GNU mode with
gnu_version >= 70100 and Clang mode with clang_version >= 30900, the front end
now recognizes the "maybe_unused" standard attribute in C++ mode for C++11 or
later.


6/3/21   [EDGcpfe/23953,EDGcpfe/24298]
Spurious narrowing error on some template arguments

Consider:

  struct S {
    unsigned int x;
    constexpr S(unsigned int x): x(x) {}
  };
  template<int> void g();
  int main() {
    constexpr S s(42);
    g<s.x>();  // Previously an error.  Now okay.
  }

Previously, the call g<s.x>() produced an error because s.x was not folded
prior to checking for a narrowing conversion (after folding, the known value
42U for s.x causes the conversion from unsigned int to int not to be a
narrowing conversion).  That is now fixed.


6/2/21   [EDGcpfe/23870]
C++-generating back end: enum types and GNU "mode" attribute

Consider (in GNU C++ mode):

  typedef enum { e } E __attribute((mode(word)));
  E x = e;

Previously, the C++-generating back end did not render the enum type (it was
just replaced by an integer type like "long"), and thus the rendered code for
"E x = e;" would refer to an "e" that was never declared.  That is now fixed
by treating the enumeration type definition as an "autonomous" definition,
which results in the code above to be rendered as something like:

  enum { e };
  typedef long E __attribute((mode(word)));
  E x = (e);


6/2/21   [EDGcpfe/24113]
C++-generating back end: dependent operator< template argument list

In configurations in which template definitions are generated from the
prototype instantiation IL, a function-style invocation of an operator<
template with an explicit template argument list appearing in a template
definition resulted in the C++-generating back incorrectly concatenating
the "<" of the operator function name with the "<" of the template argument
list.  This is now fixed.  For example, with --g++:

  template<typename T> bool operator<(T, T);
  template<typename T> void f() {
    operator< <int>(T(), 0);  // Previously generated as "operator<<int>"
  }


6/2/21   [EDGcpfe/24389]
Spurious consteval failure in temmplated contexts

Consider:

  consteval long p(unsigned) { long r = 1; return r; }
  template<typename T, typename U> struct X {};
  template<int, int> struct Y {};
  template<typename> struct S {
    static constexpr int f() { return 1; }
    static constexpr unsigned u = { f() };
    using P = X<int, Y<1, p(u)>>;  // Previously an error.  Now okay.
  };

Previously, the front end issued an error about p(u) being a call to a
consteval function that doesn't produce a constant.  That is now fixed.


6/2/21   [EDGcpfe/24393]
Microsoft compatibility: problem with ADL using-directive lookup emulation

In permissive Microsoft mode we emulate a quirk of the Microsoft compiler
where it ignores certain namespaces during argument-dependent lookup if
those namespaces were searched during the normal lookup (see EDGcpfe/9368).
Our emulation incorrectly ignored using-directives that appeared after the
point at which the lookup was effectively being done.  Now fixed.

  namespace std {
    template <class T> T&& declval() noexcept;
  }
  float h(int *) { return 1; }
  namespace N1 {
    namespace N2 {
      struct A{};
      int h(A *) { return 2; }
    }
    template<typename T> struct B {
      // Resolved to incorrect function h
      template<typename U> static decltype(h(std::declval<U*>())) test(int);
      typedef decltype(test< N2::A >(0)) type;
    };
    template <typename T> void f() { B<float>(); }
    void g() { f<double>(); }
    using namespace N2;
  }


6/1/21   [EDGcpfe/20413,EDGcpfe/22068,EDGcpfe/22974,EDGcpfe/24354]
Spurious error on reinterpret_cast

In some cases, the front end issued a spurious error about casting away
constness with a reinterpret_cast expression.  For example:

  char data[42];
  auto r = reinterpret_cast<char const**>(&data);
             // Previously resulted in a (spurious) error.  Now okay.

That is now fixed.


6/1/21   [EDGcpfe/22008]
Type-transforming attributes for alias templates

Consider:

  template<typename T, int N>
  using V [[gnu::__vector_size__(N)]] = T;

The front end previously treated type-transforming attributes (e.g., the above
gnu::__vector_size__ attribute) when applied to alias templates as no-ops. This
is now fixed, and type-transforming attributes will now work as expected in
alias templates.


6/1/21   [EDGcpfe/24392]
GNU compatibility: GCC 9.4.0 builtins

No new builtins were introduced in GCC 9.4.0, but the builtin_def.h file
has been modified to reflect availability of certain builtins when
gnu_version == 90400.


5/28/21  [EDGcpfe/24361]
C++-generating back end: g++ 11.1 compatibility

In certain complex cases (once such example appears in the gcc version 11.1
<chrono> header), the C++-generating back end could produce correct output
that nevertheless caused g++ to encounter an internal error when compiling
the generated code.  This is now fixed.


5/26/21  [EDGcpfe/24339]
Alias templates in diagnostics

Consider the following (erroneous) example:

  template<typename T> struct S {
    typedef T Type;
  };
  template<typename> struct X {};
  X<S<int>::Type> xsi = 42;  // Error: conversion failure.

By default, the diagnostic for the last line expresses the destination type as
"X<int>" instead of "X<S<int>::Type>"; i.e., it "looks through" instantiations
of member typedefs, since that is usually more helpful to analyze the cause of
the error.  Now the same occurs with instantiations of alias templates.
For example:

  template<typename T> using A = T;
  template<typename> struct X {};
  X<A<int>> xsi = 42;  // Error: conversion failure.

By default the diagnostic for this example now also mentions "X<int>", whereas
previously it mentioned "X<A<int>>".  With both examples, the original form can
be produced with the command-line option --template_typedefs_in_diagnostics.


5/26/21  [EDGcpfe/24360]
Spurious error on certain dependent uses of the unary "*" operator

Consider, in C++20 mode:

  template<typename T> concept D = requires(T &&p) {
    *(decltype(p)&&)p;  // Previously a spurious error.  Now okay.
  };

The front end previously spuriously diagnosed the use of the unary "*" in
this example.  That is now fixed.


5/25/21  [EDGcpfe/23677]
Microsoft compatibility: Size of pointer-to-member types

The front end does not currently implement the Microsoft C++ ABI per se (even
though it implements some Microsoft-specific behaviors in that area, such as
the bit field layout strategy).  Now, however, it can be configured to compute
the same size as the Microsoft compilers for pointer-to-member types when IL
lowering is disabled.  A new macro TARG_MICROSOFT_PTR_TO_MEMBER_SIZING can be
configured to TRUE to enable that behavior (or a variant of that macro for a
specific target configuration).  The Microsoft ABI size of pointer-to-member
types depends on the "inheritance kind" of the associated class.  Previously,
the front end identified four values for that kind: ihk_none, ihk_single,
ihk_multiple, and ihk_virtual.  Now, an additional value ihk_incomplete has
been introduced to describe cases where a pointer-to-member type is formed
while the inheritance kind of the associated class is not known yet.  For
example:

  struct I;
  static_assert(sizeof(char I::*) == 3*sizeof(int), "");
    // Now accepted when TARG_MICROSOFT_PTR_TO_MEMBER_SIZING is TRUE.

The global variable default_inheritance_kind has been removed (it previously
decided the inheritance kind assigned to incomplete classes associated with
pointer-to-member types).


5/21/21  [EDGcpfe/24188]
Old-style specializations

Previously, the front end accepted old-style explicit specializations (i.e.,
without the "template<>" prefix) by default in many nonstrict C++ modes (unless
the configuration macro DEFAULT_OLD_SPECIALIZATIONS_ALLOWED is set to FALSE).
Now, it no longer does so by default in C++11 modes, nor in GNU C++ modes with
gnu_version >= 30400 (although in GNU modes, an exception is made for old-style
explicit class template specializations that are not definitions).


5/21/21  [EDGcpfe/24227]
Equality folding in GNU and Clang C++ modes

The front end emulates a GCC behavior where expressions like "x == x" (with x a
variable that is not constant-valued) are treated as constant-expressions.
Previously, that emulation was accidentally enabled in Clang modes (because
they are internally treated as variants of corresponding GNU modes): That is no
longer the case.  Furthermore, that behavior is no longer emulated in GNU C++03
modes or in GNU C++11 modes with gnu_version >= 60000 (this matches the
observed behavior of various GCC versions).  The behavior is still enabled in
all GNU C modes.  For example:

  void g(int x) {
    enum { e = x == x ? 1 : -1 };  // Now an error in Clang modes, in GNU C++03
  }                                // modes, and in GNU C++11 modes with
                                   // gnu_version >= 60000.


5/21/21  [EDGcpfe/24358]
Subscript operations converted to prvalues

Consider:

  int const volatile *p;
  void f() {
    int y = p[0];
  }

The IL entry representing p[0] is an expression node with type int because that
expression undergoes a glvalue-to-prvalue conversion that drops the const and
volatile qualifiers.  In such cases, the an_expr_node::orig_lvalue_type field
should record the type prior to that conversion, but it failed to do so for
subscript operations.  That is now fixed.


5/20/21  [EDGcpfe/24332]
Microsoft compatibility: C Standard _Pragma for all modes

Microsoft mode when emulating Visual Studio 16.5 or later would previously
require at least C99 to be specified for the C Standard _Pragma to be
recognized.  This is now fixed.

In Microsoft mode 16.5.x and later, with --c or --c++:

  _Pragma(once) // Previously invalid. Now valid.

In Microsoft mode 16.4.x and earlier, with --c or --c++:

  _Pragma(once) // Previously invalid. Still invalid.


5/20/21  [EDGcpfe/24198]
GNU Compatibility: GCC 9.x+ single argument _Static_assert

GCC mode when emulating GCC 9 or later would previously error when encountering
a single argument _Static_assert.  This is now fixed.

In GCC mode 9.x and later:

  _Static_assert(1); // Previously invalid.  Now valid.

In GCC mode 8.x and earlier:

  _Static_assert(1); // Previously invalid.  Still invalid.


5/18/21  [EDGcpfe/24334]
C++-generating back end: array, pointer, and reference casts in initializers

The C++-generating back end could put out an initializer expression as a
functional-notation cast even when the type is an array, pointer, or
reference type, which is a syntax error.  This is now fixed, and a C-style
cast is used instead.  For example, with --c++20:

int (&&r)[3] = static_cast<int[3]>(0);  // Previously generated as int[3](0)


5/17/21  [EDGcpfe/24328]
__FILE__/__BASE_FILE__ with non-ASCII file names

In some locales, using the __FILE__ or __BASE_FILE__ predefined macros with
a file name containing non-ASCII characters could produce incorrect
results, with some, but not all, bytes of a multibyte character being
replaced by octal escapes.  This is now fixed.


5/17/21  [EDGcpfe/24329]
GNU Compatibility: GCC 8.5.0 builtins

A change has been made to extend the GCC 8.4.0 builtins to GCC 8.5.0 (i.e.,
there are no changes to the builtin signatures themselves, but certain builtins
are now available with gnu_version == 80500).


5/16/21  [EDGcpfe/23825]
Spurious access error using protected inheriting constructor

The front end could issue a spurious access error on a reference to an
inherited protected constructor.  Now fixed.

  struct A {
    static void f();
  protected:
    A(int);
  };
  struct B {
    B(A*);
  };
  struct C : public A {
    using A::A;
    static void f() {
      A::f();
    }
  };
  inline void A::f() {
    B p(new C(99));
  }


5/14/21  [EDGcpfe/24289]
Assertion failure in perform_post_pass_on_lowered_expression

In configurations that do lowering and have EXPENSIVE_CHECKING set to TRUE,
an assertion failure (in perform_post_pass_on_lowered_expression) had been
introduced in version 6.2 as a result of the changes for EDGcpfe/20535.
The change caused an internal IL consistency check to fail on cases such as:

  int a;
  volatile int b;
  int main() {
    const int N = 10;
    int i = 1;
    a = (i > 0 ? b : N) - b;
  }

The internal consistency check has been modified to allow such cases.


5/14/21  [EDGcpfe/23731]
Abort in C++-generating back end on specialization of static data member

Consider:

  template<int I> struct S {
    static constexpr int N = I;
  };
  template<> constexpr int S<1>::N = 100;

In C++17 mode, the front end previously aborted with an internal error in
gen_variable_decl, because the source sequence entry associated with the
explicit specialization did not record a "declared type".  That is now fixed.


5/14/21  [EDGcpfe/24309]
C-generating back end: memcpy, memset, bcopy, bzero declarations

Previously the C-generating back end unconditionally emitted un-prototyped
declarations for builtin functions memcpy, memset, bcopy, and bzero; now those
declarations are emitted as prototyped declarations.  This avoids the warnings
that some back end compilers (e.g., gcc 11.1.0) emit when compiling the
generated code.


5/13/21  [EDGcpfe/23296,EDGcpfe/23831]
Value category of selection through pointer-to-data-member

Consider:

  struct S { int i; };
  int S::*pmd = &S::i;
  S f();
  int &&r = f().*pmd;  // Previously an error in many modes.  Now okay.

Previously, the expression "f().*pmd" was treated as an lvalue in many modes.
Now it's an xvalue in non-Microsoft C++11 mode.  In Microsoft mode it's still
an lvalue when microsoft_version < 1900, and a prvalue otherwise (which
reflects the behavior of the Microsoft compiler).


5/13/21  [EDGcpfe/23724,EDGcpfe/23940,EDGcpfe/24251,EDGcpfe/24267]
C++-generating back end: incorrect parameter name in template definition

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end could erroneously
put out references to template parameters in a class template definition
using the name of a parameter of a previous template declaration.  This is
a regression introduced in version 6.1 by the changes for EDGcpfe/22562.
The error occurred when the class template is used in class template
argument deduction and the referenced template parameter has a default
argument.  This is now fixed.  For example, with --c++17
--gnu_version=90100:

  template<typename XXX> struct Z;
  template<typename T = short> class S {
    T t;  // previously generated as "XXX t;"
  };
  int main() {
    S x;  // class template argument deduction
  }


5/13/21  [EDGcpfe/22472,EDGcpfe/23539,EDGcpfe/23840]
Constant-evaluation of pointer and pointer-to-member casts

The front end was previously unable to constant-evaluate certain pointer and
pointer-to-member casts: That is now fixed.  For example:


  struct S {
    int const *const *p;
    constexpr S(int **p) : p(p) {}
  };
  constexpr S sp(nullptr);  // Previously an error because the conversion
                            // in the mem-initializer was not supported.
                            // Now okay.


5/12/21  [EDGcpfe/24213]
GNU C++ compatibility: Severity of narrowing conversion in return expression

In GNU C++ mode, the front end now issues a warning instead of an error when
encountering narrowing in a braced return construct.  For example:

  struct S { short x; };
  S g(int p) {
    return { p };  // Previously an error in GNU C++11 mode.  Now a warning.
  }


5/12/21  [EDGcpfe/23969]
Extraneous destructor call in conditional operator

In some cases involving a combination of list-initialization and aggregate
initialization within a branch of a conditional operator, the lowered IL failed
to skip the destruction of temporaries in the non-executed branch of that
operator.  For example:

  #include <initializer_list>
  extern "C" int printf(const char*,...);
  
  template<typename T> struct V {
        V(std::initializer_list<T>) { printf("Ctor\n"); }
        ~V() { printf("Dtor\n"); }
  };
  struct S { V<char> data; } ;
  struct W { void f(S&&) {} };
  int main() {
    W p;
    bool detected = true;
    detected ? p.f({{0x01}}) : p.f({{0x02}});
  }

Code generated from the lowered version of the IL would cause the resulting
program to output

  Ctor
  Dtor
  Dtor

(the last line is extraneous).  This was the consequence of the dynamic
initializer flag "inside_conditional_expression" not being set to TRUE in
an entry of the unlowered IL.  That is now fixed.


5/12/21  [EDGcpfe/23989]
GNU and Microsoft C++20 compatibility: Ambiguous comparisons

Consider the following C++20 code:

  template<typename T> struct S {
    S() {}
    template<typename U> S(S<U> const&) {}
    bool operator==(S const&) { return true; }
  };
  S<int const> x;
  S<int> y;
  auto r = x == y;  // Ambiguous in standard C++20, but accepted in
                    // Microsoft and GNU modes.

The overload resolution process for "x == y" considers two candidates:
  1) the normal member operator S<int const>::operator==, and
  2) the operator S<int>::operator== that results from trying
       the comparison in reversed order.
The first candidate matches exactly on the x operand, but requires a
(user-defined) conversion on the y operand.  The second candidate, however,
has opposite matches: x requires a user-defined conversion and y matches
exactly.  Such situations are always ambiguous in standard C++, but GCC and
Microsoft appear to introduce a tie breaker for this specific pattern.  The
front end now emulates this by discarding the "reversed-operands" candidate
if it is the only competing candidate for a comparison where the other
candidate is generated from the same function or templated entity.  That
causes the example above to be accepted in Microsoft and GNU C++20 modes.


5/12/21  [EDGcpfe/24310]
C++-generating back end: parenthesized zero-initialization expressions

In some circumstances, the C++-generating back end could put out redundant
parentheses enclosing an explicit zero-initialization temporary.  In
certain expressions, the resulting expression formed a cast to a function
type, leading to uncompilable generated code.  For example, with --c++17
--gnu_version=100200:

  struct S {
    S() {};
    S(const S &other) {};
  };
  int operator+(S, S) {
    return 0;
  }
  template<typename T> int f() {
    return S() + S();
  }

The expression in the return statement of f() was previously generated as
"((S()) + (S()))", which is parsed as a cast to the function type "S()" of
the result of applying the unary "+" operator to S().  This is now fixed,
and the redundant parentheses are now suppressed in such cases.


5/11/21  [EDGcpfe/24238]
Assertion failure displaying IL containing designated initializers

Displaying the intermediate language, via either the edgcpdisp utility or
the --il_display command-line option (see EDGcpfe/23906), when
gcc_or_clang_is_generated_code_target is TRUE and the IL contains a
compiler-generated designated initializer could result in an assertion
failure in form_constant.  This is now fixed.  For example, with --g++
--c++20 --il_display, the following example caused an assertion failure
because of the initialization of the second member of the union:

  template<typename T> struct B {
    union {
      struct {
        T e[4];
      };
      struct {
        T x;
      };
    };
    constexpr B(T x): x(x) { // assertion failed on IL for this initialization
    }
  };
  template<typename T> class D : public B<T> {
    constexpr D(const T x_) : B<T>(x_) {}
    static const D<T> m;
  };
  template<> constexpr D<float> D<float>::m = D<float>(1.f);


5/11/21  [EDGcpfe/24272]
GNU Compatibility: __gnu__ attribute namespace not recognized

Previously when encountering the attribute namespace "__gnu__" the front end
would warn that "__gnu__" is not a recognized namespace and fail to recognize
attributes within the namespace.

This is now fixed, and the front end now recognizes the "__gnu__" attribute
namespace as equivalent to the "gnu" attribute namespace.  As an example, the
following are now equivalent:

  static void foo [[gnu::unused]] (void) { }
  static void foo [[__gnu__::unused]] (void) { }


5/7/21   [EDGcpfe/23909,EDGcpfe/23910]
Incorrect substitution of some nontype template arguments

Consider:

  template<typename T, T V> struct C { static constexpr T value = V; };
  struct HasConstexpr {
    template <typename T> static auto test(int) -> C<bool, (T{}.f(), true)>;
    template <typename T> static auto test(...) -> C<bool, false>;
  };
  template<typename T> constexpr bool hasConstexpr() {
      using X = decltype(HasConstexpr::template test<T>(0));
      return X::value;
  };
  struct WithConstexpr { constexpr int f() { return 0; } };
  struct WithoutConstexpr { void foo(); };
  static_assert(hasConstexpr<WithConstexpr>(), "");
  static_assert(!hasConstexpr<WithoutConstexpr>(), "");

Previously, this triggered spurious errors because of a pair of bugs in the
code handling substitution of nontype template arguments (particularly, the
substitution of "T{}.f()" in this example).  Those bugs are now fixed and the
example above is now accepted (in C++11 and later modes).


5/6/21   [EDGcpfe/24284]
C++-generating back end: parenthesized braced constant aggregate initializers

The C++-generating back end incorrectly replaced a parenthesized braced
constant initializer with a form using only parentheses, resulting in
generated code that could not be compiled.  This is now fixed.  For
example, with --c++14:

  typedef struct {
    double a, b;
  } S;
  void f() {
    S s({1, 0});  // Previously generated as "s(((1), (0)))"
  }


5/6/21   [EDGcpfe/24210]
Abort when inheriting constructors with default arguments in nested classes

The front end could abort in copy_param_type_list when attempting to copy the
default arguments of a constructor being inherited that belongs to a nested
class.  For example:

  struct A {
    struct B {
      B(int x = 0) { }
    };
    struct C : B {
      using B::B; // Abort triggered here
      C(void *);
    };
  };
  A::C c;

This is now fixed.


5/6/21   [EDGcpfe/23468]
Multiple translation units: Spurious incompatibility diagnostic on function
templates

When compiling multiple translation units, the front end could issue a spurious
diagnostic complaining that two identical routines are incompatible due to
their exception specifications when the exception specification is instantiated
in one TU but not the other.  For example, the front end would issue a spurious
diagnostic when compiling two TUs that both contain:

  template<typename T> struct Empty {};
  template<typename T> struct Bad {
    // Spurious diagnostic issued when X below is instantiated in only one TU
    template <typename... l> Bad() noexcept(Empty<l...>::val2);
  };
  template<typename T> struct S1 {
    S1();
    Bad<T> var;
  };
  template<typename T> void func() {
    S1<char> var;
  }
  template<typename T> class S2;
  template<> class S2<char> {
    void foo() {
      func<char>();
    }
  };
  template<typename T>
  struct X {
    X() {
      S1<char> var;
    }
  };

and one TU also contains:

  void f() {
    X<int> var;
  }

This is now fixed.


5/5/21   [EDGcpfe/24221]
Abort in deduce_auto_type on specialization of deleted member

Consider:

  template <class ...Ts> struct S {
    static auto& f() = delete;
  };
  template <> inline auto &S<>::f() {
    int x = 42;
    return x;
  }

Previously this aborted in deduce_auto_type (overload.c).  That is now fixed.


5/5/21   [EDGcpfe/18134,EDGcpfe/20669,EDGcpfe/24253]
Vector operations handled incorrectly in constexpr interpreter

Ordinarily, attempting to perform a constexpr operation not supported by the
interpreter causes the interpreter to report an interpretation failure.
However, for certain vector operations that were not previously supported
(like addition), the interpreter did not report a failure and produced
unpredictable results instead.  The interpreter has been updated to support a
variety of vector operations, and to more reliably fail interpretation for
unsupported operations.  For example:

  using V __attribute__((vector_size(4))) = unsigned char;
  constexpr auto f() {
    auto a = V{1, 2, 3, 4};
    auto b = V{1, 2, 3, 4};
    return a + b;
  }
  auto r = f();  // Previously produced unpredictable results.  Now okay.


5/4/21   [EDGcpfe/23467]
Multiple translation units: Spurious diagnostic about mismatched using decls,
failure to mix function attributes when one TU has GNU function multiversioning

When compiling multiple translation units, the front end would issue a spurious
diagnostic stating that a class declaration that contains a base class using
declaration was incompatible with an identical class declaration in another TU.
For example, if two TUs both include a header containing:

  struct Base {};
  struct Derived : Base
  {
    using Base::Base; // Triggers a spurious "Derived is incompatible" error
  };

In addition, when one TU uses GNU function multiversioning while the other
doesn't, the front end could issue spurious diagnostics and/or segfault when
diagnosing missing attributes in verify_attr_corresp_one_way.  For example,
if two TUs both include a header containing:

  inline void __attribute__((__gnu_inline__)) foo() {}

and one TU contains (prior to the #include):

  #pragma GCC target "sse2"

the front end would issue a spurious diagnostic about the __gnu_inline__
attribute missing on foo() in one of the TUs, and then potentially segfault
(depending on which TU contained the pragma).  These issues are now fixed.


5/4/21   [EDGcpfe/24122,EDGcpfe/24208]
GNU C++ compatibility: abort when GCC target attribute is used with templates

An abort would occur (in attach_attributes_to_routine_instance) if a GCC
target pragma was used in a context in which the associated attribute
would be applied to a member function of a class template.  Now fixed.

  #pragma GCC target ("avx")
  template <typename T> struct A {
    const T* f() { return nullptr; }
  };
  int main() {
    A<char> a;
    a.f();
  }


5/3/21   [EDGcpfe/24259]
Abort after using-declaration for assignment operator

Consider:

  template<typename T> struct X: T {
    X& operator=(const X& other) = default;
    using T::operator=;
    X& operator=(X&&) noexcept;  // Previously triggered an internal error.
  };

Previously, the using-declaration introduced a symbol for the assignment
operator without also updating the assignment operator entry in the symbol
supplement for the associated class.  That triggered an internal error when
attempting to add the subsequent assignment operator to its overload set.
That is now fixed.


4/29/21  [EDGcpfe/22034]
Incorrect size for an empty class with no virtual bases

In IA-64 ABI modes with re-used tail padding, when handling a non-POD empty
class (e.g., a lambda closure class), the front end could incorrectly record
the size_without_virtual_base_classes field in the associated
a_class_type_supplement as zero, rather than the appropriate size for an empty
class.  This could cause some spurious failures and incorrect treatment of a
class without virtual bases as if it had virtual bases.  For example, with
multiple translation units (with IA64_ABI == TRUE and
DEFAULT_REMOVE_UNNEEDED_ENTITIES == FALSE), the front end would previously
abort in set_parent_scope when two TUs both included a header containing:

  template<class T> struct my_vector {
    typedef T element_type;
    element_type const &front() const {return __ptr[0];}
  private:
    element_type *__ptr;
  };
  template<class T> struct my_shared_ptr {
  public:
    typedef T element_type;
    element_type *__ptr;
  };
  struct SubscriptionCountByTag
  {
    SubscriptionCountByTag(SubscriptionCountByTag const& other);
    virtual ~SubscriptionCountByTag();
  };
  struct SubscriptionCountByTypedInstance
  {
    void foo() const
    {
      // Previous abort in set_parent_scope when processing this entity in a
      // secondary TU
      [](my_shared_ptr<SubscriptionCountByTag> const& subCount) {
      }(tagCounts_.front());
    }
  private:
    my_vector<my_shared_ptr<SubscriptionCountByTag>> tagCounts_;
  };

This is now fixed.


4/28/21  [EDGcpfe/24228]
GNU compatibility: GCC 11.1.0 builtins

Signatures for builtin functions have been updated to reflect the GCC 11.1.0
release.


4/23/21  [EDGcpfe/23972,EDGcpfe/23973,EDGcpfe/24178]
Internal errors when substituting certain requires-expression

The front end previously aborted with an internal error (usually indicating an
unexpected template-dependent construct) when substituting certain
requires-expressions.  For example:

  template<typename T> struct X { X(T); };
  template<typename T> T&& f(T);
  template<typename T> constexpr void g(T t) {
    requires { X{ f<T>(t) }; };
  }
  struct S {};
  int main() {
    g(S{});  // Previously triggered an abort.  Now okay.
  }

That is now fixed.


4/22/21  [EDGcpfe/23703,EDGcpfe/23939,EDGcpfe/23948,EDGcpfe/24163,
          EDGcpfe/24197]
Trailing requires clauses on non-templates

Consider:

  template<typename T>
    concept C1 = requires(T t) { t.f(); };
  template<typename T> requires C1<T&> void f(T&&);
  template<typename T>
    concept C2 = requires(T &t) { f(t); };
  template<typename T> struct B {
    void g() requires C2<T>;  // (1)
  };
  struct D: B<D> {  // (2)
    int f();
  };
  int main() {
    f(D{});  // (3)  Previously an error.  Now okay.
  }

Line (2) causes the instantiation of line (1) with T=D where D is still
incomplete.  Previously, that included instantiating the trailing requires
clause C2<T>, which found an unsatisfied constraint C1<D&> because T=D is
still incomplete.  Since constraint evaluations are cached (as the standard
permits), this resulted in the call on line (3) to fail to find a viable
candidate (the candidate f<D> also requires the constraint C1<D&>).  The
C++20 standard, however, does not actually permit the instantiation of the
constraint in line (1) until the member g() that it declares is used in
some way that requires the constraint to be known.  The front end now
implements that on-demand behavior for such trailing requires clauses, and
as a consequence it now also accepts the example above (a variation of that
situation appears in at least one standard-library implementation).



4/22/21  [EDGcpfe/24185]
Diagnostics for invalid reinterpret_cast-like operations

Consider:

  template<char (*)()> struct S {};
  int f();
  S<(char (*)())f> x;  // Previously accepted.  Now an error.

The cast in the template argument for S has reinterpret_cast semantics, which
the standard does not allow.  Previously, however, the front end did not
diagnose the error.  Now, it does, except in Microsoft C++ modes (because
current Microsoft compilers still accept such code).


4/22/21  [EDGcpfe/22347,EDGcpfe/24008,EDGcpfe/24036]
C++20: Modules Dependency Discovery (P1857R3)

A change has been made to implement committee paper P1857R3, which deals with
restricting the syntax of the C++20 modules feature to enable fast dependency
scanning via partial preprocessing.


4/22/21  [EDGcpfe/21185,EDGcpfe/24187]
Spurious error on union member designator in GNU and Clang C++ modes

Consider:

  union U {
    int i;
    int v = 0;
  } u = { .v = 5 };  // Now accepted in GNU/Clang C++11 modes.

Previously, the front end issued an error on this example in GNU and Clang
C++11 modes, even though the corresponding compilers accept this case.  The
front end now emulates GCC and Clang in this regard.


4/20/21  [EDGcpfe/21589,EDGcpfe/22350,EDGcpfe/22465,EDGcpfe/22466]
C++: Class template argument deduction for aggregates

The C++20 feature that extends class template argument deduction to include
aggregates (described in committee papers P1816R0 and P2082R1) is now
implemented.

  template <typename T> struct A {
    T x;
    T y;
  };
  template <typename T> struct B {
    A<T> a;
    T t;
  };
  B b = {{1u, 2u}, 3}; // B<int> deduced

This support involves a small IL CHANGE.  The overriding_virtual_functions
field in a_base_class has been moved into a union, and uses of the field
should check the value of the is_pack_expansion flag.

This feature is also enabled in Microsoft mode when microsoft_version >=
1927 and --ms_c++20 (or --ms_c++latest) is specified.


4/19/21  [EDGcpfe/23980]
C++-generating back end: Cast with brace notation incorrectly rendered

Consider:

  template<typename T, unsigned N> struct A { T m[N]; };
  template<typename T, T... Vs> struct S {};
  struct Pos { unsigned u; };
  template<typename T, T... Vs>
    A<Pos, sizeof...(Vs)> f(S<T, Vs...>) {
      return {{ Pos{Vs}... }};  // Previously misrendered.  Now okay.
    }

Previously, the initializer element "Pos{Vs}..." was incorrectly rendered as
"((Pos)(Vs))..." by the C++-generating back end.  The underlying problem was an
incorrect flag in the IL.  That is now fixed.


4/19/21  [EDGcpfe/24169,EDGcpfe/24176]
Clang compatibility: Add builtin functions for 12.0.0

Builtins for clang 12.0.0 have been added.


4/16/21  [EDGcpfe/23768]
Constrained member functions with deducible return types

In some cases, a constrained member function with a deducible return type
triggered an error during overload resolution when its constraint is not
satisfied when instead that member function should just have been discarded
as a candidate.  That is now fixed.


4/14/21  [EDGcpfe/23937]
Microsoft compatibility: Packing and explicitly-aligned types

In Microsoft modes, the front end ignores packing directives for fields of
types with explicit alignment requirements (see the entry of 8/1/05).  Now,
that behavior is extended to base classes and to types containing subobjects
with explicit alignment requirements.  For example:

  #pragma pack(1)
  struct alignas(16) A {};
  struct B { A a; };  // 16-byte aligned despite #pragma in effect.
  struct D: B {};     // Ditto.
  static_assert(alignof(D) == 16, "");  // Now accepted in Microsoft mode.


4/13/21  [EDGcpfe/23110,EDGcpfe/23694,EDGcpfe/23923,EDGcpfe/23924]
Constrained function templates sometimes erroneously discarded

When processing a nondependent call in a template-dependent context, the front
end sometimes discarded constrained function templates when it should not have
done so.  That could result in spurious overload resolution errors in somewhat
complex cases.  That problem is now fixed.


4/13/21  [EDGcpfe/24080]
C++-generating back end: CTAD with dependent type

In some cases with class template argument deduction using a dependent type
in a templated context, the C++-generating back end generated code that
could not be compiled by g++ or clang.  This is now fixed.  For example,
with --c++17 --gnu_version=90300:

  template<typename T> struct X { };
  template<typename...> struct Y {
    Y();
  };
  template<typename T> auto f() { }
  template<auto &F> struct Z {
    using T = X<decltype(F)>;
    static void g() {
      auto x = f<T>();
      Y c(x);  // Was generated as "Y c(Y(x))", producing g++/clang errors
    }
  };


4/12/21  [EDGcpfe/23841]
Microsoft C++ compatibility: Friend function template injection

In Microsoft C++ modes with microsoft_version >= 1800 the front end no longer
injects friend function templates into the surrounding namespace scope.  For
example:

  template<typename T> struct S {
    template<typename U>
      friend bool operator==(S const&, U const&);
    S(T const&) {}
  };
  template<typename T> struct X { S<int> f; };
  struct Y {
    enum E { e };
    int g(int i) {
      return i == e;  // Previously ambiguous.  Now okay.
    }
  };

Previously, "i == e" was ambiguous (in Microsoft C++ mode) between the built-in
equality operator and the injected function template.  Now, the template is no
longer a candidate when microsoft_version >= 1800 and this example is then
accepted.


4/9/21   [EDGcpfe/24056]
Trivial throwing destructors

Consider:

  struct TTD {
    ~TTD() noexcept(false) = default;
  };
  static_assert(!__is_nothrow_destructible(TTD), "");
    // Previously spuriously failed.  Now okay.

The front end previously produced "true" for __is_nothrow_destructible(TTD)
because trivial destructors were discarded too early.  That is now fixed and
the example above is now accepted.


4/9/21   [EDGcpfe/24137]
Abort in constraint_chart_of

The front end could previously abort in constraint_chart_of due to a null
pointer indirection when dealing with certain constrained function templates.
That is now fixed.


4/9/21   [EDGcpfe/24060]
C++-generating back end: dependent decltype with member access operand

In some cases, the C++-generating back end incorrectly added parentheses
around the operand of a decltype operator, changing the result type in the
generated code from what it was in the original source.  For example, with
--c++11:

  struct S { int x; } s;
  template<class T, T* t> void f(decltype(t->x) x) {
    x = 66;
  }
  int main() {
    int y = 42;
    f<S, &s>(y);
    return y;
  }

In the original code, the type of the parameter of f<S, &s> is "int", so
the assignment to x in the body of the function has no effect on the value
of y and the return value from main() is 42.  The C++-generating back end,
however, previously put out the decltype as "decltype((t->x))".  The added
parentheses made the parameter type "int&", resulting in a return value of
66 from main().  This is now fixed, and no parentheses are added in such
cases.


4/8/21   [EDGcpfe/24133]
Representation of type constraints for deduced return types

The front end previously did not always record a "declared type" that
represents a placeholder type for a function with a deduced return type, and
if that placeholder was specified with a constraint that constraint was not
recorded in the IL.  Now this is done consistently and the C++-generating back
end renders that constraint.  Furthermore, the tk_typeref type entry placed
over the deduced type now also records the constraint in the associated
a_typeref_type_supplement entry.


4/5/21   [EDGcpfe/24035]
Microsoft compatibility: --ms_await_strict

A new command-line option, --ms_await_strict, has been added to emulate the
/await:strict Visual Studio command-line option.  This option enables
coroutine support (even in pre-C++20 modes) and defines the
_DOWNLEVEL_COROUTINES_SUPPORTED macro (which is used by the Visual Studio
header files).


4/4/21   [EDGcpfe/24000,EDGcpfe/24127]
Diagnostics for unreferenced variables in template instantiations

Formerly, the front end would issue a diagnostic about an unreferenced
variable during a template instantiation in cases where the diagnostic
was not useful because it was potentially issued on only some instantiations,
so there was no way for the user to change the code to avoid the diagnostic.
When the front end could determine during the prototype instantiation that
an entity was always unused and never had side-effects, a diagnostic would
be issued during the prototype instantiation, and that would cause any
diagnostics during real instantiations to be suppressed. The front end has
now been changed to not emit these diagnostics at all during real
instantiations.  The behavior during prototype instantiations remains the
same, so now unreferenced variable diagnostics are only issued in prototype
instantiations.  In modes in which prototype instantiations are not done
the behavior has not changed.

A similar change has been made for unused function parameters where a
diagnostic could be issued in a case where the parameter was used only
in an empty pack expansion.

  template <class T> void f(T) {
    T x;    // formerly, warned in some instantiations
    int y;  // warned during prototype instantiation
  }
  struct A {
    A(){}
  };
  int main() {
    f(1);  // would warn that x is unreferenced
    f(A()); // would not warn because declaration of x has side-effects
  }


3/29/21  [EDGcpfe/5372,EDGcpfe/8585,EDGcpfe/11120,EDGcpfe/13910,EDGcpfe/23583,
          EDGcpfe/23610]
Changes to "#pragma diag_*" and add "#pragma diagnostic push/pop"

The previous implementation of the EDG-specific "#pragma diag_*" feature
had resulted in some unexpected diagnostics because the pragmas had been acted
upon at unexpected points in the compilation.  For example, in each of the
following cases, the diag_error #pragmas surprisingly affected the declarations
that precede them.  In the following example, the processing that detects
whether or not a function is referenced is performed at the end of the
compilation, resulting in a spurious error:

  #pragma diag_suppress declared_but_not_referenced
  static void f() { }   // had given an error, now suppressed
  #pragma diag_error declared_but_not_referenced
  static void g() { }   // gives an error (now and previously)

Similarly, template instantiation had often resulted in surprising diagnostics.
For example, with -tused:

  #pragma diag_suppress implicit_return_from_non_void_function
  template <typename T> int f() {}  // previously an error, now suppressed
  #pragma diag_error implicit_return_from_non_void_function
  int main() {
    f<int>();
  }

The handling of these EDG-specific pragmas was substantially rewritten to base
the behavior on the source location of the error (i.e., what "#pragma diag_*"
was in effect at that location in the source code), rather than the point
in the compilation where the error was detected.

Additionally, a new EDG-specific #pragma has been added to save and restore the
state of how the front end handles diagnostics.  This is similar to mechanisms
used by other compilers (i.e., "#pragma GCC diagnostic push/pop" in GCC,
"#pragma clang diagnostic push/pop" in clang, "#pragma warning( push/pop )"
in Visual Studio).  The syntax is shown in the example below:

  #pragma diagnostic push
  #pragma diag_suppress implicit_return_from_non_void_function
  int f() {}  // no warning here
  #pragma diagnostic pop
  int g() {}  // warning here

The new "diagnostic" pragma affects the existing EDG-specific diag_suppress,
diag_remark, diag_warning, diag_error, and diag_default behaviors but does not
alter the behavior of diag_once.

Note that this new mechanism does not emulate the GCC/clang/Visual Studio
handling of pragmas that are specific to those compilers (diagnostic numbers
cannot be easily mapped from one compiler to another).


3/27/21  [EDGcpfe/24089]
C++-generating back end: pseudo-destructors in generated explicit
specializations

In some configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is set to TRUE,
the C++-generating back end could sometimes generate a pseudo-destructor
call using the name of the scalar type instead of a typedef, which is an
error and resulted in generated code that could not be compiled.  This is
now fixed.  For example, with --c++11 -tused:

  template<typename T> struct A {
    typedef T AT;
  };
  template<typename T> struct B {
    typedef typename T::AT BT;
    BT m;
    void f() {
      m.~BT();
    }
  };
  void g() {
    B<A<bool>> bab;
    bab.f();
  }

The explicit specialization generated for B<A<bool>>::f() previously
contained the statement

  m.bool::~bool();

which is an error.  This has been addressed by putting out a typedef
declaration defining a temporary name for bool preceding the explicit
specialization and forming the pseudo-destructor invocation using that
temporary name:

  typedef bool __T12345678;
  template<> inline void B<A<bool>>::f() {
    m.~__T12345678();
  }


3/25/21  [EDGcpfe/23763]
MS compatibility: separate header unit mappings for quote and angle imports

MSVC provides header unit mapping options that give a user more granular
control over whether the mapping applies to an import of a system header (angle
brackets, /headerUnit:angle) or a user header (quotes, /headerUnit:quote).
This functionality has been added to the front end with corresponding options
--ms_header_unit_angle and --ms_header_unit_quote, respectively.  These behave
similarly to --ms_header_unit, except that the header names given to these
options are resolved when looked up, as opposed to being assumed to have
already been resolved when provided on the command-line.  For example, with
-I inc and/or --sys_include inc where the "inc" directory contains both foo.h
and bar.h:

  import "foo.h" // Requires --ms_header_unit inc/foo.h=foo.ifc, or
                 //          --ms_header_unit_quote foo.h=foo.ifc.
                 // Ignores  --ms_header_unit_angle foo.h=foo.ifc.
  import <bar.h> // Requires --ms_header_unit inc/bar.h=bar.ifc, or
                 //          --ms_header_unit_angle bar.h=bar.ifc
                 // Ignores  --ms_header_unit_quote bar.h=bar.ifc.


3/25/21  [EDGcpfe/23974]
MS compatibility: #include translation to import

MSVC provides a command-line option (/translateInclude) to indicate that
#include directives should be treated as import directives whenever the
included header has a mapping in the header unit map.  This functionality has
been added to the front end with a new command-line option,
--ms_translate_include.  For example (with --ms_header_unit foo.h=foo.ifc):

  #include "foo.h" // Translated to import "foo.h"
  #include "bar.h" // No mapping; not translated

A corresponding counter-option, --no_ms_translate_include, has been added to
cancel out this setting, should it be needed.


3/25/21  [EDGcpfe/24098]
Concepts-related IL display

The IL display utility failed to correctly output certain concepts-related
entities (like requires clauses, concept templates, requires-expressions,
etc.).  That is now fixed.


3/24/21  [EDGcpfe/24090]
C++20: throw() specifiers

C++17 removed most dynamic exception specifications except the "throw()" form.
C++20 also removed the latter (through the committee's paper P0619R4) and the
front end now diagnoses uses of the "throw()" specifier in C++20 modes (an
error in strict mode, a warning otherwise).  For example:

  void f() throw();  // Now elicits a warning in most C++20 modes, and
                     // an error in strict C++20 mode.


3/24/21  [EDGcpfe/23947]
MS compatibility: Module interface command-line option

MSVC provides a command-line option (/interface) to indicate that the source
being compiled is intended to be a module interface unit.  A new command-line
option, --ms_mod_interface, has been added for compatibility with this switch.

Specifying --ms_mod_interface will treat every module unit declaration as if
it had been exported (whether or not the export keyword is present on the
declaration), and will have no effect on TUs that are not module units.  A
corresponding counter-option, --no_ms_mod_interface, has also been added to
disable this mode.  Note that specifying --no_ms_mod_interface will *not*
prevent a module interface unit from being specified at the source level
(e.g., "export module foo;").


3/24/21  [EDGcpfe/24040]
Spurious exception specification mismatch error

The front end previously issued a spurious error on the following example
claiming that the exception specification of the out-of-class member
definition does not match that of the in-class declaration:

  struct X { void x(); };
  template<typename T> struct S {
    X s;
    void f() noexcept(noexcept(s.x()));
  };
  template<typename T>
    void S<T>::f() noexcept(noexcept(s.x())) {}  // Previously an error.
                                                 // Now okay.

This was caused by a difference in the way the implicit "this->" qualification
for "s.x()" (i.e., "s" is "this->s") was modeled in the two contexts.  That is
now fixed.


3/23/21  [EDGcpfe/21142,EDGcpfe/23692]
Mangling of lambda expressions

The IA-64 ABI doesn't specifically mention mangling of lambda expressions
(though it does specify how to mangle lambda closure types), but in some
configurations (mostly C++-generating configurations with MANGLE_ALL_NAMES),
a lambda expression can find its way into a mangled name, causing an
assertion failure.  A change has been made to mangle these lambda expressions
as GCC does -- as braced-init lists.  For example (with --c++20):

  template <int N> void foo(const char (*s)[([]{}, N)]);


3/22/21  [EDGcpfe/24079]
Spurious warning on by-reference capture of "this"

Capturing "this" by copy is deprecated (see the entry for EDGcpfe/20001, etc.).
However, the front end also issued warnings for implicit by-reference captures
of "this".  For example:

  struct S {
    int g() { return  2; }
    void f() {
      int  value = 3;
      [&]{ return value+g(); };  // Previously a spurious warning.  Now okay.
    }
  };

This is now fixed.


3/22/21  [EDGcpfe/21141,EDGcpfe/23339,EDGcpfe/24078]
Unbounded recursion when mangling some lambda types

A stack overflow had occurred when mangling certain lambda types that had
occurred in unevaluated contexts.  Now fixed.  For example (with --c++20):

  auto x = [](decltype([]{}) y) { return y; };


3/22/21  [EDGcpfe/24046]
GNU C++ compatibility: Conversions to arrays of unknown bound

The changes made for EDGcpfe/21591 for C++20 mode -- which enable binding an
array of known length to a pointer or reference to an array of unspecified
bound -- are now enabled in all GNU C++ modes.


3/19/21  [EDGcpfe/23190,EDGcpfe/23697,EDGcpfe/23766]
Excessive recursion walking name reference entries

The processing of name reference entries (mostly in C++-generating back
end configurations) could cause stack overflow as a result of too many
recursive calls during needed flag and/or keep-in-il walks of the IL.
This is now fixed.


3/19/21  [EDGcpfe/24055]
Dynamic allocations of multi-dimensional arrays in interpreter

C++20 introduced the ability to dynamically allocate objects during constant-
evaluation.  However, the constexpr interpreter did not correctly handle uses
of such a dynamically allocated object when that object was a multi-dimensional
array.  For example:

  constexpr int f() {
    int (*vec)[5] = new int[3][5];
    vec[3][0] = 42;   // Invalid access.
    delete [] vec;
    return 1;
  }
  int x[f()];

Here, the sub-expression vec[3][0] is invalid because it attempts to refer to
an object out of bounds, but the front end failed to catch this and memory
could be corrupted as a consequence of it.  That is now fixed.


3/19/21  [EDGcpfe/23836]
Microsoft compatibility: new-expressions with unspecified array bounds

The front end emulates a Microsoft compiler behavior where a new-expression
allocating an array with unspecified bound is treated as if a bound of zero
was specified.  For example:

  int *p = new int[];  // Accepted in some Microsoft modes and treated
                       // as "int *p = new int[0];".

Unfortunately, the code emulating that behavior interacted poorly with the
changes that allow such a new-expression with an initializer to implicitly
dimension the allocated array (see the entry for EDGcpfe/20914).  Now, this
emulation is limited to microsoft_version < 1900 (to match actual Microsoft
compiler versions) and if an initializer is present, the deduction of the
allocated length from the initializer takes precedence over assuming a zero
length in the other cases.


3/18/21  [EDGcpfe/23834]
C++-generating back end: "<unnamed>" as template argument in generated code

The C++-generating back end in some complicated template cases could put
out the string "<unnamed>" as a template parameter name when the parameter
has no name in the source.  This is now fixed.


3/18/21  [EDGcpfe/23839]
C++-generating back end, Microsoft compatibility: qualification of hidden types

Visual Studio 2019 has a bug that causes it to report spurious errors in
some cases when a qualified name is used in an elaborated-type-specifier
that refers to a hidden name.  The C++-generating back end sometimes put
out such elaborated-type-specifiers with unnecessary name qualification.
This is now fixed, and the identifiers in such elaborated-type-specifiers
are no longer qualified.  For example:

  #include <typeinfo>
  struct S {
    int S;
    void f() {
      typeid(struct S);  // Previously generated as "struct ::S", which
                         // triggered the MSVC bug
    }
  };


3/18/21  [EDGcpfe/24029,EDGcpfe/24069]
Value initialization of aggregates in C++20 mode

Consider:

  struct S { int i; };
  auto s = S();

In C++20 mode (which enables "parenthesized aggregate initialization"), the
front end treated "S()" identically to "S{}" because S is an aggregate.
However, the standard still specifies that "S()" is value-initialization,
which is distinct from aggregate initialization.  Now, the front end treats
"S()" again as value-initialization in C++20 mode.  (C++17 mode was
unaffected by prior changes and always treated "S()" as value-initialization.)


3/18/21  [EDGcpfe/24070]
Narrowing conversions and template deduction

In some fairly complex situations involving overload resolution and template
deduction the front end failed to disqualify certain candidate function
templates even though the candidate requires a narrowing conversion during
the substitution of an expression in the function template's declaration.
That problem is now fixed.


3/17/21  [EDGcpfe/24072]
Deferred static data member instantiation and explicit constructors

Consider:

  struct E { explicit E() = default; };
  template<typename T> struct S {
    static inline E value{};
  };
  E e = S<int>::value;

The changes for EDGcpfe/23502 in version 6.2 caused the instantiation of the
initializer for S<int>::value to be deferred until its value is needed.
However, that deferred initializer processing was never considered to be a
"direct-initialization" and thus the explicit constructor was incorrectly
ignored.  That regression is now fixed.


3/17/21  [EDGcpfe/24020]
Handling of namespace-scope compound literals in interpreter

Consider (in GNU C++ mode):

  struct I { int i; };
  struct S {
    constexpr S(I const *is) : is(is) {};
    I const *is;
  };
  static constexpr S s = S((const I[]){{ 1000 }});

Previously, this triggered an error because the array compound literal was
treated as a limited-lifetime temporary object and the address of such an
object cannot be part of a constant expression's result.  That is now fixed.


3/17/21  [EDGcpfe/24071]
Clang compatibility: Conversion to "ext_vector_type" types

In Clang mode, any arithmetic or enumeration type can be converted to an
"ext_vector_type" type (see the entry for EDGcpfe/22952,EDGcpfe/23348).
However, the front end previously treated that conversion as an identity
conversion; now it is treated as a promotion, which avoids overload ambiguities
in some cases.


3/14/21  [EDGcpfe/21586,EDGcpfe/22684]
C++20: using enum declarations

C++20 "using enum" is now implemented.  This adds the new "using enum"
declaration which introduces all of the enumerators of the specified type
into the current scope, and allows using-declarations to introduce individual
enumerators into the current scope.  This feature was introduced by committee
document P1099R5.

  // Using of enumeration
  namespace N {
    enum E { e1, e2};
  }
  using enum N::E;
  int x = e1 + e2;

  // Using of enumerator
  enum class button { up, down };
  struct S {
    using button::up;
    button b = up;
  };


3/11/21  [EDGcpfe/23822,EDGcpfe/23917,EDGcpfe/23998]
Nonstandard anonymous unions with base classes

Previously, nonstandard anonymous unions that are really struct types -- in
modes that accept that extension -- were never permitted to have base classes.
Now that restriction only applies to GNU C++ mode with gnu_version < 30400.
In other GNU C++ modes, the anonymous struct is only required to be a trivially
copyable type, and in Clang and Microsoft C++ modes even that requirement is
lifted.  For example:

  struct B {};
  struct S {
    struct : B {  // Previously a warning, because the nonstandard
      int i;      // anonymous union-like construct was not recognized.
    };
  };
  int main() {
    S s;
    s.i = 1; // Previously an error.  Now okay in GNU, Clang, and Microsoft
  }          // C++ modes.


3/10/21  [EDGcpfe/23932]
Abort on use of variadic requires-expression parameters

The front end could previously abort with an internal error in overload.c (in
determine_function_viability) when expanding variadic parameters of a
requires-expression.  For example:

  template<typename F, typename ...Ts> auto g(F fn, Ts ...ps) {
    return fn(ps...);
  }
  template<typename F, typename ...Ts>
    concept C = requires(F fn, Ts... ps) { g(fn, ps...); };
  static_assert(C<void(*)(int), int>);
         // Previously aborted when substituting the g(fn, ps...) call in
         // the requires-expression above.

That is now fixed.


3/9/21   [EDGcpfe/24023]
GNU C++ compatibility: Packing non-standard-layout types

In GNU and Clang C++ mode, packing attributes are ignored for fields that are
of a non-standard-layout class type.  However, the actual criterion used by the
front end for ignoring such attributes was that the field type is not C++03 POD
type.  That criterion remains in effect for Clang modes, but in GNU C++ mode it
is now relaxed to fields that are not of standard-layout aggregate class types.
For example, in GNU C++14 mode:

  struct S {
    unsigned a = 0; // Default initializer makes this non-POD.
  };
  struct X {
    S b;
    unsigned char c;
  } __attribute__((packed));  // Attribute was previously ignored.
                              // Now it is applied in GNU C++14 mode (but
                              // not in Clang C++14 mode).

The new behavior has been determined by trial and error and might not match
what GCC actually implements.


3/9/21   [EDGcpfe/24034]
Clang and GNU C++ compatibility: Mem-initializers for flexible array members

The changes for EDGcpfe/22387 in version 6.2 of the front end introduced a
regression: Those changes resulted in an error being issued if a flexible
array member of a class type was value- or default-initialized by the
mem-initializers of a constexpr constructor.  For example:

  struct S {
    constexpr S()
      : i(), fam() {} // An error in version 6.2.  Now sometimes okay.
    int i;
    char fam[];
  } s;

Now, such cases are accepted in Clang C++ mode when clang_version >= 11000 and
in GNU C++ mode when gnu_version >= 80000 and gnu_version < 100000.


3/9/21   [EDGcpfe/23083,EDGcpfe/23735,EDGcpfe/24027]
Accessing constexpr variables with mutable members

The front end previously did not permit accessing a constexpr variable with a
mutable member even if the mutable member itself was not examined.  Now such
cases can be accepted.  For example:

  struct S {
    int i;
    mutable int mi;
  };
  constexpr S cs{ 1, 2 };
  constexpr int x = cs.i;  // Previously an error.  Now okay.


3/9/21   [EDGcpfe/24028]
Clang C++ compatibility: Flexible array members in otherwise empty classes

The changes for EDGcpfe/22387 in version 6.2 of the front end introduced a
regression: Those changes caused flexible array members in Clang C++ mode to
be treated like standard C99 flexible array members.  However, C99 requires
such a member not to be the sole named member of its parent type, but Clang
does not enforce that constraint in C++ modes (it does in C modes).  The
front end now emulates that behavior in Clang C++ modes, thereby fixing the
regression.  For example:

  struct S {
    int fam[];  // An error in Clang C++ mode with version 6.2 of the front
  };            // end.  Now accepted.


3/5/21   [EDGcpfe/18999,EDGcpfe/23905,EDGcpfe/23995]
GNU/Clang compatibility: --[no_]strict_gnu command-line option

The GNU and Clang compilers have two different sets of command-line options to
specify the version of the C/C++ standard to accept: -std=gnu* and -std=c*.
The -std=c* form closely adheres to the appropriate ISO C or C++ standard
document while the -std=gnu* version selects the "GNU dialect" of that
standard (including some features that might conflict with the ISO standard).
The front end had previously not distinguished between these modes.

A new command-line option, --[no_]strict_gnu, will now be used to distinguish
these cases.  Using the --strict_gnu command-line option will mimic the -std=c*
variant in GNU/Clang and using the --no_strict_gnu command-line option will
emulate the -std=gnu* GNU/Clang behavior.  In the absence of either, when
a --c* or --c++* command-line option is explicitly specified, the -std=c*
behavior will be used (e.g., --c++11 is equivalent to -std=c++11); otherwise,
the -std=gnu* behavior will be emulated.

The difference between --strict_gnu and --no_strict_gnu currently has two
effects: with --strict_gnu, the __STRICT_ANSI__ predefined macro is now
defined, and with --no_strict_gnu, complex literals (e.g., "1.0i") are now
accepted (previously this was interpreted as a user-defined literal in modes
where UDLs are enabled).


3/5/21   [EDGcpfe/23935]
Internal error in GNU C++-mode friend function definition

The changes for EDGcpfe/23704 in version 6.2 of the front end introduced a
regression in some GNU C++ modes when handling certain friend function
definitions in class templates.  This usually led to an internal error in
rescan_reusable_cache, but in some other configurations the abort occurred
in set_routine_declared_type instead.  For example (GNU C++ mode with
prototype instantiation deferral disabled):

  template<typename T> struct S {
    friend int f() { return 42; }
  };
  int f();
  template<typename T> int g() {
    return f();
  }
  S<int> s;
  int r = g<int>();  // Previously triggered an internal error.  Now okay.

That is now fixed.


3/5/21   [EDGcpfe/23934]
Internal error on invalid pointer arithmetic in some configurations

When the configuration macro PTR_TO_INCOMP_ARRAY_ARITHMETIC_ALLOWED is TRUE,
the front end sometimes aborted with an internal error in process_fill_in
("specified fill-in not found"; error.c).  For example:

  void g(void *p) { p + 1; }  // Previously triggered an abort in some
                              // configurations.  Now an ordinary error.

That regression -- introduced in version 6.2 of the front end by the changes
for EDGcpfe/23512 -- is now fixed.


3/5/21   [EDGcpfe/24025]
C++-generating back end, Microsoft compatibility: pointer to array type in
template argument

The Microsoft compiler has a bug that results in spurious syntax errors in
some cases if a template argument contains a pointer to array type.  The
C++-generating back end sometimes used the underlying type of a typedef
referring to such a type, thus triggering the MSVC bug.  For example,
with --microsoft:

  template<int> struct A {
    typedef int type;
  };
  template<typename> struct B {
    static const unsigned value = 5;
  };
  template<class T> struct C {
    typedef char(*type)[B<T>::value];
  };
  A<sizeof(*(C<int*>::type)0)>::type x;

In the last line, the template argument uses the typedef C<int*>::type,
which is declared as a pointer to a character array.  The C++-generating
back end previously used the underlying type of this typedef in the
generated code, resulting in that declaration being put out as:

  A<sizeof(*((char(*)[B<int*>::value])0))>::type x;

This form of the template argument to A, although correct, resulted in
spurious errors when the generated code was compiled.  This is now fixed,
and the generated code now preserves the use of the typedef.


3/4/21   [EDGcpfe/24024]
GNU/Clang emulation: C11 _Atomic with --ms_extensions

The C11 _Atomic extensions are not yet supported by Microsoft Visual Studio
and the change for EDGcpfe/23370 (in 6.1) made that explicit, but that change
had the undesirable effect of also disallowing those extensions in GNU and
Clang emulation modes when --ms_extensions is specified.  Now fixed.


3/3/21   [EDGcpfe/24010]
GNU compatibility: Conversions to and from incomplete class types

The changes for EDGcpfe/23274 (introduced in version 6.2) caused certain casts
to incomplete class types to be accepted in GNU C++ modes if those casts appear
in template-dependent contexts.  Now that change is limited to GNU C++ modes
with gnu_version <= 100200 but extended to more situations, and it is also
extended to conversions from (as opposed to "to") incomplete class types.
For example:

  struct I;
  template<typename T> void f() {
    decltype(I(1))      *p1;
    decltype(int(I()))  *p2;
  }

Previously the cast "I(1)" was rejected in GNU modes that don't defer prototype
instantiations because I is an incomplete type.  Now it is accepted when
gnu_version <= 100200.  Similarly, the cast "int(I())" is now accepted in those
modes.


3/2/21   [EDGcpfe/23978]
Abort in class_qualified_id_lookup on substitution of conversion function call

In somewhat unusual SFINAE substitutions, the front end could abort with an
internal error in class_qualified_id_lookup when substituting an explicit call
to a conversion function.  That is now fixed.


3/2/21   [EDGcpfe/23979]
Lambda using a local reference without capturing it

Consider:

  int i = 0, x;
  int main() {
    constexpr int &r = i;
    []{ x = r; }();
  }

Previously, the representation of "x = r;" pointed directly to the variable
entry for r.  One consequence of that is that, when the lambda invocation was
not expanded in-line, the C code generated by the C-generating back end was
invalid because no "r" is declared in the scope of the call operator of the
lambda (r is not captured).  It could also be surprising to a back end to have
such a representation.  Now, the use of r in that context is "constant-folded"
and the representation of "x = r;" therefore points directly to x instead.


3/2/21   [EDGcpfe/24004]
Clang compatibility: spurious error on __type_pack_element in some contexts

The clang builtin __type_pack_element (see EDGcpfe/18310) could result in
spurious errors when it was used in contexts in which template substitution
was performed.  Now fixed.

  template <typename... Ts> class A {
    template <typename T = __type_pack_element<0, Ts...>> using type = bool;
  };


3/2/21   [EDGcpfe/23293,EDGcpfe/23497,EDGcpfe/23983]
Failure to deduce array length from braced-list argument

The front end previously sometimes failed to deduce the length of a template-
dependent array parameter from a braced-list argument when the element type of
the array parameter is non-dependent.  For example:

  template <decltype(sizeof(1)) N> void f(long (&&arr)[N]) {
    (void)arr;
  }
  int main() {
    f({1, 2});  // Previously an error.  Now okay.
  }

That is now fixed.


3/2/21   [EDGcpfe/23990]
Abort in interpreter on recursive std::construct_at call

The front end previously could abort in the constexpr interpreter when
std::construct_at is invoked recursively.  For example:

  void* operator new(decltype(sizeof(0)), void*);
  void operator delete(void*, void*);
  namespace std {
    template<typename T, typename ... Args>
    constexpr T* construct_at(T *p, Args &&...args) {
      return new((void*)p) T(args...);
    }
  }
  struct I {
    int i;
    constexpr I(int i): i(i) {}
    constexpr ~I() {}
  };
  struct X {
    I i;
    constexpr X(): i(42) {
      this->i.~I();
      std::construct_at(&this->i, 8);  // Previously triggered an abort in
    }                                  // the interpreter.
    constexpr ~X() {}
  };
  struct Y {
    X x;
    constexpr Y(): x() {
      this->x.~X();
      std::construct_at(&this->x);
    }
    constexpr ~Y() {}
  };
  constexpr Y y{};

That is now fixed.


3/1/21   [EDGcpfe/23890]
Front end self build issue

The FALLTHROUGH macro used by the front end to abstract use of the
[[fallthrough]] attribute had caused spurious diagnostics when self-compiling
the front end in modes earlier than --c++17.  Now fixed.


2/27/21  [EDGcpfe/23821]
Microsoft compatibility: handling of comma in variadic macro arguments

As noted in the description for EDGcpfe/16179, in general the traditional
Microsoft preprocessor does not treat commas appearing in the text of
__VA_ARGS__ as delimiting macro arguments when __VA_ARGS__ is passed to
another macro; however, that is sometimes not the case when the name of
the macro to which __VA_ARGS__ is passed is constructed in certain ways by
nested macro invocations during the rescanning of the top-level expansion.
The changes for EDGcpfe/16179 addressed some of those patterns but failed
to emulate the behavior of the traditional Microsoft preprocessor in others.
For example, with -E --microsoft, both

  #define M1(x,...) x + __VA_ARGS__
  #define CAT_V(x,...) x##__VA_ARGS__
  #define B(...) CAT_V(M,1)(__VA_ARGS__)
  B(abc, def)

and

  #define E1(x,...) x + __VA_ARGS__
  #define CAT_N(x,y) DO_CAT(x,1)
  #define DO_CAT(x,...) x##1
  #define E(...) CAT_N(E,1)(__VA_ARGS__)
  E(abc, def)

failed to treat the comma in __VA_ARGS__ as a delimiter and thus produced
the output

  abc, def +

The front end's emulation has now been changed to match that of MSVC,
resulting in

  abc + def

for these examples.


2/27/21  [EDGcpfe/23986]
Change in default versions supported by the front end

The front end has been updated to emulate more recent versions of the GCC,
Clang, and Microsoft Visual Studio compilers by default.  The default versions
have changed as follows:

  - DEFAULT_GNU_VERSION from 40800 to 80100
  - DEFAULT_CLANG_VERSION from 30500 to 90100
  - DEFAULT_MICROSOFT_VERSION from 1900 to 1926

You can change these defaults in your defines.h, and as always, to avoid
surprises when these values change, you should explicitly set these
configuration macros or ensure that the proper command-line options are
specified.


2/26/21  [EDGcpfe/23899]
Optimize assignment of variable to itself in lowered code

The change made by EDGcpfe/23122 in 6.2 could introduce an inefficiency
in the lowered code, resulting in an assignment of a variable to itself
in certain cases.  Lowering now recognizes such cases and removes them.
For example:

  struct A {
    int x;
    A mf() const;
  };
  void f(bool b, const A &a) {
    const A a2 = b ? a : a.mf();
  }


2/26/21  [EDGcpfe/23970]
Clang compatibility: __has_builtin(__make_integer_seq)

__has_builtin(__make_integer_seq) now returns 1 in clang emulation modes
when clang_version >= 30900.


2/26/21  [EDGcpfe/22267]
Constant-evaluation of template arguments

Several improvements have been made to the handling of template arguments and
the constant-evaluation in particular.  For example, in GNU C++14 mode:

  struct S {
    constexpr S();
    int x;
  };
  template <typename, int, int i> class C {
    static constexpr S s = S(i);
    template<typename = C<double, s.x, 42>> int f();
       // Previously an error about s.x not being constant.
       // Now accepted (in GNU mode).
  };

This example (which is not standard C++) was previously rejected in all modes,
but now it is accepted in GNU C++ mode.


2/26/21  [EDGcpfe/22003,EDGcpfe/23814]
Temporary introduced by lowering was incorrectly const-qualified

In configurations that do lowering, a temporary introduced when lowering
a selector had been incorrectly const-qualified resulting in generated C code
that would not compile.  That was the case in configurations with
RECORD_BACKING_EXPRS_WITH_IL_LOWERING set to FALSE for this example
(with --c++11):

  struct S {
    void f(int x) {
      x_ = x;
    }
    int x_ = 0;
  };
  void g(void) {
    S().f(1);
  }

This is a regression introduced in 6.0 by the changes for EDGcpfe/21809.


2/24/21  [EDGcpfe/23966]
Internal error in scan_function_body on defaulted friend comparison

The changes for EDGcpfe/23704 introduced a regression in the handling of
defaulted friend comparison functions in version 6.2 of the front end.  For
example:

  template<typename T> struct S {
    T value;
    friend bool operator==(S const&, S const&) = default;
  };
  S<int> si;
  bool r = si == si;

Previously, this example elicited an internal error in scan_function_body
(func_def.c).  That is now fixed.


2/24/21  [EDGcpfe/23975]
Spurious failure to match a dependent nontype template parameter

The changes for EDGcpfe/20943,EDGcpfe/23454 in version 6.2 introduced a
regression that caused the front end to sometimes spuriously fail to match a
template-dependent nontype template parameter that turns out to be const-
qualified after substitution.  For example:

  struct S{
    using X = char const;
  };
  template <typename T, typename T::X = 0> void f();
  void g() {
    f<S>();  // Previously an error.  Now okay.
  }

In this example, the dependent template parameter type "T::X" ends up being
"char const" after substitution.  The default argument 0 is a valid argument
for that parameter, but the front end previously failed to establish that.
That problem is now fixed.


2/23/21  [EDGcpfe/18078,EDGcpfe/23889]
Premature optimization of logical operators in SFINAE contexts

Consider:

  template<bool> struct E { };
  template<> struct E<true> { using type = bool; };
  template <typename _U1> constexpr bool f() { return false; }
  template <typename _U1> constexpr bool g() { return true; }
  template<typename T> struct C {
    C();
    template<typename U, typename E<f<T>() && g<U>()>::type = true>
      constexpr C(U&&, T const&) {}
  };
  struct X {};
  C<X> b;

Previously, the front end issued an error during the instantiation of C<X>
because the expression "f<T>() && g<U>()" was folded to false for T=X, even
though U is unknown.  Now this early folding is not done, and thus the
constructor candidate will instead be discarded if an attempt is made to call
it (which would trigger a substitution failure).  This was a regression
introduced in version 4.13 (by the changes for EDGcpfe/17934).


2/23/21  [EDGcpfe/23951]
Clang compatibility: enabling VLAs with --ms_extensions

Variable length arrays (VLAs) are disabled in C mode when emulating Microsoft
Visual Studio, but are now enabled in Clang mode when --ms_extensions is
specified.


2/23/21  [EDGcpfe/23908]
Attributes not being correctly applied to class templates

In some cases an attribute was not being applied to a class template definition
if there had been a previous class template declaration without the attribute.
Now fixed.  For example (with --g++):

template<typename T> struct S;
template<typename T> struct __attribute__((visibility("default"))) S {};


2/20/21  [EDGcpfe/23929]
Microsoft compatibility: Standard-conforming preprocessor for C11 and C17

Beginning with version 1928, MSVC by default uses the Standard-conforming
preprocessor (see the entry for EDGcpfe/19828,EDGcpfe/20117) with /std:c11
and /std:c17.  The front end has been changed to emulate this behavior with
--ms_c11 and --ms_c17.  For example, with --microsoft_version=1928 --ms_c11,
the following now compiles without error, whereas it previously triggered
the #error directive:

  #if !defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL != 0
  #error The Standard-conforming preprocessor is not enabled
  #endif


2/19/21  [EDGcpfe/23928]
Uninitialized end-position in C++20 parenthesized aggregate initialization

Consider, in C++20 mode:

  struct S {};
  void f(S) {}
  void g() {
    f(S());  // Incorrect "end position" for node representing S().
  }

Here, the sub-expression "S()" is treated as a parenthesized aggregate
initialization, and ultimately represented using an enk_temp_init node.
However, the end-position of the sub-expression (recorded when the macro
EXTRA_SOURCE_POSITIONS_IN_IL is TRUE), was previously set from an
uninitialized value, causing the enk_temp_init node's expr_range field to
be incorrect.  That is now fixed.


2/18/21  [EDGcpfe/23723]
C++-generating back end: constexpr variables as nontype template arguments

When a constexpr variable is used as a nontype template argument, the
C++-generating back end sometimes used its initializer instead of the
variable name as the argument in the generated code.  This could result
in uncompilable code if the initialization involves type conversions.
This is now fixed: a constexpr variable used as a template argument in
the first reference to a template instance will be used in the generated
code as well.  For example, with --c++17 --clang:

  int i;
  typedef void *PTR;
  constexpr void * const p = &i;  // Converts int* to void*
  template<PTR> int x1;
  constexpr const PTR p2 = p;
  template int x1<p2>;  // Previously generated as ill-formed "x1<&i>"


2/18/21  [EDGcpfe/23764]
C++-generating back end: incorrect attribute generation in Microsoft mode

Due to the changes for EDGcpfe/22101,EDGcpfe/22140 (in version 6.1) when
running in Microsoft emulation mode the front end had incorrectly classified
attributes that appeared after the type in an alias declaration, resulting in
their generation in the wrong location when generating C++ code.  For example,
with --microsoft_version 1928:

  using X = int [[ ]];    // Had generated "[[ ]] using X = int;"


2/18/21  [EDGcpfe/23385,EDGcpfe/23452]
Implicit imports of module interface units from module implementation units

Primary module implementation units (module units without a partition)
implicitly import the module's primary interface unit, as if there was an
explicit import directive with the same name.  For example:

  module foo; // Implicit import foo;

The front end now performs this implicit import.


2/17/21  [EDGcpfe/23907]
#pragma il_display

In configurations where NEED_IL_DISPLAY is TRUE, a new #pragma, il_display,
has been added as a debugging aid.  This is a pbk_next_construct pragma
that binds to the declaration or statement that follows it and dumps
(non-recursively) the IL for that entity (along with some debugging
information).  For example:

  struct A { int x, y; };
  void f(int i) {
  #pragma il_display
    A a = { 1, 2 };
  #pragma il_display
    i++;
  }


2/16/21  [EDGcpfe/23906]
Add --il_display command-line option

Previously, to display the IL in a textual form, it was recommended to
write the IL in binary format to a file and then build the front end
with STANDALONE_IL_DISPLAY defined to build a second executable that would
read the binary IL and emit a textual version.  That was cumbersome and
prone to differences in configuration between the two executables.

A new option, --il_display, has been added to enable textual IL to be
displayed directly from the front end.  The output is written to stdout and
is suppressed when there are errors in the IL.  The IL is displayed after
lowering takes place (if so configured), but if the --no_il_lowering
command-line option is used, lowering is suppressed resulting in unlowered
IL being displayed.

This new command-line option is available only when NEED_IL_DISPLAY is TRUE,
which is now the case when DEBUG is TRUE (you can explicitly set
NEED_IL_DISPLAY to FALSE to suppress this option).  You can still configure
the front end as a stand-alone IL display executable if so desired.


2/14/21  [EDGcpfe/23913]
Spurious substitution failure when an undefined function name is used in
a SFINAE context

When a dependent function call occurs in a SFINAE context an "unknown
function" entry is created to save information such as the class or namespace
in which the function name was found.  If the lookup did not find a name,
the unknown function entry would refer to an sk_undefined symbol.  In such
cases, a subsequent search for a possibly previously created unknown function
entry could incorrectly return an entry that refers to an sk_undefined symbol,
resulting in a spurious substitution failure.  Now fixed.

In the example below, func must be used in a SFINAE context before any global
scope func is defined in order for the error to occur.  This apparently does
not come up often in real code, as this bug has been present since at least
version 4.5 (October, 2012). 

  template <typename T, typename U> struct V {};
  template <typename T> V<T, decltype(func(T{}))> g(T);
  int func(int) { return 0; }
  template <typename T> decltype(func(T{})) f(const T&) { return 0; }
  int main() {
    f(0); // spurious substitution failure
  }


2/11/21  [EDGcpfe/23901]
Build failures in some configurations

Version 6.2 of the front end introduced a build failure in il_to_str.c for
configurations that enable neither BACK_END_IS_C_GEN_BE nor
BACK_END_IS_CP_GEN_BE.  That is now fixed.

Furthermore, configurations that set NEW_CAN_BE_FOLDED_INTO_CTOR to TRUE but
DELETE_CAN_BE_FOLDED_INTO_DTOR to FALSE ran into build failures for expr.c and
decl_inits.c even in prior releases.  That is now also fixed.


2/10/21  [EDGcpfe/23854]
IL display: Incomplete handling of coroutine nodes

The coroutine description was not completely handled by the IL display
routines.  As a result, edgcpdisp displayed BAD ENTRY KIND when encountering
the coroutine description, and later it printed out an incomplete accounting of
the coroutine description as part of the stmk_coroutine output.  This has now
been fixed - stmk_coroutines now print out all associated fields.


2/10/21  [EDGcpfe/23895]
Supporting Windows-style paths in non-Windows modes

The front end previously tied handling of Windows-style paths to the
__MICROSOFT_OS__ configuration macro.  This prevented handling Windows-style
paths in non-Microsoft OS modes, including Cygwin.  A new configuration macro
WINDOWS_PATHS_ALLOWED has been added to separate this behavior and allow the
front end to handle Windows-style paths in other modes.  This variable must be
TRUE when __MICROSOFT_OS__ is TRUE, and defaults to TRUE when either
__MICROSOFT_OS__ is TRUE or __CYGWIN__ is defined.


-------------------------------------------------------------------------------
Version 6.2, February 10, 2021

2/4/21   [EDGcpfe/23649]
GNU compatibility: may_alias attribute

In C mode, GCC accepts (with a warning in some cases) the may_alias attribute
on enum and struct definitions.  A change has been made to emulate that.  For
example (with --gcc):

  __attribute((may_alias)) struct A {};
  __attribute((may_alias)) enum E {e};


2/3/21   [EDGcpfe/23849]
Clang compatibility: __array_rank and __array_extent type intrinsics

The __array_rank and __array_extent type intrinsics have been added in 
clang emulation mode.


2/3/21   [EDGcpfe/23767,EDGcpfe/23844]
Constexpr destructor evaluation

The constexpr interpreter previously disallowed access to members of a class
as soon as the destructor evaluation starts, which prevented the destructor
body from accessing member variables.  Furthermore, virtual destructors were
not always handled correctly, and their evaluation could lead to memory
corruption.  That is now fixed.


2/2/21   [EDGcpfe/23816]
Overload resolution failure with conversions to arrays of unknown bound

Committee document P0388R4 allows for conversions of arrays of known bounds to
pointers or references to arrays of unknown bounds.  This was implemented in
EDGcpfe/21591 (in version 6.0), however, the implementation missed updating
the check for an overloaded function match.  This caused spurious errors when
attempting to call a function that had an overload set (where calling a
function with no overload set would succeed).  For example:

  void f(int(&)[]);
  void g(int(&)[]);
  void g();
  void test() {
    int arr[1];
    f(arr); // Accepted
    g(arr); // Previously rejected, now accepted
  }

This is now fixed.


2/2/21   [EDGcpfe/23612]
Incorrect handling of substitution of variable templates

In somewhat complex situations (occurring in recent versions for the Boost
"asio" library, for example), the front end did not correctly handle the
substitution of a dependent template-id that refers to a variable template.
That resulted in spurious overload resolution errors.  That problem is now
fixed.


2/1/21   [EDGcpfe/23674]
C++-generating back end: spurious pack expansion token output

The fix for EDGcpfe/21990 (in version 6.0) introduced a regression in the
C++-generating back end where pack expansion tokens would be emitted where they
should not have been.  For example:

  template <typename T, int size>
  struct arr { T arr[size]; };
  struct Ele { int i; };
  template <int... Is>
  auto doit() {
    // Spurious output of {{Ele{Is...}...}} in C++-generating back end mode
    return arr<Ele, sizeof...(Is)>{{Ele{Is}...}};
  }
  auto returns = doit<1>();

This is now fixed.


1/29/21  [EDGcpfe/23820]
Evaluation of std::construct_at for union members

The constexpr interpreter previously did not adjust the "active member" of a
union when constructing such a member using std::construct_at.  That in turn
could lead to spurious errors later on.  This is now fixed.


1/28/21  [EDGcpfe/23792,EDGcpfe/23823]
Spurious GNU C++17 mode error on nonconstant static data member initializer

Prior to C++17, in-class static data member initializers always had to be
constant initializers.  With C++17, such members can be "inline" and those can
have non-constant initializers.  In GNU C++17 mode, however, the front end
handles such members slightly differently when they appear in class template
instances to emulate GCC's on-demand instantiation of the initializer.
Unfortunately, that handling previously still required a constant initializer
and that triggered spurious errors in GNU C++17 mode.  For example:

  int f();
  template<typename T> struct S {
    static inline int const x = f();
  };
  int r = S<int>{}.x;  // Previously an error in GNU C++17 mode.  Now okay.

That problem is now fixed.


1/28/21  [EDGcpfe/21309]
Microsoft compatibility: forward declaration of enum type

The C++ standard prohibits a forward declaration of an enum type but
Microsoft allows it.  The front end had also allowed in Microsoft emulation
mode, but only with --ms_permissive.  A change has been made to accept this
in all Microsoft emulation modes.  For example, with --microsoft
--no_ms_permissive:

  enum E; // Now accepted even with --no_ms_permissive


1/27/21  [EDGcpfe/23819]
Class with a constexpr destructor and anonymous union not treated as literal

The front end previously always treated a class with a constexpr destructor and
an anonymous union as a non-literal class type.  That in turn could result in
spurious errors.  For example:

  template<typename T> struct S {
    union { T object; };
    constexpr ~S() {}
  };
  struct N {
    constexpr ~N() {}
  };
  constexpr void f() {
    S<N> s;  // Previously an error because S<N> considered non-literal.
  }          // Now okay.

That is now fixed.


1/26/21  [EDGcpfe/23550]
Microsoft compatibility: enabling additional features

A number of C++20 features are now enabled in various Microsoft emulation
modes.  The C++20 concepts feature (see the Changes entry for EDGcpfe/20005,
EDGcpfe/20118) is now enabled when microsoft_version >= 1923 and --ms_c++latest
is specified.  The C++20 modules feature is now enabled in Microsoft
emulation mode when microsoft_version >= 1928 and --ms_c++latest is specified.

Additionally, long_long_promotion_allowed, allow_parenthesized_aggregate_init,
and constexpr_dynamic_alloc_enabled are enabled when microsoft_version >= 1928
and --ms_c++latest is specified.

A slight versioning change is also taking place to follow the changes made
in the Microsoft Visual Studio numbering.  Previously, emulating Visual Studio
16.x typically meant setting microsoft_version to 192x, but beginning with
Visual Studio 16.9, some Visual Studio releases will share the same
microsoft_version number (e.g., 16.8 and 16.9 will both map to a
microsoft_version value of 1928) and can be distinguished (if necessary)
by specifying the appropriate microsoft_build_number (build numbers 29500 and
above indicate Visual Studio 16.9).


1/26/21  [EDGcpfe/23802]
C- and C++-generating back end: Rendering of 128-bit integer types

Previously, the C- and C++-generating back ends always rendered GNU 128-bit
integer types as "__int128_t" and "__uint128_t", which are predefined GCC
typedefs.  However, starting in version 4.6, GCC also accepts __int128 with an
optional "signed" or "unsigned" modifier.  That caused the back ends to render

  signed __int128 x = 0;

(in GNU modes with gnu_version >= 40600) as

  signed __int128_t x = 0;

which is invalid since the "signed" modifier cannot be applied to a typedef
name.  That is now fixed: When the target GCC version is 40600 or larger, the
back ends now render the 128-bit integer types using the __int128 specifier.


1/26/21  [EDGcpfe/23812]
GNU/Clang compatibility: Explicit specialization of constexpr variable

Consider:

  struct S {
    template <typename> static constexpr int m = 104;
  };
  template<> constexpr int S::m<int>;  // Normally an error.  Now accepted in
                                       // some GNU and Clang modes.

The explicit specialization is normally an error because it is missing an
initializer (see also the resolution of Core issue 2409), but GCC and Clang
accept the case (Clang in C++17 mode only).  The front end now emulates that
GCC and Clang behavior in the respective compatibility modes.


1/26/21  [EDGcpfe/23805]
C++-generating back end: out-of-bounds array access with auto type specifier

Use of the auto type specifier could result in out-of-bounds array accesses
in source_corresp_for_template_param, causing unpredictable behavior
including segfaults and incorrect output.  This is now fixed.  For example,
with --c++17:

  template<typename T> void f(T t) {
    auto t2(t);   // Caused out-of-bounds array access
  }


1/25/21  [EDGcpfe/12122,EDGcpfe/23794,EDGcpfe/23799]
Clang compatibility: additional builtin type intrinsics

The following builtin type intrinsics are now available in Clang emulation
mode: __is_arithmetic, __is_complete_type, __is_compound, __is_const,
__is_floating_point, __is_fundamental, __is_integral, __is_lvalue_reference,
__is_member_function_pointer, __is_member_object_pointer, __is_member_pointer,
__is_object, __is_pointer, __is_reference, __is_rvalue_reference, __is_scalar,
__is_signed, __is_unsigned, __is_void, and __is_volatile.

Additionally, enabled builtin type intrinsics now return TRUE when queried with
__has_builtin.  Furthermore, the intrinsic __is_signed is treated specially in
some contexts: If it appears immediately following decl-specifiers that include
"static", "bool", and "const", the __is_signed is treated as an ordinary
identifier from that point (with a warning).  For example:

  bool x = __is_signed(int);  // Okay.  "__is_signed" is a keyword.
  static bool const __is_signed = false;  // Okay (with warning).
                                          // "__is_signed" is not a keyword.
  bool y = __is_signed(int);  // Syntax error.

This matches Clang behavior and allows certain GCC headers that declared an
__is_signed identifier to be parsed in modes that support the __is_signed
intrinsic by default.


1/22/21  [EDGcpfe/23797]
Missing destructor evaluation in constexpr initialization

Consider:

  struct S {
    int *m;
    constexpr S(): m(new int{}) {}
    constexpr ~S() { delete m; }
  };
  constexpr int f(const S&) { return 0; }
  constexpr int i{ f(S{}) };  // Previously an error.  Now okay.

Previously, the front end failed to evaluate the destructor for the temporary
created by the expression S{}.  In turn, that caused the dynamic allocation in
the constructor of S not to have a matching deallocation, and an error was
issued claiming the initializer for i is not a constant because not all dynamic
allocations were freed at the end of the evaluation.  That is now fixed: The
destructor for S{} is now evaluated, and the example above is accepted.


1/22/21  [EDGcpfe/23796]
Nontrivial generated constexpr destructors

The front end previously always treated nontrivial generated destructors as not
being constexpr.  However, that is not correct behavior if the generated
destructor never calls a non-constexpr destructor.  For example (C++20 mode):

  struct S {
    constexpr ~S() {}
  };
  class C { S s; };
  constexpr C c{};  // Previously an error.  Now okay.

Previously, the front treated the (generated) destructor of C as non-constexpr.
Now, it is considered a constexpr member function because it only calls the
destructor of S, which is itself constexpr.


1/21/21  [EDGcpfe/23597]
Enum bit field initialization in Microsoft mode

In Microsoft mode, enum bit fields are treated as their underlying type when
initializing, due to the Microsoft compiler allowing integral types to be used
as initializers.  Unfortunately, this caused a spurious error when initializing
a scoped enum bit field with an enumerator belonging to that scoped enum.  For
example:

  enum class E
  {
    A = 0x0, B = 0x1
  };
  struct X {
    E member1 : 2;
    E member2 : 2;
  };
  X var{E::A, E::B}; // Attempt to initialize an "int" with an enum class
  X var2{0, 1}; // Ill-formed, still accepted in Microsoft mode

This has now been fixed.


1/21/21  [EDGcpfe/23479]
Multiple translation units: DMIs in class templates not being scanned

In configurations that support multiple translation units, the front end skips
instantiations in secondary TUs when those instantiations have already been
done.  For class templates that have fields with initializers, this could lead
to the field initializers not being scanned in those secondary TUs, causing
the front end to abort in prepare_for_trans_unit_copy.  For example, if two
TUs both contain:

  template<bool> struct X;
  struct Y {
    static constexpr bool val = true;
  };
  template<typename T> struct Z
  {
    using MY = Y;
    using MX = X<MY::val>;
    int mem_var = 0;
    Z() {}
  };
  struct Foo {
    Z<int> var{};
  };

This is now fixed.


1/20/21  [EDGcpfe/23683]
Clang compatibility: __builtin_assume

Changes have been made to better emulate clang's __builtin_assume.
Specifically, this builtin can now be used in a constexpr context and is
now lowered like Microsoft's __assume builtin.  For example, with
--clang_version 110000:

    constexpr int f(int i) {
      __builtin_assume(i >= 0);
      return i + 1;
    }
    constexpr int j = f(2);


1/19/21  [EDGcpfe/23510]
Assertion failure in unlink_src_seq_entries after static data member error

In somewhat unusual error cases, the front end aborted with an internal error
in unlink_src_seq_entries (src_seq.c) while parsing a static data member
declaration (usually, this involved severe preceding syntax errors).  This
problem occurred in configurations with the configuration macro
TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE.  For example:

  template<typename T>
  struct HK {
    static T const& f(T const& v) {
      return v;
    }
  };
  template<typename K, typename T>
  struct HK<HV<K, T>> {         // Error: HV undeclared
    typedef HV<K, T>  VT;
    typedef P<K const, T>  CT;  // Error: P undeclared
    template<typename U> static 
      typename E<S<U, VT>::value, CT const&>::type f(U &p) {  // (1)
        return p.f();
      }
  };

Due to several identifiers (HV, P, and E) not being declared, angle brackets
are not recognized as such and (1) is parsed as a static data member
declaration.  Previously, the front end's error recovery measures were
insufficient and it aborted as described above.  That problem is now fixed.


1/18/21  [EDGcpfe/23688]
C++-generating back end: parenthesized dependent destructor invocation

In configurations in which template definitions are generated from the
prototype instantiation IL, when the C++-generating back end generated code
for an explicit invocation of the destructor of a dependent type it
enclosed the member access expression designating the destructor in
unnecessary parentheses.  If the template is instantiated with a scalar
type, forming a pseudo-destructor call, the resulting expression violated
the C++ Standard's requirement that a pseudo-destructor reference be the
direct operand of a call operation.  This is now fixed; the redundant
parentheses are omitted in such cases.  For example, with --c++14:

  template<typename T> void f(void *vp) {
    auto p = (const T *)vp;
    p->~T();   // Previously generated as (p->~T)()
  }
  void g() {
    f<int>(nullptr);
  }


1/18/21  [EDGcpfe/23684]
Microsoft compatibility: __assume

Microsoft's __assume builtin function allows a user to give hints to a code
generator to optimize certain cases.  The operand of the builtin function
is not executed and had, in cases where the expression had side-effects,
been removed from the IL during lowering (replaced with a cast of zero to the
correct type).  A change has been made to lower the operand of __assume in
all cases, thereby allowing a back end to see the entire (lowered) operand.
For example, with --microsoft:

  struct A {
    A(int);
    ~A();
    operator bool();
  };
  int main() {
    __assume(bool(A(1)));
    return 0;
  }

This is a slight IL CHANGE and back ends should ensure that the operand of
an eok_assume is not evaluated.


1/15/21  [EDGcpfe/23728]
Coroutines in lambda expressions

The implementation of the restriction that coroutines cannot be constexpr
functions in the front end failed to account for functions that are implicitly
constexpr if they can be constexpr.  Most notably, this includes lambda
expressions.  For example:

  #include <coroutine>
  void f()
  {
    // Spurious "a constexpr function cannot be a coroutine" error
    auto g = []() -> std::generator<int> {
      co_yield 1;
      co_yield 2;
    };
  }

This is now fixed.


1/15/21  [EDGcpfe/23704]
Friend definitions in class templates and constexpr

Consider:

  template<typename T> struct S {
    friend constexpr int f(S<T>) { return sizeof(T); }
  };
  template<typename T> struct X { double x[f(T{})]; };
  X<S<int>> xsi;  // Previously an error.  Now okay.

Previously, this elicited a spurious error claiming the instantiation of the
array dimension "f(T{})" is not a constant expression because the function
"f" is not defined.  This was due to an ordering issue in the "instantiation"
of the friend function definition.  That is now fixed.


1/14/21  [EDGcpfe/23730]
Incorrect handling of rewritten comparison operators in some SFINAE contexts

Consider:

  struct Order { friend bool operator<(Order, decltype(nullptr)); };
  struct S {};
  Order operator<=>(S const&, S const&);
  template<typename T> concept HasNot = requires (T p) { !p; };
  template<typename T> concept C = requires (T s) { { s < s } -> HasNot; };
  static_assert(C<S>);  // Previously an error.  Now okay.

For the static assertion to succeed, the result of "s < s" with s of type S
must be of a type to which the "logical not" operator applies.  That is the
case here since "s < s" is rewritten as "(s <=> s) < 0" which invokes the
friend operator< whose type is bool.  However, previously the front end used
the type of "(s <=> s)" (which is Order) when checking the HasNot constraint,
and that led to a spurious error.  Similar errors could occur in other SFINAE
contexts.  That problem is now fixed.


1/13/21  [EDGcpfe/23758]
C++-generating back end: invalid memory access with MAKE_FRONT_END_CALLABLE

The C++-generating back end failed to set the variable
avail_access_cache_entries to NULL upon entry, potentially resulting in
access to freed memory in configurations in which MAKE_FRONT_END_CALLABLE
is TRUE.  This is now fixed.


1/12/21  [EDGcpfe/23664]
Failure to treat certain dependent qualifiers as nondeducible

Consider:

  template<typename> struct V { typedef void Type; };
  template <typename, typename = void> struct X;
  template <typename T> struct X< T, typename V<decltype(bool(T()))>::Type> {
    static constexpr bool value = true;
  };
  static_assert(X<int>::value, "");  // Previously an error.  Now okay.

The front end previously did not match X<int> to the partial specialization
because it did not consider V<decltype(bool(T()))>::Type to be nondeducible.
That is now fixed (and the case above is now accepted).


1/11/21  [EDGcpfe/23700]
Temporary eliminated in lowering of class rvalue-returning comma operation

In cases where the second operand of a comma operation initialized a class
rvalue, lowering would create a temporary variable, initialize it, and then
copy (without invoking a copy or assignment constructor) the temporary to
its final destination.  That had violated some of the guarantees of the class.
For example (with --c++11):

  extern "C" void abort();
  struct S {
    void* p;
    S() noexcept : p(this) { }
    ~S() noexcept {
      if (p != this) abort();   // had aborted previously
    }
  };
  int main() {
    S s = ((void)0, S());
    return 0;
  }

There is a slight IL CHANGE to support this: the
is_optimized_class_rvalue_question_mark field in a_dynamic_init has now been
renamed to class_rvalue_initialized_through_master_entry to reflect its
expanded role.


1/11/21  [EDGcpfe/17807,EDGcpfe/19983,EDGcpfe/20388,EDGcpfe/22137]
Microsoft compatibility: access checking in SFINAE contexts

Earlier versions of the Microsoft compiler did not perform access checking
as part of the SFINAE process.  Starting with version 1910, they now do.
We now enable SFINAE access checking in Microsoft mode when microsoft_version
is >= 1910.

  struct A {
    template <class T> static typename T::X f(T);
  };
  class B {
    typedef int X;
  };
  int main() {
    B b;
    A::f(b);  // now fails overload resolution
  }


1/11/21  [EDGcpfe/23743]
Typo: USE_X64_X64 -> USE_X86_64

A mis-typing of the deprecated USE_X86_64 configuration macro in targ_def.h is
now fixed.  Although the fix has no real consequence, it may trigger #error
messages designed to alert the customer of uses of the deprecated macro.  The
change was originally made by EDGcpfe/15604 et al.


1/6/21   [EDGcpfe/23738]
Divide by zero floating-point exception

The front end could trigger a divide by zero floating-point exception
(in decompose_vector_binary_operation) when folding certain vector operations.
Now fixed.  For example (with --g++):

  typedef float Z;
  typedef Z __attribute__((vector_size(sizeof(Z)))) V;
  static constexpr V v = V() + 0.0f;


1/5/21   [EDGcpfe/23727]
GNU compatibility: redeclaration of variable inside for loop

Versions of GNU earlier than 4.7.0 allowed a variable name defined in a
for-init construct to be reused for another variable in the loop's body (see
the Changes entry from 1/11/05).  A change has been made to issue an error
when gnu_version >= 40700.  For example:

  void f() {
    for (int i = 0;;) {
      int i = 3;  // Now an error when gnu_version >= 40700
    }
  }


12/29/20 [EDGcpfe/23719]
Microsoft compatibility: pack init-captures and lambda disambiguation

When Microsoft extensions are enabled, special processing is done to
disambiguate between a lambda and a Microsoft attribute.  This processing
did not correctly handle C++20 pack init-captures resulting in spurious
errors in some cases.  Now fixed.

  template<typename U, typename ... T> void f(U u, T ... t) {
    auto l ([i = u, ... j = t](){});
  }
  template void f(int, char, short, int);


12/28/20 [EDGcpfe/23718]
Inconsistent representation of pack init-captures

The IL representation for pack init-captures (a C++20 feature) was not
consistent with the representation of other (non-init-capture) forms of
capture.  In particular, the entries for the expansion of "... i" incorrectly
had their is_pack_expansion flag set.  In addition, the IL for the definition
of the pack "i" incorrectly had the is_captured_pack_element field set.  As
part of the resolution of this issue, an is_pack_element field has been added
to the a_lambda_capture entry (a small IL CHANGE).

  template<typename ... T> void f(T ... t) {
    [t ...] () { };
    [... i = t] () { };
  }
  template void f(short, int);


12/18/20 [EDGcpfe/23498]
C++-generating back end: missing type name in initializer for deduced type

In a variable declaration in which the type of the variable is deduced from
the initializer, the C++-generating back end sometimes incorrectly omitted
the type name from the initializer expression, resulting in generated code
that could not be compiled.  This is now fixed.  For example, with --c++17:

  struct S {
    S(int, int) {}
  };
  void f() {
    auto x{S(0, 0)};  // Previously generated as "x{0,0}"
  }


12/17/20 [EDGcpfe/23120]
Improvements to parenthesized aggregate initializers

In C++20, aggregates can be initialized from a parenthesized list of values
(see the entry for EDGcpfe/20913).  The standardization committee's paper
P1975R0 made a few changes to that, enabling for example casting a value to
an aggregate type whose first element matches the value.  For example:

  struct X { int i; char *pc = nullptr; };
  X x1 = X(1, nullptr);      // Enabled by the changes for EDGcpfe/20913.
  X x2 = X(1);               // Now also accepted in C++20 mode.
  X x3 = (X)(1);             // Ditto.
  X x4 = static_cast<X>(1);  // Ditto.


12/16/20 [EDGcpfe/23693]
Microsoft compatibility: template argument to __builtin_zero_non_value_bits

A spurious error had been emitted when the type of the argument to
__builtin_zero_non_value_bits is a template dependent type.  Now fixed.

  template <class T> void f(T t) {
    __builtin_zero_non_value_bits(t);
  }


12/15/20 [EDGcpfe/23671]
Source sequence entry for nonreal friend class

In some cases, the front end did not record a source sequence entry for a
friend declaration naming a nonreal class.  That in turn caused the C++-
generating back end not to render the friend declaration.  For example:

  template<typename T> struct S: public T::template N<S<T>> {
    friend typename T::template N<S>;  // Previously not recorded in the
  };                                   // source sequence entries list.

That problem is now fixed.


12/15/20 [EDGcpfe/23685]
Parenthesized pseudo-destructor names

The changes for EDGcpfe/21397 caused the front end to diagnose the use of a
pseudo-destructor name that is not the immediate operand of a "call".  That
includes parenthesized pseudo-destructor names, such as in the following
example:

  typedef int I;
  void g(I *p) {
    (p->~I)();  // Always an error in versions 6.0 and 6.1 of the front end.
  }             // Now okay in nonstrict modes.

The standard currently deems this example invalid, but other implementations
accept it, and there are reasons to believe that perhaps the standard wording
is unintentional.  The front end therefore now accepts the example above in
nonstrict C++ modes.
  

12/15/20 [EDGcpfe/23675]
Abort in unwrap_if_tpck_expression

The changes for EDGcpfe/22825 introduced a regression (in version 6.1) that
caused the front end to abort (with a null pointer indirection) in
unwrap_if_tpck_expression (in some configurations).  For example:

  template<typename T> T f(T*);
  template<int I> void g(int *x) {
    f<int>(&x[I+1]);  // Triggered an abort in version 6.1.
  }

That is now fixed.


12/15/20 [EDGcpfe/23690]
Add missing attribute kind strings

A number of attribute kinds were not properly mapped to display strings
resulting in "** BAD KIND **" being displayed by the edgcpdisp IL display
program.  Now fixed.


12/14/20 [EDGcpfe/23515,EDGcpfe/23643]
C++20: Ambiguity with rewritten reversed-parameters comparison candidate

The changes for EDGcpfe/23009 relax the overload resolution rules in nonstrict
modes when a member operator== is ambiguous because of differences in const-
qualifiers between the explicit parameter and the "this" parameter.  Now, that
relaxation is also applied when an operator!= can be rewritten in terms of such
an operator==.  For example:

  struct X {
    bool operator!=(const X&);
    bool operator==(const X&);
  };
  bool b = X() != X();  // Previously ambiguous in C++20 mode.  Now selects
                        // operator!= in nonstrict C++20 modes (with a
                        // warning).


12/11/20 [EDGcpfe/23679]
C++-generating back end: return statement with attributes

Previously, the C++-generating back end always omitted a return statement
with no expression appearing at the end of a function, since simply flowing
off the end of the function is equivalent to a return with no expression.
However, that omission resulted in incorrect code when the return statement
carries an attribute.  This is now fixed, and such return statements are
now preserved in the generated code.  For example, with --c++14:

  void foo() {
    [[likely]] return;  // Previously generated only the attribute
  }


12/10/20 [EDGcpfe/23640]
GNU compatibility: __builtin_convertvector

The __builtin_convertvector builtin has now been enabled when
gnu_version >= 90000.


12/10/20 [EDGcpfe/22967,EDGcpfe/23184]
Abort in anon_union_field_is_active_field

The front end previously sometimes aborted in anon_union_field_is_active_field.
This regression, introduced by the changes for EDGcpfe/22948 in version 6.1, is
now fixed.


12/9/20  [EDGcpfe/23646]
C++20: Defaulted explicitly constexpr default-constructors

Consider:

  struct S {
    int i;
    constexpr S() = default;  // Now accepted in C++20 mode.
  };

Previously this elicited an error in all C++ modes, because the default
constructor is declared constexpr but fails to initialize the member i.
However, the committee's paper P1331R2 lifted the requirement that a constexpr
constructor initialize all its subobjects: The example is therefore now
accepted in C++20 mode (but still an error in non-C++20 modes).  See also the
entry for EDGcpfe/23055, which covers the similar case for a non-defaulted
constexpr constructor definition.


12/9/20  [EDGcpfe/23648]
Missing diagnostic on dynamic_cast<void*> applied to null pointer value

The front end previously accepted the following example:

  struct S {};
  auto p = dynamic_cast<void*>((S*)nullptr);  // Previously accepted.
                                              // Now an error.

The standard, however, requires a diagnostic because S is not polymorphic
(and that is relied upon by a common SFINAE idiom to determine if a class type
is polymorphic).  This is now fixed: A diagnostic is issued.


12/9/20  [EDGcpfe/14164,EDGcpfe/19415,EDGcpfe/23273]
Core issue 903: Null pointer constants

The resolution of Core issue 903 (treated as a defect report against C++11)
restricts null pointer constants to zero literals.  Other expressions that
produce an integer constant of value zero are no longer treated as null pointer
constants by the front end, unless matching specific behavior of other
compilers (for example, permissive Microsoft mode still retains the prior
behavior, and in GNU modes casting a zero literal to an integer type can still
produce a null pointer constant).  For example:

  int *p = 4-4;  // Now an error in default C++11 mode.

(See also the entry of 11/11/20 for EDGcpfe/23533,EDGcpfe/23541, which covers
constant variables evaluating to a zero value.)


12/7/20  [EDGcpfe/23666]
Colorization of diagnostic output

A change has been made to enable "colorization" of certain portions of the
diagnostics emitted by the front end (similar to the behavior of GNU and
clang).

Portions of diagnostic messages have been instrumented to enable highlighting
of them via various escape sequences (Select Graphic Rendition or SGR codes)
that are generally recognized by many terminals and/or terminal emulators.
See https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters for a list.

The items that can currently be highlighted are:

  - "error": highlights the "error" or other error-like words
  - "warning": highlights the "warning" keyword
  - "note": highlights the "note" or "remark" keyword
  - "quote": highlights certain fill-in portions of diagnostics
  - "locus": highlights the initial source location
  - "range1": highlights subsequent source locations

Each of these can be assigned a sequence of SGR codes to highlight the
particular item(s).  The default SGR codes are given by the
DEFAULT_EDG_COLORS macro whose default value is:

  "error=01;31:warning=01;35:note=01;36:locus=01:quote=01:range1=32"

The string is a colon-separated list of "value"="SGR codes" pairs where
"value" is from the list above.  The values can appear in any order.  Any that
are unset are not used.  Setting the EDG_COLORS environment variable overrides
the default value.  If EDG_COLORS is unset, GCC_COLORS is used if set.

The changes above are enabled when the new global variable
colorized_diagnostics is set to TRUE.  The default value for the variable is
set by the new configuration macro DEFAULT_ENABLE_COLORIZED_DIAGNOSTICS (which
defaults to TRUE).  Command-line options --[no_]colors have also been added.
Additionally, colorized diagnostics are also disabled if any of the following
are true:

  - The diagnostic output is not a terminal device.
  - The EDG_COLORS environment variable is set to the empty string.
  - The NOCOLOR environment variable is set.
  - The TERM environment variable is not set (or is set to "dumb").

This feature will only work on terminal emulators that support this feature.

When this feature is enabled, diagnostics are "annotated" with information
describing the beginning and end of each of the highlightable pieces listed
above (see the a_diagnostic_annotation_kind enum).  These annotations are then
converted to SGR codes in format_output_line when colorizing diagnostics, but
customers could use the annotations to provide their own highlighting (in a
GUI, for example).


12/7/20  [EDGcpfe/23662]
Argument-dependent lookup and template-ids

Consider:

  struct S {};
  template<typename> struct V {};
  namespace X {
    struct SX {};
    template<template<typename ...> class C> int f(SX);
    template<typename T> int operator|(T, int(*)(SX));
  }
  namespace Y {
    struct SY {};
    template<template<typename ...> class C> int f(SY);
  };
  namespace Z {
    using X::f;
    using Y::f;
  }
  int r = S{} | Z::f<V>; // Previously an error.  Now okay.

For argument-dependent lookup, the front end previously did not consider
namespaces and classes associated with the templates that make up the overload
set denoted by Z::f<V> in the example above.  That is now fixed.


12/7/20  [EDGcpfe/23465]
Abort on constexpr member variable in non-real instantiations

When a class contains a constexpr member variable with a dependent initializer,
the front end could previously abort when attempting a non-real instantiation
of the class.  For example:

  struct data
  {
      int x;
  };
  template<typename T>
  struct X
  {
      static constexpr data value = data{ 0 };
  };
  template<typename T>
  struct Y
  {
      static constexpr data value = X<T>::value;
  };
  template<typename T>
  struct Z : Y<T> { }; // Triggers non-real instantiation in Microsoft mode

This is now fixed.


12/4/20  [EDGcpfe/23502]
GNU/Clang compatibility: Inline static data members of class templates

In GNU C++ mode, in-class initializers for constant static data members of
class template instantiations are only instantiated when the associated value
is needed or the associated definition is instantiated (see the entry for
EDGcpfe/16403,EDGcpfe/16644).  Now that behavior has been extended to inline
static data members of class template instantiations, in both GNU and Clang
modes.  For example:

  template<typename T> struct S {
    static inline int value = T::f();
  };
  struct X: public S<X> {         // Previously an error.  Now okay in GNU and
    static int f() { return 0; }  // Clang C++17 modes.  
  };

Ordinarily, the example above produces an error because the initializer for
S<X>::value is parsed while S<X> is instantiated, prior to parsing the "body"
of X (i.e., before X::f() is declared).  Now, the example is accepted in GNU
and Clang modes because the initializer "T::f()" is not instantiated until it
is needed.


12/2/20  [EDGcpfe/23164]
Friend declarations for class member templates overwriting access

When a friend declaration targets a class member template, the front end could
overwrite the access level of the class member template with the level that was
currently active in the class where the friend declaration appeared.  For
example:

  class _State {
  public:
    template<typename _Res, typename _Arg>
    struct _Setter;

    template<typename _Res, typename _Arg>
    struct _Setter<_Res, _Arg&> {
    };
  };
  template<typename _Res>
  class promise {
  private:
    template<typename, typename> friend class _State::_Setter; // #1
  };

On the line labeled with #1, the access of _State::_Setter could get
overwritten with the private access level.  This is now fixed.


12/2/20  [EDGcpfe/23163]
Multiple translation units: Constexpr static data members in template prototype
instantiations

In configurations that support multiple translation units, when a template
prototype instantiation contains a constexpr static data member that has a
dependent initializer referencing another constexpr entity with internal
linkage, and this entity appeared in multiple TUs, the front end would issue a
diagnostic stating that the two entities were incompatible.  For example, if
two TUs include a header containing:

  constexpr int fac[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  template<int N>
  class count_time {
    static constexpr int factor = fac[N];
  public:
    static constexpr double toDouble(int val) {
      return static_cast<double>(val * factor);
    }
  };
  constexpr double func(int val) {
    return count_time<9>::toDouble(1);
  }

The front end would previously issue a diagnostic stating that
"count_time<N>::factor had a different meaning".  While this is technically an
ODR violation (meaning the diagnostic is correct) since "fac" has internal
linkage, the front end has relaxed the check for prototype instantiations in
non-strict modes.


12/2/20  [EDGcpfe/23162]
Multiple translation units: Spurious routine incompatibility with generated
exception spec

In configurations that support multiple translation units, the front end could
incorrectly mark two functions as incompatible (due to incompatible exception
specifications) when the exception specification is generated only when needed.
For example, if both TUs include a header containing:

  template<class T>
  struct time {
    time() = default;
    ~time() = default;
  };
  template<int N>
  struct count_time {
  };
  using Time = time<count_time<9>>;
  struct t {
    Time grantedTime;
    int x;
  };

and only one of the TUs has an instance of "struct t", the front end would
previously issue a spurious "declaration had a different meaning" or
"declaration is incompatible" diagnostic for the "time()" constructor.  This is
now fixed.


12/2/20  [EDGcpfe/23598]
Mangling of nontype template parameters in prototype instantiations

In configurations that do lowering, prototype instantiations are not
mangled (as they are not needed for code generation), but in some
configurations (when MANGLE_ALL_NAMES is TRUE), prototype instantiations
are mangled and their mangled names are generally unique.  That's not true
for cases involving nontype template parameters, for example the mangled
names for the prototype instantiations of following two templates were
identical:

  template <int *> void f() {}
  template <char *> void f() {}

A change has been made to use the mangled encoding for the type of the
template parameter rather than the template parameter itself in such cases,
thereby making them unique.  This change is conditional on 
ABI_COMPATIBILITY_VERSION >= 602 and affects only configurations that do
not do lowering.


12/2/20  [EDGcpfe/23161]
Multiple translation units: Out-of-line defaulted definitions

The fix for EDGcpfe/22583 (in version 6.1) was too restrictive and
inadvertently caused the front end to issue a spurious "declaration is
incompatible" error when a function was defaulted separate from its
declaration in one TU, while the class was defined in both TUs.  For example,
if both TUs include a header file containing:

  struct foo {
    foo() = default;
    ~foo() noexcept;
  };

and one TU also contains:

  foo::~foo() = default;

The front end would spuriously complain that the two instances of "foo::~foo()"
were incompatible.  This is now fixed.


12/2/20  [EDGcpfe/21189,EDGcpfe/21408,EDGcpfe/22012,EDGcpfe/23625]
Fold-expressions in alias templates

The front end previously incorrectly handled the substitution of fold
expressions appearing in alias templates.  For example:

  template<bool> struct B { static constexpr bool value = true; };
  template<bool> struct CX { typedef bool type; };
  template<bool V> using C = typename CX<V>::type;
  template <typename ...Ts> using And = B<(Ts::value && ...)>;
  template<typename T> struct X {
    static const bool value = true;
  };
  template<typename ...Ts, typename = C<And<X<Ts>...>::value>>
  void g(Ts &&...) {}
  int main() {
    g(0, 0, 0, 0);  // Previously an error because the substitution in And
  }                 // failed.

That is now fixed.


12/1/20  [EDGcpfe/23623]
Designated initializers and constant evaluations

Consider (in GNU C mode):

  struct S { int i, j, k; };
  int main() {
    return ({
      struct S s = { .i = 1, .k = 3 };
      s.j;
    });
  }

The C standard specifies that s.j is zero even though it is seemingly "skipped"
by the designators for the initializer of s.  However, the interpreter (which
is invoked for the statement expression; see the entry for EDGcpfe/20980) did
not perform that zero initialization, causing the example above to return an
uninitialized value.  That issue -- a regression introduced in version 5.1 --
is now fixed.


11/30/20 [EDGcpfe/23168]
Assertion failure "missing typeinfo variable"

Generating typeinfo information for a function type with an exception
specification had, in some cases, resulted in an assertion failure
("missing typeinfo variable").  Now fixed.  For example (with --c++17):

  #include <typeinfo>
  void f() {}
  typedef void (*fp)(void) noexcept(true);
  auto *g() { return (fp)f; }
  const std::type_info &x = typeid((true, g)());


11/30/20 [EDGcpfe/21163]
Infinite loop with typedefs and attributes

It had been possible to get the front end into an infinite loop when adding
certain attributes to function types using typedefs.  That is now fixed.
For example (with --g++):

  typedef void f1_t(int*, int*, int*) __attribute__((nonnull(1)));
  typedef f1_t f2_t __attribute__((nonnull(2)));
  f2_t fn2 __attribute__((nonnull(3)));


11/30/20 [EDGcpfe/19889,EDGcpfe/23616]
GNU/Clang compatibility: Friend template declarations

Consider:

  namespace N { void f(); }
  struct X {
    template<class T> friend void N::f(T&&);       // (1)
    template<class T> friend void N::f(const T&);  // (2)
  };

Ordinarily, both friend declarations are errors, because the use of a qualified
name ("N::f") requires a matching template to exist.  However, GCC and some
versions of Clang accept that case.  The front end already attempted to
emulate this behavior and was successful in doing so with (1) (see the entry
for EDGcpfe/16435), but it issued a spurious error when a second friend
template declaration (like (2)) is added.  That is now fixed: The example
above is now accepted in GNU C++11 modes and in Clang C++11 modes with
clang_version < 90000.


11/30/20 [EDGcpfe/23591]
Unbounded loop while checking defaulted comparison function

In some cases, the front end could enter an unbounded loop (in function
may_be_lvalue_ref_to_const_type) while checking the parameters of a defaulted
comparison function.  For example (C++20 mode):

  template<typename T> struct S {
    friend bool operator !=(S const&, T&) = default;
  };                             // Previously triggered an unbounded loop.

That is now fixed.


11/30/20 [EDGcpfe/21482,EDGcpfe/22869,EDGcpfe/23117]
Assertion failures when lowering lambdas

In certain cases, an assertion failure (in release_reusable_temporaries or
free_temporary_list_entry_list) had occurred when lowering lambdas.  For
example (with --c++20):

  struct A {
    int x;
    int y;
    ~A() {}
  };
  void f() {
    [x = A(0)]{ return 0; }();
  }


11/30/20 [EDGcpfe/23618]
GNU compatibility: coroutine builtins

Signatures for coroutine builtins are now enabled in the appropriate GNU
emulation modes (i.e., when gnu_version >= 100100).


11/25/20 [EDGcpfe/23258]
Invalid code generated by lowering of some "for" statements

In cases where the increment expression of a "for" statement generates
temporaries that need initialization, the lowered initialization of such
temporaries had preceded its definition, causing generated C code that would
not compile.  For example (with --c++11):

  struct A {
    int x = 99;
  };
  void f() {
    for (; int y = 37; A{});
  }


11/24/20 [EDGcpfe/23474]
Build errors with TARG_HAS_IEEE_FLOATING_POINT is FALSE

The front end had failed to build in configurations where
TARG_HAS_IEEE_FLOATING_POINT is FALSE.  Now fixed.


11/24/20 [EDGcpfe/16972,EDGcpfe/20434]
Lowered code doesn't initialize aggregate properly

In cases where lowering of an aggregate constant with dynamic initialization
leaves a partially-initialized constant as part of the initialization, the
constant portion of the initialization had been omitted if that initialization
followed an executable statement.  For example (with --c++11):

  struct C {
    C() {}
  };
  struct A { int a; };
  struct B { A a; C c; };
  int main() {
    0;
    B b{};        // initialization follows an executable statement
    return b.a.a; // b.a.a is not initialized
  }


11/24/20 [EDGcpfe/23615]
Spurious error on dependent destructor invocation in constant-expression

Consider:

  template<bool> struct X {};
  template<typename T> X<(T().~T())> g();  // Previously an error.  Now okay.

Previously, this triggered a spurious error about the destructor invocation not
being permitted in a constant-expression context.  That is now fixed: The case
is now accepted.


11/24/20 [EDGcpfe/23614]
Clang compatibility: Clang 8.0.1 builtins

Builtin signatures have been updated to reflect builtins from clang version
8.0.1.


11/23/20 [EDGcpfe/23584,EDGcpfe/23596]
Improved support for non-8-bit-byte targets and hosts in constant evaluation

Various aspects of the constexpr interpreter have been improved to better deal
with target and/or host platforms where bytes are not eight bits wide.  For
example, an attempt to constant-evaluate a call to __builtin_bswap16 or similar
function previously resulted in an internal error if the target byte size is
not equal to 8.  Now, the evaluation just fails gracefully.


11/23/20 [EDGcpfe/23600]
Clang compatibility: __is_array

In Clang C++ modes, the front end now accepts the __is_array type traits
helper.


11/23/20 [EDGcpfe/23602]
Clang compatibility: Type differences when matching partial specializations

Consider:

  template<int M> struct I {};
  template<typename> struct S;
  template<short N> struct S<I<N>> {};
  S<I<100>> s;  // Now accepted in Clang mode.

This example is invalid because the partial specialization S<I<N>> is never
deduced as a match since the type of N (short) is not identical to the type of
the nontype template parameter M (int).  Clang, however, accepts this example
and the front end now also accepts it in Clang mode.  (Note that the example
was already accepted in Microsoft mode, but the Microsoft behavior that enables
the example is not limited to partial specializations.  See also the entry for
EDGcpfe/9367.)


11/23/20 [EDGcpfe/23435]
C++-generating back end, Microsoft compatibility: parenthesized pack
expansion template arguments

In some complex cases, MSVC reports a spurious error if a pack expansion
used as a non-type template argument is enclosed in unnecessary
parentheses.  The C++-generating back end has now been changed to avoid
putting out extra parentheses for expressions in such cases.


11/20/20 [EDGcpfe/23569]
Microsoft compatibility: __VA_OPT__ with --ms_std_preprocessor

The front end has now been changed to enable support for the __VA_OPT__
preprocessor operator (see EDGcpfe/20002) when the --ms_std_preprocessor
command-line option is specified, to better emulate the behavior of MSVC.


11/20/20 [EDGcpfe/22804]
C++-generating back end: C++20 rewritten comparison operators

In C++20, certain expressions involving comparison operators are rewritten
in terms of other operators, and the IL reflects the rewritten form of the
expression.  The C++-generating back end sometimes failed to restore the
original form of the expression, and in some cases the generated code was
incorrect.  This is now fixed.  For example, with --c++20:

  struct A {
    int i;
    friend bool operator==(const A&, const A&);
    friend bool operator!=(const A&, const A&) = default;
    void f() {
      A a, b;
      bool x = a != b;  // Previously generated as "!a == b"
    }
  };


11/20/20 [EDGcpfe/23133]
Missing initialization of nested aggregate

In configurations that use lowering, the lowered IL had, in some cases,
omitted zero initialization of nested aggregates, leading to objects having
uninitialized contents.  For example, with --c++14:

  struct C {
    C() {}
  };
  struct A { int a; };
  struct B { A a; C c; };
  int main() {
    B b{};
    return b.a.a;   // Result had been uninitialized and is now zero.
  }


11/19/20 [EDGcpfe/23608]
String literal operator templates in clang mode

The conditions under which string literal operator templates (see
EDGcpfe/15168,EDGcpfe/20235) were enabled in clang mode were not correct.
As noted in the original description, the feature was supported only in
C++14 and newer modes and when gnu_version was at least 40900.  In clang
mode, the restriction to C++14 mode was incorrect, and the dependency on
gnu_version was unobvious.  The front end has now been changed to enable
the feature in clang mode for C++11 and newer modes when clang_version is
at least 30400, regardless of the value of gnu_version.  For example, with
--c++11 --clang_version=30400:

  template<typename T, T ...chars> int operator"" _x();  // Now accepted


11/19/20 [EDGcpfe/23605]
Abort on constant-evaluation of Microsoft-mode prvalue conditional expression

The constexpr interpreter previously sometimes aborted (in do_constexpr_ctor)
when attempting to evaluate a conditional expression producing a prvalue for a
nontrivial class type.  For example:

  struct D { char data[4]; };
  struct X {
    constexpr X() = default;
    constexpr X(X&&) {}
    constexpr X(X const &x): val{x.val} {}
    D val{};
  };
  constexpr X f() {
    X v{};
    return true ? v : X{};
  }
  void g() { f(); }  // Previously triggered an abort in Microsoft C++ mode.
                     // Now okay.

That is now fixed.


11/19/20 [EDGcpfe/23606,EDGcpfe/23607]
Abort on requires-expression in nested template constraint

In C++20 mode, the front end previously sometimes aborted with an internal
error ("missing default rescan info" in get_expr_rescan_info, exprutil.c) when
attempting to evaluate a constraint on a nested template written with a
requires-expression.  For example:

  template<typename T> struct X {
    template<typename U> requires requires { f(U()); }
    X(U u) {}
  };
  X<int> r{ 1 };  // Previously an internal error.  Now an ordinary error.

This is now fixed.


11/19/20 [EDGcpfe/23561]
Clang compatibility: __is_pod

Consider (in Clang C++17 mode):

  struct E {};
  struct S { E const e; };
  static_assert(!__is_trivially_copyable(S));  // (1)
  struct SA { E const e[2]; };
  static_assert(!__is_trivially_copyable(SA));  // (2)

According to the C++ standard, both the static assertions (1) and (2) should
fail.  However, Clang accepts them both.  The changes for EDGcpfe/17387 et al.
caused us to accept (1) in Clang modes, but not (2).  Now (2) is also accepted
in Clang modes.  This affects not only the __is_trivially_copyable type trait
helper, but also related helpers like __is_pod and __is_trivial.


11/19/20 [EDGcpfe/23595]
Raw string literals in macro arguments with large macro replacements

The changes for EDGcpfe/21089 (in version 6.1) introduced a bug causing a
failed assertion (in nested_source_line_modif) when a raw string literal
containing a newline is used as a macro argument and the top-level macro
expansion in which this occurs is large enough to require extending the
buffer used for macro expansion.  This is now fixed.


11/19/20 [EDGcpfe/22202,EDGcpfe/23567]
Various fixes for attribute namespaces and __has_cpp_attribute

A number of small changes have been made to the way the __has_cpp_attribute
macro treats attribute namespaces, making the front end more compatible with
GNU and Clang.  For example:

  static_assert(__has_cpp_attribute(clang::fallthrough));
    // No longer fails the assertion in appropriate clang modes.
  static_assert(__has_cpp_attribute(gnu::__noinline__));
    // No longer fails the assertion in appropriate GNU modes.


11/19/20 [EDGcpfe/21953,EDGcpfe/23506,EDGcpfe/23604]
Abort on value-initialization of GNU vector type

The front end previously aborted (with an internal error in overload.c) on
attempts to value-initialize a GNU vector type.  For example (GNU C++11 mode):

  typedef int V4I __attribute((vector_size(16)));
  void f(V4I);
  void g() { f({}); }  // Previously triggered an internal error.  Now okay.

That is now fixed.


11/18/20 [EDGcpfe/23187]
C++-generating back end: naming members of inaccessible base classes

In some cases, the C++-generating back end put out a reference to a member
of a base class using the base class name as a qualifier, even though the
base class is inaccessible and the original source refers to the member
using the name of an accessible derived class as the qualifier.  For
example:

  template<typename T> class B {
  protected:
    template<int I> struct BN {
      static const T v = 0;
    };
  };
  template<typename T> struct D: B<T> {
    template<int I> struct DN: B<T>::template BN<I> { };
  };
  int x = D<int>::DN<10>::v;  // Previously "B<int>::BN<10>::v"

Previously the reference to the static member "v" was put out using the
class of which it is a member, even though B::BN is not accessible at the
point of the reference.  Now the C++-generating back end replaces the
inaccessible name qualifier for "v" with the name of the accessible derived
class.  (This change depends on use of the prototype instantiation IL for
the class templates and thus is not effective in configurations and modes
in which the class template definitions are generated from the string form
of the templates.)


11/18/20 [EDGcpfe/22900]
Partial ordering of rewritten comparison candidates

The resolution of Core issue 2445 fixed the rules determining the partial order
of function templates when one of the candidates is a C++20 comparison function
with reversed parameters.  The front end now implements that resolution.
For example:

  template<typename T> struct X {};
  template <typename T, typename U> bool operator==(T, X<U*>);
  template <typename T, typename U> bool operator!=(X<T>, U) = delete;
  auto r = X<int*>{} != X<int>{};  // Previously an error.  Now okay.


11/16/20 [EDGcpfe/23402]
Core issue 2267: Initialization of temporary for reference binding

The resolution of Core issue 2267 concludes that the initialization of a
temporary created for a reference binding should be treated as a "copy
initialization" even when the reference initialization uses direct-
initialization syntax.  That means that the temporary cannot be initialized
with an explicit conversion operator.  For example:

  struct X {};
  struct Y { explicit operator X(); } y;
  X const &rcx(y);  // Error: Explicit operator is not an option
                    // for copy initialization of temporary.

This change is currently not enabled in Clang and GNU modes since the
corresponding compilers do not implement that behavior yet.  In Microsoft
C++ mode, it is enabled when microsoft_version >= 1929.


11/16/20 [EDGcpfe/23592]
Microsoft compatibility: __builtin_offsetof assertion failure during lowering

As a result of the changes for EDGcpfe/21283 (in version 5.0), the
__builtin_offsetof builtin function was enabled in some Microsoft emulation
modes, but certain uses of it could cause an assertion failure (in
lower_builtin_operation).  That is now fixed.  For example (with
--microsoft_mode=1928):

  struct A { int x[100]; };
  int f(int i) {
    return __builtin_offsetof(A, x[i]);
  }


11/16/20 [EDGcpfe/22383,EDGcpfe/22903]
Core issue 2352: Reference binding and similar types

The front end now implements the resolution of Core issue 2352, which affects
certain reference bindings.  For example:

  int *ptr;
  const int *const &f() {
    return ptr;  // Previously a warning about binding a reference to a
  }              // local temporary.  Now returns a direct reference to ptr.


11/12/20 [EDGcpfe/23562]
GNU compatibility: Constant-evaluation of two-operand conditional operator

The constexpr interpreter can now evaluate the first branch of a GNU
two-operand conditional operators in more cases.  For example:

  constexpr int f(int p) { return p; }
  constexpr int g(int p) { return p ?: -1; }
  static_assert(g(1) == 1, "Unexpected");  // Previously an error.  Now
                                           // accepted.


11/12/20 [EDGcpfe/21841]
Spurious error with braced-initialization of a base class with a protected dtor

When a class constructor has an explicit braced-initializer of its base class,
and that base class has a protected-access destructor, the front end would
issue a spurious accessibility error.  For example:

  class Base {
  protected:
    ~Base();
  };
  struct Derived : public Base {
    Derived() : Base{} {} // Spurious "Base::~Base is inaccessible" error
  };

This is now fixed.


11/12/20 [EDGcpfe/23566]
GNU C++11 compatibility: Missing return statement in constexpr function

In GNU C++11 mode, the severity of a missing return statement for a constexpr
function template has been lowered to a warning if the template is never
instantiated.  For example, in GNU C++11 mode with no deferral of prototype
instantiations:

  template<typename T> struct S {
    constexpr bool f() {}  // Previously an error, now a warning.
  };

Furthermore, the error that is issued in other modes is now discretionary.


11/11/20 [EDGcpfe/23531,EDGcpfe/23564]
Constant-evaluation of __builtin_memcmp

Previously, evaluating __builtin_memcmp in a constant-expression required that
the operands to the intrinsic function be the addresses of top-level integer or
array of integer objects.  Now, the "top-level" requirement has been dropped:
The integer or integer array objects being compared can be subobjects.  For
example, in Clang C++17 mode:

  constexpr char const *alpha = "abcdefg";
  static_assert(__builtin_memcmp(alpha+1, alpha, 3) != 0);
                      // Now okay.  Previously a constant-evaluation failure.


11/11/20 [EDGcpfe/23533,EDGcpfe/23541]
Null pointer constants

In C++11 mode, the front end no longer treats as a "null pointer constant" an
expression that names a constant-valued variable of integer type with value
zero.  For example:

  int const zero = 0;
  int f(char);
  int f(const char*);
  int r = f(zero);  // Previously always ambiguous because "zero" was
                    // considered a valid null pointer constant.  Now okay
                    // in C++11 (and later) modes.

This is a consequence of the resolution of Core issue 903 (treated as a defect
report against C++11).  In permissive Microsoft modes, the prior behavior is
retained, however.


11/9/20  [EDGcpfe/23341]
Pack expansions in member-initializers (IL CHANGE)

When a pack expansion occurs in the member-initializer portion of a constructor
definition, the front end would previously issue spurious errors if the pack
expansion would initialize members in an order different from what is required.
For example:

  struct A {};
  template<class... Ts> struct X : public virtual Ts... {
    X(const Ts &... ts) : Ts(ts)... {}
  };
  X<X<A>, A> y{{{}}, {}};

In the above example, the pack expansion for 'X' amounts to:

  template<>
  struct X<X<A>, A> : public virtual X<A>, public virtual A {
    X(const X<A>& ts_1, const A& ts_2) : X<A>(ts_1), A(ts_2) {}
  };

Note that 'A' is also a virtual base class of 'X<A>'.  Because 'A' is a common
virtual base, it must be initialized first, despite appearing second in the
pack expansion.  The front end now correctly handles such initialization/
pack-expansion order differences.  As part of this change, the front end no
longer caches member-initializers, resulting in a small IL CHANGE: the
a_constructor_init field source.expr, a union member, is now a direct non-union
member named source_expr.


11/9/20  [EDGcpfe/23542]
Clang and Microsoft C++20 compatibility: Comparison rewrites

Consider:

  template<typename T> int operator!=(T const&, T const&);
  struct S {} s;
  int operator==(const S&, const S&);
  auto r = (s != s);

In C++20, this code is invalid: The overload resolution rules prefer rewriting
s != s in terms of operator== because (unlike the operator!=) it is not a
template, but C++20 also requires that the underlying operator produce a bool
result.  Clang does diagnose the case, but it only issues a warning if the
return type of operator== is a non-bool integer or enumeration type (as is the
case here).  We now emulate that behavior in Clang mode, and in other modes the
diagnostic is now a discretionary error.  The Microsoft compiler, on the other
hand, prefers the operator!= template: We now emulate that (nonstandard) choice
in Microsoft modes.  Note that the example above was valid C++17, and thus from
that perspective this could be seen as a regression in Clang and Microsoft
modes: Our implementation of the standard behavior in this particular case was
introduced through the changes for EDGcpfe/21587 in version 6.0.


11/6/20  [EDGcpfe/19958,EDGcpfe/23536]
GNU compatibility: "mode" attribute in C-generating back end configs

Previously the "mode" attribute had been suppressed in the C-generating back
end and is now emitted.  That enables typedefs like the one below to be
properly generated (in GNU modes):

  typedef _Complex float __attribute__((mode(TC))) __complex128;

Note also that in configurations where LOWER_COMPLEX is TRUE, the "mode"
attribute is effectively removed during the lowering of complex types.


11/4/20  [EDGcpfe/22904]
Lifetime-extended temporaries in constant expressions

The front end now permits the use of lifetime-extended temporaries bound to
reference-to-const variables.  For example:

  typedef const int CI[3];
  constexpr CI &ci = CI{11, 22, 33};
  static_assert(ci[1] == 22, "");  // Previously an error.  Now okay.

This implements the resolution of the C++ standardization committee's Core
issue 2126.


11/4/20  [EDGcpfe/23535]
Instantiation vs. substitution of exception specification

An earlier change (see EDGcpfe/22541) made exception specifications not
a SFINAE context in normal overload resolution.  This additional change
also removes the SFINAE processing in address of function and declaration
contexts.  For the example below, the diagnostic that was formerly
issued was 'no instance of function template "f" matches'.  With this
change an error is now issued on the instantiation of the exception
specification (in this case, 'no suitable constructor exists to convert
from "A<int> *" to "A<int>"').

  template <typename...> struct A { void f(A); };
  template <typename... Ts>
    void f(A<Ts...> &l, A<Ts...> &r) noexcept(noexcept(l.f(&r))){}
  void (*p)(A<int> &, A<int> &) = f<int>;


11/4/20  [EDGcpfe/22814]
C++-generating back end: template keyword in dependent friend declarations

In a friend declaration appearing in a class template in which the
qualifier contains a dependent template-id, the C++-generating back end
omitted the required "template" keyword, resulting in generated code that
could not be compiled.  This is now fixed.  For example:

  template<typename T> struct S1 {};
  template<int> struct S2 {
    template<typename T> struct S3 {
      using type = S1<int>;
    };
  };
  template<template<int> class X> struct S {
    friend typename X<0>::template S3<int>::type;  // "template" was omitted
  };


11/4/20  [EDGcpfe/21707,EDGcpfe/22796,EDGcpfe/23311,EDGcpfe/23528]
Spurious SFINAE failure on lookup for member selection (regression)

The changes for EDGcpfe/20899 (introduced in version 5.1) fixed some spurious
SFINAE failures, but they accidentally introduced new ones in other complex
situations.  For example, in C++17 mode:

  template<typename...> struct S { void f(S); };
  template<typename... Ts>
    void g(S<Ts...> &l, S<Ts...> &r) noexcept(noexcept(l.f(r)));
  void (*p)(S<int>&, S<int>&) = g<int>;  // Previously a spurious error.
                                         // Now okay.

That regression is now fixed.


11/3/20  [EDGcpfe/23514]
Abort on use of disambiguated operator== template

The changes for EDGcpfe/23009 (in version 6.1) introduced a disambiguation
measure for operator== members that are normally ambiguous because of a missing
const qualifier.  Unfortunately, that measure did not correctly handle
operator== member templates, and attempting to use such a template could lead
to an abort (in different places depending on the configuration).  For example:

  template<typename T> struct S {
    template<typename U> bool operator==(S<U> const&) /*not const*/;
  };                               
  bool f() {
    S<int> s;
    return s == s;  // Previously triggered an abort.  Now okay.
  }

That issue is now fixed.


11/3/20  [EDGcpfe/23519]
GNU compatibility: 80- or 128-bit complex numbers

The changes for EDGcpfe/18231 et al. (in version 5.0) added support for 80-
and 128-bit complex numbers, but typedefs for such types were incorrectly
generated by the C- and C++-generating back ends resulting in compilation
errors for the generated code.  That is now fixed.  For example:

  typedef _Complex float __attribute__((mode(TC))) __complex128;
  typedef _Complex float __attribute__((mode(XC))) __complex80;


11/3/20  [EDGcpfe/23518]
Abort on interpretation of dynamic_cast

In some cases involving address constants, the interpreter could abort (in
do_constexpr_dynamic_cast) on an attempt to perform a "sideways" dynamic_cast.
For example:

  struct B1 { constexpr virtual int f() { return 1; } };
  struct B2 { constexpr virtual int f() { return 2; } };
  struct D: B1, B2 { constexpr virtual int f() { return 3; } };
  D d;
  constexpr B1 *pb1 = &d;
  constexpr B2 *pb2 = dynamic_cast<B2*>(pb1);  // Previously triggered an
                                               // abort.  Now okay.

This is now fixed.


11/2/20  [EDGcpfe/23512]
Expression type diagnostics

A number of diagnostics that indicate problems with expression types have been
improved to explicitly mention the problematic type.  For example:

  struct S { int operator->(); } s;
  int r = s->f();  // Error text now mentions the "int" type.

Previously, the diagnostic on the "s->f" expression only noted that a pointer
type is expected.  Now, it also mentions that the "->" operator is applied to
type "int" specifically. 


11/2/20  [EDGcpfe/18571,EDGcpfe/23517]
Internal error with nonstandard default argument deduction

An internal error could occur (in i_copy_dynamic_init or copy_param_type_list)
when nonstandard default argument deduction is done (see 8/9/05 entry).  This
is done in old Microsoft (microsoft_version <= 1300) and g++ (gnu_version <=
40300) modes, or if the --nonstd_default_arg_deduction option is used.  Now
fixed.

  template <typename T> struct A;
  template <typename T, typename U> struct A<U T:: *> {
    static const bool value = true;
  };
  template <bool b> struct B { static const bool value = true; };
  template <class F> void func(F f) { const bool x = B<A<F>::value>::value; }
  struct S { ~S(); };
  struct S2 {
    void set(const S &n=S()) { }
  };
  int main() {
    func(&S2::set);
  }


10/30/20 [EDGcpfe/20512]
Incorrect evaluation of string literals when char is signed

In configurations with TARG_HAS_SIGNED_CHARS set to TRUE, the constexpr
interpreter failed to sign-extend its internal representation of string
elements, which could result in spurious errors.  For example:

  constexpr char const *s = "\200";
  int main() {
    static_assert(*s == '\200');  // Previously failed in some configurations.
  }                               // Now okay.

The subexpression *s (after integer promotion) was incorrectly folded to the
value 128 whereas the promotion of the character literal '\200' was correctly
evaluated to -128.  Consequently, the static_assert declaration failed
spuriously.  That is now fixed.


10/29/20 [EDGcpfe/23500]
C++-generating back end: form of enumeration constants

For enumeration values near the maximum and minimum of an enumeration's
signed underlying type, the C++-generating back end sometimes put out the
value in a form that could cause problems for some compilers when compiling
the generated code.  Enumeration values are now set to the expression that
appeared in the original source code rather than to a corresponding integer
constant.  For example, assuming 32-bit integers:

  enum E {
    mn = ~0x7fffffff   // Previously put out as 0x80000001-1
  };


10/29/20 [EDGcpfe/23504]
Overload resolution tie breaks based on inheritance

Consider:

  struct B {
    B(int, int = 0);
    void f(int = 0);
  };
  struct C: B {
    using B::B;  // Inheriting constructor.
    C(int);
    using B::f;
    void f();
  };
  struct D: C {
    using C::C;
    using C::f;
  };
  int main() {
    D d(1);  // Previously ambiguous.  Now okay.
    d.f();   // Previously always ambiguous.  Now okay in some GNU modes.
  }

The initialization "D d(1);" has to perform overload resolution between the
inherited C::C(int) constructor and the inherited B::B(int, int = 0);
constructor.  They match equally well as far as the constructor arguments go,
and the front end therefor previously reported an ambiguity.  However, the
standard includes a tie-breaking rule that prefers the constructor in the more
derived class in such cases (i.e., the C::C(int) constructor in this example).
That tie-breaking rule is now implemented.  The standard rule only applies to
constructors, and the call d.f() therefore remains ambiguous in most cases.
However, GCC 7.x and later appear to apply the constructor rule also to other
member functions: The front end now emulates that behavior in corresponding GNU
modes.  Prior to the rework of inheriting constructors in version 6.1 (see the
entry for EDGcpfe/17687) the example above was accepted (i.e., this change also
fixes a regression).


10/28/20 [EDGcpfe/23485]
Implicit noexcept and anonymous unions

The front end previously ignored anonymous union members when determining the
implicit exception specification of destructors.  For example:

  struct ND { ~ND() noexcept(false); };
  struct VED { virtual ~VED() noexcept(true); };
  struct S: VED {
    union { ND v; };
  };  // Previously silently accepted.  Now a warning or error because
      // the generated destructor is noexcept(false), but the overridden
      // destructor is noexcept(true).

Previously, the generated destructor of S was noexcept(true) because the
variant member S::v (whose destruction is noexcept(false)) was ignored for the
purposes of determining the exception specification.  Now, the variant member
causes the destructor of S to become noexcept(false), which makes it
incompatible with the base class destructor.  Some minor adjustments were also
made to the diagnostics in this area in Microsoft modes and C++11 modes.


10/28/20 [EDGcpfe/23241]
Microsoft compatibility: pack expansions and Microsoft nonreal base classes

In Microsoft mode, the front end emulates a Microsoft feature that finds
certain names in dependent base classes (see EDGcpfe/12786).  That
emulation could cause incorrect behavior when a sizeof...() operator was
used in a variadic template in a class that was instantiated as a nonreal
base class.  Now fixed.

  template <int> struct A;
  template <> struct A<1> {
    template <typename A0> struct B {
      typedef int X;
    };
  };
  template <typename T, typename... Ts> struct C {
    // Was 'too many arguments for class template "A<1>::B"'
    typedef typename A<sizeof...(Ts) + 1>::template B<int, Ts...>::X& X;
  };
  template <typename T> struct D : C<T> {};


10/27/20 [EDGcpfe/23377]
Argument-dependent lookup and local classes

When an argument of local class type (including local lambdas) was used
as a function argument, argument-dependent lookup should have included
the associated namespaces of the enclosing routine, but did not.  This
could produce an incorrect result from overload resolution.  Now fixed.

  template <class T> inline void f(T t) {
    auto l = []{};
    g(t, l);  // Was 'identifier "g" is undefined'
  }
  template <class T, class L> inline void g(T, L) {}
  int main() {
    f(1);
  }


10/27/20 [EDGcpfe/23496]
Microsoft C++ compatibility: Converting 0 to a nontype pointer parameter

C++11 (and later) does not allow a null pointer constant (like 0) to be used
as a nontype template argument of pointer type.  However, an exception was
previously made in Microsoft mode.  For example:

  template<int*> struct S {};
  S<0> s;  // Previously accepted in all Microsoft C++ modes.

Now, such cases are also permitted only in Microsoft mode with
microsoft_version < 1928.


10/27/20 [EDGcpfe/22831]
Trailing requires-clause on a member function and its explicit instantiation
or explicit specialization

Consider:

  template<typename T> struct S {
    int f() requires (sizeof(T)<128);
    int f() requires (sizeof(T)>=128);
  };
  template int S<int>::f();  // Previously an error.  Now okay.

Previously, the front end issued an error on the explicit instantiation
directive because it attempted to find a member declaration with no trailing
requires-clause.  Now, it evaluates the requires clause of each candidate
declaration and discards the candidates that fail the requirements.  In this
example (assuming sizeof(int)<128) that means the second member function is
discarded and the first one is instantiated for S<int>.


10/27/20 [EDGcpfe/23495]
Abort in interpreter during prototype instantiation with braced initializer

Consider:

  struct S { void (*pfs[2])(); };
  void f() { }
  template<typename T> void g(T) {
    constexpr S s = { f, f };  // Previously could abort.  Now okay.
  }

In some configurations, the front end could abort in the constexpr interpreter
during the prototype instantiation of g(T).  The root cause of that abort is
that in template-dependent contexts a braced initializer is not always matched
up with its destination type, even if the latter type is nondependent.  As a
result, the interpreter expanded the initializer into an object (variable s)
that does not match the layout of the initializer constant, leading to invalid
memory accesses later on.  This problem is now fixed.



10/26/20 [EDGcpfe/22840]
Trailing requires-clauses on friend declarations

The front end now issues an error (as required by the forthcoming C++20
standard) on a friend function declaration with a trailing requires-clause in
a class template definition if that function declaration is not a definition.
For example:

  template<typename T> class X {
    friend void f(T p) requires (sizeof(T) < 100);  // Now an error.
  };


10/26/20 [EDGcpfe/19494,EDGcpfe/20574,EDGcpfe/22687,EDGcpfe/23470]
GCC compatibility: accept nullptr in call to sync/atomic builtins

For some sync/atomic builtins, GCC/clang will accept an argument with pointer
type for an integer parameter (as long as the pointer and integer are the same
size).  That has now been extended to allow nullptr.  For example
(with --g++ --c++11):

  #define ATOMIC_ACQUIRE 2
  void f() {
    int* p = nullptr;
    __atomic_exchange_n(&p, (void*)0, ATOMIC_ACQUIRE); // Previously okay.
    __atomic_exchange_n(&p, nullptr, ATOMIC_ACQUIRE);  // Now also okay.
  }


10/26/20 [EDGcpfe/22978]
C++-generating back end: Concept definitions with comma expressions

Consider:

  template<typename T> concept C = (T() == T(), true);

The C++-generating back end previously rendered the resulting IL as

  template<typename T> concept C = (T() == T()), true;

in configurations with PARENS_IN_IL set to FALSE.  The syntax for a concept
definition, however, does not permit a top-level comma expression for the
expression on the right of the "=" token.  This is now fixed, and the front
end now renders that example as:

  template<typename T> concept C = ((T() == T()), true);

(The extra parentheses are benign.)


10/26/20 [EDGcpfe/22976]
Abort after invalid requires clause

The front end previously aborted due to a null pointer indirection in
scan_trailing_requires_clause (declarator.c) when an invalid requires clause
appeared on an unnamed ("abstract") declarator.  For example:

  template<typename ...T> struct X {};
  X<int* requires (0) > x;  // Previously aborted.  Now a normal error.

That is now fixed.


10/26/20 [EDGcpfe/11102,EDGcpfe/23484]
Microsoft compatibility: suppress __thiscall in generated C

A change has been made to suppress an explicit mention of the __thiscall
calling convention when generating C code for the corresponding declaration.
For example (with --microsoft):

  struct A {
    int __thiscall f(); // __thiscall is the default for member functions
                        // but now does not appear in the generated C for A::f.
  };
  int main() {
    A a;
    a.f();
  }


10/23/20 [EDGcpfe/22589,EDGcpfe/23473]
Internal error in get_rescan_info with class template argument deduction

In some situations with constructors involving parameter types that include
expressions, the front end aborted with an internal error in get_rescan_info
(exprutil.c, "missing default rescan info") while performing class template
argument deduction.  For example:

  template<int> struct E {};
  struct I { static constexpr int one = 1; };
  template<typename T> struct S {
    static constexpr int N = T::one;
    S() {}
    S(E<N> x) {}
  };
  void g() {
    S<I> x;
    S y(x);  // Previously triggered an internal error.
  }

This is now fixed.


10/22/20 [EDGcpfe/23483]
Microsoft compatibility: enable pack expansion in lambda init-capture

When lambda init-captures were added (in version 6.1, see EDGcpfe/20024) the
feature was not enabled in Microsoft C++20 mode, but should have been.  It
is now enabled in Microsoft C++20 mode when microsoft_version is >= 1922.


10/22/20 [EDGcpfe/18776,EDGcpfe/21126]
Designated initialization

DR 413 of the C standard makes it clear that implicit initialization of a field
does not override explicit initialization.  That is now implemented (in all
modes except GCC).  For example, with --c99:

  struct A { int i,j; };
  struct S { struct A a; };
  struct A a = { 1, 2 };
  int main() {
    struct S s = { a, .a.j = 102 };
    return s.a.i != 1;
  }

Previously, the value of s.a.i in the example above was 0 because s was
effectively initialized to {{0,102}}.


10/22/20 [EDGcpfe/23372,EDGcpfe/23373]
Incorrect lookup in class with same-named friend class

If a class template or an explicit specialization of a class template
contained an unqualified friend class template declaration of the same class
template, the lookup in an out-of-class constructor declaration could produce
an incorrect result or an internal error (in inactive_scope_lookup).  Now
fixed.

  template <class T> struct A {
    A(int i);
  };
  template <> struct A<int> : A<char> {
    A(int i);
    template <class T> friend class A;
  };
  A<int>::A(int i) : A<char>(i) {}


10/22/20 [EDGcpfe/23313]
C++-generating back end: omitted class prvalue cast in C++17 mode

In C++17 mode, the C++-generating back end sometimes omitted a cast that
changed the cv-qualification of a class prvalue, resulting in an expression
with the wrong type in the generated code.  This is now fixed.  For example,
with --c++17:

  struct A {};
  int f(const A& x);  // #1 
  int f(A&& x);       // #2
  int i = f(static_cast<const A>(A{}));  // Previous omitted the cast,
                                         // calling #2 instead of #1


10/20/20 [EDGcpfe/22089]
Microsoft C++ compatibility: __is_constructible

In Microsoft C++ modes, the __is_constructible type traits helper previously
took into account a Microsoft-mode anachronism that allows an lvalue reference
to a non-const class type to bind to a class prvalue.  However, the Microsoft
compiler does not do so.  For example:

  struct S { S(S&); };
  S make_S();
  S s(make_S());  // Anachronism still accepted in Microsoft mode.
  static_assert(!__is_constructible(S, S));
                  // Previously failed in Microsoft mode due to the anachronism
                  // illustrated above.  Now okay.


10/20/20 [EDGcpfe/22387]
GNU C++ compatibility: Flexible array members

Previously, in GNU and Clang C++ modes, the front end always treated a
nonstatic data member whose type is an array of unspecified length as if it
were an array of length zero (see the Changes entry of 10/17/02).  Now, in
Clang C++ modes and in GNU C++ modes with gnu_version >= 60000 such members are
treated like C99 flexible array members.  For example:

  struct S {
    char a;
    int b[];  // Now an error in Clang C++ modes and GNU C++ mode with
    char c;   // gnu_version >= 60000 because the flexible array member is
  };          // not the last member.


10/20/20 [EDGcpfe/23427]
Abort in find_instantiation_insert_scope with variable template instance

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
front end sometimes aborted with a null pointer access while processing a
variable template reference that does not correspond to a formal instantiation
(this could happen in particular in complex error cases).  That issue is now
fixed.


10/19/20 [EDGcpfe/23463]
C++-generating back end: Out-of-bounds array access

The function handle_rewritten_comparison in the C++-generating back end is
responsible for rendering comparison expressions that the front end "rewrote"
in terms of more fundamental operators.  When an x != y expression was
rewritten in terms of "!" and "==" operators, however, a typo caused the C++-
generating back end to access an array beyond its bounds.  That could
potentially lead to an abort or to incorrectly rendered code.  That issue is
now fixed.


10/19/20 [EDGcpfe/23461]
Abort during processing of Clang enable_if attribute

The use of Clang's enable_if attribute could result in an internal error in
release_local_constant.  For example:

  constexpr int g() __attribute((enable_if(0, ""))) { return 0; }
  constexpr int g() { return 1; }
  static_assert(g() == 1, "");  // Previously an internal error.  Now okay.

This is now fixed.


10/16/20 [EDGcpfe/23260]
Abort in is_skipped_decltype_context in GNU C++17 mode

The front end previously aborted (due to a null pointer indirection) in
is_skipped_decltype_context when processing certain ill-formed cases in
GNU C++17 mode.  For example:

  template<typename T> struct S {};
  template<typename T> void f() { S s; }

That is now fixed.


10/15/20 [EDGcpfe/23458]
Abort on Microsoft array property subscript with Clang ms-extensions mode

The front end previously could abort with an internal error in
conv_glvalue_to_prvalue when subscripting a Microsoft array property in Clang
ms-extensions mode.  For example:

  struct S {
    __declspec(property(get=get_x, put=put_x)) int x[];
    int get_x(int i, int j);
    void put_x(int i, int j, int k);
  };
  int main() {
    S *p = 0;
    return p->x[1][2];  // Previously triggered an internal error in some
  }                     // modes.  Now okay.

This is now fixed.


10/15/20 [EDGcpfe/23439]
Default constructible const members

Consider:

  struct I { int i = 42; };
  struct S {
    const I ci;
  };
  S s;  // Previously an error.  Now okay (except in Clang modes).

Previously, the generated default constructor of S was marked as deleted
because it contains a const member of type I const where I has no user-provided
default constructor).  Now, the front end instead checks whether class type I
is "const-default-constructible" (a standard property), which I satisfies by
providing default initializers for its members, and that prevents the default
constructor of S from being deleted.  In Clang mode the previous behavior is
maintained because current versions of Clang still appear to match that.


10/14/20 [EDGcpfe/21969,EDGcpfe/23039,EDGcpfe/23365,EDGcpfe/23455]
GNU/Clang compatibility: attributes on enumerators in C mode

Attributes are now enabled on enumerators in C mode when emulating clang
or when emulating GCC (when gnu_mode >= 60000).  For example:

  enum {
    old __attribute__((deprecated("do not use")))
  };


10/14/20 [EDGcpfe/23456]
Clang compatibility: builtin support for Clang 11.0.0

New builtin signatures for Clang 11.0.0 have been added.


10/12/20 [EDGcpfe/22823]
C++17: Allow converted lambda as nontype template pointer-to-function argument

The front end now accepts the following example:

  template<void(*)()> struct A {};
  int main() {
    constexpr auto fp = +[]{};
    (void)A<fp>{};  // Previously always an error because fp points to a
  }                 // function with no linkage.  Now okay in C++17 modes.

in C++17 modes.  This is a consequence of the standardization committee's
paper N4268 (see also the entry for EDGcpfe/18747).


10/12/20 [EDGcpfe/20943,EDGcpfe/23454]
Default template arguments for template-dependent nontype template parameters

Consider:

  template<typename T, T const& = T()> struct S {};

Previously this elicited an error in C++03 mode because the default template
argument can never be a match for the parameter type.  Now, in nonstrict modes,
that error is delayed until the template S is instantiated using that default
argument (because that appears to be what other implementations do).  Also,
some cases involving C++17 "auto" template parameters are now correctly
handled.  For example (C++17 mode):

  int n;
  template<auto X, decltype(X) = &n> struct S {};  // Previously an error.
  S<&n> sn;  // Okay.

Previously, this example elicited an error because the front end attempted to
bind &n to the parameter of type decltype(X) too early.


10/12/20 [EDGcpfe/23165]
IA-64 ABI: Assertion failure in add_discriminator

In IA-64 ABI configurations that do mangling, an assertion failure (in
add_discriminator) had occurred when mangling a constant in a local class.
This regression was introduced by the changes for EDGcpfe/11127,EDGcpfe/21364
(in version 6.0).  For example:

  void f() {
    class A {
      const int x = 33;
    };
  }


10/9/20  [EDGcpfe/23257]
Type-constraints applied to decltype(auto)

The front end previously issued spurious errors on a variable declaration using
a type-constraint followed by decltype(auto).  For example:

  template<typename> concept C = true;
  C decltype(auto) x = 42;  // Previously an error.  Now okay.

That is now fixed.


10/9/20  [EDGcpfe/23450]
Visibility of function template in its own noexcept specifier

The front end previously failed to diagnose cases like the following:

  template<typename> concept C = true;
  void f(C auto) noexcept (f(42)) {}
    // Previously erroneously accepted.  Now an error.

because the front end delays the parsing of the noexcept operand and that
accidentally made the template visible in its own noexcept specifier.  That is
now fixed: The example now elicits an error about f being undefined in "f(42)".


10/8/20  [EDGcpfe/22255]
Coroutines: Abort on projection symbol for operator new/delete

In configurations where coroutines are enabled, the front end could abort in
record_symbol_reference_full due to attempting to record a symbol reference on
a projection symbol for operator new/delete.  This is now fixed.


10/8/20  [EDGcpfe/23432]
Multiple translation units: Incorrect correspondence for enums in routines

When compiling multiple translation units, in cases where the front end is
required to compare template argument lists and the arguments contain
enumerator constants, the front end could incorrectly deem two different
enumerators as corresponding to each other.  This would in turn lead to
spurious "had a different meaning" errors.  For example, with an empty primary
TU and a secondary TU containing:

  class X {
    template<typename T> X(T);
  };
  bool operator==(X, X);
  template<int N> struct D {
    D() {
      enum { e1 = N, e2 };
      if (e1 == e2) {} // Instantiates X::X and compares template arg lists
    }
  };
  D<0> q;
  D<1> r; // Creates the different enumerator constant list in D::D

This is now fixed.


10/8/20  [EDGcpfe/18784,EDGcpfe/18847,EDGcpfe/20144,EDGcpfe/21386,
          EDGcpfe/23124,EDGcpfe/23447]
Constant-evaluation of unsigned integer to same-sized signed integer

The front end previously did not correctly handle the constant-evaluation of a
conversion from an unsigned integer that has its most significant bit "on" to
an unsigned type of the same size.  For example:

  constexpr unsigned f(unsigned p) {
    return (int)p + 1;  // The cast was previously not handled correctly.
  }
  static_assert(f(~0) == 0, "Unexpected");  // Previously failed.  Now okay.

That is now fixed.


10/8/20  [EDGcpfe/23397]
Binding rvalue references to character arrays to braced string literals

The front end previously aborted (in prep_list_initializer, overload.c) on the
following case:

  int f(const char (&&)[4]);
  int f(const char (&&)[5]);
  int r = f({"abc"});

That is now fixed.  In addition, the handling of the following related example:

 const char (&&r4)[4] = {"abc"};  // Error: Attempt to bind to an lvalue.
 const char (&&r5)[5] = {"abc"};  // Okay: Binds to a temporary.
 const char (&&r_)[] = {"abc"};   // Previously okay.  Now same as r4 case.

has been fixed.  Previously, the unspecified bound was handled as a distinct
"length" causing the front end to treat the r_ case like the r5 case.  That is
now corrected: It is treated like the r4 case, and thus a similar error is
issued for the r_ case.


10/7/20  [EDGcpfe/23434]
Multiple translation units: Abort with a template using-declaration

When compiling multiple translation units where two TUs contain the same
class template which inherits from another class template, the front end could
have an assertion failure (in equiv_base_using_decls) when in Microsoft
compatibility mode if a using-declaration named a template in the base class.
For example, if both TUs contain:

  template<typename> struct X {
    template<typename> void func();
  };
  template<typename T>
  struct Y : public X<T> {
    using X<T>::func; // Assertion triggered here
  };

This is now fixed.


10/7/20  [EDGcpfe/23394]
Assertion failure in mangled_encoding_for_function_type

In configurations that do lowering, an assertion failure (in
mangled_encoding_for_function_type) had occurred with this example and is
now fixed:

  #include <typeinfo>
  struct A {
    const std::type_info* const info;
    template <typename T> static void f() {
      static A a = { &typeid(T) };
    }
  };
  void g() {
    A::f< int(*)() >();
  }


10/7/20  [EDGcpfe/23445]
Abort in check_template_constraints

The front end previously sometimes aborted when checking type-constraints on
certain templates (in check_template_constraints, attempting to dereference a
null pointer).  For example:

  template<typename T> concept C = requires(T &r) { r.f(); };
  template<typename T> struct S { template<typename U> S(U&&); };
  template<C T> S(T&&) -> S<int>;
  struct X { int f(); };
  void g(X x) {
    S s{ x };  // Previously aborted while checking the constraints on the
  }            // deduction guide.

That is now fixed.


10/6/20  [EDGcpfe/23433]
Multiple translation units: Missing correspondence for variable templates

When compiling multiple translation units, the front end could abort in
check_correspondences with a message stating that an "entity with external
linkage does not have corresp info".  This was caused by the presence of a
non-real instantiation of a variable template.  For example, in Microsoft mode
where the primary TU is empty and a secondary TU contains:

  template<bool> struct X;
  template<typename> bool var; // Abort due to missing corresp info
  template<typename> class Y {
    template <typename T, X<var<T>>>
    friend bool i(Y);
  };
  template<typename> class Z {
    virtual Y<int> func() {}
  };
  Z<int> foo;

This is now fixed.


10/6/20  [EDGcpfe/22253,EDGcpfe/23053]
Microsoft compatibility: Template template parameter deduction bug

Older versions of the Microsoft compiler (MSVC 19.21 and earlier) exhibit a
subtle bug when deducing template template parameters.  Specifically, if a
template template parameter is preceded by one or more template parameters
with default arguments and the deduction process would use all the default
arguments, then deduction fails.  For example:

  template<typename> class X;
  template<template<typename> class> struct S {};
  template<typename, int = 42, int = 42, template<typename> class TT>
    int f(S<TT>) { return 0; }
  int main() {
    int r = f<char>(S<X>{});    // Error in older MSVCs.
    return f<char, 8>(S<X>{});  // Accepted by older MSVCs.
  }

The front end now emulates this behavior in Microsoft bugs mode with
microsoft_version < 1922.


10/5/20  [EDGcpfe/23298]
Abort with default arguments to inheriting constructors

In configurations where IL lowering is performed, the front end could abort in
lower_dynamic_init when lowering code where a default argument is provided to
a constructor that has been inherited, and that inheriting constructor is being
used.  For example:

  struct A {
    ~A() { }
  };
  template <class T> struct B {
    B(int, A = A()) { }
  };
  struct C : B<int> {
    using B<int>::B;
  };
  template <class T> void f() {
    C c(1); // Abort triggered here
  }
  void g() {
    f<int>();
  }

This is now fixed.


10/5/20  [EDGcpfe/23191]
Spurious GNU-mode ambiguity on member overloaded with using-declaration

The changes for EDGcpfe/21627 introduced a regression in some GNU C++ modes in
situations where a member template is overloaded with a member projected by a
using-declaration.  For example:

  template<typename> struct B {
    template<typename U> B& operator=(U v);
  };
  template<typename T> struct D: public B<T> {
    using B<T>::operator=;
    template<typename U> D& operator=(U v);
  };
  int main() {
    D<int> di;
    di = 2;  // Previously ambiguous in GNU C++ modes.  Now okay.
  }

That regression (introduced in version 6.0) is now fixed.


10/5/20  [EDGcpfe/23361]
Spurious error with DMI and nested types

The change for EDGcpfe/19729 (in version 6.1) introduced a regression where
the front end would issue spurious errors on certain data member initializers
that used nested types.  For example:

  struct A {
    class B {
      int m_0{0};
    };
    B b1{};
    B b2{}; // Spurious "constructor cannot be used in an initializer for its
            // own data member" error
  };

This is now fixed.


10/5/20  [EDGcpfe/13299,EDGcpfe/18121,EDGcpfe/20733,EDGcpfe/23411]
GNU compatibility: Spurious warnings with "noinline" attribute

The front end had given spurious warnings when the "noinline" attribute was
applied to a member function (implicitly defined as "inline").  For example
(with --g++):

  struct A {
    __attribute__((noinline)) void f() {};  // No warning now.
  };


10/5/20  [EDGcpfe/23378]
C++-generating back end: unrecognized pragmas and implicit IL blocks

The IL for certain source constructs includes compiler-generated stmk_block
entries to manage the scoping and lifetime of variables, and the
C++-generating back end put those out in the generated code, even though
they were not present in the source and are implied by the associated
constructs.  In configurations with INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL set
to TRUE, however, the location of pragmas could be incorrect with respect
to the block structure of the generated code.  For example, with --c++14:

  void f() {
    #pragma omp parallel
    {
      const int I = 32;
      while (true) {
        const int J = I;
        if (J == 0) {
          continue;
        }
      }
      #pragma omp critical
      {
        ;
      }
    }
  }

The generated code previously contained an extra block around the body of
the "while", i.e., "while (true) { { ... } }", and the "omp critical"
#pragma was placed between the two closing braces.  This is now fixed; the
C++-generating back end no longer puts out braces for compiler-generated
blocks in the generated code.


10/5/20  [EDGcpfe/23436]
Abort in name mangling following error in template static data member

An abort could occur (in add_variable_template_indication) in certain
configurations with MANGLE_ALL_NAMES set to TRUE because in some error
cases a variable with is_template_variable set to TRUE had a NULL
template_info pointer.  Now fixed.
 
  template <typename> struct S {
    static constexpr bool = true;   // Missing member name
  };


10/5/20  [EDGcpfe/22801]
C++-generating back end: type operators in template arguments

In certain complex cases, a type operator appearing in a template argument
could be put out by the C++-generating back end as a type involving a
temporary name (of the form  __T12345678).  This is now fixed.  For
example, with --c++14:

  template<typename> struct A {
    static constexpr bool v = true;
  };
  template<typename T> struct B { B(T) { } };
  template<typename T> using id = T;
  template<typename T> B<T> f(T t) { return {t}; }
  void g() {
    auto x = f([]{});
    static_assert(A<id<decltype(x)>>::v);  // Previously generated as
                                           // "A<B<class __T12345678>>::v"
  }


10/2/20  [EDGcpfe/23423,EDGcpfe/23429]
Comparison operators defaulted outside of their associated class definition

Two bugs related to comparison operators defaulted outside of their associated
class definition have been fixed.  First, the front end previously aborted with
an internal error when deducing an "auto" return type for an operator<=>
defaulted outside its associate class definition.  For example:

  #include <compare>
  struct S {
    class N {
      int i;
      friend auto operator<=>(N, N);
    };
  };
  auto operator<=>(S::N, S::N) = default;  // Previously triggered an
                                           // internal error.

That is now fixed (as is the spurious error that was also triggered by that
example).  Second, some comparison comparison operators defaulted outside of
their associated class definition caused the front end to issue an error when
it instead should have marked the operator as implicitly deleted.  For example:

  #include <compare>
  union U {
    int i;
    friend bool operator!=(U, U);
  };
  bool operator!=(U, U) = default;  // Previously an error.  Now the operator
                                    // is "deleted" (because there is no
                                    // corresponding operator==).

That is now also fixed.


10/2/20  [EDGcpfe/23426,EDGcpfe/23430]
Dependent enumerator constants used in template arguments

Consider:

  template<int N> struct X {};
  template<int N> struct S {
    enum E { e = N, f = e+1 };
    X<f> m() { return X<f>{}; }
  };
  S<3> s;

The changes for EDGcpfe/22825 caused the representation of X<f> to be recorded
as if it were X<e+1>.  However, that replacement was not needed for the issue
resolved by EDGcpfe/22825 and it loses some information that is useful for
accurately rendering the template argument in some applications.  The use of
the enumerator constant f is now restored in the representation of the nonreal
type X<f> of that example.


10/1/20  [EDGcpfe/23424]
Incorrect mangled names in IA-64 ABI config

A recursive call during the mangling of a constant had resulted in the
inadvertent overwriting of a static buffer resulting in an incorrect value for
some integer constants in an IA-64 ABI mangled name.  That resulted in
duplicate (but both incorrect) mangled names for this example (with --c++17):

  template <int N> struct A {
    enum { e1, e2 };
  };
  template <auto T> void f();
  void g() {
    f<A<99>::e1>();
              // Was _Z1fILN1AILi99EEUt_E99EEvv, now _Z1fILN1AILi99EEUt_E0EEvv
    f<A<99>::e2>();
              // Was _Z1fILN1AILi99EEUt_E99EEvv, now _Z1fILN1AILi99EEUt_E1EEvv
  }


9/29/20  [EDGcpfe/20535,EDGcpfe/23410]
Conditional operator value category with incompatible type qualifiers

Consider:

  int const ic = 42;
  int volatile iv = 0;
  auto r = &(0 ? ic : iv);  // Previously okay.  Now an error.

Previously, the front accepted such code because it treated the conditional
operator as being an lvalue with the combined type qualifiers of both operands
(i.e., int const volatile).  Now, the conditional operator is only a glvalue
if one operand is a qualified version of the other; otherwise, it is a prvalue
(which makes the address-of operator in the example invalid).

9/29/20  [EDGcpfe/23251]
Multiple translation units: Abort with friend template specializations

When compiling multiple translation units, where a secondary TU contains a
class template with a friend template, where the class is later instantiated,
the front end could abort in check_correspondences with a message saying
"entity with external linkage does not have corresp info".  For example, with
an empty primary TU and a secondary TU containing:

  template<typename> struct X
  {
    template<typename T> friend void foo(T, X);
  };
  template<typename> struct Y {
    virtual void func() {
      X<int>(); // Abort due to foo(T, X<int>) not having corresp info
    }
  };
  Y<int> var;

This is now fixed.


9/29/20  [EDGcpfe/23104]
Multiple translation units: Abort with variable templates

When compiling multiple translation units that both referred to the same
variable template instance, the front end could abort in set_trans_unit_corresp
with a "correspondence busy" message.  For example, the front end would abort
if two TUs both #include a header containing:

  struct X {
    template<typename> static constexpr int k = 0;
    template<int> struct Y;
    template<typename T> using A = Y<k<T>>;
    template<typename T> A<T> foo(T); // Abort here, caused by using 'k'
  };

This is now fixed.


9/29/20  [EDGcpfe/23417]
C++-generating back end, GNU C++ compatibility: ill-formed initializers in
function template default arguments

G++ accepts certain ill-formed initializers in the default arguments of
function templates, and the front end correctly emulates this behavior.
However, the resulting IL could cause the C++-generating back end to abort
with an assertion failure in gen_initializer_constant.  This is now fixed.
for example, with --parse_templates --c++14 --gnu_version=80300:

  template <typename, int> struct S { };
  template <int N = 1> void f(const S<int, 2>& s = {0, 1});

This example previously aborted with the message "ran out of fields"
because S<int, 2> does not have any members for the given initializers to
initialize.  (Note that a similar abort could occur with some well-formed
initializers, because accepting the ill-formed initializers requires not
doing the processing required to produce initializers in the prototype
instantiation IL that fully match the target of the initialization.)


9/28/20  [EDGcpfe/22851,EDGcpfe/23408]
GCC and Microsoft compatibility: Aliases and deduction guides

Consider:

  template<typename...> struct S;
  template<typename> using A = S<>;
  template<typename T> S() -> const A<T>;  // (1)

The deduction guide (1) is invalid both because it includes a const qualifier
for the deduced type and because that deduced type isn't written in terms of
the template name ("S") of the deduction guide.  However, GCC and MSVC both
accept this form (i.e., they ignore the type qualifiers and look through the
alias).  The front end now emulates that behavior in the corresponding C++
modes.


9/28/20  [EDGcpfe/23414]
C++-generating back end, Microsoft compatibility: injected-class-name as
template template argument

Older versions of MSVC issue a spurious error when the injected-class-name
of a class template is passed as an argument to a template template
parameter.  The C++-generating back end previously generated code of this
form, but now when msvc_is_generated_code_target is TRUE and
msvc_target_version_number is less than 1913, such references in template
arguments are put out using the qualified name of the template instead of
its injected-class-name.  For example, with --microsoft_version=1900
--parse_templates:

  template<template<typename> class> struct A { };
  template<typename> struct B {
    A<::B> ab;   // Previously generated as "A<B>"
  };


9/27/20  [EDGcpfe/21489]
Redeclaration of template with different parameter names and noexcept

A spurious error could result if a function template was redeclared with
different parameter names that were used in a noexcept-specifier.  Now
fixed.

  template <class T> void f(T &t) noexcept(noexcept(t));
  template <class U> void f(U &u) noexcept(noexcept(u));


9/24/20  [EDGcpfe/23407]
Microsoft compatibility: Failure to substitute sizeof(&T::m)

In Microsoft bugs mode, the front end now fails substitution (SFINAE) for an
expression of the form sizeof(&T::m) where &T::m is a pointer-to-member
constant.  For example:

  template<typename T> int f(int (*)[sizeof(&T::init)+1]);
  template<typename T> int f(...) = delete;
  struct X { void init(); };
  int r = f<X>(0);  // Normally accepted, but now selects the deleted f(...)
                    // in Microsoft bugs mode.


9/24/20  [EDGcpfe/21829,EDGcpfe/23284]
Microsoft compatibility: Microsoft nonreal base classes, --parse_templates,
and --no_ms_permissive

In Microsoft mode, the front end emulates a Microsoft feature that finds
certain names in dependent base classes (see EDGcpfe/12786).  This emulation
was previously disabled if --dep_name was used.  In addition, the emulation
was supposed to be disabled with --no_ms_permissive, but it was still
incorrectly being done.  The emulation is now correctly disabled with
--no_ms_permissive and is now also disabled when parsing nonclass templates
(i.e., when nonclass_prototype_instantiations is TRUE).  This prevents a
spurious error from being issued for examples like the one below when
compiled with --microsoft --parse_templates.

  struct A {
    void *v = nullptr;
  };
  template <typename T> struct B : public A {
    B();
  };
  template <typename T, typename U> struct C : public B<T> {
    explicit operator T&() { return *(this->v); }
  };


9/24/20  [EDGcpfe/23245]
Internal error following syntax error in decltype in default template argument

An internal error could occur (in copy_tokens_from_cache) if a default
template argument resulted in certain syntax errors during the instantiation
of a dependent default template argument.  Now fixed.

  struct A {};
  template <bool> using B = A;
  template <typename> void f();
  template <typename> class E;
  template <typename... Ts> struct F : B<__is_constructible(E<int>, Ts...)> {};
  template <typename h> class E {
    // h(...) is a functional-notation cast when h is int, and so the second
    // argument is not allowed.
    template <typename = decltype(h(0, f<>))> class G;
  };
  int main () {
    F ff;
  }


9/23/20  [EDGcpfe/19404,EDGcpfe/23405]
Abort on generic lambda nested in local non-generic lambda

The front end previously could abort in scope_depth_for_capture (expr.c) with
an internal error when checking capturing by a generic lambda nested in a local
non-generic lambda.  For example:

  int main() {
    const int N = 42;
    auto nl = [](){ return [](auto){ return N; }; };
    nl()(8);
  }

This is now fixed.


9/22/20  [EDGcpfe/23299]
C++-generating back end: attributes in friend function declarations

The C++-generating back end incorrectly inverted the order of attributes
and the "friend" keyword in generated code.  This is now fixed.  For
example, with --c++17:

  class C {
    [[nodiscard]] friend int f() {  // Previously put out as
                                    // "friend [[nodiscard]] int f()"
      return 0;
    }
  };


9/22/20  [EDGcpfe/23404]
Microsoft compatibility: spaceship operator

The C++20 spaceship operator was previously enabled with --ms_c++latest
only when microsoft_version was 1922 or greater; that has been changed to 1921
to match Visual Studio's behavior.


9/22/20  [EDGcpfe/23391]
Clang ms-extensions compatibility: static/extern mismatch

The changes for EDGcpfe/21168 cause the front end to accept

  extern void g(void); 
  static void g(void) {}

in Microsoft mode.  It turns out that Clang also accepts this with its
-fms-extensions switch, and the front end now follows suit with the
--ms_extensions option.


9/22/20  [EDGcpfe/23400]
Abbreviated function templates and source sequence entries

Configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE usually aborted
on abbreviated function templates because extraneous source sequence entries
not pointing to any entities were recorded.  For example:

  auto f(auto i) { return 2*i; }  // Previously aborted in some configurations.

That is now fixed.  In addition, the C++-generating back end has been updated
to correctly render such abbreviated function templates.


9/22/20  [EDGcpfe/23399]
Microsoft compatibility: --no_ms_permissive is now implied by --ms_c++latest

Beginning with microsoft_version == 1928, --no_ms_permissive is implied
when --ms_c++latest is specified.  This can be overridden by adding
--ms_permissive.


9/22/20  [EDGcpfe/23401]
Deleted virtual overrider and exception specification mismatch

In C++17 mode, the front end now permits a deleted virtual function overrider
to have a less-strict exception specification than the (deleted) virtual
function it overrides.  For example:

  struct B { virtual void h() noexcept = delete; };
  struct D : B {
    void h() = delete;  // Now accepted in C++17 mode.
  };


9/21/20  [EDGcpfe/23396]
Regression with __LPREFIX appearing in template definition

The changes of EDGcpfe/16268 (in version 6.1) introduced a regression in
the front end's handling of __LPREFIX inside template definitions: the type
of such an expression became "array of const char" instead of "array of
const wchar_t".  This is now fixed.  For example, with --microsoft:

  void f(const wchar_t *);
  template <typename T> void g(T t) {
    f(__LPREFIX(""));   // Previously an error, now okay
  }
  void x() {
    f(1);
  }


9/21/20  [EDGcpfe/21410]
Class template argument deduction and single-element initializer lists

Single-element initializer lists are sometimes treated specially for the
purpose of class template argument deduction.  The changes for EDGcpfe/20936
implemented that special rule for direct-list-initialization, but failed to do
so for copy-list-initialization.  For example:

  #include <initializer_list>
  template<typename T> struct X {
    X(std::initializer_list<T>);
  };
  X<int> x{};
  X y = { x };  // Previously, y had type X<X<int>>.  Now y has type X<int>.

That is now fixed.


9/21/20  [EDGcpfe/21600]
Member function qualifiers erroneously ignored in conditional operator

Consider:

  struct S {
    int f();
    int g() const;
  };
  auto pmf = 0 ? &S::f : &S::g;  // Previously accepted.  Now an error.

The changes for EDGcpfe/20971 introduced a regression in version 5.1 causing
the difference in qualifiers between &S::f and &S::g to be ignored when forming
the composite pointer-to-member type for the conditional operator.  That
regression is now fixed.


9/21/20  [EDGcpfe/23362]
Mangling for designated initializers

Mangling for designated initializers has been added to both the IA-64 and
Cfront ABIs.  The mangling for the Cfront ABI uses the same codes and overall
structure as that of the IA-64 ABI.  For example, with --c++20:

  struct A { int a, b; };
  struct B { int c, d; };
  template<typename T> void f(decltype(T{.a = 1, .b = 2}));
  template<typename T> void f(decltype(T{.c = 1, .d = 2}));
  int main() {
    f<A>(A());
    f<B>(B());
  }


9/21/20  [EDGcpfe/22879]
Constant-evaluation of __builtin_memcpy

In GNU and Clang modes, the front end (interpreter) can now evaluate certain
invocations of __builtin_memcpy at compile time.  For evaluation to succeed
the address operands must point to compile-time objects, the number of bytes
being copied must correspond to copying underlying objects (e.g., not a partial
integer), and the objects being copied must be trivially copyable.  For
example:

  constexpr bool test() {
    float arr[] = { 1.0, 42.0 };
    float arr2[2];
    (void)__builtin_memmove((void*)arr2, (void*)arr, 2*sizeof(float));
    return arr2[0] == arr[0] && arr2[1] == arr[1];
  }
  static_assert(test());  // Now accepted in GNU and Clang C++ modes.

__builtin_memmove, __builtin_wmemcpy, and __builtin_wmemmove are similarly
supported.


9/18/20  [EDGcpfe/23374]
Spurious errors on noexcept-specifier on friend template declaration

A noexcept specifier of a template should only be instantiated if needed.
The front end could issue spurious errors as a result of evaluating a
noexcept-specifier of a friend template declaration too early.  Now fixed.

  template <typename T> struct B {
    template <typename>
      friend void f(B &&p) noexcept(noexcept(static_cast<T const &>(p))) {}
  };
  struct D;
  struct E: B<D> {};


9/17/20  [EDGcpfe/22717,EDGcpfe/23086]
Multiple translation units: Aborts with mistaken canonical correspondences

When compiling multiple translation units where an entity exists in more than
one translation unit, the front end could sometimes fail to distinguish
properly canonical representations of that entity from cases where no other
corresponding entities had yet been assigned.  This caused aborts in
f_set_unvisited_trans_unit_corresp and
set_master_instance_for_new_canonical_routine.  The change for EDGcpfe/22581
(in version 6.1) partially fixed this issue, but not correctly nor completely.
This has now been fixed (by backing out that change and replacing it with a
different fix).


9/17/20  [EDGcpfe/23383]
GNU C++ compatibility: missing "template" keyword bug fixed in g++

A change made in version 5.0 (see EDGcpfe/19506) restricted a g++ bug
emulation to versions < 60000.  However, only part of that bug was
fixed in g++ 6.x.  The remaining part was fixed in g++ 7.x.  g++ did
not require the "template" keyword if the name used following a field
selection operator when looked up by normal lookup found a template
that is a member of the current prototype instantiation.  We now
emulate this behavior when gnu_version is < 70000.

  template <class T> struct A {
    template <int I> void g();
    template <class U, int I> void f(A<U> at) {
      at.g<I>();  // Was "expected an expression" with gnu_version 60000
    }
  };
  int main() {
    A<int> a;
    a.f<int,1>(a);
  }


9/16/20  [EDGcpfe/22901]
consteval calls in unevaluated contexts

The front end now implements the changes of the C++ standardization committee's
paper P1937R2, which cause consteval calls in non-evaluated contexts to no
longer be called.  For example (in C++20 mode):

  constexpr int f();
  consteval int g(int p) { return p; }
  decltype(g(f())) r = 42;  // Previously an error.  Now okay.

Previously, this elicited an error because the evaluation of g(f()) could not
be completed due to a missing definition of f().  Now the example is accepted
because g(f()) is no longer evaluated.


9/15/20  [EDGcpfe/23002,EDGcpfe/23380]
Lowering of __builtin_constant_p

In configurations with DEFAULT_ALWAYS_FOLD_CALLS_TO_BUILTIN_CONSTANT_P set to
FALSE, the front end sometimes generates actual calls to __builtin_constant_p
(see the entry of 10/31/06).  However, previously, the operand to such calls
was parsed as "unevaluated operands" (i.e., like sizeof operands), which caused
lowering to abort in some cases.  For example:

  struct A { A(); };
  int main() { return __builtin_constant_p(new A); }
    // Previously could abort in lower_init.c in some configurations.

This is now fixed: Such operands are parsed as normal function call operands if
there is a possibility that they will result in an actual call.


9/14/20  [EDGcpfe/23370]
Microsoft compatibility: C mode

A change has been made to more closely emulate the /std:c11 and /std:c17
command-line options in Microsoft emulation mode (when microsoft_version >=
1928).  In particular, the __STDC_VERSION__, __STDC_NO_ATOMICS__,
__STDC_NO_COMPLEX__, __STDC_NO_THREADS__, and __STDC_NO_VLA__ macros are now
set properly.


9/14/20  [EDGcpfe/23310]
Issues with promotion of constants during lowering

A couple of issues were fixed when lowering constants in a function scope
that are promoted to the file scope during lowering.  Those issues had
resulted in a segfault (in mangled_variable_name_with_possible_qualification)
or in IL write-read assertion failures and are now fixed.  For example,
with --gnu_version=70300:

  void (*fptr)(void) = [](void){};
  struct A {
    void f() {
      static void *b[] = { &&L };
      const char *x = __FUNCTION__;
    L:;
    }
  };


9/13/20  [EDGcpfe/23342]
C++-generating back end: lambda that captures and uses *this

The front end previously aborted with a failed assertion (in gen_expr) when
generating code for a lambda that captures and then uses *this.  This is
now fixed.  For example, with --c++17:

  struct S {
    void foo(){
      [*this]() { S x = *this; };   // Previously aborted
    }
  };


9/13/20  [EDGcpfe/23264]
C++-generating back end, Microsoft compatibility: parenthesized decltype
operands

Recent versions of MSVC have a bug that can result in spurious errors when
a dependent operand of a decltype operator is enclosed in redundant
parentheses.  The code previously generated by the front end could trigger
this bug, but it has now been changed to suppress such parentheses when
msvc_is_generated_code_target is TRUE.  For example, with --microsoft
--parse_templates:

  template<typename T> T f();
  template<typename, typename = void> struct B { using type = int; };
  template <typename T> struct B<T, decltype(f<typename T::X>().g())> {
    using type = int;
  };
  using BI = B<int>::type;

The partial specialization of B was previously generated as

  struct B<T, decltype(((f<typename T::X>().g())))>

which triggered the MSVC bug.


9/13/20  [EDGcpfe/23379]
Possible double substitution of type with copy_type_with_substitution

In some cases, a type such as A<T>::B<T> could result in the substitution
of the B<T> part happening more than once.  We are not aware of any ill
effects of this in the standard EDG source, but we have had reports of
issues caused in customer modifications of the front end.  In addition,
the extra substitution is wasted time and so is best eliminated.  This
change has now been made.


9/12/20  [EDGcpfe/23024]
Internal error with characters in function name not in current code page

In configurations in which NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is
TRUE, the front end could abort in Microsoft mode with an internal error
("assoc_source_line_modif: bad address") when a source file with a Unicode
encoding defines a function whose name contains a character that is not
representable in the current code page and that function contains
__FUNCTION__ or similar constructs.  This is now fixed.


9/11/20  [EDGcpfe/22429,EDGcpfe/23337]
Spurious failure substituting parenthesized new-initializer

The front end previously sometimes failed to substitute a parenthesized
new-initializer when the allocated type is not a class type and the
parenthesized expression is a pack expansion.  For example:

  inline void *operator new(__EDG_SIZE_TYPE__, void *p) noexcept { return p; }
  template<typename...> using void_t = void;
  template<typename T> T makeT() noexcept;
  template<typename T, typename... Args>
  auto place_at(T *p, Args &&...args)
    -> decltype(::new ((void*)p) T(args...));
       // The substitution of args... was previously not handled correctly.
  template<typename Void, typename, typename...> bool can_place_at = false;
  template<typename T, typename... Args>
  bool can_place_at<void_t<decltype(place_at(makeT<T*>(), makeT<Args>()...))>,
                    T, Args...> = true;
  struct X {};
  auto r = can_place_at<void, int, X>;
      // Previously triggered a spurious error above.  Now okay.

That problem is now fixed.


9/11/20  [EDGcpfe/23351]
Incorrect parsing of __is_constructible with variadic pack expansion

In some complex template-based code where __is_constructible was invoked with
a trailing pack expansion (something like "__is_constructible(T, As...)"), the
front end could erroneously complain about a missing right parenthesis.  That
problem is now fixed.


9/11/20  [EDGcpfe/23376]
Multi-level substitution of concept-ids

Previously, when performing substitution of dependent concept-ids, the front
end only permitted substitutions with non-dependent arguments.  That prevented
some cases where multi-level substitutions are required (i.e., first the
concept-id is substituted with a set of template arguments that are still
dependent, and then the result of that substitution is substituted again).
That is now fixed.


9/10/20  [EDGcpfe/22431]
C++-generating back end: explicit specializations of member function templates
used in their class

In configurations in which both
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS are TRUE, the
C++-generating back end could put out an explicit specialization for a
member function template before the explicit specialization of the class
template of which it is a member.  This is now fixed.  For example, with
--g++ --c++14:

  template<typename T> struct A {
    static T x();
    template<typename U> static decltype(x()) y(int);
    static const bool z = sizeof(y<T>(0));
  };
  template<typename T> struct B {
    bool v = A<int>::z;
  };

In the generated code for this example, the explicit specialization for
A<int>::y<int>(int) previously preceded the explicit specialization for
A<int>, resulting in errors when compiling the generated code.  There is no
point at which an explicit specialization of the member function template
could validly appear, since it would either precede the explicit
specialization of its parent class or follow its use inside the class, so
such explicit specializations are now suppressed.

In addition, in C++-generating back end configurations in which
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is FALSE but
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, similar
examples could result in code that triggers a g++ bug that prevents
matching an explicit specialization with its template.  The C++-generating
back end has now been changed to suppress such explicit specializations
when gcc_is_generated_code_target is TRUE.  For example, with --g++:

  template <typename T> T v;
  template <typename T> class C {
    template <typename U> static int f(U);
    template <typename V> static decltype(f(v<V>)) g(int);
    static const bool b = sizeof(g<T>(0));
  };
  template <typename> struct S {
    bool v = C<int>::b;
  };

The generated code for this example previously contained the explicit
specialization

  template<> template<> int C<int>::g<int>(int);

which triggered the g++ bug.


9/9/20   [EDGcpfe/23243]
Multiple translation units: Abort with a function using-declaration

When compiling multiple translation units where two TUs contain the same
class template which inherits from another class template, the front end could
have an assertion failure (in equiv_base_using_decls) when in Microsoft
compatibility mode if a using-declaration named a function in the base class.
For example, if both TUs contain:

  template <typename T> class B {
    void operator-();
  };
  template <typename T> class D : public B<T> {
    using B<T>::operator-; // Assertion failure triggered here
  };

This is now fixed.


9/9/20   [EDGcpfe/23367]
Deducing a boolean template parameter from a noexcept property

In Clang and GNU C++ modes, the front end supports the deduction of a boolean
template parameter based on whether a function type is "noexcept" or not: See
the entry for EDGcpfe/18317.  However, the emulation of that extension had a
bug that caused "noexcept" (with no explicitly-specified value) to be treated
as "noexcept(false)" for deduction purposes, when it really should be treated
as "noexcept(true)".  For example (in GNU C++17 mode):

  template<typename R, typename ...Ps, bool N>
    constexpr bool is_noexcept(R(&)(Ps...) noexcept(N)) { return N; }
  void g() noexcept;
  static_assert(is_noexcept(g));  // Previously failed.  Now okay.

That problem is now fixed.


9/9/20   [EDGcpfe/23355]
Missing diagnostic on invalid value-initializing cast

Consider:

  struct S { union { int const ic; } u; };
  S x = S();  // Previously accepted.  Now an error.

Previously, the front end failed to determine that S cannot be
value-initialized (because of the const member in the nested union) and
therefore it erroneously accepted the example above.  Now an error is issued.


9/8/20   [EDGcpfe/23360]
C++-generating back end: forward references to opaque enumerators

In cases where an opaque enumeration is declared and then later defined,
the C++-generating back end could put out values of the enumeration as
enumerators before those enumerators are defined.  This is now fixed.  For
example, with --c++11:

  enum E : int;
  E x{};  // Previously generated as "x{ zero }", now as "x{ (E)0 }"
  enum E : int { zero };


9/4/20   [EDGcpfe/19987,EDGcpfe/23358]
Overloading static and nonstatic member function templates

The standard does not permit overloading static and nonstatic member function
templates with identical parameter types, trailing requires-clauses, and
template parameterization.  However, Clang and GCC appear to enforce that rule
only if the return types are also identical.  The front end now emulates that
behavior in GNU and Clang modes.  For example:

  struct S {
    template<typename T> void f(int);
    template<typename T> static int f(int);
      // Previously always an error.  Now accepted in GNU and Clang modes.
  };


9/4/20   [EDGcpfe/22952,EDGcpfe/23348]
Clang compatibility: Conversion to "ext_vector_type" types

In Clang mode, any arithmetic or enumeration type can now be converted to a
"ext_vector_type" type.  For example:

  typedef float VF4 __attribute__((ext_vector_type(4)));
  VF4 vec = (VF4)1;  // Now accepted in Clang modes.


9/4/20   [EDGcpfe/23312]
Member selections in member templates of nested classes

Consider (in a C++ mode that parses function templates in their generic form;
e.g., default C++11 mode):

  template<typename T> struct S {
    struct N {
      template<typename U> static void h() {
        S<T>::n.f<U>();  // Previously a spurious error.  Now okay.
      }
      template<typename> void f();
    };
    static N n;
  };

Previously, the front end treated the "<" following "S<T>::n.f" as a "less
than" operator, which in turn resulted in spurious errors.  That is now fixed:
the "<" is now treated as the beginning of a template argument list.


9/4/20   [EDGcpfe/22940]
Microsoft compatibility: builtins for coroutines

When microsoft_version >= 1928, builtin signatures are now available for
__builtin_coro_destroy, __builtin_coro_done, __builtin_coro_noop,
__builtin_coro_promise, and __builtin_coro_resume.


9/3/20   [EDGcpfe/23352,EDGcpfe/20915]
Modules: Disable modules by default in C++20 mode

C++20 modules as a feature are not yet complete.  However, due to an oversight,
these were enabled by default (in C++20 mode) in version 6.1.  A configuration
macro "DEFAULT_MODULES_ENABLED" has been added to control this, and (currently)
defaults to FALSE.  Once the feature is complete, modules will be enabled by
default in C++20 mode.


9/2/20   [EDGcpfe/23346,EDGcpfe/20915,EDGcpfe/23278]
Modules: Spurious error when "module" used as an identifier

When modules are enabled, the front end was previously treating "module" as a
non-context-sensitive keyword.  This caused spurious errors when "module" is
used as an identifier.  For example:

  int module;

This is now fixed.


9/2/20   [EDGcpfe/23345]
C++-generating back end: braced default member initializers and casts

In cases where a default member initializer is specified using the braced
form and the initializer expression is an explicit cast invoking a
constructor, the C++-generating back end failed to put out the enclosing
braces, resulting in incorrect code.  This is now fixed.  For example:

  struct A { A(); };
  struct B {
    A a{ A() };  // Previously generated as "A aA{};"
  };


9/2/20   [EDGcpfe/20414,EDGcpfe/23347]
Microsoft/GNU compatibility: Aggregate initializers and explicit constructors

Consider:

  struct S { explicit S(int = 0) {} };
  struct X { S s; };
  X x = {};  // Normally an error, but now okay in Microsoft mode.

In standard C++ this is an error, because the default aggregate initializer
for x.s is copy-initialized but the default constructor of S is explicit (and
explicit constructors are normally not eligible for copy-initialization).
It appears, however, that the Microsoft and GCC compilers accept such cases
and the front end now emulates that behavior in Microsoft and GNU C++ modes.


9/1/20   [EDGcpfe/23259,EDGcpfe/23343]
Function template ordering and C++20 constraints

Consider (in C++20 mode):

  struct S {
    template<typename ... Ts>
      constexpr int operator()(Ts &&...) requires true { return 1; }
    template<typename T1, typename T2, typename T3>
      constexpr int operator()(T1&&, T2&&, T3&&) requires true { return 2; }
  };
  static_assert(S{}(1, 2, 3) == 2);  // Previously ambiguous.  Now okay.

Previously, this elicited an ambiguity error because the constraints on the two
candidates are not equivalent (they're both "true", but distinct "true" tokens
are not equivalent constraints).  Now, the second candidate is selected because
it is more specialized based on traditional deduction rules and that takes
precedence over constraint ordering.


8/31/20  [EDGcpfe/23330]
Spurious errors when preloading builtins in some modes

Using the --set_flag preload_builtin_functions command-line option had caused
spurious errors when the char8_t type was not enabled (for example with
--microsoft_version=1922).  Now fixed.


8/31/20  [EDGcpfe/23259,EDGcpfe/23336]
Template constraints on conversion function templates

Consider:

  struct X {
    template<typename T> requires (sizeof(T) == 1)
      operator T();
    template<typename T>
      operator T();
  } x;
  int r = x;  // Previously a constraint-failure error.  Now okay.

Previously, overload resolution did not treat the constraint failure of the
deduced X::operator int() as a deduction failure (SFINAE), and thus an error
was issued on the first conversion function template candidate.  Now, the first
candidate is discarded and overload resolution successfully selects the second
candidate.


8/31/20  [EDGcpfe/23322]
Substitution of variadic requires-expressions

The front end did not always correctly substitute requires-expressions with
a parameter list containing a parameter pack.  In some complex cases, this
resulted in spurious errors.  That problem is now fixed.


8/31/20  [EDGcpfe/23322]
Template constraint checking performance improvement

The front end now caches certain aspects of template constraint checking for
improved performance (in some complex but realistic cases, front end processing
time is now reduced by two orders of magnitude).


8/31/20  [EDGcpfe/23222]
Memory corruption in interpreter for error-type IL

The interpreter (particularly, function mark_whole_subobject_uninitialized)
could corrupt memory when given IL with error type nodes.  For example,
the following code containing multiple errors resulted in an abort due to
such memory corruption:

  template<typename T> concept C = (sizeof(T) == sizeof(int));
  struct S {
    C T;  // Causes S to contain a member with error type.
  } s = { .x = s.~S() };  // Previously caused memory corruption.
  int r = s.x;

That is now fixed.


8/30/20  [EDGcpfe/22970,EDGcpfe/23074]
C++-generating back end: qualified names in explicit instantiation directives

In configurations in which RECORD_FORM_OF_NAME_REFERENCE is TRUE, the
C++-generating back end could omit necessary name qualifiers for a template
instance in an explicit instantiation directive.  This is now fixed.  For
example, with --g++:

  template<typename T> struct S {
    static const int i = -1;
  };
  template const int S<int>::i;  // Previously omitted "S<int>::"


8/27/20  [EDGcpfe/23319]
Microsoft compatibility: coroutines

With --microsoft_version=1928 and --ms_cpp20 or --ms_c++latest, coroutines are
now enabled (providing that COROUTINE_ENABLING_POSSIBLE is TRUE).  Also, a new
command-line option, --ms_await, is added to emulate the /await Visual Studio
command-line option.

When --ms_await is specified, or coroutines are enabled and microsoft_version
is between 1900 and 1928, the original (pre-C++20) coroutine behavior is
preserved (meaning that the _RESUMABLE_FUNCTIONS_SUPPORTED macro and
__cpp_coroutines feature test macro are defined).  This matches the Microsoft
Visual Studio behavior.


8/27/20  [EDGcpfe/23320]
Incorrect feature test macro name for coroutines

The feature test macro for coroutines is "__cpp_impl_coroutine" and was
mistakenly named "__cpp_impl_coroutines".  Now fixed.


8/26/20  [EDGcpfe/22161,EDGcpfe/22456]
Coroutines: Abort when awaiting rvalue references

The front end would abort in make_expr_reusable_copy when awaiting on an rvalue
reference (whether directly or via await transformations).  For example:

  #include <coroutine>
  struct A {
    struct promise_type
    {
      A get_return_object() { return{}; }
      auto initial_suspend() { return std::suspend_always{}; }
      auto final_suspend() noexcept { return std::suspend_always{}; }
      void unhandled_exception() noexcept {}
      void return_void();
      A&& await_transform(A&& expression) { return (A&&)expression; }
    };
    ~A();
    bool await_ready() const { return false; }
    void await_suspend(std::coroutine_handle<> handle) const {}
    A await_resume() const { return {}; }
  };
  A f() {
    co_await A{};  // Previously aborted due to the "await_transform" call
  }

This is now fixed.


8/26/20  [EDGcpfe/21677,EDGcpfe/23263]
Constexpr interpreter aborts when copying capture of "this"

In some relatively complex situations, the constexpr interpreter could abort
(dereferencing a null pointer) when evaluating the copy of a closure for a
lambda that captures a "this" pointer.  For example:

  template<typename T> struct S {
    S(S const&) = default;
    S(S&) = default;
  };
  template<typename F> void g(F) {}
  struct X {
    template<typename F> void eval(F f){
      g(f);
    }
  };
  struct Z {
    void f(S<int> p) {
      x.eval([this, p]{});  // Previously triggered an abort.
    }
    X x;
  };

That problem is now fixed.


8/26/20  [EDGcpfe/23261,EDGcpfe/23276]
C-mode type of conditional operator with null pointer constant

Version 6.1 of the front end introduced a regression in C mode (due to the
extensive changes for handling C++20 concepts) causing some null pointer
constants not to be recognized as such.  For example, in C11 mode:

  int main() {
    return _Generic(1 ? (void*)(2-2) : (int*)0, int*: 1, void*: 0);
  }

Normally, the type of the unevaluated conditional operator should be int*
because "(void*)(2-2)" is a null pointer constant and thus that program
returns 1.  However, version 6.1 returned 0 because it failed to recognize
that "(void*)(2-2)" is a null pointer constant in unevaluated contexts.  That
is now fixed.


8/26/20  [EDGcpfe/23286]
Abort on static data member template involving concept-id

Consider (in C++20 mode):

  namespace N {
    template<typename, typename> concept C = true;
  }
  struct S {
    template<typename T, typename U>
      static constexpr bool B = N::C<T, U>;  // Previously triggered an
  };                                         // internal error.  Now okay.

Previously, this aborted with an internal error in copy_tokens_from_cache
(lexical.c).  That is now fixed.


8/26/20  [EDGcpfe/23288]
Spurious ambiguity among partial specializations involving constraints

Consider (in C++20 mode):

  template<typename T> concept Has_minus =
                         requires(T const &a, T const &b) { { a-b }; };
  template<typename> struct X {};
  template<typename T> struct X<T const> : X<T> {};
  template<typename T> requires Has_minus<T> struct X<T> {};
  X<int *const> x;  // Previously an error.  Now okay.

Previously, the front end erroneously reported an ambiguity between the two
partial specializations of X when considering which one to instantiate for
X<int *const>.  Now, the one for X<T const> is preferred.


8/25/20  [EDGcpfe/23301]
Incorrect addition of Windows drive letter to relative paths

The normalize_dir_name function adds the windows drive letter to absolute paths
if it's missing.  However, when is_partial_file_name is set to TRUE, it was
also incorrectly adding the windows drive letter to relative paths.  This is
now fixed.


8/25/20  [EDGcpfe/23292]
Incorrect is_local_to_function flag for variable template instance

The inheriting constructor changes in version 6.1 could result in the
creation of a variable template instance with its is_local_to_function flag
incorrectly set to TRUE.  Now fixed.  It was theoretically possible for this
to occur in other cases not involving inheriting constructors both in 6.1
and in prior versions, but this has not been observed.  This issue could
result in several different kinds of internal errors, depending on the
configuration, including ones in enclosing_routine_for_local_type,
get_scope_for_list, and add_discriminator.

  namespace N {
    template <bool B, class T = void> struct A { using type = T; };
    template <class T> inline constexpr bool V = false;
    struct D {
      template <class T, typename A<V<T>, int>::type = 0> D(T&&) {}
    };
  }
  int main() {
    struct my_D : N::D {
      using N::D::D;
    };
    my_D{1};
  }


8/24/20  [EDGcpfe/23291]
Wrong delete routine selected when using template class

In cases where a pointer to a template class is being deleted and that
class has not been previously instantiated, as a result of the changes for
EDGcpfe/20036 (in 6.1), the global delete routine had been erroneously
selected.  This example now elicits an error (with --c++11):

  template<typename T> struct A {
    void operator delete(void*) = delete;
  };
  void f(A<int> *p) {
    delete p;     // Should get an error because selected operator delete
                  // is deleted.
  }


8/24/20  [EDGcpfe/23268]
Assertion failed in mangled_encoding_for_function_type

In some configurations, an assertion failure could occur (in
mangled_encoding_for_function_type) when a lambda appears in an initializer
of a selection statement (see the Changes entry for EDGcpfe/17414).
For example, with --c++20:

  consteval int f(int n) {
    switch(int x = [](){return 10;}(); n) {
      default:
        return x;
    }
  }
  int x = f(0);


8/19/20  [EDGcpfe/23274]
GNU C++ compatibility: non-dependent functional notation casts in templates

A g++ bug emulation (see EDGcpfe/17306 from 6/15/16) could cause partial
specialization to fail when a template argument used an expression with
a non-dependent functional notation cast as part of a template argument
in a template declaration context.  Now fixed.

  template <class T> struct X {
    typedef int Y;
  };
  template <class T, class U> struct A;
  template <class T> struct A<T, X<decltype(bool())>::Y> {};
  A<int, int> a;


8/19/20  [EDGcpfe/23279]
Spurious parse error building with VS2015

When building the front end using Visual Studio 2015 with USE_EDG_NAMESPACE set
to TRUE, a spurious parse error (C2888) was emitted, stating that
a_template_arg member symbols could not be defined within namespace 'edg'.
This is now fixed.


8/18/20  [EDGcpfe/22807,EDGcpfe/22956,EDGcpfe/23262]
Performance issue with is_pod_class

In some cases the computation in is_pod_class was fairly expensive, and the
result was re-computed multiple times for the same class.  This caused
significant increases in compilation time, including at times the appearance
of hanging.  This is now fixed (by caching the result).


8/14/20  [EDGcpfe/23252]
Regression in interpretation of certain compound assignments

The changes for EDGcpfe/22546 (in version 6.1; see the entry of 4/30/20)
introduced a new bug that caused the erroneous constant-evaluation of
certain mixed-type expressions involving a -=, *=, or /= operator.  For
example:

  constexpr float f(float x) { return x -= 0.0; }
  static_assert(f(2.0f) == 2.0f, "Unexpected");  // Previously failed.
                                                 // Now okay.

That is now fixed.


8/13/20  [EDGcpfe/23247]
unexpected_condition in mangled_function_base_name

As a result of the changes for EDGcpfe/17687 in 6.1, configurations that do
name mangling but not lowering and use the IA-64 ABI would encounter an
unexpected_condition in mangled_function_base_name on any use of a C++17
inheriting constructor, e.g. (with --c++17):

  struct A {
      A(int);
  };
  struct B : A {
    using A::A;
  };


8/13/20  [EDGcpfe/23244]
Assertion failure in remap_secondary_pointer_for_rewrite

As a result of the changes for EDGcpfe/22516 in 6.1, the aliasing of "strlen"
and "abs" to their __builtin counterparts was broken in certain cases.  That
led to an assertion failure in remap_secondary_pointer_for_rewrite in
multi-translation unit mode with a case like this (with --c++11 --clang):

  // File 1:
  typedef decltype(sizeof(0)) size_t;
  size_t length(const char* __s) { return __builtin_strlen(__s); }
  extern "C" size_t strlen (const char *__s);

  // File 2:
  typedef decltype(sizeof(0)) size_t;
  extern "C" size_t strlen (const char *__s);


8/13/20  [EDGcpfe/23248]
Segfault in scan_function_call

As a result of the changes for EDGcpfe/22516 in 6.1, the following code
had resulted in dereferencing a NULL pointer and is now fixed.  With
--c++17 --clang:

  namespace std {
    enum class align_val_t : decltype(sizeof(0));
  }
  struct A {
    template <class T> void f(void *p, T t) {
      __builtin_operator_delete(p, t);
    }
    void c() {
      f(0, std::align_val_t());
    }
  };


8/12/20  [EDGcpfe/23214]
GNU C compatibility: Folding of arithmetic on void* pointers

The front end previously treated folding arithmetic on void* pointers (which
is accepted in GNU C modes) as if such pointers point to zero-length objects.
Now it treats it them as pointing to byte arrays (i.e., objects of length
one).  For example (in GNU C mode):

  unsigned char buf[100];
  int g() {
    return buf == (void*)buf+1;  // Previously returned 1.
  }                              // Now returns 0.


8/12/20  [EDGcpfe/21277,EDGcpfe/23238]
GNU C++17 compatibility: strlen and abs folding and noexcept

In GNU C and C++ modes, the front end treats certain declarations of strlen
and abs as equivalent to __builtin_strlen and __builtin_abs, respectively
(see, e.g., the entry for EDGcpfe/10179).  One consequence of that is that
calls to such functions can be evaluated at compile time.  Consider:

  extern "C" unsigned long strlen(char const*) noexcept;
  constexpr auto r = strlen("");

Previously, this was accepted in GNU C++11 and C++14 modes, but not in GNU
C++17 mode because in the latter mode the "noexcept" specifier made the
declaration incompatible with the implicit declaration of __builtin_strlen.
That is now fixed: Top-level noexcept specifiers are now ignored for the
purposes of linking strlen and abs to the corresponding built-in entities.


8/12/20  [EDGcpfe/22822]
Narrowing conversions

Since C++11, certain implicit conversions are considered "narrowing" and such
conversions are invalid in certain contexts, including when considering
implicit conversions for nontype template arguments.  The front end had two
bugs in this area:
  1) A conversion from an integer constant to bool is non-narrowing only
     if the constant value is 0 or 1, but the front end previously allowed
     any constant value representable in the underlying type (e.g., unsigned
     char).
  2) Narrowing was not checked for certain template argument substitutions
     during SFINAE checking.

Both of these problems are now fixed.


8/11/20  [EDGcpfe/23232]
Spurious error on use of type constraint using concept with default argument

The front end previously issued a spurious error for the following case:

  template<typename, typename = int> concept C = true;
  C auto x = 42;  // Previously an error.  Now okay.

because it ignored the default template argument and therefore expected an
explicit argument on the use of C as a type constraint.  That is now fixed.


8/11/20  [EDGcpfe/23235]
Substitution failure in concept-id

Consider the following C++20 example:

  template<bool B> struct L { using type = long; };
  template<typename> concept A = true;
  template<typename T> concept hasX = A<typename T::X>;
  template<typename T> typename L<hasX<T>>::type f(T) { return {}; }
  auto r = f((int*)0);  // Previously an error.  Now okay.

Previously, this resulted in an error because the substitution failure of
typename T::X did not just cause hasX<T> (for T = int*) to be evaluated to
false, but instead it was considered a SFINAE failure for the substitution
of hasX<T>.  That is now fixed. 


8/10/20  [EDGcpfe/23236]
C++-generating back end: braced-form casts to fundamental types

Given a braced-form explicit cast to a fundamental type in the original
source, the C++-generating back end put out a C-style cast instead.  This
transformation is usually harmless, but some examples could result in
uncompilable generated code.  This is now fixed, and the original source
form of such casts is preserved.  For example, with --c++14 in a
configuration in which template definitions are generated from the
prototype instantiation IL:

  struct c {
    int i;
    template<typename... Args> void f(Args&&... args) {
      i = int{args...};  // Previously generated as (int)(args...)
    }
  };


8/10/20  [EDGcpfe/23237]
Constexpr specifier on function template lost after substitution failure

Consider:

  void e();
  template<typename T> concept E = requires(T &&p) { e(p); };
  template<typename T> constexpr T f() {
    (void)E<T>;
    return T{};
  }
  static_assert(f<int>() == 0);  // Previously an error because f<int>()
                                 // was not considered a call to a constexpr
                                 // function.

The evaluation of E<T> for T = int requires the substitution of the call e(p)
during the instantiation of f<int>().  This substitution fails because there
are too many arguments for the call to e().  Previously, this caused the front
end to make the enclosing function (f<int>()) non-constexpr, and that in turn
caused the static_assert declaration to be rejected.  That is now fixed.


8/10/20  [EDGcpfe/22541]
noexcept-specifier incorrectly treated as SFINAE context in C++17 mode

An exception specification (i.e., a noexcept-specifier) was incorrectly
treated as a SFINAE context in C++17 mode.  Formerly this would typically
result in an overload resolution failure (i.e., there would be no matching
function) when it should have resulted in  an error on the instantiation
of the exception specification.  However, it could also have resulted in
incorrect overload resolution (i.e., the wrong function being selected)
in some cases.  Now fixed.

  template <typename T> int f() noexcept(T(0));
  template <typename T> struct A {
    using type = decltype(f<T>());
  };
  A<A<int>>::type at;


8/10/20  [EDGcpfe/23215]
More efficient mangling in IA-64 ABI configurations

The IA-64 ABI specifies how to mangle names of functions and variables, and
the manglings for types within those names, but generally does not require
type names themselves to be mangled.  The front end, when lowering is enabled
or when MANGLE_ALL_NAMES is TRUE, opts to generate mangled names for these
types largely because it creates unique names that might otherwise conflict
when using the C-generating back end to generate compilable C code.
For example the two classes below have the same name in C++, but are unique
types and cannot both be named "A" in generated C (as they would conflict):

  namespace N1 { class A { int x;  }; }
  namespace N2 { class A { char c; }; }

Such mangling is also useful for customers who require a unique string
representation for an object that can be demangled to return the original
declaration of the object.  Mangled names are also useful in that they
remain constant across different compilations.

A change has been made to offer a more efficient mapping from a type to a
unique identifier (basically by creating a string that consists of the
hexadecimal address of the type's IL entry preceded by "__t").  That creates a
unique string that can be used in generated C code, but that string may change
from one compilation to another and cannot be demangled.

This change saves about 5% of the total time of running a recent version of
the Boost tests in a C-generating configuration.

This new behavior is controlled by the new
ONLY_MANGLE_TYPES_NEEDED_FOR_EXTERNAL_NAMES configuration macro.  By default,
it is FALSE (to preserve the old behavior).  This option is not available in
the Cfront ABI.


8/9/20   [EDGcpfe/23189]
C++-generating back end, GNU C++ compatibility: deleted member functions and
the constexpr keyword

The C++-generating back end previously could put out the definition of a
deleted member function using the constexpr keyword.  This construct could
cause problems when the generated code was compiled by older versions of
g++ if the class of which the function is a member is not a literal type.
This is now fixed, and deleted member functions are no longer declared
constexpr.  For example, with --c++11:

  class A {
    A();
    void operator=(const A &) = delete;  // Previously declared constexpr
  };


8/7/20   [EDGcpfe/23223]
Clang compatibility: __builtin_launder

The built-in pseudo-function "__builtin_launder" is now enabled in C++ Clang
mode for clang_version >= 80000.  It was previously enabled in that mode but
its signature was incorrect, causing a spurious error in this example
(with --clang_version 80000 --c++17):

  template<class T> constexpr T* __launder(T* t) {
    return __builtin_launder(t);
  }
  void f(int* a) {
    __launder(a);
  }


8/7/20   [EDGcpfe/23225]
Support for UTF-8 character literals

Support for UTF-8 character literals (see EDGcpfe/16385) requires support
for other u-literals.  However, it was possible, through configuration
and/or command-line options, to attempt to enable UTF-8 character literals
while other u-literals were disabled, resulting in a failure to recognize
occurrences of the "u8" encoding prefix.  This is now fixed: conflicting
command-line options are diagnosed, and specifying --utf8_char_literals
implicitly enables support for other u-literals.


8/7/20   [EDGcpfe/22824]
Spurious errors due to invalid handling of variable template substitutions

The front end previously did not correctly handle default template arguments
of variable templates when substituting such templates for SFINAE-checking
purposes.  This could result in spurious errors.  That problem is now fixed.


8/7/20   [EDGcpfe/19915,EDGcpfe/22388]
Template template parameter that is a pack expansion

The front end failed to properly handle a template template parameter that is
itself a pack expansion.  Now fixed.

  template <class...T> struct A {
    template <template <T> class... TTP, class U> struct B { };
  };
  template <int I> struct C { };
  template <char C> struct D { };
  A<int,char>::B<C, D, int> a;


8/6/20   [EDGcpfe/23217]
C++-generating back end: Incorrectly-suppressed explicit specializations

In C++-generating back end configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, a
generated explicit specialization of a class template could be incorrectly
suppressed if the declaration of a member of that specialization resulted
in the instantiation of a class template that is not a member of the class
template being specialized.  This omission occurred only in non-Microsoft
modes and was the result of the changes for EDGcpfe/22273 (in version 6.1),
which inadvertently considered non-member templates as well as member
templates.  This is now fixed.  For example, with --g++:

  template<typename T> struct A { };
  template<typename T> struct B {
    struct C { };
    A<C> at;
  };
  B<char> bc;

Previously the generated code did not contain an explicit specialization
for B<char>; now it does.


8/6/20   [EDGcpfe/23220]
Remove a_uintptr and change return type of unique_id_for_il_pointer

A change has been made to replace uses of a_uintptr with its underlying
type, uintptr_t.  Additionally, this type is now used as type of the
returned value from the unique_id_for_il_pointer macro (to better accommodate
configurations where a pointer is larger than an unsigned long type).


8/5/20   [EDGcpfe/23201]
Matching requires-clauses for out-of-class member template definitions

The front end previously failed to match requires-clauses for out-of-class
member template definitions.  For example:

  template<typename> concept C = true;
  template<typename> concept D = true;
  struct S {
    template<typename T> requires C<T> && D<T> int f(T);
  };
  template<typename T> requires C<T> int S::f(T) {  // Previously accepted.
    return 42;                                      // Now an error.
  }

That is now fixed.


8/5/20   [EDGcpfe/23200]
Type constraints allocated in wrong memory region

In some cases, type constraints were allocated in function memory when they
should have been allocated in file scope memory (since they are pointed to by
a type, allocated in file scope memory).  This could lead to aborts.  For
example:

  template<typename> concept C = true;
  constexpr C auto x = [](C auto x) {
                         C auto y = x;  // Type constraint allocated in wrong
                         return y;      // memory region.
                       };
  int y[x(42)];

In this example, the enk_concept_id node representing the type constraint C on
the type of y was allocated in function scope memory.  That is now fixed.


8/4/20   [EDGcpfe/23192]
Erroneous handling of disjunction in constraints

The front end previously did not correctly handle disjunctions in constraints
(treating them as atomic constraints for the purposes of subsumption checking).
For example:

  template<typename T> concept C = (sizeof(T) >= 0);
  template<typename T> concept D = (sizeof(T) <= 64);
  template<typename T> requires C<T> || D<T> constexpr int f(T) {return 1;}
  template<typename T> requires C<T> constexpr int f(T) {return 2;}
  static_assert(f(42)==2);  // Previously ambiguous.  Now okay.

That is now fixed.


8/4/20   [EDGcpfe/23177]
GNU compatibility: GNU-style attributes on an alias declaration

Previously the presence of GNU-style attributes on an alias declaration
had caused spurious errors; now fixed.  For example (with --gnu_version 90000):

  struct A {
    using T __attribute__((deprecated)) = char;
  };


8/4/20   [EDGcpfe/23115]
Microsoft compatibility: Add --ms_c17 command-line option

In preparation for emulating Visual Studio's /std:c17 command-line option,
the --ms_c17 command-line option has been added to the front end.  It functions
the same as the --ms_c11 command-line option currently.


8/4/20   [EDGcpfe/23188]
Assertion failure: mangled_operator_name: bad kind

In configurations that use function multiversioning, the use of a "target"
attribute on an operator member function elicits a discretionary error, but 
had also elicited an assertion failure during mangling (in configurations
that do mangling).  For example, with --clang_version 60000 --diag_suppress
target_on_special_function:

  struct S {
    __attribute__ ((target("avx2"))) void operator+=(const S&) { }
  };


8/4/20   [EDGcpfe/23198]
Clang compatibility: function multiversioning with clang_version < 30700

In configurations that use clang compatibility with clang_version < 30700,
that also have USE_X86_FUNCTION_MULTIVERSIONING and DO_IL_LOWERING,
using the function multiversioning feature (i.e., with "target" attributes)
had resulted in an assertion failure in load_matching_builtin_function.
Now fixed.  For example (with --clang_version 30500):

  __attribute__ ((target("avx2"))) void f();


8/4/20   [EDGcpfe/23122]
Incorrect code generated for optimizable class prvalue "?" operation

In configurations that use lowering, incorrect code had been generated in
some cases where the front end has identified an optimizable class prvalue
"?" operation (see do_class_rvalue_question_optimization).  In the example
below, the incorrect code had caused a.x to be uninitialized, resulting in
undefined behavior (with --c++11):

  struct A {
    int x;
  };
  A g(int x) {
    return {x};
  }
  int f(bool b) {
    constexpr const A z{0};
    A a = b ? g(-1) : z;
    return a.x;
  }
  int main() {
    return f(false);
  }


7/30/20  [EDGcpfe/22795]
C++-generating back end: partial suppressions of generated explicit
specializations

In C++-generating back end configurations in which
TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, under some
circumstances a generated explicit specialization of a class template could
be put out missing some members that are present in the class template
definition.  This situation occurred in cases where the declaration and the
definition of the explicit specialization are separated in the generated
code and some member of the class refers to a type that is not yet defined
at the point of the explicit specialization declaration but is defined at
the point of the explicit specialization definition.  The result of this
was that the declaration of the explicit specialization and its members
were suppressed but the definition of the explicit specialization was not.
This is now fixed, with suppression of the declaration unconditionally
resulting in the suppression of the definition as well.


7/30/20  [EDGcpfe/22965]
Abort in interpreter on template-dependent use of certain built-in functions

Consider:

  template<typename T> constexpr int f(T p) {
    int const r = __builtin_signbit(p);  // Previously aborted.  Now okay.
    return r;
  }

This previous aborted with an internal error in do_constexpr_builtin_function.
A number of other built-in functions with floating-point parameters were
similarly affected.  That is now fixed.


7/30/20  [EDGcpfe/7898,EDGcpfe/7979,EDGcpfe/15641,EDGcpfe/18706]
GNU compatibility: __INCLUDE_LEVEL__ built-in macro

The front end now supports (in all modes) the GNU __INCLUDE_LEVEL__ builtin
macro, which expands to the number of #include directives currently active
at the point at which the macro appears.  For example, if source file a.c
includes file b.h, which in turn includes file c.h, a use of
__INCLUDE_LEVEL__ in c.h will expand to the integer value 2.


7/29/20  [EDGcpfe/23185]
Spurious warning on operator function only used in template instances

Consider:

  struct S {};
  static inline bool operator!=(S,S) { return true; }
  template<typename T> void g(T t) { t != t; }
  int main() {
    g(S());
  }

Previously, in modes that perform a prototype instantiation of g(T) but do not
eagerly instantiate all used instances (i.e., not -tused or -tall modes), the
front end spuriously warned about operator!= (which has internal linkage) being
defined but not used (this problem was specific to operator functions; ordinary
functions with internal linkage did not elicit such warnings).  That is now
fixed.


7/29/20  [EDGcpfe/20033,EDGcpfe/20276,EDGcpfe/22245]
C++20: Nontype template parameters of class type or floating-point type

In C++20 mode, the front end now accepts nontype template parameters (and
corresponding arguments) of floating-point types and of certain class types
(such class types must be "structural types").  For example:

  struct S {
    constexpr int f() const { return i; }
    int i;
  };
  template<S s> struct X {
    static constexpr int f() { return s.f(); }
  };
  X<S{42}> xs;  // Now accepted in C++20 modes.
  constexpr int r = xs.f();  // Initializes r to 42.

This implements the changes to the standard made by the standardization
committee's paper P1907R1, which itself modified an earlier proposal adopted
via paper P0732R2.


7/28/20  [EDGcpfe/23076]
C++-generating back end: front-end customization point for excluding
generated explicit specializations

In C++-generating back end configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, a
customization point has been added to the front end to allow identifying
instances of function templates that should not be represented as explicit
specializations in the generated code. The function
check_for_function_that_cannot_be specialized (overload.c) is called at the
point at which a function template instance is selected by overload
resolution.  It currently does nothing, but customers can add code to set
the suppress_explicit_specialization flag in the a_routine entry for any
function template instance that is deemed to be problematic.


7/28/20  [EDGcpfe/22129]
GNU C++ compatibility: Literal types and virtual base classes

In GNU C++ modes, virtual base classes no longer disqualify a class type from
being a literal type.  However, an object of such a type can still not be
constructed as part of a constant expression.  For example:

  struct B {};
  struct D: virtual B {};
  constexpr int f(D) { return 1; }  // Now okay in GNU C++ mode.
  constexpr D d{};  // Error in all modes.

Function f in this example is nonstandard because it is declared constexpr but
has a parameter of nonliteral type D.  However, GCC does consider D to have a
literal type and thus accepts the definition of f.  Defining a constexpr object
of type D is still an error, however, even in GNU C++ modes.


7/27/20  [EDGcpfe/22850]
C++-generating back end: overloading via using-declaration with dependent base

When putting out a call to a member function inherited by using-declaration
in a class with a dependent base, the C++-generating back end sometimes
inappropriately used a qualified name for the member function, forcing the
selection of a different function than in the original source.  This is
now fixed.  For example, with --g++:

  extern "C" int printf(const char*, ...);
  int gx = 0;
  struct A {
    void f(int) { gx = 3; }
  };
  template<class T> struct B {
    void f(double) { gx = 5; }
  };
  template<class T> struct C : B<T>, A {
    using A::f;
    using B<T>::f;
    void g() {
      f(2);        // Previously put out as A::f(2)
      printf("gx:%d\n",gx);
      f(2.2223);   // Previously put out as A::f(2.2223)
      printf("gx:%d\n",gx);
  }
  };
  int main() {
    C<int> c;
    c.g();
  }


7/27/20  [EDGcpfe/22600]
Clang compatibility: attribute "overloadable" (IL CHANGE)

Version 5.0 of the front end added support for the Clang attribute
"overloadable", which enables overloading function declarations in C mode (see
the entry for EDGcpfe/14779, etc.).  However, the attribute was essentially
ignored in C++ mode.  Now, it also allows overloading extern-C functions in
Clang C++ mode.  For example:

  extern "C" {
    int f(int) { return 1; }
    int f(unsigned) __attribute((overloadable)) { return 2; }
      // Previously an error in all C++ modes.  Now okay in Clang C++ mode.
  }

Previously, the type of a function declared using this attribute was marked as
"C++ external" (see the routine_name_linkage field of the associated routine
type supplement).  That is no longer the case, and instead the routine entry
itself is marked as having "C++ name linkage" if appropriate (via the
source_corresp.name_linkage field).  This is a subtle IL CHANGE.


7/27/20  [EDGcpfe/23158]
Spurious ambiguity in partial specialization of variadic template

In some cases, the front end could incorrectly consider partial specializations
to be ambiguous.  This could occur when the argument list of the primary
template was a template parameter pack but the first parameter of each of the
partial specializations was not a template parameter pack.  Now fixed.

  template <typename... T> struct A;
  template <typename T, typename... U> struct A<T, U...> {};
  template <typename T, typename... U> struct A<T&, U&...> {};
  int main() {
    A<int&> t;
  }


7/27/20  [EDGcpfe/22727]
Spurious redeclaration error with decltype nontype parameter type

A spurious error could result if two function templates had the same
function types and had template parameter lists that were the same except that
a nontype template parameter had different dependent expressions used in the
decltype-specifier that specified the nontype parameter type.  Now fixed.

  template<typename P, decltype(P::X) val = 1> int f() {return val;}
  template<typename P, decltype(P::Y) val = 2> int f() {return val;}
  struct A { constexpr static int X = 1; };
  struct B { constexpr static int Y = 1; };
  int main() {
    if (f<A>() != 1 || f<B>() != 2) return 1;
  }


7/27/20  [EDGcpfe/22747]
C++-generating back end: missing namespace qualifier with CTAD

When using class template argument deduction, a class template name could
be emitted without the appropriate namespace qualifier when using the
C++-generating back end.  Now fixed.

  namespace N {
    template <class T> struct A { A(T, int){} };
  }
  // N::A incorrectly emitted as just A.
  template <class T> void f(T t) { N::A s{t, 0}; }
  int main() {
    f(0);
  }


7/27/20  [EDGcpfe/22849]
C++-generating back end: unneeded qualification in member access

The C++-generating back end sometimes added an unnecessary name qualifier
when putting out a member access expression.  Ordinarily such redundant
qualification is harmless, but in some cases it could result in incorrect
generated code.  This is now fixed.  For example:

  template <class T> struct A {
    void mf2();
    int T1;
    A() : T1(0) {}
  };
  template <class T1> void A<T1>::mf2() {
    T1++;  // Previously generated as A<T1>::T1++.  Since the member T1
           // hides the template parameter T1, "A<T1>" was an error.
  }


7/24/20  [EDGcpfe/22947]
C++-generating back end: dependent deduced decltype(auto) return types

In contexts in which a decltype(auto) deduced return type appears in a
templated context, the C++-generating back end could drop parentheses in
the return expression, thus changing the deduced type.  This is now fixed,
and the parentheses are preserved in the generated output.  For example,
with --g++ --c++14:

  void f() {
    auto f3 = [](auto && in) -> decltype(auto) {
      return (in.val);  // Previously generated as "return in.val;"
    };
  }


7/24/20  [EDGcpfe/22672]
Abort with template parameters defaulted to functions

In C++11 modes and beyond, the front end would abort in
conv_function_designator_to_ptr_to_function when a template parameter is
defaulted to a function.  For example:

  void foo();
  template <typename Compare, Compare = foo> // Would previously abort here
  class A;

This is now fixed.


7/24/20  [EDGcpfe/22430]
C++-generating back end: accessible member typedefs of class templates

When an accessible member typedef of an instance of a class template is used
to refer to an inaccessible type, the C++-generating back end sometimes put
out the reference using the inaccessible type instead of the accessible
typedef, resulting in uncompilable generated code.  This is now fixed.  For
example, with --c++11 --g++:

  namespace std {
  class type_info { };
  template <typename> class A {
    struct B { };  // private
  public:
    typedef B C;
  };
  }
  void f() {
    typeid(std::A<char>::C);  // Previously generated using B instead of C
  }


-------------------------------------------------------------------------------
Version 6.1, July 24, 2020

7/22/20  [EDGcpfe/22973]
Constant evaluation of pseudo-destructors for rvalues

The constexpr interpreter previously did not correctly handle certain rvalue
destructions (permitted in C++20, see the entry for EDGcpfe/21597), including
temporaries which are lifetime-extended because of a reference binding.  In
some cases, this could lead to memory corruption and aborts later on.  For
example:

  #include <initializer_list>
  template<typename T> constexpr T g(T const &p) {
    std::initializer_list<T> list = { p };
    return list.begin()[0];
  }
  struct S {
    constexpr S(): buf() {}
    constexpr ~S() {}
    char buf[42];
  };
  constexpr S x;
  constexpr S const &r = g(x);  // Previously caused memory corruption.

This problem is now fixed.


7/22/20  [EDGcpfe/23151]
Feature-test macro for coroutine support

The C++ Standards Committee, by means of Library Working Group issue 3393,
changed the name of the feature test macro for language-level coroutine
support from __cpp_coroutines to __cpp_impl_coroutines.  The front end now
supports the new macro name, while continuing to define the previous macro
name as before for backward compatibility.


7/22/20  [EDGcpfe/23132]
C++-generating back end, Microsoft compatibility: trailing return types in
template arguments

The Microsoft C++ compiler has a bug that results in issuing spurious
errors if a function declarator appearing in a template argument uses the
trailing-return-type syntax.  The C++-generating back end has now been
changed to work around this bug by putting out all function declarators in
template arguments using the traditional syntax when
msvc_is_generated_code_target is TRUE.  For example, with --c++11:

  template<typename T> struct A { };
  template<typename T> struct B { };
  // The following declaration is now put out for MSVC as
  // template<> struct A<B<int> (*)(void)> { };
  template<> struct A<auto (*)()->B<int>> { };


7/21/20  [EDGcpfe/23123]
GNU/Clang compatibility: Vector assignment

In GNU and Clang modes, the front end now accepts more assignments involving
"vector" types.  For example:

  typedef long long VLL1 __attribute((vector_size(8)));
  typedef int VI2 __attribute((vector_size(8)));
  void g(VLL1 x, VI2 y) {
    x = y;  // Previously an error.  Now okay.
  }


7/20/20  [EDGcpfe/20988,EDGcpfe/23131]
Class template argument deduction for variable templates

The front end previously often failed parsing variable template definitions
that relied on class template argument deduction.  For example:

  template<typename> struct X {};
  template<typename T> X<T> f() { return X<T>{}; }
  template<typename T>
  X vt = f<T>();  // Previously failed to parse.  Now okay.

That is now fixed.


7/20/20  [EDGcpfe/23007]
C++-generating back end: friend declarations in generated explicit
specializations

In configurations with CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
set to TRUE, the C++-generating back end sometimes omitted friend function
declarations from the generated explicit specializations for instances of
class templates.  This is now fixed.  For example:

  namespace N {
    template<typename T> class C;
    template<typename T> int f(C<T> c) { return c.i;}
    template<typename T> class C {
      friend int N::f<T>(C<T>);
      int i;
    };
  }
  int g() {
    N::C<int> ci;
    return N::f(ci);
  }

In the generated specialization for N::C<int>, the friend declaration was
previously omitted but is now present.


7/19/20  [EDGcpfe/23126]
Missing instantiations in IL

The changes for EDGcpfe/20503 in version 5.1 could cause function
instantiations referenced from functions with deduced return types to be
omitted from the IL in certain conditions.  The changes for EDGcpfe/20503
have been removed for now.


7/17/20  [EDGcpfe/21422,EDGcpfe/22544,EDGcpfe/23066,EDGcpfe/23089]
Memory corruption in constexpr interpreter

The constexpr interpreter normally immediately stops interpretation when
encountering an error situation, to avoid corrupting its data structures.
A few situations were found where interpretation continued despite an error
situation, resulting in memory corruption and, most likely, an abort.  In
particular, certain cases involving unknown array sizes previously proceeded
as if the array had length zero.  That is now fixed.


7/16/20  [EDGcpfe/20005,EDGcpfe/20118]
C++20: Concepts

The front end now supports constrained templates, concept templates, requires-
expressions, and abbreviated function template declarations, features that are
collectively thought of as the C++20 "concepts" feature.  The principal
committee papers describing the changes for the standard are P0734R0 and
P1142R2 (the latter for abbreviated function template declarations), but a
number of additional papers added refinements to the original specification
and most of those have been implemented as well (including P0857R0, P1084R2,
P1452R2, P1616R1, P1972, P1980, and P2092).  For example:

  template<typename T> concept Sizeable = requires { sizeof(T); };
  template<typename T> concept Small = Sizeable<T> && sizeof(T) < 100;
  int f(Small auto p) { return 1; }   // (1)
  void f(auto) {}                     // (2)
  int r = f(42);  // Okay: Prefers (1).

The IL data structures that mirror some of the front end data structures
(a_template_parameter and a_template_decl) are now created unconditionally.
Formerly, the were only created when all_template_info_in_il was TRUE.  This
is a small IL CHANGE.


7/16/20  [EDGcpfe/23081]
GNU compatibility: Value-initialized vectors in constant expressions

The front end previously did not fold the value-initialization of GNU vector
types.  For example (in GNU C++14 mode):

  using V4 = int __attribute((vector_size(16)));
  constexpr V4 x = V4();  // Previously an error.  Now okay.

That is now fixed.


7/15/20  [EDGcpfe/23099]
C++-generating back end: friend function definitions in class templates

Given a class template in which a friend function is defined in the class
definition, the body of the friend function was replaced by a ";" in the
string form of the class template definition, and this substitution was
reflected in the output of the C++-generating back end in modes and
configurations in which the definitions of class templates are taken from
the string form rather than from the prototype instantiation IL.  This is
now fixed.  For example, with --microsoft (which suppresses prototype
instantiation):

  template<typename T> class A {
    friend void f(A<T>) { } // Previously generated as "friend void f(A<T>);"
  }


7/15/20  [EDGcpfe/22503,EDGcpfe/23082]
GCC compatibility: Vector shift-assign operations

In GNU modes with gnu_version >= 40800 and Clang modes with clang_version >=
40000, the front end now accepts shift-assign (>>= and <<=) operations on
vector types.  For example:

  typedef int __attribute((vector_size(16))) V4;
  void g(V4 *p) {
    *p <<= 2;  // Now accepted in some GNU and Clang modes.
  }


7/15/20  [EDGcpfe/23055]
Constexpr constructors and uninitialized subobjects

Consider:

  template<int> struct X {
    constexpr X() {} // Fails to initialize this->i.
    int i;
  };
  struct S {
    constexpr S() {}
    X<42> x;
  };

The front end previously always issued an error on the default constructor of
S because it is declared "constexpr" but no invocation of it could possibly
produce a constant prior to C++20.  C++20 relaxed the rules through paper
P1331R2 and the resolution of core issue 2424.  In C++20 modes, such examples
are therefore now accepted without diagnostics.  Furthermore, other 
implementations do not diagnose this specific case (where the constructor
called for the initialization of S::x is a template instance) in their
pre-C++20 modes either.  In Clang, GCC, and Microsoft pre-C++20 modes
the front end therefore now only issues a warning for this case and a
discretionary error in other pre-C++20 modes.


7/15/20  [EDGcpfe/23051]
Local static variables and MAKE_FRONT_END_CALLABLE

The function constant_conv_function_result previously relied on local static
variables.  However, such variables do not get re-initialized when the front
end is re-invoked in a configuration when MAKE_FRONT_END_CALLABLE is TRUE, and
thus invoking that function could lead to memory corruption.  That problem is
now fixed (the local static variables have been eliminated).


7/15/20  [EDGcpfe/20412]
Abort in constexpr interpreter when C++11-style SFINAE is disabled

Consider:

  struct A { enum { value }; };
  template<bool> struct B { };
  template<typename T, typename U>
    typename B<U(A::value || U::value)>::type operator==(T, U);
  template<typename> class C;
  template<typename T> bool operator==(C<T> const&, C<T> const&);
  template<typename T> class C {
    friend bool operator==<T>(C const&, C const&);
  };
  C<int> a;

Previously, this could abort in the constexpr interpreter (in the function
check_boolean_condition) in C++11 mode with C++11 SFINAE rules disabled (i.e.,
with the --no_c++11_sfinae option).  That problem was a regression introduced
in version 5.0 by the changes for EDGcpfe/17707,EDGcpfe/18676.  This is now
fixed.


7/14/20  [EDGcpfe/23075]
Spurious C++20 comparison error in GNU C++ mode

Consider:

  struct S {
    int n;
    auto operator<=>(S const&) const { return 0; }
  } s{1};
  auto r = s <=> s;  // Previously an error.  Now okay.

In GNU C++ mode, the front end produced a spurious error about the <compare>
header not being included.  That was a consequence of an unintended interaction
between the overload resolution rules for C++20 comparison operators and a late
overload resolution tiebreaker that is specific to GCC.  That is now fixed.


7/14/20  [EDGcpfe/22022]
ext_vector_type attribute and typedefs

In Clang mode, the ext_vector_type attribute did not produce a correct size
for the resulting type if the underlying type is a typedef.  For example:

  typedef unsigned char uchar;
  typedef uchar uchar2 __attribute__((ext_vector_type(2)));
  typedef unsigned char ucharV2 __attribute__((ext_vector_type(2)));
  static_assert(sizeof(uchar2) == sizeof(ucharV2), "Unexpected");
    // Previously failed.  Now okay.

That is now fixed.


7/14/20  [EDGcpfe/23037]
Assertion failure in initialize_vptr

In Cfront ABI configurations that do lowering, an assertion failure in
initialize_vptr could occur when attempting to initialize a _vptr field
in a class that has a member with the [[no_unique_address]] attribute as well
as an unnamed bit-field.  For example (with --c++20):

  struct A {
    virtual void f();
    [[no_unique_address]] struct B {} b;
    int : 2;
  } a;


7/14/20  [EDGcpfe/20826]
Internal error: add_field: two fields have the same offset

In configurations that do lowering and have CHECKING enabled, an internal
error had occurred when adding the _vptr field into a class that has a member
with the [[no_unique_address]] attribute.  For example (with --c++20):

  struct A {
    virtual void f();
    [[no_unique_address]] struct B {} b;
  };


7/14/20  [EDGcpfe/23034]
Internal error: ptr_remap_function: address not in any mem block

In configurations with ALTERNATE_IL_FILE_FORMAT set to FALSE, lowering of
certain classes whose members have attributes could lead to an internal error
in ptr_remap_function.  For example (with --c++20):

  struct B {};
  struct A : B {
    [[no_unique_address]] struct {} m [[align(4)]];
  };


7/13/20  [EDGcpfe/23087]
Constexpr intrinsics and precompiled headers

The data structure used by the interpreter to implement certain intrinsics
(like std::is_constant_evaluated()) turns out to be incompatible with the
front end's mechanism for precompiled headers.  As a result, precompiled
headers making use of such intrinsics were likely to trigger an abort.
That problem is now resolved.  As part of this change, the a_routine field
"virtual_function_number" has been renamed to "number.virtual_function"
(where number is a new member union).


7/10/20  [EDGcpfe/23054]
Spurious error during disambiguation of range-based for (regression)

In version 6.0, changes made to support range-based for statements with an
initializer (see entry for EDGcpfe/20007) could cause spurious errors during
disambiguation.  In particular, a base class member followed by a "<" was
incorrectly considered to start a template argument list.  Now fixed.

  template <class T> struct A {
    int f();
    int i = 0;
  };
  struct B : A<int> {
    void g() {
      // Formerly "error: is not a template"
      for (; i < f();) {}
    }
  };


7/10/20  [EDGcpfe/23080]
Issue with compilation terminated by --time_limit option

When the --time_limit option is used and the time limit is exceeded, the code
that terminates the compilation could hang if, for example, the compilation
was within malloc when the signal was sent and then term_compilation attempted
to allocate more memory.  To avoid issues like this, the sign-off message
is no longer issued when the CPU time limit is exceeded.


7/8/20   [EDGcpfe/22311]
C++-generating back end: dependent alias template specializations as qualifiers

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end sometimes used the
underlying type of a dependent alias template specialization as a
qualifier, even when that underlying type would be an error.  This is now
fixed, with the generated code now retaining the alias template
specialization in such cases.  For example, with --c++14:

  template<typename...> struct a;
  template<int I> struct b {
    using c = void;
  };
  template<typename... Ts> using d = b<sizeof...(Ts)>;
  template<typename... Ts>
  using e = typename d<a<Ts>...>::c; // previously generated as (erroneous)
                                     // b<sizeof...(a<Ts>)>::c


7/7/20   [EDGcpfe/23058]
Spurious SFINAE failure when rescanning a subexpression

Consider:

  template<typename T> T &&declval() noexcept;
  struct W { bool value; };
  template<typename T> constexpr W wrap = { noexcept(*declval<T>()) };
  template<typename T> void f(T &&v) noexcept(wrap<T>.value) {}
  void g(int *x) { f(x); }

Previously, the substitution of "wrap<T>.value" failed because the front end
erroneously attempted to force a conversion to bool-like type on wrap<T>
(instead of wrap<T>.value).  That is now fixed.


7/7/20   [EDGcpfe/22402]
C++-generating back end: deduced return types and generated specializations

In C++-generating back end configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE,
function and template parameters appearing in generated explicit
specializations could sometimes be incorrectly put out using "auto" as a
type, resulting in uncompilable generated code.  This is now fixed.  For
example, with --c++17:

  template<typename T> void f(T);
  template<typename T> struct S {
    static auto x() { return T(); }
  };
  void g() {
    f(S<int>::x());
  }

The explicit specialization of f<int> was previously put out incorrectly as:

  template<> void f(auto);

and now correctly as:

  template<> void f(int);

The underlying issue for this problem was that the placeholder type indicating
that a return type was deduced (i.e., the return type of S<int>::x() in the
example above) was used for the type of the expression representing a call to
the associated function.  That placeholder type then propagated through
deduction to other function types.  Now, the expression no longer carries the
placeholder type.


7/4/20   [EDGcpfe/23048]
C++-generating back end: use of local types in template arguments

In configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
C++-generating back end suppressed generated explicit specializations in
which a type template argument is a type that is local to a function
(because such types cannot be named outside the block scope in which they
appear).  However, it failed to apply that test recursively; i.e., it did
not suppress specializations in which the template argument is an instance
of a class template that has a local type as an argument.  For example,
with --c++11:

  namespace N {
    template<typename T> struct A { };
  }
  template<typename T> struct B { };
  void f() {
    N::A<B<struct S>> abs; // declares struct S local to f
  }

Here, the C++-generating back end correctly suppressed the generated
explicit specialization for B<S>; however, it failed to do so for
N::A<B<S>>, so that the generated code was something like:

  namespace N {
    template<> struct A<B<struct S>> ;  // #1
  }
  namespace N {
    template<> struct A<B<S>> { };
  }
  void f() {
    N::A<B<S>> abs;  // #2
  }

Note that the explicit specialization at #1 incorrectly introduced struct S
as a member of namespace N; also, because the type had already been
declared, the 'struct' keyword was omitted in the template argument at #2.
This is now fixed; the explicit specialization of A<B<S>> is now
suppressed, and the 'struct' keyword is restored in the template argument
inside f.


7/1/20   [EDGcpfe/22997]
C++-generating back end: ordering issues with base of nested class

In general, the C++-generating back end preserves the way base class
specifiers are designated in the generated code, using a typedef name for
the base class if the source code does.  In configurations in which
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, however,
that can lead to ordering dependencies that result in generated code that
cannot be compiled.  For example:

  template<typename T> struct Outer {
    struct Inner : T {
      virtual void f() { };
    };
    enum { v = sizeof(T) == sizeof(Inner) };
  };
  template<typename T> struct A {
    typedef T type;
    static_assert(!Outer<type>::v, "bug");
  };
  struct B { };
  struct C {
    A<B> ab;
  };

In the generated code, the explicit specialization for A<B> must
necessarily follow that of Outer<B> because of the use of Outer<B>::v in
the static_assert declaration. However, Outer<B>::Inner has a base class
that is originally specified as A<B>::type, which is a typedef for B.  If
the explicit specialization for Outer<B> specified Inner's base class using
that typedef, that use would result in the implicit instantiation of A<B>
before its explicit specialization, which is an error.

The C++-generating back end has now been changed to detect such forward
references to typedefs in base class specifiers and use the underlying type
instead.  In this example, the explicit specialization for Outer<B> now
specifies "Inner : B" instead of "Inner : A<B>::type" and the generated
code can be compiled without error.


6/30/20  [EDGcpfe/23025]
Partial ordering of function template and exception specifications

When exception specifications are part of function types (i.e., C++17 mode),
the front end previously erroneously substituted exception specifications
during the process of determining the partial order of function template
candidates.  Those substitutions could trigger instantiations that in turn
triggered spurious errors.  That problem is now fixed.


6/30/20  [EDGcpfe/23009]
C++20: Ambiguity with reversed-parameters candidate

Consider the example of EDGcpfe/21912:

  struct X { bool operator==(const X &b); };
  bool b = X() == X();  // Previously an error.  Now a warning.

As explained in the entry for EDGcpfe/21912, C++20 makes this example ambiguous
because the declared operator== is a better match for the second argument, but
the candidate synthesized by reversing parameters is a better match for the
first argument.  Although such code is likely unintentional (i.e., the
programmer forgot to "const-qualify" the operator== declaration), it is not
entirely uncommon.  The front end therefore now prefers the declared candidate
(without reversal of parameters) in such cases, but a warning is issued.


6/28/20  [EDGcpfe/23014]
Position information for ambiguous overload resolution candidates

Consider:

  int f(long);
  int f(long long);
  int r = f(42);  // Ambiguous call.

The call f(42) is ambiguous, and the front end lists the ambiguous candidates.
Now that list includes position information about where the candidates were
declared.


6/26/20  [EDGcpfe/22934]
Change for unexpected_condition* routines

A number of cleanup changes were made to the source code as we moved to using
PC-Lint version 1.3.5.  One change that may be noticed is that the
unexpected_condition, unexpected_condition_str, and unexpected_condition_str2
routines now call exit_compilation in all configurations (previously the
compilation was terminated only when CHECKING was TRUE).


6/25/20  [EDGcpfe/22999]
__builtin_is_constant_evaluated availability

The version checking for support of the __builtin_constant_evaluated builtin
was incorrect.  For example, its use was enabled when microsoft_version is
1925, but not in subsequent versions.  Now fixed.


6/24/20  [EDGcpfe/17930]
Microsoft compatibility: __declspec(guard(id))

The front end now accepts annotations of the form "__declspec(guard(id))" on
some declarations (where id is an identifier).  The front end does not check
the validity of any such constructs (e.g., it does not check that id is an
identifier that the Microsoft compiler would recognize).  Currently, this
construct is accepted on declarations of functions, variables, and parameters.


6/23/20  [EDGcpfe/22987]
Internal source sequence entry error on static data member template

In some configurations, the front end could abort with an internal error in
add_src_seq_end_of_variable_if_needed because of an invalid assumption in the
treatment of static data member templates.  For example:

  #pragma pack(1)
  #pragma pack(1)
  #pragma pack(1)
  #pragma pack(1)
  struct S {
    template<typename T> static constexpr bool val = T::val;
  };  // Previously triggered an internal error.

That is now fixed.  (The problem only manifested in some configurations that
have GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE.)


6/23/20  [EDGcpfe/22985]
Missing error (and possible abort) on invalid decltype name qualifier

The front end failed to issue a diagnostic when a decltype-specifier was used
in a qualified name and the type that resulted from the decltype did not refer
to a class or enumeration type.  In some cases this could result in an abort
(in class_qualified_id_lookup).  Now fixed.

  typedef int A;
  int main() {
    A a = 0;
    a.decltype(a)::~A(); // incorrectly accepted
    a.decltype(1)::x;    // aborted
  }


6/22/20  [EDGcpfe/22971]
Warning for variable that is initialized but unused

The front end previously issued a warning for a variable that is declared
but not used, but not if its initialization involved a constructor call.
The latter exception reflected the common usage in which the initialization
of the variable performs some useful action but the variable is otherwise
not needed.  Recognizing, however, that there may be circumstances in which
not using an initialized variable actually does reflect a programming
mistake, the front end has now been changed to report the appropriate
diagnostic with a severity of es_none, which can be optionally increased by
command-line options, pragmas, etc.  For example, with
--diag_warning=declared_but_not_referenced:

  struct S {
    S();
    S(const S &);
  };
  void f(S s) {
    S s2 = s;  // Normally evokes no warning because of constructor call
  }


6/20/20  [EDGcpfe/22653]
C++-generating back end: parenthesized conditional expression operand

Previously, the C++-generating back end enclosed the third operand of a
?: operator in parentheses when the operand was the name of a variable and
thus needed no parentheses.  In configurations in which the definitions of
templates are generated from the prototype instantiation IL, this unneeded
parenthesization produced code that elicited spurious errors from early
versions of g++.  This is now fixed, and such parentheses are no longer
added.  For example, with --c++14 --gnu_version=50400:

  template <typename = void> struct S {
    static const char a[];
  };
  template <typename T> const char S<T>::a[] = "";
  template <typename> const char *f() {
    return 0 ? "" : S<>::a;  // Previously generated as "(S<>::a)", which
                             // caused spurious errors in older g++ versions
  }
  auto p = &f<char>;


6/19/20  [EDGcpfe/18036,EDGcpfe/21779]
Instantiation of namespace member may fail to use using-directive

In some cases the instantiation of a template defined in one namespace and
instantiated from a reference in another namespace could fail to make use
of certain using-directives in the namespace containing the template
definition.  Now fixed.

  namespace N {
    namespace O {
      enum E { e1 };
    }
  }
  namespace M {
    using namespace N::O;
    template <typename T> E f(T) { return E::e1; }
  }
  namespace N {
    int f() { return M::f(0); }
  }


6/19/20  [EDGcpfe/22827]
C++-generating back end: missing empty template argument list in dependent call

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end failed to emit an
empty template argument list in a dependent function call.  This is now
fixed.  For example, with --c++11 --g++:

  template<class T> struct X {
    void f(int) { }
    template<class TT> void f(TT) { }
  };
  template<class T> void f(T t) {
    X<T> x;
    x.template f<>(t);  // Previously generated without "<>"
  }


6/19/20  [EDGcpfe/22504]
IL display for lambda closure initializers

The IL display utility now outputs the lambda associated with a dik_lambda
dynamic initialization entry (i.e., the initializer for a lambda closure).


6/18/20  [EDGcpfe/22931]
C++-generating back end: friend functions referencing local types

In configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, when the
source contains a class template in which a friend function is defined, the
C++-generating back end puts out a namespace-scope definition of that
friend function for each instance of the class template, substituting
template arguments for template parameters as needed.  If the class
template is instantiated with a local type as a template argument, a friend
function that refers to the corresponding template parameter cannot be
validly defined at namespace scope.  The C++-generating back end has now
been changed to suppress such definitions.  For example, with --microsoft:

  template <class T> struct A {
    friend void f(A) { }
  };

  void g() {
    struct S { };
    A<S> as;
    f(as);
  }

This example instantiates A with the local class type S.  Previously the
generated code for this example contained the definition

  inline void f(A<S>) { }

which cannot be compiled because of the use of S.  That definition is now
omitted from the output.


6/17/20  [EDGcpfe/22721]
C++-generating back end: decltype specifiers with reference object expressions
in member function calls

Versions of MSVC prior to 1914 had a bug that resulted in spurious errors
if the expression in a decltype specifier consists of a member function
call in which the object expression has a reference type.  In configurations
in which TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LIST is TRUE, the
C++-generating back end could put out such decltype specifiers in generated
explicit specializations, triggering the MSVC bug when compiling the
generated code.  This has been addressed by putting out the type designated
by the decltype specifier rather than the decltype specifier itself when
msvc_is_generated_code_target is TRUE and msvc_target_version_number is
less than 1914.  For example, with --microsoft_version=1900:

  struct S {
    int f();
  } s;
  template<typename T> struct X {
    X(T& tr) : t(tr) { }
    T &t;
    auto g() -> decltype(t.f()) { return 0; }
  };
  int i = X<S>(s).g();

Previously the generated code for this example contained the explicit
specialization

  inline auto X<S>::g()->decltype(((t).f())) { return 0; }

Because X<S>::t has type S&, MSVC issued errors for this code.  Now the
explicit specialization is generated as

  inline auto X<S>::g()->int { return 0; }

which is accepted without error.


6/16/20  [EDGcpfe/22943]
C++-generating back end: "overloadable" attribute on function declaration

The C++-generating back end put out an extern "C++" specifier for a
non-defining declaration of a function with the "overloadable" clang C
attribute.  This is now fixed.  For example, with --clang --c:

  void f(int) __attribute__((overloadable));

was previously put out as

  extern "C++" void f(int) __attribute((overloadable));

even though the generated code was supposed to be C and not C++.


6/16/20  [EDGcpfe/22942]
C++-generating back end: postfix attributes in function definitions

The C++-generating back end failed to put out attributes appearing between
the parameter list and the function body in a function definition.  This
is now fixed.  For example, with --clang --c:

  void f(int) __attribute((overloadable)) { } // attribute previously omitted


6/16/20  [EDGcpfe/22913]
Microsoft compatibility: value of _MSVC_LANG with --ms_c++latest

The value of _MSVC_LANG has been changed from 201704L to 201705L when
microsoft_version >= 1920 to match the behavior of Microsoft Visual Studio.


6/15/20  [EDGcpfe/21089]
Raw string literals in macro arguments

When a raw string literal appears in a macro argument, some characters in
the value were replaced with canonical values rather than being preserved
in their original form.  These sequences included embedded newlines, line
splices, trigraphs (in modes that support them), and null characters.  This
is now fixed and the original values are preserved.  For example, with
--c++11:

  #define M(x) x
  const char *p = R"(a
  b)";    // Value is "a\nb"
  const char *q = M(R"(a
  b)");   // Value was previously "a\\nb", now same as p


6/15/20  [EDGcpfe/22949]
GCC compatibility: Pseudo-destructors

The changes for EDGcpfe/21397 (see entry of 7/31/19) ensured that the front end
correctly enforces that pseudo-destructors are only used as the target of a
call expression.  However, it appears that GCC prior to version 7.4 did not
enforce when more than one level of SFINAE checking is in progress.  The front
end now matches that behavior in corresponding GCC modes.


6/15/20  [EDGcpfe/22948]
Interpreter error with generated copy/move of variant fields

In some fairly complex situations, the interpreter did not correctly handle
generated copy/move construction from a source object containing variant
fields.  That is now fixed.


6/11/20  [EDGcpfe/19682,EDGcpfe/20186,EDGcpfe/20189,EDGcpfe/20956,
          EDGcpfe/20957,EDGcpfe/21231,EDGcpfe/21699]
Deduction failure with parameter of class type with auto template argument

Consider:

  template<auto> struct X {};
  template<typename T, T N> void g(X<N>) {}
  int main() {
    X<10> t;
    g(t);  // Previously an error.  Now okay.
  }

The front end previously failed to deduce the template parameters for g in the
call to g(t) because of an error in matching a template argument to its
corresponding "auto" template parameter.  That is now fixed.


6/11/20  [EDGcpfe/22935]
C++-generating back end: missing static data member templates

The C++-generating back end could omit the declaration of a static data
member template from the generated code.  This is now fixed.  For example,
with --c++11:

  struct S {
    template<typename T> static const T m;  // Previously omitted
  };
  template<typename T> const T S::m = { };


6/11/20  [EDGcpfe/20143]
Spurious abort due to failure to detect dependence

The function arg_list_is_dependent (in overload.c) is expected to detect
"instantiation dependence", but it sometimes only checked for a more
restricted version of template-dependence known as "type dependence".  That
could result in internal errors, such as with the following example in some
Microsoft modes:

  template<typename T> struct L { L(T&); };
  struct K {};
  template<typename T> struct X {
    K k;
    void f() {
      L x(k);  // Previously the instantiation-dependence of k was not
    }          // detected and an internal error could ensue.
  };

That problem is now fixed.


6/9/20   [EDGcpfe/22924]
C++20 comparison rewrites

A number of problems involve C++20 comparison rewrites are now fixed.  That
includes cases like the following:

  #include <compare>
  struct X {
    auto operator<=>(int x) const { return 42 <=> x; }
  } x;
  auto r = 1 <=> x;  // Previously a spurious error.  Now okay.

A different problem occurred when a nondependent rewritten comparison occurred
in a template instantiation.  For example:

  #include <compare> 
  struct X {
    auto operator<=>(int x) const { return 42 <=> x; }
  } x;
  template<typename> auto cmp = 1 <=> x;
  auto r = cmp<void>;  // Previously triggered a spurious error.  Now okay.
    


6/9/20   [EDGcpfe/22675]
C++-generating back end: attributes on explicit instantiation directives

In configurations in which TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
is TRUE, the C++-generating back end replaces explicit instantiation
directives in the original source with explicit specializations in the
generated code; however, attributes that are present in the explicit
instantiation directive were omitted from the explicit specialization.
This is now fixed.  For example, with --microsoft:

  template<typename> struct S { };
  template struct __declspec(dllimport) S<int>;

Previously, the generated code contained the explicit specialization

  template<> struct S<int> { };

Now the explicit specialization is

  template<> struct __declspec(dllimport) S<int> { };


6/9/20   [EDGcpfe/22886]
Spurious error on use of class template being defined in static data member

Consider:

  template<typename> struct S {
    static constexpr S sm = S{};
  };

Previously, the front end issued an error about S being incomplete in the
initializer for S::sm.  Now such examples are accepted.


6/8/20   [EDGcpfe/22910]
C++-generating back end: non-public types in definitions of templated members

In configurations in which TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
is TRUE, the C++-generating back end failed to generate an explicit
specialization for a templated member function if the return type or
parameter types are non-public members of the containing class or class
template.  For example:

  class C {
    typedef int I;  // Private
  public:
    template<typename> void f(I) { }
  };
  void g() {
   C().f<int>(0);
  }

The C++-generating back end previously suppressed the generated explicit
specialization for C::f<int>(I) because I is not public.  This is now
fixed.


6/7/20   [EDGcpfe/22774]
C++-generating back end: public typedefs for private classes as qualifiers

In configurations in which TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
is TRUE, the C++-generating back end replaced the name of a private class
of a generated explicit specialization with a public typedef for that
private class as the qualifier in the definition of the private class's
members.  The generated code is correct, but it triggered a bug in older
versions of MSVC, resulting in spurious errors when compiling the generated
code.  This is now fixed, and the private class name is used as the
qualifier in such definitions.  For example, given:

  template<typename T> class S {
    struct priv {       // Private class
      priv() { }
    };
  public:
    typedef priv pub;   // Public typedef
  };
  S<int>::pub sp;

the generated code previously contained a definition like

  inline S<int>::pub::priv() { }

which triggered a bug in MSVC.  The definition is now put out using "priv"
as the qualifier instead of "pub".


6/5/20   [EDGcpfe/22897]
std::strong_equality and std::weak_equality

When operator <=> was first specified in the C++20 draft, it had provisions for
result types std::strong_equality and std::weak_equality.  In particular,
comparison of pointer-to-function types, pointer-to-member types, and nullptr
values all produce a std::strong_equality result.  However, the standards
committee's paper P1959R0 changed that to make such comparisons ill-formed and
it removed std::strong_equality and std::weak_equality.  The front end now
implements those changes in C++20 modes, except in Microsoft C++20 mode with
microsoft_version < 1925.


6/5/20   [EDGcpfe/22825]
Partial specialization ordering failure with cast in nontype argument

In some complex cases, the front end sometimes spuriously failed to order
partial specializations that involved nontype template argument expressions
containing a cast.  For example:

  template<int V> struct IntVal { static constexpr int val = V; };
  template<bool> struct BoolVal;
  template<typename, typename, typename> struct Assign;
  template<typename T, typename U>
    struct Assign<T, U, BoolVal<bool(1+(unsigned)T::val)>>;
  template<typename T>
    struct Assign<T, T, BoolVal<bool(1+(unsigned)T::val)>> {};
  Assign<IntVal<0>, IntVal<0>, BoolVal<1>> ai;  // Previously an error.
                                                // Now okay.

Previously, this example triggered an error claiming that more than one partial
specialization of Assign matches its use, because the cast to "bool" was
handled slightly differently in the two partial specializations.  This is now
fixed.


6/4/20   [EDGcpfe/18615,EDGcpfe/22094,EDGcpfe/22399,EDGcpfe/22641]
Error on braced initializer in base-specifier of class template definition

The caching of class template definitions did not properly handle a
braced initializer in a template argument list of a base-specifier
resulting in spurious errors.  Now fixed.

  template <int> struct B {};
  template <class T> struct A : B<T{}> {};


6/4/20   [EDGcpfe/22885]
GNU C++ compatibility: undetected recursive instantiation of static data member

In g++ mode, the in-class initializer of a static data member of a class
template is only evaluated when it is first used.  That processing did
not check for runaway recursive evaluations of the static data member,
which could result in a stack overflow.  Now fixed.

  template <int I> struct A {
    static const int v = A<I+1>::v;
  };
  const int x = A<1>::v;


6/3/20   [EDGcpfe/22793]
C++-generating back end: template arguments involving local types

In C++-generating back end configurations in which
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, a use of a
template with a template type argment that is an array, pointer, or
reference involving a local type resulted in a generated explicit
specialization for that template instance in which the template argument
referred to the local type from a point at which it is not in scope.  This
is now fixed; such explicit specializations no longer appear in the
generated code.  For example:

  template<typename T> struct A { };
  template<typename T> struct X { };
  void f() {
    struct A { };
    X<A*> xa;
  }

previously resulted in generated code containing an explicit specialization
in global scope like:

  template<> X<struct A*> { };

where "A" was intended to be the local class A but incorrectly referred
to the class template A, resulting in a compiler error for a missing
template argument list when compiling the generated code.


6/2/20   [EDGcpfe/22475]
Spurious error with inheriting constructor using-declaration in class template

The front end would attempt to diagnose invalid inheriting constructor
using-declarations in class templates, even when those templates are not
instantiated.  This could lead to spurious errors when the targeted base class
is dependent.  For example:

  template<typename T> struct A { A(T) {} };
  template<typename T> struct B : public A<T> {
    using B::A::A; // Spurious "must be inherited from a direct base" message
    using B::X::X; // Valid "must be inherited from a direct base" message
  };
  B<int> x(1); // Valid message now issued here

The front end now defers all such diagnostics (even when the base class is
not dependent) until the class template is instantiated.  This also improves
compatibility with MSVC, GCC, and Clang, as all of these also defer these
diagnostics until instantiation.


6/2/20   [EDGcpfe/15662,EDGcpfe/22819]
Assertion failure in type_is_lambda_in_default_argument

In IA-64 ABI configurations that do mangling, certain lambda expressions
that appear in default arguments had caused an assertion failure in
type_is_lambda_in_default_argument.  That is now fixed.  For example:

  int f(int x = [y=37]{ return 1; }() +
                    []{ return 0; }()) {
    return 0;
  }


6/2/20   [EDGcpfe/22393]
C++-generating back end: name of template template parameter

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end put out a use of a
template template parameter in a template definition using its name from
the original declaration of the template instead of its name in the
definition, which can be different.  This is now fixed.  For example:

  template<template<class> class  > void f();
  template<template<class> class T> void f() {
    T<int> t;  // Previously generated as <unnamed><int>
  };


6/1/20   [EDGcpfe/22867]
Loop in alias template declaration processing

In some circumstances a cycle can occur in the type representation involving
a parent type that is an instance of a class template and a template argument
that uses a type nested within that type as a template argument of the
parent class template.  This could result in a checking that does not
terminate in check_alias_template_param_usage.  We believe the circumstances
that give rise to this situation to be very rare as we have only had one
report of this issue.  The checking that is done there has been revised to
eliminate the problematic recursion.


5/28/20  [EDGcpfe/22861]
GCC 10.x compatibility: Lookup in noexcept-specifiers

One of the GCC bugs emulated by the front end relates to the lookup of names in
noexcept specifiers (see also the changes for EDGcpfe/16810).  For example:

  template<typename T> struct S {
    void f() noexcept(g());  // Previously always an error in GNU C++ mode.
    constexpr bool g() { return true; }  
  };

In this example, GCC 9.x (and earlier) and the front end in GNU C++ mode do not
consider later members when looking up "g" in "noexcept(g())".  GCC 10.1 has
fixed this and the front end now follows suit when gnu_version >= 100000.  Note
that GCC 10.1 system headers rely on this fix.


5/28/20  [EDGcpfe/22798]
Clang compatibility: use of --microsoft_version with --clang

The front end attempts to emulate Clang's emulation of Microsoft Visual
Studio in certain modes (see the Changes entry for EDGcpfe/16502).  Such
a command-line invocation might look like: "--clang --clang_version 60000
--ms_extensions --ms_compatibility", but adding --microsoft_version to
the command-line had resulted in a command-line incompatibility error message
in configurations where DEFAULT_MICROSOFT_MODE is TRUE.  That is now fixed.


5/28/20  [EDGcpfe/20661,EDGcpfe/22799]
GNU compatibility: "fallthrough" attribute

The "fallthrough" attribute has now been enabled in GNU (when gnu_version >=
70000) and Clang (when clang_version >= 100000) emulation modes (both C and
C++).  Additionally, some tweaks have been made to the [[fallthrough]]
processing in GNU emulation mode for better emulation.  For example:

  void f(int i) {
    switch (i) {
      case 0:
        f(i);
        __attribute__((fallthrough));
      case 1:
        break;
    }
  }

As is currently the case with [[fallthrough]], application of the attribute
does not suppress any diagnostics (the front end does not diagnose
"fallthrough" errors).


5/28/20  [EDGcpfe/19109]
Abort on invalid class member variable template partial specialization

An abort could occur (in decl_static_data_member) after a diagnostic
is issued for an invalid partial specialization of a member variable
template.  Now fixed.

  template<typename T> struct X {
    template <typename U> static int y;
    template <typename U> static int y<T>;
  };
  X<int> xi;


5/28/20  [EDGcpfe/19134]
Incorrect storage class for static variable template and its explicit
specializations

The prototype instantiation of a static variable template was not given
static storage class.  In addition, an explicit specialization of a static
variable template was also not given static storage class.  Now fixed.

  template <typename T> static T v;
  template <> int v<int> = 2;


5/27/20  [EDGcpfe/22651]
Microsoft compatibility: incorrect substitution of namespace member call

A change made in version 4.14 (see EDGcpfe/17925) could cause a spurious
"unexpected function type" error if a function name used in a decltype
in a function template function type was specified with an unqualified
name and the name found was made visible by a using-declaration.  Now
fixed.

  namespace N {
    template <typename T> struct A {};
    namespace O {
      template <class T> struct A : N::A<T> {};
      struct B : A<B> {};
    }
    template <typename T> N::O::B D(N::O::A<T> const&) noexcept;
    namespace NU {
      inline int D(...) noexcept;
    }
    namespace E {
      using NU::D;
      template <typename T> using F = decltype(D(T{}));
    }
    template <typename T> using G = E::F<T>;
    namespace NF {
      template <typename T> N::G<T> f(T val) { return {}; }
    }
    namespace NS {
      using NF::f;
      struct H {
        template <typename T> static auto g(T t) -> decltype(f(t)) {
          return f(t);
        }
      };
    }
  }
  int main() {
    N::NS::H::g(N::O::B());
  }


5/27/20  [EDGcpfe/22538]
IA-64 ABI: discriminators for enumerators of scoped enumerations in functions

As a result of the changes for EDGcpfe/11127,EDGcpfe/21364 (in version 6.0),
enumerators of enumerations had, in some cases, been given multiple
"discriminators" resulting in mangled names that could not be demangled.  One
of those "discriminators" is now suppressed.  Note that the IA-64 ABI does not
require enumerators to be mangled and an EDG-specific mangling is provided to
ensure unique names for the C-generating back end.  In the IA-64 ABI,
discriminators are sequential small integers tied to lexical position in the
scope, but in the EDG-specific mangling of enumerators, a unique (to the
compilation) number (the declaration sequence number) is used in the place of a
discriminator.  Note that even though this changes the mangled names, this
change is not conditional on ABI_COMPATIBILITY_VERSION because it only affects
enumerators in local functions.  For example, with --c++11:

  void f() {
    { enum class E { e }; }
    { enum class E { e }; }
  }


5/26/20  [EDGcpfe/22829]
Constant GNU statement expressions

Since version 5.1, the front end is able to constant-fold GNU statement
expressions.  In turn, this can reveal that a statement expression has no
effect at all.  For example:

  void g() {
    ({ 1; }); // Folded to value 1.  No effect.
  }

In versions 5.1 and 6.0, the front end issued a warning that the statement
expression has no effect.  However, GCC does not issue such warnings and such
situations are somewhat common in actual use.  The front end therefore no
longer warns about such statement expressions (i.e., no warning is issued
anymore for the example above).


5/26/20  [EDGcpfe/22834]
Alias template with non-dependent definition can cause incorrect behavior

In the unusual case of an alias template with a definition that does not
depend on its template parameters (e.g., D in the example below), incorrect
behavior could result when an instance of the alias template was used as
a template argument to a class template.  In the example below, a nonreal
type was referenced in the IL (as the type of C<int>::v.  In addition,
this example should have produced an "incomplete type" error on the
declaration of C<T>::c.  Now fixed.

  auto lambda = []{};
  template<class T> using D = decltype(lambda);
  template<class T> struct A {
    template< class U > struct B {
      B(){}
    };
  };
  template <class T, class V = typename A<D<T>[]>::template B<T*>> struct C {
    decltype(C<short>()) c;  // Should get "incomplete type" error
    V v;
  };
  C<int> ca;


5/26/20  [EDGcpfe/21483]
Spurious error on constexpr static data member in template

In some template cases, the front end issued a spurious error on a constexpr
static data member whose type is still being defined.  For example:

  template<typename> struct S {
    constexpr S(int i) {}
    static constexpr S sdm = 0;  // Previously an error.  Now okay.
  };

That is now fixed.


5/22/20  [EDGcpfe/22364,EDGcpfe/22777]
Access error not correctly handled in system headers

A change in the handling of SFINAE diagnostics in version 6.0 introduced a
regression causing access errors to not trigger deduction failures in system
headers even when cpp11_sfinae_ignore_access is FALSE.  That regression is now
fixed.  Furthermore, DEFAULT_DIAG_OVERRIDE_DOES_NOT_AFFECT_SFINAE now no longer
affects whether an error in a system header is treated as a substitution
failure (SFINAE) or not.


5/22/20  [EDGcpfe/21603,EDGcpfe/22071,EDGcpfe/22228,EDGcpfe/22661]
Spurious GNU C++-mode error on explicit specialization with noexcept specifier

In GNU C++17 mode, the front end sometimes failed to match up an explicit
specialization with the corresponding function template that includes a
noexcept specifier.  An error was issued as a result of this failure.
For example:

  template<typename> void f() noexcept(true);
  template<> void f<int>() noexcept;  // Previously an error in GNU C++17
                                      // mode.  Now okay.

That is now fixed.


5/22/20  [EDGcpfe/22376]
Conversion from bool incorrectly treated as narrowing

The front end previously treated many conversions from bool to another integer
type as "narrowing", which is incorrect.  For example:

  unsigned g(bool b) {
    return unsigned{b};  // Previously warned about narrowing.  Now
  }                      // silently accepted.

That is now fixed.


5/21/20  [EDGcpfe/22789]
Abort on uninitialized interpreter representation of empty derived object

Consider:

  struct D;
  struct B {
    constexpr D b2d();
  };
  struct D: B {};
  constexpr D B::b2d() { return static_cast<D&>(*this); }
  constexpr void f(D d) {
    d.b2d();
  }
  constexpr void g(D d) {
     f(d);  // Previously triggered an abort.  Now okay.
  }

Although the parameter d of g(D) is not a constexpr variable, the interpreter
can operate on it because it is an empty object of a "trivial class".  However,
previously, the interpreter did not fully initialize the representation of such
objects if they have base classes, which in turn could result in aborts later
on (e.g., in do_constexpr_expression).  That is now fixed.


5/20/20  [EDGcpfe/18333]
Internal error on use of variable template within a prototype instantiation

An internal error could occur (in push_template_instantiation_scope) if
a variable template that was a member of a class template was instantiated
with a non-dependent template argument list within the prototype instantiation
of another member of the class template.  Now fixed.

  template <class T> struct A {
    template <class U> static void (*fp)(U);
    static void f() {
      void (*k)(float) = fp<float>;
    }
  };
  int main() {
    A<int>::f();
  }


5/20/20  [EDGcpfe/22773]
C++-generating back end: internal error with local classes

In versions with hidden name processing enabled (e.g., C++-generating
back end versions), an internal error could occur when doing hidden
name processing for a local class of a prototype instantiation.  The
internal error occurred in push_template_instantiation_scope when
(indirectly) called from clone_inherited_hidden_members.  Now fixed.

  template <class T> struct C {
    struct A {
      int g();
    };
    A a;
    template <class U> int f(U u) {
      struct B : public A {
        B(A i) : A(i) {}
       };
       return a.g();
    }
  };


5/19/20  [EDGcpfe/22813]
Missing definition of defaulted member function with explicit instantiation

When a class template instance is explicitly instantiated in one translation
unit and instantiations are suppressed in another translation through use
of "extern template", a definition of the default function was not emitted
when it should have been.  Now fixed.  This was observed with the IA-64
ABI when using LOWER_EXTERN_INLINE, but could potentially affect other
configurations.  Now fixed.


  file x.h:
  struct B { B(const B&); };
  template <typename _Tp> struct A {
    A (const A&) = default;
    B b;
  };
  extern template class A<int>;

  file t1.c:
  #include "x.h"
  template class A<int>;
  B::B(const B&){}

  file t2.c:
  #include "x.h"
  void f(const A<int> &a) {
    A<int> a2(a);
  }
  int main() {}


5/18/20  [EDGcpfe/22723]
Maintain static data member constant initialization during lowering

In cases where a static data member has an initializer but is not defined,
there is no initialization to be performed, so lowering changes the
initialization of the static data member to initk_none, thereby effectively
removing the constant from the lowered IL.  A change has been made, in cases
where is_member_constant is TRUE, to maintain the (unlowered) constant.

  struct A {
    static const int X = 42;    // 42 remains in the lowered IL now.
  };
  int f() {
    const int* px = &A::X;
    return *px;
  }


5/15/20  [EDGcpfe/21210]
Spurious substitution failure in nested template in some complex cases

In some complex cases involving nested templates the front end sometimes
incorrectly failed to substitute a constant expression represented by a
tpck_expression entry in function copy_template_param_con.  The specific
circumstances of the failure are difficult to describe concisely, but they
were encountered during a specific use of the GNU std::variant implementation.


5/15/20  [EDGcpfe/15504,EDGcpfe/20605,EDGcpfe/22391]
Folding of source location builtins

The builtin functions __builtin_COLUMN, __builtin_LINE, __builtin_FILE, and
__builtin_FUNCTION are now generally folded in the front end.  In most cases
the source location reported is that of the call of the builtin itself,
but for calls in default arguments, the source location is that of the call
to the routine with the default argument.  Similarly, if the builtin call
is in a default member initializer, the reported location is that of the
constructor performing the initialization.  The latter case cannot be
determined by the front end and is left in the IL or replaced during lowering
(in configurations that use lowering).  These builtins are available when
emulating the latest versions of GCC, clang, or MSVC.  For example,
with --microsoft_version 1927:

  extern "C" int printf(const char *,...);
  #define print(loc) \
    printf("%s: FILE=%s, FUNCTION=%s, LINE=%d, COLUMN=%d\n", (loc), \
           __builtin_FILE(), __builtin_FUNCTION(), __builtin_LINE(), \
           __builtin_COLUMN())
  struct A {
    int x = (print("in A::x"), 0);
  } a;
  struct B {
    int x;
    B() : x((print("in B()"), 0)) {}
  } b;
  void def_arg_fn(int x = (print("in def_arg_fn"), 0)) {}
  int main() {
    print("in main");
    def_arg_fn();
    return 0;
  }


5/14/20  [EDGcpfe/22785]
GNU/clang compatibility: diagnose invalid class template constructor

In g++ and clang modes the front end accepted in invalid constructor
declaration in which the constructor name included a template argument
list.  A diagnostic is now issued in g++ mode when gnu_version >= 40000,
and in all clang modes (it is still accepted in Microsoft mode).

  template <class T> struct A { A();};
  template <class T> A<T>::A<T>() {};  // Now an error


5/14/20  [EDGcpfe/22780]
Incorrect initialization resulted in assertion failure in bigint_divmod

In configurations where USE_HOST_FP_CONVERSION_ROUTINES is FALSE and
MAKE_FRONT_END_CALLABLE is TRUE, invoking the front end multiple times
had resulted in an assertion failure in bigint_divmod.  This is now fixed.


5/13/20  [EDGcpfe/22540]
Use of local constexpr variable in nontype template argument

Consider:

  template<int> void f() {}
  template<typename T> void g() {
    constexpr T N{3};
    f<N>();
  }

Previously, in the prototype instantiation of g(), "f<N>" was represented as
"f<{3}>" where "{3}" is a template-dependent constant.  The C++-generating
back end also rendered the call in that form ("f<{3}>()"), which is invalid.
Now, a representation that maintains the designation of the variable is used
instead (specifically, a ck_template_param/tpck_expression constant pointing
to an enk_variable expression node).  This also fixes the rendering of the
C++-generating back end.


5/12/20  [EDGcpfe/22358,EDGcpfe/22463]
Defaulted comparison operators

The front end now implements the changes in the C++ standardization committee's
paper P2085 ("Consistent defaulted comparisons").  This allows defaulting
comparison operators outside the definition of the class to which the operator
applies.  For example:

  struct S {
    int i = 0, j = 0;
    bool operator==(S const&) const;
  } x, y;
  bool S::operator==(S const&) const = default;  // Previously an error.
  int r = x == y;                                // Now okay.


5/12/20  [EDGcpfe/21610]
Diagnosing expressions with no effect

The front end attempts to issue a warning for expressions that have no effect.
For example:

  int main() {
    42;  // Warning: expression has no effect
  }

That warning can be silenced by casting the expression to void.  For example:

  int main() {
    (void)42;  // No warning.
  }

Now the front end no longer issues a warning if the expression itself has type
void.  For example, in GNU C mode:

  int main() {
    ({});  // Previously a warning.  Now no warning.
  }


5/12/20  [EDGcpfe/21604,EDGcpfe/21715]
Spurious failure to fold call to generated copy/move constructors

Generated copy and move constructors were previously never marked as constexpr
if their associated class has variant members.  That in turn resulted in
spurious errors.  For example:

  template<typename> struct X {
    constexpr X(): i() { }
    constexpr X(float): i() { }
    constexpr X(bool, X): X(0 ? X() : float{}) {}
      // This delegating constructor was previously treated as non-constexpr
      // because it invokes the generated move constructor which was
      // erroneously marked as non-constexpr for moving a variant data member.
    union { int i; };
  };
  constexpr X<void> x(true, X<void>{});  // Previously an error.  Now okay.

That is now fixed.  The changes for EDGcpfe/20539 in version 5.1 interacted
with this issue in a way that caused apparent regressions (although the
underlying issue was pre-existing); for example, the code above was accepted
in version 5.0 but triggered an error in 5.1.


5/11/20  [EDGcpfe/21748]
Label addresses as the result of folding constant-expressions

The changes of EDGcpfe/20980 (enabling folding of GNU statement expressions)
accidentally accepted attempts to produce labels as results of such folding,
introducing a regression in version 5.1.  For example (in GNU C mode):

  void g(void) {
    void *p = ({ L: &&L; });  // Previously constant-folded.  Now no longer
  }                           // folded.

This resulted in nonsensical IL since the folding operation made the label
declaration itself disappear.  In some configuration, this could result in
aborts.  That issue is now fixed by not folding an expression whose result
would be the address of a label.


5/11/20  [EDGcpfe/20024,EDGcpfe/20274,EDGcpfe/22506]
C++20: Pack expansion in lambda init-capture

The front end now implements pack expansions in lambda-init captures in
C++20 mode.  The feature is also supported in g++ and clang modes when
the language mode is C++11 or later.

  template <class... T> inline void g(T... ts){}
  template <typename... Args> inline void f(Args... args) {
    [...xs=args]{
      g(xs...); // xs is an init-capture pack
    }();
  }
  int main() {
    f();  // OK: xs contains zero init-captures
    f(1); // OK: xs contains one init-capture
    f(1,2); // OK: xs contains two init-captures
  }


5/10/20  [EDGcpfe/22743]
File handle leaked on Windows when using precompiled header files

On Windows, the use of precompiled header files could cause file handles
to leak.  This is not a problem for most configurations as they would
be released when the front end exits, but when using MAKE_FRONT_END_CALLABLE,
this could be more problematic.  Now fixed.


5/8/20   [EDGcpfe/22704]
Abort on attempt to substitute a call producing a complex object

The front end sometimes aborted with an internal error in get_expr_rescan_info
when substituting a call that produces its own enk_temp_init node to hold the
result of the call.  For example:

  template<typename T> struct M {
    template<typename F> auto f(F &&rf) -> decltype(rf(*T::r()));
  };
  template<typename E> struct A { E operator*(); };
  struct C { void operator=(C&&); };
  struct R { static A<C> r(); };
  auto x = M<R>{}.f([](C &&p){ return 42; });

Here, the substitution of *T::r() resulted in an internal error.  That issue
is now fixed.


5/8/20   [EDGcpfe/22732]
C++-generating back end: default member initializers for bit-fields

When emitting the declaration of a bit-field with the "=" form of default
member initializer (a C++20 feature, see EDGcpfe/19998), the C++-generating
back end failed to enclose the expression for the bit-field width in
parentheses, leading to the possibility of incorrect code, with the "=
<value>" being taken as part of the width expression instead of as a
default member initializer.  This is now fixed.  For example, with --c++20:

  constexpr bool b = true;
  struct S {
    int i : (b ? 8 : 16) = 23;  // previously omitted parentheses, attempting
                                // to assign 23 to 16
  };


5/8/20   [EDGcpfe/22729]
GNU compatibility: GCC 10.1.0 builtins

Builtin signatures have been updated to reflect builtins from GCC version
10.1.0.


5/7/20   [EDGcpfe/22728]
C++-generating back end: non-defining static data member declarations

The C++-generating back end incorrectly put out the constexpr and inline
specifiers on the non-defining in-class declaration of a static data
member if they appear on its out-of-class definition.  This is now fixed.
For example, with --c++20:

  struct S {
    static const S s;  // Previously declared "constexpr inline"
    constexpr S(int) { }
  };
  constexpr inline const S S::s(0);


5/6/20   [EDGcpfe/22295]
Builtin helper operators and functions for layout-compatibility checking

The front end has introduced two builtin operators and two builtin functions
to implement some C++20 standard library facilities that enable checking of
layout-compatibility:
  - __builtin_is_layout_compatible(T1, T2):
    T1 and T2 denote types.  This operator produces a true value if and
    only if the given types are layout-compatible.
  - __builtin_is_pointer_interconvertible_base_of(B, D):
    B and D denote types.  If either type is not a non-union class type,
    the result is false.  Otherwise, if the two types are identical,
    the result is true.  Otherwise, the result is true if and only if B
    is an unambiguous nonvirtual base class type of D at offset zero in D.
  - __builtin_is_pointer_interconvertible_with_class(pmd):
    pmd must have pointer-to-member type.  If pmd is a non-null,
    pointer-to-data-member value pointing to a data member at offset zero,
    this builtin pseudo-function produces true.  Otherwise, it produces
    false.
  - __builtin_is_corresponding_member(pmd1, pmd2):
    pmd1 and pmd2 must have pointer-to-member type.  It produces true if
    and only if both arguments are non-null pointer-to-data-members
    referring to members that are in the common initial sequence of
    their respective class types and those members have equal offsets
    within those class types.

The associated standard library facilities were added to C++20 through the
C++ standardization committee's paper P0466R5.
 

5/5/20   [EDGcpfe/22711]
C++-generating back end: disambiguating parentheses in initializers

Under some circumstances, the C++-generating back end could omit parentheses
needed to syntactically disambiguate expressions from types, resulting in
uncompilable generated code.  This is now fixed.  For example:

  struct S { S() { } };
  struct T { T(S &&) {} };
  int main() {
    T a((S()));   // Previously generated as "a(S())", which is an error
  }


5/5/20   [EDGcpfe/22715]
Possible incorrect translation of UTF-8 file names on Windows

On Windows configurations, the use of a file name containing UTF-8 characters
for a file name that is more than 512 characters long could produce an
incorrect result as a result of a bug in the buffer expansion code.  Now
fixed.


5/5/20   [EDGcpfe/22712]
Incorrect disambiguation of enum-base

The front end sometimes did not correctly parse enum-base specifiers because
of a flaw in the grammar disambiguation code.  For example, in GNU C++11 mode:

  int x;
  enum E: __typeof(x) {}; // Previously an error.  Now okay.

This is now fixed.


5/4/20   [EDGcpfe/22680]
Narrowing conversions to bool

The C++ standardization committee's paper P1957R2 classifies conversions from
pointer and pointer-to-member types to type bool as "narrowing".  That means
that the following example is now invalid:

  struct S { int i; };
  bool b = { &S::i; };  // Previously okay.  Now an error because the
                        // conversion is deemed "narrowing".

The front end now enforces this by default.  In Clang C++ mode, the constraint
is enforced when clang_version > 100000, in GNU C++ mode when gnu_version >=
100000, and in Microsoft mode when microsoft_mode >= 1927.


5/4/20   [EDGcpfe/22468]
Core issue 2310: Conversion from a derived class to a base class

The resolution of core issue 2310 clarified that a conversion from a derived
class pointer to a base class pointer requires the derived class to be
complete.  For example:

  struct B {};
  struct D: B {
    static constexpr B *p = (D*)nullptr;  // Now an error in default mode.
  };

Previously, this example was accepted in all modes.  Now, however, it triggers
an error by default because D is not complete at the point of the D*-to-B*
conversion needed for the static data member initializer.  For compatibility
reasons, the previous behavior is preserved in Clang mode, in GNU C++ mode with
gnu_version < 90000, and in Microsoft C++ mode with microsoft_version < 1927.


5/4/20   [EDGcpfe/22471]
Abort on attempt to substitute conditional explicit specifier

In C++20 mode, the front end supports "conditional explicit" specifiers (see
the entry for EDGcpfe/20042 of 10/9/18).  In some cases, such a specifier
requires substitution, but the front end sometimes failed to record the
auxiliary data needed to perform such a substitution, which caused it to
abort with an internal error in get_expr_rescan_info later on.  For example:

  template<typename T, int N = -1> struct S {
    explicit(N != -1) S(T*);
  };
  S s = (int*)0;  // Previously aborted.  Now okay.

That problem is now fixed.


5/3/20   [EDGcpfe/22665]
C++-generating back: missing pack expansion in default template argument

If a default template argument of a member class template was used within
the prototype instantiation of the enclosing class, and the default argument
contained a pack expansion, the pack expansion might not be marked as such.
In the example below, the use of the default template argument of E in f(Q)
did not have the is_parameter_pack field of Ts set.  This resulted in a
missing ellipsis in the code generated by the C++-generating back end.  Now
fixed.  This was introduced by the changes for EDGcpfe/16582 in version 4.11.

  template <typename> struct A;
  template <typename> struct B;
  template <typename> struct C;
  template <typename T, typename... Ts> struct D {
    template <typename Q, typename = typename C<Q(Ts...)>::type> struct E;
    template <typename U, typename V> using F = typename B<V>::type;
    template <typename Q> F<E<typename A<Q>::type>, D> f(Q);
  };


5/3/20   [EDGcpfe/22473]
Microsoft compatibility: __builtin_zero_non_value_bits

The __builtin_zero_non_value_bits builtin function has been added (when
microsoft_version >= 1927).  This builtin function is used to zero padding
bits in a class so that compare-and-exchange operations avoid spurious
failure (see P0528R3).  The builtin takes a pointer to an object and sets
all bits in the object that are not value bits to zero.  


4/30/20  [EDGcpfe/22546]
Interpreter error for floating-point compound assignments

The constexpr interpreter previously did not correctly compute compound
assignments involving two different floating-point types.  For example:

  constexpr float g(float x) {
     return x += 2.0;  // "float += double", previously produced incorrect
  }                    // result.
  static_assert(g(2.0) == 4.0, "");  // Previously failed.  Now okay.

This is now fixed.


4/30/20  [EDGcpfe/22635]
Spurious error on attempt to call friend function with auto return type

The changes for EDGcpfe/18786,EDGcpfe/21191 (see entry of 11/25/19) introduced
a regression in version 6.0 causing the front end to erroneously discard
certain friend function declarations with a deduced ("auto") return type during
call resolution.  For example:

  template<typename> class S {
    friend auto f(S const&) { return 0; }
  };
  template<typename T, typename = decltype(f(T()))> int g(T const &) {
    return 0;
  }
  int r = g(S<int>());  // A spurious error in version 6.0.  Now okay.

That is now fixed.


4/30/20  [EDGcpfe/22679]
Microsoft compatibility: Efficient sized delete for variable sized classes

The changes for P0722R3 (see EDGcpfe/20036) have now been enabled when
microsoft_version >= 1927 when --ms_c++latest is specified.


4/29/20  [EDGcpfe/22692]
Memory corruption after block-extern constexpr function declaration

Consider (in C++17 mode or later):

  constexpr int f() {
    if (static int x = true; true) {  // Error: static not allowed.
       constexpr int f();
    }
    return 1;
  }
  int r = f();

This correctly elicits an error for attempting to declare a static variable in
a constexpr function.  Ordinarily, that causes the interpreter not to permit
interpretation of calls to f().  However, the subsequent block-extern constexpr
declaration of f() accidentally re-enabled the interpretation of the call to
f(), which resulted in memory corruption (usually triggering an abort) when
attempting to handle the initialization of the static variable.  This is now
fixed.


4/29/20  [EDGcpfe/22690]
Microsoft compatibility regression: Constant addresses

Microsoft compilers accept examples like the following:

  template<int*> struct S {};
  S<(int*)42> s;

This was accepted in Microsoft mode by version 5.0 of the front end (and
earlier), but a regression introduced in version 5.1 by the changes for
EDGcpfe/20944 and EDGcpfe/22015 lost that compatibility feature.  This is
now fixed.


4/28/20  [EDGcpfe/22671]
Spurious "incomplete type is not allowed" in friend template declaration

In some situations, the front end issued a spurious "incomplete type is not
allowed" diagnostic while parsing a friend template declaration.  For example:

  template<typename> void g();
  template<unsigned I, typename T>
    auto h(T &&p) -> decltype(g<I>(static_cast<T&&>(p)));
  template<typename T> struct X : T {
    template<unsigned I, typename U >
      friend auto f(X<T> &&p) -> decltype(h<I>(static_cast<U&&>(p)));
          // Previously complained about p having an incomplete type in
  };      // the static_cast expression.  Now accepted.

That regression, introduced in version 5.0 by the changes for EDGcpfe/19506,
is now fixed.


4/28/20  [EDGcpfe/22420]
C++-generating back end: Out-of-order generated specializations after GNU-mode
reference in static data member initializer

In configurations with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to
TRUE, the C++-generating back end could render generated explicit template
specializations out of order when the first reference to such a specialization
appears in a static data member initializer.  For example:

  template <typename> struct S { enum { e = 0 }; };
  template <typename T> struct X {
    static int const N = (int)S<T>::e;
  };
  int main() {
    return X<float>::N;
  }

In GNU C++ mode, the initializer of X<float>::N is not parsed during the
instantiation of X<float> (because GCC delays in-class static data member
initializer instantiations until the member is used) but a little later.  As
a result, the explicit specialization of S<float> appeared after the
definition of X<float>, which resulted in code rendered by the C++-generating
back end somewhat like the following:

  template <typename> struct S { enum { e = 0 }; };
  template <typename T> struct X {
    static int const N = (int)S<T>::e;
  };
  template<> struct X<float> {
    static int const N = (int)S<float>::e;  // Use of S<float>.
  };
  template<> struct S<float> { enum { e = 0 }; };  // Invalid!

That last explicit specialization is invalid since the specialization was
already previously used.  This problem is now fixed by forcing specializations
referenced from deferred in-class static data member initializer instantiations
to be emitted before the data member's parent class.


4/28/20  [EDGcpfe/22674]
Cross-reference output for generic lambda template parameters

The front end previously never output cross-reference information for the
declaration of template parameters of generic lambdas since until C++17 they
were always implicitly declared as part of the processing of "auto" lambda
parameters.  For example:

  int f() { return [](auto){ return 42; }(1); }

In the example above, the template parameter of the lambda's call operator is
implicit, and therefore should not be output in cross-reference information.
However, C++20 permits explicit template parameters for generic lambdas:

  auto lm = []<typename T>() { return 42; };

and those were previously also omitted from the cross-reference output even
though they are explicitly declared.  That is now fixed.


4/27/20  [EDGcpfe/22673]
Microsoft C++/CLI compatibility: assertion failure using managed nullptr type

In C++/CLI mode, the front end aborted with an assertion failure in
temp_init_from_operand_full if the source program creates a temporary of
the managed nullptr type.  This is now fixed.  For example, with --c++cli:

  template<typename T> int f(T&&) { return 0; }
  int i = f(nullptr);   // Previously aborted


4/27/20  [EDGcpfe/8863,EDGcpfe/22666]
Remarks on non-prototype function declarators

C permits function declarators -- known as non-prototype declarators -- that do
not specify the types of the associated parameters.  For example:

  void f();
  void f(a) int a; {}  /* Old-style (non-prototype) definition. */

This feature is also accepted in some C++ modes, but it has never been standard
in C++ and has been "obsolescent" in standard C since C99.  The front end now
issues a remark about such cases, except for the case of a function definition
that was first declared with a prototype.  For example:

  void f1();             /* Triggers a remark. Prefer "void f1(void);". */
  void f2(void (*)());   /* Triggers a remark. */
  void f3(n) int n; {};  /* Triggers a remark. */
  void f4(int n);        /* No remark: Prototype declaration. */
  void f4(n) int n; {}   /* No remark: Previously declared with a prototype. */

This enables functionality similar to GCC's -Wstrict-prototypes option.  The
severity of the remark can be raised to a warning or an error with the
--diag_warning or --diag_error options.


4/27/20  [EDGcpfe/22539]
Regression in constant folding for GNU statement expressions in C mode

The change made for EDGcpfe/21184 inadvertently included C mode when
determining whether a given struct had a trivial copy function.  This
could cause constant folding to occur for GNU statement expressions where it
previously would not have, and in turn caused the wrong C code to be generated
(when using the C-generating back end).  For example:

  struct a {} b,d;
  struct a foo()
  { return ( {b;d;}); } // Previously would generate "return {};"

This is now fixed.


4/27/20  [EDGcpfe/21744]
Incorrect name linkage for explicit specialization of variable template

Variable template instances with const-qualified types are given internal
linkage (although this is expected to changed based on core issue 1713).
The front end made such instances static, but did not set the name
linkage to internal.  This could result in incorrect behavior, such as
the variable incorrectly being put into a COMDAT group.  Now fixed.

  template <class T> inline T x = T();
  template <> inline const short x<int> = 1; 
  int main() {
    return x<int> != 1;
  }


4/27/20  [EDGcpfe/22581]
Multiple translation units: Abort when type exists in three or more TUs

When compiling multiple translation units where a type exists in more than two
translation units, the front end could abort in
f_set_unvisited_trans_unit_corresp.  This has now been fixed.


4/27/20  [EDGcpfe/21552,EDGcpfe/22064,EDGcpfe/22656]
Spurious strict-mode error on member selection of a class being defined

Consider:

  struct S {
    auto f()->int;
    auto f(int)->decltype((*this).f());  // Previously an error in strict
  };                                     // C++11 mode.  Now okay.

This example previously elicited a spurious error in strict C++11 (or later)
mode.  That problem is now fixed.


4/25/20  [EDGcpfe/22294]
Substitution failure involving alias templates and exception specifications

In some cases, the substitution of a noexcept specifier that uses an alias
template that is a member of a class template could produce an incorrect
result.  This occurred in modes where the exception specification is part
of the type (i.e., in most C++17 modes).  Now fixed.

  template <typename... Ts> inline constexpr bool V = true;
  template<typename... Ts> class A;
  template<int _Np, typename _A> struct B;
  template<typename T1, typename... Ts> struct B<0, A<T1, Ts...>> {
    using type = int;
  };
  template<typename... Ts> struct A {
    template<typename U> using C = typename B<0, A>::type;
    template<typename U> A(U&& __t) noexcept(V<C<U&&>, U&&>);
  };
  A<int, char*> f() { return 0; }


4/24/20  [EDGcpfe/22583]
Multiple translation units: Incorrect handling of mismatched default function
declarations

When compiling multiple translation units, the front end would accept routines
that had mismatched default declarations.  For template classes with direct
member initializers, this could cause the defaulted constructor to lose the
field initializers and (when DO_IL_LOWERING is TRUE) cause an abort in
copy_non_static_data_member_initializers_if_necessary.  For example, if a.cpp
contains:

  template<typename T> struct A {
    int var = 0;
    inline A();
  };
  A<int> a;

and b.cpp contains:

  template<typename T> struct A {
    int var = 0;
    inline A() = default;
  };
  A<int> b;

the front end would treat the defaulted A<int>::A() as the definition of
the non-defaulted A<int>::A().  The front end now issues an error that the two
declarations are mismatched.


4/24/20  [EDGcpfe/22419,EDGcpfe/22654,EDGcpfe/22655]
Regression for __is_constructible and __is_destructible

Version 6.0 introduced a regression through the changes for EDGcpfe/21664
causing an error in the following example:

  static_assert(!__is_constructible(int&, void), "");

Specifically, the front end complained about void being an incomplete type.
However, common practice is to accept "void" in that context.  The front end
now accepts such examples again.  Similarly, EDGcpfe/21664 introduced a
regression of __is_destructible applied to incomplete array types causing the
following static assertion to fail:

  static_assert(!__is_destructible(int[]), ");

That, too, is now fixed.


4/24/20  [EDGcpfe/22648]
GNU compatibility: static_cast to pointer to cv-qualified derived class

The changes for EDGcpfe/9593 (see entry of 10/6/09) cause the front end to
emulate a GCC bug in the handling of static_cast when gnu_version >= 30400.
That emulation is now disabled when gnu_version < 40600, which corresponds to
the version where that GCC bug was fixed.  For example:

  struct B { };
  struct D: B { };
  D* g(B* p) {
    return static_cast<const D*>(p);  // Normally an error, but accepted in
  }                                   // some GNU C++ modes.

This example now triggers an error in GNU C++ modes with gnu_version >= 40600.
Previously, it was accepted in such modes.  It is still accepted in GNU C++
modes with gnu_version in the range 30400 to 40599.


4/24/20  [EDGcpfe/19729]
Abort when recursively processing field initializers

When a field initializer references a nested class constructor and that nested
class has fields with field initializers, the front end could abort in various
places, such as "copy_non_static_data_member_initializers_if_necessary" and
"do_constexpr_ctor".  For example:

  struct A {};
  struct B {
    A val = C(); // Previously caused an abort
    struct C {
      union { int x = 37; };
    };
  };

This is now fixed.


4/24/20  [EDGcpfe/21759]
Abort on default argument containing lambda with template parameter list

An abort could occur (at an indeterminate point) as a result of stack
overflow caused by unbounded recursion if a template default argument
contained a generic lambda definition with a C++20 explicit template
parameter list.  Now fixed.

  template <class T> struct C {};
  template < class T = decltype([]<int I>{}) > struct A { } ; 
  A<> a;


4/23/20  [EDGcpfe/22659]
C++-generating back end: explicitly-defaulted functions defined as deleted

In cases where a special member function is explicitly defaulted in the
source but implicitly defined as deleted, the C++-generating back end put
the function definition as "= delete" instead of "= default", as it was in
the original source.  This has now been fixed.  For example, with --c++11:

  struct B {
    B(B&&) = delete;
  };
  struct D : B {
    D(D&&) = default;  // Previously emitted as "= delete"
  };


4/22/20  [EDGcpfe/21592,EDGcpfe/22467]
C++20: constinit

The front end now supports the "constinit" specifier in C++20 modes.  It is
used to enforce static initialization of variables with static or thread
storage duration.  For example:

  constinit int x = 42;   // Okay.
  int f();
  constinit int y = f();  // Error: dynamic initialization.

In GNU C++ modes (even non-C++20 modes), the __constinit keyword is accepted
with similar semantics.


4/21/20  [EDGcpfe/21168]
Weak diagnostic on static/extern mismatch

Consider:

  extern void g(void); 
  static void g(void) {}

Previously this was accepted with a remark in nonstrict modes (because older
compilers accepted it too).  Now, a discretionary error is issued by default,
a warning in Microsoft modes and in GNU C modes with gnu_version < 40000, and
a remark in Cfront and K&R C modes.


4/21/20  [EDGcpfe/22642]
Invalid memory reference on rescan of decltype in non-local generic lambda

During the rescan of a decltype expression in the function type of a generic
lambda that was not declared in a local scope, an invalid scope stack index
could be used in scope_depth_to_allocate_decltype_expr.  This was observed
to sometimes cause an abort in switch_to_scope_region_and_lifetime.  Now
fixed.

  auto f() {
    auto l = [](auto t) -> decltype(t) { return 0; };
    return l;
  }
  auto x = f()(1);


4/21/20  [EDGcpfe/22607]
using-declaration of ambiguous base class member diagnosed only on use

A using-declaration that refers to a member of an ambiguous base class
should not result in an error at the point of the using-declaration,
only at the point at which the use of the base class member would require
a derived-to-base conversion to the ambiguous base class.  Formerly, an
error was incorrectly issued on the using-declaration.  Now fixed.  In
addition, the diagnostic issued on the use now mentions the ambiguous
base class instead of simply saying (for the example below) that D::i
is ambiguous.

  struct A {
    int i;
  };
  struct B : A { };
  struct C : A { };
  struct D : B, C {
    using A::i;  // error formerly issued here
  };
  D d;
  int i = d.i;  // error still issued here (but different error)


4/17/20  [EDGcpfe/22272]
Template rescan treating builtin binary operators as unary

When constant folding is attempted on builtin operators during template
instantiation, the front end was incorrectly treating certain binary operators
as if they were unary operators.  This caused undesirable behavior including
aborts.  For example:

  template <int a> struct b { static const int c = a; };
  class f;
  template <class d> struct g : b<__is_trivially_assignable(f, d)> {};
  class f {
      template <typename e>
          void operator=(e) noexcept(b<__is_nothrow_assignable(int, int)>::c);
  };
  int var = g<f>::c;

This is now fixed.


4/17/20  [EDGcpfe/20436,EDGcpfe/22620]
Spurious error on GNU-mode braced list conversion in template definition

In GNU C++ mode, the front end sometimes issued a spurious error on the
conversion of a braced list to a class type, when that conversion appears
in a template definition and the braced list omits some nested braces.
For example:

  struct A { A() {} };
  struct B { A x, y; };
  struct C { B b; };
  template<typename> struct D {
    D() {
      A a;
      C{a, a};  // Omits the braces for C::b.  Previously a spurious error
    }           // in GNU C++ mode.  Now okay.
  };
  D<int> di;

That issue is now fixed.


4/17/20  [EDGcpfe/22628]
C++-generating back end: pseudo-destructor applied to integer constant

The C++-generating back end generated incorrect code when the source
contains a pseudo-destructor invocation in which the object expression is
an integer literal, producing code that parsed as a user-defined floating
point literal.  This is now fixed.  For example, with --c++20:

  void f() {
    using C = int;
    0 .C::~C();  // Previously generated as "0.C::~C()", where "0.C" is
                 // parsed as a user-defined floating point literal invoking
                 // the (nonexistent) literal operator "C".
  }


4/17/20  [EDGcpfe/22474,EDGcpfe/22623]
Spurious error in substitution failure of default nontype template argument

In some cases, a nondependent nontype template argument for a dependent
nontype parameter could erroneously cause a template substitution failure.
For example:

  template<int> struct A {
    template<typename T> using Type = T;
  };
  template<int N, typename A<N>::template Type<int> = 0> void f() {}
  void g() {
    f<0>();  // Previously failed because the substitution of the default
  }          // argument "0" for the second template parameter of f failed.

This is now fixed.


4/16/20  [EDGcpfe/22408]
Spurious interpreter error after access of array member

In some configurations certain accesses to array members were not handled
correctly by the constexpr interpreter, which in turn could result in spurious
failures to evaluate constant expressions.  For example:

  constexpr int check(bool const *first, bool const *last,
                      bool const& value) {
    for (; first != last; ++first)
       if (*first == value) return 42;
    return 0;
  }
  struct A {
    bool ab[2];
    constexpr bool const* begin() const { return ab; }
    constexpr bool const* end() const { return ab+2; }
  };
  struct S {
    static constexpr A x{{ false, false }};
    static constexpr int b = check(x.begin(), x.end(), true);
             // Evaluation of call to check(...) previously produced a
  };         // spurious error in some configurations.  Now okay.

This is a regression introduced in version 5.1 that is now fixed.


4/16/20  [EDGcpfe/21671,EDGcpfe/22290]
Abort in corresponding_base_class during interpreter evaluation

In some fairly complex cases (arising, e.g., from instantiating certain Boost
templates), the front end could abort with an internal error in
corresponding_base_class (types.c, "base class not found") when interpreting
a conversion to a base class.  That problem is now fixed.


4/16/20  [EDGcpfe/22615]
Clang compatibility: Clang 10.0.0 builtins

Builtin signatures have been updated to reflect builtins from clang version
10.0.0.  Note that some new builtins use the 16-bit __fp16 floating-point
type which is as yet unimplemented in the EDG front end; any attempted
use of those builtins will elicit an error.


4/15/20  [EDGcpfe/22373]
Incorrect substitution of pack in noexcept of member template

In modes where exception specifications are part of the type (i.e., most
C++17 modes) the substitution of a pack expansion in a noexcept specifier
of a member function template could produce an incorrect result.  In the
example below (reduced from a use of g++ 9.1 tuple) U... was substituted
as an empty pack resulting in a pack length mismatch error in the
instantiation of g.  Now fixed.

  template <class... T> struct B {};
  template <class... T> constexpr bool h(T...){return true;}
  template <class ...T> struct A {
    template <class... U> static constexpr bool g() {
      return h(B<T,U>()...);
    }
    template <class... U> static void f(U...) noexcept(g<U...>()){}
  };
  int main() {
    A<int> ai;
    ai.f(1);
  }


4/15/20  [EDGcpfe/19376,EDGcpfe/19754,EDGcpfe/22618]
Abort on invalid template declaration

An abort could occur (in variable_template_declaration) on a template
declaration where the declarator-id was followed by "(;" in configurations
with EXTRA_SOURCE_POSITIONS_IN_IL == TRUE .  Now fixed.

  template <typename T> void f(;


4/14/20  [EDGcpfe/22608]
Spurious deduction failure in C++17 mode with pointer to dependent array

A spurious deduction failure could occur in C++17 mode when a function
template has a parameter that is dependent only because an array bound
uses a template parameter and the parameter is a pointer to the array
type.  Now fixed.

  template <typename... Ts> void f(int (*p)[sizeof ... (Ts)]){}
  int main() {
    f<int>(0);
  }


4/13/20  [EDGcpfe/18507]
Array declarators with embedded lambda expressions

Consider:

  int (*x)[[]{ return 42; }()];  // Now a discretionary error.

Previously this was accepted in C++ modes that accept lambdas.  Now it is a
discretionary error because the standard only permits two consecutive left
brackets to introduce attributes.


4/13/20  [EDGcpfe/22442]
SFINAE failure on substitution of pointer-to-member template argument

Consider:

  template <typename U, typename Signature>
  struct has_member_f {
    template<Signature> struct helper;
    template<typename T> static char check(helper<&T::f>*);  // (1)
    template<typename T> static long check(...);             // (2)
    static const bool value = sizeof(check<U>(0)) == sizeof(char);
  };
  template<typename> struct B { int f(); };
  template<typename T> struct D: B<T> {};
  int x [!has_member_f<D<int>, int (D<int>::*)()>::value];

This example requires substituting &T::f with T == D<int>, which produces a
pointer-to-member constant of type int (B<int>::*)().  However, that is not
a match for helper<&T::f> because Signature == int (D<int>::*)() and a
conversion from int (B<int>::*)() to int (D<int>::*)() is not permitted for
nontype template arguments.  Previously, the front end failed to check that
conversion during SFINAE processing in some non-C++11 modes that enable
C++11-style SFINAE (e.g., some GNU C++03 modes), causing it to select (1)
instead of (2) in this example.  However, during actual instantiation the
erroneous conversion was diagnosed.  That is now fixed.


4/10/20  [EDGcpfe/22516]
Clang compatibility: __builtin_operator_new/__builtin_operator_delete

Previously (see EDGcpfe/16734), __builtin_operator_new and
__builtin_operator_delete were added as builtin operators in clang emulation
modes, and the aliased_routine was used, in some cases, to point to the
appropriate operator new/delete routine as appropriate.  The aliased_routine
mechanism did not work well because that allows only a single alias per
builtin function and these builtins are overloaded so a builtin call may
refer to one function at one call site and another at a subsequent call
site.  Additionally, the call now invokes the appropriate global operator
new/delete directly as appropriate.  For example, with --clang --c++17:

  namespace std {
    typedef decltype(sizeof(0)) size_t;
    enum class align_val_t : size_t;
  }
  void f(std::size_t s) {
    __builtin_operator_delete(__builtin_operator_new(s));
        // Invokes _Znwm and _ZdlPv on IA-64 ABI configs
    __builtin_operator_delete(__builtin_operator_new(s, std::align_val_t(2)),
                              std::align_val_t(2));
        // Invokes _ZnwmSt11align_val_t and _ZdlPvSt11align_val_t
  }


4/8/20   [EDGcpfe/22580]
C++-generating back end: alias declaration in nested class of class template

Consider the following example, compiled with --c++14 --gnu_version=80300:

   template<typename> struct A {
     struct B { };
     struct C {
       using B = typename A::B;
     };
   };

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end previously put out
the alias declaration for A::C::B as

  using B = B;

Although this declaration is correct, since the point of declaration of
the name in an alias declaration is after the type-id, g++ issued a
spurious error when compiling the generated code.  In g++ mode, the
C++-generating back end now uses a qualified name for the type-id in such
alias declarations.


4/7/20   [EDGcpfe/22587]
Ptr_map memory allocation strategy

The Ptr_map template previously always used "general" memory to allocate its
associated hash tables.  Now, a template parameter has been added to control
that allocation.  Furthermore, Ptr_map's attempt to keep a list of previously-
allocated tables for potential reuse has now been removed: It did not work
correctly when the front end was invoked multiple times in configurations with
MAKE_FRONT_END_CALLABLE set to TRUE; doing so resulted in memory corruption
and likely aborts.


4/6/20   [EDGcpfe/22478]
C++-generating back end, clang compatibility: injected-class-name of class
template

Versions of clang before 5.0 did not allow use of the injected-class-name
of a class template as a template template argument, treating it as a type
instead of as a template.  The C++-generating back end has now been updated
to work around this limitation when clang_is_generated_code_target and
clang_target_version_number is less than 50000 by using a qualified name
when a class template name appears as a template template argument within
the scope of the template's injected-class-name.  For example, with --c++14
--clang_version=40000:

  template <template <class> class> struct A;
  template <class> class B {
    B<A<::B>> f();  // Previously always generated as B<A<B>>; now the
                    // qualified form is used for older clang versions
  };


4/5/20   [EDGcpfe/22204]
Pack deduction in expansion that uses enclosing packs

Template argument deduction for a parameter pack did not work properly when
an expansion used both template parameter packs from an enclosing template and
template parameter packs from the current declaration.  This could result in
an internal error (in get_curr_variadic_arg_for_param) or a deduction failure.
Now fixed.

  template<typename ...T> struct A {
    template<T ...N> A(const T (&...p)[N]) { }
  };
  template<typename ...T> struct B {
    template<int ...N> B(const T (&...p)[N]) { }
  };
  int array[10];
  A<int> a(array);  // internal error
  B<int> b(array);  // deduction failure


4/5/20   [EDGcpfe/22582]
C++-generating back end: namespace of friend functions of class templates

In C++-generating back end configurations with
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, the
definition of a friend function defined inside a class template could
sometimes be placed into the wrong namespace in the generated code.  For
example:

  namespace N {
    template<typename> class S {
      friend void f(S) { g(); }
      static void g() { }
    };
  }
  void h() {
    f(N::S<int>());
  }

For this example, the definition of f(<N::S<int>) in the generated code was
previously incorrectly emitted in the global namespace instead of in
namespace N as it should have been.


4/3/20   [EDGcpfe/18674]
Linkage of members of anonymous namespaces

Starting with C++11, members of anonymous namespaces have internal linkage.
The front end now implements this.  In addition, template instantiations where
one or more template arguments have internal linkage now also have internal
linkage (controllable with global variable
"template_linkage_depends_on_instantiation_args").  For example:

  namespace {
    int var; // Now has internal linkage in C++11 modes
    struct S {};
  }
  template<typename> struct X {}; // Has external linkage
  X<S> xs; // X<S> has internal linkage


4/3/20   [EDGcpfe/22457]
Folding initializers for large objects

The front end generally attempts to fold initializers for static-lifetime
variables.  Previously, this required the entire initialized object to be
represented in the constexpr interpreter.  If the initialized object was
larger than the interpreter can handle (by default, 1MB in terms of interpreter
representation), this folding always failed and the initialization was treated
as a dynamic initialization.  Now, if the initializer is already an aggregate
initializer, the front end attempts to fold its dynamic sub-elements, which
may be smaller and therefore representable in the interpreter.  For example,
in GNU C++ mode (to enable folding of reinterpret_cast) when type long has
the size of a pointer:

  struct X {
    X();
    void *p1, *p2;
  };
  unsigned* g() {
    static unsigned table[1000000] = {
      static_cast<unsigned>(
                 reinterpret_cast<long>(&(reinterpret_cast<X*>(0x1234)->p2)))
    };
    return &table[0];
  }

Previously, the initialization of "table" was a dynamic initialization.  Now
it is a static initialization.


4/3/20   [EDGcpfe/22439]
Segfault when converting 128-bit floating-point to long double on some configs

In configurations that use 128-bit floating-point types to represent an
internal host floating-point value, if the target configuration specifies
an 80-bit long double type, but the host long double type is only 64-bits,
a segfault (in conv_host_fp_to_long_double) could occur.  That has now been
fixed, but such a configuration is only allowed when USE_SOFTFLOAT is TRUE
(since the host has no way to convert to an unsupported 80-bit long double).


4/2/20   [EDGcpfe/16268]
Microsoft compatibility: additional encoding-prefix string literal operators

As described in the entries of 2/18/98 and 5/12/04, the front end supports
several Microsoft extensions for producing wide string literals: prefixing
the stringize operator # with L, concatenating L with a function-name token
like __FUNCTION__, and the built-in operator __LPREFIX.  These extensions
have now been expanded to include parallel mechanisms for producing string
literals with the encoding-prefixes U, u, and u8 as both raw and non-raw
strings.  In particular, __uPREFIX, __UPREFIX, and __lPREFIX add the
encoding-prefixes u, U, and u8, respectively, to their string operand; the
concatenation and stringize operations use the encoding-prefixes directly.
For example, with --c++20 --microsoft:

  #define _U(x) U##x
  #define U(x) _U(x)
  #define uR(x) uR#x
  void f() {
    auto a = U(__FUNCTION__);  // equivalent to U"f"
    auto b = uR(xx(abc)xx);    // equivalent to uR"xx(abc)xx", i.e., u"abc"
    auto c = __lPREFIX("z");   // equivalent to u8"z"
  }


4/2/20   [EDGcpfe/22542]
Failure to fold assignment to rvalue

In some cases, the constexpr interpreter failed to fold the result of an
assignment to an rvalue.  For example:

  struct S { int x = 1; };
  constexpr S a = (S() = S());  // Previously an error.  Now okay.

That is now fixed.


4/2/20   [EDGcpfe/22567]
Abort in is_pod_class

In somewhat complex cases, the front end ended up accidentally calling
is_pod_class on a class type generated by lowering (to represent a base class
as a field).  This triggered an abort because such classes do not have an
associated symbol.  That problem is now fixed.


4/2/20   [EDGcpfe/22575]
Spurious error on namespace extension without inline keyword

The C++ standard allows a namespace extension of an inline namespace to
omit the inline keyword.  Previously an error was generated (in strict mode
and a warning otherwise) for this case; now a remark is issued.  For example,
with --c++17:

  inline namespace N {}
  namespace N {}       // previously an error in strict mode; now a remark


4/2/20   [EDGcpfe/20832,EDGcpfe/22458]
Spurious ambiguity error on partial specialization selection

In some cases where a nontype template argument is implicitly converted to the
corresponding parameter's type, the front end failed to select among partial
specializations that are not in fact ambiguous.  For example:

  enum E { e, f };
  template<typename, int N, int = (N == 1 ? f : e)> struct X {};
                      // Default argument implicitly converted from E to int.
  template <typename, typename> struct S {};
  template <typename T, typename U, int R>
     struct S <X<T, R>, X<U, R>> {};  // (1)
  template <typename T, int R> struct S<X<T, R>, X<T, R>> {};  // (2)
  using XD = X<double, -1, 0>;
  S<XD, XD> sxd;  // Previously ambiguous.  Now correctly selects (2).

This is now fixed.


4/1/20   [EDGcpfe/22274]
Internal error on constexpr if in friend of class template

An internal error could occur (in if_statement) when a constexpr if was
used in a friend function of a class template.  Now fixed.

  struct A { };
  template <typename> struct B : A {
    friend void f(B) {
      if constexpr (g() == 1) ;
    }
    constexpr static int g() { return 1; }
  };
  A a;
  B<int> g = static_cast<B<int> &>(a);
  int main() {
    f(g);
  }


3/31/20  [EDGcpfe/22562]
Microsoft compatibility with C++-generating back end: incorrect default
template argument in generated code

In Microsoft mode, when using a C++-generating back end configured with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE,
an incorrect default template argument could be emitted in a generated
explicit specialization of a member template of a class template.  Now fixed.

  template<typename T> struct A {
    template<typename U = T> A() { }
  };
  A<int> ai;


3/31/20  [EDGcpfe/22561]
Constant-evaluation of __builtin_memcmp

The interpreter previously did not correctly evaluate calls to __builtin_memcmp
with operands that point to non-byte-array objects.  For example:

  int const x = 1;
  int const y = 1;
  static_assert(__builtin_memcmp(&x, &y, sizeof(x)) == 0);
    // Previously failed.  Now okay.

That is now fixed.  The interpreter can only fold __builtin_memcmp calls for
operands pointing to constant objects of integral or array-of-integral types
(that is approximately the same constraint as GCC and Clang impose).


3/25/20  [EDGcpfe/22520]
Abort in symbol_for_template_param_unknown_entity_rescan

Certain situations requiring the substitution of a member access expression
for a constant static member previously resulted in an internal error in
symbol_for_template_param_unknown_entity_rescan.  For example:

  struct S { static constexpr int x = 42; };
  constexpr S v;
  template<S const *p = &v, int = p->x> int f();
  int r = f();  // Previously triggered an internal error.

That is now fixed.


3/25/20  [EDGcpfe/21275,EDGcpfe/22515]
Failure to deduce "auto" template parameter

In some cases, the front end failed to deduce a C++17-style "auto" template
parameter when it should have been able to do so.  For example:

  template<typename T, auto = T()+42> int f(T) { return 42; };
  int r = f('x');  // Previously a spurious error.  Now okay.

That is now fixed.


3/25/20  [EDGcpfe/22519]
Abort in variable_this_exists_full on complex lambda use

The front end previously could abort with an internal error in
variable_this_exists_full (overload.c) when a lambda appears in a member
function of a class itself appearing in a default member initializer.

  struct X {
    int x = []() {
              struct N {
                int x;
                int f() { return [=](){ return x; }(); }
                  // Previously triggered an internal error.
              };
              return 42;
            }();
  };

That is now fixed.


3/25/20  [EDGcpfe/22527]
Missing diagnostic on use of template variable in its own initializer

The front end previously failed to diagnose a template variable declared with
a placeholder type and used in its own initializer.  In some configurations,
an abort could ensue.  For example:

  template<typename T> auto &&x = !x<T>;
  bool b = x<int>;  // Previously not diagnosed (sometimes aborted).
                    // Now an error.

That is now fixed.


3/25/20  [EDGcpfe/22464]
Microsoft compatibility: Enable C features with new command-line option

A change has been made to enable certain C11 features when microsoft_version
>= 1927 and a new command-line option, --ms_c11, is specified (similar to
the /std:c11 command-line option for Microsoft Visual Studio).  This change
enables _Alignof, _Alignas, _Noreturn, and restricted pointers.  For example,
this test case is accepted with --ms_c11 --microsoft_version=1927:

  char *restrict rp;
  _Noreturn void f();
  int _Alignas(128) y;
  int x = _Alignof(int);
  struct S { int m; };
  void g() {
      struct S s = (struct S){0};
  }


3/24/20  [EDGcpfe/22351,EDGcpfe/22462]
Defaulted comparison operators

The front end now implements the changes of the C++ standardization committee's
paper P2002R1 regarding the handling of defaulted comparison operators (a C++20
feature; see the entry for EDGcpfe/20014).  Among the effects of this change is
a new diagnostic when declaring a defaulted operator== or operator<=> that
would directly invoke a non-constexpr function.  For example:

  struct S { friend bool operator==(S const&, S const&); };
  struct X: S {
    friend constexpr bool operator==(X const&, X const&) = default;
      // Now an error because the constexpr operator== for X would invoke
      // the non-constexpr operator== for S.
  };


3/24/20  [EDGcpfe/22537]
Invalid code in get_definition_of_class

When GET_DEFINITION_OF_CLASS_NEEDED is TRUE but MICROSOFT_EXTENSIONS_ALLOWED
is FALSE, get_definition_of_class failed to compile.  In addition,
get_definition_of_class mixed checks for MICROSOFT_EXTENSIONS_ALLOWED with
checks for CPPCLI_ENABLING_POSSIBLE.  This has now been fixed.

As part of this change, it was discovered that most code assumed that
CPPCLI_ENABLING_POSSIBLE is TRUE whenever CPPCX_ENABLING_POSSIBLE is TRUE.
This has now been formally made a requirement and it is now an error if
CPPCLI_ENABLING_POSSIBLE is FALSE while CPPCX_ENABLING_POSSIBLE is TRUE.


3/24/20  [EDGcpfe/22536]
GNU/Clang compatibility: Use of "main" as a variable

As a result of the changes for EDGcpfe/17598 (in version 5.1), the use of
"main" as a variable was disallowed in all modes.  That appears to be too
restrictive as all versions of gcc and clang in C mode accept it, as well
as early versions of both compilers in C++ mode.  A change has been made to
more closely emulate that.  For example:

  extern int main;  // warning in GNU/clang C modes
                    // warning in early GNU/clang C++ modes
                    // error in strict C++ mode
                    // discretionary error otherwise


3/23/20  [EDGcpfe/22517]
C++-generating back end: namespace of typedef return type of generated
explicit specializations

As noted in the changes for EDGcpfe/20209 and EDGcpfe/22369, C++-generating
back end configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE
sometimes declare generated function template explicit specializations
using a generated typedef as the return type in order to work around a bug
in MSVC.  In cases where the use of the function template appears in a
different namespace from that of the template itself, this generated
typedef could be incorrectly placed into the namespace where the use occurs
rather than the namespace containing the function template, resulting in
errors compiling the generated code.  This is now fixed.  For example:

  template<typename T, unsigned N> char (*f(T(&)[N]))[N];
  namespace NS {
    char arr[256];
    int i = sizeof(*f(arr));
  }

Previously, the code generated for this example used a generated typedef
for the return type of the explicit specialization for "f", but the
declaration of that typedef appeared in namespace NS while the explicit
specialization itself is a member of the global namespace.  The generated
typedef is now declared in the global namespace as well.


3/23/20  [EDGcpfe/22354,EDGcpfe/22505]
Coroutines: Potentially-inconsistent value category for a parameter-copy
initializer

When a coroutine parameter is an rvalue reference type, the initializer for
the parameter's copy was incorrectly marked as both an lvalue and an xvalue.
This is now fixed.


3/23/20  [EDGcpfe/22437]
C++-generating back end: Abort on attempt to render an exception specification

In configurations with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to
TRUE, the front end could abort while accessing an invalid variant of an
exception specification entry during an attempt to render that exception
specification.  This occurred when the entry had its copy_from_prototype flag
set to TRUE (indicating that the exception specification was never fully
substituted).  That is now fixed (such exception specification are now simply
not rendered).


3/20/20  [EDGcpfe/22502]
Substitution failure with alias template instance in noexcept specifier

In modes in which the exception specification is part of the type (i.e.,
most C++17 modes), a substitution failure could occur when the noexcept
specifier made use of a member alias template instance.  Now fixed.

  struct A { bool operator()(); };
  template<typename Unused> struct B {
    template<typename... T> using C = decltype(A()(T()...));
    template<typename... T> void f(T&& ...) noexcept(noexcept(!C<T ...>())){}
  };
  int main() {
    B<int> b;
    b.f();
  }


3/19/20  [EDGcpfe/22488]
Failure to propagate befriending classes of a function template member of a
nested class

The front end was failing to propagate befriending class information along to
the instantiation of a function template when the function template is a
member of a nested class in a class template.  This could lead to spurious
access failures.  For example:

  template<typename>
  struct X {
    struct Inner {
      template<class T> InnerB(T o, typename T::Q x) {}
    };
  };
  class S {
    using Q = int;
    template<class U> template<class T>
    friend X<U>::Inner::Inner(T, typename T::Q);
  };
  X<int>::Inner s(S(), 2); // Spurious "no matching constructor found" error

This is now fixed.


3/19/20  [EDGcpfe/22490]
Spurious error using an alias template to define a class template member

A spurious error could result if an alias template reference was used as
the qualifier in the definition of a member of a class template.  Now fixed.

  template<typename T, typename U> struct A;
  template<typename T> struct A<T, int> {
    A(int);
  };
  template <typename T> using B = A<T, int>;
  template <typename T> B<T>::A(int) { }


3/19/20  [EDGcpfe/22404]
Coroutines: Allow exceptions to be disabled

Coroutines require that the promise type have an "unhandled_exception" method
and that the function body be wrapped in a try/catch block.  These requirements
are now ignored in modes where exceptions are disabled.


3/19/20  [EDGcpfe/22418]
Operator precedence rules with operator new

The standard does not allow a postfix operator to follow a "new" expression.
For example:

  struct E {
    int x;
  };
  int main() {
    new E()->x = 7;   // Ill-formed according to the standard
    (new E())->x = 7; // Well-formed
  }

Previously the front end only diagnosed this in strict ANSI mode.  Now the
front end will diagnose this as a discretionary error.


3/19/20  [EDGcpfe/19781,EDGcpfe/22052]
Incorrect inheriting constructor template instantiation context scopes

When inheriting constructor templates are being instantiated, the front end was
using the scope of the derived class as the context scope, rather than the
scope of the base class from where the constructor originated.  This could
cause spurious instantiation failures (and therefore cause SFINAE to behave
incorrectly).  For example:

  struct S {};
  template<typename, typename> struct X {};
  template<typename> struct A {
    static constexpr bool val = true;
  };
  template<bool, typename = void> struct B;
  template<typename T> struct B<true, T> { typedef T type; };
  template<typename... T> struct C : S {
    C(const T&...) = delete; // Previously the front end chose this function
    template<typename... U,
             typename = typename B<A<X<T, U>...>::val>::type
            >
    C(U&&...); // Now the front end chooses this function
  };
  struct D : C<S> {
    using C::C;
  };
  void f(S s) {
    D var(s); // Previously an error (calling deleted function), now accepted
  }

This is now fixed.


3/18/20  [EDGcpfe/22298]
Coroutines: Adjust behaviour of implicit try/catch block

C++ Committee document P1971R0 changed how a coroutine's implicit try/catch
block is handled.  The initial suspend point has been moved inside the try
block, and the catch block checks an implicit boolean variable
"initial-await-resume-called" that is initially false and set to true
immediately before the "await-resume" of the initial suspend point.  If
"initial-await-resume-called" is false when an exception is caught, it is
rethrown.  Otherwise, behavior continues as previously defined.


3/18/20  [EDGcpfe/22053]
Missing pack expansion flag on inheriting constructor using declarations

When an inheriting constructor using declaration contains a pack expansion, the
front end was previously failing to record this information.  This could lead
to back end failures where this information was important.  For example, with
the C++-generating back end, the output using declaration was ill-formed as it
was missing the ellipsis.  For example:

  template <class... T> struct S : public T... {
    using T::T...; // C++-generating back end was outputting "using T::T;"
  };

This is now fixed.


3/18/20  [EDGcpfe/22291]
C++-generating back end: missing qualifier on pointer-to-member

When DEFAULT_RECORD_FORM_OF_NAME_REFERENCE is TRUE, the name reference
for a pointer-to-member address constant could be incorrect.  Typically, the
name reference would indicate that no qualifier was present, causing an
invalid pointer-to-member reference to be generated.  Now fixed.

  const bool X = true;
  template <class T> struct S {
    void f() noexcept(X) {}
  };
  void (S<int>::*x)() noexcept(X) = &S<int>::f;


3/17/20  [EDGcpfe/22489]
Update an_encoded_entry_number to use TYPE_FOR_PREFIX_ENTRY_NUMBER as its type

EDGcpfe/11767 introduced the TYPE_FOR_PREFIX_ENTRY_NUMBER configuration macro
to enable greater flexibility; however, in configurations where
ALTERNATE_IL_FILE_FORMAT is TRUE, this flexibility was lost as
an_encoded_entry_number still continued to use a hard-coded type.
an_encoded_entry_number now uses TYPE_FOR_PREFIX_ENTRY_NUMBER as its type to
continue to enable greater flexibility when ALTERNATE_IL_FILE_FORMAT is TRUE.


3/17/20  [EDGcpfe/22476]
Use of uninitialized data during floating-point calculations

In configurations where FP_USE_EMULATION is TRUE, valgrind had detected
an unintended use of uninitialized data in fp_frac_sub on certain operations
on operands of float types.  Now fixed.  For example:

  float f = 1.175494351e-38F;


3/16/20  [EDGcpfe/22484]
Missing diagnostic and/or abort on function template definition via decltype

The front end failed to issue a diagnostic on a function template definition
whose type was obtained using decltype.  In C++17 mode, this could also
result in an abort (in form_exception_specification).  Now fixed.

  int f();
  template <typename> decltype(f) g{};


3/16/20  [EDGcpfe/22055]
C++-generating back end: incorrect generated code for decltype as qualifier

When DEFAULT_RECORD_FORM_OF_NAME_REFERENCE is TRUE, a qualified name
that uses decltype, and which contains more than one level of qualification,
could be incorrectly emitted by the C++-generating back end.  Now fixed.

  struct S {
    struct T {
      static int m;
    };
  };
  S s;
  auto &x = decltype(s)::T::m;


3/16/20  [EDGcpfe/22375]
Partial specialization issue with pack expansions and non-variadic templates

If multiple pack expansions were passed to a non-variadic template (as in the
case of the use of A<Ns..., T...> in C<T>::D below) partial specialization
could produce an incorrect result.  Now fixed.


  template <int I> struct A { };
  template <typename T> using B = int;
  template <int ...T> struct C {
    template<int... Ns> using D = A<Ns..., T...>;
  };
  template <template<int...> class TT, typename = int> struct E;
  template <template<int...> class TT> struct E<TT, B<TT<1>> > {
    using type = int;
  };
  using F = E<C<>::D>::type;


3/15/20  [EDGcpfe/22292]
C++-generating back end: calls via constexpr function pointer/reference

When a constexpr function pointer or reference to a function is
initialized, overload resolution is done to select the appropriate function
for the initialization.  If that constexpr variable is then used in a
function call, however, the C++-generating back end generated the call
using the name of the function with which the constexpr variable is
initialized in place of the variable name, which could lead to overload
resolution failures compiling the generated code.  This has now been fixed,
and the name of the constexpr pointer or reference is preserved in the
generated code.  For example, with --c++14:

  int f(long double);
  float f(unsigned long long);

  constexpr int (*p)(long double) = f;  // Selects f(long double)
  int x = p(1);  // Previously generated as f(1), which is ambiguous


3/15/20  [EDGcpfe/22407]
Matching of template template parameters

A change in version 5.0 (see EDGcpfe/19716) loosened the matching of template
template arguments with their associated template template parameter in g++
and clang modes when not using the new C++17 style matching.  The looser
checking is now done in all modes except Microsoft mode.   In addition, the
clang version check has been changed to >= 30800 (from >= 50000 previously).
The clang version change was made because clang versions 3.8 and newer use
the looser behavior for the builtin template __make_integer_seq, but not for
other cases.  Rather than special-case __make_integer_seq, we expanded the
versions to which the special processing applies.

  template <template <typename U, U...> class S, typename T, T> using MIS = T;
  template <int... _Indexes> struct A { };
  template <int N> struct B {
    template <typename, int... Is>
    using X = A<Is...>;
    // Now accepted in default mode and when clang_version >= 30800 (and, as
    // before, when gnu_version >= 60000)
    using type = MIS<X, int, N>;
  };


3/13/20  [EDGcpfe/17687]
C++17 inheriting constructors

C++ Committee document P0136R1 (adopted in C++17) significantly changes how
inheriting constructors are handled.  This significantly changes both the code
that is accepted by the front end as well as how objects are initialized when
an inheriting constructor is called.  For example:

  struct A { A(int); };
  struct B : A { using A::A; };
  struct V1 : virtual B { using B::B; };
  struct V2 : virtual B { using B::B; };
  struct D2 : V1, V2 {
    using V1::V1;
    using V2::V2;
  };
  D2 d2(0); // Now OK: initializes virtual B base class, which initializes the
            // A base class, then initializes the V1 and V2 base classes as if
            // by a defaulted default constructor

This is now implemented.


3/13/20  [EDGcpfe/22460]
GNU compatibility: Deferred evaluation of default function arguments for
function templates

GCC defers validation of a default function argument for a function template
until it's required, even when the argument is non-dependent.  For example:

  struct X;
  struct A {
    template<class c> A(c &&, X = X()); // Incomplete type error for "X"
  };

This is now accepted in GNU emulation mode.


3/13/20  [EDGcpfe/22297]
Coroutines: Mandate the return type for return_value and return_void to be void

C++ Committee document P1971R0 added the requirement that the coroutine promise
type's "return_value" or "return_void" have a void return type.  This has been
implemented.


3/13/20  [EDGcpfe/22374]
Failure to diagnose extra braced tokens following an in-class definition

In C++11 mode, the front end previously failed to diagnose brace-enclosed
tokens following an in-class constructor definition.  For example:

  struct X {
    X(int i): i(i) {}
    { tokens here }  // Previously accepted.  Now an error.
    int i;
  };

This is now fixed.
  

3/13/20  [EDGcpfe/22452]
GNU C++ compatibility: __is_same

In GNU C++ modes with gnu_version >= 100000 the type traits helper __is_same
is now accepted as a synonym for __is_same_as.  (See the changes of 10/23/19
for EDGcpfe/21327, etc.)


3/13/20  [EDGcpfe/21752]
Spurious error on unevaluated expression in constant contexts

Consider:

  template<typename T> struct Cond {
    static constexpr bool value = (sizeof(T) == 17);
  };
  struct D { ~D(); };
  constexpr bool check(D const&) { return true; }
  template<typename T> constexpr int g() {
    constexpr bool r = Cond<T>::value && check(D());  // Previously an error.
    return 42;                                        // Now okay.
  }
  constexpr int r = g<int>();

Previously, the front produced a spurious error about the initializer for r
not being constant because D() introduces a destructor call.  However, that
call is not necessarily evaluated (depending on T).  That is now fixed.


3/13/20  [EDGcpfe/22451]
Potential memory corruption when compiling multiple source files

In version 6.0, the front end memory allocator was extended to enable freeing
and reusing front end memory allocations.  Unfortunately, the added data
structure added to enable this reuse was not correctly reset when compiling
multiple source files (in configurations with COMPILE_MULTIPLE_SOURCE_FILES
set to TRUE), which could result in memory corruption mostly likely to result
in aborts.  That is now fixed.
 

3/10/20  [EDGcpfe/22054]
C++-generating back end: friend declaration of defaulted function

The C++-generated back end previously included the "= default" notation in
a friend declaration naming a defaulted function.  This is now fixed.  For
example, with --c++11:

  struct S { S() = default; };
  struct T { friend S::S(); };  // Previously included "= default"


3/10/20  [EDGcpfe/19162]
C++/CLI: Internal error checking for missing or incorrect overridden functions

An internal error could occur in C++/CLI mode when checking for missing or
incorrect overridden functions.  For example, an internal error could occur
(in class_qualified_id_lookup) for the test case below.  In addition, an
internal error could occur (in check_quasi_overrides) if a missing or
incorrect override resulted in a warning rather than an error.  These are
now fixed.

  #include <cliext\xhash>
  int main() { return 1; }


3/10/20  [EDGcpfe/22389]
Microsoft compatibility: nested empty macro expansions

When the expansion of a macro invokes another macro that has an empty
expansion and that macro invocation is followed in the expansion by white
space, the front end could sometimes eliminate the white space following
the empty macro expansion, resulting in incorrect token concatenation.
This is now fixed.  For example, with --microsoft -E:

  #define M1() 
  #define M2 M1() y
  -M2  // Previously expanded to "-y", now to "- y"


3/10/20  [EDGcpfe/20641]
Spurious error on lambda capturing "this" for C++/CX ref class

The front end previously emitted a spurious error when a lambda expression
attempts to capture "this" for a ref class.  For example (C++/CX mode):

  ref class R {
    property int i;
    void f() {
      auto a = [=](){ return i; };  // Previously an error.  Now okay.
    }
  };

That problem is now fixed.


3/9/20   [EDGcpfe/19963]
Define _DEFAULT_SOURCE to avoid deprecated warnings for _BSD_SOURCE

In later versions of the GNU headers, _BSD_SOURCE is deprecated, causing
warnings when compiling the front end.  _DEFAULT_SOURCE is now defined in
those cases, eliminating the warning.


3/8/20   [EDGcpfe/22434]
C++-generating back end: scoped enum members of generated explicit
specializations

In C++-generating back end configurations with
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, when
the source contains a class template that defines a member scoped
enumeration, a generated explicit specialization for the template had a
non-defining declaration of the member enumeration inside the class and an
out-of-class definition.  That code is well-formed and accepted by most
compilers, but g++ issues a spurious error for an out-of-class definition
in such cases.  The C++-generating back end has now been changed to emit
the definitions of such member scoped enumerations inside the class
definition when gcc_is_generated_code_target is TRUE.  For example, with
--g++:

  template<typename T> struct S {
    enum class E : unsigned char { zero, one };
    E m;
  };
  void f() {
    S<int> s;
    s.m = S<int>::E::zero;
  }

Previously, the generated code for this example contained the explicit
specialization:

  template<> struct S<int> {
    enum class E : unsigned char;  // Not defined inside class
    E m;
  };
  enum class S<int>::E : unsigned char { zero, one };

In code generated for g++, the scoped enumeration is now defined inside the
class body.


3/7/20   [EDGcpfe/22448]
C++-generating back end: types defined in return statements

The change for EDGcpfe/21366 (in version 6.0) caused a regression in which
the C++-generating back end put out a type defined in a return statement as
a reference to an undeclared temporary name (of the form __T12345678)
instead of the definition of the type.  This is now fixed.  For example,
with --gnu_version=90100 --c++14:

  struct A {
    static inline const A f() {
      return A((unsigned)(__extension__((union { unsigned l; float d; })
                                                 { l: 0x3f800000 }).d));
      // Previously put out with "union __T12345678" instead of definition
    }
    A(unsigned);
  };


3/7/20   [EDGcpfe/22441]
C++-generating back end, g++ compatibility: friend declarations of members of
sibling nested classes

In C++-generating back end configurations in which template definitions are
generated from the prototype instantiation IL and with
DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to FALSE, the change for
EDGcpfe/21785 (in version 6.0) caused a friend declaration naming a sibling
nested class template or member thereof to be put out using an
unnecessarily-qualified name.  The generated code was correct, but it
triggered a g++ bug that resulted in spurious compilation errors.  This has
now been fixed, and the generated code no longer uses the unnecessary name
qualification.  For example:

  template<typename T> struct A {
    template<bool> class B;
    class C;
    };

  template<typename T> class A<T>::C {
    friend class B<false>;
    // Previously named as "A<T>::template B<false>", which g++ rejected
  };


3/6/20   [EDGcpfe/22445]
Memory corruption after call of expr_interpret_expression_operand

The changes for EDGcpfe/21926 (in version 6.0) introduced a regression causing
certain calls to expr_interpret_expression_operand in dependent contexts to
return TRUE without actually producing a constant operand.  That could lead to
memory corruption when subsequent code accessed the (invalid) constant variant
of the operand.  This is now fixed.


3/5/20   [EDGcpfe/22447]
__is_same_as in rescanning contexts

The Changes for EDGcpfe/21327,EDGcpfe/21944,EDGcpfe/21951 introduced support
for GCC's __is_same_as type trait helper, but they failed to handle that
extension in rescanning contexts.  That in turn could lead to internal errors
in rescan_expr_with_substitution_internal.  This is now fixed.


3/4/20   [EDGcpfe/22438]
GNU compatibility: GCC 8.4.0 builtins

Although there are no new builtins in GCC 8.4.0 (from 8.3.0), builtin_defs.h
has been updated to reflect that some builtins are now available when
gnu_version >= 80400 && gnu_version < 90000.


3/3/20   [EDGcpfe/17387,EDGcpfe/21970,EDGcpfe/22117,EDGcpfe/22118]
__is_pod and trivial default constructors

Some tweaks were made to the processes determining whether a defaulted default
constructor is trivial or not.  These changes affect the outcome of the
__is_pod type trait helper, sometimes for better conformance to the standard,
and sometimes for better compatibility with GCC and Clang.  For example:

  struct S1 {
    int i;
    S1() = delete;
  };
  static_assert(__is_pod(S1), "");  // Previously an error in all modes.
                                    // Now accepted in some GCC modes.


2/28/20  [EDGcpfe/15915,EDGcpfe/22427]
Segfault with MAKE_FRONT_END_CALLABLE and digit separators

In configurations with MAKE_FRONT_END_CALLABLE set to TRUE, uses of digit
separators in separate calls to the front end could result in aborts in
remove_digit_separators.  This is now fixed.


2/28/20  [EDGcpfe/22239]
C++20: __builtin_bit_cast (helper builtin operator for std::bit_cast)

The front end now supports a new __builtin_bit_cast builtin operator that
allows libraries to efficiently implement std::bit_cast.  This new builtin
is enabled in clang emulation mode when clang_version >= 90000 and also
in Microsoft emulation mode when microsoft_version >= 1926.


2/28/20  [EDGcpfe/14115,EDGcpfe/22262]
Internal errors on noexcept specifiers in nested contexts

In various somewhat complex situations, the front end could abort due to a
failed assertion check in is_nothrow_type (types.c) when dealing with
function or member function declarations in certain nested contexts (such as
a nested class).  For example:

  struct S {
    struct N {
      int n = f();
      int f() noexcept (false) { return 10 ; }
    };
    N n;  // Previously triggered an internal error.  Now okay.
  };

That is now fixed.


2/28/20  [EDGcpfe/22142]
Support for very large IL files

Until now, the front end has used the ftell and fseek functions to query
and set file positions within IL files, which typically limits the size of
an IL file to 2 GB.  The front end can now be configured to support larger
IL files by setting the new configuration macro LARGE_IL_FILE_SUPPORT to
TRUE.  In that configuration, the front end will use _ftelli64/_fseeki64 on
Windows and ftello/fseeko on other platforms.  (Note that it is typically
also necessary to define _FILE_OFFSET_BITS to 64 in order to configure the
library typedef off_t, used in ftello and fseeko, to be a 64-bit type.)


2/27/20  [EDGcpfe/22397]
Spurious Microsoft C++14-mode error on overload resolution with enum types

Consider:

  struct Q {
    Q(float f);
    operator float();
  };
  double operator-(int, Q);
  enum E : int { e } x;
  auto r = x - e;  // Previously an error in Microsoft C++14 mode.  Now okay.

This example previously triggered an error in Microsoft C++14 mode.  That is
now fixed.


2/27/20  [EDGcpfe/22423]
__func__ in constexpr functions

Previously, the use of __func__ (and similar constructs) in constexpr
functions was only permitted in GNU and Clang C++ modes.  Now it is allowed
in all C++ modes.  (See also the entry for EDGcpfe/19389.)


2/25/20  [EDGcpfe/22400]
C++20: Value of __cplusplus and std_version finalized

With the final approval of the C++20 FDIS at the February meeting of WG21,
the value of __cplusplus for the new revision of the Standard has been set
to 202002L.  The temporary value of 202000 originally adopted by the front
end to represent the C++20 version of the language (see EDGcpfe/20000) has
now been updated accordingly.  For example, with --c++20:

  long l = __cplusplus;  // Now sets l to 202002L


2/25/20  [EDGcpfe/22406]
C++-generating back end: generated variable template explicit specializations

In C++-generating back end configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE,
generated explicit specializations representing implicit instantiations of
variable templates were put out without a template argument list.  This is
now fixed.  For example, with --c++14, the generated code for

  template<typename T> bool x = false;
  bool y = x<int>;

previously contained the erroneous explicit specialization

  template<> bool x = false;

and now correctly contains

  template<> bool x<int> = false;


2/24/20  [EDGcpfe/22394]
GNU compatibility: GCC 7.5.0 builtins

Although there were no new builtins introduced in GCC 7.5.0, some builtins
were enabled only through gnu_version 70400 and have now been extended to
70500.


2/24/20  [EDGcpfe/22036,EDGcpfe/22310]
GNU/clang compatibility: spurious error with noexcept(true) function template

A spurious error could result in g++ and clang mode when taking the address
of an instance of a noexcept(true) function template using it as a
noexcept(false) value, or explicitly instantiating a noexcept(true) function
template without marking the explicit instantiation as noexcept(true).  Now
fixed.
 
  template <class T> void f(void) noexcept(true) { }
  void (&r)() = f<int>;


2/23/20  [EDGcpfe/22223]
Spurious error on definition of nested inline namespace member

A spurious error could occur on the definition of a namespace member that
is declared in more then one inline namespace level.  Now fixed.

  namespace A {
    inline namespace B {
      inline namespace C {
        void f();
      }
    }
  }
  void A::f() {}  // error: namespace "A" has no actual member "f"


2/23/20  [EDGcpfe/22283]
Incorrect behavior with generic lambda defined in template contexts

A spurious error, or internal error, could result in some cases when a
generic lambda is defined in a template declaration or a class template
prototype instantiation context.  Now fixed.

  template <class T> struct A {
    static constexpr int I = [](auto x) -> int {return 0; }(1);
  };
  A<int> ai;


2/21/20  [EDGcpfe/20194,EDGcpfe/22386]
Using references with constant-address initializers

Consider:

  int gi = 42;
  struct S {
    constexpr static volatile int &mri = gi;
  };
  int  main() {
    return S::mri;
  }

Prior to C++17, the in-class declaration of S::mri was not considered a
definition.  The standard does not actually require a definition to exist for
the use of S::mri in main().  However, the changes for EDGcpfe/18834 (see entry
of 10/3/17) introduced a regression in version 5.0 of the front causing it to
require a definition for that reference.  That in turn caused the example above
to result in a linker error in C++11 or C++14 modes (because S::mri is
undefined).  This regression is now fixed.


2/20/20  [EDGcpfe/17750,EDGcpfe/22385]
Incorrect folding of type_info address comparison

Consider:

  #include <typeinfo>
  enum class E {} e;
  std::type_info const &rti1 = typeid(e);
  std::type_info const &rti2 = typeid(E);
  static_assert(&rti1 == &rti2);  // Previously failed.

The front end previously did not correctly fold the comparison of type_info
addresses in this example, causing the static_assert to fail.  That is now
fixed.  (This is a regression introduced by the changes for EDGcpfe/17054 in
version 4.12.)


2/20/20  [EDGcpfe/21784,EDGcpfe/22120]
Class types not always correctly classified as literal/non-literal

The front end sometimes did not correctly determine whether a class type is a
literal type or not.  For example:

  struct D { ~D() {}; };  // Not a literal type (non-constexpr destructor).
  struct S { union { D m; }; };  // Not a literal type (member with non-
                                 // literal type).
  static_assert(!__is_literal_type(S), "");
     // Previously failed.  Now okay.

That is now fixed.


2/20/20  [EDGcpfe/22211]
Clang compatibility: Inline namespaces and explicit specializations

A change made in 4.13 (see EDGcpfe/17520) altered the lookup of inline
namespace members.  That change was not correct and the underlying issue
actually concerned explicit specializations.  In the example in EDGcpfe/17520,
clang does not reopen the inl1 namespace when processing the explicit
specialization.  We now emulate this behavior in clang mode.  The original
change we made caused examples like the one below to be handled incorrectly.
This example resulted in a spurious ambiguity on the call of f.  Now fixed.

  namespace N {
    inline namespace M { void f(){} }
    inline namespace O {
      void f(){}
      void g() {
        f(); // spurious ambiguity
      }
    }
  }


2/20/20  [EDGcpfe/19901]
Clang C++ compatibility: Conversion from pointer to _Atomic to void*

In Clang C++ mode, the front end now permits (with a warning) implicit
conversions from _Atomic-qualified pointers to void*.  For example:

  _Atomic(int) *p;
  void *q = p;  // Now accepted in Clang C++ mode (previously an error).


2/19/20  [EDGcpfe/22369]
C++-generating back end, Microsoft compatibility: generated explicit
specializations returning indirect reference or pointer to function or array

EDGcpfe/20209 described an issue in which a generated explicit
specialization for a function template whose return type is a pointer or
reference to a function or array type triggered an MSVC bug that caused
spurious errors compiling the code generated by the C++-generating back
end.  That problem also occurs when the return type is multi-level, e.g., a
pointer or reference to a pointer to a function type.  This is now fixed.
For example, when the front end is configured with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE and
msvc_is_generated_code_target is TRUE, with --c++11
--microsoft_version=1900:

  template<typename T> T* &&f();
  void g() {
    f<void()>();
  }

The generated code previously contained the explicit specialization,

  template<> void (*&&f<void (void)> ())(void);

which triggered the MSVC bug.  Now the generated code uses a typedef for
the return type:

  typedef void (*&&__T12345678)(void);
  template<> __T12345678 f<void (void)>();

which MSVC accepts without error.


2/17/20  [EDGcpfe/22043]
C++-generating back end: fold-expressions involving explicit temporaries

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end unnecessarily
parenthesized explicit temporaries appearing as operands in
fold-expressions, resulting in incorrect generated code in some cases.
This is now fixed.  For example:

  template <class... T> int f (T... ts) {
    return (T() + ... );  // Previously generated as "(T()) + ...", which is
                          // invalid, as "(T())" looks like the start of a
                          // cast to a function type and is a syntax error.
  }


2/14/20  [EDGcpfe/22342]
Incorrect variant of a_symbol used

A projection symbol created for a conversion function in a base class
(in check_base_class_conversion_list) could have the incorrect value set for
a_symbol::variant.projection.any_intervening_using_decl due to an incorrect
variant being used when setting that flag.  Now fixed.


2/11/20  [EDGcpfe/22334]
Assertion failure in debug_exit: "stop tokens set checksum is incorrect"

The alloc_literal_operator_header had a db_enter macro invocation but no
matching db_exit macro invocation.  That had caused an assertion failure
in debug_exit when debug_level > 0 in some cases.  For example, with
-d1 --g++ --gnu_version=80300 --c++14:

  void operator""s(const char*, __EDG_SIZE_TYPE__);


2/11/20  [EDGcpfe/22322]
Infinite loop in multi-translation unit mode

When using multi-translation unit mode with C source code in GNU emulation
mode, code that triggers an ec_bad_linkage_of_ref_within_inline_function
warning could then cause the front end to loop indefinitely.  For example,
when invoked with two other empty files and --gcc --gnu_version 50000:

  static void f(void) {}
  inline void g(void) {
    f();
  }


2/6/20   [EDGcpfe/22230]
C++-generating back end: decltype-specifier using out-of-scope local class

In C++-generating back end configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, under some
complex conditions a decltype-specifier could be emitted that referred to a
local class of a function outside that function's body.  This is now fixed.


2/6/20   [EDGcpfe/22303]
Spurious "pack not at end" for template parameter that uses pack expansion

If a template parameter pack was declared using an expansion of an enclosing
pack, and that was followed by another template parameter, a spurious error
could result.  Now fixed.

  template <typename ... T> struct A {
    template <T ..., typename U> struct B {};
  };
  A<int> ai;


2/6/20   [EDGcpfe/22301]
Microsoft compatibility: nested namespace alias in a namespace extension

The C++ standard prohibits using a namespace-alias in a namespace extension,
but the front end allows it in Microsoft emulation mode.  In the case where
a nested namespace is used as a namespace-alias, spurious errors could occur,
e.g., (with --microsoft_version 1300 --c++11):

  namespace N1 {
    using T = int;
    namespace N2 {}
  }
  namespace N = N1::N2;
  namespace N {
    T f();      // Spurious error because N1::T had not been found.
  }

This is now fixed.  Additionally, the use of a nested namespace alias to extend
a namespace has been limited to microsoft_version < 1400 to mimic the behavior
of Visual Studio.


2/6/20   [EDGcpfe/22018,EDGcpfe/22131,EDGcpfe/22299]
Abort on nontype template parameter substitution with dependent type

In somewhat complex cases involving a member template with a nontype template
parameter whose type depends on a previous template parameter, the front end
aborted due to an assertion failure in get_expr_rescan_info.  For example:

  template<bool> struct B;
  template<typename> struct E {};
  struct S { template<typename> static bool sf(); };
  struct X {
    template<typename T, typename B<S::sf<T>()>::Type = true> X(E<T>);
    template<typename T> void operator=(E<T>);
  };
  X g();
  E<int> ei;
  int main() { g() = ei; }

In this example, the problem occurred during the substitution of the type of
the second template parameter for the constructor template of X.  This problem
is now fixed.


2/6/20   [EDGcpfe/22300]
Uninitialized a_class_type_supplement::defined_in_field_initializer

The changes for EDGcpfe/21195 (in version 5.1) made the field
a_class_type_supplement::defined_in_field_initializer unconditional (previously
it had been conditionally compiled with NEED_NAME_MANGLING).  Unfortunately,
the initialization for the field was still conditionally compiled so it could
be uninitialized in configurations where NEED_NAME_MANGLING is FALSE.


2/5/20   [EDGcpfe/20900]
Spurious "too few arguments" for template argument to pack expansion

A spurious "too few arguments" message could be issued for a template
argument list to a template parameter list that was the result of a
pack expansion.  Now fixed.

  template <class T, typename... Us> struct A {
    template <Us...> struct B {};
  };
  int main() {
    A<int, int, int>::B<1, 2> ab;
  }


2/5/20   [EDGcpfe/22289]
Incorrect template parameter position for empty pack expansion

When a template parameter is declared using a pack expansion the parameter
that is created is given an incorrect position when the pack expansion
is empty.  Now fixed.

  int g(...);
  template <typename ...T> struct A {
    template <T... X> static decltype(g(X...)) f();
  };
  auto x = A<>::f<>(); // Template parameter X has incorrect position


2/4/20   [EDGcpfe/22221]
C++-generating back end: __make_integer_seq incorrectly named

The C++-generating back end sometimes put out a reference to the builtin
alias template __make_integer_seq using an internal name,
__make_integer_seq_alias, resulting in errors when compiling the generated
code.  This has now been fixed.  For example, with --clang_version=90000:

  namespace std {
  template<typename _Tp, _Tp... _Idx> struct integer_sequence {
    typedef _Tp value_type; 
  };
  }

  void f() {
    typedef __make_integer_seq<std::integer_sequence, int, 100> s;
    // Previously generated as __make_integer_seq_alias<...
  }


2/4/20   [EDGcpfe/22246]
C++-generating back end: explicit specializations of function templates whose
return type uses a dependent decltype-specifier

The entry for EDGcpfe/21621 describes an MSVC bug that affected the output
of the C++-generating back end in configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE.
Briefly, versions of MSVC before 1915 could not match a generated explicit
specialization with its corresponding function template when the return
type of the function template is a dependent decltype-specifier.  It now
appears that that MSVC bug is more general, affecting function templates in
which a dependent decltype-specifier is used anywhere within the function
return type, such as within a template argument.  The C++-generating back
end has now been modified to suppress all such explicit specializations
when msvc_is_generated_code_target is TRUE and msvc_target_version_number
is less than 1915.  For example, with --microsoft
--msvc_target_version=1914:

  template <typename> struct A {
    using an_int_t = int;
  };
  template <typename> struct B {};
  template <typename T> using I = typename A<T>::an_int_t;
  template <typename T> auto f(T t) -> B<B<I<decltype(t)>>>;
  void g() {
    f(0);
  }


2/4/20   [EDGcpfe/21241]
Spurious Microsoft-mode error on variadic default member initializers

Consider:

  template<typename ... Ts> struct X {
    int szs[sizeof...(Ts)] = { sizeof(Ts)... };  // Previously a spurious
  };                                             // error in Microsoft modes.
  X<int, short> xis;

Previously, the instantiation of the default member initializer triggered an
error in Microsoft modes (complaining that a "}" was expected instead of the
ellipsis "...").  That is now fixed.


2/4/20   [EDGcpfe/22273]
C++-generating back end: missing definition of nested class template

In C++-generating back end configurations in which
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, when the
source contains a class template in which an instance of a nested class
template is used as the type of a member of the outer template, the
generated code could contain an explicit specialization of the outer class
template in which the nested class template was only declared, not defined,
resulting in errors when the generated code was compiled.  This is now fixed.
For example, given

  template<typename T> struct O {
    template<typename U> struct I { };
    I<T> it;
  };
  O<int> oi;

when compiled with --g++ the generated code previously contained the
explicit specialization

  template<> struct O<int> {
    template<class U> struct I;
    I<int> it;   // Error: incomplete type
  };

Such explicit specializations are now suppressed because the required
explicit specialization for O<int>::I<int> would need to appear inside the
explicit specialization for O<int>, which is not permitted in standard C++.


2/3/20   [EDGcpfe/21029]
Spurious error on use of local reference in constant-expression context

In strict mode, the front end previously sometimes failed to evaluate valid
constant-expressions that refer to local references.  For example:

  int arr[2] = { 1,2 };
  void g() {
    auto &[ x, y ] = arr;
    static_assert (&x == &arr[0]);  // Previously an error.  Now okay.
  }

That problem is now fixed.


2/3/20   [EDGcpfe/21030]
Spurious error on by-reference captures in constant-expression contexts

The front end previously emitted spurious errors when a lambda in a constant-
expression context captured a variable outside that context by reference.
For example:

  bool f() {
    int i;
    constexpr bool r = [&]{ return &i; }() == &i;  // Previously an error.
    return r;                                      // Now okay.
  }

That is now fixed.


2/3/20   [EDGcpfe/22277]
Incorrect lookup of potential type-specifier in template instantiation

In the definition of C::f a "tentative type" lookup is done to determine
whether A is a type name.  When this lookup was done in a template
instantiation context of a class member, a type name from the context enclosing
the class could incorrectly be found (i.e., the global scope A was found)
resulting in incorrect behavior or spurious errors.  Now fixed.

  struct A {
    A();
  };
  struct B {
    int i;
    inline int& A() {return i; }
  };
  struct C : public B {
    template <typename T> void f(const T&) { A() = 0; }
  };
  int main() {
    C c;
    c.f(1);
  }


1/31/20  [EDGcpfe/22278]
Incorrect return value for constexpr __builtin_memcmp and other builtins

The implementation of __builtin_memcmp in the interpreter was flawed and
would sometimes silently return an incorrect return value if one or more of
the first arguments were not array types.  For example, with --gnu_ver 80000

  const int x = 1;
  const int y = 0;
  static_assert(__builtin_memcmp(&x, &y, sizeof(x)) == 1);

Other constexpr builtins (strcmp/memcmp/wcscmp/wcsncmp/wmemcmp/strncmp) were
also affected and are now fixed.


1/31/20  [EDGcpfe/21190]
Missing diagnostic on const inline static members

The front end previously failed to diagnose a missing initializer on a case
like the following:

  struct S {
    static inline int const ic;  // Previously undiagnosed.  Now an error
  };                             // (missing initializer).

That is now fixed.


1/31/20  [EDGcpfe/22276]
Potential reference through uninitialized pointer

The alloc_gcc_pragma_options_entry function returns a pointer to an
a_gcc_pragma_options_entry data structure, but the "next" pointer in that
data structure is not initialized, potentially leading to undefined behavior.
This issue could appear during processing of the "GCC" #pragma.


1/30/20  [EDGcpfe/22271]
Missing "else" in code intended to be "} else if"

In three front end source files (declarator.c, interpret.c, and overload.c),
a pattern of the form:

  if (cond1) {
    ...
  } if (cond2) {
    ...

occurred.  In all cases, an "else" was missing following the closing brace.
That is now fixed.


1/27/20  [EDGcpfe/22148]
Invalid pointer access via scan_expression_list_context_expr

Calls to scan_expression_list_context_expr could previously (in some
difficult-to-characterize situations) result in accessing an invalid pointer
value.  That is now fixed.  (The problem was discovered by running valgrind on
the front end processing the Ranges-v3 source code.)


1/24/20  [EDGcpfe/22091]
Failure to apply copy elision with the conditional operator

The front end was failing to apply copy elision in applicable modes such as
C++17 (guaranteed copy elision) when an operand to the conditional operator
contained the comma operator.  This could lead to spurious errors in cases
where calling the copy/move constructor would result in an error.  For example:

  struct S
  {
    S(int);
    S(S&& param)=delete;
  };
  void func(bool test)
  {
    test ? (S(1)) : (1,S(2)); // Spurious "call to deleted move ctor" error
  }

This is now fixed.


1/24/20  [EDGcpfe/22236]
Warnings for suspect uses of std::is_constant_evaluated()

The front end now warns about various uses of std::is_constant_evaluated() that
seem suspect because the value can be determined at the point of call.  For
example:

  constexpr int f(int x) {
    if constexpr (std::is_constant_evaluated()) {  // Always true!  Now
      return x;                                    // elicits a warning.
    } else {
      return 0;
    }
  }

(The intrinsic __builtin_is_constant_evaluated() is handled similarly.)


1/24/20  [EDGcpfe/22116]
Spurious "unexpected designator" error in class template assignment

When a braced-initializer containing designated initializers is used to
initialize a template-dependent type, the front end would issue a spurious
"unexpected designator" error while parsing the prototype template.  This
also affected non-dependent types in gnu versions earlier than 70200, as
these types are treated as dependent in expression contexts.  For example:

  struct Foo { int a; };
  template<typename T> struct Bar {
      T baz;
      T fun() { return this->baz = { .a = 42 }; } // Spurious error here
  };
  int main(){
      Bar<Foo> *b = new Bar<Foo>();
      b->fun();
  }

This is now fixed.


1/24/20  [EDGcpfe/22096,EDGcpfe/22237]
Spurious incomplete type error on explicit specialization of variable template

A spurious incomplete type error could be issued on an explicit specialization
of a variable template if the type instantiated based on the template
definition would have had an incomplete type.  Now fixed.

  template <typename T> struct X;
  template <typename T, typename = void> constexpr X<T> V;
  template<> constexpr int V<int> = 1;
  int main() {
    return V<int>;
  }


1/24/20  [EDGcpfe/22152]
Assertion failure on use of injected class name as template argument

A change made in version 5.1 added an incorrect assertion check that would
produce a spurious internal error (in equiv_template_arg_lists) on some
uses of an injected class name as a template argument.  Now fixed.

  template <typename> struct A {
    static const bool value = true;
  };
  template <typename T> T&& f();
  template <typename T> struct C {
    template<typename U, typename = A<decltype(f<C>() + f<U>())>> void g();
  };


1/24/20  [EDGcpfe/20420,EDGcpfe/21576]
GNU C++ compatibility: spurious substitution failure substituting template
argument list in parent type

In some complex situations involving a nested substitution of a template
argument list under a parent type, a spurious substitution failure could
occur in g++ and clang modes.  Now fixed.

  template <class T> struct A {};
  template<bool b> struct B { static constexpr bool v = b; };
  typedef B<true> true_type;
  typedef B<false> false_type;
  template<bool, typename T = void> struct E { };
  template<typename T> struct E<true, T> { typedef T t; };
  template<typename, typename> struct H { static constexpr bool v = true; };
  template <typename T> struct C{using t = T;};
  template <typename T> struct C<A<T>>{using t = T;};
  struct G {int v;};
  struct F { template <typename T> using ftype = false_type; };
  template <typename T> using D = C<T>;
  template <typename Q, typename T> using U = typename Q::template ftype<T>;
  template <typename Q, typename T> using S = U<Q, typename D<T>::t>;
  template <typename Q, typename T, typename = void> struct I{};
  template <typename Q, typename T>
  struct I<Q, T, typename E<!S<Q, T>::v>::t> {
    using t = G;
  };
  bool b = H<I<F, int>::t, G>::v;



1/24/20  [EDGcpfe/22247]
Remove duplicate enumerators for __builtin_is_constant_evaluated

There had been separate enumerators for the __builtin_is_constant_evaluated
builtin function (bfk_is_constant_evaluated and bufk_is_constant_evaluated).
The front end now uses the former and maintains the latter for backward
compatibility (though now the two values are the same so either can be used).


1/24/20  [EDGcpfe/22241,EDGcpfe/22242]
Microsoft compatibility: Enable Visual Studio 16.6 features

Two features that are supported by Microsoft Visual Studio 16.6 are now
enabled when microsoft_version >= 1926.  In C mode, _Generic (see
EDGcpfe/14743) is now enabled, and in C++ mode, with --ms_c++latest or
--ms_c++20, immediate functions (see EDGcpfe/20550) are now enabled.


1/23/20  [EDGcpfe/21590]
C++20: asm-declarations in constexpr functions

In C++20 mode, the front end now accepts asm-declarations in constexpr
functions.  Such declarations cannot be evaluated as part of constant
expressions, however.  For example:

  constexpr int f() {
    return 42;
    asm ("");
  }
  static_assert(f() == 42);  // Now okay in C++20 mode.

This change was introduced in the working paper for C++20 by the C++
standardization committee's paper P1668R1.  The predefined macro
__cpp_constexpr now has the value 201907L in C++20 mode to reflect that this
feature and the changes for EDGcpfe/21581 etc. are now implemented.


1/23/20  [EDGcpfe/21581,EDGcpfe/22234,EDGcpfe/22240]
C++20: Uninitialized local variables in constexpr functions

The changes for EDGcpfe/17158, which permitted uninitialized local variables of
empty class types in constexpr function definitions, have now been enabled in
all nonstrict C++14 modes and in all C++20 modes.  For example:

  struct S {};
  constexpr void g() {
    S s;  // Now accepted in all nonstrict C++14 modes.
  }       // Previously only accepted in GNU and Clang C++14 modes.

Furthermore, in C++20 mode, this is now generalized for all types and the
rules introduced by the standardization committee's P1331R2 are enabled.
For example:

  struct X { int i; };
  constexpr X h() {
    X x, y = {42};
    x = y;
    return x;
  }
  static_assert(h().i == 42);  // Now accepted in C++20 mode.


1/22/20  [EDGcpfe/22229]
C++-generating back end: use of dependent alias template from invalid scope

In some obscure cases, the output of the C++-generating back end could use
an instance of an alias template defined in one class template to represent
a dependent type appearing in the definition of an unrelated class
template.  Depending on the characteristics of the alias template, this
could lead in some cases to errors when compiling the generated code.  This
is now fixed.


1/22/20  [EDGcpfe/22235]
Build error with !TARG_CASE_SENSITIVE_EXTERNAL_NAMES

The change to accommodate const correctness for string literals (see
EDGcpfe/10662, part of version 4.8) overlooked a necessary edit in
find_external_symbol (symbol_tbl.c), resulting in a build error when
TARG_CASE_SENSITIVE_EXTERNAL_NAMES is FALSE.  This is now fixed.


1/21/20  [EDGcpfe/21207,EDGcpfe/21623]
GNU compatibility: __builtin_has_attribute

The GNU __builtin_has_attribute builtin function has been implemented.  Its
first argument is a type-or-expression (similar to sizeof) and its second
argument is an attribute (with optional attribute arguments).  For example,
with --gcc --gnu_version 90000:

  __attribute__ ((aligned (8))) int x;
  _Static_assert (__builtin_has_attribute (x, aligned), "aligned");
  _Static_assert (__builtin_has_attribute (x, aligned (8)), "aligned (8)");
  _Static_assert (!__builtin_has_attribute (x, aligned (4)), "aligned (4)");


1/20/20  [EDGcpfe/22226]
Incorrect inlining of asm statements

Inlining of calls within asm statements had, in some cases, resulted in
replacement of the asm statement with the inlined call itself.  Now fixed.
For example:

  inline int f() { return 0; }
  void g() {
    asm volatile ("foo %0, %1;" :: "n"(f()), "n"(1) : "memory");
  }


1/17/20  [EDGcpfe/22151]
GNU-mode regression on type of conditional operator

Consider:

  struct X { X(); };
  X const xc;
  void f(bool b) {
    X&& x(b ? throw : xc);  // Previously accepted in GNU mode.
  }                         // Now an error (qualifiers are dropped).

This code is invalid because the initializer for x has a const type, but x is
a reference-to-non-const type.  However, the changes for EDGcpfe/20526 caused
this to be accepted in GNU C++ modes (i.e., a regression in version 5.1).  That
is now fixed.


1/17/20  [EDGcpfe/22083]
GNU compatibility: template dependent arguments to __builtin_assume_aligned

A spurious error had been given when a dependent type was used as the third
argument to __builtin_assume_aligned.  Now fixed.  For example (with -tused
--gnu_version 70300):

  template <typename T> void f(T *p, T align) {
    __builtin_assume_aligned(p, align, align);
  }
  void bar(long *p, long align) {
    f(p, align);
  }


1/16/20  [EDGcpfe/22210]
Multiple translation units: Failure to update canonical entry for enumerators
in a nested enumeration

The fix for EDGcpfe/21866 did not go far enough; while the enumerations were
having the correct canonical entry applied, the enumerators contained therein
were not.  This caused an abort in configurations that have
IL_SHOULD_BE_WRITTEN_TO_FILE set and compiling multiple translation units when
both the primary and a secondary TU contain instantiations of the class
template and usages of the enumerator, and the secondary TU contains an
independent usage of the enumerator (and therefore the secondary TU had its own
instantiation of the enumeration).  For example, if t.h contains:

  template<typename>
  struct A {
    enum class ENUM { e1 };
    A(int);
    void func();
    virtual void vfunc();
  };
  struct B {
    A<int> arr[1] { 0 };
  };
  template<typename T>
  void A<T>::func() {
    ENUM::e1;
  }
  template<typename T>
  void A<T>::vfunc() {
    ENUM::e1;
  }

and a.cpp #includes t.h while b.cpp contains:

  #include "t.h"
  void func() {
    B().arr[0].func(); // Abort/potential segfault triggered here
  }

the front end would abort in 'read_memory_region'.  Also note that if
IL_SHOULD_BE_WRITTEN_TO_FILE is FALSE, the front end may have accessed invalid
memory and segfaulted.  This is now fixed.


1/16/20  [EDGcpfe/22196]
Interpreter aborts processing constants in templates

Under some circumstances, the front end could abort attempting to process
constants appearing in templates.  For example, in Clang C++14 mode:

  template<typename T> struct B {
    constexpr B(char const *p): p{p} {}
    char const *p;
  };
  template<typename T> struct D : B<T> {
    constexpr D(const char* p) noexcept : B<T>(p) {}
  };
  template<typename> struct X  {
    D<char> g()  { return x; }  // Previously aborted in interpreter.
    static constexpr D<char> x{D<char>("xyz")};
  };

This example previously aborted in some configurations where the interpreter
attempted to load the value of X::x, because that representation has an
inconsistent type due to the inability to precisely check types in templates
(in this case a ck_aggregate constant has an element that has the same type
as the aggregate).  This problem is now fixed.


1/16/20  [EDGcpfe/22205]
Spurious error with variable defined with class-template argument deduction

Consider (in C++17 mode):

  template<typename = int> struct X { };
  template<typename T> void g(T t) {}
  int main() {
    X x;   // Class-template argument deduction with no initializer.
    g(x);  // Previously a spurious error.  Now okay.
  }

The variable x is defined with type X<int>, relying on class-template argument
deduction to deduce the <int> argument.  In cases like these, where no actual
initializer appears in the variable definition, the front end did not correctly
determine that the deduction was completed, and later uses -- such as in the
call g(x) -- produced spurious errors claiming the variable cannot be used in
its own initializer.  That is now fixed.


1/14/20  [EDGcpfe/20839]
Diagnose invalid attributes in more cases

Changes have been made to diagnose invalid attributes in more cases.
For example (with --c++20):

  typedef void (*fp)([[no_unique_address]] void);     // Now an error.
  template <int I [[no_unique_address]]> struct A {}; // Now an error.


1/10/20  [EDGcpfe/21192]
Unused inline variables

The front end previously issued a spurious error for an inline variable that
is declared but not defined, and referenced but not odr-used.  For example:

  extern inline int i;  // Not a definition.
  auto r = sizeof(i);   // i is referenced, but not "used".  Previously, this
                        // triggered an error.  Now okay.

That is now fixed.


1/10/20  [EDGcpfe/19636,EDGcpfe/21872]
Issue a diagnostic on extraneous attributes in new expression

The syntax for a "new" expression does not allow for attributes that follow
a cv-qualified ptr-operator.  A discretionary error is now given for such cases
(except in GNU emulation mode where a remark is issued).  For example
(with --c++11):

  void f() {
    new int * volatile [[]];    // Now generates a diagnostic.
  }


1/9/20   [EDGcpfe/20929,EDGcpfe/21998,EDGcpfe/22163]
Using-declarations and conversion functions

Consider:

  struct X { operator bool() const; };
  struct Y { operator bool() const; };
  struct D: X, Y {
    using X::operator bool;
  };
  bool foo(D d) {
    return d;  // Previously ambiguous.  Now okay.
  }

The front end previously did not hide Y::operator bool() in the presence of the
using-declaration for X::operator bool() in D.  That resulted in a spurious
ambiguity error.  This is now fixed.


1/9/20   [EDGcpfe/21041,EDGcpfe/22138]
Use of uninitialized bits when creating floating-point hash value

In configurations that use 128-bit floating-point types as the host type and
support 80-bit extended floating-point for long double types, a conversion
from 128-bit to 80-bit had resulted in the correct value, but some of the
unused bytes in the result were uninitialized.  That could lead to cases where,
e.g., a conversion of 0.0 would result in a value where not all of the
16 bytes were zero.  This could also cause problems when using floating-point
values in a hash (e.g., with fp_hash).  Those unused bytes are now zeroed.


1/9/20   [EDGcpfe/22101,EDGcpfe/22140]
Microsoft compatibility: attributes after decl-specifiers

Syntactically, attributes that appear after a decl-specifier appertain to
the type for the declaration, but Microsoft appears to apply them to the
object being declared.  In Microsoft emulation mode (and when microsoft_bugs is
TRUE), the front end now does the same.  For example, with --ms_c++latest
--microsoft_version 1925:

  static alignas(32) int x;
  static_assert(__alignof(x) == 32);


1/9/20   [EDGcpfe/22185]
GNU compatibility: Accept hot/cold attributes on labels

The "hot" and "cold" GNU attributes, which had previously only been recognized
when applied to functions, can now be applied to labels.  As is the case when
applied to functions, these attributes are recorded and otherwise ignored
by the front end.  For example (with --gnu_version 40800):

  int f(int x) {
    if (x > 1) goto coldbranch; else goto hotbranch;
  hotbranch: __attribute__((hot));
    return 1;
  coldbranch: __attribute__((cold));
    return 2;
  }


1/8/20   [EDGcpfe/22005]
Spurious error direct-initializing lvalue-ref with a dependent expression

When a template dependent type is used to direct-initialize a non-const lvalue
reference using braced-initialization, the front end would issue a spurious
"initial value of reference to non-const must be an lvalue" error.  For
example:

  struct A {};
  template<typename T>
  struct B
  {
    B(T& val) : a{val.getA()} {} // Spurious error here
    A& a;
  };

This is now fixed.


1/8/20   [EDGcpfe/22162]
C++-generating back end: reference to undefined type in decltype operand

In C++-generating back end configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, an explicit
specialization could sometimes be generated containing a decltype specifier
in which the operand expression referred to a class type that was not
defined at the point of the explicit specialization.  This is now fixed.
For example, with --c++11, given the input file

  template <typename T> struct A {
    typedef T type;
  };
  template <typename T> class B {
    using dt = decltype(T().g());
  public:
    using type = typename A<dt>::type;
  };
  void f() {
    struct C {
      bool g() { return true; }
    };
    using type = B<C>::type;
  }

the generated output previously contained the following explicit
specialization:

  template<> struct A<bool>  {
    typedef decltype((struct C().g())) type;
  };

However, "C" is a local class that cannot be referred to from namespace
scope, where explicit specializations must appear.  The C++-generating back
end now produces the following correct explicit specialization:

  template<> struct A<bool>  {
    typedef bool type;
  };


1/8/20   [EDGcpfe/22184]
Reference to uninitialized pointer

The "restrictions" variable in builtin_restrictions_met had been uninitialized
in some cases, leading to undefined behavior.  Now fixed.


1/7/20   [EDGcpfe/22179]
Spurious 'expected a ")"' error during template instantiation

In certain instances the front end would issue a spurious 'expected a ")"'
error during template instantiation where C++20 parenthesized aggregate
initialization was used.  For example:

  template <typename T>
  int func() noexcept(T(0));
  template <typename T>
  struct A {
    using type = decltype(func<T>()); // Spurious 'expected a ")"' error here
  };
  A<A<int>>::type foo;

This is now fixed.


1/6/20   [EDGcpfe/22147]
Abort in coroutines when awaiting an operand with a non-trivial destructor

The operand to a (possibly generated) co_await expression produces an
auxiliary expression "e" for the implicit e.await_ready, e.await_suspend, and
e.await_resume function calls.  If "e" contains an object destruction, the
front end would abort in update_last_processed_dynamic_init.  For example:

  namespace std {
    template<typename R, typename ...Args> struct coroutine_traits {
      using promise_type = R::promise_type;
    };
    template <typename = void> struct coroutine_handle {};
  }
  struct A {
    struct promise_type
    {
      A get_return_object();
      A initial_suspend();
      A final_suspend() noexcept;
      void unhandled_exception() noexcept;
      void return_void();
      A await_transform(A);
    };
    ~A();
    bool await_ready() noexcept;
    template<typename T> void await_suspend(std::coroutine_handle<T>) noexcept;
    A await_resume() noexcept;
  };
  A f()
  {
    co_await A{}; // Previously triggered an abort, now accepted
  }

This is now fixed.


1/6/20   [EDGcpfe/22141]
Abort on CTAD with single-element braced initializer

When class template argument deduction is being performed using a braced
initializer containing a single element, the front end could abort in
'can_ignore_single_element_braces'.  For example:

  template <typename>
  struct A {
      A(...) {}
  };

  template <class T>
  A(T)->A<T>;

  const A a{1}; // Previously a potential segfault, now accepted

This is now fixed.


1/3/20   [EDGcpfe/22139]
Abort in make_cast_rescan_operands

Under certain circumstances, the front end failed to record some important
information to enable correct handling of SFINAE for cast expressions.  That
in turn could result in a failed assertion check in make_cast_rescan_operands
(exprutil.c).  For example:

  template<int, int> struct X {};
  template<int A, int B, int C = ((A==1 || B==1) ? 1 : 0)> struct S {};
  template <int N, int M> S<N, static_cast<int>(M)> f(X<N, M> const&);
  void g() {
    X<3, 3> const y;
    S<3, 3> n = f(y);  // Previously triggered an internal error during the
  }                    // substitution of "static_cast<int>(M)".  Now fixed.

That problem is now fixed.


1/3/20   [EDGcpfe/22063]
GNU compatibility: "visibility" attribute on enumeration types

A change has been made to accept the GNU "visibility" attribute on enumeration
types when gnu_version >= 60000 or in clang mode.  Additionally, a warning
is no longer given in Microsoft emulation mode when microsoft_version < 1200
for dllimport/dllexport attributes attached to an enumeration declaration
or a struct (in C mode).  Those changes allow this code to be accepted in
most emulation modes:

  #if defined(_MSC_VER)
  #define EXPORT __declspec(dllexport)
  #else
  #define EXPORT __attribute__((visibility("default")))
  #endif
  enum class EXPORT E { e };


1/2/20   [EDGcpfe/21870]
Performance issue with Ranges library

The way in which the substitution of alias template references is handled
resulted in poor performance in some cases.  This issue created particularly
poor performance for the Ranges library.  Now fixed.


12/31/19 [EDGcpfe/22146]
Abort when __has_include is the last token of a file

The change for EDGcpfe/21966 (in version 6.0) caused a regression in which
a file containing __has_include as the last token of the file, when
compiled in a mode that enables feature-test macros, resulted in an abort
due to a segfault (in skip_white_space).  This is now fixed.  For example,
with --microsoft:

  __has_include   // Last token of file, previously a segfault, now okay


12/27/19 [EDGcpfe/22143]
C++-generating back end: hidden enumerator names

When an enumerator of an unscoped enumeration is used in a scope in which
its name is hidden by another declaration, the C++-generating back end
failed to use a qualified name, causing the generated code to refer to the
hiding name rather than to the enumerator.  This is now fixed.  For
example:

  enum E { zero };
  namespace N {
    struct zero {                 // Hides the enumerator "zero"
      static const E v = ::zero;  // Previously omitted "::"
    };
    E x = ::zero;                 // Previously omitted "::"
  }


12/20/19 [EDGcpfe/19565,EDGcpfe/19659,EDGcpfe/21650]
Spurious failure of old-style rvalue-reference cast in deduction context

Consider:

  struct X {};
  X const g();
  template<typename T> auto f()->decltype((T&&)g(), 42) { return 42; }
  int r = f<X>();  // Previously an error.  Now okay.

Previously this example triggered an error because the substitution of
"(T&&)g()" with T = X failed spuriously.  That is now fixed.


12/20/19 [EDGcpfe/18623,EDGcpfe/22073]
Spurious error on value-initialization of union

Consider:

  union X { int i = 1; };
  union U {
    X x;
    int y;
  } u(U{});  // Previously a spurious error.  Now okay.

The front end previously issued a spurious error for the value-initialization
U{}, claiming the initialization is ambiguous.  That is now fixed.


12/19/19 [EDGcpfe/21272]
Source sequence entries for instantiations triggered within unnamed classes

Consider:

  template<typename T> T max(T x, T y) { return x<y ? y : x; }
  typedef struct {
    int f(int i) { return max(i, 42); }
  } X;

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured to
TRUE, the front end puts out a source sequence entry for the max<int> instance.
If the class in the example were named, this involves (a) moving the definition
of the member f(int) out of the class, and (b) preceding that out-of-class
definition by the source sequence entry for max<int> (which the C++-generating
back end renders as an explicit specialization).  However, with an unnamed
class type that transformation is not possible, and in some modes (Microsoft
mode in particular) the front end previously emitted the source sequence entry
for max<int> after that for the unnamed class definition (and thus after the
point of use of max<int>), causing the C++- generating back end to render
invalid code.  That is now fixed: References to template instances are now
treated differently within unnamed classes.  The example above now causes the
source sequence entry for max<int> to be emitted just before that for the
unnamed class definition even in Microsoft mode, and the resulting code
generated by the C++-generating back end is now correct.


12/19/19 [EDGcpfe/21697,EDGcpfe/21846]
Microsoft compatibility: short-circuiting dependent nontype template arguments

A change made in version 5.1 (EDGcpfe/20756) added emulation of a bug in
the Microsoft compiler that caused certain expressions to be considered
non-dependent if the dependent portion of a logical operation could be
determined to not affect the result.

The Microsoft compiler, however, only exhibited that behavior in certain
contexts.  Our earlier change applied the behavior too widely and had
the effect of producing errors in other cases that the Microsoft compiler
accepted.  We have revised the change to more closely model the behavior
of the Microsoft compiler.

  template <bool b, class T = void> struct A {};
  template <class T> struct A<true, T> {
    typedef T type;
  };
  template <bool b, class T = void> using A_t = typename A<b, T>::type;
  template <class T, bool b = false> struct C {
    template <bool E, typename = A_t<b && E, T>> void f() { }
  };
  C<int> m;


12/19/19 [EDGcpfe/18516,EDGcpfe/21398]
Microsoft C++ compatibility: SFINAE and default template arguments

Consider:

  void g();
  template<typename T> struct S { 
    template<typename = decltype(g(T{}))> int f(int);
    int f(double);
  };
  int r = S<int>{}.f(42);  // Previously always an error.
                           // Now okay in Microsoft bugs mode.

This example is invalid, because when S<int> is instantiated (for the
sub-expression "S<int>{}"), the substitution of the default template argument
"decltype(g(T{}))" is invalid since g() doesn't accept an argument.  Note that
this is not a SFINAE error because the error occurs during a class template
instantiation and not during the deduction process.  The Microsoft compiler,
however, has a bug that causes it to essentially treat that failure as a
deduction failure (the substitution is delayed until the call to S<int>::f,
and in that context it is treated as a SFINAE error).  In Microsoft bugs mode,
the front end now emulates this in some situations (specifically, in decltype
constructs appearing in default template arguments).


12/18/19 [EDGcpfe/22011,EDGcpfe/22134]
C++20: Allow defaulting comparisons by value

The initial specification of defaulted comparison operators required that
each parameter be a reference to the const-qualified type of the class
being compared.  C++ Committee document P1946R0 extended that rule to allow
defaulted friend comparison functions to take both arguments either by
value or by const reference.  The front end has now been modified to
support this extension.  For example, with --c++20:

  struct C {
    int i;
    friend bool operator==(C, C) = default;  // Previously an error, now okay
  };


12/17/19 [EDGcpfe/22104,EDGcpfe/22105,EDGcpfe/22106]
Microsoft compatibility: Enabling C++20 features

Changes have been made to enable some C++20 features in Microsoft emulation
mode when microsoft_version >= 1925.  Those features correspond to committee
papers P1161R3, P1002R1, and P0595R2 which correspond to EDGcpfe/21580,
EDGcpfe/20645, and EDGcpfe/20647 respectively.  See their descriptions earlier
in the Changes file for more information.


12/14/19 [EDGcpfe/20032,EDGcpfe/21890]
C++20: relaxed checking for abstract class types

Because there can be no objects of an abstract class type (i.e., a class
with one or more pure virtual member functions), an abstract class type
cannot be used as a function return type or parameter type.  C++ Committee
document P0929R2 changed the contexts in which this restriction is
enforced.  Previously, it was ill-formed to declare such a function; the
new rules specify that a function's return and parameter types are checked
for abstractness only when the function is defined or called.  Because the
paper was adopted as a defect report, the new rules apply to C++17 and
earlier versions, not just in C++20.

The front end has now been changed to apply the new rules for all standard
versions in both strict and default modes, as well as in Microsoft mode
when microsoft_version is at least 1925.  In addition, the front end's
behavior in g++ and clang modes has been updated to reflect that of those
compilers more closely.  In particular, the front end previously did not
check function return types for abstractness in g++ mode, but g++ began
doing so in versions 5.x and later.  Clang only checks return types for
abstractness for nonmember functions.  The front end now follows suit in
both g++ and clang modes.  (Neither of those compilers yet implements the
new rules.)

The default behavior can be overridden using the new
--[no_]relaxed_abstract_checking command-line option.  For example, with
--relaxed_abstract_checking:

  struct A { virtual void f() = 0; };
  A f0(A);     // Previously an error for return and parameter, now okay
  A f1(A a) {  // Previously and still an error for return and parameter types
    f0(a);     // Now an error for return and parameter types
    return a;
  }


12/14/19 [EDGcpfe/22123]
C++-generating back end: segfault for trivial destructor call via local typedef

In C++-generating back end configurations in which
clang_is_generated_code_target is TRUE, the changes for EDGcpfe/21335 (in
version 5.1) resulted in dereferencing a null pointer (in
scope_is_in_name_context_stack) when a trivial destructor is invoked using a
local typedef name.  This is now fixed.  For example, with --clang:

  void f() {
    typedef struct { } S;
    S s;
    s.~S();  // Previously a segfault, now okay.
  }


12/13/19 [EDGcpfe/22057]
Initialization with reinterpret_cast result

In C++11 (and later), reinterpret_cast is not allowed in constant expressions.
That implies that in the following example:

  struct X { int x; };
  static union {
    char buf[sizeof(X)];
    int aligner;
  } u;
  X &r = reinterpret_cast<X&>(u.buf); // (1) 

the initialization (1) is a "dynamic initialization" according to the standard.
However, implementations are permitted to implement this initialization as a
static ("constant") initialization, and many implementations do.  The front end
now handles this reinterpret_cast specially in this context to produce a
constant initializer even in C++11 (and later) modes.


12/13/19 [EDGcpfe/21559]
Lowered expression evaluation order for eok_dot_member_call and virtual calls

Strict expression evaluation ordering (see the Changes entry for EDGcpfe/17701)
had not been properly maintained in lowered code for some eok_dot_member_call
and virtual function calls.  That is now fixed.  For example (with --c++17):

  extern "C" int printf(const char *format, ...);
  struct A {
    void f(int) { }
    virtual A& operator=(const A& other) { return *this; }
  } a;
  A& get_selector()          { printf("get_selector\n"); return a; }
  decltype(&A::f) get_ptmf() { printf("get_ptmf\n");     return &A::f; }
  int get_arg()              { printf("get_arg\n");      return 0; }
  A& get_lhs()               { printf("lhs\n");          return a; }
  A& get_rhs()               { printf("rhs\n");          return a; }
  int main() {
    (get_selector().*get_ptmf())(get_arg());
    get_lhs() = get_rhs();  
  }

The example above should print:

get_selector
get_ptmf
get_arg
rhs
lhs


12/12/19 [EDGcpfe/22090]
Spurious error on pragma in constexpr if between the condition being tested
and the dependent statement

If an "if constexpr" had a next-construct pragma after the condition being
tested but before the dependent statement a spurious "this pragma must
immediately precede a statement" error could be issued.  Now fixed.

  struct A {
    static constexpr int v = 0;
  };
  template <typename T> inline void f() {
    if constexpr(T::v)
  #pragma test_next_statement
                       for (int i = 0; i < 1; i++);
  }
  int main() {
    f<A>();
  }


12/12/19 [EDGcpfe/22014]
GNU C++ compatibility: multi-character Unicode character literals

According to the C++ Standard, UTF-16 and UTF-32 character literals must
have exactly one character between the apostrophes.  G++, however, accepts
(with a warning) such literals containing multiple characters, discarding
all but the last.  The front end has now been modified to do the same in
g++ mode.  For example, with --g++ --c++11:

  char32_t c = U'abc';  // Previously an error, now a warning in g++ mode;
                        // c is initialized as if by U'c'


12/11/19 [EDGcpfe/22097]
Explicit conversion operator spuriously ignored for static_cast operation

Consider:

  struct X { explicit operator int&&(); };
  int r = static_cast<int const&>(X{});

Previously, this failed because the static_cast conversion was treated as a
copy-initialization context, which in turn caused the explicit conversion
operator to be erroneously ignored.  That is now fixed.


12/9/19  [EDGcpfe/22092]
Abort when reading the IL for a coroutine

In configurations where IL_SHOULD_BE_WRITTEN_TO_FILE is TRUE and
ALTERNATE_IL_FILE_FORMAT is FALSE, the front end would abort in
'ptr_remap_function' when reading the IL associated with a coroutine.  For
example:

  #include <coroutine>
  std::generator<int> f(int arg0) { // Abort in 'ptr_remap_function'
    co_yield arg0;
    co_return arg0;
  }

This is now fixed.


12/6/19  [EDGcpfe/22088]
Interpreter evaluation of __builtin_memcmp, etc.

If __builtin_memcmp and similar built-in comparison functions are interpreted
with a zero length argument, the front end now treats the operation as
successful and producing a zero value.  In particular, it does not check the
validity of the pointer arguments in that case.  For example (in Clang and
Microsoft modes):

  constexpr int v = __builtin_wmemcmp(nullptr, nullptr, 0);
                         // Previously elicited an error because the
                         // interpreter considered this a case of null
                         // pointer indirection.  Now okay.

(See also the changes for EDGcpfe/18000, which introduced interpreter support
for these comparison functions.)


12/6/19  [EDGcpfe/22087]
Microsoft C++ compatibility: __is_constructible (etc.) and destructors

The changes for EDGcpfe/17852 made __is_constructible produce a false value if
__is_destructible produced a false value for the given type.  However, an
exception was made in Microsoft mode, because Microsoft compilers at the time
did not behave that way.  Now, the Microsoft-mode exception only exists when
microsoft_version <= 1910.  This also affects __is_nothrow_constructible and
__is_trivially_constructible.  For example:

  struct N { ~N(); };
  static_assert(__is_trivially_constructible(N), "");
    // Now an error in Microsoft modes with microsoft_version > 1910.


12/6/19  [EDGcpfe/20036]
C++20: Efficient sized delete for variable sized classes

The front end now implements a destroying operator delete as described
in P0722R3.


12/6/19  [EDGcpfe/22086]
Microsoft C++ compatibility: __is_standard_layout and function types

In Microsoft C++ modes, the front end now produces a true value for
__is_standard_layout applied to a function type.  For example:

  static_assert(__is_standard_layout(int (int)), "");
    // Normally an error, but now accepted in Microsoft C++ modes.


12/5/19  [EDGcpfe/22075]
C++-generating back end, Microsoft compatibility: generated explicit
specializations and dependent array bounds in parameters

In configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, the
C++-generating back end represents implicit instantiations of function
templates as explicit specializations.  When the type of a function
parameter of a function template is a (possibly multi-dimensioned) array
type with a dependent bound, a generated explicit specialization for it
triggered a bug in versions of MSVC prior to 19.12, causing them to issue a
spurious error C2912, "not a specialization of a function template".  In
order to avoid this bug, the C++-generating back end now suppresses such
generated explicit specializations when msvc_is_generated_code_target is
TRUE and msvc_target_version_number is less than 1912.  For example, with
--microsoft --msvc_target_version=1911:

  template<int N> void f(int a[2][N]) { }
  void g() {
    int a[2][4];
    f<4>(a);
  }

The generated code previously contained an explicit specialization,

  template<> void f<4>(int a[2][4]) { }

which triggered the MSVC bug.  This explicit specialization is now
suppressed in the affected modes.


12/5/19  [EDGcpfe/22084]
GNU C++ compatibility: Vacuous destructor calls and vector types

The front end now accepts vacuous destructor calls applied to vector types.
For example:

  typedef int Vec __attribute__((__vector_size__(8)));
  Vec& g();
  int main() {
    g().~Vec();  // Previously an error.  Now okay.
  }


12/5/19  [EDGcpfe/22076]
Address of parenthesized id-expression as template argument

The changes for EDGcpfe/20944 (version 6.0) introduced a regression in
pre-C++17 modes, causing the front end to erroneously reject the address of a
parenthesized id-expression as a template argument.  For example:

  template<int*> struct S {};
  int i = 42;
  S<&(i)> sai = {};  // Error in version 6.0 in pre-C++17 modes.  Now okay.

That is now fixed.


12/4/19  [EDGcpfe/22074]
C++-generating back end: gcc mode, typedefs, and volatile return types

In cases where a function is declared to return a volatile-qualified struct
type, where the struct is unnamed and referred to via a typedef, in gcc mode
the C++-generating back end put out the return type using an undeclared
temporary name (of the form __T12345678).  This is now fixed; in gcc mode,
unnamed structs defined in typedef declarations are now put out with a
temporary name as the tag so that a later reference can use that tag.  For
example, with --gcc:

  typedef struct { int i; } S;
  volatile S f(void);  // generated as "struct __T12345678 f(void);"

The typedef declaration will now appear in the generated code as:

  typedef struct __T12345678 { int i; } S;


12/5/19  [EDGcpfe/21898]
Digit separators in skipped conditional compilation text

The front end previously could issue an error reporting a misplaced digit
separator appearing in text that is skipped by conditional compilation.
This is now fixed.  For example, with --c++11:

  #if 0
  0x'  // Previously an error, "digit separator cannot appear here", now okay
  #endif


-------------------------------------------------------------------------------
Version 6.0, December 5, 2019

12/2/19  [EDGcpfe/21866]
Multiple translation units: Failure to update canonical entry for a nested
enumeration

When a class template contains a scoped enumeration and an enumerator is used
(causing the enumeration to be instantiated), the front end failed to update
the canonical source correspondence.  This caused an abort in configurations
that have IL_SHOULD_BE_WRITTEN_TO_FILE set and compiling multiple translation
units when both the primary and a secondary TU contain instantiations of the
class template, but only the secondary TU contains a usage of the enumerator
(and therefore only the secondary TU had the enumeration instantiated).  For
example, if a.cpp contains:

  template<typename>
  struct B {
    enum class ENUM { i };
    virtual ENUM func();
  };
  B<int> a;

and b.cpp contains:

  template<typename>
  struct B {
    enum class ENUM { i };
    virtual ENUM func();
  };
  B<int> b;

  template<typename T>
  B<T>::ENUM B<T>::func() {
    return ENUM::i; // Previously triggered an abort, now fixed.
  }

then compiling a.cpp b.cpp would trigger an abort in 'read_memory_region'.
This is now fixed.


12/2/19  [EDGcpfe/21625]
Lowered compound assignment expressions and strict evaluation ordering

When lowering a compound assignment expression, strict expression ordering
had not been properly maintained, resulting in expressions that had been
executed in the incorrect order.  For example, with --c++17:

  extern "C" int printf(const char *format, ...);
  bool  b;
  bool& lhs() { printf("lhs\n"); return b; }
  bool  rhs() { printf("rhs\n"); return b; }
  int main() {
    lhs() += rhs();  // Now executes rhs() first.
    return 0;
  }


11/27/19 [EDGcpfe/20437,EDGcpfe/21093]
Assertion failure in get_typeinfo_var

In configurations that do lowering, an assertion failure (in get_typeinfo_var)
had occurred when using typeinfo for some pointer-to-member functions in modes
where exception specifications are considered part of a function type.
For example (with --c++17):

  #include <typeinfo>
  struct A {};
  auto &x = typeid(void (A::*)() noexcept);


11/27/19 [EDGcpfe/22013]
__is_function type trait helper

The __is_function type trait helper has been implemented (in all modes).


11/25/19 [EDGcpfe/18786,EDGcpfe/21191]
Deduction failures due to missing definitions

Consider:

  struct X { };
  auto g(X);  // No definition.
  template<typename T> constexpr auto f(T p) -> decltype(g(p)) { return 1; }
  template<typename T> constexpr auto f(T p) -> int { return 2; }
  static_assert(f(X{}) == 2, "Unexpected");  // Now accepted.

Previously, the attempt to call f(X{}) triggered an error about not being able
to deduce the type of g(p) because g has no definition.  Now that error is
treated as a deduction failure ("SFINAE"), and overload resolution selects the
second declaration of f without issuing an error.


11/21/19 [EDGcpfe/21254,EDGcpfe/21630,EDGcpfe/21957,EDGcpfe/21985,
          EDGcpfe/22031,EDGcpfe/22041]
Incorrect substitution when combining alias templates

Version 5.1 of the front end introduced a regression in the substitution of
alias templates when multiple alias templates were combined in complex ways.
For example:

  template<typename T> T make();
  template<typename> struct Wrap;
  template<typename> struct Func;
  template<typename R, typename... Ps> struct Func<R(Ps...)> {
    template<typename F> using RetType = decltype(make<F>()(make<Ps>()...));
    template<typename F> using WrapRet = Wrap<RetType<F>>;
    template<typename C> using CondInt = int;
    template<typename F, typename = CondInt<WrapRet<F>>>
      Func(F);
  };
  template<int> struct X {};
  void g(Func<void(X<0>)>);
  void g(Func<void(X<1>)>);
  struct Callable { void operator()(X<0>); } callable;
  int main() {
    g(callable);  // Previously considered ambiguous.  Now okay.
  }

Previously, the substitution of CondInt<WrapRet<F>> with F = Callable produced
an incorrect type independent of Callable.  As a result, the call was treated
as ambiguous.  That is now fixed.


11/21/19 [EDGcpfe/22045]
C++-generating back end: missing parentheses around constexpr initializer

In cases where the source code contains an initializer explicitly invoking
a constexpr default constructor in a parenthesized direct initialization,
the C++-generating back end failed to emit the extra set of parentheses
needed to disambiguate the declaration from a function declaration.  This
was a regression introduced in version 5.1 by the changes for
EDGcpfe/20976.  This is now fixed.  For example, with --c++11:

  struct S {
    constexpr S() {}
    S(S&&) {}
  };
  struct T {
    int i = 0;
    T(S) { }
  };
  int main() {
    T a((S()));  // Previously generated as T a(S()), a function declaration
    return a.i;
  }


11/21/19 [EDGcpfe/19140]
IA-64 ABI: Eliminate unneeded typeinfo reference in configs where
GENERATE_EH_TABLES is FALSE

A change has been made to eliminate an unresolved typeinfo reference in certain
cases in configurations that do lowering but have GENERATE_EH_TABLES set to
FALSE.  For example:

  struct A {
    virtual void f();
  };
  struct B : A {
    A a;
    virtual ~B();
    void f() {
      dynamic_cast<B *>(&a);
    }
  };


11/21/19 [EDGcpfe/19645]
Assertion failure in mangled_encoding_for_sizeof_pack

In non-lowering configurations that have MANGLE_ALL_NAMES set to TRUE, an
assertion failure (in mangled_encoding_for_sizeof_pack) had occurred during
mangling of some nonreal non-prototype instantiations.  For example
(with --c++11):

  template <class T> struct A;
  template <class T, int n> using B = class A<T>;
  template <class T, class... U>
  using D = class B<T, sizeof...(U)>::template f<U...>;
  template <class T> struct C {
    template <class... Ts> using f = D<T, int, Ts...>;
  };


11/20/19 [EDGcpfe/21979]
Spurious error on deleted copy constructor with conditional comma expressions

When the second and third operands to the conditional operator were comma
expressions, the front end was failing to recognize when these comma
expressions were movable.  This led to an incorrectly called copy constructor.
For example:

  struct S
  {
    S(int);
    S(const S&) = delete;
    S(S&&);
  };
  void f()
  {
    1 ? (1,S(1)) : (1,S(2)); // Previously emitted an error due to the deleted
                             // copy ctor being called, now accepted
  }

This is now fixed.


11/19/19 [EDGcpfe/21806,EDGcpfe/21853]
Regressions resulting from changes in handling large, complex macro expansions

The changes for EDGcpfe/21772, not part of a release but widely
disseminated as a patch for version 5.1, caused regressions in cases where
the name and closing parenthesis of a function-like macro invocation appear
in different macro expansions.  The effects of the regression range from
incorrect macro expansions to aborts accessing nonexistent memory.  For
example, with -E, the result of

  #define a(x,y) test macro: x + y
  #define f g , green)
  #define g a ( keith
  f

should be

  test macro: keith + green

but after the regression it was

  test macro: keith + green , green)

This is now fixed.


11/19/19 [EDGcpfe/22015]
Invalid nontype template arguments

A number of changes were made to more consistently diagnose invalid nontype
template arguments.  For example, in GNU C++ mode:

  template<char(*)()> struct X {};
  extern int g();
  int main() {
    X<(char (*)())g> x;  // Previously accepted in GNU C++11 mode.
  }                      // Now an error.


11/19/19 [EDGcpfe/20944]
Using arrays as nontype template arguments

Consider:

  template<typename T, T> struct X {};
  char arr[3];
  X<const char(&)[3], arr> x;  // Previously an error.  Now accepted.

This case previously elicited an error because the front end failed to
correctly evaluate the conversion of arr to the nontype template parameter's
type.  That is now fixed.


11/19/19 [EDGcpfe/21990]
Abort on literals in list initializers during variadic template prescan

The change for EDGcpfe/21187 (in version 5.1) caused an abort in
prep_generic_operand_full during variadic template prototype instantiation and
prescanning template arguments involving list initializers containing literals.
For example:

  template <typename T> void foo(T x){}
  template <typename T>
  struct S2 {
     using type = T;
  };
  void bar() {
     foo<typename ::S2<decltype(long{1234})>::type>(long{1234});
     // The above line would previously cause an assertion failure
  }

This is now fixed.


11/19/19 [EDGcpfe/22044]
Severity of diagnostic for noexcept with exceptions disabled

The severity of the diagnostic that is issued when exceptions are disabled
and a noexcept specification is used in a function declaration has been
reduced from a warning to a remark.

  void f() noexcept {}

11/19/19 [EDGcpfe/22023]
GNU C++ compatibility: "template" keyword ignored for overload resolution

When the "template" keyword is followed by a function or overload set name,
g++ includes non-template functions in the overload set.  This causes it
to call the normal function rather than attempt to call the deleted template
in the example below.  We now emulate this behavior in g++ mode.

  template <typename T> struct A {
    static void f(T){}
    template <typename U> static void f(U) = delete;
  };

  int main() {
    A<int>::template f(1);
  }


11/18/19 [EDGcpfe/22037]
C++-generating back end: call to function pointer with dependent type

In configurations in which function template definitions are generated from
the prototype instantiation IL, the C++-generating back end could abort with
a segfault in gen_argument_list_no_parens if a call is made to a function
pointer with a dependent type.  This is now fixed.  For example:

   template<typename T> void tf(T *f) {
     f();  // Previously might abort, now okay
   }


11/15/19 [EDGcpfe/22029]
GNU compatibility: incorrect lowered code for some GNU statement expressions

In cases where a GNU statement expression's last statement is a void expression
that, when lowered, creates additional lowered expressions (e.g., because of
destructions) a temporary variable of "void" type had been created.  Now
fixed.  For example (with --g++):

  struct A {
    ~A();
  };
  void g() {
    ({
      A a;
      g();
    });
  }


11/15/19 [EDGcpfe/20890]
Attributes on nested namespace declarations

Attributes are not allowed on nested namespace declarations and the front
end had diagnosed such cases, but if the attribute had been an attribute
that was not known to the front end, a warning rather than an error had
been given.

  namespace [[foo]] A::B {}   // Now an error as well as a warning.


11/15/19 [EDGcpfe/20677,EDGcpfe/20882,EDGcpfe/21204,EDGcpfe/21213]
GNU/clang compatibility: diagnostics for incorrectly applied attributes

Attributes that are incorrectly applied to entities had elicited an error
in most instances and now elicit a warning in clang and GNU (when
gnu_version >= 40300) emulation modes.  For example:

  namespace [[maybe_unused]] A {}   // Now a warning in some modes.


11/14/19 [EDGcpfe/17973,EDGcpfe/17974,EDGcpfe/20619,EDGcpfe/21971]
GNU/Clang C++ compatibility: __func__, __FUNCTION__, and __PRETTY_FUNCTION__

In GNU C++ mode, the static variables corresponding to __func__, __FUNCTION__,
and __PRETTY_FUNCTION__ are now declared "constexpr".  This extends the changes
for EDGcpfe/20207 (see entry of 9/27/18) to GNU C++ mode.  In addition, in
GNU C++ mode, the value of __PRETTY_FUNCTION__ now also includes a "constexpr"
prefix for functions declared constexpr.  Finally, various changes were made to
the output of template parameter values for __PRETTY_FUNCTION__ to bring them
closer to the behavior of Clang and GCC in the corresponding C++ modes.


11/14/19 [EDGcpfe/21986]
Direct-initialization in explicit variable template specializations

The front end previously treated direct-initialization in explicit variable
template specializations as if it were copy-initialization.  That, for example,
caused erroneous type deduction in some cases.  For example:

  #include <initializer_list>
  template<typename> constexpr auto &v{"x"};
  template<> inline constexpr auto &v<bool>{"y"};  // Previously an error.
                                                   // Now okay.

That is now fixed.


11/14/19 [EDGcpfe/22024]
Issue with inline variables when using INSTANTIATE_INLINE_VARIABLES

INSTANTIATE_INLINE_VARIABLES is used in environments that do not have COMDAT
support to use the prelinker to provide a single definition of inline
variables.  This did not work properly in some cases involving dynamic
initialization.  This could result in a prelinker loop.  Now fixed.

  int f() { return 1; }
  struct A {
    inline static int I = f();
  };
  int main() { }


11/14/19 [EDGcpfe/22021]
Abort while substituting nontype template parameter during deduction

In some situations where a constexpr variable initialized with a nontype
template parameter needs substitution during template argument deduction, the
front end could abort in get_expr_rescan_info ("missing default rescan info",
in exprutil.c).  For example:

  template<typename T> struct W { using Type = T; };
  template<typename, int N = 42> struct X {
    static constexpr int num = N;
    template <int = num> constexpr X() {}
  };
  template<typename C> X(C &) -> X<typename C::Type>;
  void g(W<char> x) {
    X{ x };  // Previously triggered an abort.  Now a normal error.
  }

That is now fixed.


11/14/19 [EDGcpfe/22019]
Microsoft compatibility: spurious error on dependent virtual function

When Microsoft nonreal base class lookup is enabled, a spurious error
could be produced during the nonreal instantiation of such a base class
if it included a pure specifier but did not include the "virtual" keyword.
Now fixed.

  template <typename T> struct A {
    virtual int f(T x) = 0;
  };
  template <typename T> struct B : public A<T> {
    int f(T x) override = 0;
  };
  template <typename T> struct C : public B<T> {
    int f(T){return 0;}
  };
  C<int> ci;


11/13/19 [EDGcpfe/21289]
Parameter variables with destructors

Consider the following program:

  template<typename T> struct D { ~D(); };
  template<typename T> inline D<T>::~D() {}
  template<typename T> X: D<T> {};
  void g(D<int>) {}
  int main() { return 0; }

With the ABIs supported by the front end (IA64 and Cfront), parameter variables
are destroyed by the caller of a function.  As a result, this program does not
reference the destructor of D<int> because g(D<int>) is never called.  However,
in Microsoft's nonstandard ABI (not implemented in the front end), the callee
is responsible for destroying its parameter variables, and so the Microsoft
compiler would instantiate the destructor of D<int> when it processes the
definition of g(D<int>).  In C++-generating back end configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS, the destructor
definition of D<int> will normally not be emitted (since it is not referenced),
and when that output is passed to the Microsoft compiler a linker error will
ensue.  To compensate for this, a new configuration macro
REF_DESTRUCTORS_FOR_PARAMETER_VARIABLES can now be set to TRUE to force the
destructors for parameter variables to be marked as referenced when a function
is defined.  With that macro set to TRUE, the C++-generating back end will then
emit the destructor definition of D<int> in the above example.


11/12/19 [EDGcpfe/21949]
IL write-read abort after folding local variable initializer

In some (but not all) configurations with IL_SHOULD_BE_WRITTEN_TO_FILE,
folding a local variable initializer involving a constexpr call occasionally 
resulted in an IL write-read abort.  This was caused by the dynamic initializer
entry of the corresponding stmk_init statement not being updated to reflect the
folded initializer.  For example (in GNU C++11 mode):

  enum E { e };
  constexpr E f() { return e; }
  template<typename> struct A {
    A() {
      const E g = f();  // Previously resulted in inconsistent IL, leading
    }                   // to an IL write-read abort.
  };
  struct B {
    A<char> a;
    B(): a() {}
  };

Sometimes, the abort did not happen in the front end proper, but in standalone
utilities, like the IL display program.  That problem is now fixed.


11/12/19 [EDGcpfe/21982]
GCC & Clang compatibility: inline variables in pre-C++17 modes

In GNU and Clang modes the front end now accepts inline variable declarations
in pre-C++17 modes when gnu_version >= 70000 or clang_version >= 30900,
respectively.  A warning is issued the first time such nonstandard code is
encountered outside a system header.  For example:

  inline int x = 32;  // Now accepted with a warning in some GNU and Clang
                      // C++14 modes.


11/12/19 [EDGcpfe/21918]
C++-generating back end: abort with non-dependent reference to incomplete class

The C++-generating back end could abort with an assertion failure in
push_class_name_context when a template definition contains a non-dependent
reference to a member of an incomplete class (which is permitted in g++
emulation mode).  This is now fixed.  For example, with --g++:

  struct S;
  template <typename T> void f(S &s) {
    s.x();   // S is incomplete; previously aborted, now okay
  }


11/11/19 [EDGcpfe/21981]
C++-generating back end: top-level pointer qualification in generated explicit
specializations

Recent versions of MSVC have a bug that prevents it from matching a use of
a function template to an explicit specialization if the specialization has
a parameter that is a function pointer or a member function pointer that
has a pointer parameter with a cv-qualifier at the top level.  For example,
given

  template <typename T> void f(T) { }
  void g(int * const) { }
  void h() {
    f(g);
  }

In a C++-generating back end configuration with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS, the call "f(g)"
resulted in an explicit specialization

  template<> void f(void (*)(int * const)) { }

The presence of the const qualifier on the parameter in the explicit
specialization in the generated code prevented MSVC from matching the call
"f(g)" to the explicit specialization; instead, MSVC implicitly
instantiated f<void (*)(int *)>(void (*)(int *)) (which has the same type
as the explicit specialization, since top-level cv-qualification of
function parameters is dropped in determining the function type) and called
that instance instead of the explicit specialization.

To work around this MSVC bug, the C++-generating back end now drops
top-level cv-qualification in parameters of generated explicit
specializations of function templates when msvc_is_generated_code_target is
TRUE and msvc_target_version_number is 1400 or greater.


10/31/19 [EDGcpfe/21810]
Clang compatibility: __builtin_operator_new and __builtin_operator_delete

Clang defines __builtin_operator_new and __builtin_operator_delete builtin
functions, but their definitions reflect the single argument versions of
their respective operator functions.  A change has been made to the
signatures of these builtin functions to also accommodate the overloaded
signatures (i.e., those with more than a single argument).  For example
(with --clang):

  template <class T1, class T2>
  void f(void *ptr, T1 a1, T2 a2) {
    return __builtin_operator_delete(ptr, a1, a2);
  }


10/31/19 [EDGcpfe/21927]
C++-generating back end: missing qualification with template parameter hiding

The C++-generating back end failed to use a qualified name to refer to an
entity in a scope containing a template definition when the name of the
entity is hidden by the name of a template parameter.  This is now fixed.
For example:

  int I;
  template<int I> int f() { // Template parameter I hides ::I
    return ::I;             // Previously generated as "return I;"
  }


10/30/19 [EDGcpfe/20007,EDGcpfe/21948]
C++20: Range-based-for statements with initializer

An optional initializer statement is now allowed in a range-based-for
statement in C++20 mode.  See P0614R1 for details.  For example (with --c++20):

  void f() {
    int sum;
    int a[] = {1,2};
    for (sum = 0; auto y: a)
      sum += y;
  }


10/30/19 [EDGcpfe/21966]
Abort with __has_include invoked from a macro expansion

Defining an object-like macro to replace the name of the __has_include
feature-test macro and then invoking __has_include via that replacement
name could result in an abort (in adjust_deletion_counts).  This is now
fixed.  For example, with --c++17:

  #define M __has_include
  #if  M(<donthave>)  // Previously sometimes aborted, now okay
  #endif


10/29/19 [EDGcpfe/21910]
Wrong end position on single-argument dynamic initialization

The end position of some initializers that used a template constructor were
incorrect in C++11 mode or later.  For example:

  template <class T> struct S1 {
    static const bool mem;
  };
  template <class T> const bool S1<T>::mem = true;
  template <bool> struct S2 { typedef int type; };
  struct S3
  {
    template<typename T1,
             typename T2 = typename S2<S1<T1>::mem == 0>::type>
      S3(T1);
  };
  S3 v1(1); // Previously used the location of '::mem' in the
            // defaulted 'typename T2'.  Now uses the closing ')' for 'v1(1)'

This is now fixed.


10/29/19 [EDGcpfe/21925]
Clang compatibility: "availability" attribute

Clang accepts an "availability" attribute that can be placed on declarations to
describe the lifecycle of that declaration relative to operating system
versions.  The attribute and its syntax are very specific to Apple products
and assume that the compiler knows about the target operating system and
versions.  See https://clang.llvm.org/docs/AttributeReference.html#availability
for details.

Since the front end does not know about target operating systems, a change
has been made to parse the "availability" attribute and invoke the new
check_availability_attr function for further processing.  Presumably a customer
would replace this function with an implementation that understands the
target operating system and versions to achieve the desired results.

At this time, the related "clang availability" pragma is not supported.


10/29/19 [EDGcpfe/21750]
Spurious substitution failure calling function template

In some cases involving the deferral of instantiations (which is done when
one or more class definitions is still in process), the front end could
incorrectly consider a substitution loop to be encountered causing substitution
to fail.  Now fixed.

  template <class T> void f(T) { }
  template <class T> struct A {
    T t;
    void begin() { f(t); }
    void end()   { f(t); }
  };
  template <class T> struct B {
    A<int> *a;
    void begin() { a->begin(); }
    void end()   { a->end();   }
  };
  B<int> b;
  struct C {
    inline static int I = (b.begin(), 1);
    void g() { b.end(); }
  };
  int main() { }



10/28/19 [EDGcpfe/21962]
C++-generating back end: block-scope lambda closure types in template arguments

For certain complex cases in which the closure type of a block-scope lambda
is used as a template argument and in C++-generating back end configurations
in which CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the front
end could abort with an assertion failure in gen_type_operator.  This is now
fixed.


10/25/19 [EDGcpfe/20058,EDGcpfe/21530,EDGcpfe/21795,EDGcpfe/21848]
Spurious errors on inline static data member template instance

The front end previously issued spurious errors on certain inline static
data member template declarations.  For example:

  struct S {
    template<int N> static inline int m = N;  // Previously triggered a
  };                                          // spurious error when
  int i = S::m<42>;                           // instantiated.

That is now fixed.


10/25/19 [EDGcpfe/21965]
GNU/clang compatibility: string literal operator template character type

As noted in the entry for EDGcpfe/15168,EDGcpfe/20235, the proposed
Standard wording in C++ Committee document P0424R0 specifies that the
character type deduced for an invocation of a string literal operator
template is the element type of the literal array; for example, given a
user-defined literal like L"ab"_x, the elements of the array have type
"const wchar_t".  However, the implementation of this feature in g++ and
clang drops the "const", and the front end has now been changed to do the
same.  For example, with --c++14 --gnu_version=90200:

  template<typename T, T ...chars> int operator"" _x();
  int i = L"ab"_x;  // calls operator""_x<wchar_t, L'a', L'b'>()


10/24/19 [EDGcpfe/21961]
Spurious error on C++17 aggregate initialization of C++/CLI value class

In a Microsoft mode combining C++/CLI with C++17, the front end previously
issued a spurious error when attempting to use aggregate initialization for
a C++/CLI value class.  For example:

  value class V {};
  void f() {
    V v{};  // Previously an error in "C++17/CLI" mode.  Now okay.
  }

That is now fixed.


10/24/19 [EDGcpfe/20609,EDGcpfe/21897]
Aborts and spurious errors with string literal operator templates

The front end could abort with a segfault (in array_element_type) or issue
a spurious "invalid literal operator name" error when compiling an
invocation of a string literal operator template (see the entry for
EDGcpfe/15168,EDGcpfe/20235 for a description).  This is now fixed.  For
example, with --c++14 --gnu_version=90100:

  template<class C, C... S>
  int operator""_suf() {
    return 0;
  }
  template<class X = decltype("0x"_suf)>  // Previously aborted, now okay
  int f() { return 1; }


10/24/19 [EDGcpfe/21942]
Abort in insert_call_to_initialize_entity for multi-translation-unit case

When simultaneously compiling multiple translation units with a secondary
translation unit containing a mem-initializer for a flexible array member
(possible, e.g., in some Microsoft modes), the front end could abort during
lowering in insert_call_to_initialize_entity (due to invalid IL).  For example,
the problem manifested itself with an empty primary translation unit and the
following secondary translation unit compiled in Microsoft mode:

  struct S { char c; };
  struct X {
    X(): n(42), as() {}  // Previously triggered an abort in Microsoft mode.
    int n;               // Now okay.
    S as[];
  };
  X* g() {
    return new X();
  }

That is now fixed.


10/23/19 [EDGcpfe/16509,EDGcpfe/21952]
C11-mode abort on _Generic construct that can match multiple types

The front end previously aborted with an internal error on certain C11 _Generic
constructs that can match multiple cases.  For example:

  int r = _Generic((void (*)())0,
                   void (*)(int)  : 0,
                   void (*)(void) : 0);  // Previously aborted.  Now an
                                         // ordinary error.

That is now fixed.


10/23/19 [EDGcpfe/21327,EDGcpfe/21944,EDGcpfe/21951]
__is_same and __is_same_as

In Clang C++ mode, the front end now accepts the type trait helper __is_same,
which takes two types and produces true if the types are identical (ignoring
aliases) and false otherwise.  In GNU C++ mode with gnu_version >= 70000, the
equivalent type trait helper __is_same_as is accepted instead.  For example:

  static_assert(__is_same(int*, int*), "Test 1 failed");
    // Now accepted in Clang C++ mode.
  static_assert(!__is_same_as(int, int*), "Test 2 failed");
    // Now accepted in some GNU C++ modes.


10/22/19 [EDGcpfe/21031,EDGcpfe/21904]
GNU compatibility: Nonstandard folding

The front end now emulates a few additional cases where GCC treats as constant
an expression that is not constant according to the relevant standards.  First,
comparing a variable with itself produces a constant true value with "==" or
constant false value with "!=".  For example:

  int x;
  struct S { int i: 1+(x == x); }; // Now accepted in GNU modes.

Second, certain casts of null pointers are now treated as constants in GNU C
mode.  For example, in GNU C11 mode:

  _Static_assert((int*)(void*)0 == (int*)0, "");  // Accepted in GNU C mode.


10/22/19 [EDGcpfe/21896]
GNU compatibility: constant folding of vector operations

In configurations that support GNU vector types, the front end would abort
with an assertion failure (in unary_operation or binary_operation) when
certain operators are applied in a constant-expression context; these
include !, ==, !=, <, >, <=, >=, &&, and ||.  This is now fixed.  For
example, with --g++ --c++14:

  typedef int V __attribute__ ((vector_size (16)));
  constexpr V b1 = { 0, 1, 10, 20 };
  constexpr V b2 = { 0, 2, 10, 0 };
  constexpr V b3 = b1 == b2;  // Previously aborted, now okay


10/21/19 [EDGcpfe/21934]
Default member initializers for bit fields in GNU and Microsoft modes

The front end now accepts default member initializers for bit fields in GNU and
Microsoft C++20 modes.  Such constructs were previously already accepted in
other C++20 modes (see entry for EDGcpfe/19998).


10/21/19 [EDGcpfe/21947]
Implement scoping changes for P0184R0

The changes for EDGcpfe/17338 relaxed some of the requirements for range-based
for statements, but neglected to implement the scope changes.  Previously
the rewritten __begin and __end variables for a range-based for statement had
been in a separate scope (a_range_based_for_loop::begin_end_scope) and now they
are in the same scope as the __range expression (i.e.,
a_range_based_for_loop::range_based_for_scope).  As this change removes
a_range_based_for_loop::begin_end_scope, it is a slight IL CHANGE.


10/21/19 [EDGcpfe/21930]
Interpreter accesses uninitialized memory in do_constexpr_condition

In some situations the front end previously accessed uninitialized memory after
it failed to evaluate a condition expression (e.g., for an if- or switch-
statement) in do_constexpr_condition (interpret.c).  That problem is now fixed.


10/21/19 [EDGcpfe/21902]
C++-generating back end: block-scope lambda closure types in template arguments

In certain complex cases involving long chains of member typedefs of class
templates, some of which are inaccessible, and the closure type of a
block-scope lambda, the C++-generating back end could put out a template
argument in a form that referred to the closure type using an undeclared
temporary name (of the form __T12345678).  This is now fixed.


10/19/19 [EDGcpfe/21926]
__INTADDR__ and constexpr evaluation

The EDG-specific extension __INTADDR__ (which enables the folding of its
operand even if that operand includes operations that require adding an offset
to a null pointer) has been reworked to work with the constexpr interpreter.
That enables some cases that had become errors in modes that support
constexpr.  For example:

  #define offsetof(T, member)  (__INTADDR__((&((T *)0)->member)))
  struct S {
    unsigned arr[4];
  };
  enum { N = offsetof(S, arr[1]), };  // Previously an error in C++11 mode.
                                      // Now okay.


10/18/19 [EDGcpfe/21920]
NULL return from ctime

The front end determines the time of compilation by calling the ctime
system call.  It is possible for ctime to return NULL, which had caused a
crash in the front end.  A change has been made such that in such cases the
front end will no longer abort, but the values of the __DATE__ and __TIME__
macros will be incorrect (though properly formatted).


10/17/19 [EDGcpfe/21855]
Deleted copy constructors causing classes to be marked as non-trivally copyable

When a copy or move constructor is declared with a signature that does not
match that which would be implicitly generated, and this constructor is marked
as deleted, the front end would still mark these classes as non-trivially
copyable because of the mismatched function signature.  This resulted in
unexpected behavior in certain cases, such as copy elision.  For example:

  struct S
  {
    S(const S&&) = delete;
  };
  void f(S param = {}); // Spurious "deleted function referenced" diagnostic

This is now fixed.


10/17/19 [EDGcpfe/21921]
Microsoft-mode abort on use of "enum class" in generic lambda parameter

Consider:

  enum class E {};
  auto r = [](enum class E) {};  // Previously triggered an internal error
                                 // in Microsoft mode.  Now okay.

That is ordinarily an error because "enum class E" is not permitted as an
elaborated type specifier.  However, Microsoft compilers do accept that form
and the front end previously aborted on the case above because it failed an
assertion test while prescanning the lambda declarator.  That is now fixed.


10/17/19 [EDGcpfe/21923]
Microsoft C++ compatibility: Extraneous qualifier on template declaration

In Microsoft C++ modes with 1900 <= microsoft_version <= 1910, the front end
now accepts an extraneous namespace scope qualifier on a template declaration:

  namespace N {
    template<typename> void N::f();  // Now accepted in some Microsoft modes.
  }

See also the Changes entries of 11/2/03 and 11/3/03.


10/16/19 [EDGcpfe/21914]
C++-generating back end: Spurious commas generated for implicit initializers

Version 5.1 of the front end introduced a regression in the C++-generating
back end, which caused spurious extraneous commas to sometimes be emitted in
braced initializers that have associated implicit initializers.  For example:

  struct S {
    int i;
    struct N { N() {} } n;
  };
  struct X {
    S s;
    double d = 1.0;
  } x = { 42 };  // Previously rendered as "... { 42, , };"

That is now fixed.


10/16/19 [EDGcpfe/21916]
Deduction of operator templates

Operator functions have certain constraints on their parameters.  For example,
most operators require that at least one parameter have a class or enumeration
type, or a reference type for such a type.  Previously, the front end failed to
diagnose violations of such constraints when instantiating operator templates.
Now such violations are handled as deduction failures.  For example:

   template<typename T> struct X { operator T const&(); };
   struct B {};
   struct D : public B {};
   template<typename T> bool operator==(T const&, B const*);
   bool g(D *x, X<B*> y) {
     return x == y;  // Previously an ambiguity error.  Now picks the
   }                 // built-in 

Previously, this resulted in an ambiguity error: The operator== template
instantiated to operator==(D *const &, B const*) conflicted with the builtin
equality operator.  Now, that operator== instance is discarded because neither
of its parameters is a class or enumeration type.


10/15/19 [EDGcpfe/21775]
C++-generating back end: "constexpr" on friend functions in class templates

The front end previously failed to record the presence of a "constexpr" (or
"consteval") specifier in a friend function declaration appearing in a class
template (at least, in the prototype instantiation of that class template).
This caused the specifier to be omitted from the output of the C++-generating
back end.  For example:

  template<typename T> struct S {
    friend constexpr bool operator==(S, S) { return true; }
      // Previously, the "constexpr" specifier was not rendered by the
  };  // C++-generating back end.

That is now fixed.


10/14/19 [EDGcpfe/21912]
Incorrect overload resolution for C++20 comparison operators

Consider:

  struct X { bool operator==(const X &b); };
  bool b = X() == X();  // Previously always okay.
                        // Now an error in C++20 mode.

In C++20 mode (per the working paper) this should be ambiguous because two
candidates are considered for the equality operator: (1) the declared member
operator==, and (2) a synthesized operator obtained by reversing the *this and
b parameters (which is a "const" member function with a "reference to
(nonconst) X" parameter).  However, the front end previously accidentally
dropped that second candidate when it is a nonstatic member function.  That is
now fixed.


10/10/19 [EDGcpfe/16652,EDGcpfe/18881,EDGcpfe/21224,EDGcpfe/21879]
Abort on nested generic lambdas

The front end sometimes aborted (in scope_depth_for_capture, defined in expr.c)
when trying to resolve a variable requiring capture in a nested generic lambda.
For example:

  struct S { static constexpr int b = 0; };
  template<typename F> void g(F &&f) { f(S{}); }
  int main() {
    int r = 0;
    g([&](auto id1) {
      g([&](auto id2) { [&]{ r = 1; }(); });  // Previously triggered an
    });                                       // internal error.  Now okay.
    return r;
  }

That is now fixed.


10/10/19 [EDGcpfe/20266,EDGcpfe/21689]
Right-to-left expression evaluation and destructors for temporaries

In C++17 mode, some operations (like assignments) have their operands
evaluated in "right-to-left" order (see also the entry of 9/19/17 for
EDGcpfe/17701).  Previously, however, the front end did not adjust the
destructor invocations for temporaries constructed in such operands.
For example:

  extern "C" int printf(char const*, ...);
  struct X {
    X(char const *str) : str(str) { printf("C[%s]", str); }
    ~X() { printf("D[%s]", this->str); }
    char const *str;
  };
  void operator+=(X const&, X const&) {}
  int main() {
    X{"L"} += X{"R"};
    printf("\n");
  }

Previously, this printed "C[R]C[L]D[R]D[L]".  Now, "C[R]C[L]D[L]D[R]" is
output instead.

Also, the lowering of expression nodes has been modified to lower expression
nodes in the same order as they would be executed so that any temporaries
the may be created or destroyed are performed in the correct order.


10/9/19  [EDGcpfe/21893]
Template substitution of explicit conversion function invocation

The front end previously did not correctly handle the substitution of an
explicit conversion function invocation.  For example:

  template<typename T> auto f()->decltype(g(T{}).operator T*());
  struct S {
    operator S*() const;
  };
  S g(S);
  int r = f<S>();  // Previously triggered a spurious error.

In this example, during template argument deduction, S must be substituted for
T in the expression g(T{}).operator T*(), but the front end failed to do so.
As a result, a spurious error was issued for the call (in this case about the
instantiation and substitution not producing identical types).  That is now
fixed.


10/8/19  [EDGcpfe/21770]
C18: Allow _Alignas in compound literals

The ISO defect report 444 clarifies that compound literals can have _Alignas
attributes.  That construct is now accepted in --c11 and later modes.  Note
that the _Alignas attribute is attached to the type for the compound literal as
a typeref with variant.typeref.for_type_attributes set to TRUE.  For example:

  void f() {
    int x;
    x = (_Alignas(32) int){1};
  }


10/8/19  [EDGcpfe/21862]
Core issue 2351: void{}

In modes that accept C++11-style list initialization, the front end now accepts
an expression of the form "void{}" and treats it like "void()".  This
implements the standardization committee's resolution for Core issue 2351.


10/7/19  [EDGcpfe/21366]
Copy elision with the Cfront ABI

Consider:

  struct S {
    S() = default;
    S(const S&) = default;
    ~S();
  };
  S foo(S *p) {
    return static_cast<S>(*p);
  }

The static_cast conceptually creates a copy of the lvalue *p, and that copy is
then copied as the return value.  With the IA-64 ABI, the presence of the
nontrivial destructor causes S to be returned through a hidden pointer
parameter, and the copy for the static_cast is made directly through that
pointer, thereby eliding the second copy.  In the Cfront ABI, however, the
value is returned using the traditional C-like mechanism and the additional
copy was not elided.  The front end has been updated to elide the copy even
in the Cfront ABI.  The ABI itself has not changed: I.e., the value is still
not returned through a hidden pointer parameter.


10/4/19  [EDGcpfe/21877]
C++-generating back end: direct-initialized structured binding from array

The C++-generating back end previously aborted with an assertion failure
(in gen_paren_or_brace_dynamic_init) with source containing a structured
binding direct-initialized from an array object.  This is now fixed.  For
example:

  int f(int (&a)[3]){
    auto [ e, f, g ] (a);  // Previously aborted, now okay
    return g;
  }


10/4/19  [EDGcpfe/21871]
C++-generating back end: class types declared in template arguments

In C++-generating back end configurations in which
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, if the
source declares a class type in the template argument list of a template
defined in a different namespace from the one where the reference occurs, the
generated explicit specialization for the implicitly-instantiated class
template was incorrect.  In particular, the explicit instantiation was
correctly placed into the proper namespace but the class type was declared
in that namespace; as a result, when the class from the template argument was
later referred to, omitting the class/struct/union keyword, the name was not
found and the generated code could not be compiled.  This has now been
addressed by explicitly declaring such class types before the generated
explicit specialization is emitted.  For example:

  namespace N {
  template<typename> struct S { };
  }
  struct A {
    typedef N::S<struct U> NSU;
    NSU nsu;
  };

The generated output for this example previously contained the explicit
specialization

  namespace N { template<> struct S<struct U> { }; }

which declared N::U instead of ::U.  This is now put out as

  struct U;
  namespace N { template<> struct S<U> { }; }

so that subsequent references to "U" refer to the correct type.


10/3/19  [EDGcpfe/19146,EDGcpfe/19818,EDGcpfe/20689,EDGcpfe/21875]
Spurious failure to constant-evaluate constexpr constructor call

The front end previously sometimes failed the constant-evaluation of constexpr
constructor calls, leading to spurious errors about accessing "expired
storage".  For example:

  constexpr int id(int p) { return p; }
  struct S {
    int v1, v2;
    constexpr S(int p) : v1{p}, v2{this->v1} {}
  };
  constexpr int g(int p) {
    S s(id(p));
    return s.v2;
  }
  constexpr int r = g(0);  // Previously triggered an error.  Now okay.

That is now fixed.


10/2/19  [EDGcpfe/21180]
Missing access error on use of inherited using-declaration

If a reference was made to an inherited inaccessible using-declaration,
the access error was not detected in some cases.  This could cause incorrect
behavior if the access affected SFINAE.  Now fixed.

  struct A {
    int f() { return 0; }
  };
  class B : public A {
    using A::f;
  };
  struct C : public B {};
  typedef decltype(C().f()) f_type;;  // An error is now issued


10/2/19  [EDGcpfe/21869]
Assertion failure in builtin_function_type

In GNU emulation mode when gnu_version >= 90000 or clang emulation mode when
clang_version >= 90000, the use of __builtin_is_constant_evaluated in pre-C++11
modes would result in an assertion failure in builtin_function_type.
That is now fixed.  For example, with --c++03 --gnu_version 90100:

  void f() {
      __builtin_is_constant_evaluated();
  }


10/2/19  [EDGcpfe/21353]
Spurious constexpr-constraint error on inheriting constructor

Consider:

  struct X { X(int) {} };
  template<typename T> struct B {
    T val;
    constexpr explicit B(T p): val(p) {}
  };
  struct D: B<X> {
    using B::B;  // Previously a spurious error.  Now okay.
  };
  int main() { D d(X{42}); }

The instantiation of the constructor B<X>::B(X) is not constexpr because X is
not a literal type.  That is not an error because the constructor is the result
of template instantiation.  However, the front end previously (erroneously)
issued an error about the generated inheriting constructor being constexpr but
involving a non-literal type X.  That is now fixed.


10/2/19  [EDGcpfe/21819]
Segfault in form_float_constant

When compiling the front end with g++ and using lib_gcc < 7.0.0, converting
a long double positive infinity floating-point constant to __float128
erroneously results in a NaN value (rather than positive infinity).  That
difference could cause a segfault in form_float_constant in configurations
where HOST_FP_VALUE_IS_128BIT is TRUE and USE_SOFTFLOAT is FALSE.  A change has
been made to address the segfault, but it is recommended that lib_gcc >= 7.0.0
be used to avoid these floating-point conversion issues.  For example, with
--gcc:

  long double infl = __builtin_infl();


10/1/19  [EDGcpfe/21854]
GNU/Clang C++ compatibility: __final in class templates

The changes for EDGcpfe/14942 (see entry of 10/13/16) meant to enable treating
"__final" as a synonym for "final" in GNU C++ modes.  However, that change did
not affect some template cases.  For example:

  template<typename> struct X __final {};  // Previously always an error.
                                           // Now accepted in GNU C++11 mode.

That is now fixed.  Furthermore, this behavior now also applies to Clang C++
modes.


10/1/19  [EDGcpfe/20537]
Spurious error on constexpr access to array first declared without bound

Consider:

  extern const int arr[];
  constexpr auto p = arr;
  constexpr int f(int i) { return p[i]; }  // (X)
  constexpr int arr[] = { 1, 2, 3 };
  constexpr int x = f(2);  // Previously an error.  Now okay.

Previously, the call f(2) failed to evaluate as a constant because the
expression p[i] on line (X) does not reflect the array length determined
later on.  That is now fixed.


9/30/19  [EDGcpfe/21849]
Constant-evaluation of complex floating-point conversions

Previously, the front end did not correctly handle conversions between
different complex floating-point precisions.  Incorrect complex constants were
produced in the IL as a consequence of this defect.  For example, in GNU C++
mode:

  constexpr __complex float zf = { 1.0, 2.0 };
  constexpr __complex double g(__complex float const &p) { return p; }
  __complex double z = g(zf);
      // Previously, the a_constant entry representing the initializer for z
      // did not represent the correct value.

That problem is now fixed.


9/27/19  [EDGcpfe/21584]
Defaulted operator<=>

In C++20, it is possible to define a defaulted operator<=> for a given class.
Previously, the generated definition for such a defaulted operator was
specified entirely in terms of <=> being applied to its subobjects.  Recently,
however, the C++ standardization committee made some changes to that approach
through its paper P1186R3.  In particular, these changes allow an operator<=>
to be synthesized for a class with a subobject that has no associated <=>
operator, but instead has == and < operators, provided the return type of the
defaulted operator<=> is not deduced.  For example:

  #include <compare>
  struct C {
    bool operator==(C const&) const;
    bool operator<(C const&) const;
  };
  struct S {
    int i;
    C c;
    std::strong_ordering operator<=>(S const&) const = default;
      // The c member is compared using == and <.
  } x, y;
  auto r = x <=> y;  // Previously an error.  Now accepted.


9/27/19  [EDGcpfe/21812]
Infinite loop rescanning certain built-in operations

An infinite loop could occur if certain built-in operations (such as
__is_constructible) appeared in a variadic rescan context and were rescanned
with an empty pack.  This problem potentially existed for a long time, but
only began occurring with this test case in release 5.1 as a consequence
of another change.

  template <typename T, bool> using A = T;
  struct B {
    template <typename T, typename... b>
    auto f() -> A<int, __is_constructible(T, b...)>;
    template <typename T = B> decltype(&T::template f<int>) k(int);
    operator bool() { return k(0); }
  };


9/27/19  [EDGcpfe/21839]
C++-generating back end: new-expression with pointer-to-member-function typedef

In C++-generating back end configurations in which
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
generated code contains explicit specializations for templates that are
implicitly instantiated in the original source code.  Previously, if the
source code contains a template with a new-expression where the type is
dependent, and the template is instantiated from a reference in which that
type is given as an inaccessible typedef designating a
pointer-to-member-function type, the generated code emitted the
new-expression in the corresponding generated explicit specialization in an
incorrect form, using the underlying type of the typedef but failing to
enclose the type in parentheses.  This is now fixed.  For example:

  template<typename T> void* f() {
    return new T;
  }
  class S {
    typedef void (S::*mfp)() const;  // typedef is private
    static void* p;
  };
  void *S::p = f<mfp>();

The code generated for this example previously contained an explicit
specialization for the function template f() as follows:

  template<> void *f<void (S::*)(void) const> () {
    return new void (S::*)(void) const;
  }

The new-expression in that generated explicit specialization contains a
syntax error because the type should have been parenthesized.  The
generated explicit specialization is now correct:

  template<> void *f<void (S::*)(void) const> () {
    return new (void (S::*)(void) const);
  }


9/24/19  [EDGcpfe/21587]
Minor changes to handling of comparison operators

The C++ standardization committee made some changes to the way comparison
operators are handled through its paper P1630R1.  The changes for EDGcpfe/20014
(see entry of 6/14/19) anticipated some of those changes, but not all.  The
front end now more closely implements P1630R1.  For example:

  #include <compare>
  struct S {
    int i;
    friend int operator==(S const&, S const&);
    friend bool operator!=(S const&, S const&) = default;
      // operator!= is deleted here because the corresponding operator==
      // does not return type bool.
  } s;
  bool r = s != s;  // Previously accepted.  Now an error because operator!=
                    // is deleted.


9/23/19  [EDGcpfe/21811]
Abort after erroneous definition of implicitly-declared special member

The changes for EDGcpfe/19122 (see entry of 2/11/19) in version 5.1 introduced
a regression in configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE.
Specifically, having a class definition with an implicitly-declared trivial
special member followed by an explicit definition of that member resulted in an
internal error in eliminate_function_body_source_sequence_entries (src_seq.c).
The internal error followed one or more ordinary errors.  For example:

  struct S {};
  S::S() {}  // Previously triggered an abort in some configurations.

That is now fixed.


9/23/19  [EDGcpfe/20875]
Clang compatibility: Ignoring ill-formed attributes before extern "C"

Attributes may not appear before a C++ linkage specification, but clang
appears to accept and ignore such ill-formed attributes.  The front end now
issues a warning in such cases in clang emulation mode (as it also currently
does in Microsoft emulation mode).  For example (with --clang --ms_extensions):

  __declspec() extern "C" void f();   // now a warning in some modes


9/23/19  [EDGcpfe/21809]
Const-qualified lowered constants

A change in version 5.1 caused some lowering-generated constants not to be
const-qualified (whereas previously they had been).  This change restores
the previous behavior.  For example (with --c++11):

  struct A {};
  const A a;
  A f() {
    return a;
  }


9/23/19  [EDGcpfe/21799]
Clang compatibility: Updated builtins for clang 9.0.0

Builtin functions definitions have been updated to reflect the recent release
of clang 9.0.0.


9/20/19  [EDGcpfe/21786]
GNU C compatibility: Folding of calls to implicitly-aliased functions

In GNU C mode, the front end sometimes implicitly aliases functions that match
standard C library functions to their __builtin_... counterparts (see the
entries for EDGcpfe/10179, EDGcpfe/10328, and EDGcpfe/14348).  Calls to such
functions can appear in constant-expression contexts, but the changes for
EDGcpfe/14569 (entry of 11/15/13) limited that feature to modes with
gnu_version < 40500.  It now appears that GCC still does evaluate such calls
at compile time if they appear in static-lifetime variable initializers, but
not in other contexts requiring constant evaluation (like array dimensions).
The front end now emulates that distinction.  For example:

  typedef __EDG_SIZE_TYPE__ size_t;
  extern size_t strlen (const char*);
  int x = (int)strlen("abc");  // Accepted in all GNU C modes.
  int y[(int)strlen("abc")];   // Accepted in GNU C modes with
                               //   gnu_version < 40500


9/20/19  [EDGcpfe/21761]
C++-generating back end: class name in qualified name in type reference

The front end uses name reference entries to record the form in which a name
is specified in many contexts, but such information is not available
for references to types.  When record_form_of_name_reference is TRUE
(i.e., in most C++-generating back end configurations), a use of a type is
now represented in the IL by a typeref that is added on top of the referenced
type when that type was specified using a qualified name that refers to an
inherited class member (and not a member of the class specified by the
qualifier).  This allows the C++-generating back end to output the name
using the correct qualifier, which can be important if the member is only
accessible using the proper name.

  struct B {
  protected:
    struct N { };
  };
  struct C : private B {
   protected:
    using B::N;
  };
  struct D : C {
    friend struct E;
  };
  struct E {
    D::N *n;  // Previously emitted as B::N, which is inaccessible
  };


9/19/19  [EDGcpfe/21624]
Narrowing conversion in deduction contexts

The front end did not always correctly treat invalid narrowing conversions as
deduction failures.  For example, in C++17 mode:

  template<int (*p)()>
    constexpr bool narrows(decltype(int{(p(), 0U)})) { return true; }
                                          // Previously a spurious warning.
  template<int (*p)()>
    constexpr bool narrows(...) { return false; }
  int g() { return 0; }
  static_assert(!narrows<g>(0));  // Previously an error.  Now okay.

That problem is now fixed.


9/18/19  [EDGcpfe/21785]
C++-generating back end: befriending base class members

When a friend declaration in a derived class declares a base class member,
the base class member name must be qualified; otherwise, the friend
declaration declares a non-member function or class.  In configurations in
which DEFAULT_RECORD_FORM_OF_NAME_REFERENCE is FALSE, the C++-generating
back end previously failed to put out the class qualifier for such friend
declarations.  This is now fixed.  For example:

  struct A {
    void foo();
  };
  struct B : A {
    friend void A::foo(); // Previously generated as just "foo()"
  protected:
    B() : A() { }
  };
  void A::foo() {
    B *x = new B;         // Previously an access error in the generated code
  }


9/17/19  [EDGcpfe/21789]
Incorrect lowered code for array initialization

Lowering had mistakenly emitted code that could initialize past the end of
an array in some cases, leading to undefined behavior at run time.  This is
a regression introduced in 5.1 and is now fixed.  For example (with --c++14):

  int main() {
    struct A {
      struct B {
        struct C {
          int x = *new int(29);
        } vec[3];
      };
      B b{};
    };
    delete [] new A[2];   // Had written past end of array.
    return 0;
  }


9/17/19  [EDGcpfe/21513]
C++/CLI: Properties and inheritance

Consider the following C++/CLI code:

  ref struct B {
    property int v {
      void set(int) {}
      virtual int get() { return 0; }
    }
  };
  ref struct D: B {
    D(): B() {}
    property int v {
      virtual int get() override { return 0; }
    }
  };
  void g() {
    D^ d = gcnew D();
    d->v = 42;  // (1) Previously an error.  Now okay.
  }

Line one previously triggered an error because it needs a writable property
d->v and only found a read-only property definition in the definition of D.
Now, the code is accepted because the inherited v::set member is found.


9/17/19  [EDGcpfe/21791]
IA-64 ABI: Incorrect mangled name for some constructors/destructors

Another case similar to that described in the Changes entry for EDGcpfe/20424
has been fixed.  This only occurs in IA-64 ABI configurations that have
DEFAULT_MAX_MANGLED_NAME_LENGTH set to a non-zero value when mangling a
constructor or destructor name that exceeds that length.


9/17/19  [EDGcpfe/21790]
Remove unused gnu_init_priority_attribute_enabled

Changes to the source code in 4.1 rendered gnu_init_priority_attribute_enabled
unused so it is now removed (along with the
DEFAULT_GNU_INIT_PRIORITY_ATTRIBUTE_ENABLED configuration macro).


9/16/19  [EDGcpfe/21627]
GNU compatibility: using-declarations for member function templates

Consider:

  template<typename, typename> struct C;
  template<typename T> struct C<T, T> {
    using Type = T;
  };
  struct B {
    template<typename T, typename = typename C<T, int>::Type>
      int operator=(T);
  };
  struct D: B {
    using B::operator=;
    template<typename T, typename = typename C<T, float>::Type>
      int& operator=(T);
  } d;
  int r = (d = 42);  //  Now accepted in GNU C++ mode.

The assignment in the last line is usually invalid because only the operator=
template in D is found and its default template argument fails to instantiate.
However, GCC accepts the case and now we do as well in GNU C++ mode: The base
member is added to the overload set (instead of being hidden by the derived
class member), but only if the derived-class member returns a different type.


9/16/19  [EDGcpfe/21664]
__is_constructible and incomplete types

Previously, applying __is_constructible to an incomplete class or enumeration 
type -- either the constructed type or an operand type -- was accepted and
resulted in a "false" value.  Now such cases elicit a diagnostic in non-GNU
modes (or a deduction failure it they occur during template argument
deduction).  For example:

  struct S;
  bool r = __is_constructible(int, S);  // Previously okay (with FALSE value).
                                        // Now an error in non-GNU modes.

A similar change was made for __is_destructible.


9/16/19  [EDGcpfe/21782]
Abort on union designators in statement expression in GNU C mode

The changes for EDGcpfe/20980 (version 5.1) introduced a regression in GNU C
mode: A statement expression containing multiple designators for a union
initializer could result in an internal error in extract_value_from_constant
(interpret.c).  That is now fixed.


9/14/19  [EDGcpfe/21772]
Internal error with large and complex macro expansions

The change for EDGcpfe/18829 (in version 5.0) caused the front end to abort
with an internal error ("assoc_source_line_modif: bad address") or have
other incorrect behaviors when processing some large complex macro
expansions.  This is now fixed.


9/13/19  [EDGcpfe/19555,EDGcpfe/21781]
Spurious deduction failure for non-deducible use of nontype template parameter

Consider:

  template<typename T> int g(T, char(*)[sizeof(T)]);
  int r = g(1.0, 0);  // Previously an error.  Now okay.

This should be valid: The first argument in the call deduces T = double, and
the second argument does not produce a deduction because T in the corresponding
parameter is non-deducible.  The second argument is therefore treated like a
null pointer constant.  However, previously, the front end erroneously
considered T in the second parameter type to be deducible and therefore failed
to match the argument 0 as a null pointer constant.  That is now fixed.


9/12/19  [EDGcpfe/21705]
Abort on recursive use of __is_constructible (and similar)

The type traits helper function __is_constructible (and some similar type
traits helper functions) is sometimes evaluated in the front end by setting up
an expression that is "rescanned" (i.e., substituted much like what happens
during template argument deduction).  In some complex cases, that substitution
can trigger recursive evaluation to the same __is_constructible query, but the
front end previously did not reliably handle such recursion and sometimes
aborted with an internal error ("missing default rescan info", in exprutil.c).
That is now fixed.


9/12/19  [EDGcpfe/21323]
Incorrect declared type for explicit specialization of variable template

An explicit specialization of a variable template sometimes had an incorrect
declared_type.  This would occur if the declared type of the explicit
specialization differed from the one produced by instantiating the declaration
of the variable template.  In the example below the declared_type field of
b<0> was B<0> when it should have been "auto"

  struct A { };
  constexpr A a{};
  template<int N> struct B { };
  template<int N> constexpr B<N> b{};
  template<> constexpr auto b<0> = a;



9/12/19  [EDGcpfe/21464]
Performance with large number of function template explicit specializations

The processing of explicit specializations of function templates could
result in poor performance if a program contained a very large number of
explicit specializations of a given function template.  Now fixed.


9/12/19  [EDGcpfe/21755,EDGcpfe21756]
C18 mode

The front end now accepts the option "--c18" to enable C18 mode.  C18 is a
"bug fix" version of the C11 standard, and, consequently, in C18 mode the
front end currently behaves differently from C11 mode in only a few ways:
  - the macro __STDC_VERSION__ is predefined to 201710L,
  - type qualifiers are completely ignored on function return types
    (resolution of DR423), and
  - the first operand of a _Generic construct undergoes the usual
    conversions (resolution of DR481; this was already the case in GNU C11
    mode).

For example:

  int f(void);
  int const f(void);  // Error in C11 mode.  Okay in C18 mode because of
                      // the resolution of DR423.

C18 was originally meant to be C17 and various other implementations and
documents refer to it under the "C17" name.  The front end therefore also
accepts "--c17" as an option equivalent to "--c18".


9/11/19  [EDGcpfe/21553]
Abort due to missing rescan info in some uses of partial specializations

The changes for EDGcpfe/20975 (in version 5.1) introduced a regression in some
complex cases involving the use of partially specialized class templates.  The
problem manifested itself as an internal error "missing default rescan info"
(in exprutil.c).  That is now fixed.


9/11/19  [EDGcpfe/21512]
Incorrect setting of needed flag when using --no_extern_inline

The --no_extern_inline option was provided for compatibility with very
early C++ compilers that emitted inline functions as static functions
that did not have the semantics required when the standards committee gave
inline functions external linkage by default.  In some cases the flag
associated with this option was not tested when it should have been.
This resulted in, for example, the needed flag being incorrectly set to
TRUE for A<int>::f in the example below.  Now fixed.

  template <class T> class A {
    static void f(){}
  };
  template class A<int>;


9/10/19  [EDGcpfe/21754]
Incorrect lookup in member initializer scanned on-demand

A change made in version 4.11 could result in an incorrect lookup in a
member initializer when the evaluation of the initializer is required
before the normal completion of the class.  This can occur, for example,
if the class has been used in an instantiation through use as a template
argument (in the example below the member initializer in X::Y is needed
when Y is used as a base class via the instantiation of B<Y>).  The lookup
incorrectly ignored names declared after the declaration of the class being
instantiated.  Now fixed.

  template <class T> class A { typename T::a x; };
  template <class T> class B {
    struct C : T { typedef int a; };
    A<C> x;
  };
  namespace N { struct C { }; }
  struct X {
    struct Y {
      int a = sizeof(N::C);
      Y() = default;
      Y(int i);
    };
    B<Y> b;
  };


9/10/19  [EDGcpfe/17960,EDGcpfe/21766]
Microsoft compatibility: __has_extension/__has_feature

In configurations where DEFINE_FEATURE_TEST_MACRO_OPERATORS_IN_ALL_MODES is
TRUE, a warning is now given in Microsoft emulation mode for the
__has_extension and __has_feature feature-test macros (and the macros
return 0).

Also, a change has been made to enable the __has_include feature-test macro
in more modes (including GNU C mode when gnu_version >= 40902), and is now
independent of the DEFINE_FEATURE_TEST_MACRO_OPERATORS_IN_ALL_MODES
configuration macro (since __has_include is part of C++17).

__has_include_next (not part of the C++17 standard) continues to be enabled
only in modes where the emulated compiler supports it or when
DEFINE_FEATURE_TEST_MACRO_OPERATORS_IN_ALL_MODES is TRUE.


9/10/19  [EDGcpfe/21760]
C++-generating back end: qualification in implicit-this member selection

In the case where a member name is hidden by a local declaration in a
member function and the member is accessed using an implicit "this", the
C++-generating back end failed to put out the necessary qualifier on the
member name to circumvent the hiding.  This is now fixed.  For example:

  struct C {
    int i;
    bool f() {
      int i;
      return C::i == 2;  // Previously put out without "C::"
    }
  };


9/9/19   [EDGcpfe/21701]
Instantiation of exception specifications for member function templates

Consider in C++14 mode:

  template<typename T> struct B {
    template<typename...> B() noexcept(T::X);
  };
  struct D: B<int> {};  // Triggered an error in version 5.1.
                        // Now accepted in non-Microsoft pre-C++17 modes.

After the changes for EDGcpfe/20840 (see entry of 2/4/19) the front end now
issues an error for that; so does Microsoft's compiler, but it is a regression
in non-Microsoft modes.  The change for EDGcpfe/20840 has therefore been
disabled for member functions in non-Microsoft modes, which causes the front
end to accept the above case again in non-Microsoft pre-C++17 modes.


9/9/19   [EDGcpfe/21629]
Assertion failure folding unary operation on vector operand

When the type of a GNU-compatible vector constant is specified via a typedef,
a unary operation applied to that constant resulted in an assertion failure
(in unary_operation).  That is now fixed.  For example, with --g++:

  typedef int VECT __attribute__((vector_size(16)));
  VECT x = -((VECT){0,0,0,0});  // Previously resulted in assertion failure


9/6/19   [EDGcpfe/21685]
C++-generating back end: Abort on malformed constructor template definition

The C++-generating back end previously triggered an internal error when
attempting to render a malformed constructor template that the front end failed
to diagnose.  For example:

  struct S {
    int i;
    template<typename T> S(T i) : i(i);  // Previously aborted.  Now fixed. An
  };                                     // error is issued in modes where the
                                         // definition is parsed.

That is now fixed.


9/4/19   [EDGcpfe/21732]
Incorrect lowering of _Generic construct

In configurations where REPRESENT_C11_GENERIC_CONSTRUCT_IN_IL is TRUE, lowering
of the C11 _Generic construct was incomplete and could result in an assertion
failure (in match_routine_type_in_call).  That has now been fixed.  For
example (with --c11):

  long double fld(long double x);
  double fd(double x);
  float ff(float x);
  #define fg(X) _Generic((X), long double:fld, default:fd, float:ff)(X)
  void f(void) {
    fg(0.0L);
  }


9/4/19   [EDGcpfe/21706]
__is_trivially_copyable for unions with non-trivially copyable members

The change for EDGcpfe/21184 (in version 5.1) inadvertently introduced a
regression in the evaluation of __is_trivially_copyable for unions with
non-trivially copyable members.  For example:

  struct S {
    S& operator=(const S&);
  };
  union U {
    S s;
  };
  static_assert(!__is_trivially_copyable(S));
  static_assert(!__is_trivially_copyable(U)); // Would previously fail

This is now fixed.


9/3/19   [EDGcpfe/19115]
Multiple translation units: Redeclaration error with opaque enum decl

When compiling multiple translation units where two translation units declare
the same enum and at least one of those declarations is opaque, the front end
would issue a spurious "incompatible redeclaration" error.  For example, if
t1.cpp contained this:

  enum class E { EV }; // Spurious incompatible redeclaration error

and t2.cpp contained this:

  enum class E; // Spurious incompatible redeclaration error

then compiling both files on the same command line would result in an error.
This is now fixed.


9/3/19   [EDGcpfe/21719]
C++-generating back end: assertion failure with user-defined literal

In C++-generating back end configurations with non-const string literals
(either by setting the configuration macro DEFAULT_STRING_LITERALS_ARE_CONST
to FALSE or via the command-line option --no_const_string_literals), an
invocation of a raw literal operator (i.e., one with a const char *
parameter) resulted in an assertion failure in handle_operator_call.  This
is now fixed.  For example, with --no_const_string_literals --c++11:

   unsigned operator "" _w(const char*);
   void f() {
     12_w;  // Previously an assertion failure, now okay
   }


8/29/19  [EDGcpfe/21683]
C++-generating back end: friend function parameters and name lookup

In some cases the C++-generating back end failed to use a qualified name in
the code generated for a friend declaration when the qualification is
needed to avoid matching an incorrect declaration found by unqualified
lookup.  This has now been addressed by extending the change for
EDGcpfe/20394 to apply to all modes, not just g++ and clang modes, and thus
always using qualified names in the parameter list of a friend function
declaration.  For example:

  namespace N1 { class B; }
  namespace N2 { void f(N1::B&); class B; void f(N2::B&);}
  namespace N1 {
    class A {
      friend void N2::f(N1::B&);  // Previously generated as f(B&), thus
                                  // matching f(N2::B&)
      int m;
    };
  }
  class N1::A g;
  namespace N2 {
    void f(N1::B& b) {
      g.m = 1;  // Previously an access error in the generated code because
                // the friend declaration matched f(N2::B&), not this function
    }
  }


8/27/19  [EDGcpfe/21702]
C++-generating back end: missing explicit template parameter list for lambda

In C++20 mode, a generic lambda can have a traditional template parameter
list instead of, or in addition to, having function parameters that use the
"auto" type specifier (see the description for
[EDGcpfe/20004,EDGcpfe/20273]).  However, the C++-generating back end
failed to put out the template parameter list for such lambdas.  This is
now fixed.  For example, with --c++20:

  auto f = []<typename T>(T a) {};  // Previously omitted "<typename T>"


8/26/19  [EDGcpfe/21698]
C++-generating back end: incorrect IL for initializer after code generation

The changes for EDGcpfe/20976 (in version 5.1) introduced a regression for
applications that examine the IL after the C++-generating back end is run:
for variables whose initial value is the result of folding a dynamic
initializer to a constant, the C++-generating back end overwrote the
constant in the an_initializer entry with the original dynamic initializer
but left the variable's init_kind field as initk_static.  This is now
fixed, and the an_initializer entry is restored to the original folded
constant once the code for the initialization has been generated.


8/26/19  [EDGcpfe/21695]
C++-generating back end: unnamed class types and decltype-specifiers

When an unnamed class type is used as the type of a non-static data member
and that class is referred to via a decltype-specifier, the C++-generating
back end used an undeclared temporary name (of the form __T12345678) to
refer to that type in the generated code.  That is now fixed.  In addition,
the changes for EDGcpfe/21274 (in version 5.1) introduced a regression for
the similar case of a variable member of a namespace whose type is an
unnamed class, using an undeclared temporary name to refer to that type.
That regression is also fixed.  For example, with --g++ --c++11:

   struct {
       struct { char c;} m;
   } a;
   namespace N {
     struct {
       int i;
     } b;
   }

   template <typename T> void f(T) { }

   void func(){
     f<decltype(a.m)>(a.m);    // Previously generated as
                               // f<decltype(a)::__T12345678>(a.m), now as
                               // f<decltype(decltype(a)::m)>(a.m)
     f<decltype(N::b)>(N::b);  // Previously generated as
                               // f<N::__T12345678>(N::b)
   }


8/23/19  [EDGcpfe/21166]
C-generating back end: type list ordering

When ENSURE_LOWERED_TYPE_LIST_ORDERING is TRUE, the type list is sorted to
ensure that the type list is in order.  Typically a back end C compiler allows
a pointer to an incomplete type, but clang and GCC version 4.0.0 and later
don't allow a pointer to an incomplete array type.  A change has been made to
reflect that in the ordering.  For example:

  namespace N {
    struct A {};
  }
  struct B {
    B();
    N::A (*m)[2];
  };
  B::B() {}


8/23/19  [EDGcpfe/16614,EDGcpfe/20883]
Clang compatibility: ext_vector_type attribute

Basic support for clang's ext_vector_type attribute has been added.
Additionally, support has been added for an undocumented variant of clang's
__builtin_shufflevector where there are two arguments and the second
argument is a vector of integral types.  Note that at the present time,
no additional support for these vector types (e.g., V.wxyz expressions) has
been added.  For example (with --clang):

  typedef float float4 __attribute__((ext_vector_type(4)));
  typedef unsigned int uint4 __attribute__((ext_vector_type(4)));
  void f(float4* A, float4 x, uint4 mask) {
    *A = __builtin_shufflevector(x, mask);
  }


8/23/19  [EDGcpfe/21384]
Spurious access error instead of substitution failure

In certain cases the front end would issue an access failure error when
attempting to instantiate a template, instead of producing a substitution
failure.  For example:

  template<class Tx> void f(const Tx &);
  template<class Tx> auto g(int) -> decltype(f<Tx>({}));
  template<class Ty> bool g(float);
  class A
  {
    A() {}; // Private ctor
  };
  decltype(g<A>(0)) a; // Spurious A::A() is inaccessible error

This is now fixed.


8/22/19  [EDGcpfe/21652]
Incorrect lookup of name following "template" in some contexts

In contexts where the name following "template" could be a class member
or a name from the current context, the front end sometimes incorrectly
used the name from the current context during a prototype instantiation,
which could result in spurious errors.  Now fixed.

  template <typename T> struct A {
    template <int I> void B() {}
  };
  template <typename T> struct B {
    void f() {
      A<T> a;
      a.template B<0>();
    }
  };
  int main() {
    B<int> b;
    b.f();
  }


8/21/19  [EDGcpfe/21694]
--no_short_enums command-line option

Previously the front end only accepted the --short_enums command-line
option and not its negation, because the option is only applicable in GNU C
modes and the default behavior for all supported GNU C modes is not to
produce short enumerations.  Now, however, the --no_short_enums
command-line option is accepted.  This allows overriding a project-wide
--short_enums via a --no_short_enums appearing later in the command line
for specific files, for example, as well as accommodating customers who
have local modifications in support of platforms for which enumerations are
short by default.


8/21/19  [EDGcpfe/21621]
C++-generating back end: explicit specializations of function templates with
a dependent decltype-specifier return type

In configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, the
C++-generating back end represents implicit instantiations of function
templates as explicit specializations.  When the return type of a function
template is a dependent decltype-specifier, a generated explicit
specialization for it triggered a bug in versions of MSVC prior to 19.15,
causing them to issue a spurious error C2912, "not a specialization of a
function template".  In order to avoid this bug, the C++-generating back
end now suppresses such generated explicit specializations when
msvc_is_generated_code_target is TRUE and msvc_target_version_number is
less than 1915.  For example, with --microsoft --msvc_target_version=1914
--c++17:

  template<typename T> int f();
  template<typename T> auto g(T) -> decltype(f<T>());
  int i = g(0);

The generated code previously contained an explicit specialization,

  template<> auto g(int)->decltype((f<int>()));

which triggered the MSVC bug.  This explicit specialization is now
suppressed in the affected modes.


8/19/19  [EDGcpfe/19039,EDGcpfe/21626]
Spurious error brace-initialized ctor-initializer that is a pack expansion

If a class template contained a constructor with a ctor-initializer that
used a brace-initialized pack expansion (i.e., "A<Ts>{args}..." in the
example below), spurious errors were issued.  Now fixed.

  template <typename T> struct A {
    A(T t);
  };
  template <typename... Ts> struct B : public A<Ts>...  {
    B(Ts&&... args) : A<Ts>{args}... {}
  };
  int main() {
    B<char, short , int, long> b('c', 1, 2, 3L);
  }


8/15/19  [EDGcpfe/21631]
Spurious error for class defined in statement expression in function template

The changes for EDGcpfe/20016 (in version 5.1) resulted in the front end
issuing a spurious error when a class is defined in the body of a GNU
statement expression that appears within the definition of a function
template.  This is now fixed.  For example, with --c++14 --g++:

  template<typename> void f () {
    int a = ({ struct A{} b; 42; }); // Previously a spurious error, now okay
  }


8/15/19  [EDGcpfe/21644]
Constexpr explicit specialization of variable templates and initializers

The front end previously failed to diagnose missing initializers on constexpr
explicit specializations of variable templates.  For example (in C++14 mode):

  template<typename T> inline T v = T();
  template<> constexpr int v<int>;  // Previously accepted.  Now an error
                                    // because the constexpr variable is not
                                    // initialized.

That is now fixed.


8/15/19  [EDGcpfe/21660]
Abort in Clang mode during error recovery

During some error recovery situations the front end could abort due to access
through a null pointer in Clang mode (in scan_expr_full).  For example:

  namespace N { template<typename> struct E; }
  template <class T> struct E {};
  using namespace N;
  void f() {
    E<int> e;  // Error: Ambiguous E.  Previously aborted afterwards.
  }

That problem is now fixed.


8/15/19  [EDGcpfe/21632]
C++-generating back end: incorrect reference to injected-class-name in friend

The changes for EDGcpfe/20394 and EDGcpfe/20426 (both in version 5.1)
resulted in a regression in which a friend function declaration appearing
in a class template with an unnamed template parameter and using the
injected-class-name of the class template in a parameter type of the friend
function incorrectly referred to the injected-class-name using a qualified
name.  This is now fixed.  For example, with --g++:

  namespace N {
  template<typename> struct S {
    friend void f(S);  // Previously generated as f(N::S)
  };
  }


8/15/19  [EDGcpfe/21665]
Volatile and trivial copyability

The changes for EDGcpfe/18467 are now also enabled in Microsoft C++ mode with
microsoft_version > 1910 and in GNU C++ mode with gnu_version >= 100000.


8/15/19  [EDGcpfe/21617]
Abort in 5.1 from performance optimizations

A performance improvement made in version 5.1 (see EDGcpfe/20767) introduced
an abort that could occur during partial ordering of function templates.  The
abort would occur in get_template_arg_list_by_pos during partial ordering of
certain class templates that make use of nontype template arguments whose
type depends on other template arguments.  Now fixed.

  template <class T, class U, U N> struct A { };

  template <class T1, class T2, class U2, U2 N2>
  void f(T1 t1, A<T2, U2, N2> t2) { }
 
  template <class T1, class U1, U1 N1, class T2, class U2, U2 N2>
  void f(A<T1, U1, N1> t1, A<T2, U2, N2> t2) { }
 
  int main() {
    A<char, int, 2> a;
    f(a, a);
  }



8/14/19  [EDGcpfe/20871]
C++-generating back end: Rendering of "constexpr" for generated specializations

In C++-generating back end configurations in which the configuration macro
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the front
end renders implicit specializations of function templates or member functions
of class templates as explicit specializations.  Previously, the explicit
specialization usually was rendered with "constexpr" if the associated template
was declared "constexpr".  However, that may result in invalid code: Whereas a
template can validly be declared "constexpr" even when some of its instances
can never produce a constant expression, an explicit specialization may not
be validly declared "constexpr" if it cannot possibly produce a constant
expression (no diagnostic is required by the standard, but some compilers do
issue errors for some cases).  For example:

  int g();
  template<typename T> constexpr int f() {
    return sizeof(T) == 1 ? g() : 42;
  }
  int r = f<char>();

Here, f<char>() cannot ever produce a constant expression, but the front end
previously rendered it as follows (slightly reformatted):

  template<> constexpr int f< char> () {
    return (sizeof(char) == (1)) ? g() : 42;
  }

(Some compilers issue an error on that invalid code.) Now, the "constexpr"
specifier is only issued for such cases if at least one call to the function
was successfully evaluated by the constexpr interpreter.  Since that isn't the
case with the example above, the specialization is instead rendered as:

  template<> inline int f< char> () {
    return (sizeof(char) == (1)) ? g() : 42;
  }

Note: This is a revision of a change made in version 5.1 for the same issue
number EDGcpfe/20871.  Although the "constexpr" specifier is now more
consistently dropped from generated explicit specialization source code when
it is not known to be valid, the IL still reflects the "constexpr" flag
(unlike the original attempt at addressing this issue).


8/13/19  [EDGcpfe/21593]
C++20: Deprecating ill-advised uses of volatile

Committee document P1152R4 (in C++20) deprecates certain uses of volatile
types, as these are often subtly broken at run time.  The following scenarios
are deprecated:
 - Postfix ++ and -- expressions and prefix ++ and -- expressions on volatile-
   qualified operands.
 - Simple assignments to a volatile type, unless they are discarded-value
   expressions or appear in an unevaluated context.
 - Compound assignments to a volatile type (e.g., +=).
 - Volatile-qualified return types and/or parameters in functions.
 - Volatile-qualified structured binding declarations.
For example:

  typedef volatile int volint;
  volint f(int i, volint vi) { // Return type and vi parameter usage deprecated
    int arr[3] = {1,2,3};
    volatile auto [a,b,c] = arr; // Deprecated
    vi++;                        // Deprecated
    vi = i;                      // Not deprecated
    i = vi;                      // Not deprecated
    i = vi = i;                  // Deprecated
    vi -= i;                     // Deprecated
  }


8/13/19  [EDGcpfe/21655]
Abort in unlink_src_seq_entries on invalid typeof construct

The changes for EDGcpfe/17886 (and related) introduced a regression in version
5.1 with configurations that record source sequence entries, causing the front
end to abort with an internal error in unlink_seq_seq_entries when recovering
from an invalid use of typeof in GNU mode.  For example:

  int x;
  int typeof;  // Aborts in version 5.1.  Now an ordinary error.

That is now fixed.


8/12/19  [EDGcpfe/21567]
C++-generating back end: local typedefs as template arguments

The changes for EDGcpfe/21336 (in version 5.1) caused a regression in which
a local typedef name that is used as a template argument was put out in the
generated code with an extraneous global qualifier "::".  This is now
fixed.  For example, with --c++14 --gnu_version=80100:

  template <typename T> int f(T) ;
  template <typename> struct A { };
  template <unsigned long> struct B {
    typedef int type;
  };
  template <typename T> class C : public A<T> {
    template <int N> int g() {
      typedef typename B<N>::type type;
      return f(A<type>());  // Previously generated as A<::type>
    }
  };


8/12/19  [EDGcpfe/21628]
Internal error on invalid specialization of member via using-declaration

An internal error could occur (in full_specialization) on an explicit
instantiation of a member of a class template that was overloaded and
the specialization that was selected was made part of the overload set
by a using-declaration (which makes the program ill-formed).  Now fixed.

  struct A {
    void f();
  };
  template <class T> struct B : A {
    using A::f;
    void f(int);
  };
  template <> void B<int>::f();


8/9/19   [EDGcpfe/21633]
C++-generating back end: local lambdas as template arguments

In C++-generating back end configurations in which
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, using a
local lambda as a template argument to a template which then instantiates
additional templates using the type of that lambda as a template argument
could result in a generated explicit specialization appearing in the
generated code with an undeclared temporary name (of the form __T12345678)
as that template argument.  This has now been fixed; explicit
specializations, in which a type template argument cannot be named, are
now suppressed in the generated code.


8/9/19   [EDGcpfe/21605]
Ignore apostrophe in printf format string

Previously a warning was emitted if an apostrophe was found in a printf
format string; now it is ignored.  For example (with --g++):

  void __attribute__((format(printf, 1, 2))) f(const char * str, ...);
  void g() {
    f("%'d", 10);
  }


8/9/19   [EDGcpfe/21641]
Strict evaluation ordering lost on optimized eok_subscript operations

During lowering, optimize_node_if_possible will rewrite an eok_subscript
operation with an eok_padd operation.  Doing so had inadvertently removed
any settings for strict evaluation ordering for the operation.  Now fixed.


8/8/19   [EDGcpfe/21565]
Strict evaluation ordering and lowered class assignments

Certain class assignments are rewritten during the lowering process to calls to
memcpy (or eliminated if the class is empty).  In cases where strict evaluation
ordering is in force (see the Changes entry for EDGcpfe/17701), lowering
had failed to maintain the proper expression ordering.  For example (with
--c++17):

  struct S {
    int x;
    char c;
    S() {}
  };
  S s;
  S& second() { return s; }
  S first() { return s; }
  void f() {
    second() = first();   // first() is called before second() with --c++17
  }


8/8/19   [EDGcpfe/21381]
Memory region problem with __integer_pack

In GNU C++ mode, the front end supports the __integer_pack construct (see the
entry of 1/17/18 for EDGcpfe/18903).  Previously, if that construct was used
with a template argument involving a local variable, the resulting IL
representation could violate the requirement that file-scope IL entries do not
directly point to function-scope IL entries.  In particular, such situations
were encountered in some uses of the Boost libraries.  That problem is now
fixed.


8/8/19   [EDGcpfe/21472]
Effect of __builtin_expect on control-flow warnings

Consider (in GNU or Clang mode):

  int f() {
    if (__builtin_expect(true, 0)) throw 0;
  }
  int g() {
    if (true) throw 0;
  }

Previously, this triggered a warning about f() missing a return statement.
No such warning was issued for g(), because the front end recognized that the
if-condition in g() is always true.  Now, the front end sees through the
__builtin_expect (and __builtin_expect_with_probability) intrinsics to identify
control-flow conditions that are always true, and as a result no warning is
emitted anymore for f() above.


8/7/19   [EDGcpfe/21647]
Incorrect setting of is_local_to_function for variable template instances

The is_local_to_function field of the source correspondence field for
variable template instances could be incorrectly set to TRUE in some
cases.  This could cause various kinds of problems.  It has been observed
to cause an internal error in add_discriminator in name mangling, and
an EXPENSIVE_CHECKING internal error in expensive_il_entry_prefix_of
during the IL walk process.  Now fixed.


8/7/19   [EDGcpfe/21649]
Abort with inline variables and implicit inclusion

An abort could occur (in instantiate_template_variable) when inline variables
were used in conjunction with implicit inclusion of template definitions.
Now fixed.  This example would abort with "-tused --c++17 --implicit_include".

  template <class> struct A {
    static inline int x;
  };
  int *p = &A<int>::x;


8/7/19   [EDGcpfe/21403]
Internal error in conv_glvalue_expr_to_prvalue in template

In some configurations and C++-language modes, the front end could abort with
an internal error in conv_glvalue_expr_to_prvalue (exprutil.c; with message
"bad expr") on some expressions.  For example, in GNU C++ mode with
gnu_version=70000 and a configuration with the C++-generating back end:

  template<int N> void g(float *p, float d) {
    float r = (N == 1) ? p[0] : d;
      // Previously triggered an internal error.  Now okay.
  }

That problem is now fixed.


8/7/19   [EDGcpfe/21648]
Softfloat library now in extern "C" block

The Softfloat library (see the Changes entry for EDGcpfe/21259) is a C library
and is now referenced in an extern "C" block when the front end is compiled
by a C++ compiler.


8/6/19   [EDGcpfe/21615]
Class template argument deduction and const variables

The front end previously failed to diagnose a missing initializer on a variable
whose type involved deduced class template arguments.  For example:

  template<typename ...> struct S { int x[2]; };
  constexpr S s;  // Deduces S<> as the type of s, but missing initializer
                  // was previously not diagnosed.  An error is now issued.

This is now fixed.


8/6/19   [EDGcpfe/21642]
USE_POINTER_TO_CONST_CHAR eliminated

As part of transitioning the source code of the front end to C++11, the
configuration macro USE_POINTER_TO_CONST_CHAR has been eliminated.  Defining
this macro to FALSE now triggers a #error directive.


8/6/19   [EDGcpfe/21596]
C++20: More implicit moves in return statements and throw expressions

Committee document P1825R0 added additional contexts where implicit moves are
possible.  Rvalue reference variables are now candidates for implicit moves,
and throw expressions now match return statements for when an implicit move is
possible, so long as the scope of the thrown entity does not extend past the
try block containing the throw.  For example (with --c++20):

  struct base {
    base();
    base(base const &) = delete;
    base(base &&);
  };
  struct derived : base {};
  base h(base &&b, derived&& d, bool c) {
    if (c)
      throw b; // Now calls move constructor
    return d;  // Now calls move constructor
  }


8/5/19   [EDGcpfe/19157,EDGcpfe/20085,EDGcpfe/21466,EDGcpfe/21635]
Invalid treatment of types of lvalues in interpreter

The constexpr interpreter previously checked that it could compute the size of
the types of lvalues.  This could result in spurious errors in cases of lvalues
referring to objects whose type is incomplete or too large.  For example:

  #define offsetof(T, M) (__INTADDR__(&(((T*)0)->M)))
  union U {
    unsigned char x[(500*1024)];
  };
  constexpr auto r = offsetof(U, x);  // Previously an error.  Now okay.

Here, the offsetof expression was previously not evaluated as a constant
because the interpreter considered U to be too large of a type to allocate.
However, no object of type U has to be allocated to compute the offsetof
expression.  Here is an example involving an incomplete type:

  struct A {
    const A* p;
  };
  static const A arr[] = { {&arr[1]}, {&arr[0]} };
     // Previously dynamically initialized.  Now, statically initialized.
  const A* f() { return arr; }

In this second case, the interpreter failed while attempting to compute the
size of arr (as part of the evaluation of &arr[1]) while the array length is
still not known.  (The changes for EDGcpfe/19246 -- in version 5.0 --
exacerbated this problem by handling more cases with the interpreter.)  This
issue is now fixed.


8/2/19   [EDGcpfe/21580]
C++20: Deprecated unparenthesized comma operator in array subscript expressions

Committee document P1161R3 deprecated the usage of unparenthesized comma
operators in array subscript expressions.  The front end will now issue remarks
in all C++ modes prior to C++20 and warnings in C++20 mode whenever such
expressions are encountered.  For example:

void f(int *a, int b, int c) {
  a[b,c];   // Deprecated
  a[(b,c)]; // Still accepted
}


8/2/19   [EDGcpfe/21634]
Missing dik_lambda case in disp_dynamic_init

The dik_lambda case was missing from a switch statement in disp_dynamic_init
which could cause "**BAD DYNAMIC INIT KIND**" to be displayed rather than the
constant associated with the dik_lambda in edgcpdisp output.


8/2/19   [EDGcpfe/21591]
C++20: Permit conversions to arrays of unknown bound

Committee document P0388R4 allows for conversions of arrays of known bounds to
pointers or references to arrays of unknown bounds.  This includes an
adjustment to overload resolution to prefer a conversion to an array of unknown
bound when a list-initialization sequence does not exactly match a known-bound
array.  For example:

  void f(int(&)[]);
  void g(int(*)[]);
  void h(int    (&&)[] );    // #1
  void h(double (&&)[] );    // #2
  void h(int    (&&)[2]);    // #3
  void h(int*);              // #4
  void f() {
    int arr[1];
    int *ip = arr;
    int (&r)[] = arr;  // Now accepted
    int (*p)[] = &arr; // Now accepted
    f(arr);            // Now accepted
    g(&arr);           // Now accepted
    h( {1} );          // Calls #1
    h( {1.0} );        // Calls #2
    h( {1.0, 2.0} );   // Calls #2
    h( {1, 2} );       // Calls #3
    h( ip );           // Calls #4
  }


8/2/19   [EDGcpfe/21569]
Spurious Microsoft-mode error on constexpr initialization in template

In Microsoft C++ modes, the front end sometimes issued a spurious error about a
constexpr static data member in a class template not having a constant
initializer.  For example:

  template<typename> struct V { static const int v = 42; };
  template<typename T> constexpr int v = V<T>::v;
  template<typename T> struct B {
    static constexpr int v = v<T>;  // Previously a spurious error.
  };
  template <typename T> struct D: B<T> {};

The problem was triggered during the "nonreal instantiation" (a Microsoft-mode-
specific operation) of the dependent base class of D<T>.  That is now fixed.


8/1/19   [EDGcpfe/21606]
C++-generating back end: unnamed enumerations as template arguments

When an enumeration is unnamed, a function template is instantiated using
that enumeration type as a deduced template argument, and that function
template instance is later referenced using a decltype-specifier as an
explicit template argument, the C++-generating back end previously put out
all references to that function template instance with an explicit template
argument that was an undeclared temporary name (of the form __T12345678).
This is now fixed; the template argument in such references now uses a
decltype-specifier referring to the first enumerator of the unnamed
enumeration.  For example, with --c++11:

  template<typename T> int f(T);
  enum { E1, E2 };
  int i = f(E2);               // Previously generated as f<__T12345678>, now
                               // as f<decltype(E1)>
  int j = f<decltype(E2)>(E2); // Also generated as f<decltype(E1)>


7/31/19  [EDGcpfe/21397]
Pseudo-destructors

Naming a pseudo-destructor is only permitted as the immediate expression
designating the target of a call.  The front end previously did not enforce
that constraint.  For example:

  using S = int;
  int *p;
  using X = decltype(p->~S); // Previously accepted.  Now an error.
                             // ("decltype(p->~S())" would be okay.)

That is now fixed.  In addition, diagnostics that previously referred to a
"vacuous destructor call" are now phrased using the more widely-known
term "pseudo-destructor call".


7/31/19  [EDGcpfe/21607]
C++-generating back end: preprocessing directives in enumerator lists

The front end could abort (in check_for_and_take_source_seq_entry) with an
internal error if preprocessing directives (#pragma or #define) appear
between enumeration constants in the definition of an enumeration.  This is
now fixed.  For example, in a configuration with RECORD_MACROS_IN_IL set to
TRUE, the following example aborted:

  enum { ZERO,
  #define EMPTY  // Previously caused an internal error
         ONE };


7/31/19  [EDGcpfe/21608]
C++-generating back end: trailing type attributes

When the name of a type is followed by a type attribute, the C++-generating
back end failed to insert a space before the attribute in the generated
code, effectively concatenating the type name and the attribute specifier.
This is now fixed.  For example, with --g++ --c++11:

  using T = int __attribute((aligned(16)));  // Previously generated as
                                             // int__attribute


7/31/19  [EDGcpfe/20221,EDGcpfe/21612]
Linkage of explicit specializations of const variable template instances

Currently, const instances of variable templates are given internal
linkage (in the same way that other const variables are).  While the front
end gave internal linkage to implicit instantiations, it did not do so for
explicit specializations.   Explicit specialization are now also given
internal linkage in such cases.  This will be changing as a result of core
issue 2387, which specifies that all instances of variable templates should
have the same linkage as the template.

  template <int i> const int x = 100;
  template <> const int x<0> = 99;  // now has internal linkage


7/31/19  [EDGcpfe/20111,EDGcpfe/21417]
Zero not accepted as null pointer constant in default template argument

Zero can be used as a null pointer constant in a default template argument
starting with C++11.  The front end now accepts such usage (note that it
was previously accepted in Microsoft mode).

  template<typename T> struct A { typedef T type; };
  template<typename T> class B {
    template<typename A<T>::type* = 0>
    B() {}
  };


7/30/19  [EDGcpfe/21435]
SFINAE failure with decltype of invalid code

When invalid code appeared in a decltype expression in a template argument,
the front end may have incorrectly deduced the decltype of the expression as
something other than an error type.  This could lead to SFINAE (or other)
failures.  For example:

  struct AGGR {
    short x;
  };
  void func(AGGR);
  template <typename, typename To, typename From>
  struct Test {
    static constexpr bool value = false;
  };
  template <typename To, typename From>
  struct Test<decltype( func({From()}) ), To, From> {
    static constexpr bool value = true;
  };
  /* Previously used the specialization of Test, causing the assert to fail.
     The expression func({From()}) in the partial specialization's template
     argument list attempts to initialize AGGR::x, of type short, from a value
     of type float.  This is a narrowing error, which should cause the partial
     specialization not to match the template arguments used in the
     static_assert condition. */
  static_assert(!Test<void, AGGR, float>::value);

This is now fixed.


7/29/19  [EDGcpfe/21546,EDGcpfe/21613]
Uninitialized end position for constructor calls

In configurations where EXTRA_SOURCE_POSITIONS_IN_IL == TRUE, the change
introduced by EDGcpfe/20913 (in version 5.1) inadvertently caused the end
position for some constructor calls (e.g., an_expr_node.expr_range.end or
a_variable.initializer_range.end) to not be set (leaving the memory
uninitialized).  For example:

  struct A {
    A();
  };
  void f() {
    A a = A(); // End position of the initializer not set
    A();       // End position of the temporary expression not set
  }

This is now fixed.


7/26/19  [EDGcpfe/21585,EDGcpfe/21594]
C++20: Enhancements to [[nodiscard]] attribute

The [[nodiscard]] attribute has been enhanced to include an optional string
literal (see P1301R4).  Additionally, the [[nodiscard]] attribute can now
appertain to a constructor (see P1771R1).  The value of
__has_cpp_attribute(nodiscard) has been updated to return 201907L.
Note that these features are available in C++17 mode as well (including
the new value for __has_cpp_attribute(nodiscard)) even though P1301R4 is
a C++20 feature.


7/25/19  [EDGcpfe/21555]
C++-generating back end: embedded type definitions in typedefs

The C++-generating back end incorrectly handled non-autonomous type
definitions embedded within typedef declarations.  Instead of the type
definition, the generated code used an elaborated-type-specifier, including
use of a temporary name (of the form __T12345678) if the embedded type is
unnamed.  This is now fixed.  For example, with --microsoft --c,

  typedef char c[(int)&(((struct { char x; } *)0)->x)+1];

appeared in the generated code as:

  typedef char c[(int)&(((struct __T12345678 *)0)->x)+1];


7/25/19  [EDGcpfe/21539]
Abort when a lambda expression appears in an array bounds expression

With the change for EDGcpfe/21423 (in version 5.1), the front end would abort
in i_copy_expr_tree if a lambda expression that had init captures appeared in
an array bounds expression, and the backing expression for the integral
constant was retained (e.g., RECORD_BACKING_EXPRS_WITH_IL_LOWERING == TRUE).
For example:

  struct A {};
  A f() {
    A z[ ([x = 1]{}, 1) ]; // Previously could abort
    return z[0];
  };

This is now fixed.


7/25/19  [EDGcpfe/21597]
C++20: Support for constexpr destructors and dynamic allocations

In C++20 mode, the front end now accepts constexpr destructors and can
perform dynamic allocations and deallocations during the evaluation of
constant expressions.  For such allocations to be valid, they must all be
deallocated before the completion of the evaluation they are part of.
For example:

  consteval int forty_two() {
    int *p = new int(42);
    int r = *p;
  #ifndef NEG
    delete p;
  #endif
    return r;
  }
  static_assert(forty_two() == 42);

This example is now accepted in C++20 mode, unless compiled with the macro NEG
defined: In the latter case, the allocation is not deallocated by the time the
call to forty_two() completes, and that call is therefore not considered a
valid constant expression.

Allocations can be performed using global non-placement new-expressions or
using the standard allocator (std::allocator<X>, provided the appropriate
members of that allocator are declared "constexpr").  The interpreter also
implements evaluation of the placement-new expression that occurs in a normal
std::construct_at implementation (other placement-new expressions are not
permitted, though).

These features were added to the draft working paper for C++20 through the
standardization committee's paper P0784R7.


7/24/19  [EDGcpfe/21514]
Use of uninitialized variable in select_coroutine_new

The front end used an uninitialized variable in the select_coroutine_new
function when processing a coroutine that has no parameters.  This could lead
to selecting the wrong operator "new" and/or crashes.  This is now fixed.


7/23/19  [EDGcpfe/18122,EDGcpfe/20802,EDGcpfe/20933]
Handling of non-trailing function parameter packs

Consider the following variadic template case:

  template<typename ... Ts> int f(Ts ... ps, int x);
  int r = f(1); // Now accepted.  Previously an error.

The function parameter pack ps is a non-deducible context (because it's not
a trailing pack).  Previously, this caused the front end to fail to match the
call "f(1)" to the given function template.  However, a close reading of the
C++ standard suggests that instead such a pack should be substituted with an
empty expansion, which allows the example above to be valid.  That rule is now
implemented in the front end.


7/23/19  [EDGcpfe/21578]
Core issue 2406: [[fallthrough]] in loop statements

Core issue 2406 clarifies that a program is ill-formed if a fallthrough
statement (i.e., an empty statement with the [[fallthrough]] attribute)
is contained in an iteration statement and the next statement is not part of
the same execution of the substatement of the innermost enclosing iteration
statement.  The following example now gives a warning in default mode or
an error in strict mode (with --c++17):

  void f(int n) {
    switch (n) {
    case 1:
      do {
        [[fallthrough]]; // Now an error in strict mode.
      } while (false);
    default:
      break;
    }
  }


7/22/19  [EDGcpfe/21560]
C++-generating back end, clang compatibility: template keyword following
namespace qualifier

The change for EDGcpfe/21238 (in version 5.1) addressed a bug in the clang
compiler that required the template keyword in certain cases where a
template name has a namespace qualifier.  However, clang rejects the use
of the "template" keyword if it appears in a declaration rather than in an
expression.  This additional clang compatibility issue has now been
addressed.  For example, with --clang_version=50000:

  namespace N { template<typename> struct S; }
  class E1 {
    template<typename> friend struct N::S; // Previously generated as
                                           // N::template S, rejected by clang
  };


7/22/19  [EDGcpfe/11127,EDGcpfe/21364]
Mangled names for local variables

A change has been made (to both IA-64 and Cfront ABIs) to discriminate between
local variables with the same name when used in mangled names.  This change
is only effective when ABI_COMPATIBILITY_VERSION >= 520.  In the example
below, the two instantiations of "tf" had mistakenly been given the same
mangled name (with --c++17):

  template<int* T> int tf() {
     return *T;
  }
  extern inline int f(int a) {
    if (a) {
       static int r = 1;
       return tf<&r>();
    } else {
       static int r = 2;
       return tf<&r>();
    }
  }
  int main() {
     return f(1);
  }


7/18/19  [EDGcpfe/21500]
Mangled name for prototype instantiation with parameter pack

A change has been made (when ABI_COMPATIBILITY_VERSION >= 520) to include
a parameter pack indication in the mangled name of a prototype instantiation of
a template with a parameter pack.  In the example below the two entities had
been given the same mangled name (with --c++11):

  template <class...> struct A;        // Had been _Z1AIJT_EE now _Z1AIJDpT_EE
  template <class T>  struct A<T> {};  // _Z1AIJT_EE


7/18/19  [EDGcpfe/21518]
Assertion failure in mangled_simple_id

Mangling of certain unresolved names, in some configurations, could cause
an assertion failure in mangled_simple_id.  Now fixed.  For example:

  template <class T> auto f(T t) -> decltype(decltype(t)::X::g());


7/16/19  [EDGcpfe/21503,EDGcpfe/21521,EDGcpfe/21525,EDGcpfe/21526,
          EDGcpfe/21527]
Incorrect lowered IL generated for some [[no_unique_address]] cases

In certain cases, the lowered IL generated for a reference to a field with the
[[no_unique_address]] attribute was incorrect, leading (in configurations that
use the C-generating back end) to C that could not compile or various assertion
failures.  Now fixed.  For example (with --c++20):

  struct C {};
  int f(C);
  struct B {
    [[no_unique_address]] C c;
    int g() {
      return f(c);
    }
  } b;
  int x = b.g();


7/16/19  [EDGcpfe/18875,EDGcpfe/19127,EDGcpfe/21547]
Clang compatibility: __builtin_*_overflow builtins

The clang versions of __builtin_add_overflow, __builtin_mul_overflow, and
__builtin_sub_overflow are "generic" in that they accept three arguments of
various types and require the compiler to validate the argument types.  The
(dummy) signature for these builtins (as reported by clang) is "void (...)" and
has now been changed to "__edg_bool_type__ (...)" so the return type is
correct.  For example (with --clang):

  void f() {
    unsigned long result;
    if (__builtin_add_overflow(1, 1, &result) ||
        __builtin_mul_overflow(1, 1, &result) ||
        __builtin_sub_overflow(1, 1, &result)) {
    }
  }

As a consequence of this change, user-defined entries for builtins (i.e.,
in builtin_user_table) will now take the place of similarly-named builtins
in the generic builtin table (i.e., builtin_table).  This allows customers to
change entries that are found to be incorrect in builtin_table.


7/12/19  [EDGcpfe/21515]
Assertion failure in lower_dynamic_init

An assertion failure (in lower_dynamic_init) could occur when lowering
certain dynamic initializations in configurations where
PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE is FALSE.  Now fixed.  For example
(with --c++17):

  struct S {
    int m;
    constexpr S(int i=1) : m(i) {};
    ~S() {}
  };
  int f() {
    static S s(42);
    return s.m;
  }


-------------------------------------------------------------------------------
Version 5.1, July 12, 2019

7/10/19  [EDGcpfe/21505]
Abort when capturing "this" in a nested lambda for a field initializer

When a nested lambda in a field initializer captured "this" and the enclosing
lambda is a generic lambda, the front end would abort with an assertion failure
in scan_lambda_capture_list.  For example:

  struct A {
    int x = [=](auto a) {
      [this]{}; // Previously caused an abort
      return 0;
    }(0);
  };

This is now fixed.


7/8/19   [EDGcpfe/21490]
GNU/Clang compatibility: spurious error on variable with alignment

An error had been issued when a variable declaration with an alignment
attribute had occurred after a definition of that variable without an alignment
attribute.  That error is now suppressed in GNU emulation mode and a warning is
given in Clang emulation mode.  For example:

  float f = 0.0;
  extern float f __attribute__((aligned(8)));


7/4/19   [EDGcpfe/21445]
Abort when using local classes in "new" expressions inside a default template
argument

The front end would abort with an assertion failure in scan_new_operator when
it encountered a "new" expression using a local class when parsing a default
template argument.  For example (with --c++17):

  template<int I = [] {
    struct A {
      int&& x = 29;
    };
    decltype(new A) x; // Previously caused an abort
    return 0;
  }()>
  int f();

This is now fixed.


7/2/19   [EDGcpfe/21423]
Abort when dynamic initializers with destructors used in array bounds

The front end expects the bound for an array type to be an integral constant
expression.  When provided with an expression that cannot be folded to an
integral constant, the resulting dynamic initializer for the expression could
cause the front end to abort if there is a corresponding destructor that may
need to be called during the initialization.  For example:

  struct A {
    constexpr A(bool b) noexcept(false) { if (b) throw 0; }
    constexpr operator unsigned() { return 1; }
    ~A();
  };
  using T = A[1];
  void f()
  {
    int a [ T{{true}}[0] ];  // Previously caused abort
  }

This has now been fixed.


7/2/19   [EDGcpfe/21463]
Exception specifications as part of function types of function parameters when
exceptions disabled

The change for EDGcpfe/19495 made it so that exceptions continue to make up
part of the function type in C++17 mode, even when --no_exceptions is
specified.  However, the front end was still not taking this into account when
determining whether two function types had compatible exception specifications.
This could lead to spurious errors.  For example:

  void f(void (*g)()) {}
  void f(void (*g)() noexcept) {} // Spurious redeclaration of "f" error

This is now fixed.


7/2/19   [EDGcpfe/21436]
Microsoft compatibility: binding const volatile lvalue reference to rvalues

In certain cases the Microsoft compiler allows binding const volatile lvalue
references to rvalues.  This is not standard compliant, and when permissive
mode is disabled, the Microsoft compiler no longer allows this.  The front end
was already emulating the permissive mode (when microsoft_bugs is set), but was
not emulating the non-permissive mode.  For example:

  using T = int;
  T t{};
  const volatile T& x =
    static_cast<T&&>(t); // Now rejected with --no_ms_permissive

This is now fixed.


7/2/19   [EDGcpfe/21475]
Segfault in attach_attributes_to_routine_instance

An abort in attach_attributes_to_routine_instance could occur when trying to
attach attributes to an ill-formed function template.  For example
(with --c++17):

  template <class T> [[deprecated]] void f(T) noexcept (f<int>) {}


6/28/19  [EDGcpfe/21465]
C++-generating back end, Microsoft compatibility: function declarator syntax

MSVC has a bug that sometimes causes it to fail to match the definition of
a member function of a class template with the corresponding declaration if
the definition uses the traditional C-style function declarator syntax
instead of a trailing return type.  The code generated by the
C++-generating back end could trigger this MSVC bug if the in-class
declaration of the member function uses the traditional syntax because it
was incorrectly preserving the syntax from the in-class declaration when
generating the member function definition.  This is now fixed.  For example,
with --microsoft --c++14 --parse:

  template <int length> class A {};

  template <int N> class B {
    enum E {
      e = N
    };
    constexpr A<e> f() const;
  };

  template<int N>
  constexpr auto B<N>::f() const -> A<e> {  // Previously generated as:
                                            // A<B<N>::e> B<N>::f() const
    A<e> v; return v;
  }


6/27/19  [EDGcpfe/21458]
Vector types are trivially copyable

The front end now treats vector types as trivially copyable (in modes that
accept such types).  For example:

  using V = int __attribute__((vector_size(4*sizeof(int))));
  static_assert(__is_trivially_copyable(V), "Unexpected");
    // Now accepted in GNU C++11 mode.


6/25/19  [EDGcpfe/21456]
Synthesis of inheriting constructor definitions

In configuration with INSTANTIATE_EXTERN_INLINE set to TRUE, the front end
often synthesized a definition for an inheriting constructor when it should
not have done so (that in turn could lead to duplicate definition errors issued
by a linker that cannot discard duplicate definition).  That is now fixed.


6/25/19  [EDGcpfe/21434]
Copy-list-initialization with explicit constexpr constructors

The C++11 standard forbids copy-list-initialization where a constructor that
has been marked explicit would be used.  The front end failed to issue a
diagnostic for this when the explicit constructor was also constexpr.  For
example:

  struct X {
    explicit constexpr X(int){};
  };
  struct S {
    X x;
  };
  S s { {3} }; // Previously accepted without a diagnostic, now an error

This is now fixed.


6/25/19  [EDGcpfe/21446]
Multiple translation units: Potential infinite loop when using built-in
functions

In some multiple translation unit modes where source sequence lists are
generated, the front end could enter into an infinite loop when attempting
to merge name reference lists for built-in function types.  For example, when
compiling two source files that both include a header containing this code:

  template<typename>
  void f()
  {
    _Atomic(bool) atom;
    __c11_atomic_exchange(&atom, 0, 0);
  };
  struct B
  {
    _Atomic(bool) atom;
    void f() volatile {
      __c11_atomic_exchange(&atom, 0, 0);
    }
    void g() {
      __c11_atomic_exchange(&atom, 0, 0);
    }
  };

In the above example, the front end would enter into an infinite loop.  This is
now fixed.


6/24/19  [EDGcpfe/21433]
Implicit constructors for unions with members having non-trivial constructors

Committee core issue 2084 noted that a union that contains a member with a
default member initializer as well as a (possibly the same) member that has a
non-trivial constructor would have its constructor implicitly deleted.  The
Committee resolution is that a default member initializer in a union should be
treated as if a user-declared default constructor was present - meaning that
the constructor should not be deleted.  This has been implemented except in
compatibility modes for GCC, Clang, and MSVC, as none of these have implemented
this change yet.  In addition, Committee core issue 1301 changed list
initialization of a union that is an aggregate to use aggregate initialization
and not the constructor, whether or not it's deleted.  For example:

  struct A {
    A();
  };
  struct B {
    union {
      int i = 1;
      A a;
    };
  };
  void f() {
    B b1;   // Uses default constructor - no longer deleted (core issue 2084)
    B b2{}; // Uses aggregate initialization, not ctor (core issue 1301)
  }

The front end has been updated to reflect these changes.


6/24/19  [EDGcpfe/21440]
Clang compatibility: Spurious error with designated initializers

Clang accepts designated initializers for members of anonymous structs/unions
without an extra layer of braces, however the front end was spuriously
rejecting these cases.  For example:

  struct A {
    struct {
      char c;
    };
  };
  void f() {
    A a = { .c = 1 }; // Spurious error requiring an extra layer of braces
  }

This is now fixed.


6/24/19  [EDGcpfe/21368]
Microsoft compatibility: __builtin_clz*, __builtin_ctz*, __builtin_popcnt*

When microsoft_version >= 1923, the builtins __builtin_clz, __builtin_clzl,
__builtin_clzll, __builtin_ctz, __builtin_ctzl, __builtin_ctzll,
__builtin_popcount, __builtin_popcountl, and __builtin_popcountll are now
enabled (and can be used in constexpr contexts).


6/21/19  [EDGcpfe/18111,EDGcpfe/21119,EDGcpfe/21276]
The noexcept operator and constant expressions

In C++11 and C++14, applying the noexcept operator to a "core constant
expression" (an expression that the compiler can evaluate) produced a "true"
value:

  static_assert(noexcept(true ? 0 : throw 0), "");  // Okay in C++11 and C++14.
                                                    // Fails in C++17.

That rule was accidentally dropped through the changes made by the committee's
paper P0003R5, but, after review, the committee decided to let the effect of
P0003R5 in this area stand.  Since other compilers never implemented the
original rule, the front end now applies the revised rules (causing the
static_assert above to fail) by default.  The previous behavior can be
restored by setting the global flag core_constant_expr_is_noexcept to TRUE.
The previous behavior is also still enabled in Microsoft mode (which is
slightly different from both the original C++11/C++14 standard and from the
revised standard rules).  Furthermore, the behavior in GNU C++ mode has been
tweaked to more closely match the slightly nonstandard behavior of GCC.  E.g.,
in GNU C++ modes the above example fails, but the following succeeds:

  constexpr int const* f(int const *p) { return p; }
  constexpr int i = 42;
  static_assert(noexcept(*f(&i)), "");  // Okay in all GNU C++ modes that
                                        // support noexcept.  Fails in
                                        // default modes.
 

6/21/19  [EDGcpfe/21402]
Abort in aggr_init_chained_designator with template-dependent types

In modes where designated initializers are supported, the front end could
abort when attempting to initialize a template-dependent type in a malformed
way.  For example:

  template<class T> void f()
  {
    T v[1][1] = {{ [0][0] = 0 }}; // Would previously abort, now an error
  };
  void g() {
    f<short>();
  }

This is now fixed.


6/20/19  [EDGcpfe/21409]
Abort in scan_ctor_arguments with constexpr user-defined conversion function

When a constexpr user-defined conversion function was used to enable copy
construction of an object, the front end would abort.  For example:

  struct A {
    int x;
    constexpr A(int i) : x(i) {}
    constexpr A(const A& obj) : x(obj.x + 10) {}
  };
  struct _AAA {
    A val;
    constexpr operator A() const { return val; }
  };
  constexpr A a(37);
  constexpr A b(_AAA{a}); // Previously the front end would abort here

This is now fixed.


6/20/19  [EDGcpfe/20016]
C++20: Deprecate the POD type category

Committee document P0767R1 moved the definition of POD types to Annex D of
the draft C++ Standard for C++20 and removed all references to the term
from the main body of the Standard.  Type restrictions that had previously
been phrased in terms of POD types now refer to more-granular
characteristics such as triviality and standard-layout types.  The front
end has now been changed to remove the term "POD" from all diagnostics and,
for C++11 and later dialects, to use the more-granular type checking for
those diagnostics.  (Earlier dialects continue to check whether the types
are PODs or not when determining whether a type can be used in the relevant
contexts.)


6/20/19  [EDGcpfe/21405]
Assertion failure in scan_new_operator with non-C++03 POD class and no
initializer

In certain specific cases, given a class that has no constructor and is POD by
C++11 rules but not by C++03 rules, where an object of this class type is being
created without an initializer via a "new" expression, the front end aborted
with a "non-POD class has neither actual nor assumed ctor" message.  For
example:

  template<auto lam = [] {
    struct A {int x = 29;};
    new A; // Previously aborted with "neither actual nor assumed ctor" message
  }>
  void f();

This is now fixed.


6/20/19  [EDGcpfe/21415]
Incorrect dynamic initialization of certain arrays whose bounds are specified
at run time

Lowering had incorrectly lowered some dynamic initializations of arrays,
effectively not performing them.  In the example below, the initialization
for A::B::y had been performed zero times, resulting in g() never being
called (with --c++17):

  int f() { return 1; }
  int g() { return 1; }
  struct A {
    A(const A&) = delete;
    struct B {
      int y = g();    // g() was never called
    };
    B b {};
  };
  int main() {
    auto x = new A [f()]{};
    return 0;
  }

Additionally, a bug where multiple expressions pointed to the same
expression node, resulting in invalid IL, was also fixed.


6/20/19  [EDGcpfe/21416]
Auto array types in "new" expressions

Previously the front end would not directly diagnose the usage of "auto" in a
"new" array expression - instead it issued a "could not deduce auto type"
message when the deduction eventually failed.  This is in contrast with the
message issued when attempting to use "auto" when declaring an array ('"auto"
type cannot appear in top-level array type').  In addition, this "could not
deduce auto type" error would only appear when instantiating a template that
had such a "new" expression, instead of issuing the error during prototype
instantiation.  These diagnostics have been made to be consistent with each
other.  For example:

  template<typename T>
  void f() {
    auto x[1] { T{} }; // Issues a "cannot appear in top-level array" message
    new auto [1] { T{} }; // Now also issues the same message
  }
  void g() {
    f<int>(); // Previously triggered a "cannot deduce auto type" message
              // for the "new" expression in f()
  }


6/19/19  [EDGcpfe/21404]
Microsoft compatibility: C++20 features enabled in Microsoft emulation mode

A number of changes have been made to better align the enabling of C++20
features in the correct Microsoft emulation mode.


6/18/19  [EDGcpfe/18985,EDGcpfe/21183]
GNU compatibility: Constexpr evaluation of comma-like operators

Consider:

  struct S {
    constexpr static int f() { return 42; }
  };
  void g(S const &s) {
    constexpr int r1 = s.f();
    constexpr int r2 = (s, S::f());
  }

Because S::f is a static member function, the initializers for r1 and r2 are
essentially equivalent.  They are also invalid, because "s" is not a valid
core constant expression in that context.  However, it appears that GCC
accepts such cases (i.e., no attempt is made to evaluate the "left" operand
if it is simple enough).  The front now approximates that behavior and accepts
the case above (and other similar ones) in GCC modes.


6/18/19  [EDGcpfe/21253]
Spurious error on call through reference type cast in dependent context

Consider:

  auto f = [](auto &&f) {
             return static_cast<decltype(f)>(f)();  // Previously an error.
           };                                       // Now okay.

This previously elicited a spurious error because the front end failed to
look through the reference type represented by "decltype(f)" to note that the
underlying type is template-dependent (and therefore it could become a pointer
to a function type after substitution).  That is now fixed.


6/18/19  [EDGcpfe/21242]
Microsoft compatibility: Empty classes and constant expressions

The changes for EDGcpfe/18739 (see entry of 2/21/18) allowed the trivial
copying of empty class objects as part of constant expressions even when those
empty objects are "non-constant run-time" objects.  However, that change was
not enabled in Microsoft mode.  Now, it is enabled in Microsoft C++ modes with
microsoft_version >= 1914.  Note that this can also apply to closure types.
For example:

  auto closure = [](auto p) { return p; };
  constexpr auto r = closure; // Now accepted in some Microsoft C++17 modes.


6/17/19  [EDGcpfe/21336]
C++-generating back end: inaccessible names in underlying type of typedef

Under some complex circumstances involving dependent expressions as nontype
template arguments, the C++-generating back end sometimes replaced a
typedef name appearing in the source with its underlying type in the
generated code when some names referred to in that type are inaccessible.
This is now fixed.  For example, with --c++11 --g++:

  template<int X, int Y> struct A {
    static const int vx = X;
    static const int vy = Y;
    static const int v = X + Y;
  };

  template<int X, int Y> struct B {
    static const int v = X + Y;
  };

  template<typename _R1, typename _R2> class C {
    static const int vx1 = _R1::vx;
    static const int vx2 = _R2::vx;
  public:
    typedef A<B<(_R1::vx / vx1), (_R2::vx / vx2)>::v,
              B<(_R1::vy / vx2), (_R2::vy / vx1)>::v> type;
    };
  typedef C<A<2, 3>,A<2, 3>>::type r;
  // In the generated code, r was previously replaced by a version of its
  // underlying type that referred to the private member vx1:
  int i = r::vx;


6/14/19  [EDGcpfe/20014,EDGcpfe/20120]
C++20: Three-way comparison (aka. the spaceship operator)

In C++20 mode, the front end now supports the three-way comparison operator
("<=>", aka., the spaceship operator).  For example:

  #include <compare>  // Required.
  int main() {
    return (1 <=> 2) != 0;
  }

It also handles the associated changes in overload resolution and the
synthesis of defaulted == and <=> operators.  In addition, a sample
implementation of the new <compare> header is now provided (that sample
implementation does not currently include the "3way" library functions
mandated by the standard).  The following example is thus accepted in C++20
mode:

  #include <compare>
  struct B {
    float x = 1.1;
    auto operator<=>(B const&) const = default;
  };
  enum E { e };
  struct S: B {
    E e;
    int i;
    auto operator<=>(S const&) const = default;
    friend bool operator==(S const&, S const&) = default;
  };
  constexpr S s1 = { {}, e, 42 };
  constexpr S s2 = { {}, e, 41 };
  static_assert(s1 > s2);  // Evaluates: s1.operator<=>(s2) > 0
  static_assert(s1 != s2); // Evaluates: !operator==(s1, s2)

Some aspects of this language feature are still somewhat in flux at the time
of this writing.  Our current implementation mostly follows the specification
of the working paper number N4810, with some adjustments in overload
resolution to reflect more recent committee discussions.


6/14/19  [EDGcpfe/21383]
Compiler-generated expressions (IL CHANGE)

Previously, the "operation" variant of expression nodes contained a
"compiler_generated" flag that was set to TRUE for certain compiler-generated
expression constructs (e.g., implicit casts).  That flag is now no longer
attached to a particular variant (i.e., any expression node can now be marked
as "compiler generated").  Because of this, the "compiler_generated" flag in
a_gcnew_supplement has been removed and the new flag is used instead for that
same purpose.


6/13/19  [EDGcpfe/20580]
Spurious "function had a different meaning" error with multiple translation
units

When attempting to establish the canonical entry for a function template that
appears in multiple translation units, the front end was failing to account for
function templates with decltype return types that differed in type by the
decltype expression alone.  This could lead to spurious "function had a
different meaning" errors caused when the canonical entry for a function
template did not agree with the function symbol itself.  For example, given two
source files that both include a header with these declarations:

  template <class T, class U>
  auto f(T a, U b) -> decltype((a)); // #1
  template <class T, class U>
  auto f(T a, U b) -> decltype((b)); // #2

The canonical entry for #1 was incorrectly referring to the entry for #2.  This
is now fixed.


6/13/19  [EDGcpfe/19678]
Missing diagnostic on narrowing conversion from char to bool

The front end was failing to diagnose the conversion from char to bool as a
narrowing conversion.  For example:

  struct S {
    S(bool);
  };
  char c = 'a';
  S s{c}; // Previously accepted, now an error


6/12/19  [EDGcpfe/21369]
Explicit conversions in braced-initialization of references

In cases where a reference type is being initialized by braced-initialization
and the initialization requires the invocation of an explicit user-defined
conversion function, the front-end was failing to consider these explicit
user-defined conversion functions.  This resulted in an error.  For example:

  struct A {
    explicit operator int&&();
  };
  void f() {
    int&& irr{ A{} }; // Previously issued a "no suitable conversion" error
  }

This is now fixed.


6/11/19  [EDGcpfe/21370]
Error for typedef with no declarator in strict mode

For typedef declarations that do not declare a typedef-name, the front end
issues a warning.  In strict ANSI mode, this is now an error.  For example:

  typedef struct A { };  // Previously a warning in strict mode, now an error


6/10/19  [EDGcpfe/20913]
C++20: Initializing aggregates from a parenthesized list of values

C++20 allows initializing aggregate types from a parenthesized list of values
when no constructor applies (Committee paper P0960R3).  Unlike
braced-initialization, narrowing of values is allowed.  For example:

  struct A {
    int x;
    double y;
  };
  A a1(1.0, 1); // Well-formed, no narrowing conversion diagnostic
  A a2{1.0, 1}; // Narrowing conversion diagnostic

Note that array types can be initialized this way as well, including in new
expressions (in conjunction with Committee paper P1009R2; see EDGcpfe/20914):

  double a[](1,2,3);
  double *p = new double[](1,2,3);


6/8/19   [EDGcpfe/21274]
C++-generating back end: referring to unnamed enumerations via decltype

The C++-generating back end previously used an undeclared temporary name
(of the form __T12345678) to refer to an unnamed enumeration type when the
original source code denotes the type using a decltype-specifier naming a
variable of the enumeration type.  This is now fixed.  For example, with
--c++11:

  template<typename> struct S { };
  enum { e } ue;
  int main() {
    S<decltype(ue)> s;  // Previously generated as S<__T12345678>
  }


6/7/19   [EDGcpfe/21238]
C++-generating back end: template keyword following namespace qualifier

The clang compiler has a bug that causes it sometimes to issue a spurious
error when a dependent template-id is referenced via a namespace-qualified
name unless the template-id is preceded by the "template" keyword, even
though the "template" keyword is not needed in that location.  In
configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end previously put out
such names without the "template" keyword, but now adds the keyword when
clang_is_generated_code_target is TRUE.  For example, with --clang:

  namespace N {
  template <typename D, int I> struct A;
  template <typename D, int I> struct B {
    int f();
  };
  }

  template <typename> class C {
    template <int I> int f() {
      return (*this).N::template B<C, I>::f(); // Previously omitted "template"
    }
  };


6/7/19   [EDGcpfe/21219]
Spurious error on C++17 explicit specialization with exception specification

Consider:

  template<typename> struct X { static constexpr bool value = true; };
  template<typename T> void f(T&, T&) noexcept(X<T>::value);
  template<> void f(int& a1, int& a2) noexcept(X<int>::value) {}

Previously this triggered a spurious error in C++17 mode (except for GCC and
Clang modes).  That is now fixed.


6/7/19   [EDGcpfe/21137,EDGcpfe/21235]
Incorrect instantiation of template class's special member function's exception
specification

In some cases the special member functions of a class may have had their
exception specifications incorrectly instantiated.  For example:

  template <class T>
  struct A
  {
    A& operator=(A&&) noexcept(false) = default;
  };
  A<int> a; // A<int>::operator= incorrectly had noexcept(true)

This is now fixed.


6/6/19   [EDGcpfe/20897,EDGcpfe/21341]
Implicit move constructor of class with variant members spuriously deleted

Consider:

  struct M {
    M(M const &);
    M(M&&) = default;  // Trivial move constructor.
  };
  struct S {
    S();
    union {
      int i;
      M m;
    };
  } s;
  S r = static_cast<S&&>(s);  // Previously an error.  Now okay.

Previously, the front end marked the move constructor generated for struct S
as "deleted" because the copy constructor of M is nontrivial.  As a result,
the attempt to move-initialize r from s failed.  That is now fixed.


6/6/19   [EDGcpfe/20918]
Exception specifications in explicitly-defaulted functions

Committee paper P1286R2 changed how a mismatch between a routine's explicitly-
specified exception specification and its generated default behaves.  The new
behavior is to use the explicitly-specified exception specification but
otherwise generate the routine as usual - even if this means an exception may
be thrown in spite of a noexcept(true) specification (std::terminate will be
called).  This change has been made to apply retroactively to older C++ modes
(e.g., C++11), however in GCC, Clang or MSVC compatibility modes the original
behavior has been preserved outside of C++20 mode.  For example:

  struct T {
    T();
    T(T &&) noexcept(false);
  };
  struct U {
    T t;
    U();
    U(U &&) noexcept = default; // Previously implicitly deleted, now kept
  };
  U u1;
  U u2 = static_cast<U&&>(u1); // Previously an error, now accepted


6/6/19   [EDGcpfe/21347]
Microsoft compatibility: Selecting C++ standard mode

In Microsoft compatibility mode the front end was overriding an explicitly
specified C++ standard mode (e.g., --c++20) if the microsoft version being
emulated was 19.03 or newer.  This has now been fixed.


6/6/19   [EDGcpfe/20911,EDGcpfe/20912]
Allowing lambda capture of structured bindings

Committee papers P1091R3 and P1381R1 relaxed the rules around lambda capture of
structured bindings to allow capture-by-value (P1091R3) and
capture-by-reference (P1381R1).  This has now been implemented.  For example:

  void f() {
    int arr[] = {1, 2, 3};
    auto [a, b, c] = arr;
    auto& [ra, rb, rc] = arr;
    int r1 = [=] {
      return a + b + c; // Previously an error, now returns 1 + 2 + 3
    }();
    int r2 = [&] {
      ra = 10; // Previously an error, now sets arr[0] to 10
      b = 20; // Previously an error, now sets b to 20 (arr[1] unchanged)
      return ra + rb + rc; // Previously an error, now returns 10 + 2 + 3
    }();
  }


6/6/19   [EDGcpfe/20912]
Allowing static and thread_local storage specifiers on structured bindings

Committee paper P1091R3 relaxed the rules around structured bindings to allow
the static and thread_local storage classes to be applied to structured
binding declarations.  This has now been implemented.  For example:

  void f() {
    int arr[] = {1, 2, 3};
    static auto [sa, sb, sc] = arr; // Previously an error, now accepted
    thread_local auto [ta, tb, tc] = arr; // Previously an error, now accepted
  }


6/6/19   [EDGcpfe/21343]
Incorrect floating-point results in some configurations

The sizes of floating-point types can be specified at run time via the
--target option (see the Changes entry for EDGcpfe/15604 et al.), but some
compile-time configuration had ignored the run time settings.  That was the
case if the default configuration had different representations for the
"double" and "long double" types, but the run-time selected target
configuration had identical representations for "double" and "long double".
That is fixed now.


6/5/19   [EDGcpfe/21335]
C++-generating back end, clang compatibility: qualified typedef name in a
trivial destructor invocation

The clang compiler has a bug that causes it to reject the invocation of a
trivial destructor in which the type is given as a typedef named by a
qualified-id.  In configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is set to TRUE,
the C++-generating back end could produce such destructor calls in
generated explicit specializations.  For example, given

  struct S { };
  namespace N {
  typedef S X;
  }
  template<typename T> T& f() {
    static T t;
    return t;
  }
  template<typename T> void g() {
    f<T>().T::~T();
  }
  void h() {
    g<N::X>();
  }

the generated code contained the following explicit specialization:

  template<> void g<S>() {
    f<S>().N::X::~X();
  }

The use of the name N::X in the destructor call triggered the clang bug.
This has now been addressed by using the underlying type of the typedef in
the generated code when clang_is_generated_code_target is TRUE.


6/4/19   [EDGcpfe/21339]
C++-generating back end, clang compatibility: matching explicit
specializations of function templates

The clang compiler sometimes fails to match an explicit specialization of a
function template with its primary template if the explicit specialization
relies on template argument deduction rather than explicit template
arguments.  In C++-generating back end configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, a
generated explicit specialization was put out without an explicit template
argument list if none of the references to that template instance in the
original source uses explicit template arguments.  The generated C++ code
could thus could trigger the clang bug.  For example, given the input
source

  template<typename T> void f(const T&) { }
  template<typename T> void f(T&&) { }
  void g(const int& r) {
    f(r);
  }

the generated code contained the following explicit specialization:

  template<> void f<> (const int &) { }

Compiling the generated code, clang complains that the reference to f is
ambiguous.  This is now fixed; when clang_is_generated_code_target is TRUE,
the explicit specialization is generated as

  template<> void f<int> (const int &) { }

which clang accepts without error.


6/4/19   [EDGcpfe/20020]
Relaxed range-based-for loop customization point finding rules

The C++ standardization committee paper P0962R1 relaxes the range-based-for
loop customization point finding rules such that if a class contains only one
member "begin" or "end", this is no longer an error (and the found function is
not considered a candidate for the range-based-for loop begin/end calls).  This
allows "begin" and "end" functions in associated namespaces to operate on
classes that declared a "begin" or "end" function (but not both).  This change
is retroactive to all modes that support range-based-for loops.  For example:

  struct A { void end(); };
  int* begin(A&);
  int* end(A&);
  void f() {
    for (auto a : A()) {} // Previously would issue an error that A::begin
                          // doesn't exist. Now uses ::begin and ::end
  }


6/4/19   [EDGcpfe/19495]
Exception specifications as part of function types when exceptions disabled

In C++17, exceptions make up part of the function type.  The front end was
disabling this when --no_exceptions was specified, which could lead to errors
when overloading with function types that differed only by their exception
specification.  For example:

  template<typename> struct A;
  template<typename T> struct A<T (*)()> {};
  // Caused "already defined" error with --no_exceptions
  template<typename T> struct A<T (*)() noexcept> {};

This is now fixed.  Prior to this change the mangled name generated could be
different depending on whether or not the --no_exceptions option was used in
C++17 mode.  After this change, the mangled names will be the same regardless
of the --no_exceptions option (but of course, this means that the mangled names
could be different from those generated before this change when --no_exceptions
is used).


6/3/19   [EDGcpfe/21337]
"Storage class not first" remark with constexpr declarations

The stylistic remark (warning in strict mode) that highlighted when a storage
class specifier was not the first specifier in a declaration has been modified
to not be issued when the preceding specifier is "constexpr".  For example:

  constexpr static bool var1 = true; // No longer issues storage class remark
  const static bool var2 = true; // Still issues storage class remark


6/3/19   [EDGcpfe/21184]
__is_trivially_copyable for classes with const members

In some modes (e.g., GCC versions earlier than 4.9.0) the generation of
constructors for certain POD classes (e.g., ones with const members) is
suppressed.  For these classes, __is_trivially_copyable was returning "false",
even though it was possible to trivially copy the class.  For example:

  struct S { const int x; };
  // Previously the below assert would fire
  static_assert(__is_trivially_copyable(S), "S not copyable");

This is now fixed.


6/3/19   [EDGcpfe/21184]
GNU compatibility: Default constructors for classes with const members

GCC versions earlier than 4.9.0 did not implement the requirement that
constructors for classes with uninitialized const members be defined as
deleted (see EDGcpfe/14040).  GCC versions 4.9.0 and newer do fulfil this
requirement.  Clang always fulfilled this requirement.  For example:

  struct A {
    constexpr int f() const { return x+1; }
    int const x;
  };
  int x[A().f()]; // Previously accepted in GCC/Clang compatibility modes
                  // Now an error with gnu_version >= 40900 or any clang mode

GNU compatibility mode has been updated to reflect these changes.


6/3/19   [EDGcpfe/15936,EDGcpfe/18827,EDGcpfe/18884,EDGcpfe/19887,
          EDGcpfe/21308]
Underlying types of enumerations in GNU compatibility mode

GCC treats the underlying type of an unscoped enumeration as unsigned int when
this can contain all the values of the enumeration.  The front-end was
correctly emulating this behavior for unscoped enumerations, except for when
the enumeration was empty.  It was also incorrectly applying this behavior to
scoped enumerations.  For example:

  template<typename,typename> struct same;
  template<typename T> struct same<T, T>{};
  enum A {};
  enum B { b };
  enum class C {};
  enum class D { d };
  void f() {
    same<__underlying_type(A), unsigned int>(); // Failure to match GCC
    same<__underlying_type(B), unsigned int>(); // Matched GCC
    same<__underlying_type(C), int>(); // Matched GCC
    same<__underlying_type(D), int>(); // Failure to match GCC
  }

This is now fixed.


6/3/19   [EDGcpfe/21047]
C++-generating back end: Missing using-declaration in generated C++ code

In code where multiple entities were imported into a namespace via a comma-
delimited using-declaration list, later using-declarations may have incorrectly
been marked as having no "representative" using-declaration.  In C++-generating
back-ends, this may result in these using-declarations being omitted from the
generated code.  For example:

  int f00();
  namespace N01 {
    int f01();
  }
  namespace N02 {
    int f02();
  }
  namespace N {
    using ::f00, N01::f01, N02::f02; // Generated code previously had no
                                     // using-declaration for N02::f02
  }

This is now fixed.


5/31/19  [EDGcpfe/21329]
Floating-point constants incorrectly rounded to infinity

In configurations where USE_FLOAT128_FOR_HOST_FP_VALUE is TRUE, some
floating-point constants were incorrectly treated as infinite.  For example
(with --gcc):

  __float128 x = 1.189731495357231765085759326628007e+4932Q;


5/31/19  [EDGcpfe/21072]
Assertion failure in IL display program

In cases where a template-dependent type involves an expression that refers
to a block-scope entity, the edgcpdisp IL display program could abort with
a failed assertion ("scope for routine is NULL", in scope_for_routine).
This is now fixed.  For example, attempting to display the IL produced for
the following example resulted in the failed assertion:

  template <typename...> struct b;
  template <typename> struct d;
  template <class bk, typename bl, typename... bm>
  struct d<bl (bk::*)(bm...)> {
    typedef bk bn;
    typedef b<> bo;
  };
  template <typename> struct e;
  template <typename... bm> struct e<b<bm...>> {
    static int bx() { int c[sizeof...(bm)]; }
  };
  class f {
    void bz();
    void ca();
  };
  class g {
  public:
    void cc();
  };
  class h {
  public:
    template <typename ce, typename cf>
    static inline void cg(const typename d<ce>::bn *, ce,
                          const typename d<cf>::bn *, cf);
  };
  template <typename ce, typename cf>
  void h::cg(const typename d<ce>::bn *, ce, const typename d<cf>::bn *, cf) {
    e<typename d<ce>::bo>::bx;
  }
  void f::bz() {
    g a;
    h::cg(&a, &g::cc, this, &f::ca);
  }


5/31/19  [EDGcpfe/21071,EDGcpfe/21135]
Result of noexcept operator and pointer-to-member calls

Consider:

  struct S {
    void f() noexcept {}
    void g() {}
  } s;
  static_assert(!noexcept((s.*(true ? &S::f : &S::g))()));

The front end previously rejected this code because it could identify the
function being called after folding the conditional operator, and that function
(S::f) is noexcept.  However, the standard requires that only the type
information of the pointer-to-member expression (i.e., the conditional operator
expression) should be used in determining whether the expression is potentially
throwing, and the front end now reflects that (i.e., the case above is now
accepted).


5/31/19  [EDGcpfe/20602]
Trivial copyability and deleted copy-assignment operator

The front end previously issued a spurious error for:

  struct S { int const ic; };
  static_assert(__is_trivially_copyable(S), "Unexpected");

because the generated copy-assignment operator is deleted.  Deleted special
members, however, should not a priori affect the trivial copyability of class
types.  That is a consequence of a change introduced by the resolution of the
standardization committee's Core issue 1734.  The front end now implements
that resolution except in Microsoft mode.


5/31/19  [EDGpcfe/21158]
GNU/Clang compatibility: Mutability of compound literals

In GNU and Clang modes, the front end sometimes treats compound literals as
rvalues.  Those rvalues may later be turned back into lvalues by associating
them with a generated static variable.  That variable was previously declared
with the type specified for the compound literal, but now it is always declared
with a "const" type to communicate the immutability of the compound literal
(the expression denoting the compound literal is not necessarily "const",
however).  Note that the standard (in C) "compound literal" feature produces
an lvalue that is mutable if its type is not "const".


5/30/19  [EDGcpfe/21314]
C++-generating back end: decltype(auto) return types and expressions

The C++-generating back end previously failed to preserve parentheses
around the name of a variable used as the return expression in a function
whose return type is decltype(auto).  A parenthesized variable name
results in a reference return type, while an unparenthesized variable name
causes the return type to be the type of the variable.  For example, with
--c++14:

  int xxx;
  constexpr decltype(auto) foo() {
    return (xxx);  // Previously generated without parentheses
  };
  constexpr decltype(auto) yyy = foo();
  static_assert(&yyy == &xxx, "");

Because of the omitted parentheses in the generated code, the return type
was deduced as "int" rather than as "int &", as it was in the original
source, and the generated code failed the static assertion.  This is now
fixed.


5/30/19  [EDGcpfe/21164]
Clang compatibility: __reference_binds_to_temporary

In Clang C++ mode with clang_version >= 70000 the front end now supports the
type traits helper operator "__reference_binds_to_temporary".  Specifically,
__reference_binds_to_temporary(R, T) produces a true value if and only if R
is a reference type and

	R r = std::declval<T>();

is valid and causes r to be bound to a temporary.  For example:

  static_assert(!__reference_binds_to_temporary(int&, int&));
  static_assert(__reference_binds_to_temporary(int const&, long));
    // Now accepted in some Clang modes.


5/30/19  [EDGcpfe/21316]
Uninitialized constants in string aggregate initializers

When the constexpr interpreter encountered a string literal initializing an
array, it generated an aggregate initializer for the array from the string
literal.  However, if the length of the literal (including null terminator) was
less than the size of the array, the remaining constants in the aggregate
initializer contained uninitialized memory instead of zeroes as expected.  For
example:

  struct A
  {
    char name[10] = "";
  };
  void f() {
    A a; // name[1] through name[9] uninitialized
  }

This is now fixed.


5/29/19  [EDGcpfe/21172]
Incorrect handling of bit fields in constexpr interpreter

Unsigned bit fields were incorrectly treated as signed in the constexpr
interpreter, leading to spurious errors.  For example, in C++17 mode:

  struct S { unsigned bf:4; };
  static_assert([]{ S s{}; s.bf = 15; return s.bf; }() == 15);
       // Previously failed.  Now okay.

Furthermore, the operators &=, |=, and ^= could produce results that were not
limited to the width of a bit field to which they were applied.  E.g.:

  constexpr int f() {
    struct { int i:4; } s{0};
    return s.i |= 255;
  };
  static_assert(f() < 16, "Unexpected");  // Previously failed.  Now okay.

That is now fixed.


5/29/19  [EDGcpfe/21307]
Add --promote_warnings command line option

A --promote_warnings (-W) option has been added to enable promotion of warnings
to discretionary error severity.  For example (with --promote_warnings):

  void f(int x) { // Remark: parameter not referenced (severity unchanged)
    int y = 0;    // Error: variable not referenced (severity promoted)
  }


5/29/19  [EDGcpfe/20012,EDGcpfe/20421]
C++20: Access Checking on Specializations

C++20 allows partial specializations and full specializations to make use of
inaccessible members in the declaration of the specialization (see P0692R1).
This is now supported in C++20 mode.  This is also enabled in Microsoft
mode and g++ mode for gnu_version >= 60000 (g++ 9.1 actually rejects this
usage, but we believe that to be a g++ bug).

  template <class T> struct A;
  template <class T> void f(T);
  class B {
    template <class U> struct C {};
  };
  template <class T> struct A<B::C<T>>;  // now allowed
  template <> void f(B::C<int>) {  // now allowed
    B::C<int> bc;  // still an error
  }


5/29/19  [EDGcpfe/21201]
Spurious error on defaulted exception specification of template member

Consider:

  struct X { X(X const&) noexcept(false); };
  template<typename T> struct Y {
    T x;
    Y(Y const&) noexcept(false) = default;
  };
  Y<X> f(Y<X> const &p) {
    return p;  // Previously a spurious error.
  }

Previously, this resulted in a spurious error because the front end
erroneously marked the copy constructor of Y<X> as "deleted".  This was a
consequence of failing to "instantiate" the "noexcept(false)" exception
specification.  That is now fixed.


5/28/19  [EDGcpfe/21194]
Incorrect value category when using non-member "get" with structured bindings

The front end was not properly applying the appropriate value category for
a tuple-like structured binding when using a non-member "get" function.  For
example:

  struct A {};
  namespace std
  {
    template <typename> struct tuple_size;
    template <> struct tuple_size<A> { static constexpr int value = 1; };
    template <int, typename> struct tuple_element;
    template <> struct tuple_element<0, A> { typedef int type; };
  }
  template <int> int get (A &&);
  void f(A a)
  {
    auto  [a0] = a; // Incorrectly failed to find a suitable "get" function
    auto& [a1] = a; // Correctly fails to find a suitable "get" function
  }

This is now fixed.


5/28/19  [EDGcpfe/21283]
Microsoft compatibility: __builtin_offsetof

The __builtin_offsetof builtin function is now accepted in Microsoft emulation
modes when microsoft_version >= 1910.


5/27/19  [EDGcpfe/21115]
Defaulted parameters having the parent class type in copy constructors

In C++14 and earlier, a copy constructor that has a defaulted parameter of the
same type as the class being constructed would use the copy constructor to copy
the default argument value to the parameter variable, resulting in unbounded
recursion, and was therefore not permitted.  In C++17, however, guaranteed copy
elision means that that copy may be elided, making such parameters potentially
valid.  The front end now accepts copy constructors with defaulted arguments
that have the parent class type in these modes.  For example:

  struct B {
    B();
    B(const B &, B = B()); // Rejected in C++14 mode
                           // (Now) accepted in C++17 mode
  };
  void f() {
    B b;
    B b2(b);
  }

This is now fixed.


5/27/19  [EDGcpfe/20997]
Spurious "incompatible declaration" error with multiple translation units

When a symbol such as "std::align_val_t" is predeclared and later defined in
one translation unit but not another, this could lead to spurious "incompatible
declaration" errors arising from differences between the predeclared type and
the type as seen in source.  For example, given the following definition of
"std::align_val_t":

  namespace std {
    typedef decltype(sizeof(0)) size_t;
    enum class align_val_t : size_t { };
  }

If one TU had this definition but the other did not, an "incompatible
declaration" error could be issued.  This is now fixed.


5/27/19  [EDGcpfe/20966]
Spurious "function has different meaning" error with multiple translation units

In C++17 mode, the exception specification makes up part of the type of the
function.  When attempting to compare two of the same special functions (e.g.,
a constructor) between translation units where one TU had the exception
specification of the function determined, while the other had it still
indeterminate, this could cause a spurious error.  For example, given this
header:

  struct A {
    A();
  };
  struct B : A {}; // Possible spurious "different meaning of B::B()" error

If two files include the header but only one creates an instance of "B", a
spurious error would be generated.  This is now fixed.


5/27/19  [EDGcpfe/21059,EDGcpfe/21151]
Abort with class template argument deduction and multiple translation units

When a secondary translation unit contained code where class template argument
deduction was being performed with implicit deduction guides, the front end
would fail an internal assertion check in 'find_routine_correspondence'.  For
example, if the following code was in a secondary translation unit:

  template<class T> struct B
  {
    B(T v1,T v2);
  };
  void foo() {
    new B{1,2}; // Previously the generated deduction guide caused an abort
  }

This is now fixed.


5/27/19  [EDGcpfe/20953]
Spurious errors on inline variables with multiple translation units

In configurations allowing compilation of multiple translation units, spurious
"already defined" errors were being issued for C++17 inline variables.  For
example, when compiling two files with this code:

  inline int foo = 1; // Spurious "already defined" error

This is now fixed.


5/24/19  [EDGcpfe/21187]
Spurious failure instantiating partially explicit template function

In some uses where a template function used a pack expansion inside a decltype
construct and the template arguments were partially specified, a spurious error
might be encountered.  For example:

  template <int... Ints> struct is { };
  struct A {
    A(int, int);
  };
  template <class T, int... I>
  decltype(T{ I... }) func(T, is<I...>);

  void f() {
    A f{1, 2};
    func<>          (f, is<1, 2>{});
    func<A>         (f, is<1, 2>{}); // Spurious "no matching function" error
    func<A, 1>      (f, is<1, 2>{}); // Spurious "no matching function" error
    func<A, 1, 2>   (f, is<1, 2>{});
    func<A, 1, 2, 3>(f, is<1, 2>{}); // Valid "no matching function" error
  }

This is now fixed.


5/24/19  [EDGcpfe/21110]
Assertion failure in lower_routine

In some configurations that use lowering, an assertion failure (in
lower_routine) had occurred and is now fixed.  For example (with --c++17):

  auto monoid = [](auto v) { return [=] { return v; }; };
  auto add = [](auto m1) constexpr {
    auto ret = m1();
    return [=](auto m2) mutable {
      auto m1val = m1();
      auto plus = [=] (auto m2val) mutable constexpr { return m1val += m2val;};
      ret = plus(m2());
      return monoid(ret);
    };
  };
  constexpr auto zero = monoid(0);
  constexpr auto one = monoid(1);
  static_assert(add(one)(zero)() == one());


5/24/19  [EDGcpfe/21291]
GNU compatibility: __builtin_expect and __builtin_expect_with_probability
accepted in constexpr expressions in C++11 mode

A change has been made to accept calls to __builtin_expect and
__builtin_expect_with_probability in constexpr contexts in C++11 mode.
For example, with --gnu_version 50400 --c++11:

  constexpr int f(int i) {
    return __builtin_expect(i <= 100, 1) ? 0 : 0;
  }
  constexpr int l = f(4);


5/23/19  [EDGcpfe/21234]
Spurious error on singleton braced initializer for aggregate class object in a
template dependent context

The previous fix for EDGcpfe/17295 did not handle the case where the braced
initializer list contained a single value that was dependent on template
arguments.  For example:

  struct A {};
  template <typename T> void foo(T t)
  {
    A a{t};  // Spurious "too many initializer values" error
  }
  void f()
  {
    foo(A{});
  }

This is now fixed.


5/23/19  [EDGcpfe/21152]
Rename __type_info to __EDG_type_info

The name of the type created by lowering to handle tik_user types had been
__type_info, but that name is used by the LLVM libc++ library (by
include/any) and causes a conflict.  The name used by the front end has
been renamed __EDG_type_info to avoid this conflict.


5/23/19  [EDGcpfe/21281]
Auto type specifier flag on function pointer with trailing return type

Function pointer variables declared with trailing return types were incorrectly
having their declared_with_auto_type_specifier flag set.  This caused problems
when using that variable.  For example:

  int f(void);
  auto (*g)(void) -> int;
  int h() {
    g = f;      // Spurious "auto variable in its own initializer" error
    return g(); // Spurious "auto variable in its own initializer" error
  }

This is now fixed.


5/23/19  [EDGcpfe/21188]
Missing has_direct_braced_initializer flag for static data members of class
templates

An instantiation of a class template containing a static data member with a
direct braced initializer in modes where the initializer is instantiated on
demand was not setting the has_direct_braced_initializer flag for the variable
unless the initializer was instantiated.  For example:

  template<class T> class A
  {
    static const int foo{1}; // has_direct_braced_initializer == TRUE in the
                             // prototype instantiation of A<T>::foo
  };
  A<int> a; // has_direct_braced_initializer == FALSE for A<int>::foo

This is now fixed.


5/22/19  [EDGcpfe/21244]
C++-generating back end: name qualification of enumerators in generated
template instances

In configurations in which DEFAULT_RECORD_FORM_OF_NAME_REFERENCE and one or
both of CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS are TRUE, needed
qualification could be omitted on the name of an enumerator appearing in a
generated template instance if that enumerator name is the result of
substituting a template argument for a template parameter.  For example,
given

  namespace N {
    enum E { e };
  } 
  template <N::E V> struct S {
    bool f() {
      return (0 != V);
    }
  };
  typedef S<N::e> Se;
  void f() {
    Se se;
    se.f();
  }

the generated code contained an explicit specialization for the function
S<N::e>::f() in which the return statement was put out as

  return (0 != e)

i.e., the use of the enumerator "e" was missing the necessary qualifier
"N::".  This is now fixed.


5/22/19  [EDGcpfe/20917,EDGcpfe/20948]
C++20: Coroutines

The previous implementation of coroutines that was enabled when the
COROUTINES_ALLOWED flag was set has been replaced with a C++20-compliant
implementation.  The COROUTINES_ALLOWED flag has been removed.  Lowering of
coroutines is not fully supported as of yet, so the new flag
COROUTINE_ENABLING_POSSIBLE has been added to indicate whether coroutine
support should be enabled.  This flag defaults to FALSE in configurations that
set the DO_IL_LOWERING flag, and to TRUE otherwise.

The most notable change between the previous implementation and the current one
is that return type deduction for coroutines is no longer possible.
Furthermore, the expected call sequence and required member functions have been
changed to match what is required by C++20.  While the C++20 standard requires
that name lookup of the appropriate classes occurs in the std namespace, the
implementation will look in both the std and the std::experimental namespaces,
for compatibility with previous implementations; no other compatibility with
older implementations is implied.

  #include <coroutine>
  std::task<int> coro() {
    co_await std::suspend_always();
    co_yield 1;
    co_return 2;
  }


5/20/19  [EDGcpfe/20270]
C++20: Relaxed typename rules

C++20 allows the typename keyword to be omitted when it is possible to know
that a name must be a type based on context (see P0634R3).  This is now
implemented in C++20 mode.  This change includes a change expected to be
made as the resolution of core issue 2413, which adds conversion-type-id
to the contexts where a name is known to be a type.

  template <class T> T::R f();  // T::R now know to be a type


5/18/19  [EDGcpfe/21218,EDGcpfe/21255]
Internal error processing fold expression

An internal error could occur (in copy_tokens_from_cache) when a fold
expression occurred in a default template argument.  Now fixed.

  template <bool B> struct A { };
  template <char v> struct B {
    static constexpr char value = v;
  };
  template <char... Ts> struct C {
    constexpr inline C() noexcept { };
    template <char c, typename = A<((Ts == c) || ... || false)>>
    constexpr inline C(B<c>) noexcept { }
  };
  C<'a','b'> c{};
  C<'c'> c2{B<'c'>{}};


5/16/19  [EDGcpfe/21259]
Use Berkley SoftFloat library for floating-point arithmetic

Previously, the front end could only support floating-point types that were
also supported by the host compiler (because the front end needs to be able
to fold floating-point operations at compile time).  A change has been made
to optionally use the Berkley SoftFloat library to perform all floating-point
arithmetic.  This option can be selected by setting the new USE_SOFTFLOAT
configuration macro to TRUE (the default is FALSE).  In such configurations,
the build process must be suitably modified to include the SoftFloat headers
and library.

The front end was tested with Release 3e of the Berkley SoftFloat distribution.
See http://www.jhauser.us/arithmetic/SoftFloat.html for documentation and
licensing information.  Performing floating-point operations in software is
slower than performing them in hardware.  See the SoftFloat documentation for
details.

In configurations where USE_SOFTFLOAT is TRUE, USE_HOST_FP_CONVERSION_ROUTINES
must be set to FALSE (see the Changes entry for EDGcpfe/21236).  This provides
a configuration that, e.g., can support 128-bit floating-point types when
compiled by a host compiler that does not support 128-bit floating-point types.


5/15/19  [EDGcpfe/21222]
C++-generating back end: Rendering of type for new-expressions

The syntax for new-expressions like "new X*[3]" requires parentheses around
certain type constructs.  For example, "new (X(*)())" cannot leave out the
outer parentheses.  However, the parenthesized form cannot contain a run-time
dimension.  E.g., "new int[n]" is valid for a nonconstant n, but "new (int[n])"
is not.  Previously, the C++-generating back end used a criterion for rendering
parentheses that erred on the side of adding redundant parentheses.  Now it
adds the parentheses only if syntactically required.


5/14/19  [EDGcpfe/21175]
Nontype template arguments and local static variables

In C++17 mode, a nontype template argument of reference or pointer type can now
refer to a local static variable.  For example:

  template <int*> struct S {};
  auto f() {
    static int x = 0;
    return S<&x>{};  // Now accepted in C++17 mode.
  }


5/14/19  [EDGcpfe/21229]
C++-generating back end: template arguments for function template instances

In configurations in which DEFAULT_RECORD_FORM_OF_NAME_REFERENCE is FALSE
or NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
C++-generating back end put out the complete template argument list when
generating the name of an instance of a function template.  In most cases
this did not cause problems, but in cases like the one in the example
below, the resulting code was incorrect and could not be compiled.  This
has now been addressed by putting out only as many template arguments as
the maximum number specified at any point in the translation unit. For
example, in a configuration in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, with
--c++11,

  template<typename...> struct A { };
  template<typename, typename... Ts, typename... Us>
  void f(A<Ts...> &, A<Us...>) { }
  void g() {
    A<int> ai;
    A<char> ac;
    f<int>(ai, ac);
  }

the generated code contained an explicit specialization whose name was
given as "f<int, int, char>", which could not be compiled because of the
ambiguity of determining which template arguments matched Ts and which
matched Us.  The name of the explicit specialization is now put out as
"f<int>", since only one explicit argument was ever used in referencing
that instance of the template.


5/14/19  [EDGcpfe/21206]
GNU compatibility: __builtin_expect_with_probability

The GNU builtin function, __builtin_expect_with_probability, can now be
invoked in a constexpr context.  Only the first argument is evaluated
(just like __builtin_expect); see the Changes entry for EDGcpfe/19838.


5/14/19  [EDGcpfe/21023]
Spurious error on constant-evaluation involving init-capture

In some situations, constant-evaluating a lambda with init-captures resulted
in a spurious error about the init-capture not having been initialized.  For
example:

  template<typename T> constexpr auto f(T t) {
    return [c = t]() { return c; };
  }
  template<int N> constexpr auto x = f(N);
  constexpr int r = x<42>();  // Previously an error because "c" above was
                              // considered uninitialized.  Now okay.

That is now fixed.


5/14/19  [EDGcpfe/21233]
Internal error after decltype applied to a dependent structured binding

In some situations, applying the decltype operator to a structured binding with
a dependent initializer could lead to an internal error because the decltype
construct silently produced an error type.  For example:

  struct S { int member; };
  S f(int i) { return S{i}; }
  template<typename T> bool v = T{};
  template <typename T> int g(T p) {
    auto [b] = f(p);            // Previously triggered an internal error
    return v<decltype(b)>;      // in name mangling.
  }
  int r = g(42);

In this example, decltype(b) silently produced an error type, causing name
mangling to later fail an assertion check.  That is now fixed.


5/14/19  [EDGcpfe/21179]
Microsoft compatibility: Builtins for char8_t

Three new builtins, __builtin_u8memchr, __builtin_u8memcmp, and
__builtin_u8strlen have been added in Microsoft emulation mode when
microsoft_version >= 1922.  Additionally, the char8_t type (see the Changes
entry for EDGcpfe/20530) has been enabled by default when microsoft_version
>= 1922 and ms_cpp20_mode is TRUE.


5/13/19  [EDGcpfe/19757,EDGcpfe/21050]
Spurious error on initializer for static data member template

The front end previously issued a spurious error on initializers for static
data member templates that are introduced by an assignment token ("=") followed
by a left parenthesis.  For example:

  struct S {
    template<typename T> static constexpr T *const sm = (T*)0;
          // Previously triggered spurious error about a missing ")".
  };      // Now okay.

That is now fixed.


5/12/19  [EDGcpfe/21237]
Instantiating inline variables with prelinker with LOWER_EXTERN_INLINE

Formerly, in configurations that do not have COMDAT support, the handling
of both inline functions and inline variables was controlled by
INSTANTIATE_EXTERN_INLINE.  This meant that the prelinker could not be used
to instantiate inline variables when LOWER_EXTERN_INLINE was TRUE.
A new configuration flag named INSTANTIATE_INLINE_VARIABLES has been added
to allow this to be controlled separately.  By default it is FALSE if
the IA-64 ABI is being used or if LINKER_CAN_DISCARD_DUPLICATE_DEFINITIONS
is TRUE, and FALSE otherwise.  See also EDGcpfe/20083.


5/10/19  [EDGcpfe/15513,EDGcpfe/20180]
Microsoft compatibility: __uuidof and constexpr

In Microsoft modes, the front end now treats __uuidof expressions as full-
fledged constant expressions.  For example:

  typedef struct _GUID {
    unsigned long  Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char  Data4[8];
  } GUID;
  struct __declspec(uuid("{12345678-ABCD-EFFE-DCBA-987654321000}")) X {};
  constexpr GUID guid = __uuidof(X);        // Now accepted in Microsoft mode.
  static_assert(guid.Data3 == 0xEFFE, "");  // Ditto.
  

5/10/19  [EDGcpfe/21236]
Floating-point conversion routines

Historically, conversion between the binary representation of floating-point
numbers and their decimal string representation has been performed by
routines provided by the host (e.g., sscanf, sprintf, strtod, or in some
configurations, strtoflt128).  Using host routines for conversion has
two limitations: it limits the floating point types that can be supported on
the target to those that are provided by the host compiler, and the
implementation is not very portable from one host to another.

Routines have now been added to do the binary to decimal floating-point
conversion completely in software, using integer arithmetic, to avoid any
dependence on the underlying hardware's floating-point capabilities.
This new capability can be selected by setting the value of the configuration
macro USE_HOST_FP_CONVERSION_ROUTINES to FALSE (it is TRUE by default).
These routines support four types of floating-point types (and are configurable
to support more): binary32 (typically float), binary64 (typically double and
sometimes long double), binary128, (__float128 and sometimes long double),
and 80-bit extended (__float80 and sometimes long double).

When setting USE_HOST_FP_CONVERSION_ROUTINES to FALSE, is important to set
the appropriate FP_LONG_DOUBLE_IS_* macro to select the proper floating-
point type for the "long double" type.

Setting USE_HOST_FP_CONVERSION_ROUTINES to FALSE will cause the front end to be
slower when converting floating-point numbers (as the conversion is done
totally in software without the aid of floating-point hardware).

Three new files were added to support this capability: float_type.h,
floating.c, and floating.h.


5/10/19  [EDGcpfe/21232]
Spurious error on specialization of variable template declared with auto

A spurious error was issued if a variable template was defined using an
auto type and then later explicitly specialized (with or without the use
of auto).  Now fixed.

  template <typename> auto v = 0;
  // Both explicit specializations resulted in errors
  template <> auto v<int> = 1;
  template <> int v<char> = 2;


5/9/19   [EDGcpfe/17793,EDGcpfe/18028,EDGcpfe/18143]
GNU C++ compatibility: Variable-length array initialization

A number of changes have been made to the handling of initialized VLA objects
(available in g++ emulation mode when gnu_version >= 40900).  Previously
configurations where LOWER_VARIABLE_LENGTH_ARRAYS is TRUE had failed an
assertion check in all C-generating back end configurations.  That is now
fixed.  Additionally, a change has been made to mark VLA initializers as
partially-initialized, thereby enabling default initialization of all elements
of the VLA at run-time.

The type of an aggregate being used to initialize a VLA object has also been
modified to reflect the number of elements in the aggregate, and no longer
matches the type of the VLA object.  E.g., for "int x[n] = { 1, 2 };",
the aggregate type will be "array [2] of int" (whereas it had been
"array [n] of int").  That is necessary because GCC appears to use all
initializers in the array, even if the array is too small for them at
run time.  For example (with --gnu_version 40900):

  extern "C" int printf(char const*, ...);
  struct X {
    X() { printf("X()\n"); }
    X(int i) { printf("X(%d)\n", i); }
  };
  void f(int i) {
    printf("i=%d\n",i);
    X x[i] = { 1, 2 };
  }
  int main() {
    f(0);   // calls X(1), X(2), initializes x[0], x[1]
    f(1);   // calls X(1), X(2), initializes x[0], x[1]
    f(2);   // calls X(1), X(2), initializes x[0], x[1]
    f(3);   // calls X(1), X(2), X(), initializes x[0], x[1], x[2]
    return 0;
  }


5/7/19   [EDGcpfe/19803,EDGcpfe/21178]
GNU C++ compatibility: abort using __integer_pack

An abort could occur when doing substitution on a g++ __integer_pack.  The
abort would occur in update_template_param_symbols.  Now fixed.

  template <class T> struct A;
  template <class T, T... _Idx> struct IS {};
  template <class T, T N> using make_IS = IS<T, __integer_pack(N)...>;
  template <int N> using D = make_IS<int, N>;
  template <class... Ts> class C {};
  template <class... Ts> struct A<C<Ts...>> {
    static constexpr int v = 2;
  };
  template <class C, class U = D<A<C>::v>> auto f(C) -> decltype(U());
  int main() {
    C<int,int> c;
    f(c);
  };


5/6/19   [EDGcpfe/21195]
Spurious error capturing "this" in a lambda during template argument deduction

The fix for EDGcpfe/20863 missed the case where the lambda expression needed
to be used to deduce a template parameter.  In this case, the front end was
still issuing a spurious error when attempting to use "this".  For example:

  struct function
  {
    template<typename _Functor> function(_Functor);
  };

  struct Lambda
  {
    function callback_ =
      [this](const auto v) { return this; }; // Spurious error on using "this"
  };

This is now fixed.


5/3/19   [EDGcpfe/20664]
GNU compatibility: Builtins for GCC 9.1.0

The front end has been updated to incorporate builtins from release 9.1.0
of GCC.


5/2/19   [EDGcpfe/21186]
GNU compatibility: Suppress __weak__ attribute with __always_inline__

When a routine is marked for a COMDAT section the C-generating back end
(when GCC or Clang is being used as the back end compiler) adds the __weak__
attribute to the generated C declaration.  For later versions of GCC, that
can cause the generated code to fail to compile when the routine is also marked
with the __always_inline__ attribute (because the linker could conceivably
choose a different routine than the one that is inlined in the translation
unit).  In such cases, the __weak__ attribute is now suppressed.  For example:

  inline __attribute__ ((__always_inline__)) int f() { return 0; }
  int main() {
    return f();
  }


5/1/19   [EDGcpfe/19913]
GNU compatibility: Failure to properly diagnose directly calling a constructor

The front end was failing to issue an error when directly calling a constructor
in GNU compatibility modes.  Furthermore, the error being issued when directly
calling a constructor was non-obvious (it complained about taking the address
of the constructor).  A new error has been added that makes the error clear,
and is now correctly issued in all modes.

  struct S { S(){} };
  S s = S::S(); // Previously failed to issue an error


5/1/19   [EDGcpfe/21174]
Template substitution of member declarations containing member calls

Consider:

  template<bool b> struct B { static constexpr bool value = b; };
  struct S {
    template<typename T> static bool test();  // (1)
    template<typename T> static auto test(int) -> B<test<T>()>;  // (2)
    template<typename> static B<false> test(...);  // (3)
  };
  auto r = S::test<int>(0);

Overload resolution for the call S::test<int>(0) performs template argument
substitution in the expression test<T>() in the return type of candidate (2).
In the context of (2), looking up "test" only finds declaration (1),
so the call test<int>() is unambiguous and well-formed, making candidate (2)
viable, and overload resolution selects candidate (2) over candidate (3).
However, during the instantiation of candidate (2), the front end performs the
lookup of 'test' in 'test<int>()' in the complete class, which resulted in an
ambiguity between candidates (1) and (3).  The standard actually deems such
cases (where a lookup yields different results at the point of the member
declaration and in the completed class) ill-formed, but does not require a
diagnostic for them.  However, it appears that common practice is for the
substitution to perform the substituted lookups in the completed class context.
In this example, that means that substitution of (2) triggers the
aforementioned ambiguity, and hence candidate (2) is simply discarded (SFINAE)
for the call "S::test<int>(0)".  Candidate (3) is then the unambiguously
selected function for that call.


5/1/19   [EDGcpfe/20499]
Abort when attempting CTAD with no viable deduction guides

The front end failed an assertion in select_overloaded_function in cases where
it was attempting to perform class template argument deduction where no viable
deduction guides existed.  Most commonly this would be during error recovery
where the error type prevented default constructors from being generated.  For
example:

  template <class T<int>>
  struct A {}; // Error, T is not a template
  A a = {};    // Previously would abort, now issues an error


4/30/19  [EDGcpfe/21173]
Microsoft compatibility: hexadecimal floating-point literals

Hexadecimal floating-point literals are now accepted in default Microsoft C++
emulation modes when microsoft_version >= 1913.  See also the Changes entry
for EDGcpfe/18705.


4/29/19  [EDGcpfe/20867]
Parameter pack expansion failure in generic lambda instantiation

In some scenarios where a generic lambda was being used from within a template,
parameter packs would not be correctly expanded.  For example:

  template<typename Ts>
  struct S {
    S() {
      [&](auto... x) { f(x...); }; // Spurious "too many arguments to f" error
    }
    void f();
  };

  S<int> s;

This is now fixed.


4/29/19  [EDGcpfe/20639]
Dependent constant bounds in GNU C++ mode

Consider:

  template<int N> constexpr int f() { return N; }
  template<int N> void g() {
    static float x[f<N>()];
  }

Previously, this elicited an error in GNU C++ mode, because the front end
considered the possibility of variable-length arrays (VLAs, permitted in GNU
C++ mode) and treated "f<N>()" as a run-time expression.  That is now fixed.



4/29/19  [EDGcpfe/20782]
Microsoft compatibility: internal error on new template template matching

In Microsoft modes where the C++17-style template template argument matching
is done (e.g., with --ms_c++17 --microsoft_version=1912), an internal
error could occur (in get_template_arg_value_from_default).  Now fixed.

  template <typename T, typename U> struct A {
    typedef int ax;
  };
  template <template< typename P1, typename P2> class B,
            typename T1, typename T2, typename U> struct A<B<T1, T2>, U> {
    typedef A<T1, U> a1;
    typedef typename a1::ax ax1;
  };
  template< class TA, class TB, bool force_mutable = false > class C {};
  typedef A<C<int, int, 1>, void > a;
  typedef typename a::ax ax;


4/26/19  [EDGcpfe/20884]
Abort in C++-generating back end on dependent template argument

Consider:

  template<int> struct S;
  template<int I> using A = S<I>;
  template<typename T> int f() {
    constexpr int N = T::N;
    return A<N>(0);  // Previously triggered an internal error.  Now okay.
  }

The template argument N in A<N> is represented as a ck_template_param constant
entry allocated in file scope, and that constant must refer to the function-
scope variable N.  This referral from a file-scope entry to a function-scope
entry was previously lost, causing the C++-generating back end to abort because
it could not access the template argument expression.  That is now fixed.


4/26/19  [EDGcpfe/20167]
Copy elision with the comma operator

The front end was not eliding copies when the result of the comma operator
was eligible for copy elision.  For example (with --c++17):

  struct S { S(); S(const S&) = delete; };
  S s = (42, S{});  // Spurious deleted copy constructor error issued

This is now fixed.


4/25/19  [EDGcpfe/20863]
Capturing "this" in a NSDMI within a local class

The change EDGcpfe/20049 (not part of a release, but widely distributed as a
patch for 5.0) caused a regression that made it so that the "this" member of a
local class was not able to be captured by a lambda expression in a non-static
data member initializer.  For example:

  void f() {
    struct Z {
      int i;
      int b = ([&] { return i; }()); // Spurious error on the implicit "this"
    } z;
  }

This is now fixed.


4/25/19  [EDGcpfe/20787]
Assertion failure in final_overrider

In some scenarios the front end would attempt to suppress the virtual function
mechanism while still in a template prototype instantiation context.  This
could lead to an abort in final_overrider.  For example (with -tused):

  struct Base2 { virtual void coupled(); };
  template <class T> struct Base : public Base2 {};
  template <class T> struct Derived : public Base<T>
  {
    using Base2::coupled;
    Derived(int) {
      coupled();  // Previously would abort
    }
  };
  Derived<int> foo(0);

This is now fixed.


4/25/19  [EDGcpfe/21118]
Explicit specialization of member variable template considered definition

An explicit specialization of a member variable template was considered
a definition in some cases when it should not be resulting in spurious
errors.  Now fixed.

  struct A {
    template <class T> static T v;
  };
  template <class T> T A::v = 1;
  template <> int A::v<int>;
  template <> int A::v<int> = 2;
  int main() {
    return A::v<int> != 2;
  }


4/24/19  [EDGcpfe/20935]
Bit field promotions in folded constants

The front end was previously ignoring the original expression when using the
resulting constants from performing constant folding on class/struct/union
fields.  This led to a failure to properly promote bit field types.  For
example:

  struct S { unsigned long long f:4; };
  void f(S s) {
    decltype(+s.f) x;   // Correctly gets type of "int"
    decltype(+S{}.f) y; // Incorrectly received type of "unsigned long long"
  }

This is now fixed.


4/24/19  [EDGcpfe/20063]
GNU __extension__ and statement expressions

The front end failed to apply the GNU __extension__ keyword appearing on a
statement expression to expressions nested within it.  For example:

  void f(void *p)
  {
    __extension__({ p + 0; }); // Spurious pointer arithmetic warning issued
    __extension__(p + 0);      // No warning issued
  }

This is now fixed.


4/24/19  [EDGcpfe/21017]
Position information for uses of lambda captures

Consider:

  auto lm = [x]{ if (x) return 1; else return 42; };

The use of the identifier x in the if-statement produces a compiler-generated
selection statement (selecting the captured value from the associated closure).
Previously, no position information was recorded in the field selection node
(because, generally, no position information is recorded for compiler-generated
nodes).  Now, the position of the identifier (in the if-statement condition) is
recorded in that node.


4/24/19  [EDGcpfe/19433,EDGcpfe/21060]
Abort in function_template_call_argument_deduction with empty pack expansion

Consider:

  template<typename R, typename P> R f(P);
  template<typename F, typename S, typename... Ts> int f(Ts... x, S y, S z);
  auto r = f<int>(42);  // Previously aborted.  Now okay.

This case previously aborted in function_template_call_argument_deduction
with an internal error because that function did not expect the argument
count of the call to be different from the parameter count of the second
template after substituting the "<int>" template argument list (in most cases,
such mismatches are caught earlier).  That is now fixed.


4/24/19  [EDGcpfe/21165]
Unions and nested interpreter invocations

When dealing with unions, the interpreter manages "variant path entries" that
represent union field selections in addressable contexts (glvalues, pointers,
and references).  Those entries were previously always reclaimed when an
invocation of the interpreter completed.  However, it is possible for multiple
interpreter invocations to nest: In such cases, the reclamation of "variant
path entries" for an inner invocation could erroneously reclaim entries that
should remain active for the outer invocation.  Such situations could lead to
aborts or spurious errors.  That is now fixed.


4/23/19  [EDGcpfe/21160]
__has_cpp_attribute with g++ and clang attributes

The front end previously always made __has_cpp_attribute return false for
gnu and clang attributes, even when they were available in the current
emulation mode.  This is now fixed.  For example, with --g++:

  #if !__has_cpp_attribute(noinline)
  #error Missing noinline support  // Previously incorrectly triggered
  #endif


4/23/19  [EDGcpfe/20185,EDGcpfe/20187,EDGcpfe/20232,EDGcpfe/20353,
          EDGcpfe/20937,EDGcpfe/20960]
Auto nontype template parameter issues

In some cases, types were not deduced from nontype template parameters
as should be done when the changes for auto template parameters are enabled.
This resulted in spurious errors for partial specialization cases such as
this one:

  double f(int, bool);
  template <auto& f> struct A;
  template <class R, class... Args, R (& f)(Args...)> struct A<f> {
    using type = R;
  };
  using R1 = A<f>::type;

In addition, deduction involving deduction from the type of an array bound
(if not otherwise deduced) did not work in cases such as those in this
example:

  template <typename T, T SZ> void f(const int (&)[SZ]) { }
  template <typename T, T SZ> void g(const T (&)[SZ]) { }
  int main() {
    int arr[3];
    f(arr);    // (1) should work, but is rejected
    g({{}, {}}); // (2) should work, but is rejected
  }

These issues are now fixed.


4/23/19  [EDGcpfe/21034]
C++-generating back end: default arguments in alias templates

In configurations in which template definitions are generated from the
prototype instantiation IL, if a parameter in an alias template definition
has a default argument that refers to a previous parameter and an instance
of the alias template uses that default argument, the name of the instance
put out by the C++-generating back end included the default argument, even
though the template parameter is no longer in scope at that point.  This
is now fixed.  For example, with --c++11:

  struct Q {};
  template <typename> struct S {
    template <typename T, typename U = T> using X = int;
    X<Q> a;  // Previously generated as X<Q, T>
  };


4/23/19  [EDGcpfe/20924]
Variadic using-declaration fails with empty expansion

If a variadic using-declaration was expanded with an empty pack, a spurious
error was issued.  Now fixed.

  template<typename ...T> struct A : T... {
    using T::f ...;
  };
  A<>     a;


4/22/19  [EDGcpfe/21136]
Clang compatibility: internal_linkage attribute

The front end now accepts the internal_linkage attribute in clang emulation
modes when clang_version >= 40000.  See the clang documentation
(https://clang.llvm.org/docs/AttributeReference.html#internal-linkage) for a
description of the attribute.  In the example below, f, A::A, A::f, and A::m
are all local to the file in which they appear (with --clang_version 40000):

  void __attribute((internal_linkage)) f() {}
  struct __attribute((internal_linkage)) A {
    A() {}
    void f() {}
    static int m;
  };



4/21/19  [EDGcpfe/21157]
Incorrect handling of empty expansion of template parameter pack

If the type of a nontype template parameter is the expansion of another
template parameter pack (T... X in the example below), the expansion
could fail when the pack for T was empty.  This could result in spurious
errors and/or internal errors.  Now fixed.

  int g(...);
  template <typename ...T> struct A {
    template <T... X> static decltype(g(X...)) f() { return g(X...); }
  };
  int main() {
    A<>::f<>();
  }


4/19/19  [EDGcpfe/20803]
Microsoft compatibility: "if constexpr" enabled in more modes

Recent Microsoft system header files are using the C++17 "if constexpr"
feature in non-C++17 modes.  Apparently, the use of this feature in such
cases generates a diagnostic that is automatically downgraded to a warning.
Rather than try to emulate this behavior, the "if constexpr" feature is
now enabled when microsoft_version >= 1911 in C++14 mode (which is the
default for microsoft_version 1911).


4/18/19  [EDGcpfe/20936]
Class template argument deduction with single-element initializer list

Committee paper P0702R1 added an exception to CTAD with initializer lists when
the initializer list contained a single element whose type would match the
class copy constructor.  In this case, the deduced type is that of the element
itself rather than an instance of std::initializer_list.  For example:

  template<typename T> struct X {
    X(std::initializer_list<T>) = delete;
    X(const X&);
  };

  void bar(X<int>& x) {
    X x1{x}; // Previously called deleted ctor, now calls copy ctor
    X x2(x); // Calls copy ctor
  }

This is now implemented.


4/18/19  [EDGcpfe/20989,EDGcpfe/21153]
Microsoft compatibility: __is_assignable_no_precondition_check

The builtin __is_assignable_no_precondition_check has been implemented
in Microsoft emulation mode.  It acts the same as __is_assignable.


4/18/19  [EDGcpfe/21154]
Use const-qualified temporaries when possible

A change has been made to const-qualify lowered temporary variables in more
situations.


4/16/19  [EDGcpfe/20452]
Inline static data members of class templates

The front end had several issues regarding inline static data members of
class templates, either reporting spurious errors or failing to diagnose
legitimate ones.  These are now fixed.  For example, with --c++17:

  template<typename T> struct S {
    static inline int i = 1;
    static inline int j = 1;
  };
  template<typename T> int S<T>::i;  // Error, previously undiagnosed
  template<> int S<int>::j = 2;      // Previously a spurious error


4/16/19  [EDGcpfe/21150]
Substitution of parenthesized decltype

In some cases, substituting a parenthesized decltype resulted in the front end
incorrectly ignoring the parentheses.  That could lead to spurious errors or
incorrect results.  For example:

  template<typename> void f();
  template<typename T> using X = decltype((f<T>));
  template<typename T> struct S {};
  template<typename T> S<X<T>> g();
  auto r = g<int>();  // Previously triggered an error.

Previously, the instantiation of g<int> failed because the type obtained by
substitution ignored the extra parentheses and therefore differed from the
type obtained by instantiation.  This is now fixed.


4/16/19  [EDGcpfe/20951]
Array structured bindings in range-based-for loops

The front end previously issued a spurious error on array structured binding
declarations in range-based-for iterator declarations.  For example:

  int arr[3][3] = { {0,1,2}, {3,4,5}, {6,7,8} };
  int g() {
    int s = 0;
    for (auto [ x, y, z ] : arr) {  // Previously an error.  Now okay.
      s += x+y+z;
    }
    return s;
  }

That is now fixed.


4/15/19  [EDGcpfe/20538,EDGcpfe/21108]
Guaranteed copy elision

The front end was not always performing copy elision when required by C++17.
For example:

  struct A {
    A();
    A(A &key);
  };
  auto foo = A{}; // Previously issued a "no suitable copy constructor" error

This is now fixed.


4/15/19  [EDGcpfe/19567,EDGcpfe/21044]
Pointer to function parameters and noexcept specifiers

Consider, in C++17 mode:

  void f() noexcept(true) {}
  void g(void(*func)(void) noexcept);  // (1)
  void g(void(*func)(void));
  int main() {
    g(f);  // Previously an ambiguity error.  Now okay.
  }

Previously, the front end considered the call in main ambiguous.  Now, it
prefers candidate (1).


4/15/19  [EDGcpfe/20965]
Reference to function parameters and noexcept specifiers

Consider, in C++17 mode:

  void f() noexcept(true) {}
  void g(void(&func)(void));  // (1)
  void g(...) = delete;       // (2)
  int main() {
    g(f);  // Previously an error.  Now okay.
  }

The front end previously did not consider candidate (1) viable for the call
g(f) and as a result it selected the deleted candidate (2) and issued an error.
Now (1) is selected instead and the example is accepted.  (Note that in non-
overloaded contexts -- e.g., in the absence of candidate (2) -- the front end
already accepted such calls.)
 

4/14/19  [EDGcpfe/20992]
constexpr lambdas sometimes instantiated too early

In general, constexpr functions must be instantiated earlier than
non-constexpr functions would be because they may be required to produce
a constant value at the point where they are called.  In some cases
constexpr functions were instantiated earlier than was needed.  This was
a particular issue for lambdas, which can be implicitly constexpr.  In
the example below this resulted in a spurious failure to deduce the return
type of A<F>::operator().  Now fixed.

  template<typename F> struct A {
    F f;
    decltype(auto) operator()() { return f(*this); }
  };
  template<typename F> A<F> g(F f) { return { f }; }
  int main() {
    auto l = [](auto& self) -> int { self(); return 0; };
    auto m = g(l);
    return m();
  }


4/14/19  [EDGcpfe/20543]
Incorrect substitution when performing class template argument deduction

In certain cases where a constructor parameter list involved a dependent
nested type specified elsewhere in the class template (e.g., T::type in
the example below), class template argument deduction using that constructor
could produce incorrect results.  Now fixed.

  template <typename T> struct A {
    using U = typename T::type;
    A(T, U);
  };
  struct B {
    B(int);
    typedef B type;
  };
  A(double,double) -> A<B>;
  A a = {1, 2};


4/12/19  [EDGcpfe/21128]
_Alignof/alignof operator 

The front end now issues a discretionary error when applying the C++11 alignof
operator or the C11 _Alignof operator to a function type (except in GNU modes).
In C11 mode, a diagnostic is now also issued on _Alignof applied to an array
type with an unspecified bound (an error in strict C11 mode, a warning
otherwise).  For example:

  long a1 = _Alignof(int(void));  // Now an error in C11 mode.
  long a2 = _Alignof(int[]);      // Now a warning in nonstrict C11 mode,
                                  // and an error in strict C11 mode.

Note that the behavior using nonstandard syntax (e.g., "__ALIGNOF__") is not
affected by this change.
  

4/12/19  [EDGcpfe/20153,EDGcpfe/20797,EDGcpfe/20885,EDGcpfe/21002]
Generated copy functions incorrectly marked as deleted

Consider:

  template<typename T> struct I { using Type = T; };
  struct X {
    X& operator=(volatile const X&) = delete;
    template<typename T = X>
      X& operator=(typename I<const T&>::Type);
  };
  struct S { X x; };
  int main() {
    S s;
    s = s;   // Previously an error.  Now fixed.
  }

This previously triggered an error because the front end erroneously discarded
the assignment operator template when synthesizing the copy assignment operator
for S.  This regression (introduced by the changes for EDGcpfe/15716; see the
entry of 11/23/14) is now fixed.


4/12/19  [EDGcpfe/20993]
Class template argument deduction not performed in typename-specifier

Class template argument deduction should have been performed for a type
specified in a typename-specifier, but was not.  Now fixed.

  template <class T> struct A {
    A(T);
  };
  typename ::A y(1);


4/11/19  [EDGcpfe/18533,EDGcpfe/21125]
Using-declarations and access checking during template substitution

Consider:

  struct X {
    template<typename T> struct N: T {
      using T::f;
    };
  };
  class C {
    friend struct X;
    static int f();
  };
  template<typename T> auto g(T) -> decltype(X::N<T>::f());
  int main() {
    g(C{});
  }

This previously failed to compile because no matching function "g" was found
for the call in main().  That was caused by the name "X::N::f" being access-
checked as if it had been C::f (i.e., short-circuiting the using-declaration).
That is now fixed.  A related change has also been made to improve Microsoft
compatibility in this area:

  class B {
    template<typename T> static int f(T);
  };
  struct C: B {};
  template<typename T> struct D: T {
    using T::f;
  };
  D<C> x;  // Now accepted in Microsoft bugs mode.

Ordinarily, this should be an error because the using-declaration instantiated
for T = C cannot access the private member B::f.  In Microsoft compatibility
mode, however, this is now accepted.  (A similar compatibility behavior was
previously already supported for the cast where f is a non-template function.)


4/10/19  [EDGcpfe/21122]
Microsoft compatibility: Disallow asm statements in lambda expressions

Newer versions of MSVC reject asm statements in lambda expressions.  The front
end has been updated to match this behavior.  For example:

  void f()
  {
    auto lambda = [&]
    {
      __asm { mov eax, 0 } // Previously accepted, now rejected.
    };
  }


4/9/19   [EDGcpfe/21063]
Incorrect resolution of tuple case in structured bindings

If a std::tuple_size has been provided that is not well-formed when
instantiating it with std::tuple_size<E>, the front end would previously
accept that instance anyways.  This would lead to erroneously using the tuple
case for structured bindings at best, and an abort at worst.  For example:

  struct A { int i; };
  namespace std {
    template<typename T, typename U>
    struct tuple_size { static constexpr int value = 1; };
  }
  void f() {
    A a{42};
    auto [ai] = a; // Would previously attempt to instantiate
                   // std::tuple_size<A> and use the tuple case to resolve the
                   // declaration.
  }

Now fixed.


4/9/19   [EDGcpfe/20914]
Array size deduction in "new" expressions

The front end has been enhanced to support array size deduction in "new"
expressions as described in Committee document P1009R2.  This allows
symmetric behavior between direct-initialization of an array variable and the
equivalent "new" expression.  For example:

  void f() {
    int arr[]{1,2,3};  // Creates an integer array of three elements
    new int[]{1,2,3};  // Now also creates a 3-element integer array
  }


4/6/19   [EDGcpfe/21113]
Missing "pack ... not expanded" diagnostics

In some cases a "pack was referenced but not expanded" diagnostic was not
issued.  This could cause invalid code to be accepted and other incorrect
behavior.  The example below resulted in an internal error (in lower_expr)
in versions that perform IL lowering.  Now fixed.

  template <class ...T> inline void f() {
    struct A : T... {
      A(T... args) : T(args...)... {}
      T x = T();
    };
  };
  int main() {
    f<>();
  }


4/5/19   [EDGcpfe/21055]
Abort on instantiation of variadic template

Under some unusual error conditions involving the instantiation of a
variadic template, an abort could occur (in update_template_param_symbols).
Now fixed.


4/5/19   [EDGcpfe/19843,EDGcpfe/21109]
Incorrect substitution of explicit template arguments during deduction

Consider:

  template<typename> void f();
  template<typename T>
    void g(T p) noexcept(noexcept(void(f<0>(p))));
  namespace N {
    template<typename> struct S {};
    template<int I, typename T> void f(S<T>&);
  }
  int main() {
    g(N::S<int>{});  // Previously failed.  Now okay.
  }

Previously this code was not accepted by the front end, because when it
substituted the call "f<0>(p)" to verify the deduction of g<N::S<int>>, it
matched the explicit template argument list "<0>" against ::f (which expects
a type argument instead of the given nontype argument) instead of N::f as
required by the standard.  That is now fixed.


4/5/19   [EDGcpfe/21073]
GNU C++ compatibility: incorrect behavior with --ms_extensions

Microsoft-mode nonreal base classes were incorrectly enabled in other
modes when --ms_extensions was used.  This could cause incorrect behavior.
An internal error would occur in find_inclass_sdm_initializer_for_instance
when compiling the example below.  Now fixed.

  namespace N {
    template <class T, T v> struct A {
      static constexpr T value = v;
    };
    typedef A<bool, false> FT;
    template <class> struct B;
    template <class> struct C : FT { };
    template <class T, class U> struct C<T U::*> : A<bool, !B<T>::value> { };
  };


4/4/19   [EDGcpfe/20978]
Out-of-class declarations of inline static data members

The front end previously failed to diagnose out-of-class declarations of
non-constexpr inline static data members.  Such redundant declarations are
permitted for constexpr inline static data members, which are implicitly
inline, but not for those that are inline but not constexpr.  This is now
fixed.  For example, with --c++17:

  struct S {
    static inline const int i = 0;
  };
  const int S::i;   // Previously erroneously accepted, now an error


4/4/19   [EDGcpfe/20923]
Abort in get_expr_rescan_info with class template argument deduction

Consider:

  template<int> struct I {};
  template<typename T> struct S {
    S(T t, I<sizeof(t)>);
  };
  void g() {
    S s(0, I<sizeof(int)>());  // Previously aborted.  Now okay.
  }

The declaration of variable s relies on class template argument deduction.
However, the front end previously failed to record all the metadata needed to
complete this deduction.  That in turn triggered an internal error in
get_expr_rescan_info (exprutil.c, "missing default rescan info").  That is now
fixed.


4/4/19   [EDGcpfe/21070]
__has_unique_object_representations with empty unions

The front end incorrectly specified the result of the
__has_unique_object_representations type traits helper as true when applied
to an empty union.  This is now fixed and gives the correct value.  For
example, with --c++17:

  union U {};
  static_assert(!__has_unique_object_representations(U)); // Previously failed


4/4/19   [EDGcpfe/20889]
Capturing of variable-length arrays

In GNU and Clang C++11 modes, the front end now allows by-reference capture
of certain variable-length arrays.  The element type of the array cannot
itself be variably modified, however: That matches GCC's constraints, but not
Clang's.  For example, in GNU C++11 mode:

  void f(int n) {
    float a1[n];
    a1[0] = 1.0;
    auto x = [&]{ return a1[0]; }();     // Now accepted.
    float a2[n][n];
    a2[0][0] = 1.0;
    auto y = [&]{ return a2[0][0]; }();  // Still invalid.
  }


4/3/19   [EDGcpfe/19820,EDGcpfe/20159,EDGcpfe/20991]
Incorrect syntax disambiguation for class template argument deduction

Consider:

  template<typename T> struct X { X(T) {}; };
  auto x = (X(0));  // Previously an error.  Now accepted in C++17 mode.

Here "X(0)" is a use of class template argument deduction in a functional-
notation cast.  However, the expression-vs-declaration disambiguator previously
failed to recognize that, triggering a number of errors (the sequence "(X" was
treated as the start of a C-style cast).  That is now fixed.


4/3/19   [EDGcpfe/20981]
Incorrect resolution of default operator delete

The front end was incorrectly ignoring delete operator candidates when
determining the corresponding "operator delete" for an "operator new".  For
example:

  using size_t = decltype(sizeof(0));

  namespace std { enum class align_val_t : size_t {}; }

  struct A
  {
    void *operator new(size_t);
    void operator delete(void*, std::align_val_t) = delete;
  };

  auto *a1 = new A; // Would previously succeed (no matching delete).
                    // Now correctly errors out that the matching delete is
                    // deleted.

This is now fixed.


4/3/19   [EDGcpfe/20649,EDGcpfe/20949]
C++20: Changes to feature-test macros

The changes to feature-test macros described in Committee document P1353R0
have now been implemented in the front end.  In particular, the macro
__cpp_explicit_bool has been renamed to __cpp_conditional_explicit (the
previous name is still supported, for backward compatibility), and the
macro __cpp_impl_three_way_comparison is defined, with value 201711L, when
the corresponding feature is enabled.


4/3/19   [EDGcpfe/20998]
Duplicate cross-reference entries for implicit destructor invocation

Consider:

  struct S {
    ~S();
    void f() { S v(*this); }
  };

Previously, outputting cross-reference information produced duplicate entries
for the destructor invocation that cleans up variable v.  That is now fixed.


4/2/19   [EDGcpfe/20963]
Resolution of "get" member in std::tuple-like structured binding declarations

In cases where the "get" member function of a class had ref-qualifiers
provided, the wrong "get" may have been chosen when used in a structured
binding declaration.  For example:

  struct wrap {
    template<int> void get() &;
    template<int> int  get() &&;
  };

  namespace std {
    template<typename T> struct tuple_size;
    template<int, typename> struct tuple_element;

    template<> struct std::tuple_size<wrap> {
      static const int value = 1;
    };
    template<> struct std::tuple_element<0, wrap> {
      typedef int type;
    };
  }

  auto [a] = wrap();  // Previously chose "void get<0>() &"

This is now fixed.


4/2/19   [EDGcpfe/20945]
Application of cv-qualifiers to reference types in structured bindings

The front end was previously applying the cv-qualifiers added to reference
types in a structured binding declaration, when it should not have been.  This
is now fixed.  For example:

  struct A {
    int i = 0;
    int &r = i;
  };

  void f() {
    const auto [i,r] = A(); // Previously r would have type "const int&".
                            // Now it correctly has type "int&"
  }


4/2/19   [EDGcpfe/20172,EDGcpfe/20979]
Class template argument deduction and cv-qualifiers

Consider:

  template<typename T> struct S { S(T); };
  S const si = 42;  // Previously an error.  Now okay.

Previously this elicited an error because the front end did not accept
cv-qualifiers on top of a placeholder type for class template argument
deduction (see the entry of 8/8/18 for EDGcpfe/17697,EDGcpfe/18314).
That is now fixed.


4/1/19   [EDGcpfe/20791,EDGcpfe/21084]
Error in inheriting constructor templates in C++17 mode

The change made for [EDGcpfe/17926,EDGcpfe/20176,EDGcpfe/20373,EDGcpfe/20470]
covered only non-template constructors.  The fix has been extended to include
inherited constructor templates as well.

  struct B {
    template<typename T>
    B(T) noexcept(false);
  };
  struct D: B {
    using B::B;
    template<typename T>
    D(T) noexcept(false); // Spurious "invalid redeclaration" error here
  };
  D d{1};


4/1/19   [EDGcpfe/20982]
Spurious error on initializer statement in selection statement

Beginning in C++17 (see the Changes entry for EDGcpfe/17414), selection
statements can have initializer statements, but a parenthesized declarator in
an init-statement had resulted in a spurious error.  Now fixed (with --c++17):

  void f() {
    if (int (n) = 0; n) {}
  }


4/1/19   [EDGcpfe/21074]
Abort with malformed raw string in macro definition

The front end could abort with an internal error ("assoc_source_line_modif:
bad address") if a macro definition ends with a malformed raw string
literal.  This is now fixed.  For example, with --c++17:

  #define MM(...) __VA_ARGS__
  #define M( X , Y , ... ) X ## Y MM ( R" )
  int main() {
    M(f,1);
  }


4/1/19   [EDGcpfe/20925,EDGcpfe/21014]
Abort in is_false_constant on Clang-mode enable_if attribute

Previously, certain (currently unsupported) uses of the Clang enable_if
attribute caused the front end to abort with an internal error in
is_false_constant.  For example:

  struct S {
    template <int N> S(const char (&rs)[N])
        __attribute((enable_if(__builtin_strlen(rs) == N-1, "Error!")));
  };
  S s("xyz");

That is now fixed: Such cases now elicit ordinary errors because the front
end does not currently fully support the enable_if attribute (see the entry
for EDGcpfe/17738).


3/31/19  [EDGcpfe/20521]
Spurious error on instantiation of variable template in constexpr if

A spurious "must have a constant value" error could be issued if a variable
template instance was first instantiated in the condition in a discarded
branch of a constexpr if.  Now fixed.

  template <class T> constexpr bool v = true;
  int main() {
    if constexpr (true) {}
    else if constexpr (v<int>) {}
  }


3/28/19  [EDGcpfe/21069]
Narrowing conversion not correctly diagnosed

The front end previously did not treat a conversion from a signed integer type
to a larger unsigned integer type as a narrowing conversion (in C++11 and later
modes).  For example:

  unsigned long long x[] = { -1 };  // Previously a warning in strict C++11
                                    // mode.  Now an error.

That is now fixed.


3/28/19  [EDGcpfe/20986]
Missing diagnostic (and potential abort) on structured binding templates

The front end previously failed to diagnose attempts at defining a structured
binding template.  In some configurations, doing so could lead to an internal
error in name mangling.  For example:

  float p[3];
  template<typename T> auto [x, y, z] = p;  // Now an error.

That is now fixed.


3/27/19  [EDGcpfe/21046]
C++-generating back end: function arguments to deduced non-type template
parameters

When the address of a function is used as a non-type template argument, the
C++-generating back end previously did not emit an "&" operator, relying on
the implicit conversion from a function lvalue to a pointer to function.
With the advent of deduced non-type template parameters in C++17, however,
this assumption of implicit function pointer conversion is no longer valid,
and the C++-generating back end has been changed to put out an explicit "&"
operator to ensure that the type of the argument in the generated code is a
pointer type.  For example:

  void g() {}
  template <decltype(auto)> void f() {}
  int main() {
    f<&g>();  // Previously generated as f<g>()
  }


3/26/19  [EDGcpfe/20893]
C++-generating back end, Microsoft compatibility: conditional expressions in
template arguments

MSVC has a bug that sometimes results in spurious errors when a non-type
template argument consists of an unparenthesized conditional ("?:")
expression.  The C++-generating back end previously failed to enclose such
template arguments in parentheses, resulting in code that could not be
compiled by MSVC.  This is now fixed; the C++-generating back end now
adds parentheses in such cases when msvc_is_generated_code_target is TRUE.
For example, with --microsoft --parse:

  template <long> struct S { };
  template<typename> S<true ? 1 : 2> foo();  // Now generated with parentheses


3/26/19  [EDGcpfe/19536,EDGcpfe/20971]
Conditional operator and pointers to noexcept function types

Consider:

  void (*pfn)() noexcept;
  void (*pfx)();
  auto r = true ? pfx : pfn;  // Previously an error.  Now accepted.

Previously, this elicited a spurious error about the operands of the
conditional operator being incompatible.  Now it is accepted (the result type
is the type of pfx).  Related issues with pointer-to-member functions have
also been fixed.  A part of these fixes implement the resolution for the
standardization committee's Core issue 2381.


3/25/19  [EDGcpfe/20810, EDGcpfe/20892, EDGcpfe/20972]
Braced initializer lists in "new" expressions

The front end would issue an error for braced initializers in "new"
expressions when type deduction was required.  This is now fixed.
For example:

  void f() {
    new auto {1};            // Previously rejected, now accepted
    new decltype(auto)({2}); // Still rejected, as {2} is not an expression
                             // Accepted in GCC/Clang compatibility modes
  }

In addition, the behavior of type deduction for single-element braced
initializer lists in C++11 mode has been changed to match C++14 (and newer)
modes.


3/21/19  [EDGcpfe/21025]
Clang compatibility: Support for 8.0.0 builtins

Support for clang 8.0.0 builtins (40 new builtins) has been added.


3/20/19  [EDGcpfe/20976]
Self-referential aggregate initializers and constexpr evaluation

The front end previously did not correctly evaluate aggregate initializers
that refer to their own elements.  For example:

  constexpr int g(int &r) { r *= 2; return r; }
  struct S { int &&rr; int i; };
  constexpr S s = { 42, g(s.rr) };  // Previously an error.  Now okay.

Previously, this elicited an error because the evaluation of s.rr was not
considered constant while s is being initialized.  That is now fixed.


3/19/19  [EDGcpfe/20926]
Recursive calls to generic lambdas

The front end previously did not accept the following case because it treated
a lambda's call operator as "invisible" within the lambda body:

  int main() {
    auto lm = [](int i, auto f) {
      if (i<=0) return;
      f(i-1, f);  // Previously an error.  Now okay.
    };
    lm(42, lm);
  }

That is now fixed.


3/19/19  [EDGcpfe/20927]
Microsoft-mode abort on enum bit-field initialization

The front end previously could abort attempting access through a null pointer
in some cases involving the initialization of a bit field of enumeration type
in an overload-resolution context.  For example:

  struct S {
    enum E { x, y };
    E e: 1;
  };
  int main() {
    S s{};
    s = { S::x };  // Previously caused an abort.  Now okay.
  }

That problem is now fixed.


3/19/19  [EDGcpfe/17673,EDGcpfe/18799,EDGcpfe/20597,EDGcpfe/20881]
References to class type rvalues

Consider:

  struct B { int i = 1; };
  struct D: B { int i = 2; };
  constexpr int f() {
    D d;
    B &&rr = static_cast<D>(d);  // (1)
    return rr.i;
  }
  static_assert(f() == 1);  // Previously an error.

Line (1) involves binding a reference to an rvalue of class type.  In this
case, that rvalue was represented by an enk_temp_init node on top of which an
eok_base_class_cast was applied.  However, the enk_temp_init was a prvalue and
thus the eok_base_class_cast looked like a slicing operation when it really
should be seen as a reference cast.  This could result in various problems in
later processing.  In this particular case, the lifetime of the temporary was
not correctly extended and as a result the call to f() failed to fold to a
constant.  Other similar cases could trigger internal errors.  Although this
example involves a derived-to-base conversion, the problem could also occur
with implicit type qualifier adjustments (e.g., the addition of "const" on top
of a temporary).  This class of problems is now fixed.


3/18/19  [EDGcpfe/19059]
C++-generating back end: incorrect pack ellipsis emitted

The C++-generating back end could emit a ellipsis where one was not valid
when a variadic alias was instantiated in a non-variadic context.  Now fixed.


  template <typename T, T t> struct A { };
  struct B { static const bool value = false; };
  template <typename... Ts> struct C { using type = B; };
  template <typename... Args> using D = typename C<Args...>::type;
  template <typename T> struct E {
    using type = A<bool, D<T>::value>;
    // Formerly emitted as: using type = A< bool, C< T...> ::type::value>
  };

3/18/19  [EDGcpfe/20553]
C++-generating back end: internal error in hidden name processing

Under some rare conditions, in configurations that do hidden name processing,
an internal error could occur (in push_template_instantiation_scope).  Now
fixed.


3/18/19  [EDGcpfe/20098]
Use of injected class name as a template template argument

An injected class name of a class template can be used as both a type template
argument and a template template argument.  This worked in some cases, but
not as an explicit template argument in a function template call.  Now
fixed.

  template <typename T> struct A {
    template <template<typename> class> void f(){}
    void g() { f<A>(); }
  };
  int main() {
    A<int> a;
    a.g();
  }


3/18/19  [EDGcpfe/21009]
Substituting decltype constructs

A change has been made to considerably reduce the cost of substituting
template-dependent decltype constructs (this is substitution as performed
during deduction, as opposed to actual template instantiation): The
substitution now produces the underlying type instead of a typeref entry
pointing to the underlying type, and the nodes of rescanned expressions
associated with the substituted constructs are reclaimed.  For some complex
template-based libraries, the resulting reduction in overall memory use by
the front end can be substantial (the case that prompted these changes
reduced the memory use to about a third of the use before the changes; the
combination of these changes and those described for EDGcpfe/20975 resulted
in an order of magnitude reduction in memory use).


3/18/19  [EDGcpfe/21005]
Singleton instantiation of fold-expressions

Consider:

  template<typename ...Ts> auto f(Ts ...ps) -> decltype((...*ps)) {
    return 42;
  }
  int main() {
    int x = 0;
    f3<int>(x);  // Previously an error.  Now okay.
  }

The expansion of "(...*ps)" for a single element is actually "ps0" (where ps0
denotes the single parameter of f) without any parentheses.  That means that
it is technically an "id-expression", and thus decltype should produce the
type of the parameter.  Previously, however, the "id-expression" nature of the
expansion was lost and a reference type was produced (because the expression
is also an lvalue).  That is now fixed.


3/14/19  [EDGcpfe/20899]
Spurious SFINAE failure on lookup in class instance being defined

Consider:

  template<typename T> T val();
  template<class T> struct Test_mf : T {
      template<class U = Test_mf>
      static auto test(int)
          -> decltype(val<int&>() = val<U const&>().mf(),
                      char{});
      static auto test(...) -> char(&)[2];
      static constexpr bool value = sizeof(test(0)) == 1;
  };
  struct S { int mf() const; };
  static_assert(Test_mf<S>::value, "Unexpected");

During the instantiation of Test_mf<S>, the expression "val<U const&>().mf()"
is substituted with U = Test_mf<S> itself, which means that "mf" must be
looked up in that type.  Previously, this produced a substitution (SFINAE)
failure, which resulted in the code above producing the wrong outcome.  That
is now fixed.


3/14/19  [EDGcpfe/20530,EDGcpfe/20644]
C++20: char8_t type and keyword

The front end has been enhanced to support the char8_t type and keyword as
described in Committee document P0482R6.  The char8_t keyword and the new
type for character and string literals with a u8 prefix are enabled by
the --c++20 command line option and controlled by the new --[no_]char8_t
command-line option.  For example, with --c++20:

  const char8_t str[] = u8"abc";  // Accepted with --c++20
  const char s2[] = u8"xyz";      // Now an error with --c++20

Note that the IA-64 mangling encoding for the char8_t type is "Du" which had
previously been used (as an EDG extension) to mangle __underlying_type.  As
a result of these changes, when ABI_COMPATIBILITY_VERSION >= 510,
__underlying_type will be mangled as "U3eut" (see EDGcpfe/20541) in all
(IA-64 ABI) cases.


3/14/19  [EDGcpfe/20980]
GNU statement expressions as constants

The front end now attempts to constant-evaluate GNU statement expressions in
GNU modes with gnu_version >= 50100.  For example:

  int main() {
    enum { x = ({42;}) };
    return x;
  }

Note that GCC itself only performs the constant-evaluation in limited contexts
(e.g., it does accept the case above, but it performs the evaluation for
_Static_assert constructs).  Our more general folding of statement expressions
is not expected to hamper compatibility.


3/14/19  [EDGcpfe/20969]
Abort when promoting structured bindings for bit fields

When 'bit_field_promotion_applies_to_some_operations' is set to FALSE and a
structured binding to a bit field was involved in integral promotion, the
front end would abort with an internal assertion failure in
'type_after_bit_field_integral_promotion'.  Now fixed.

  struct S { unsigned long long x : 4, y : 32; int z; };

  void f(S s) {
     auto [a, b, c] = s;
     decltype(+a) foo;  // Would previously abort
  }


3/14/19  [EDGcpfe/20994]
Missing narrowing diagnostic on float->enum conversion

In C++-mode the front end was not issuing a narrowing diagnostic message when
initializing an enum with a fixed underlying type from a brace-enclosed
expression containing a floating-point value.  This is now fixed.

  enum A : char { } ;
  A a5{ 1.5 };  // Previously silent, now diagnosed


3/13/19  [EDGcpfe/20910]
IA-64 mangling of certain qualified types

The changes for EDGcpfe/17801 (in release 4.13) had the unintended consequence
of changing certain mangled names.  In particular, mangled names involving
substitutable types that are cv-qualified versions of types that have standard
abbreviations may be affected.  For example:

  namespace std {
    template<typename> class allocator;
    template<typename> struct char_traits;
    template<typename> struct allocator {};
    template<typename T, typename = char_traits<T>, typename = allocator<T> >
    struct basic_string {};
    typedef basic_string<char> string;
  }
  using namespace std;
  template <typename T, typename _Alloc = allocator<T> > class map {};
  void bar(const string*, map<const basic_string<char> >*);
  void f() {
    bar(0,0);
  }

Note that this change is not protected by ABI_COMPATIBILITY_VERSION as it
restores previous behavior.


3/13/19  [EDGcpfe/20983]
Structured bindings in secondary declarators

The standard grammar for structured bindings doesn't permit a structured
binding declaration to be combined with other declarators.  However, the
front end previously did not consistently diagnose such cases.  E.g.:

  struct S { int i; } s = { 42 };
  auto x = s, [i] = s;  // Previously accepted.  Now an error.

That is now fixed.


3/13/19  [EDGcpfe/20990]
Performance improvement when using brief diagnostics

When brief diagnostics are being produced (e.g., with --brief_diagnostics),
the source line was sometimes read when it was not needed, which can be
an expensive operation.  This is no longer done in any cases when brief
diagnostics are being generated.


3/13/19  [EDGcpfe/20876]
Issue with constexpr functions used in secondary translation units

In configurations where COMPILE_MULTIPLE_TRANSLATION_UNITS is TRUE and
when actually compiling multiple translation units, spurious errors
could result when constexpr function templates were used.  Now fixed.


3/12/19  [EDGcpfe/20977]
const_cast conversions sometimes led to spurious constexpr failures

Consider (in C++11 or later mode):

  constexpr int i = 0;
  constexpr int *p = const_cast<int*>(&i);
  constexpr int g(int*) { return 42; }
  static_assert(g(p) == 42, "Unexpected");  // Previously sometimes an error.
                                            // Now okay.

Previously, some configurations caused the constexpr interpreter to be unable
to load the folded value of p for the call "g(p)" because that value was
produced through a const_cast.  This resulted in a spurious error about "g(p)"
not being a constant because of an invalid conversion.  That problem is now
fixed.


3/12/19  [EDGcpfe/20572]
Spurious correspondence errors when overloading "C" and "C++" functions

In configurations where COMPILE_MULTIPLE_TRANSLATION_UNITS is TRUE the front
end issued a spurious error in some Clang-mode cases with translation units
containing overloaded functions with "C" and "C++" name linkage that differ
only in the presence of enable_if attributes.  That is now fixed.


3/12/19  [EDGcpfe/20558]
Spurious correspondence error on "generic" builtins

Consider, in Clang mode, the following two translation units:

  // TU1:
  int f(_Atomic(char) *pac, char c) { return __c11_atomic_load(pac, c); }

  // TU1:
  int f(_Atomic(char) *pai, int i) { return __c11_atomic_load(pai, i); }

When the two translation units were compiled simultaneously, this previously
triggered a spurious error about the declarations of __c11_atomic_load being
incompatible across translation units.  That is now fixed.  (See also the
entry for EDGcpfe/16735 of 12/19/17.)


3/11/19  [EDGcpfe/20898]
Overload resolution of value-dependent template function calls

During template parsing, the overload resolution of non-type-dependent
function calls is recorded, and that resolution used during instantiation.
In cases where the function call is value-dependent, this resolution could
be incorrect and lead to spurious failures in overload resolution.  Now fixed.
For example (with --instantiate=used):

  struct A { };
  template<int idx>
  void foo (A *x, A *y) {
    *x = y[idx*1]; // Previously a 'no matching operator "="' error here
  }
  auto ptr = &foo<0>;


3/8/19   [EDGcpfe/20946]
__has_*_assign type traits helpers in Microsoft mode

Earlier versions of MSVC always returned false for non-class types with
these helpers.  This was changed in Visual Studio 2013, with more changes
in Visual Studio 2015; however, the front end continued to reflect the old
behavior in all Microsoft modes.  The front end's behavior now matches
Visual Studio's behavior with the respective versions. For example:

  // Previously always false, now true with --microsoft_version=1800
  bool a = __has_trivial_nothrow_assign(int);

  // Previously always false, now true with --microsoft_version=1900
  bool b = __has_trivial_assign(int);


3/1/19   [EDGcpfe/17886,EDGcpfe/19556,EDGcpfe/19680,EDGcpfe/20896]
GNU statement expressions in unevaluated contexts

In GNU modes, the front end now accepts GNU statement expressions in non-
local scopes when they appear in unevaluated contexts.  For example:

  unsigned long s = sizeof( ({ 42; }) );  // Now okay in GNU modes.


3/7/19   [EDGcpfe/20891]
C++-generating back end: constexpr member functions of generated instances

In versions before 7.2.0, g++ enforced a rule that permitted constexpr
member functions only in classes that are literal types.  However, it
accepted constexpr member functions of class templates whose instances are
not literal types.  In C++-generating back end configurations with
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE,
implicit instantiations of class templates are represented by explicit
specializations, and the code generated for these explicit specializations
preserved the constexpr specifier for member functions of the class
template, resulting in an error when compiling the generated code if the
explicit specialization is not a literal type.  The C++-generating back end
has now been updated to suppress the constexpr specifier for a member
function of such an explicit specialization when
gcc_is_generated_code_target is TRUE and gnu_target_version_number is less
than 70200.  For example, with --gnu_version=60300 --c++11:

  template<typename T> struct S {
    constexpr int f() { return 17; }
    S();
  };
  S<int> si;

The generated code previously contained an explicit specialization of
S<int> in which f() was declared constexpr, and the constexpr specifier is
now suppressed in the explicit specialization.


3/7/19   [EDGcpfe/20973]
Missing diagnostic on empty init-statement in while loop condition

Consider:

  int main() {
    while (; false) {}  // Previously accepted in C++17 mode.  Now an error.
  }

Previously this example was accepted in C++17 mode (which accepts init-
statements in "if" and "switch" statement conditions).  Now an error is issued
as required by the language definition.


3/7/19   [EDGcpfe/20975]
Reduction in memory consumption by expression rescanning information

When the front end processes expressions in deduction contexts (e.g., in
function template parameter or return types) it associates with many of the
expression nodes "rescanning information" that can later be used to substitute
template arguments in the expression nodes.  Various changes were made to
avoid recording this information when we can determine that an expression node
will not need further substitution.  For some complex template-based libraries,
the resulting reduction in overall memory use by the front end can be
substantial (the case that prompted these changes reduced the memory use
to about a third of the use before the changes).


3/6/19   [EDGcpfe/20968]
Performance improvement with large numbers of using-declarations (IL CHANGE)

Formerly, using-declarations and using-directives were placed on the same
scope list.  This could result in performance issues in routines that need to
process using-directives frequently (e.g., qualified_using_directive_lookup).
Using directives are now placed on a separate scope list.  This is a minor
IL CHANGE. 


3/5/19   [EDGcpfe/20959]
Performance improvement for overload resolution of function templates

The creation of "rescan contexts" in overload resolution for function
templates can be an expensive process.  A change was made to avoid
creating such contexts if substitution had already been done for a given
function template and a given set of template arguments.  This can result
in a significant improvement in performance in certain cases.


3/4/19   [EDGcpfe/19122]
Initialization and cv-qualifiers

Consider the following example:

  struct A {
    A();
    A(const A&);
  };
  struct B {
    operator volatile A();
  };
  int main() {
    B b;
    A a(b);  // Now an error.
  }

The front end previously accepted this in most modes, but the initialization
"A a(b);" is invalid because the copy constructor of A cannot accept the
volatile-qualified result of "B::operator volatile A()".  That is now fixed.


2/27/19  [EDGcpfe/20850]
Friend function that was called before being defined was not generated

If a friend function that is defined in a class template was called prior
to being defined by an instantiation of the class template, a definition
of the function was sometimes not evaluated, which could result in a
linker error.  Now fixed.

  void f();
  inline void g() {
    f();
  }
  template <typename T> struct C {
    friend void f() { }
  };
  int main() {
    C<int> ci;
    g();
  }


2/27/19  [EDGcpfe/20904]
Spurious access error on noexcept specifier in C++17 mode

A spurious access error could be issued in C++17 mode when performing
substitution on a noexcept specifier of a function template if the noexcept
specifier referenced a private member of a class template.  Now fixed.

  template <class> struct A;
  template <class T> struct B {
    template <class U> static A<decltype(U()())>* bv;
    typedef decltype(bv<T>) t;
  };
  template <class> class C {
    int n;
  public:
    template <class...> auto operator()() noexcept(noexcept(n)) -> decltype(n);
  };
  int main() {
    C<int> c;
    B<C<int>> bc;
 }


2/26/19  [EDGcpfe/19838,EDGcpfe/20478,EDGcpfe/20906]
__builtin_expect(expr, c) and constexpr evaluation

The front end now treats calls to __builtin_expect(expr, c) as evaluations of
the first argument (expr; the second argument, c, is ignored) during constexpr
evaluation.  For example (in GNU C++14 mode):

  constexpr int f(int p) {
    if (__builtin_expect(p, 0)) {
      return 42;
    } else {
      return p;
    }
  }
  constexpr int r = f(1);  // Previously an error.  Now okay.


2/26/19  [EDGcpfe/20888]
GNU compatibility: attributes on an alias declaration

In GNU compatibility mode, using GNU-style attributes on an alias declaration
had resulted in a spurious error.  Now fixed.  For example (with --gnu_version
80000):

  using T __attribute__((deprecated)) = int;
  T val;


2/25/19  [EDGcpfe/17900,EDGcpfe/17956,EDGcpfe/20612]
Erroneous destruction for removed operator new construction

In configurations where
LOWERING_REMOVES_UNNEEDED_CONSTRUCTIONS_AND_DESTRUCTIONS is TRUE, lowering
elides calls to constructors and destructors that have no effect.  In the case
where a new operator is invoking such a constructor, the lowering process had
erroneously left the cleanup call (to operator delete) on the
next_in_destruction list.  That could result in assertion failures (in
record_partial_aggregate_cleanup_destruction), or segfaults (in
clone_raw_region_table_entry) or incorrect cleanup information (in
configurations where lowering doesn't generate exception handling tables).
For example:

  struct A { A() {} };
  struct B { B(A*); ~B(); };
  struct C { C(B); ~C(); };
  void f() {
    C c(B(new A));
  }


2/25/19  [EDGcpfe/20861]
IA-64 ABI: Promotion of local entities from functions

A change has been made to restrict the cases where local entities are
promoted to the file scope in IA-64 ABI configurations where
PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE is TRUE.  Previously, any static
variable with a dik_nonconstant_aggregate or dik_constructor initializer
requiring destruction had triggered promotion of all entities in the function.
That test has been narrowed so local entities in cases like the one below are
no longer promoted.  For example:

  struct A { A() {} };
  int f(void) {
    static A a;       // Had triggered promotion of "a" and "i" to file scope
    static int i = 0;
    return ++i;
  }


2/22/19  [EDGcpfe/20902]
Internal error in active_scope_lookup during hidden name processing

In configurations that do hidden name processing (e.g., C++-generating back
end configurations), an internal error could occur in active_scope_lookup
if a namespace named in a using-directive contains both a using-declaration
for a typedef and a direct declaration of an equivalent typedef.  Now fixed.

  namespace N {
    typedef unsigned long A;
  }
  using N::A;
  typedef long unsigned A;
  namespace {
    struct A;
  }
  int main() {
      using namespace N;
  }


2/14/19  [EDGcpfe/20873]
Microsoft compatibility: accept additional declspec attributes

A number of new Microsoft declspec attributes now appear in the latest
header files.  These new attributes (hybrid_patchable, no_init_all, pure,
and spectre) are now accepted (in any location) and ignored in Microsoft
emulation modes.


2/14/19  [EDGcpfe/19786,EDGcpfe/20110,EDGcpfe/20773]
Attribute namespaces in __has_cpp_attribute

The front end now supports attribute namespaces in the argument to the
__has_cpp_attribute preprocessor operator.  For example, with --g++ --c++17:

  #if !__has_cpp_attribute(gnu::noinline)
  #error Missing noinline support
  #endif


2/13/19  [EDGcpfe/20083]
Inline variable support in configurations with INSTANTIATE_EXTERN_INLINE

The original support for C++17 inline variables inadvertently assumed that
COMDAT support was available and that is often not the case in configurations
where INSTANTIATE_EXTERN_INLINE is TRUE.  A change has been made to use
COMDAT sections in configurations where that feature is available (i.e., IA-64
ABI or configurations where LINKER_CAN_DISCARD_DUPLICATE_DEFINITIONS is TRUE).
In other configurations, the prelinker is used to ensure that a single
definition of an inline variable exists in the program.


2/13/19  [EDGcpfe/20874]
C++-generating back end: pseudo-destructor with enumeration type

Consider the following example:

  enum E { };
  template<typename T> struct S {
    void f(T *p) {
      p->~T();
    }
  };
  void g() {
    S<E> se;
    se.f(new E);
  }

In configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, the
C++-generating back end produced a definition for S<E>::f(E *) as follows:

  inline void S<E>::f(E *p) {
    p->E::~E();
  }

Although that is valid C++, g++ issues a spurious error for a
pseudo-destructor call involving an enumeration type.  To work around this
problem, the C++-generating back end now defines a typedef for an
enumeration type appearing in a pseudo-destructor call and uses that
typedef in the generated code:

  typedef E __T12345678;
  inline void S<E>::f(E *p) {
    p->~__T12345678();
  }

which does not trigger the g++ bug.


2/13/19  [EDGcpfe/20540]
Structured binding in the condition of a selection or iteration 
statement

The standard does not allow a structured binding in the condition of a
selection or iteration statement, but the front end used to accept this.  
For example:

  struct X {
    bool i;
  };
  void f(X x) {
    if (auto [a] = x) {} // Previously okay, now error
  }

This has now been fixed.


2/11/19  [EDGcpfe/20871]
Constexpr constructor specializations with non-constant ctor-initializers

Consider:

  struct S {
    using I = int;
    int f();
  };
  template<typename T> struct X {
    int i;
    constexpr X(typename T::I i): i(i) {};
    constexpr X(T s): X(s.f()) {}  // Okay.
  };
  X<S> xs{S{}};

in a configuration that includes the C++-generating back end and the macro
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE.
Previously, that resulted in the rendering of an explicit specialization for
X<S> and a definition of its constructor like the following:

  template<> struct X<S> { ... };
  ...
  constexpr X<S>::X(S s) : X(s.f()) {}  // Error.

Note how in the original template the "s.f()" may or may not be a constant
expression, but in the explicit specialization it is definitely not a constant
expression since S::f() is not constexpr.  The explicit specialization is
therefore invalid; although the standard does not require a diagnostic in such
cases, some compilers do emit one (e.g., some versions of GCC).  The front end
now detects such cases and drops the "constexpr" property from the instance so
that the rendering is now like the following:

  template<> struct X<S> { ... };
  ...
  X<S>::X(S s) : X(s.f()) {}  // Okay.


2/11/19  [EDGcpfe/19066]
Spurious error on address of static member function template

Consider:

  struct S {
    template<typename T> static void f();
  } s;
  template<typename T> void g() {
    void (*fp)(void) = &s.f<T>;  // Previously an error.  Now okay.
  }

Previously, in modes that parse function templates in their generic form, this
resulted in a spurious error saying that "s.f<T>" can only be used directly in
a call (i.e., for an expression like "s.f<T>()").  However, that error is
invalid because the member is static, and thus "&s.f<T>" is a valid way to
designate the address of S<T>::f.  That issue is now fixed.


2/11/19  [EDGcpfe/19122]
Referring to generated trivial constructors and destructors

Consider:

  struct S {};
  struct F {
    friend S::~S() noexcept;  // Previously an error.  Now okay.
  };

Previously, the front end did not accept that example because the trivial
destructor of S has no explicit representation.  Now, such a representation
is synthesized when needed.  Similar changes were made for trivial default
constructors and trivial copy/move constructors.


2/8/19   [EDGcpfe/20857]
Invocation of a virtual function on a non-const temporary

Previously, the front end would allow an invocation of a virtual function
on a non-const temporary in a context requiring a constant expression, even
if the lifetime of the temporary didn't begin within the evaluation of the 
constant expression.  For example :

  struct A {
    constexpr virtual int f()
    {
     return 1;
    }
  };
  constexpr A&& ref = A{};
  int x[ref.f()];  // previously accepted, now an error
  int y[A{}.f()];  // okay


2/7/19   [EDGcpfe/20862]
C++-generating back end: user-defined string literal cast to const char*

Given an invocation of a user-defined string literal, the C++-generating
back end incorrectly cast the result of the call to "const char*".  This is
now fixed.  For example, with --c++11:

  int operator"" _i(const char*, __EDG_SIZE_TYPE__);
  int i = "abc"_i;  // Previously generated as (const char *)"abc"_i;


2/5/19   [EDGcpfe/20822]
GNU compatibility: aggregate initialization of vectors

In GNU C++ mode, the front end now allows aggregate initialization of 
vectors.  For example:
  typedef int V __attribute__ ((__vector_size__ (16))); 
  V const v = {0, 0};
 

2/5/19   [EDGcpfe/20767]
Cost of reactivations during overload resolution

A number of changes were made to reduce the overall cost of reactivating
scopes when substituting templates during overload resolution.  In some
complex cases the resulting improvement in compile time can be noticeable
(e.g., half the previous time).


2/5/19   [EDGcpfe/17598]
Language linkage for main() (core issue 1886)

With the resolution of core issue 1886, a program that declares a variable
main at global scope or that declares the name main with C language linkage
(in any namespace) is ill-formed.  This has now been implemented.

  int main = 0;  // Now an error in all modes 
  extern "C" {
    int main();  // Now an error in strict mode, warning in other modes
  } 


2/4/19   [EDGcpfe/20841]
GNU C++-mode abort on member function declared with alias type

In GNU C++11 mode, the front end previously aborted on the following case
(with "reconcile_routine_types: shared param types unexpected" in decls.c):

  template<typename T> using F = void(T x);
  struct S { template<typename T> static F<T> f; };
  template<typename T> void S::f(T x) {}

(This example declares a member function using an alias for a function type,
which is highly unusual.)  That is now fixed.


2/4/19   [EDGcpfe/20840]
Instantiating exception specifications

Consider in C++11 or C++14 mode (but not in C++17 mode):

  template<typename T> struct A { static constexpr bool v = true; };
  template<typename T> int f(T&) noexcept(A<T>::v);
  int i = f<int>(i);  // (1)
  template<> struct A<int>;  // (2)

The call to f<int>(int&) on line (1) triggers a point of instantiation at that
location.  However, the language permits implementations to delay that point of
instantiation to the end of the translation unit, which is what the front end
does in this case.  However, other implementations appear to instantiate the
exception specification earlier, which triggers the instantiation of A<int> at
line (1): The explicit specialization of A<int> on line (2) is thus invalid.
(Note that in C++17, the exception specification is part of the function type,
and therefore it must be instantiated on line (1): The explicit specialization
then becomes an error independently of the chosen point of instantiation for
the function definition itself.)  The front end now also triggers the
instantiation of exception specifications at the first point of instantiation.
In configurations with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS this
affects the order in which source sequence entries are emitted for various
specializations.  As a consequence, some cases that caused the C++-generating
back end to produce invalid code now result in valid code.


2/1/19   [EDGcpfe/20799]
Constant-valued static data members without definitions

Consider:

  template <typename T> struct S {
    static constexpr T x[2][2] = { {1, 2}, {3, 4} };
  };
  int main() { return S<int>::x[1][1]; }

Prior to C++17, the static data member declaration is not a definition.  The
handling of the reference to S<int>::x in the front end resulted in a linker
error because the return expression was not constant-folded.  However, the
standard does in fact require constant-folding in cases like this and the
front end now implements that, which in turn permits the example above to
compile and link successfully.


1/31/19  [EDGcpfe/20836]
GNU C++11 compatibility: Using strlen in constexpr functions

Consider:

  using size_t = decltype(sizeof(42));
  extern "C" size_t strlen(const char*);
  constexpr size_t f(char const *s) { return strlen(s); }

Previously, the front end issued an error in C++11 mode (but not C++14 mode)
because "strlen" is not a constexpr function.  However, in GNU C++ mode, that
function is recognized as the standard library function and the front end is
able to fold calls to it when appropriate.  Therefore, no error is issued on
this example anymore (which matches the behavior of GCC).


1/31/19  [EDGcpfe/20704]
GNU compatibility: abi_tag mangling

GCC (and clang) do not include abi_tag strings in the mangled name of a
function when the function and the function's return type both have the same
implicit abi_tags.  For example (with --gnu_version 80000):

  namespace std {
    inline namespace N __attribute__((__abi_tag__("cxx11"))) {
      class B {};
    }
    namespace v1 {
      inline namespace N __attribute__((__abi_tag__("cxx11"))) {
        B foo();    // previously _ZNSt2v11N3fooB5cxx11Ev now _ZNSt2v11N3fooEv
        void f() { foo(); }
      }
    }
  }

This change is only effective when ABI_COMPATIBILITY_VERSION >= 510.


1/31/19  [EDGcpfe/20835]
Copy elision in direct-initialization context

C++17 included changes that amounted to "mandatory copy elision": Copying a
prvalue generally just causes the prvalue to be constructed directly in its
final destination.  Previously, however, that was not always correctly applied
in direct-initialization contexts.  For example:

  struct S { S(); S(S const&) = delete; };
  S obj{S{}};  // Previously an error because the copy constructor
               // invocation was not elided.  Now okay in C++17 mode.

That is now fixed.


1/31/19  [EDGcpfe/20806]
Abort in early GNU C++03 mode on class defined in default template argument

Previously, in GNU C++03 modes with gnu_version < 30400, the front end aborted
with an internal error (triggered in scan_class_definition) on the following
invalid code:

  template<typename = struct {}> void f();

That is now fixed.


1/31/19  [EDGcpfe/20805]
GNU C++ compatibility: Inline static data member with incomplete array type

Consider:

  template<typename> struct S {
    static constexpr int x[] = { 1, 2 };
  };
  S<int> si;  // Previously an error in GNU C++17 mode.  Now okay.

In GNU C++ mode, the initializer of S<int>::x isn't fully instantiated because
the static data member isn't used.  As a result, the length of the array is
left undetermined.  However, since the variable is constexpr (and therefore
implicitly inline), the front end previously required its type to be complete
at the point of declaration, which in turn triggered an error.  That is now
fixed.


1/30/19  [EDGcpfe/20771]
IL corruption in call to GCC function with "inline partner"

Consider in GNU C mode:

  extern inline void f(void) { }
  extern void f(void);
  void g(void) {
     (f)();
  }

The two declarations of f are distinct "inline partners" (see the entry for
EDGcpfe/14500).  In configurations with PARENS_IN_IL set to TRUE, the call to
f (with the extraneous parentheses) resulted in IL corruption, which was
likely to lead to an abort later on (e.g., in the C++-generating back end).
That is now fixed.


1/30/19  [EDGcpfe/20812]
Abort in scope_depth_for_capture on nested generic lambda

In some relatively complex situations, the front end sometimes failed an
assertion check in scope_depth_for_capture (expr.c) while instantiating a
generic lambda appearing within another (not necessarily generic) lambda.
The problematic situation arose because multiple scope stack entries were
active for the body of the enclosing lambda, but only the first entry has
access to the a_lambda IL entry describing the associated lambda expression.
That problem is now fixed.


1/29/19  [EDGcpfe/20809]
C++-generating back end: explicit call to destructor of unnamed class

When the destructor of an unnamed class (that has a typedef-name for
linkage purposes) is explicitly invoked, the C++-generating back end put
out the call using the string "~<unnamed>" as the name of the destructor.
This is now fixed.  For example:

  typedef struct { } T;  
  void f() {
    T t;
    t.~T();  // Previously generated as t.~<unnamed>()
  }


1/28/19  [EDGcpfe/18708]
Internal error in C-generating back end on missing address_taken flag

IL lowering previously failed to set the address_taken flag to TRUE when a
temporary variable generated by IL lowering appeared under a reference cast.
That, in turn, could trigger an internal error in the C-generating back end.
For example, in C++17 mode:

  struct S { void f() noexcept {} };
  using PMF = void (S::*)();
  void g() {
    static_cast<PMF&&>(&S::f);  // Previously triggered an internal error
  }                             // in the C++-generating back end.

This is now fixed.


1/25/19  [EDGcpfe/19750,EDGcpfe/20056,EDGcpfe/20481]
Copying an abstract base subobject using a braced initializer

Consider:

  struct AB { virtual void f() = 0; };
  struct D: AB {
    D(D const &d): AB{d} {}  // Previously a error.  Now okay.
  };

Previously, this elicited a spurious error about creating an abstract base
class.  That is now fixed.


1/24/19  [EDGcpfe/20555]
Declaration statement for an anonymous union variable (IL CHANGE)

Anonymous union variables at function scope are now represented with a 
stmk_decl variable entry in the IL.  This is a minor IL CHANGE. 


1/23/19  [EDGcpfe/20792]
C++-generating back end: unparenthesized comma in array bound

The C++-generating back end could, for some expressions, put out an array
bound expression containing an unparenthesized comma.  This is now fixed.
For example, with --g++:

  int a[(5, 10)];  // Previously generated as "a[5, 10]"


1/22/19  [EDGcpfe/20647,EDGcpfe/20775]
C++20: std::is_constant_evaluated and __builtin_is_constant_evaluated

In C++20 mode, the constexpr interpreter now recognizes the standard library
function:

  namespace std {
    constexpr bool is_constant_evaluated() noexcept {
      return false;
    }
  }

and evaluates it as a constant true value (despite the source definition
unconditionally returning a false value) when evaluating expressions and
initializers in contexts where the language requires a (possibly tentative)
constant evaluation.  Forthcoming versions of GCC and Clang will implement
this standard function by delegating to a special builtin function
__builtin_is_constant_evaluated: The front end also now recognizes that
special function in C++20 modes, in GNU C++ modes with gnu_version >= 90000,
and in Clang C++ modes with clang_version >= 90000.  This implements the
changes introduced in the working paper for the next standard by the
standardization committee's paper P0595R2.


1/22/19  [EDGcpfe/20781]
Temporary not checked for constness

When a constant reference is bound to a temporary, the constness of the 
temporary wasn't checked.  For example:
  
  constexpr int&& a = 37;
  constexpr int b[1] = {a};

The above would compile without errors even though the temporary a is bound 
to isn't constant.  This has now been fixed. 


1/22/19  [EDGcpfe/19831]
Static initialization involving creation of a temporary

If constant initialization of a variable with static storage duration 
required creation of a temporary, the front end would not statically 
initialize such a variable.  This has now been fixed.


1/18/19  [EDGcpfe/20638]
Assertion failure in expand_macro_buffer

The changes for EDGcpfe/18829 (in version 5.0) could result in a failed
assertion in expand_macro_buffer when certain complex macro expansions are
performed.  This is now fixed.


1/16/19  [EDGcpfe/20766]
Spurious error on empty pack expansion used with template template parameter

A spurious error could be issued if an empty pack expansion was passed
as an argument of a template template parameter and the template
template argument being used for an instantiation did not have a corresponding
parameter.  In the example below, a "too many arguments" error was issued
when an empty "Args..." pack expansion was used as the second argument of
TT and A did not have a second template parameter.  Now fixed.

  template <class T> class A {};
  template <template <class, class...> class TT,
            class T, class... Args> using B = TT<T, Args...>;
  template <class T> class C : public B<A, T> {};


1/16/19  [EDGcpfe/20756]
C++-generating back end: short-circuiting dependent nontype template arguments

Consider the following example:

  template<bool, typename T> struct A {
    typedef T type;
  };
  template<int N, typename A<(!1 && N < 16), int>::type = 0> int f() {
    return 0;
  }
  int i = f<8>();

The expression "!1 && N < 16" in the non-type template argument for A is a
dependent expression, involving the template parameter N.  In standard C++,
that means that A<false,int> is only instantiated by the instantiation of
f<8>(), when the value of N is known, not by the definition of the function
template.  MSVC, however, behaves differently: because "&&" is a
short-circuiting operator and the result is determined by its constant
first operand, MSVC ignores the dependent part of the expression and
instantiates A<false,int> in the context of the function template
definition.

In configurations with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set
to TRUE, the C++-generating back end attempts to represent implicit
instantiations via explicit specializations, and this difference resulted
in generated code for this example that could not be compiled by MSVC.
Because the front end instantiated A<false,int> as part of the
instantiation of f<8>(), the corresponding explicit specialization appeared
in the generated code following the definition of the function template,
causing MSVC to issue an error indicating that A<false,int> had already
been instantiated.  The front end has now been changed to emulate this
processing of short-circuiting operators in dependent expressions in
Microsoft mode, which causes the explicit specialization of A<false,int> to
precede the definition of the function template in the generated code.


1/16/19  [EDGcpfe/20599]
Substitution incorrectly succeeds in some cases with too few template arguments

In some cases substitution could incorrectly succeed in cases where there were
too few template arguments for the template.  This could result in incorrect
behavior (because the wrong function could be selected) and in the example
below resulted in an internal error (in equiv_template_arg_lists).  Now
fixed.

  template <typename T> typename T::x v1;
  template <template <typename...> class> struct A;
  template <template <typename> class TT> A<TT> v2;
  namespace N { template <typename> struct B; }
  template <template <typename...> class TT> struct A {
    template <typename... T> auto operator()() -> decltype(v1<TT<N::B<T>...>>);
  };
  template <typename T> auto g(T t) -> decltype(t());
  constexpr auto g(...) { return 0; }
  template <typename> struct C;
  static_assert(!g(v2<C>),"");


1/15/19  [EDGcpfe/20681]
C++-generating back end: new-expressions with type placeholders

Consider:

  enum { x };
  auto p = new auto(x);

Previously, the C++-generating back end failed to render the "auto" specifier
in the new-expression; instead, it rendered a meaningless temporary name
("_T...").  That is now fixed, as are similar cases involving decltype(auto)
or deduced class template arguments.


1/15/19  [EDGcpfe/20748]
GNU compatibility: noplt attribute

The GNU noplt attribute is now accepted and ignored on function declarations
in GNU emulation mode (both C and C++ modes).  For example, with --gcc:

  int f() __attribute__ ((noplt));


1/15/19  [EDGcpfe/20357]
Substitution failure on variadic noexcept specifier in C++17 mode

In modes where the exception specification is part of the type (i.e.,
most C++17 modes), a substitution failure could occur if the noexcept
specifier refers to a type that is a member of the current instantiation
of a class template, and that class template is variadic.  Now fixed.
In example below, the "C<0>::type" in the noexcept is implicitly
"B<Ts...>::C<0>::type", which is why it is affected by this issue.

  template <typename T> inline constexpr bool v = true;
  template <int N, typename U> struct Ba;
  template <typename... Ts> struct B;
  template <typename T, typename... Ts> struct Ba<0, B<T, Ts...>> { 
    using type = T; 
  };
  template <typename... Ts> struct B {
    template <int N> struct C { 
      using type = typename Ba<0, B>::type; 
    };
    template <typename> void f() noexcept(v<typename C<0>::type>) { }
  };
  int main() {
     B<bool> b;
     b.f<int>();
  }


1/14/19  [EDGcpfe/20747]
Incorrect reuse of temporaries in lowered aggregate initializations

The C++ standard (since C++11) requires that an entire aggregate initialization
be treated as a full expression, whereas previously each initializer was
treated as a full expression.  This could result in the reuse of temporary
variables before the end of a full expression leading to undefined behavior at
run time.  Now fixed.  For example (with --c++11):

  struct A {
    A(const char *) {}
    ~A();
  };
  struct B {
    int arr[2];
  };
  int x(const A &) { return 1; }
  B f() {
    return { x("S1"), x("S2") };  // Had constructed two elements at the
                                  // same temporary location, then destroyed
                                  // both elements.
  }
  int main(void) {
    f();
  }


1/13/19  [EDGcpfe/20596]
Performance issue with instantiations based on dependent expressions

A problem with the way dependent nontype template argument values were
hashed could cause a performance issue with programs that make use of a
large number of such constructs, for example, programs that contain a large
number of enable_if constructs.  Now fixed.


1/12/19  [EDGcpfe/20700]
C++-generating back end: generated explicit specializations and exception
specifications

In configurations with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set
to TRUE, the C++-generating back end attempts to represent implicit
instantiations via explicit specializations in the generated code.  Because
of C++ language rules, this is not always possible, and the C++-generating
back end generally suppresses such explicit specializations.  In one such
case, however, a problematic explicit specialization was previously
emitted.  Because, prior to C++17, exception specifications were
instantiated separately on demand, it was possible for a base class to
declare a member function whose exception specification used a member of a
derived class.  However, it is not possible to define an explicit
specialization for such a base class because the definition of the derived
class containing the member function must appear after the base class
definition, making the exception specification ill-formed.  This has now
been fixed by suppressing the explicit specialization of the base class.
For example, with --c++11:

  template<typename T> struct D;
  template<typename T> struct B {
    void f() noexcept(noexcept(D<T>::g())) { }
  };
  template<typename T> struct D: B<T> {
    static void g() noexcept { }
  };
  D<int> di;

The generated code previously contained an explicit specialization for
B<int> in which the exception specification for B<int>::f() referred to
D<int>::g while D<int> was still an incomplete class type, which is an
error.


1/11/19  [EDGcpfe/20716]
Folding casts to virtual base classes (IL CHANGE)

The front end previously did not fold casts to virtual base classes (with some
minor exceptions).  For example:

  struct V {};
  struct B: virtual V {};
  struct D: B {} d;
  constexpr V *p = (B*)&d;  // Previously an error.  Now okay.

That is now fixed.  This fix involves an IL CHANGE to the representation of
"subobject paths" (see also the entry for EDGcpfe/17710).


1/11/19  [EDGcpfe/20743]
Use of a structured binding variable in a try statement

The internal representation of a structured binding "variable" (i.e., with
an initk_binding initialization type) caused problems (an assertion failure in
dump_variable_name) in the C-generating back end when used in a try statement
(with configurations where FORCE_STORES_OF_VARS_MODIFIED_IN_TRY_BLOCKS is
TRUE).  Now fixed.

  struct A {
    int x = 29;
  };
  void f() {
    auto [sb] = A();
    try { &sb; } catch (...) {}
  }


1/11/19  [EDGcpfe/17817]
Improve the speed of compiling classes with a large number of base classes and
virtual functions.

A change has been made to optimize the update_override_registry function, 
which is used when processing an override of a virtual function. This will 
improve the speed of compiling classes with a large number of base classes and 
virtual functions.


1/10/19  [EDGcpfe/20475]
Initialization of inline variables

A change has been made to introduce a guard variable during the lowering phase
to prevent multiple initializations of an inline variable.  For example
(with --c++17):

  // file1.cpp:
  int f();
  inline int i = f();

  // file2.cpp:
  int f();
  inline int i = f();
  int f() {
    static int j;
    return ++j;
  }
  int main() {
    if (i != 1) return 1;   // f() had been invoked once per TU
    return 0;
  }


1/9/19   [EDGcpfe/20531,EDGcpfe/20648]
C++20: Nested inline namespaces

Support for nested inline namespaces (P1094R2) has been added.  For example
(with --c++20):

  namespace A::inline B::inline C {
    int i;
  }
  namespace A {
    inline namespace B {
      inline namespace C {
        int j;
      }
    }
  }


1/9/19   [EDGcpfe/20600]
Internal error during deduction of variadic template call

An internal error could occur (in f_strip_local_and_nonreal_typedefs) during
template argument deduction if a deduced variadic template parameter was
followed by another template parameter of a different kind (e.g., type vs.
nontype) when considering a template where deduction should fail.  Now fixed.

  template <class...> struct X;
  template <typename... T, typename X<T...>::type I = 0> void f(T...); // #1
  template <class T> void f(T, T){} // #2
  int main() {
    f<char>(1, 2); // Should call #2
  }


1/9/19   [EDGcpfe/20019,EDGcpfe/20423]
C++20: no_unique_address attribute

Support has now been added for the no_unique_address attribute as documented
in P0840R2.  In IA-64 ABI configurations, the layout mechanism specified in
the IA-64 ABI documentation is used.  In Cfront configurations, fields with
empty class type and the no_unique_address attribute are treated as empty
base classes for the purposes of layout.  For example (with --c++20):

  struct E {};
  struct S {
    [[no_unique_address]] E e;
    int i;
  };
  static_assert(sizeof(S) == sizeof(int));


1/9/19   [EDGcpfe/20248]
Microsoft compatibility: spurious generic argument error in C++/CX mode

In C++/CX mode when microsoft_version is >= 1900, a spurious "not a valid
generic argument" error could be issued if an unscoped enumeration value
was used in a constant context in a mode where constexpr is enabled.
Now fixed.

  enum xxx { xxx1 };
  char ccc[xxx1 + 1];


1/8/19   [EDGcpfe/20598]
Variadic generic lambdas

Consider:

  void g(...) {}
  template<typename ... Ts> auto f(Ts ... ps) {
    [=](auto ... gps) {
      g((ps + gps)...);
    }(ps...);
  }
  int main() {
    f();      // Previously a spurious error.
    f(1, 2);  // Previously an abort in make_field_for_lambda_capture.
  }

Previously this code ran into two problems in the front end.  First, the call
"f()" resulted in a spurious error about the ps and gps packs having different
length (the error occurred during the prototype instantiation of the generic
lambda performed during the real instantiation of f<>()).  Second, when
determining the captures for the use pf the ps parameter pack, the front end
failed to capture the whole pack: Instead, it only captured the first element
of the pack, which resulted in an abort later on.  Both those problems are now
fixed.


1/8/19   [EDGcpfe/20601]
Use of local variables in template argument lists

Consider:

  template<int N> constexpr bool f() { return true; }
  template<int N> void g() {
    static constexpr int CI = N;
    static constexpr const int &RCI = CI;
    static_assert(f<RCI>(), "Unexpected");
  }

Previously, this failed because the expression "f<RCI>()" was considered
non-constant (the front end failed to notice the template-dependence of RCI,
which in turn disabled the relaxation of constraints for constant expressions
in templates).  That is now fixed.


1/8/19   [EDGcpfe/20632]
C++-generating back end: order of base classes in mem-initializer-list not
preserved

In configurations in which template definitions are generated from the 
prototype instantiation IL, the C++-generating back would place any virtual 
base classes at the end of the mem-initializer-list.  For example:

  struct A {};
  template <class T> struct B : virtual A {};
  template <class T> struct C : B<T> { C(T) : A(), B<T>() {} };

The above example would result in the following generated C++ output:

  struct A { };
  template< class T> struct B : virtual public A {};
  template< class T> struct C : public B< T>  { C(T) : ::B< T> (), ::A() { } };

Such generated code is correct, but would elicit a warning from some compilers
when compiled. This has now been fixed.
 

1/7/19   [EDGcpfe/20672]
Abort in finalize_subobject_path on address of array member of const-qualified
object

Consider:

  struct I { int i; };
  struct S { I ai[2]; };
  S const sc = {};
  auto const &r = sc.ai;

Previously this aborted in finalize_subobject_path because the interpreter
failed to determine a "subobject path" for the folded result of sc.ai.  That
regression (introduced in version 5.0 through the changes for EDGcpfe/20086)
is now fixed.


1/7/19   [EDGcpfe/20549]
Invalid order in generated explicit specializations involving constexpr
variable template

Consider:

  namespace N {
    enum E {};
  }
  namespace N {
    template<typename T> struct S {
      static constexpr int val = 42;
    };
    template<typename T> constexpr int Sval = S<T>::val; // (1)
    template<typename T> struct X {
      int f(int (*p)[1+Sval<T>]) { return 0; }
    };
    inline int g(X<E> *p) {
      p->f(nullptr);
    }
  }

When compiled in a configuration using the C++-generating back end with the
macro TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, this
generates explicit specializations for implicit instantiations.  The variable
template N::Sval is instantiated with N::E, which in turn requires N::S<E> to
be instantiated.  Previously, however, the explicit specialization generated
for N::S<E> was rendered before the definition of the N::S itself (and hence
the generated code was invalid).  That is now fixed.


1/4/19   [EDGcpfe/20002]
C++20: __VA_OPT__ preprocessor operator

In C++20 mode, the front end now processes the __VA_OPT__ preprocessor
operator as described in Committee documents P0306R4 and P1042R1.  For
example, with --c++20:

  #define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
  F(a, b, c)  // replaced by f(0, a, b, c)
  F()         // replaced by f(0)


1/3/19   [EDGcpfe/20646]
C++20: typeid and dynamic_cast in constexpr functions

In C++20 mode, the front end now accepts typeid and dynamic_cast expression
evaluations in constant expressions (provided those constructs do not throw
an exception).

  struct B { virtual int f(); };
  struct D: B {} d;
  constexpr int g() {
    D d;
    B *pb = (B*)&d;
    if (dynamic_cast<void*>(pb) == (void*)&d) {
      return 42;
    } else {
      throw 43;
    }
  }
  static_assert(g() == 42);  // Now accepted in C++20 mode.

This feature was added to the working paper for the next standard by the
standardization committee's paper P1327R1.


1/3/19   [EDGcpfe/20426]
C++-generating back end: unnamed template parameters as template arguments

In some cases, a reference to an unnamed template parameter was generated
in a template argument list as an undeclared temporary name (of the form
__T12345678).  This is now fixed.  For example, with --c++11:

  template <typename A> class B { };

  template <typename A, typename = void> class D : B<A> {
    using T = typename D::B;  // Previously generated as D<A,__T12345678>
  };


1/2/19   [EDGcpfe/20645]
C++20: "try"/"catch" in constexpr functions

In C++20 mode, the front end now accepts "try"/"catch" constructs in constexpr
functions (throwing an exception is still not permitted during the evaluation
of a constant expression, however).  For example:

  constexpr int f() {
    try {                    // Now accepted in C++20 mode.
      return 42;
    } catch (...) {
      return 0;
    }
  }
  static_assert(f() == 42);  // Okay in C++20 mode.

This feature was added to the working paper for the next standard by the
standardization committee's paper P1002R1.


12/28/18 [EDGcpfe/20230]
"if constexpr" not processed properly when not parsing non-class templates

In modes where non-class templates are not parsed (e.g., permissive
Microsoft mode), "if constexpr" statements in template contexts were
sometimes not parsed properly.  Now fixed.

  template <typename T> struct X {
    int f() {
      {
        int i = 0;
        if constexpr (true) {
        } else if (i) {
        } else {
        }
        return i;
      }
    }
  };
  int main() {
    X<int> x;
    x.f();
  }


12/27/18  [EDGcpfe/20592]
Microsoft compatibility: value of _MSVC_LANG and __cplusplus with 
--ms_c++latest option

A change has been made to set _MSVC_LANG and __cplusplus to 201704L for
microsoft_version >= 1920 when the --ms_c++latest command-line option is 
specified.  This change only affects the values of _MSVC_LANG and
__cplusplus; the set of features enabled by --ms_c++latest is unchanged.  
When using the --ms_c++20 command-line option, the value of _MSVC_LANG and 
__cplusplus is still set to 202000L.


12/24/18 [EDGcpfe/20640]
C++-generating back end: Redeclarations and C-mode tentative definitions

When compiling C code containing a tentative definition of a variable, the
C++-generating back end put out subsequent tentative definitions with the
"extern" storage class specifier.  In most translation units this change
from tentative definition to non-defining declaration caused no problems.
However, in a declaration containing both a redeclaration and a tentative
definition of another variable, this transformation had the effect of
removing the tentative definition of the second variable.  This is now
fixed; the C++-generating back end no longer gratuitously adds "extern" in
tentative definitions after the first.  For example, with --c99:

  int a;
  int a, b;  /* Previously generated as "extern a, b;", which inadvertently
                eliminated the tentative definition of b. */


12/21/18 [EDGcpfe/20593]
noexcept operator and pointer-to-member-function types

Consider:

  template<typename T> T&& val() noexcept;
  struct S {};
  using PMF = int (S::*)(int) noexcept;
  static_assert(noexcept((val<S>().*val<PMF>())(42)));  // Previously failed.
                                                        // Now okay.

Previously, all calls through pointer-to-member-function types were treated
as potentially throwing an exception, which caused the example above to trigger
a spurious error.  That is now fixed.


12/20/18 [EDGcpfe/20155,EDGcpfe/20594]
New-expression with braced initializer and class template argument deduction

The front end previously issued a spurious error for:

  template<typename T> struct S {
    S(T p2) {}
  };
  int main() {
    S<int> *ps = new S{ 5 };
    return ps == nullptr;
  }

claiming no constructor matches the new-initializer (because it erroneously
treated "new S{ 5 }" as "new S({ 5 })").  That is now fixed.


12/20/18 [EDGcpfe/20634]
Abort in find_innermost_namespace_scope_depth

In configurations with CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
set to TRUE, the front end could abort in find_innermost_namespace_scope_depth
when dealing with an instance of a class template triggered during the
instantiation of a local polymorphic lambda.  That is now fixed.


12/20/18 [EDGcpfe/19989]
Lookup of allocation functions in new-expressions

Consider:

  using size_type = decltype(sizeof(42));
  struct S {};
  template<typename T> void f(T *p) {
    new(p) T;    // (1)
  }
  void* operator new(size_type, void*) noexcept;  // (2)
  void g() {
    f<S>(0);
  }

Previously, the front end treated the call to an allocation function implied
by the new-expression (1) as if it were an ordinary user-written call, except
that it was considered non-dependent.  That meant that the allocation function
was looked up in the template definition only, and thus it did not find the
intended allocation function (2).  That is now fixed.


12/20/18 [EDGcpfe/20551]
Unwanted warning about unreferenced member function of class template in 
unnamed namespace

If a class template appears in an unnamed namespace, the front end 
previously issued warnings about unreferenced member functions of 
instances of that template. These warnings were considered unwanted.  The 
front end now issues a warning for a member function of a class template 
only if the parent class isn't referenced.  For example:

  namespace
  {
    template <int n>
    struct A {
    void f1() {}
    void f2() {}
    };
  }
  void f() {
    A<1> a1;
    a1.f1();
    A<2> a2;
    a2.f2();
  }

Previously, this would result in warnings about A<1>::f2 and A<2>f1 
declared, but not referenced.  With this change, those warnings are no
longer issued.


12/19/18 [EDGcpfe/16266]
Spurious error on attribute in alias declaration

A spurious error had been given when an alias declaration contains an
attribute.  For example (with --c++14):

  using x [[deprecated]] = int;


12/18/18 [EDGcpfe/19657]
Missing diagnostic for destructor exception specification mismatch

A destructor without an exception specification is potentially-throwing if 
and only if any of the destructors for any of its potentially-constructed 
subobjects is potentially-throwing.  For example:

 struct S {
  ~S() noexcept(false);
 };
 S::~S() {} // The implicit exception specification is different from the 
            // exception specification on the previous declaration.

Previously, the front end wouldn't diagnose the mismatch in the exception
specification between the two declarations.  This has now been fixed.


12/17/18 [EDGcpfe/20503]
Instantiations for deduced return types

Consider:

  template<typename T> T u();
  template<typename T> struct S {
    static auto f() { return u<T>(); }
    static auto g() { return f(); }
  };
  int main() {
    decltype(S<int>::g()) r = 0;
    return r;
  }

In this example, S<int>::g() and S<int>:f() are instantiated only to determine
their deduced return types.  Previously, however, the resulting instantiations
resulted in IL with references to u<int>; those references could then result in
linker errors (e.g., when compiling this example in a configuration using the
C-generating back end).  That problem is now fixed: Instantiations triggered
indirectly by instantiations performed for return type deduction are now held
back until those instantiations are needed for other reasons (if at all).


12/17/18 [EDGcpfe/19593]
Assertion failure in check_carries_dependency_for_params

A carries_dependency attribute applied to a parameter in a deduction guide
would cause an assertion failure in check_carries_dependency_for_params. 
For example:

  template <class T> struct A {};
  template <class T> A([[carries_dependency]] T = 1) -> A<int>;

This has now been fixed.


12/13/18 [EDGcpfe/20158]
C++-generating back end: casts involving class template argument deduction

The C++-generating back end sometimes replaced a function-style cast with a
C-style cast when the type relies on class template argument deduction.  A
C-style cast is not one of the contexts in which class template argument
deduction occurs, so the generated code was incorrect and uncompilable.
This is now fixed.  For example, with --c++17:

template<class T> struct S { S(T){} };
template<class T> auto f(T t) {
  return S(t);  // Previously incorrectly generated as (S)t
}


12/13/18 [EDGcpfe/20265]
GNU C compatibility: Floating-point const variables

In GNU C mode, the front end already accepts the extension that allows for the
use of integer const variables in constant-expressions.  Now, that is extended
to floating-point const variables when gnu_version >= 80000.  For example:

  double const x = 3.0;
  double y = x*2.0;  // Previously an error in all GNU C modes.  Now a warning
                     // in GNU C modes with gnu_version >= 80000.


12/13/18 [EDGcpfe/20577]
Regression in template template parameter matching

Version 5.0 introduced a regression involving deduction of template template
parameters.  When a function template was called in such a way that a template
template parameter was deduced from a base class template of an argument
whose type is a derived class template, deduction could fail.  Now fixed.

  template <class T1, class T2> struct B {};
  template <class T> struct D : B<T, T> {};
  template <template <class, class> class TT, class T> void f(TT<T, T>*) {}
  int main() {
    D<int> d;
    f(&d);
  }


12/13/18 [EDGcpfe/20546]
__is_constructible and references to incomplete types

The front end previously spuriously failed the following static_assert:

  struct S;
  static_assert(__is_constructible(S&, S&), "Unexpected");

because it did not correctly handle references to incomplete types in that
context.  That is now fixed.  Note that this also changes the outcome of the
static_assert construct in the example for EDGcpfe/14879.


12/13/18 [EDGcpfe/20126]
C++-generating back end: typedefs appearing in generic lambdas

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end sometimes used the
underlying type of a typedef in place of the typedef itself in the
definition of a generic lambda, even if the underlying type uses variables
that are not captured by the lambda.  In such cases, the generated code
was incorrect and could not be compiled.  This is now fixed; the
C++-generating back end now preserves uses of typedefs appearing in
prototype instantiations.  For example, with --c++17:

  template <typename> constexpr bool m = true;
  template <long L> struct C { typedef double q; };
  void ao() {
    [](auto i) {
      using ar = typename C<i>::q;
      [] () {
        if constexpr (m<ar>) { };  // Previously generated as
                                   // m<typename C<i>::q>, which is an
                                   // error because i is not captured.
      };
    };
  }


12/13/18 [EDGcpfe/19532]
clang compatibility: C overloadable functions with ellipsis and no named 
parameters

In C mode, clang allows ellipsis and no named parameters in a function 
that has an __overloadable__ attribute. For example:

  void p(...)  __attribute__((__overloadable__));

The front end now accepts this in clang C mode.


12/12/18 [EDGcpfe/20526]
Incorrect handling of qualifiers from a conversion function result in a
conditional operator

Consider:

  struct X {
    X(); 
    X(X&);
  };
  struct Y {
    operator X const&() const;
  };
  auto &&r = true ? Y() : X(); // Now an error.  Previously accepted.

Previously, the front end accepted this erroneously because it lost the
const-qualification of the result of applying the conversion function on
"Y()" (thus enabling the copy constructor of X to bring both branches of the
conditional operator to a common type).  That is now fixed.


12/11/18 [EDGcpfe/19940,EDGcpfe/20165,EDGcpfe/20317]
GNU and clang compatibility: __has_unique_object_representations

The front end previously gave different results in g++ and clang modes than
those of the emulated compilers for some types involving bit-fields, tail
padding, arrays, and vectors.  These are now fixed.  For example, with
--g++ --c++17:

  union U { int i : sizeof(int) * __CHAR_BIT__ - 1; };
  static_assert(!__has_unique_object_representations(U), ""); // Now okay


12/11/18 [EDGcpfe/19412,EDGcpfe/20545]
Microsoft C++ compatibility: Explicit specializations and exception specifiers

Consider:

  template<typename T> void f(T);
  template<> void f(int) noexcept; // Now accepted in Microsoft mode.

That is normally an error because the exception specifier on the explicit
specialization does not match that of the template.  Microsoft compilers,
however, appear to accept it, even in C++17 modes (where exception specifiers
are part of the function type).  The front end now emulates that nonstandard
behavior in Microsoft C++ mode.


12/11/18 [EDGcpfe/20539]
Copy elision and base class subobjects

C++17 included changes that amounted to "mandatory copy elision": Copying a
prvalue generally just causes the prvalue to be constructed directly in its
final destination.  However, that should not be done for initializing base
class subobjects.  For example:

  struct N { N(N const &) = delete; };
  N makeN();
  struct S1: N {
    S1(): N{makeN()} {}  // Invalid.
  };
  struct S2: N {
    S2(): N(makeN()) {}  // Invalid.  (But previously not diagnosed.)
  };

For both S1 and S2 the construction of the base subobject cannot elide a call
to N's copy constructor, and therefore an error should be issued since that
copy constructor is deleted.  Previously, however, the front end failed to
issue the error in the parenthesized initializer case (because the copy was
incorrectly elided).  That is now fixed.  A similar issue with delegating
constructors has also been fixed.


12/11/18 [EDGcpfe/20582,EDGcpfe/20583,EDGcpfe/20584]
GNU C++ compatibility: anonymous struct members

Anonymous struct members have been enabled in GNU C++ modes with 
gnu_version >= 80100.  A change has been made to allow for addressing
the members of anonymous structs with a designated initializer in C++ 
modes.  For example :

  struct A { 
    struct { int b; }; // now valid in certain GNU C++ modes  
  };
  A a = { .b = 3; };  // now valid in certain GNU C++ modes 


12/10/18 [EDGcpfe/19426]
C++-generating back end, GNU compatibility: unnecessary name qualification
of nested class template names

In C++-generating back end configurations in which template definitions are
generated from the prototype instantiation IL, the C++-generating back end
unnecessarily used a qualified name when referring to a class template from
within its own definition.  Although the generated code was correct, in
some cases g++ was unable to compile it.  This has now been fixed and
unqualified names are used when possible for such references.  For example,
with --g++:

  template <typename a> class b {
    template <typename> struct c {
      using d = c<int>;  // Previously generated as
                         // typename ::b<a>::template c<int>, which g++
                         // is unable to compile successfully.
    };
  };


12/10/18 [EDGcpfe/20548]
GNU C++ compatibility: Null-pointer offsets in constexpr evaluations

Consider:

  struct S {
    int x[2];
  } s;
  using UI = decltype(sizeof(0));
  static_assert((UI)&((S*)0)->x[1] == sizeof(int));
    // Normally invalid.  Now accepted in GNU modes.

Normally, this is invalid because offsetting a null pointer is invalid.
In GNU modes, however, this is now accepted.  (Prior to the changes for
EDGcpfe/19246 in version 5.0, this was also accepted in all modes, but it is
not actually valid.)


12/10/18 [EDGcpfe/20527]
C++-generating back end: aliases in classes emitted as explicit specializations

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is set to TRUE,
alias templates in classes emitted as explicit specializations could have
types that use the original template parameters instead of the values
associated with the given explicit specialization.  Now fixed.

  template<typename T, typename U> struct A { };
  template<typename X> struct B {
    template<typename Y> using C = A<Y, X>;
  };
  B<int> bi;  // B<int>::C had an incorrect definition


12/10/18 [EDGcpfe/20554]
__builtin_offsetof in constexpr evaluations

The evaluation of __builtin_offsetof expressions in the constexpr interpreter
did not correctly handle array subscripting.  For example, in GNU C++17 mode:

  struct S {
    int x[2];
  };
  constexpr int g(int i) {
    return (int)__builtin_offsetof(S, x[i]);
  };
  static_assert(g(1) == sizeof(int));  // Previously failed.  Now okay.

That is now fixed.


12/7/18  [EDGcpfe/20579]
Type qualifiers lost during expression folding

Consider:

  struct S {};
  using CS = S const;
  S &&r = CS{};  // Previously accepted.  Now an error.

Previously, the front end folded the initializer "CS{}" into a constant entry,
but the "const" qualifier was lost in the process.  As a result, the reference
binding was accepted when it should have elicited an error (since a qualifier
is dropped).  That is now fixed.


12/7/18  [EDGcpfe/20578]
const_cast conversions to reference types

The changes for EDGcpfe/18553 (in version 5.0) introduced a regression in
const_cast conversions to reference types.  For example:

  template<typename T> T prvalue();
  template<typename T> T& lvalue();
  template<typename T> T&& xvalue();
  auto r1 = const_cast<int*&>(prvalue<int const*>());
  auto r2 = const_cast<int*&&>(prvalue<int const*>());
  auto r3 = const_cast<int*&>(xvalue<int const*>());

In version 5.0, the front end accepted all three of the const_cast expressions,
but all three are ill-formed according to the standard.  This is now fixed: An
error is issued for all three initializers.


12/7/18  [EDGcpfe/20576]
Abort on constant address representing "one past" a non-array union object

The front end previously aborted (in finalize_subobject_path, interpret.c) with
an internal error when constexpr evaluation produced a result with an address
one past a union object (that is not an array element).  For example:

  union U { int x; } x;
  constexpr U* f() { return &x+1; }
  U *p = f();  // Aborted in 5.0

This regression (introduced in version 5.0 by the changes for EDGcpfe/17710) is
now fixed.


12/6/18  [EDGcpfe/20573]
Diagnosing attempts to redeclare structured bindings

The front end now issues an error on code like the following:

  int x[] = { 1, 2 };
  auto &[p, q] = x;
  extern int p;  // Now an error.

Previously, the standalone declaration of p was treated as a redeclaration of
the structured binding of the same name.  As part of this change, diagnostics
now refer to structured bindings as "structured bindings" rather than as
"variables" (as was the case previously).


12/6/18  [EDGcpfe/20575]
subobject_partner now available to back ends

In configurations that do lowering, the subobject_partner field in
a_class_type_supplement is used to link class types to their corresponding
subobject class types.  Previously that field was cleared and unavailable to
a back end, but a change has been made to preserve that in the IL.


12/6/18  [EDGcpfe/20138]
C++-generating back end: explicit temporaries, class template argument
deduction, and lambda closure classes

Given an explicit temporary in which class template argument deduction is
used with an initializer that is a lambda expression, the C++-generating
back end put out the name of the class template instance using a temporary
name (of the form __T12345678) as a template argument, rather than simply
the class template name alone.  This is now fixed.  For example, with
--c++17:

  template <typename ...F> struct S {
    S(F...) { };
    void operator()() { };
  };
  struct a { };
  void f() {
    S{[](a x) { }}();  // Previously generated as S<__T12345678>
  }


12/6/18  [EDGcpfe/20082]
GNU C++ compatibility: use of inaccessible types as template arguments

The changes for EDGcpfe/12703 caused the front end to ignore certain access
errors in GNU and Clang C++ modes when they occur in template argument lists.
That nonstandard behavior is now disabled in Clang mode and in GNU modes with
gnu_version >= 40900.


12/6/18  [EDGcpfe/20010]
C++20: const mismatch with defaulted copy constructor (core issue 1331)

In C++17 and earlier, if the declared type of an explicitly-defaulted 
function is not the same as if it had been implicitly declared, then it 
is ill-formed.  In C++20, such functions are defined as deleted.  
Exceptions are made for two cases where it's desirable for a defaulted 
definition to remain ill-formed: an assignment operator with a 
mismatched return type, and an assignment operator with a parameter 
type that's not a reference.  For example:

  struct A{
      A(volatile A&) = default;
  };

A's copy constructor was ill-formed before C++20.  In C++20 it is defined 
as deleted. This has now been implemented. 



12/5/18  [EDGcpfe/20394]
C++-generating back end: friend function parameters and name hiding

When generating a friend declaration for a function that is a member of a
class or namespace, the C++-generating back end assumed that parameter
types that are members of that class or namespace could be referred to
without qualification, i.e., that the qualification of the function name
implicitly extends to the names of its parameter types.  An exception to
this assumption is when clang is the generated code target, as clang does
not implement this implicit qualification.  G++ does implement the rule,
but with a twist: it searches the local scope before searching the scope to
which the friend function belongs.  In cases where the local scope contains
a declaration with the same name as one of the friend function's parameter
types, g++ was unable to compile the generated code correctly.  Because of
these disparate lookup rules, when gcc_is_generated_code_target or
clang_is_generated_code_target is TRUE, the C++-generating back end will no
longer assume that the qualifier of the name of the befriended function
implicitly applies to names in the parameter list, and it will also ignore
the lexical scope of the friend declaration, effectively requiring full
qualification of all the names in the friend declaration.  (This also
changes the mechanism by which the example in EDGcpfe/19743 was handled in
version 5.0.)  For example, with --g++:

  namespace N {
    struct S {};
    void f(S);
  }

  class C {
    void S();
    friend void N::f(N::S);  // Previously generated as N::F(S), causing
                             // an error from g++, treating S as C::S
  };


12/5/18  [EDGcpfe/20542]
Explicit deduction guides

Consider:

  template<typename ... T> struct S { S(T...); };
  template<typename ... T> explicit S(T ...) -> S<T...>;
  S s = { 1, 2 };  // Previously accepted.  Now an error.

Previously, the front end accepted the initializer despite the fact that the
associated deduction guide is "explicit", because it accidentally preferred
the deduction guide implicitly generated from the (non-explicit) constructor
over the explicitly declared guide.  That is now fixed and an error is now
correctly issued for this case.


12/5/18  [EDGcpfe/20128]
C++-generating back end: missing parentheses in fold expression

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end failed to enclose
operands of fold operators in parentheses when necessary, resulting in
generated code that could not be compiled successfully.  This is now fixed.
For example, with --c++17:

  template<class... Tx> int f(Tx... xs) {
    return ((xs+1) + ...);  // Previously generated as (xs + 1 + ... )
  }


12/4/18  [EDGcpfe/20328]
C++-generating back end: default template arguments and redeclarations

The C++-generating back end could abort with a null pointer dereference
if a class template is declared with default arguments and then redeclared
without default arguments.  This is now fixed.  For example, with --g++
--c++11:

  template <int I, int J = (I + 1)> struct S;
  template <int, int> struct S;
  template<typename T> T f() {
    constexpr int V = T::value;
    S<V> *s2;  // Previously aborted
  }


12/4/18  [EDGcpfe/18527,EDGcpfe/20367,EDGcpfe/20522,EDGcpfe/20523]
Capturing of *this

When capturing *this, the front end often lost track of the correct types
involved, resulting in spurious errors.  For example:

  struct S {
    void f() {
        [*this]{ [this] {}; };  // Previously a spurious error about not being
                                // able to convert from S const* to S *const.
    }
  };

This is now fixed.


12/4/18  [EDGcpfe/20105]
C++-generating back end: qualified names and class template argument deduction

Previously the C++-generating back end failed to use a qualified name when
needed for a class template referenced in class template argument deduction,
resulting in erroneous generated code that could not be compiled.  This is
now fixed.  For example, with --c++17:

  namespace N {
    template<typename T> struct A {
      A(T);
    };
  }
  N::A na(5);  // Previously generated without "N::"


12/4/18  [EDGcpfe/18092,EDGcpfe/20520]
Constexpr evaluation of casts

Consider in C++17 mode:

  constexpr bool f() noexcept(true) { return true; }
  constexpr bool (*fp)() = f;
  static_assert(fp());  // Previously an error.  Now okay.

Previously, this triggered an unjustified error in some configurations.  Now,
that case is accepted.  Conversely, consider:

  struct B {
    constexpr B() {}
    constexpr int g() const;
  };
  struct D: B { int i; };
  constexpr int B::g() const {
    return this->*static_cast<int B::*>(&D::i);
  }
  static_assert(B().g(), "");

Previously, that was accepted because the static_cast lost the dynamic type
of its operand.  Now an error is correctly diagnosed.


12/3/18  [EDGcpfe/20541]
Clang compatibility: mangling of __underlying_type

When ABI_COMPATIBILITY_VERSION >= 510, the mangling used for __underlying_type
is now the vendor extension "U3eut" in Clang emulation mode.  GCC does not yet
implement mangling of __underlying_type.  No change is made in Cfront mode.
For example (with --clang_version 70000):

  enum class E: short { e };
  template <typename T> void f(__underlying_type(T) p);
  void g() {
    f<E>(2);
  }


12/3/18  [EDGcpfe/20550]
C++20: Immediate functions ("consteval")

In C++20 mode, the front end now supports immediate functions, which are
functions declared with the new keyword "consteval".  Immediate functions are
much like constexpr functions, but they generally must produce a constant
result (except when called from within another consteval function definition).
For example:

  consteval int f(int p) { return p+1; }
  int r = f(41);  // Okay.  Equivalent to "int r = 42;".
  int e = f(r);   // Error: f(r) did not produce a constant result.

This feature was added to the working paper for the (expected) C++20 standard
through the committee's paper P1073R3.


12/3/18 [EDGcpfe/20139,EDGcpfe/20643]
GNU C++ compatibility: enable __builtin_launder

The built-in pseudo-function "__builtin_launder" is now enabled in C++ GNU mode
for gnu_version >= 70100.


11/30/18 [EDGcpfe/20092,EDGcpfe/20140,EDGcpfe/20346]
Abort in need_zeroing_for_value_initialization on dependent noexcept-specifier

Consider:

  template<typename> struct S;
  template<bool B> struct S<int() noexcept(B)> {}; 
  int main() {
    S<int()>{};
  }

Previously, this aborted in C++17 mode (in lower_init.c, in function
need_zeroing_for_value_initialization).  That is now fixed.  This example now
is accepted in GNU and Clang C++17 modes, but triggers an error in other C++17
modes.


11/29/18 [EDGcpfe/20529]
Casting away constness

Consider:

  struct V { char b[10]; };
  V const v{};
  auto r = reinterpret_cast<int *const&>(v.b); // Previously an error.
                                               // Now okay in nonstrict modes.

The standard considers that case invalid because the type of v.buf is treated
as if it were:

  const array of const char

(i.e., the "const" applies to both sides of the array) and casting that to a
reference to

  const pointer to (non-const) int

causes one of the "const" qualifications to be dropped; i.e., the expression
"casts away constness".  The front end previously enforced that in all modes.
However, other compilers do accept the case and the front end now follows suit
in nonstrict C++ modes.


11/29/18 [EDGcpfe/20060]
Abort in C++-generating back end with GNU-mode recursive template instantiation

Consider:

  template<typename...> struct C;
  template<> struct C<> { static int const value = 0; };
  template<typename T, typename... Args> struct C<T, Args...> {
    static int const value = 1 + C<Args...>::value;
  };
  static_assert(C<int, float>::value == 2, "Unexpected!");

This previously aborted in GNU C++11 mode when the configuration macro
TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is set to TRUE.  That is now
fixed.


11/28/18 [EDGcpfe/20504]
Abort in finalize_subobject_path on void* pointer to union

Consider:

  union U { int i; } au[1];
  struct S {
    void *p;
    constexpr S(void* p): p(p) {}
  };
  void g() {
    S s{au};  // Previously triggered an internal error.  Now okay.
  }

Previously this aborted in finalize_subobject_path (interpret.c) while trying
to find a "void" member (corresponding to the underlying type of S::p) in U.
This regression (introduced by the changes for EDGcpfe/19216 in version 5.0)
is now fixed.


11/28/18 [EDGcpfe/19431]
Address of structured bindings for bit fields

Consider:

  struct S { int x: 3, y: 4; };
  int g(S p) {
    auto [x, y] = p;
    int &r = y;  // Previously could abort.
    return r;
  }

In configurations with ADDR_OF_BIT_FIELD_ALLOWED set to TRUE this could
previously trigger an abort in is_bit_field_operand_whose_address_can_be_taken
(exprutil.c).  That is now fixed.


11/28/18 [EDGcpfe/20502]
Nondependent structured bindings in templates

Nondependent structured bindings appearing in templates sometimes generated
spurious errors because a call to "get<N>" was not correctly set up.  That is
now fixed.


11/27/18 [EDGcpfe/20104,EDGcpfe/20279]
Structured bindings and std::tuple_element

The standard requires that the first (nontype) template parameter of
std::tuple_element be of type std::size_t and the front end previously
required that to be the case (otherwise, tuple-like structured bindings would
complain that std::tuple_element<0, X> could not be instantiated).  Now, that
requirement has been relaxed to match other implementations.  For example:

  namespace std {
    template<typename T> struct tuple_size;
    template<int N, typename T> struct tuple_element;
      // Nonstandard type "int" for the first parameter.
  }
  struct X {};
  namespace std {
    template<> struct tuple_size<X> { static constexpr int value = 2; };
    template<int N> struct tuple_element<N, X> { using type = int; };
  }
  template<int> int get(X);
  void g(X t) {
    auto [x, y] = t;  // Previously an error.  Now accepted.
  }


11/27/18 [EDGcpfe/20191]
Microsoft compatibility: Tuple-like structured bindings

The C++17 standard specifies that a structured binding should use a tuple-like
mechanism for value extraction if std::tuple_size<E>, where E is the type to be
decomposed, is a complete type.  However, the Microsoft compiler further
requires that std::tuple_size<E>::value actually be a constant integer value
before committing to the tuple-like interpretation.  For example:

  namespace std {
    using size_t = decltype(sizeof(42));
    template<typename> struct tuple_size;
    template<typename, typename = void> struct _Base_tuple_size {};
    template<typename _T>
    struct _Base_tuple_size<_T, decltype(tuple_size<_T>::value)> {
      static constexpr size_t value = tuple_size<_T>::value;
    };
    template<typename _T>
    struct tuple_size<_T const>: _Base_tuple_size<_T> {};
  }
  struct S {
    int i, value;
  } s;
  int main() {
    const auto &[x, y] = s;  // (1)
  };

Here, the type to be decomposed (in (1)) is "S const" and tuple_size<S const>
is a complete type: The standard therefore requires the decomposition to use
a tuple-like mechanism to decompose s in std::tuple_size<S const>::value
components.  Since std::tuple_size<S const>::value isn't an integral constant
expression, however, the program is ill-formed.  In Microsoft mode, however,
the front end now falls back to decomposing s by its data members (ignoring the
tuple-like mechanism).


11/27/18 [EDGcpfe/19999,EDGcpfe/20422]
Rvalue objects and const-qualified pointers to members

As described in Committee document P0704R1, C++20 relaxes the rule
prohibiting use of an rvalue object expression in a pointer-to-member
expression where the member pointer has an lvalue ref-qualifier.  Under the
new rules, such an expression is permitted if the member pointer has a
const qualifier.  For example, with --c++20:

  struct X { void foo() const &; };
  void f() {
    (X{}.*&X::foo)(); // Previously an error, now accepted in C++20 because
                      // X::foo has a const qualifier
  }


11/27/18 [EDGcpfe/20181]
Incorrect constructor selected for structured binding to xvalue

Consider:

  struct S {
    S(const S&) = delete;
    S(S&&) = default;
  };
  S a[1] { {} };
  void f() {
    auto [x] = static_cast<S(&&)[1]>(a);  // Previously an error.  Now okay.
  }

Previously this elicited an error because the initialization of the structured
binding container incorrectly selected the copy constructor instead of the move
constructor to copy the container elements.  That is now fixed.


11/27/18 [EDGcpfe/20116]
C++-generating back end: Structured bindings involving an array copy

Structured bindings sometimes require an element-by-element copy of an array
expression.  This copy is represented as an aggregate initialization involving
a special dik_constructor entry (see also the entry for EDGcpfe/17413).
Previously, however, the C++-generating back end failed to recognize that
special case and therefore incorrectly rendered structured binding declarations
that result in such array copies.  For example:

  struct S {
    S();
    S(S const&);
  } arr[2]{};
  int main() {
    auto [x, y] = arr;  // Previously rendered incorrectly.
  }

That problem is now fixed.


11/27/18 [EDGcpfe/20115]
Unreferenced structured bindings

Consider:

  float arr[2] = { 1.0 ,2.0 };
  int g() {
    auto [x, y] = arr;
    return x;
  }

Previously, this elicited a warning about variable y not being referenced.
However, it is not uncommon for structured bindings to be unused since names
must be provided for every potentially bindable component.  The front end has
therefore been updated to only emit a diagnostic if all the bindings in a
structured binding declaration are unused.


11/27/18 [EDGcpfe/20484,EDGcpfe/20487]
Assertion failure in lower_param_ref

As a result of the C++17 changes to allow aggregates to have base classes in
5.0 (see EDGcpfe/17688), some aggregate initialization that had implicitly
referred to "this" could fail an assertion check (in lower_param_ref).
For example (with --c++17):

  struct B {};
  struct A : B {
    int x;
    struct C : B {} c {(struct A&&)x};
  } a{};


11/26/18 [EDGcpfe/20113]
Spurious error on structured binding of a template class

Consider:

  template<typename T> struct S { T a; };
  void g(S<int> *b) {
    auto &[c] = *b;  // Previously a spurious error.  Now okay.
  }

Previously, this example triggered a spurious error because the front end
failed to instantiate S<int> prior to resolving the structured bindings.  That
is now fixed.


11/26/18 [EDGcpfe/20074,EDGcpfe/20099]
Structured bindings for references and decltype

The front end previously did not correctly handle decltype constructs applied
to the names of structured bindings bound to reference entities.  For example:

  struct S { int &r; };
  int x = 42;
  auto [bnd] = S{ x };
  decltype(bnd) q;  // Previously accepted.  Now an error.

In this example, the front end previously did not produce a reference type for
variable q (when it should do so) and as a result it accepted this example.
Now, a reference is produced and an error is issued because the reference q has
no initializer.  A similar problem with tuple-based bindings is also fixed.


11/26/18 [EDGcpfe/20472]
Microsoft compatibility: MSVC allows const_cast to a function type

In Microsoft mode, the front end now allows const_cast to be applied to a
function type.  For example:

  int foo(int*);
  auto bar = const_cast<int(*)(int*const)>(foo); 


11/26/18 [EDGcpfe/20151]
Microsoft compatibility: internal error on variadic nonreal instantiation

A change made in version 4.14 (see EDGcpfe/18144) enabled the use of
variadic templates as Microsoft-mode instantiated nonreal base classes.
In some cases that change could result in an invalid template argument
list for a base class that was not itself variadic.  This could then
result in a variety of incorrect behaviors, including (for the example
below) an internal error (in form_template_arg_info).  Now, a variadic
template can only have an instantiated base class if that class is itself
variadic.

  template <class T, class U, class V, class W> struct C {
    // Formerly an internal error issuing spurious error on the use of W
    typedef C<T, U, V, W> my_C;
  };
  template <class T, class U, typename... Ts> struct D : C<T, U, Ts...> { };


11/21/18 [EDGcpfe/20493]
C++20: Assignment to non-active union members during constexpr evaluation

In C++20 mode, constexpr evaluation now permits assignment to non-active
union members.  For example:

  union U { int i; double f; };
  constexpr int g() {
    U u = { .f = 1.0 };
    u.i = 42;
    return u.i;
  }
  static_assert(g() == 42);

Previously, an error was issued because "g() == 42" was never a constant
expression due to the assignment "u.i = 42;" which assigns a value to a
non-active member of u.  Now, this is accepted in C++20 mode.  This implements
the C++ standardization committee's change made through paper P1330R0.


11/21/18 [EDGcpfe/20492]
Incorrect string form of alias template member of class template instance

In configurations with RECORD_TEMPLATE_STRINGS set to TRUE, the string
produced for a member alias template of a class template instance did not
contain the type-id portion of the alias template definition.  The effect
of this bug could be seen in the output of the C++-generating back end when
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is set to TRUE.  In
such configurations, the front end attempts to produce explicit
specializations in the generated code reflecting the implicit
instantiations done by the front end.  For example, given the input

  template<typename T> struct A;
  template<typename T> struct B {
    template<typename U> using x = A<U>;
  };
  B<int> bi;

the C++-generating back end produced output containing an explicit
specialization for B<int> with B<int>::x<U> represented as:

  template < typename U > using x =;

i.e., missing "A<U>". This is now fixed.


11/20/18 [EDGcpfe/14810,EDGcpfe/20483]
Internal error with unevaluated template default argument

Consider:

  template <class T> T f();
  template <class T> decltype(f<T>())* g(T) { return 0; }
  template <class T> void h(int = 0) { }
  void d() { g(&h<int>); }

Previously, this aborted in some modes that consider default arguments of
function templates in the deduction process (e.g., with the command-line
options "--c++11 --nonstd_default_arg_deduction").  That is now fixed.


11/19/18 [EDGcpfe/20086]
Abort in finalize_subobject_path with nested arrays

Consider:

  struct P { char x, y; };
  struct S {
    char z;
    P p[2];
  };
  S s[3];
  constexpr P *pp = &(&s[2])->p[2];

Previously, the front end aborted in finalize_subobject_path because the
address constant produced by the initializer of pp represented an address that
is both one position past the end of array s and one position past the end of
the array (&s[2])->c.  That problem is now fixed.


11/16/18 [EDGcpfe/18414,EDGcpfe/20308,EDGcpfe/20458]
GNU/Clang compatibility: Enable nested namespaces

Nested namespaces (a C++17 feature) are now enabled when gnu_version >= 60000
or clang_version >= 30600.  A warning is issued in clang emulation mode.


11/16/18 [EDGcpfe/20477]
GNU/Clang compatibility: Feature test macros for standard features enabled
in earlier modes

Gcc and clang often enable language features in modes earlier than the
standards in which the features were introduced.  In such cases, they do not
define the corresponding feature-test macro when emulating the earlier
standard, even though the feature is available.  A change has been made to
emulate that behavior.


11/16/18 [EDGcpfe/20121]
C++20: ADL and function templates that are not visible

In C++20 mode, argument-dependent lookup can now be used when calling
function templates that may not be visible when using an explicit
template argument list (see P0846R0).  This example from that paper
is now accepted.

  void g();
  namespace N {
    struct A {};
    template <class T> int f(T);
    template <class T> int g(T);
    template <class T> int h(T);
  }
  int x = f<N::A>(N::A());  // OK: lookup of f finds nothing,
                            // f treated as template name
  int y = g<N::A>(N::A());  // OK: lookup of g finds a function,
                            // g treated as template name


11/16/18 [EDGcpfe/20377] 
Assertion failure in arg_list_is_type_dependent with designated initializer

A template declaration containing a designator would sometimes cause an 
assertion failure in arg_list_is_type_dependent.  For example:

  struct A {
    int x;
  };

  template < class T >
  auto f ( T x ) -> decltype ( new auto ( A ( { .x = 0 } ) ) );

This is now fixed.


11/15/18 [EDGcpfe/17926,EDGcpfe/20176,EDGcpfe/20373,EDGcpfe/20470]
Default constructor not correctly inherited

The front end previously did not correctly handle user-declared default
constructors.  For example:

  struct B { B(); };
  struct D: B {
     using B::B;  // Did not correctly inherit B's default constructor.
     D(D&&);
  };
  D d{};  // Previously an error.  Now okay.

That is now fixed.


11/15/18 [EDGcpfe/20450]
GNU/Clang compatibility: Standard attributes on namespaces

In GNU C++ mode with gnu_version >= 60000 or Clang emulation mode when
clang_version >= 60000 the front end now allows standard attributes to appear
on namespaces.  See the Changes entry for EDGcpfe/16270.


11/15/18 [EDGcpfe/20449]
GNU/Clang compatibility: using attribute prefix

In GNU C++ mode with gnu_version >= 70000 or Clang emulation mode when
clang_version >= 60000 the front end now enables the use of a "using" prefix in
an attribute specification.  When C++17 mode is not enabled, a warning is
issued for the first "using" attribute prefix that appears outside a system
header.


11/15/18 [EDGcpfe/20306]
Incorrect cleanup list with overlapping temporaries in some configurations

In lowering configurations where GENERATE_EH_TABLES is FALSE, in cases
involving destruction of temporaries in overlapping lifetimes, the cleanup
state could be incorrect.  A change has been made to address this.
For example (with --c++11):

  #include <initializer_list>
  struct A {
    A(int);
    ~A();
  };
  struct S {
    ~S();
  };
  struct C {
    C(std::initializer_list<A>);
    ~C();
  };
  void f() {
    C c { 0 };
    S s;
  }


11/15/18 [EDGcpfe/20457]
GNU compatibility: Capturing *this

In GNU C++ mode with gnu_version >= 70000 the front end now enables capturing
"*this" in C++11 mode.  When C++17 mode is not enabled, a warning is issued for
the first lambda capturing "*this" that appears outside a system header.


11/15/18 [EDGcpfe/20460]
GNU compatibility: Selection statements with initializers

In GNU C++ mode with gnu_version >= 70000 the front end now enables selection
statements with initializers (see entry for EDGcpfe/17414) even when C++17 mode
is not enabled.  A warning is issued for the first such case appearing outside
a system header.


11/15/18 [EDGcpfe/20456]
GNU compatibility: Fold-expressions

In GNU C++ mode with gnu_version >= 60000 the front end now enables fold
expressions in C++11 mode.  A warning is issued for the first fold expression
appearing outside a system header if C++17 mode is not enabled.


11/14/18 [EDGcpfe/19073,EDGcpfe/17331]
Spurious error on decltype in lambda parameter list

In modes where generic lambdas are supported (e.g., --c++14), a spurious
error could occur if a decltype operator referred to a previous parameter
of the lambda declarator.   This could also occur in some contexts if
the decltype referred to "this".  Now fixed.

  int main() {
    auto l = [](int a, decltype(a) b) {};
  }
  class A {
    void B() { [](decltype(this) param) {}; }
  };


11/14/18 [EDGcpfe/20433]
Assertion in diagnose_duplicate_union_field_init

In certain cases, an invalid declaration of an anonymous union member
would cause an assertion failure.  For example:

  union A {
    int x;
    union { int A{} ; };  
    union { int z = 37; };
  };

The invalid declaration of int A within an anonymous union member of union A 
would lead to an assertion failure when int z is declared.  This has now 
been fixed.


11/13/18 [EDGcpfe/20463]
Boolean bit field conversions during constexpr evaluation

Consider:

  struct S { bool b: 1; };
  constexpr bool g() {
    S s{};
    s.b += 2;
    return s.b;
  }
  static_assert(g());

Previously this failed, because during the evaluation of "s.b += 2", the
constexpr interpreter discarded all but the least significant bit of the
result of the addition before normalizing the boolean value.  That is now
fixed.


11/13/18 [EDGcpfe/20361]
Default initialization of inline static data members

The front end previously failed to perform default initialization for an
inline static data member with no explicit initializer.  This is now fixed.
For example, with --c++17:

  struct A {
    A() : i(53) { }
    int i;
  };
  struct B {
    static inline A a;
  };
  int main() {
    return B::a.i != 53;  // Previously returned 1
  }


11/9/18  [EDGcpfe/20424]
IA-64 ABI: non-unique names for alternate entry points in some configs

In IA-64 ABI configurations where DEFAULT_MAX_MANGLED_NAME_LENGTH is not 0,
the mangled names for alternate entry points (e.g., complete and subobject
constructors) would be the same in cases where the non-truncated mangled
name exceeds DEFAULT_MAX_MANGLED_NAME_LENGTH.  Now fixed.


11/1/18  [EDGcpfe/20268]
Local static variable of static function template incorrectly given weak
linkage

In configurations that use lowering, a local static variable in a static
function template had incorrectly been promoted out of the function and
given weak linkage (in configurations where
LINKER_CAN_DISCARD_DUPLICATE_DEFINITIONS is TRUE).  Now fixed.  For example:

  template <typename> static void *f() {
    static int x;
    return &x;
  }
  void *(*fp)() = f<int>;


10/31/18 [EDGcpfe/20409]
Return move optimization

Consider:

  struct S {
    int v;
    constexpr S(const float&): v(1) {}
    constexpr S(float&&): v(2) {}
    constexpr int val() const { return v; }
  };
  constexpr S g(float x) {
    return x;  // Now uses the S(float&&) constructor.
  }
  static_assert(g(3).val() == 2, "");  // Previously failed.  Now okay.

The rules for "move optimization" in return statements require "return x;" to
call the S(float&&) constructor.  However, previously, the front end failed to
consider move optimization if the returned expression does not have a class
type (causing the above assertion to fail).  That is now fixed (and the example
is now accepted).


10/30/18 [EDGcpfe/20385]
Assertion failure in prep_list_initializer

Consider (in GNU C++ mode or C++20 mode):

  #include <initializer_list>
  typedef std::initializer_list<int> T;
  template < class T > auto f ( T ) -> decltype ( T { . x = "abc" } ) ;
  template <class T> auto f(T) -> decltype(T{37}) {return T{37};}
  int main()
  {
    if (f(T()).begin()[0] != 37)
      return 1;
    return 0;
  }

Previously this triggered an internal error in prep_list_initializer because
the front end did not correctly record the presence of a designator in one of 
its internal structures (an_init_component).  That is now fixed.


10/30/18 [EDGcpfe/20395]
Values for __has_cpp_attribute macro

Three changes have been made to the values of the __has_cpp_attribute
preprocessing operator: all values now have a "L" suffix, the value of
__has_cpp_attribute(nodiscard) has been updated to 200809L (previously 200709),
and __has_cpp_attribute(likely) and __has_cpp_attribute(unlikely) now have
the value 201803L in C++20 mode (previously it had been 1).


10/28/18 [EDGcpfe/20391]
Precompiled headers and #line directives

Formerly, #line directives suppressed the creation of PCH files.  This
has been modified so that only #line directives in the primary source file
prevent the generation of a PCH file.


10/27/18 [EDGcpfe/20387]
GNU/clang C++ compatibility: constexpr if enabled in non-c++17 modes

Constexpr if statements are now enabled in g++ mode (gnu_version >= 70000)
and clang mode (clang_version >= 40000) for C++11 and C++14 modes.  A
warning is issued on the first use.

  int main() {
    if constexpr (1) {}
  }


10/27/18 [EDGcpfe/20390]
Missing position in diagnostic for non-constant "if constexpr"

In some cases a null source position was used as the position for the
"expression must have constant value" error for an invalid "if constexpr".
Now fixed.

  void f(int i) {
    if constexpr (i) { }
  }


10/26/18 [EDGcpfe/20386]
C++-generating back end: #pragma moved to before case label

In C++-generating configurations, a #pragma that appears in the source
code after a case label had mistakenly been moved to before the case label
in the generated C++.  For example:

  void f(int c) {
    switch (c) {
      case 0:
#pragma omp parallel for
        for(int i=0; i<10; ++i);
    }
  }


10/26/18 [EDGcpfe/20327]
Missing decl_position for string literals

Previously, the front end did not record the positions of string literals
appearing as elements in aggregate initializers.  Now it does.  For example:

  struct S { char const *p; } s = { "msg" };

In this example, the position of "msg" is now recorded in the 
source_corresp.decl_position member of the ck_string entry. Furthermore, if 
EXTRA_SOURCE_POSITION_IN_IL is set to TRUE, the end position of the literal 
is recorded in the end_position member of the ck_string entry.


10/25/18 [EDGcpfe/20370]
Uninitialized variable used in remove_hypothetical_default_guide

A variable could be used without being previously initialized in some
cases in remove_hypothetical_default_guide.  Now fixed.


10/25/18 [EDGcpfe/20312]
C++-generating back end: Out-of-order class template specialization with
TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS

Consider:

  template<typename> struct S { void f(); };
  struct B {
    template<typename> void m() {
      S<int> s;
      s.f();
    }
  } b;
  int main() {
    b.m<float>();
  }

In configurations using the C++-generating back end with the configuration
macro TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, C++ source
code is generated that attempts to model implicit instantiations as explicit
specializations.  In the example above, however, the explicit specialization
for S<int> was emitted after a use of S<int> (which is invalid).  That is now
fixed.


10/25/18 [EDGcpfe/20360]
Internal error when clang mode is used with gnu_version < 40700

An internal error could occur (in class_template_declaration) when clang
mode is combined with a gnu_version less than 40700.  This occurred during
the front end initialization process (i.e., an empty source file is
sufficient to reproduce the issue).  Now fixed.


10/25/18 [EDGcpfe/20358]
Failure to inherit trivial default constructor

Consider:

  struct B {};  // Has a trivial default constructor.
  struct D: B {
    using B::B;
    D(int);
  } d;  // Previously an error because the default constructor of B was
        // not inherited.  Now okay.

The front end previously issued an error because it failed to inherit the
trivial default constructor of B for D.  That is now fixed.


10/24/18 [EDGcpfe/20330]
Attempt to initialize a field in a union that doesn't exist should elicit 
an error

When combining list-initialization and designated initializers, the front
end would not always detect an invalid designated initializer, resulting in
incorrect IL and output from the C-generating back end that could not be 
compiled.  For example:

  struct A {
    int x;
    union {
      int y;
    };
    int z;
  };
  A a = { 37 , { . x = 47 } , 59 } ;

In the example above, designator .x is a part of the initializer for the
anonymous union member.  Previously, the front end would accept this.  With 
this fix, the front end will report an error.


10/23/18 [EDGcpfe/20302]
Floating-point status flags in C++ mode

The C99 STDC FENV_ACCESS pragma, which allows the program to check the
status of floating-point operations, was added to C++11.  One effect of
this change is that floating-point operations, when access is enabled, are
considered to have side effects, while previously they were considered to
be side-effect free.  The front end now supports this pragma and the
associated change to determination of side effects in C++11 and later
modes.  The other two floating-point STDC pragmas, FP_CONTRACT and
CX_LIMITED_RANGE, are also now accepted in those modes, although they have
no effect other than being recorded in the IL.  Gcc does not support these
pragmas, so they remain unrecognized in GNU emulation modes.  Clang does
not recognize the CX_LIMITED_RANGE pragma, and it does not support the ON
argument for FENV_ACCESS; the front end also emulates these behaviors in
clang mode.  For example, with --c++11, the following pragma is not
recognized in g++ mode, the ON argument is rejected (with a discretionary
error) in clang mode, and it causes floating-point operations to be treated
as having side effects in other emulation modes:

  #pragma STDC FENV_ACCESS ON


10/23/18 [EDGcpfe/19740,EDGcpfe/20329]
Spurious diagnostics on constexpr and auto static data member definitions

The front end previously issued spurious errors on certain static data member
definitions involving constexpr and/or auto specifiers.  For example:

  struct S {
    static const int x;
    static int y;
  };
  constexpr int S::x = 42;  // Previously an error.  Now okay.
  auto S::y = 42;  // Previously an error.  Now okay.


10/19/18 [EDGcpfe/20303]
Support configurations where GNU_EXTENSIONS_ALLOWED is TRUE and
C99_IL_EXTENSIONS_SUPPORTED is FALSE

Changes have been made to support a configuration where GNU_EXTENSIONS_ALLOWED
is TRUE but C99_IL_EXTENSIONS_SUPPORTED is FALSE.


10/19/18 [EDGcpfe/18238,EDGcpfe/19997]
Lowering and strict expression evaluation ordering

As of the 5.0 release, the front end indicates the order of evaluation of
operands for certain expressions in C++17 mode (see the Changes entry for
EDGcpfe/17701).  Expressions introduced by lowering, however, had not set
the order of evaluation flags.  A change has been made to set those flags
properly.


10/18/18 [EDGcpfe/20103]
References sometimes not correctly folded

Consider:

  int arr[2];
  void g() {
    auto &[ x, y ] = arr;  // (1)
    static_assert (&x == &arr[0]);  // Previously an error.  Now okay.
  }

Line (1) initializes an unnamed reference to a global variable arr and since
that reference is immutable, it should be usable in constant-expressions such
as the one in the static_assert.  However, the front end previously failed to
evaluate such constant-expressions in some configurations, which in turn
resulted in spurious errors.  That is now fixed.


10/18/18 [EDGcpfe/20241]
Spurious ambiguity in matching of partial specialization of variadic template

Version 4.14 introduced a regression in the matching of variadic partial
specializations that caused an ambiguity in cases such as the one below.
Now fixed.

  template<class... Ts> class A {};
  template <class A, class... Us> struct V;
  template <class... Ts, class... Us> struct V<A<Ts...>, Us...>;
  template <class... Ts, class U, class... Us> struct V<A<Ts...>, U, Us...> {
    static bool f(){ return true;}
  };
  int main() {
    V<A<>, int>::f();
  }


10/18/18 [EDGcpfe/20296]
GNU compatibility: abi_tag mangling with parameter types

It appears that GCC considers abi_tag attributes that are applied to parameter
types so a change has been made (when ABI_COMPATIBILITY_VERSION >= 510) to
emulate this behavior.  For example, with --gnu_version 80000:

  struct __attribute__((__abi_tag__("cxx11"))) string {};
  template <typename T> struct function{
    void operator()();
  };
  struct C {
    static function<void(string)> foo;
  };
  void f() {
    C::foo();  // Had been mangled as _ZN1C3fooE, now _ZN1C3fooB5cxx11E
  }


10/18/18 [EDGcpfe/20244]
Microsoft compatibility: Enabling C++20 features

A new command-line option, --ms_c++20, has been added to emulate the /std:c++20
option that Microsoft Visual Studio provides.  This option is only available
when microsoft_version >= 1920.


10/17/18 [EDGcpfe/20224]
Microsoft compatibility: spurious error in default template argument

In Microsoft mode, a dependent name followed by a "<" could incorrectly
be treated as a template name during disambiguation processing, resulting
in a spurious error.  Now fixed.

  template<bool b, class T = void> struct B {
    using t = T;
  };
  template <class T> class C {
    static const int i = 0;
  };
  struct X {
    template<class T, class U = C<T>, typename W = B<(U::i < 0)>::t> X(T);
  };

10/17/18 [EDGcpfe/20095,EDGcpfe/20182]
Spurious error on array structured binding in GNU/Clang modes

Consider:

  int a[2] { 1, 2 };
  auto [x, y] = a;  // Previously an error in GNU/Clang mode.  Now okay.

Previously this elicited a spurious error from the front end because the
emulation of a GNU extension for array variable initialization interfered with
the implementation of structured bindings.  That is now fixed.


10/17/18 [EDGcpfe/20281]
Error in converting --mmap_address argument

The --mmap_address command-line option (introduced by EDGcpfe/11484) takes
a numeric argument, but if that numeric argument was specified in base 16
(i.e., with 0x or 0X), and included the digits a-f or A-F, the resulting
address was incorrect.  Now fixed.


10/16/18 [EDGcpfe/20135]
Lookup in namespace scope variable templates

In the instantiation of a namespace scope variable template, a namespace
member with the same name as a template parameter of the variable template
could incorrectly be preferred by name lookup resulting in the template
parameter being hidden.  Now fixed.

  namespace N {
    template<typename> struct A { static constexpr int value = 1; };
    template <class T> struct U { using u_type = T; };
    template <class U> constexpr bool A_v = A<typename U::u_type>::value;
  }
  int main() {
    const bool b = N::A_v<N::U<int>>;
  }


10/16/18 [EDGcpfe/20004,EDGcpfe/20273]
C++20: Lambdas with template parameter lists

In C++20 mode (and --ms_c++latest mode with microsoft_version >= 1920), the
front end now implements support for lambda expressions that include a template
parameter list (as per the standardization committee's paper P0428R2).  For
example:

  constexpr auto lm = []<typename T>(T t, int i) { return t+i; };
    // Now accepted in C++20 mode.
  static_assert(lm(3, 4) == 7);


10/16/18 [EDGcpfe/19403]
Assertion failure in aggr_init_field_designator with nested unnamed structs 
and malformed designated initializer

In certain cases, an invalid designator within an anonymous union or a
(nonstandard) anonymous struct would cause an assertion failure.  For 
example:

  struct S {
    struct {     // #1
      struct {   // #2
        unsigned int a;
      };
      unsigned int b;
    };
  };

  struct S s = { { {
    .b = 1 
  } } };

The above designator is within the initializer for #2, but the designated 
name does not exist within that struct.  This would previously cause an 
assertion failure in aggr_init_field_designator.  The front end now detects 
the invalid designator and issues an error.


10/15/18 [EDGcpfe/20277]
C++-generating back end: qualified pseudo-destructor calls

In C++-generating back end configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, a
pseudo-destructor call was sometimes incorrectly put out in a generated
explicit specialization as a qualified-id in which the
nested-name-specifier did not match the type name appearing in the
pseudo-destructor name.  For example, given:

  struct A { };
  struct B { };
  template <int I> struct C {
    typedef B t;
  };
  template <typename T> struct D { enum { v = 0 };};
  template<typename T> struct E {
    ~E();
    void f(T*);
    T* g();
  };
  template<typename T> E<T>::~E() {
    f(g());
  }
  template<typename T> void E<T>::f(T* p) {
    p->~T();
  }
  class F {
    typedef A Data_t;
    E<Data_t> m_vector;
  };

the generated explicit specialization for E<A>::f(A*) previously contained
the incorrect expression

  p->A::~Data_t();

This is now fixed; that line is now generated as:

  p->A::~A();


10/15/18 [EDGcpfe/20038,EDGcpfe/20123]
Prohibit aggregates with user-declared constructors

Prior to C++20, the presence of a user-provided constructor in a class 
disqualified it as an aggregate.  However, explicitly defaulted and
deleted constructors are not considered to be "user-provided", only 
"user-declared".  C++20 extends the restriction to apply to user-declared 
constructors as well, and the front end now implements this rule in 
C++20 mode.  For example:

  struct X {
    int i, j;
    X() = delete;
  };
  int main() {
  X x{}; // zero-initializes i and j before C++20, ill-formed in C++20
  }


10/14/18 [EDGcpfe/19158,EDGcpfe/20254]
Generic lambda instantiation and local scope using-directives

If a generic lambda was declared in a local scope and the generic lambda
depended on an enclosing local-scope using-directive, name lookup in the
instantiation of the lambda could produce an incorrect result.  Now fixed.

  namespace N {
    namespace O { using O_type = int; }
    void f() {
      using namespace O;
      auto lam = [&] (O_type , auto) {};
      for (int i = 0; ; i++) {
        lam(0, 0);
      }
    }
  }


10/12/18 [EDGcpfe/18994,EDGcpfe/19342,EDGcpfe/20242]
Issue with prototype instantiations of nested class members and deferral
of function prototype instantiations

When function prototype instantiations are being deferred (e.g., in g++
mode in many configurations), if a function or function template was
defined in a nested class or a class template,  and that nested class
was defined outside of the enclosing class, lookup of template parameter
names of the enclosing class and pack expansions in the function template
could be processed incorrectly resulting in spurious errors.  Now fixed.

Example 1:

  template < typename T > T f(int);
  template <typename T> struct A { class B; };
  template <typename T> struct A <T>::B {
    template <typename ... Args> B(Args && ... args) : t{f<Args>(args)...}{}
    T t;
  };
  int main() {
    A<int>::B(0);
  }

Example 2:

  template <class T> struct A {
    struct Inner;
    Inner foobar;
  };
  template <class U> struct A<U>::Inner {
    template <int I> using type = U;
    Inner() {
      type<0>();
    }
  };
  A<int> a;


10/12/18 [EDGcpfe/20025]
C++20: "likely" and "unlikely" standard attributes

The "likely" and "unlikely" attributes (meant to provide hints to a back end to
aid in optimization) are now accepted on labels and statements (see P0479R5).
The front end accepts and validates these attributes but takes no action on
them.  For example, with --c++20:

  void f(int i) {
    switch (i) {
      case 1: 
        goto done;
      default:
        [[unlikely]]
        break;
    }
  [[likely]] done:;
  }


10/12/18 [EDGcpfe/20001,EDGcpfe/20031,EDGcpfe/20272,EDGcpfe/20275]
C++20: Explicit by-copy capture of "this"

Consider:

  struct S {
    void f(int i) {
      [=, this]{}();  // Now okay in C++20 mode.
    }
  };

The default capture mode is "by copy" and applies to the "this" pointer;
making it explicit when a default is specified is invalid in C++17 and earlier
standards.  In the current draft for the next standard (expected to be C++20)
this became valid through the adoption to the committee's paper number P0409R2.
The front end now implements that relaxation in C++20 mode (and --ms_c++latest
mode with microsoft_version >= 1920).  Furthermore, in those same modes, the
implicit by-copy capture of "this" is warned about (because the draft for the
next standard deprecates that feature).


10/11/18 [EDGcpfe/20037,EDGcpfe/20124]
C++20: Constexpr virtual functions

In C++20 mode (and --ms_c++latest mode with microsoft_version >= 1920), the
front end now implements support for constexpr virtual functions as per the
standardization committee's paper P1064R0.  For example:

  struct B {
    constexpr virtual int f() const { return 1; };  // Okay in C++20 mode.
  };
  struct D: B {
    constexpr virtual int f() const { return 2; };  // Okay in C++20 mode.
  };
  constexpr int g(B const &p) { return p.f(); }
  static_assert(g(B{}) == 1);  // Okay in C++20 mode.
  static_assert(g(D{}) == 2);  // Okay in C++20 mode.


10/11/18 [EDGcpfe/20240]
Sequencing diagnostics re-enabled

The changes for C++17 evaluation ordering (see EDGcpfe/17701) had disabled
sequencing diagnostics.  Those diagnostics are now re-enabled and updated to
reflect the C++17 rules.  For example, with --c++17 --remarks:

  void f(int i, int j) {
    (i++, j) = i++;     // no longer gets a sequencing remark
    f(i++, i++);        // still gets a sequencing remark
  }


10/11/18 [EDGcpfe/20234]
Friend function lookup with deferral of function prototype instantiations

When function prototype instantiations are being deferred (e.g., in g++
mode in many configurations), the lookup of names in member function
templates of non-template classes could incorrectly exclude friend
functions declared later in the class (or a nested class of the class).
Now fixed.

  template <typename T> class A {};
  struct B {
    template <typename T> static void f() {
      A<int> ptr;
      ptr.*g(C{});  // Formerly 'no matching instance of "g"'
    }
    struct C { friend int A<int>::* g(C); } ;
  };
  int main() {
     B::f<int>();
  }


10/11/18 [EDGcpfe/19996]
Inlining of routines with right-to-left expression evaluation order

The changes for C++17 evaluation ordering (see EDGcpfe/17701) are now reflected
in the inliner.  That is, when inlining a routine where right-to-left
expression evaluation is specified, the inliner will evaluate the arguments
to an inlined call from right-to-left.  For example (with --c++17):

  extern "C" int printf(const char *,...);
  struct A {
    A operator=(const A& a) { return a; }
  };
  int main() {
    A a;
    (printf("second\n"),a) = (printf("first\n"),a);
                                          // evaluation order is right-to-left
    (printf("first\n"),a).operator=((printf("second\n"),a));
                                          // evaluation order is left-to-right
  }


10/11/18 [EDGcpfe/20231]
Braced initialization of a scalar type

The front end previously issued a warning (an error in strict mode) in C++ 
when the initializer for a scalar member of an aggregate is enclosed in a 
single set of braces.  However, such initializers are well-formed since C++11.
A diagnostic is now issued only in C++03 mode and in GNU and clang C++ modes.  
For example:

  struct B { int x;};
  B b1 { .x {1} };    // Previously triggered a warning or error
  B b2 { {2} };       // Previously triggered a warning or error
  B b3 { .x {{1}} };  // Still triggers an error


10/10/18 [EDGcpfe/20249]
Spurious "nontype template parameter may not have class type" error

A spurious "nontype template parameter may not have class type" error
could be issued when a nontype template parameter has a type based on a
type template parameter (parameter n of B in the example below), and the
type used for the type template parameter is the instantiation of a
nonreal template (the type produced by a nonreal instantiation of E in
the example below).  Now fixed.

  struct A { static const bool v = true; };
  template <class T, T n> struct B {};
  template <typename> struct C { static const bool v = true; };
  template <bool> struct D { template <typename T> using G = T; };
  template <bool C, typename T> using E = typename D<C>::template G<T>;
  template <typename T> using F = B< E< C<decltype(T::v)>::v, bool >, false >;


10/10/18 [EDGcpfe/20229]
Invalid scanning of single digit followed by backslash or extended character

The changes for EDGcpfe/18278 (which optimize single-digit number tokens)
introduced a regression (in version 4.14) in some cases where a single digit
is followed by a universal character name or extended character.  For example:

  #define M(discard, ...) __VA_ARGS__
  int r = M(0\u1234'0, 42);  // Previously triggered spurious errors in
                             // C++14 mode.

That is now fixed.


10/10/18 [EDGcpfe/20243]
Lookup issue with generic lambdas and deferral of prototype instantiations

When function prototype instantiations are being deferred (e.g., in g++
mode in many configurations), the lookup of names used in generic lambdas
could incorrectly exclude certain namespace members.  Now fixed.

  template <typename _Tp> _Tp f();
  template <class T> class A {
    typedef bool value_type;
  };
  template <typename F> auto g(F&& f) -> decltype(f(3)) { return f(3); }
  template <typename F> struct B {
    using type = decltype(g(f<F>()));
  };
  template <typename F> struct C {
    typedef typename B<F>::type value_type;
  };
  template <typename F> A<typename C<F>::value_type>* h(F) {return nullptr;}
  namespace N { int i; }
  // Lookup of N::i failed
  auto l = h([](auto&& type) { h([](auto&& type) { return N::i; }); });


10/10/18 [EDGcpfe/20245]
Microsoft compatibility: Friend declarations and template names

Consider:

  template<typename T> class C {
    friend class C;  // In Microsoft mode, previously treated as
                     //   "template<typename> friend class C;".
  };                 // Now only when microsoft_version < 1800.

Previously, the friend declaration was treated as a friend template declaration
in all Microsoft C++ modes (see, e.g., the entry of 2/13/08).  Now, that
nonstandard behavior is only emulated when microsoft_version < 1800.  When
emulating more recent versions of MSVC++, the friend refers to the injected
class name (as per the standard specification).
  

10/10/18 [EDGcpfe/20252]
Trivial copyability and inheriting constructors

The front end sometimes mistook inheriting constructors for copy constructors
when determining whether a type is "trivially copyable" (e.g., as part of
determining whether a class type is a "POD" type).  For example:

  struct B {
    B() noexcept = default;
    B(int) noexcept {}
  };
  struct D: B {
    D() = default;
    using B::B; 
  };
  static_assert(__is_pod(D), "Unexpected");  // Previously failed.  Now okay.

This is now fixed.


10/10/18 [EDGcpfe/20263]
Clang C++ compatibility: Internal error when instantiating __make_integer_seq

An internal error could occur (in instantiate_make_integer_seq) if an
alias template was uses as an argument to __make_integer_seq.  Now fixed.

  template <int... I> struct A { };
  template <int N> struct B {
    template <typename, int... J> using C = A<J...>;
    using iseq = __make_integer_seq<C, int, N>;
  };
  B<1> b;


10/10/18 [EDGcpfe/18177]
Microsoft compatibility: dllimport static data member initializers

The front end no longer issues an error for a dllimport static data member with
an in-class initializer.  For example:

  struct __declspec(dllimport) S {
    static constexpr int N = 32;  // Previously an error.  Now okay.
  };


10/9/18  [EDGcpfe/20246]
C++-generating back end, clang compatibility: friend template declarations in
class 

When a nested class template is named by a friend declaration in the
definition of a class template, in configurations in which template
definitions are generated from the prototype instantiation IL the
C++-generating back end previously put out an unnecessary "template"
keyword in the qualified-id.  Clang does not accept an unnecessary
"template" keyword in that context.  The front end has now been changed
to put out the "template" keyword only when the name will be followed by
a template argument list.  For example, with --clang:

  struct A {
    struct B {
      template<typename> struct C;
    };
  };
  template<typename> class D {
    template<typename> friend class A::B::C;  // Previously generated as
                                              // A::B::template C
  };


10/9/18  [EDGcpfe/20042]
C++20: Conditional explicit

In C++20 mode, the front end now implements conditional explicit specifiers
(aka. "explicit(bool)").  For example:

  template<typename T> struct S {
    explicit(sizeof(T) > sizeof(int)) S(int x);
  };
  
  S<char> s{3};  // Okay.
  S<long long> s = 3;  // Error: S(int) constructor is not a candidate
                       // (assuming sizeof(long long) > sizeof(int)).

That language feature was added by the C++ standardization committee's paper
number P0892R2.  It is also enabled with the --ms_c++latest option when
microsoft_version >= 1920.  (The upper limit for the --microsoft_version
option has been raised from 2000 to 3000.)


10/9/18  [EDGcpfe/20130]
Microsoft compatibility: use of injected class name in typename specifier

The Microsoft compiler finds the injected class name in a typename
specifier even though the typename specifier is not supposed to influence
lookup.  We now emulate this behavior in Microsoft mode.

  template <typename T> class A {
    A& f(const A&);
  };
  template <typename T> typename A<T>::A& A<T>::f(const A&){}


10/8/18  [EDGcpfe/20251]
Disqualify routines and variables with "auto" type as candidates for module ID

When searching for a candidate for the module ID (used to ensure unique names),
the front end had previously considered routines and variables with "auto"
type.  If such an entity had met the other criteria for being a module ID,
the entity would be mangled, but the mangled name for such an entity would
not reflect the name after the type has been resolved and such early name
mangling could also have side-effects, such as missing references to
abi_tag attributes (as these are computed only the first time a name is
mangled).  For example (with --gnu_version 80000):

  inline namespace __cxx11 __attribute__ ((__abi_tag__ ("cxx11"))) {
    class A;
  }
  template <typename> struct X {
    A mf();
  };
  auto f() {
    return &X<int>::mf;   // Previously _Z1fv, now _Z1fB5cxx11v
  }


10/8/18  [EDGcpfe/20247]
Internal error in i_copy_dynamic_init

In some odd cases, as a result of the changes for EDGcpfe/19804 (introduced
in version 5.0), the front end can trigger a spurious expect_error failure.
For example (with --c++11):

  template <class T> struct A {};
  template <class T> struct S {
    typedef A<T*(void)> X;
    static void f();
  };
  struct C {
    C() { static int x = 0; }
    int i{0};
  };
  void f() {
    S<int>::f();
  }


10/3/18  [EDGcpfe/19063,EDGcpfe/19516,EDGcpfe/20210]
Template template parameter substitution issue

If a template template parameter was used in an alias template declaration,
and the alias template was used as a template template parameter, a
substitution error could occur if the template template parameter was
instantiated as part of the evaluation of a default template argument
during template argument deduction.  Now fixed.

  template <bool b> struct A {
    static constexpr bool v = b;
  };
  template <bool b, class... T> struct B {
    using type = int;
  };
  template <template <class...> class TT1, class... T> struct C {
    template <template <class...> class TT2, class = TT2<T...>>
      static A<true> f(int);
    template <template <class...> class> static A<false> f(...);
    using type = decltype(f<TT1>(0));
  };
  template <class T, class U> using D = typename B<T::v>::type;
  C<D, void, int> c;


10/3/18  [EDGcpfe/15168,EDGcpfe/20235]
String literal operator templates

C++ Committee document P0424R0 proposed the addition of string literal
operator templates to the language.  Although this feature was not adopted
into the C++ Standard, g++ and clang have implemented it as an extension.
The front end now also supports this feature in C++14 and newer g++ and
clang modes with gnu_version >= 40900.  For example, with --c++14
--gnu_version=70200:

  template<typename T, T ...chars> int operator"" _x(); 
  int i = L"ab"_x;  // calls operator""_x<const wchar_t, L'a', L'b'>()


10/3/18  [EDGcpfe/20239]
Microsoft compatibility: use of universal characters in identifiers in C mode

A change has been made to accept universal characters in Microsoft C mode
(previously these were accepted only in C99 and C++ modes).


10/3/18  [EDGcpfe/20238]
Value of __cplusplus in GNU emulation mode with --ms_extensions

The value of the __cplusplus macro had been set to 199711L in GNU emulation
mode with --ms_extensions (as it is in Microsoft emulation mode), but now
is set to the value that it would have without --ms_extensions.


10/2/18  [EDGcpfe/19942]
C++-generating back end, GNU compatibility: non-dependent member function
calls via dependent bases

Beginning with version 7.3, g++ no longer accepts "this->" as part of a
member function call to a non-dependent member function of a base class
inherited via a dependent base class.  The C++-generating back end
previously generated such calls in configurations in which template
definitions are generated from the prototype instantiation IL, but it no
longer does so when gcc_is_generated_code_target is TRUE and
gnu_target_version_number is 70300 or larger.  For example, with
--gnu_version=70300 --parse:

  struct A { template<typename T> void f(); };
  template<class T> struct B : A { };
  template<class T> struct C : B<T> {
    void f() {
      A::template f<bool>();  // Previously generated as "this->A::..."
    }
  };


10/2/18  [EDGcpfe/20003,EDGcpfe/20119]
C++20: Designated initialization

In C++20 mode, the front end now accepts designated initializers.  This
feature was added to the working paper for the next standard through paper
number P0329R4.  For example:

  struct A { int x; int y; int z; };
  A a{.y = 2, .x = 1}; // Error: designator order does not match declaration
                       // order.
  A b{.x = 1, .z = 2}; // Okay: b.y initialized to 0.


10/2/18  [EDGcpfe/20222]
Abort on flexible array member with default member initializer

The front end accepts flexible array members (a C99 feature) in Microsoft C++
mode.  Previously, if such a member also had a default member initializer, the
front end aborted with an assertion failure in aggr_init_array.  For example:

  struct S { int k[] = {}; };  // Previously aborted in Microsoft C++ mode.
                               // Now an error.

This is now fixed: An ordinary error is issued.


10/1/18  [EDGcpfe/19828,EDGcpfe/20117]
Microsoft compatibility: Standard-conforming preprocessing

New versions of MSVC will offer a choice between the traditional Microsoft
preprocessor and a preprocessor that conforms to the C and C++ Standards.
The front end now provides a similar choice, controlled by the global
variable ms_std_preproc; when that variable is TRUE, the traditional
Microsoft preprocessor behavior is disabled.  That flag is controlled by
the new command-line option --[no_]ms_std_preprocessor, as well as by the
existing --[no_]ms_permissive (if --[no_]ms_std_preprocessor is not
specified).  The default continues to be to emulate the traditional
Microsoft preprocessor.


10/1/18  [EDGcpfe/20220]
Unbounded recursion with dllexport class with inheriting constructor template

In Microsoft C++ mode, the front end previously ran into unbounded recursion
(eventually aborting when running out of call stack storage) with the following
case:

  template<typename> struct B {
    template<typename T> B(B<T>) {}
  };
  struct __declspec(dllexport) D: B<int> {
    using B<int>::B;
  };

That is now fixed.


10/1/18  [EDGcpfe/20206]
Regression in old-style template template parameter matching

Version 5.0 added support for generalized template template parameter
matching (see EDGcpfe/18746).  Those changes inadvertently changed the
behavior of some cases that don't use the new rules.  This caused
examples like the one below to select an incorrect partial specialization.
Now fixed.  Note that this example also fails using the new matching rules.
That will be addressed by a subsequent change.

  template <typename T, typename ... Ts> struct A {};
  template <typename T> struct B;
  template <typename T> struct B {};
  template <template <typename TTP1> class T, typename U> struct B<T<U>> {
    static const int x = T<int>::value;
  };
  B<A<A<int>>>  b;


10/1/18  [EDGcpfe/20226]
Excessive memory use by constexpr interpreter after evaluation failure

In some cases, the constexpr interpreter used an invalid and very large object
size to allocate storage, thus causing excessive memory use.  The invalid size
was the result of an evaluation failure that was not caught early enough.  That
problem is now fixed.


9/30/18  [EDGcpfe/20225]
Clang compatibility: __has_feature(cxx_exceptions)

The change for EDGcpfe/19478 (in version 5.0) incorrectly categorized
__has_feature(cxx_exceptions) as applicable only in C++11 and later modes,
although it is, in fact, supported in all versions of C++.  This is now
fixed.  For example, with --clang --c++03 --exceptions:

  #if !__has_feature(cxx_exceptions)
  #error "Incorrect value"  // Previously executed
  #endif


9/28/18  [EDGcpfe/20089,EDGcpfe/20196]
Spurious error on use of lambda in constant-expression context

Consider the following example:

  auto make_lambda = [](auto v) {
    return [=]{ return v; };
  };
  constexpr auto zero = make_lambda(0);

This previously elicited a spurious error because the constexpr interpreter
failed to correctly initialize the inner lambda expression for the capture
of v.  That is now fixed.


9/28/18  [EDGcpfe/20219]
Exception specifications and operator new/delete in system headers

The changes for EDGcpfe/19210 (see entry of 7/18/18) caused the front end to be
a little stricter when checking the exception specification of an operator new
or operator delete declaration that redeclares an operator predeclared by the
front end.  That change is now relaxed not to apply to declarations that appear
in system headers.


9/28/18  [EDGcpfe/15904,EDGcpfe/16112,EDGcpfe/19693,EDGcpfe/20218]
Comparing function address constants to null pointer values

In nonstrict modes and in modes with constexpr support the front end now more
consistently folds comparisons using == or != when one operand is the address
of a function and the other operand is a null pointer value.  For example, in
GNU C mode:

  void f();
  int r = f ? 1 : 2;  // Previously an error.  Now okay.

(Functions with weak linkage are excluded from this treatment.)


9/27/18  [EDGcpfe/20204]
Selection statements with empty initializers

C++17 mode accepts selection statements with initializers (see the entry of
4/14/17 for EDGcpfe/17414 and EDGcpfe/17706).  However, the front end
previously failed to accept the case of an empty initializer:

  void f(bool b) {
    if (; b) {}  // Previously an error in C++17 mode.  Now okay.
  }

That is now fixed.


9/27/18  [EDGcpfe/20207]
Clang C++ compatibility: __func__, __FUNCTION__, and __PRETTY_FUNCTION__

In Clang mode, the static variables corresponding to __func__, __FUNCTION__,
and __PRETTY_FUNCTION__ are now declared "constexpr".  That enables use cases
like the following:

  int main() {
    constexpr char c = __func__[0];
  }


9/27/18  [EDGcpfe/20217]
Microsoft compatibility: value of std_version with --ms_c++* options

A change has been made to set std_version to the appropriate value when the
--ms_c++14 (201402), --ms_c++17 (201703) or --ms_c++latest (201703)
command-line options are specified.  As a result, the internal macros
cpp14_mode and cpp17_mode will now be TRUE in the appropriate cases.


9/27/18  [EDGcpfe/20061]
Microsoft compatibility: initializations of aggregate members in some modes

As a result of the changes for EDGcpfe/16219 (in version 4.10.1), some
Microsoft modes had issued spurious errors on initialization of aggregate
members.  That's the case with the following example (with
--microsoft_version 1914 --ms_c++17):

  struct A {
    A() = delete;
  };
  struct B {
    A a;
  };
  B b{};


9/27/18  [EDGcpfe/20216]
Spurious error on array declarator in generic lambda parameter declaration

The front end previously issued a spurious error on the following example:

  int x = [](auto [3]) { return 42; }((int*)nullptr); 

That is now fixed.


9/27/18  [EDGcpfe/20215]
Incorrect setting of is_std_alignof in expression nodes

The flag variant.sizeof_info.is_std_alignof in an_expr_node is supposed to
indicate whether a given alignment query was invoked using the standard
"alignof" operator or via one of the nonstandard implementation-specific
variants such as __alignof.  However, the flag was previously not set to
TRUE when the standard "alignof" keyword was seen.  This oversight
manifested itself in the output of the C++-generating back end in some
configurations.  This is now fixed.  For example, with --c++11:

  unsigned v = alignof(int); // Previously generated as __ALIGNOF__ in
                             // some C++-generating back end configurations


9/26/18  [EDGcpfe/20213]
C++-generating back end: assertion failure with decltype-specifier template
argument

Under some complex circumstances involving a template instantiated with an
argument that involves a decltype-specifier whose operand refers to a
function parameter, C++-generating back end configurations could abort with
an assertion failure (in get_param_for_param_ref).  This is now fixed.  For
example:

  template <class T> struct A {
    typedef T t;
  };
  template <class T> struct B { 
    typedef T t;
  };
  template <class T> struct C {
    typedef typename B<typename A<T>::t>::t t;
  }; 
  struct D { };
  template <class T> struct E {
    static constexpr bool v = true;	    
  };
  struct F {
    void f();
  };
  template <class T> struct G {
    template <class S> static auto g(S s)->typename C<decltype(s.f())>::t; 
    typedef decltype(g(T())) t; 
  };
  template <class T> struct H {
    static constexpr bool v = E<typename G<T>::t>::v;		
  };
  bool b = H<F>::v;  // Previously caused an abort, now okay


9/26/18  [EDGcpfe/19599]
Type of non-captured variable reference in lambda expression

Consider:

  void g() {
    float x;
    [=] {
      float one = 1.0F;
      decltype((x)) r = one;
    };
  }

Previously, the decltype construct (which decides the type of r) produced type
"float&": "float" because that is the type of x and a reference because "(x)"
is an lvalue.  Now, type "float const&" is produced instead: Even though x is
not captured, the expression "x" in the lambda is typed as if it were captured
(it is "const" because the lambda is not mutable).  This change implements the
rules of the committee's paper P0588R1.


9/26/18  [EDGcpfe/20208]
Invalid attribute check processing (assertion in apply_nodiscard_attr)

The internal check to see if a particular attribute is enabled in a particular
configuration/mode was incorrect and had resulted in some attributes being
allowed in modes where they shouldn't have been.  The case below (with
--c++11 --microsoft_v 1914 --no_microsoft) had resulted in an assertion
failure (in apply_nodiscard_attr) rather than an unrecognized attribute
diagnostic.

  [[nodiscard]] int f();


9/26/18  [EDGcpfe/20205]
maybe_unused attribute ineffective on parameters

The maybe_unused attribute had been ineffective on suppressing remarks
about an unused parameter.  Now fixed.  For example (with --c++17 --remarks):

  void f([[maybe_unused]] int a) {}


9/24/18  [EDGcpfe/16865]
Use of uninitialized value in scan_return_expression.

Under certain conditions, the function scan_return_expression could
dereference an uninitialized value.


9/25/18  [EDGcpfe/20209]
C++-generating back end, Microsoft compatibility: generated explicit
specializations returning reference or pointer to function or array

In C++-generating back end configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
generated code was not compilable by MSVC when a generated explicit
specialization of a function template has a reference or pointer to
a function or array as its return type.  This has now been fixed.  When
msvc_is_generated_code_target is TRUE, the C++-generating back end now
creates a typedef for the return type in such cases and uses the typedef in
the explicit specialization.  For example, given

  template<typename T> T&& f();
  void g() {
    f<void()>();
  }

the previous output from the C++-generating back end contained the
explicit specialization

  template<> void (&&f< void (void)> ())(void);

which resulted in a spurious error ("C2909: 'f': explicit instantiation of
function template requires return type") when the generated code was
compiled by MSVC.  The explicit specialization is now generated as:

  typedef void (&&__T12345678)(void);
  template<> __T12345678 f< void (void)> ();

which does not trigger the MSVC bug.


9/25/18  [EDGcpfe/19968,EDGcpfe/20091,EDGcpfe/20211]
GNU C++ compatibility: internal error on use of variable template

In g++ mode, an internal error could occur during the instantiation of a
member variable template with an in-class initializer.  The internal error
occurred in ensure_inclass_static_member_constant_initializer_is_scanned.
Now fixed.

  template <int> struct A {};
  struct B {
    template<typename T> static constexpr int v = 0;
    template<typename T> A<v<T>> f(T);
  };
  int main() {
    B b;
    b.f(1);
  }


9/25/18  [EDGcpfe/18858,EDGcpfe/19908]
Interpretation of "shift left" operator for signed values

The front end previously did not correctly check the operand and result of a
"shift left" operator.  Spurious errors could result from that flaw.  For
example:

  constexpr bool f(long long int n) { return n << 1; }
  constexpr bool x = f(1LL << 62);

Previously, an error was issued because the call to f attempts to shift a bit
into the sign position ("bit 63") of a signed integer type and that looks like
a form of overflow.  However, unlike other forms of signed overflow, the
standard permits this case if the unsigned operation would not overflow (it
doesn't in this case, since 1ULL << 63 is a valid "long long" value).  The
problem is now fixed (i.e., the case above is accepted; the value produced by
the evaluation of "n << 1" is the bit pattern of "1ULL << 63" reinterpreted as
a signed long long value).


9/24/18  [EDGcpfe/20195]
Spurious substitution errors in nested templates with decltype

The changes for EDGcpfe/18942 (version 5.0) introduced a regression in certain
complex cases involving nested templates with decltype constructs.  For example
(in C++14 mode):

  struct Z { static int const value = 0; };
  template<bool> struct B {};
  struct R {
    template<typename ...Ts> Z operator()(Ts&& ...) const;
  };
  struct A {
    template<typename X> auto operator()(X &&x) const {
      return R{}(x);
    }
  };
  template <typename P> struct D {
    template<typename T>
      auto f(T &&p)-> B<decltype(P{}(p))::value>;
  };
   
  void g() {
     D<A> d;
     d.f(Z{});  // Previously triggered an error about an unexpected type
  }             // being produced by instantiation of D<A>::f(Z&&).

This problem (which manifested itself in some uses of the Boost libraries) is
now fixed.


9/24/18  [EDGcpfe/17962,EDGcpfe/20184]
Abort on inheriting constructor in dllexport class

The front end previously failed to propagate the "dllexport" property of a
class type to an inheriting constructor declaration that it contains.  In turn,
that caused an internal error in force_definition_of_generated_exported_members
(class_decl.c).  For example (in Microsoft mode):

  struct B {
    template<typename T> constexpr B(T) {}
  };
  struct __declspec(dllexport) D: B {
    using B::B;  // Previously triggered an abort in class_decl.c.
  };

That is now fixed.


9/24/18  [EDGcpfe/16566]
Remove "access control not specified" remark.

The front end no longer issues a remark when access control is not specified.
The diagnostic can still be enabled with an option like 
"--diag_warning=missing_access_specifier".  For example, with --remarks:

  struct B {};
  struct S: B { // Previously a remark about B being public by default.
  };            // Now no diagnostic by default.


9/21/18  [EDGcpfe/20199]
GCC/Clang compatibility: value of __cpp_static_assert in C++17 mode

A change has been made to better emulate the value of the __cpp_static_assert
macro in GCC and clang modes.


9/21/18  [EDGcpfe/20076]
Missing virtual base class initialization with delegating constructors

In configurations where HANDLE_VIRTUAL_BASES_IN_SUBOBJECT_CTOR_DTORS is FALSE,
an optimization to avoid calling a cdk_delegation constructor when a delegating
constructor has no body had inadvertently left any virtual base classes
uninitialized, resulting in undefined behavior at run time.  Now fixed.
For example (with --c++14):

  struct A {
    A(int x) : m(x) {}
    int m;
  };
  struct B : virtual A {
    B(int x) : A(x) {}
    B() : B(76) {}
  };
  int main() {
    B b;
    return !(b.m == 76);
  };


9/21/18  [EDGcpfe/20193]
Internal error on specialization of member variable template

Version 5.0 introduced an internal error (in record_specialization) if
a nonreal instantiation of the variable template was done before the
specialization.  Such a nonreal instantiation is an artifact of a
partial specialization declaration, so the presence of the partial
specialization in example below is one way in which the problem could
result.  Now fixed.

  template <typename T> struct B {
    template <typename U> static const U v = 0;
    template <typename U> static const U v<U*> = 1;
  };
  template <> template <typename U> const U B<int>::v = 2;


9/20/18  [EDGcpfe/20190]
GNU C++ compatibility: old g++ emulation causes rejection of valid code

Earlier versions of g++ incorrectly accepted some incorrect out-of-class
definitions of members of a class template.  For example:

  template <class T, class V> struct A {
    struct B { void f(); };
  };
  template <class T, class V> void A<T, int>::B::f() { }
//                                      ^  should be V

This emulation caused us to reject some valid code.  This was fixed in g++
4.3, so this emulation is now only done when gnu_version < 40300.  As
a result, the following example no longer results in an error in g++ mode.

  template <typename T> struct A {
    struct B { template <typename U> A<U> f(); };
  };
  template <typename T> template <typename U> A<U> A<T>::B::f() {}



9/20/18  [EDGcpfe/20183]
GCC/Clang compatibility: expressions in asm statements

A "::" token that appears as a namespace delimiter in an expression in an asm
statement had been parsed incorrectly, leading to a spurious error (and in some
cases, an infinite number of errors).  Now fixed.  For example (with --g++):

  int x;
  void f() {
     __asm__("" : : "n"(::x));
  }


9/20/18  [EDGcpfe/19959]
Clang compatibility: Clang 7.0.0 builtins

Support for builtins provided by clang 7.0.0 is now included.


9/19/18  [EDGcpfe/19949]
C++-generating back end: inherited constructor from dependent base

In configurations in which template definitions are generated from the
prototype instantiation IL, when msvc_is_generated_code_target is TRUE, the
C++-generating back end sometimes put out a using-declaration for an
inherited constructor from a dependent base class using different names for
the class and for the nested-name-specifier.  This is now fixed.  For
example, with --microsoft --parse_templates:

  template <class T> struct derived : T {
    using base_type = T;
    using base_type::base_type;  // Previously generated as "base_type::T"
  };
  struct base {};
  derived<base> x;


9/19/18  [EDGcpfe/20154,EDGcpfe/20166]
Taking the address of a dependent variable template instance

While processing a template declaration, the front end sometimes treated a
dependent reference of a variable template as non-dependent.  This could
result in an internal error (in check_for_nonreal_instance) in configurations
with EXPENSIVE_CHECKING enabled.  In this example, it could also result in
a spurious "declaration is incompatible" error in g++ mode.  Now fixed.

  template <typename T> T v {};
  template <typename T> struct A {};
  template <typename T> auto& f = v<A<T>>;
  int main() {
    f<int>;
  }


9/18/18  [EDGcpfe/19600,EDGcpfe/20114]
Structured bindings and "get" accessors

The decomposition of class types through structured bindings can be customized
through "get" accessors.  Such accessors can be members of the class to be
decomposed or they can be namespace-scoped templates (found through argument-
dependent lookup).  Originally, the member case was considered as soon as the
class to be decomposed contained a declaration of a member named "get": If that
member was not a template with a leading nontype template parameter, an error
ensued when the decomposition operations attempted to evaluate e.get<i>() for
the unnamed variable e underlying the structured binding declaration.  The
standardization committee later revised that rule to ignore "get" members
unless at least one of the members is a function template with a leading
nontype template parameter.  The revised rule was introduced through paper
P0961R1.  The front end now implements the revised rule, except in modes
corresponding to compilers that do not yet implement the new rule.


9/18/18  [EDGcpfe/20162]
GNU compatibility: PCH issue with system_header pragma

If an include file contained a "#pragma GCC system_header" directive, and
that file was not found as a "system include" (i.e., via --sys_include),
an internal error could occur if that compilation produced a PCH file that
was later consumed.  Now fixed.


9/18/18  [EDGcpfe/20145]
Inline static data members with deduced types

The front end previously rejected an inline static data member with a
deduced type if the initializer is not a constant expression.  This is now
fixed.  For example, with --c++17:

  struct wrapper {
    wrapper() {}
  };

  struct wrapped_object {
    inline static auto y = wrapper();  // Previously elicited a "must have a
                                       // constant value" error, now okay
  };


9/18/18  [EDGcpfe/19601,EDGcpfe/20108]
Structured binding and member accessibility

When using structured bindings with class members, the original specification
required the class members to be declared "public".  The committee's paper
P0969R0 later revised that to only require the member to be accessible in the
context of the structured binding declaration.  The front end now implements
the latter rule (except in modes corresponding to compilers that implement the
original rule, such as Clang mode).  For example:

  struct S {
    friend void g();
  private:
     int i;
  };
  void g() {
    S x{};
    auto [y] = x; // Previously an error.  Now okay in many modes.
  }


9/17/18  [EDGcpfe/20148]
C++-generating back end: assertion failure with decltype-specifier return type

Under some complex circumstances involving a function whose return type is
a decltype-specifier whose operand refers to a parameter of that function,
C++-generating back end configurations could abort with an assertion
failure (in get_param_for_param_ref).  This is now fixed.  For example:

  struct A {
    A();
    A(const A&);
  };
  struct B {
    B(const A&);
    A a;
  };
  struct C {
  };

  struct D {
    D(const B& br) : b(br) {}
    B b;
  };
  struct E : public D {
    E(const C&);
  }; 
  E f(int);
  auto f(double x) -> decltype(f(int(x))) {
    return E{C()};  // Previously caused an abort
  }


9/14/18  [EDGcpfe/19160,EDGcpfe/20101]
Abort or spurious failure in C++17-mode substitution of noexcept specifier

Consider:

  template<int> struct M;
  template<typename... Ts> struct S {
    using SType = M<sizeof...(Ts)>;
    S();
    template<typename...> S() noexcept(SType::X);
  };
  int main() { S<>(); }

In C++17 mode, the noexcept specifier is part of the function type and overload
resolution therefore attempts to substitute SType::X in the candidate template
S<>::S().  Previously that triggered an internal error in get_expr_rescan_info
(exprutil.c).  Other similar cases did not cause the front end to abort but to
issue a spurious error instead.  That problem is now fixed.


9/14/18  [EDGcpfe/19420,EDGcpfe/19421,EDGcpfe/19465,EDGcpfe/19474]
Attributes on redeclarations of class templates

Previously, attributes on a class template redeclaration simply replaced any
attributes from a previous declaration.  Now a class template redeclaration is
checked to ensure that it is compatible with attributes (if any) specified on
an earlier declaration.  For example (with --c++14):

  template <class> struct alignas(char) S;
  template <class> struct S {};   // Now elicits an error.

Additionally, an error is now given when attributes appear on a friend
declaration of a class template (because attributes only appertain to friend
definitions and a class cannot be defined in a friend declaration).  For
example (with --c++14):

  struct S {
    template <class> friend union [[deprecated]] U;
  };


9/14/18  [EDGcpfe/20090,EDGcpfe/20129]
Assertion failure with UDL using literal operator template

In configurations that create the string form of template definitions, the
changes for EDGcpfe/19745 in version 5.0 resulted in an assertion failure
in add_token_to_string (literal.c) when a template definition contains a
user-defined literal that refers to a literal operator template.  This is
now fixed.  For example, with --c++11:

  template<char... Digits> int operator""_s() { return 0; }
  template<typename> void f() {
    int i = 10_s;   // Previously aborted
  }


9/13/18  [EDGcpfe/19537]
GNU C++ compatibility: Nonstandard function name lookups

In GNU C++ modes, the front end previously handled dependent function calls
with unqualified names in a nonstandard way: This caused declarations appearing
after the call to be considered for the non-argument-dependent part of the
lookup (see the entries for EDGcpfe/7846 and EDGcpfe/12925).  That nonstandard
behavior is now disabled in GNU C++ modes with gnu_version >= 40700.  With that
change, the front end now accepts the following case in GNU C++ mode with
gnu_version >= 40700:

  namespace N {
    struct F {
      template<typename X, typename Y>
        auto operator()(X x, Y y) -> decltype(f(x, y));  // (1)
    };
    F f;  // (2)
  }
  struct S { friend void f(int, S); };  // (3)
  void g() { N::f(1, S()); }

Previously, this failed in GNU C++ modes because during the instantiation of
N::F::operator() the call f(x, y) on line (1) found the function object
declared on line (2) instead of the friend declaration on line (3) (the
latter is found through argument-dependent lookup).


9/13/18  [EDGcpfe/19553]
Invalid source sequence entry for friend declaration

In configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE, the front
end failed to correctly record a source sequence entry for a friend declaration
referring to a generated member.  Instead, a source sequence entry was created
that did not point to an IL entry and that in turn likely resulted in an abort
later on (access through a null pointer).  For example:

  struct B { B& operator=(B const&); };
  struct D: B {};
  struct S {
    friend D& D::operator=(D const&);  // Previously resulted in invalid IL.
  };

That is now fixed.


9/13/18  [EDGcpfe/19875]
Friend function declarations in local classes

A friend function declaration in a local class must match a declaration in the
immediately-enclosing nonclass scope.  Previously, the front end only diagnosed
this in strict mode.  Now it is diagnosed in all modes: A discretionary error
in strict, GNU, and Clang modes, and a warning otherwise.


9/12/18  [EDGcpfe/16636,EDGcpfe/19422]
Spurious error on cast to rvalue reference involving a conversion

The front end previously issued a spurious error on the following cast:

  char c = 1;
  int const &&r = static_cast<int const&&>(c);

That is now fixed.


9/12/18  [EDGcpfe/18522,EDGcpfe/20102]
Spurious "not a literal type" error for lambda closure class

The front end previously incorrectly categorized some lambda closure
classes as non-literal types when, in fact, they satisfied the requirements
for literal class types.  This is now fixed.  For example, with --c++17:

  constexpr auto make_lambda(int v) {
    auto ret = [=]() constexpr { return v; };  // Previously an error
    return ret;
  }


9/11/18  [EDGcpfe/19550]
Matching implicit conversion templates

In general, when performing an implicit conversion that involves a user-defined
conversion function, the invocation of that user-defined conversion function
can be followed by another standard conversion (e.g., an integral promotion).
However, the C++ standard specifies that that subsequent standard conversion
must be trivial (an "exact match") if the user-defined conversion is a template
instance.  Previously, the front end did not implement that last rule; now, it
does.  For example:

  template<typename T> struct Id { typedef T Type; };
  struct S {
    template<typename T = short> operator typename Id<T>::Type();
  };
  static_assert(!__is_convertible_to(S,int), "Unexpected");
    // Previously this assertion failed.  Now it passes.


9/11/18  [EDGcpfe/19634]
Deduction failure due to failure to instantiate constexpr function

Consider:

  template<typename> struct X {
    friend constexpr bool operator==(X, X) { return true; }
  };
  template<typename P, bool = (P() == P())> void g(P) {}
  int main() {
    g(X<void>());  // Previously an error.  Now okay.
  }

Previously, the front end failed to resolve the call to g because during the
substitution of "P() == P()" it did not instantiate the body of operator==
(and therefore couldn't evaluate the expression).  That is now fixed.


9/10/18  [EDGcpfe/19774]
Braced pack expansions in prototype instantiations

Consider:

  #include <initializer_list>
  void g(std::initializer_list<int>);
  template<int ... Vs> void f() {
    g({ Vs... });  // Previously lost the "...".
  }

The front end previously did not correctly record the pack expansion in the
call to g.  That caused certain C++-generating back end configurations to
render the call without the ellipsis (which is incorrect).  That is now fixed.


9/10/18  [EDGcpfe/18906,EDGcpfe/20006]
Value of __cplusplus in C++17 mode

The front end has now been updated to set the value of the __cplusplus
built-in macro in C++17 mode as required by the emulation mode in effect:
to 201703L in strict and default modes; to 201500L or 201703L in g++ mode,
depending on the value of gnu_version; and to 201406L or 201703L in clang
mode, depending on the value of clang_version.  It remains at 199711L in
all Microsoft modes.


9/10/18  [EDGcpfe/18393,EDGcpfe/20052]
Core issue 2218: Equivalence of namespace and namespace alias in lookup

Core issue 2218 clarified that the B in B::x is not ambiguous in the example
below because the names A::B and C::B denote the same entity.  We now
implement the resolution of this issue.

  namespace A { namespace B { int x; } }
  namespace C { namespace B = A::B; }
  using namespace A;
  using namespace C;
  int x = B::x;


9/10/18  [EDGcpfe/19635]
Incorrect lookup when doing deferral of function prototype instantiations

When the front end is deferring function prototype instantiations (e.g.,
in g++ or clang mode), some symbols declared in the instantiation of a
class template could incorrectly be ignored by the lookup in a function
template defined immediately after the class template.  In the example
below, the friend function g was considered to be not visible as a
non-dependent function in the prototype instantiation of f().  Now fixed.

  template <typename T> struct A {
    typedef A<T> U;
    A() {}
    friend inline void g(U& u) { }
  };
  template <typename T> void f() {
    A<float> y;
    g(y);
  }
  int main() {
    f<void>();
  }


9/7/18   [EDGcpfe/20069]
Internal error on lambda capture by copy when generating cross-reference file

An internal error could occur (in write_xref_entry) when the front end is
generating a cross-reference file (e.g., with --xref=x.log) on a lambda
capture by copy.  Now fixed.

  void f(int i) {
    [&, i]{ };
  }


9/6/18   [EDGcpfe/19806]
C++-generating back end: clang mode elaborated-type-specifiers and inline
namespaces

The changes for EDGcpfe/16279 (in version 4.11) sometimes resulted in
incorrectly dropping necessary name qualifiers when the named entity is a
member of a nested inline namespace, yielding output that could not be
compiled.  This is now fixed.  For example, with --c++11 --clang:

  namespace std {
    inline namespace __1 {
      template <class _Tp> struct hash;
    }
  }
  template <class C> class Foo {
    friend struct std::hash<C>;  // Previously generated as "struct hash<C>"
  };


9/6/18   [EDGcpfe/19742,EDGcpfe/19982]
Abort in Microsoft mode on nonreal constexpr friend declaration

In Microsoft mode, the front end performs a "nonreal instantiation" of
dependent base classes (to emulate certain nonstandard behaviors of the
Microsoft compilers).  Previously, the front end could abort due to a failed
assertion in check_use_of_constexpr when such a nonreal instantiation involved
a constexpr friend function declaration.  For example:

  template<typename> struct B {
    friend constexpr bool f();
  };
  template <typename T> struct D: B<T> {};  // Previously an internal error in
                                            // Microsoft mode.  Now okay.

This is now fixed.


9/6/18   [EDGcpfe/19743]
C++-generating back end: qualification in friend function declaration

G++ has a bug that causes it to ignore names in the current lexical scope
that appear in the parameter list of a friend declaration from a different
scope.  The C++-generating back end previously put out such names without
qualification, triggering spurious errors when the generated code was
compiled with g++.  This is now fixed; when gcc_is_generated_code_target
is TRUE, such names will now be qualified in the generated code.  For
example, with --g++:

  namespace N1 { class B;  }
  namespace N2 { void f(N1::B& b); }
  namespace N1 {
    class A {
      friend void N2::f(N1::B & b);  // Previously generated as
                                     // N2::f(B & b), triggering the g++ bug
    };
  }


9/6/18   [EDGcpfe/19986]
Spurious error on nested friend destructor declaration

Consider:

  struct C {
    virtual ~C() {}
    class F { friend C::~C(); };
  };

The front end previously issued a spurious error on the friend declaration
claiming an incompatible exception specification.  That is now fixed.


9/6/18   [EDGcpfe/19910]
Defaulted copy constructors and rvalue reference members

An rvalue reference member in a class type causes any associated defaulted
copy constructor to be deleted.  E.g.:

  struct S { int &&rr; };
  void g(S &p) {
    S s(p);  // Error: The copy constructor of S is deleted.
  }

However, the front end previously applied that rule unreliably, particularly
in cases with user-declared move constructors or move assignment operators.
For example:

  struct X {
    int &&r;
    X(X const&) = default;
    X(X&&);
  };
  void f(X &p) {
    X x(p);  // Previously erroneously accepted.  Now an error.
  }

That is now fixed.


9/6/18   [EDGcpfe/20073]
Microsoft compatibility: variadic static data member initializer regression

A change made in version 5.0 caused a regression in the processing of
static data members with out-of-class initializers involving pack
expansions.  This only occurred in modes that do not do non-class
prototype instantiations (typically permissive Microsoft mode).  Now
fixed.

  template <typename... T> struct X {
    static int arr[sizeof...(T)];
  };
  template <typename... T> int X<T...>::arr[sizeof...(T)] = { sizeof(T)... };
  int main() {
    X<int, float> x;
    x.arr[0];
  }


9/5/18   [EDGcpfe/19872]
C++-generating back end: direct-initialization from explicit temporary

In cases where a variable is initialized using the parenthesized form of
direct-initialization and the initializer is an explicit temporary of the
form T(), the C++-generating back end put out the initializer in a form
that incorrectly declared the variable as a function.  This is now fixed.
For example, with --c++11:

  struct A { };
  A a((A()));  // Previously generated as "A a();", a function declaration
  struct B {
    B(A);
  };
  B b((A()));  // Previously generated as "B b(A());", a function declaration
               // (declaring b as a function taking a pointer to a function
               // returning A)


9/5/18   [EDGcpfe/19559]
C++-generating back end: new auto with dependent initializer

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end incorrectly
parenthesized the "auto" keyword in the generated code when it is used
as a new-type-id with a dependent initializer.  This is now fixed.  For
example, with --c++11:

  template <class T> auto f(T t) ->
    decltype(new auto(t));   // Previously generated as "new (auto)(t)"


9/5/18   [EDGcpfe/20057]
Explicit casts and folding constructor calls

Consider:

  struct S {
    constexpr S(float const&) {}
    void f() {};
  };
  int g() {
    static_cast<S>(0).f(); // (1)
    return 0;
  }

The static_cast construct produces two dynamic initialization entries: one
that represents the underlying constructor call as is (i.e., a dik_constructor
entry), and one that results from folding that constructor call (a dik_constant
entry).  Previously, only the latter (dik_constant) entry was marked as
representing an explicit cast.  The lack of that marking on the unfolded entry
caused the C++-generating back end to render line (1) as

	(0).f();

which is clearly an error.  That is now fixed: Both dynamic initialization
entries are now marked as representing an explicit cast.


9/4/18   [EDGcpfe/14767,EDGcpfe/15614,EDGcpfe/16304,EDGcpfe/16427,
          EDGcpfe/18826]
Clang-style feature-test macro operators in non-clang modes

The front end by default now enables the clang feature-test macro operators
__has_feature, __has_extension, __has_include, __has_include_next,
__has_attribute, __has_builtin, and __is_identifier in all modes.  These
macro operators will remain undefined if the new configuration macro
DEFINE_FEATURE_TEST_MACRO_OPERATORS_IN_ALL_MODES is defined as FALSE.  (The
__has_include macro operator will continue to be defined in C++17 mode and
when the global variable define_portable_feature_test_macros is TRUE,
regardless of the value of the new configuration macro.)  For example, with
--g++:

  #if __has_feature(cxx_alignas)  // Previously an error, now accepted
  #endif


8/30/18  [EDGcpfe/19679]
__builtin_va_arg and templates

The front end previously issued spurious type errors when applying the
GNU/Clang __builtin_va_arg operator to a template-dependent type.  For example:

  template<typename T> void g() {
    T x;
    __builtin_va_arg(x, int);  // Previously an error.  Now okay.
  }
  template void g<__builtin_va_list>();

That is now fixed.


8/30/18  [EDGcpfe/19761]
Partial specializations and "first_decl" flag

While parsing a declaration, the front end keeps track of information about
that declaration in an entry of type a_decl_parse_state.  One of the flags in
such entries is "first_decl", which indicates whether this is the first
declaration of the underlying entity.  Now the front end sets that flag to
TRUE the first time a specific partial specialization is seen.  For example:

  template<typename T> struct X;      // Primary template.
  template<typename T> struct X<T*>;
                             // Partial specialization: first_decl == TRUE.
  template<typename T> struct X<T*>;
                             // Partial specialization: first_decl == FALSE.
  template<typename T> struct X<T&>;
                             // Partial specialization: first_decl == TRUE.


8/30/18  [EDGcpfe/19934]
Microsoft C++ compatibility: Copy elision and conditional operators

Consider:

  template<typename> struct X {
    struct N {
      N() {}
      N(N const&) {}
    };
  };
  X<int>::N g() {
    return true ? X<int>::N() : X<int>::N();
  }
  int main() {}

Ordinarily, the copy constructor call implied by the return statement of g()
in pre-C++17 modes is elided (in C++17 mode, copy elision is mandatory) and
the result is instead constructed directly into the storage provided by the
caller of g().  That means that the copy constructor of X<int>::N is not
instantiated.  When TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is set to
TRUE, a C++-generating back end will thus not generate a definition for that
copy constructor.  However, it appears earlier Microsoft compilers do not
elide the copy constructor in this case and the code generated by the C++-
generating back end therefore results in a linker error.  That problem is now
fixed: Copy-constructor elision on the result of a conditional operator is no
longer performed in Microsoft modes that (a) do not enable mandatory copy
elision (e.g., through C++17 mode) and (b) do not disable other unique
Microsoft behaviors of the conditional operator (like --no_ms_permissive; see
the entry for EDGcpfe/17992).


8/30/18  [EDGcpfe/20048,EDGcpfe/20059]
Abort on friend class template in nested class of class template

The changes for EDGcpfe/18892 in version 5.0 introduced a regression causing
the front end to abort (in primary_template_of, templates.c) on the following
example:

  template <typename> struct X {
    template<typename> class F;
    struct N { 
      template<typename> friend class F;
    };
  };

where a friend class template in a nested class of a class template names a
member template of the enclosing class template.  That is now fixed.


8/30/18  [EDGcpfe/20046]
Spurious "no constant" error on not-evaluated construct

Consider:

  constexpr int n = true ? 1 : *new int{0};

Previously, this resulted in the front end issuing a spurious error about the
new-expression not producing a constant value even though that new-expression
is not evaluated.  That is now fixed.


8/29/18  [EDGcpfe/19163]
Allocation and freeing of arrays of overaligned types

In some configurations, the front end failed to correctly satisfy the
alignment requirements of an array of a type with an extended alignment
(see EDGcpfe/17696).  In addition, the deallocation function was invoked
using an incorrect calling sequence that omitted the alignment parameter.
These issues are now fixed; the array prefix (extra space allocated before
an array to contain information about the size of the array) is now
expanded to the alignment size so that the array will begin on an
appropriate alignment boundary following the start of the allocated
storage, and the deallocation function is now invoked correctly.


8/28/18  [EDGcpfe/19948]
Assertion failure in make_cast_rescan_operands

In fairly complex situations involving a cast operation in an alias template,
the front end failed an assertion check in make_cast_rescan_operands because
of missing information in the structures supporting expression SFINAE.  For
example:

  template<typename, typename> struct P {
    static bool const value = true;
  };
  template <bool ...> struct I;
  template <bool ...Bs> using A = P<I<Bs...>, I<((void)Bs, true)...>>;
  template<typename ...> struct X {
    template<typename T> void f(T) noexcept(A<sizeof(T)>::value);
  };
  int main() {
    X<long> x;
    x.f(0);  // Previously triggered an abort.
  }

That is now fixed.


8/28/18  [EDGcpfe/20030]
Assertion failure with constexpr static data member template

The changes for EDGcpfe/19753, included in version 5.0, could cause an
assertion failure (in record_cache_checksum) in some configurations for a
constexpr static data member template of a class template.  For example, in
configurations with COMPILE_MULTIPLE_TRANSLATION_UNITS set to TRUE, the
following example with --c++17 aborted when compiled with another
translation unit:

  template<class T> struct A {
    template<class> static constexpr bool is_ok = true;
  };
  A<int> p;


8/28/18  [EDGcpfe/18424]
Visibility of a function during deduction

Consider:

  namespace N {
    template<typename> void f();
    void f();
    template <typename T, typename> auto f() -> decltype(f<T>());  // (1)
  }
  using R = decltype(N::f<double>());  // Previously triggered an error.
                                       // Now okay.

The resolution of the call "N::f<double>()" causes the front end to substitute
double for T in template (1), which in turn requires the substitution of the
call "f<double>()" in the return type of (1).  Previously, the front end
erroneously considered template (1) in the resolution of that latter call,
which resulted in unbounded recursion that was eventually stopped with an
error message.  That is now fixed.


8/24/18  [EDGcpfe/20049]
Lambdas in template arguments

The front end now diagnoses the use of lambdas in various contexts as required
by the C++17 standard, including function template signatures and template
arguments.  For example:

  template <int A[+[]{return [=]{ return 42;}(); }() ]> void f () {}
    // Now an error.

(This is the example from EDGcpfe/19178.)


8/23/18  [EDGcpfe/19998]
C++20: Default member initializers for bit fields

In C++20 mode, the front end now accepts default member initializers for bit
fields.  For example:

  struct S {
    int i: 7 = 42;  // Error in C++17 and earlier modes; okay in C++20 mode.
  };

This feature was added to the working paper for the next standard through
paper number P0683R1.


8/23/18  [EDGcpfe/20013]
C++20: Constructing closures without capture

In C++20 mode, a closure resulting from a lambda that is introduced with "[]"
(i.e., doesn't capture anything) now has a defaulted default constructor and
defaulted copy/move-assignment operators (in C++17 mode these special members
are deleted).  For example:

  auto cmp = [](auto x, auto y) { return x > y; };
  decltype(cmp) c;  // Valid in C++20 mode (error in C++17 mode).
  void g() {
    c = c;  // Valid in C++20 mode (error in C++17 mode).
  }

This feature was added to the working paper for the next standard through
paper number P0624R2.


8/23/18  [EDGcpfe/20000]
C++20 mode

The front end now accepts a new "--c++20" command-line option (as does the
eccp.sh script).  This option will enable features for the standard under
development (which is expected to be completed in 2020).  For now, it sets
the value of the global variable std_version to 202000 and the value of the
predefined __cplusplus macro to 202000L; those values will eventually be
updated to match the official __cplusplus value when the forthcoming standard
is approved.  A new macro cpp20_mode is also available in the front end to
test whether it runs in C++20 mode.  In addition, std_version is now set to
201703 for C++17 mode; it was previously set to the temporary value 201701.


8/22/18  [EDGcpfe/20017]
C++-generating back end: Generated explicit specializations for function
templates with decltype-specifier return types

The Microsoft compiler has a bug that causes it not to accept explicit
specializations of function templates where the return type is a
decltype-specifier whose operand is a member access expression.  The
C++-generating back end, configured with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE,
previously put out generated explicit specializations for instances of
such function templates, resulting in correct code that was erroneously
rejected by MSVC.  This has now been fixed by suppressing these explicit
specializations when msvc_is_generated_code_target is TRUE.  For example,
with --microsoft_version=1910:

  struct S { int f(); } s;
  template<typename T> decltype(s.f()) g(T x);
  int i = g(s);

The generated code for this example previously included a declaration of
the explicit specialization

  template<> decltype((s.f())) g(S x);

which the Microsoft compiler rejected with "error C2912: explicit
specialization 'int g(S)' is not a specialization of a function template."
The generated code no longer contains this explicit specialization, thus
avoiding the spurious MSVC error.


8/21/18  [EDGcpfe/19899]
C++-generating back end: Missing static specifier for in-class explicit
specialization of static member function template

In C++-generating back end configurations targeting MSVC for the generated
code and with NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set
to TRUE, the generated explicit specialization of a static member function
template was put out without the "static" keyword.  For example, with
--microsoft_version=1910:

  template<typename T> struct A {
    template<typename U> static auto f(U&& u)->decltype(u.g());
    typedef decltype(f(T())) type;
  };
  struct B {
    int g();
  };
  A<B> ab;

In this example, the explicit specialization for A<B>::f(B&&) previously
lacked the "static" keyword.  This is now fixed.


8/21/18  [EDGcpfe/18069,EDGcpfe/19947]
Exception specifications and defaulted special member functions

Consider the following example in C++11 or C++14 mode (but not C++17 mode):

  struct E {
     E();
     E(E const&) = delete;
  };
  template<typename T> struct B {
    B() noexcept(noexcept(T(T{})));
  };
  struct D: B<E> {
    D() = default;
  };

Previously this elicited a warning or error (depending on the mode) about an
attempt to reference the deleted copy constructor of E from the exception
specification of B<E>::B().  That exception specification was instantiated to
establish the exception specification of D::D().  Now, the instantiation of the
exception specification is delayed until D::D() is actually used and hence no
diagnostic is issued for this particular example.  This behavior was clarified
by the resolution of Core issue 1330.


8/21/18  [EDGcpfe/19888]
Abort on use of deleted function with deducible return type

Some cases of deleted function declarations with a deducible return type
resulted in an internal error (in check_defaulted_or_deleted_function in
class_decl.c).  For example:

  struct S {
    auto& f() = delete;  // Previously aborted.  Now okay.
  };

This is now fixed.  (See also EDGcpfe/18910, which resolved a variation of
this issue.)


8/20/18  [EDGcpfe/19900]
C++-generating back end: ordering of generated explicit specialization of
conversion function template

In C++-generating back end configurations targeting MSVC for the generated
code and with NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set
to TRUE, the definitions of generated explicit specializations of
conversion function templates were sometimes put out too early, so that a
reference in the body of such a function caused the implicit instantiation
of a template that was later explicitly specialized. The reason for this
potentially-problematic ordering was to work around a bug in early versions
of the MSVC compiler; see the Changes entry of 2/4/07.  More recent
versions of MSVC do not exhibit this bug, so when
msvc_target_version_number is >= 1600, the generated explicit
specializations of conversion function templates are put out in the correct
location.  For example:

  template<typename T> struct E {};
  template <typename T, int N> E<T> g(T (&)[N]) {
    return E<T>{};
  }
  template <typename T1> struct X {
    template <typename T> operator E<T>() const {
      T x[] = { T{} }; 
      return g(x);
    }
  };
  void start() {
    (E<bool>)X<bool>();
  }

Previously, the generated explicit specialization of
X<bool>::E::operator E<bool>, which contains a reference to g<bool,1>,
appeared prior to the declaration of the explicit specialization of
g<bool,1>.  As a result, g<bool,1> was implicitly instantiated before it
was explicitly specialized, which is an error.  This is now fixed.


8/20/18  [EDGcpfe/19974]
C++-generating back end: Static data members with in-class initializers

Consider the following code in C++11 mode but not C++17 mode:

  #include <initializer_list>
  struct S {
    static constexpr auto s{1.0};
  };
  constexpr decltype(S::s) S::s;

The changes for EDGcpfe/19285 (in version 5.0) caused primary source sequence
entries to be generated for both the in-class declaration and the out-of-class
definition.  That in turn, caused both to be rendered with the same "auto"
type.  That regression is now fixed: The out-of-class definition now gets a
secondary source sequence entry with its own type description and that
description is correctly used to render the type as "decltype(S::s)".


8/20/18  [EDGcpfe/19957]
Changes to assertion messages

A change has been made to add __func__ to the diagnostic displayed when an
assertion or internal error occurs in the front end.  This will help us to
more quickly diagnose front end issues.  A change has also been made to
strip the directory name (if any) from the file name that is reported.

Coincident with this change, __func__ is enabled in all modes.  For older
compilers that may not support __func__, the FUNC_AVAILABLE configuration
macro has been added (which can be set to FALSE to disable the use of
__func__).


8/17/18  [EDGcpfe/19991]
C++-generating back end: inline member function definitions of class templates

In C++-generating back end configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
bodies of member functions defined inside class template definitions were
removed from the generated code, leaving only the member function
declarations.  This was done to accommodate very old versions of some
compilers that issued spurious errors when an explicit specialization was
provided for a member function defined inline in a class template.  Modern
compilers do not exhibit this bug, so the front end has been changed to
perform this removal only when the new configuration macro
REMOVE_INLINE_BODIES_FROM_CLASS_TEMPLATE_DEFINITIONS is TRUE.  The default
value for this new macro is FALSE, meaning the bodies of these member
functions will appear in the generated code.  For example:

  template<typename T> struct S{
    void f() { } // Previously generated as "void f();" in some configurations
  };


8/17/18  [EDGcpfe/19988]
IA-64 ABI: Mangling of variable templates

The IA-64 ABI requires that variable template names be mangled with the
<unscoped-template-name> production which includes allocating a substitution
for the variable template name.  The front end had failed to do that, resulting
in incorrect mangled names in some instances (where a substitution is made
after the variable template name appears in the mangled name).  This is
now fixed (when ABI_COMPATIBILITY_VERSION >= 510).  For example, with --c++14:

  enum E { e };
  template <typename T, T t> T vt = T(0);
  auto x = vt<E, e>;    // was _Z2vtI1ELS_0EE, now _Z2vtI1ELS0_0EE


8/17/18  [EDGcpfe/19980]
GNU compatibility: specifying alignment of enum type

The C++ standard says that when multiple alignments are specified the resulting
alignment is the strictest, but, presumably due to a bug, GNU appears to use
the last alignment.  In cases where this is applied to an enum type, GNU also
appears to ignore the alignment in cases where it is smaller than the alignment
of the base type of the enum type.  The front end now emulates that behavior
(with a warning).  For example, with --gnu_version 80200:

  enum alignas(16) alignas(1) E1 { };   // should have alignment of 16
  enum alignas(16) alignas(8) E2 { };   // should have alignment of 16
  static_assert(alignof(E1) == alignof(int), "");
  static_assert(alignof(E2) == 8, "");


8/16/18  [EDGcpfe/19977]
Field selections on an incomplete type in template contexts

Consider:

  struct I;
  template<typename> struct X {
    X(X const &p) { p.f().g(); };  // Error: "p.f()" has incomplete type.
    I const& f() const;
  };

The front end issues an error on the expression "p.f().g()" because "p.f()"
has an incomplete type.  However, other compilers do not diagnose this because
the invalid operation appears in a template-dependent context.  The front end
therefore now inhibits the associated error in Microsoft, GNU, and Clang C++
modes.  The front end did previously accept most cases like this in Microsoft,
GNU, and Clang C++ modes using a different mechanism: For those cases, this is
a regression introduced in version 5.0.


8/15/18  [EDGcpfe/19979]
Prototype instantiation of member function template sometimes done too late

In some cases, the order in which member functions have their bodies scanned
at the end of a class definition could result in a member function template
being instantiated before the prototype instantiation had been done.  This 
could result in incorrect behavior, such as a spurious error on the pack
expansion in the call of "h(args...)" in the example below.  Now fixed.

  struct A {
    struct B {
      void g() { A a; a.f(1); }
    };
    void h(int){}
    template<typename... Ts> void f(Ts... args) {
      h(args...);
    }
  };
  int main() {
    A::B B;
    B.g();
  }


8/14/18  [EDGcpfe/18084,EDGcpfe/19581,EDGcpfe/19702]
Lambda expressions in template-dependent contexts

Lambda expressions in certain template-dependent contexts could previously
lead to aborts or invalid code generated by the C-generating back end.
For example:

  template <int x,
            const int (&z)[ ([] { return x ? 0 : 1; }(), 29) ]>
  struct S {
    constexpr int f() {return 0;}
  };
  constexpr int z[29] = {};
  auto r = S<47, z>().f();

This example previously resulted in invalid generated C code that referred to
a non-existing "x".  Several of these issues have been fixed by marking the
associated closure type as dependent (and the closure's member functions as
prototype instantiations).


8/14/18  [EDGcpfe/8574]
Diagnose multiple explicit instantiations of a class

The front end failed to diagnose multiple explicit instantiations of a class
template instance.  A discretionary error is now issued, except in Microsoft
mode, where a warning is issued.  This can result in diagnostic changes
in some cases.  In the example below, we formerly gave only an error that
A<char>::f was explicitly instantiated more than once.  Now we give the
error on the class A<char> instead.

  template <typename T> struct A {
    struct B { };
    void f(){}
  };
  template struct A<int>;
  template struct A<int>::B;  // now an error
  template struct A<char>;
  template struct A<char>;  // now an error


8/13/18  [EDGcpfe/19969]
Disable C++17 matching of template template arguments in some C++14 modes

Version 5.0 includes C++17 generalized template template parameter
matching (see EDGcpfe/18746).  Even though this was a defect report
against C++14, g++, clang, and Microsoft do not enable the feature in
C++14 mode.  We previously did not enable it in Microsoft C++14 mode.
We now disable it in g++ and clang C++14 modes.  We are disabling this
in those C++14 modes because it can break valid C++14 code.

  template <typename... Ts> struct A {};
  template <typename T> struct A<T> { typedef int type; };
  struct B {};
  template <template<typename... Ts> class P> void f(typename P<B>::type);
  template <template<typename T> class P> void f(typename P<B>::type);
  int main() {
    f<A>(0);  // ambiguous with new matching rules
  }


8/13/18  [EDGcpfe/19763]
Delay attaching variable template attributes

A change has been made to delay attaching attributes to variable templates
such that the declaration information for the variable template is available
when the attribute(s) are attached.


8/13/18  [EDGcpfe/19967]
C++-generating back end: missing expression for enumerator in class template

The changes for EDGcpfe/19919 (in version 5.0) caused a regression for
C++-generating back end configurations in which template definitions are
generated from the prototype instantiation IL.  In particular, the
expression giving the value of an enumerator defined in a class template
definition could be lost in the generated code.  This is now fixed.  For
example:

  template <int R, int... E> struct S1;
  template <int R>  struct S1<R> {
    enum : int { X = 0 };
  };
  template <int R, int... Tail> struct S1<R, 0, Tail...> : S1<R+1> {
    enum : int { X = 1 + S1<R+1>::X };  // Expression for X was omitted...
  };
  static_assert(S1<0, 0>::X == 1, "");  // ...so this assertion failed


8/10/18  [EDGcpfe/19965]
Constexpr interpretation of string literal copies

In configurations with EXPENSIVE_CHECKING set to TRUE, the front end could
abort in map_colliding_ptr when repeatedly copying the value of a string
literal into an array.  For example:

  constexpr int f() {
    for (int i = 0; i<2; ++i) {
      char s[1][1] = { "" };  // Previously could lead to an abort.
    }
    return 42;
  }
  int r[f()];

In configurations with EXPENSIVE_CHECKING set to FALSE, more complex examples
could potentially produce an invalid result.  That is now fixed.


8/10/18  [EDGcpfe/19962]
Fix IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR typo

The IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR macro should be
TARG_IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR.


-------------------------------------------------------------------------------
Version 5.0, August 10, 2018

8/8/18   [EDGcpfe/17697,EDGcpfe/18314]
C++17: Class template argument deduction

In C++17 mode, the front end now implements "class template argument
deduction": A feature that permits the deduction of class template arguments
from certain initializers.  For example:

  template<typename T> struct S {
    S(T);
  };
  S s = 42;  // Same as "S<int> s = 42".

This feature was added to C++17 through the standardization committee's paper
number P0091r3 (with additional provisions added through P0620r0).


8/8/18   [EDGcpfe/19638]
GNU compatibility: lvalue expressions in asm statements

Previously (see the Changes entry for EDGcpfe/11125) the front end had been
changed to disallow certain lvalue expressions (namely those whose C
counterpart would be an rvalue).  A change has been made to the front end to
allow these (in C++ mode) and let lowering deal with the resulting expression.
Currently only one lvalue expression is supported -- an assignment expression.
Other expressions will still result in the same error.  For example,
with --g++:

  void f(int a, int b) {
    asm volatile ("" : "=r" (b = a));
  }


8/8/18   [EDGcpfe/19953]
Updates to standard feature-test macros

The front end has been updated to comply with the latest specification of
the standard feature-test macros, Committee document P0941R2.  Primarily
this consisted of changing the values of the macros from an integer to a
long, e.g., 201603 became 201603L.


8/7/18   [EDGcpfe/19863]
Abort in constexpr interpreter for certain subobject zero-initializations

In some relatively complex cases, the interpretation of a zero-initialization
could corrupt data managed by the constexpr interpreter, which in turn could
lead to an abort in the interpreter.  For example:

  struct X { int x; };
  struct Y {
    union { int y; };
    int d;
    int &r = y ;
    X g = X { [](auto x){ return X(); }(d) } ;
  };
  constexpr Y v = { 37, 47 };

Previously, the evaluation of "return X();" (which involves zero-initializing
the return value) corrupted the representation of v.r in most configurations,
which in turn triggered an abort in the interpreter.  That is now fixed.


8/7/18   [EDGcpfe/18914]
Spurious errors on pack expansions in SFINAE contexts

When processing pack expansions for expression lists in SFINAE contexts, the
front end previously sometimes lost track of the pack pattern to expand when
dealing with multiple cascading expansions.  For example:

  struct A { void operator ()(...) const; };
  template<typename T> struct C {
    template<int ... I>
      auto f() -> decltype(A()(I == T()...));  // Pack expansion.
    template<typename ... Args>
      auto operator()() -> decltype(f<0>(Args()...));  // Pack expansion.
  };
  template<typename F> struct R {
    auto operator ()() -> decltype(F()());  // Previously a spurious error.
  };
  template<typename F> R<C<int>> g(const F &f...);
  int main() {
    g(A());
  }

Here the instantiation of R<C<int>>::operator() previously produced a spurious
error.  That is now fixed.


8/6/18   [EDGcpfe/19937]
Constexpr interpreter and anonymous union variables

The constexpr interpreter previously incorrectly assumed that the entity
associated with an anonymous union is a data member when it actually is a
variable.  That could lead to spurious aborts.  For example:

  struct S { int x = 37; } s;
  constexpr int f() {
    union {
      int x = s.x;  // Previously involved an invalid memory access.
    };
    return x;
  }
  constexpr int r = f();

That is now fixed.


8/5/18   [EDGcpfe/19813]
C++-generating back end: temporary names in generated explicit instantiations
for template instances

In configurations in which
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
C++-generating back end attempts to put out explicit specializations
representing implicitly-instantiated templates.  This is not always
possible, however, because of language rules regarding ordering,
visibility, or access of declarations, and the C++-generating back end
attempts to suppress such explicit specializations.  The check for invalid
explicit specializations failed to account for cases in which a local name
or type is used as a template argument, however, resulting in uncompilable
generated code, using undeclared names in namespace scope.  This is now
fixed, and such explicit specializations are now suppressed.  For example,
with --c++11:

  template<typename T> struct S { };
  template<typename T> S<T> f(T) { return S<T>(); };
  void g() {
    auto l = [](){};
    f(l);  // Previously resulted in a generated explicit specialization like
           // S<__T12345678> f(__T12345678), with __T12345678 undeclared
  };


8/3/18   [EDGcpfe/19935]
Built-in functions invoked as pseudo-calls

Some built-in functions aren't really "functions" at all and calls to them are
handled specially as "pseudo-calls".  Previously, when such a pseudo-call
appeared in a template-dependent context, the associated function was
incorrectly marked as having its address taken (a_routine::address_taken flag
set to TRUE).  For example:

  template<typename T> bool f(T const *s) {
    return __builtin_constant_p(*s);
  }

Previously, when the definition of f was parsed, the routine entry for
__builtin_constant_p had its address_taken flag set to TRUE.  That is now
fixed.


8/3/18   [EDGcpfe/19244]
Instantiation of default-initialized variable templates

In some cases, default-initialized variable templates could be instantiated
multiple times.  This could result in incorrect behavior.  Now fixed.


8/2/18   [EDGcpfe/19834]
GCC compatibility: mangling of conversion functions

GCC 7.0.0 made a change to suppress adding the abi_tags (if any) of the
return type of a conversion function to its mangled name.  The front end
now emulates that when ABI_COMPATIBILITY_VERSION >= 415.  The behavior for
clang emulation mode was also changed.  This change affects both IA-64 and
Cfront ABIs.  For example (with --gnu_version 70000):

  namespace std {
    inline namespace __cxx11  __attribute__((__abi_tag__("cxx11tag"))) {
      class string {};
    }
  }
  struct C {
    operator std::string();   // No longer has "cxx11tag" in mangled name.
  };
  void f() {
    std::string s = C();
  }


8/1/18   [EDGcpfe/19918]
Microsoft/GNU compatibility: Cast of integer constant address in
constant-expression

The changes for EDGcpfe/19212 (which permit casting a zero address to an
integer type in some modes) have been extended to also cover addresses with
known integer constant values.  This is, e.g., useful to handle certain
implementations of offsetof.  E.g.:

  struct S1 { int a; long x; int b; };
  using size_t = decltype(sizeof(42));
  static_assert(((size_t)&reinterpret_cast<char&>((((S1*)0)->x)))%4 == 0, "");
    // Now accepted in Microsoft and GCC C++11 modes.

Here, the address of the lvalue "((S1*)0)->x" is a known integer constant
value.


7/31/18  [EDGcpfe/19795]
__auto_type and arrays

The GNU C extension "__auto_type" (see the entry of 12/9/15 for EDGcpfe/15176
and EDGcpfe/16691) previously failed to perform array-to-pointer decay when
deducing the type from an initializer.  For example, in GNU C11 mode:

  double z[20];
  __auto_type x = (z); // Previously an error.  Now okay.

Previously, the type of x was deduced to be an array type, which resulted in
an error since an array cannot be initialized in this way.  That is now fixed:
A pointer type is deduced.


7/31/18  [EDGcpfe/19909]
Missing error on class template used as a destructor name

In some cases, the front end failed to diagnose a class template used as a
destructor name.  This could cause an incorrect symbol variant to be used,
which in turn could result in various forms of incorrect behavior, including
possible internal errors.  Now fixed.

  class A {};
  struct C {
    template <class U> class A {};
  };
  C c;
  int x[c.~A];


7/25/18  [EDGcpfe/19580]
Internal error on member alias template redeclaration

An internal error could occur (in f_skip_typerefs) if an alias template
was redeclared within a class template.  Now fixed.

  template <class T> struct A {
    template <class U> using X = U;
    template <class U> using X = U;
  };
  A<int> a;


7/24/18  [EDGcpfe/19876]
IA-64 ABI mangling for variable templates

The mangling used for constants that represent the addresses of variable
templates in IA-64 ABI configurations was incorrect and has now been fixed
(when ABI_COMPATIBILITY_VERSION >= 415).  For example (with --c++17):

  template <class T, T* t> T v1;
  template <class T, T* t> T v2;
  int *n = &v1<int, &v2<int, (int*)0 >>;


7/20/18  [EDGcpfe/19846]
Emulation of GCC for core issue 429

It appears that GCC 6.0.0 and later have implemented core issue 429
(see the Changes for EDGcpfe/18899), so the front end's emulation has been
updated accordingly.


7/18/18  [EDGcpfe/19210]
Replaceable operator new/delete declarations and exception specifications

Consider:

  void operator delete(void*) noexcept(false) {}

Previously, the front end always accepted this for backward compatibility
reasons.  However, since C++11, the code is strictly-speaking invalid because
"operator delete" is predeclared as "noexcept(true)".  In strict C++ mode and
in Clang C++ modes the front end now enforces the standard redeclaration rule
when implicit_noexcept_enabled is TRUE (see also the entry of 9/3/12 for
EDGcpfe/10617, etc.): In such modes an error is issued for the example above.
This change can also affect "operator new" declarations.  For example:

  void* operator new(decltype(sizeof(2))) noexcept(true);
    // Now an error because this "operator new" is implicitly predeclared
    // with "noexcept(false)".


7/17/18  [EDGcpfe/19839]
Structured bindings and decltype

Structured bindings are often reference variables.  For example:

  #include <utility>
  void f() {
    std::pair<int, int> p{ 1, 2 };
    auto [x, y] = p;
    static_assert(std::is_same<decltype(x), int>::value);
        // Previously an error.  Now okay.
  }

In this case, x and y are references bound to the members of an unnamed
variable (of the same type as p).  The front end therefore previously produced
"int&" for "decltype(x)".  However, the standard actually requires the type
underlying the reference to be produced by decltype in that case and the front
end now does so (i.e., the static_assert in the example above now succeeds).


7/17/18  [EDGcpfe/19183]
Abort in lowering on invalid use of lambdas in C++17 mode constant expressions

Consider:

  struct A { ~A() {} };
  struct B {
    A x;
    constexpr int f() {return 29;}
  };
  template<typename T> T v[ ([]{ return B(); }()).f() ] ;

Previously this resulted in an abort in C++17 mode during IL lowering (earlier
standard modes were unaffected because in those modes lambdas cannot appear at
all in constant expressions).  This is now fixed.


7/16/18  [EDGcpfe/19251]
Missing diagnostic and lowering abort on invalid fold expression operator

Consider:

  template<typename ... T> int f(T ...args) {
    typedef decltype((args ! ...)) U;
    return 42;
  }
  int y = f(1, 2);

Previously, the front end aborted during lowering because it failed to diagnose
the invalid fold expression operator ("!" is not a binary operator).  This is
now fixed: An ordinary error is issued and the front end no longer aborts
during lowering.


7/16/18  [EDGcpfe/19251]
Missing diagnostic and lowering abort on invalid constexpr defaulted definition

Consider:

  struct S {
    struct N { int x; } n;
    constexpr S();
  };
  constexpr S::S() = default;

Previously, the front end aborted during the lowering of the S::S() constructor
because the front end failed to diagnose the use of "constexpr" on a defaulted
member whose defaulted definition is not constexpr (due to B::n not being
initializable as a constant expression).  This is now fixed: An ordinary error
is issued and the front end no longer aborts during lowering.


7/16/18  [EDGcpfe/19576]
Missing initializer on specialization of constexpr static data member template

The front end previously aborted on the following example:

  struct S {
    template<typename> static constexpr int x = 42;
  };
  template<> constexpr int S::x<void>;  // Previously aborted.  Now an error.

because it failed to emit a diagnostic for the missing initializer on the
explicit specialization.  That is now fixed.


7/16/18  [EDGcpfe/19804]
Incorrect exception handling cleanup of partially-initialized class objects

In cases where temporary objects are created as a result of default member
initializers and those objects have overlapping lifetimes, the list of
destructions to perform had been incorrect.  The following example (with
--c++11) is such a case:

  struct T { T(int); ~T(); };
  struct A { A(T); ~A(); };
  struct B { B(T); ~B(); };
  struct C {
    A a1;
    B b1 = B(T(2));
    A a2;
    B b2 = B(T(4));
    C() : a1(A(T(1))), a2(A(T(3))) {}
  };
  C c;


7/16/18  [EDGcpfe/19591]
Array bounds in parameter variables of prototype instantiations

Consider:

  template<unsigned N> struct S { void f(int const [N]); };
  template<unsigned N> void S<N>::f(int const [N]) {}

Previously, the parameter variable created for the prototype instantiation of
S<N>::f did not record its array bound.  That in turn caused the C++-generating
back to fail to render that bound in the definition of S<N>::f.  That problem
is now fixed.


7/13/18  [EDGcpfe/19836]
Spurious error on use of templated operator delete in C++17 mode

Consider:

  template<typename> struct S {};
  template<typename T> void* operator new(__EDG_SIZE_TYPE__, S<T>);
  template<typename T> void operator delete(void*, S<T>);
  int *p = new(S<int>{}) int;  // Previously an error.  Now okay.

Previously, the front end issued an error in C++17 mode about the type
resulting from the instantiation of operator delete being different from the
declared type of the template.  (This was a regression introduced in version
4.14 when exception specifications were made part of function types in C++17
mode.  See the entry for EDGcpfe/17685,EDGcpfe/18637.)  That is now fixed.


7/11/18  [EDGcpfe/18549]
Member template parameters in class template instantiations

Consider:

  template<bool B> struct I { using type = int; };
  template<typename T> struct S {
    template<typename U = int,
             typename I<sizeof(U) == 2 || sizeof(T) == 1>::type> void f(U);
    template<typename U = int,
             typename I<sizeof(U) == 2 || sizeof(T) == 2>::type> void f(U);
  };
  S<int> s;  // Now accepted in GNU and Clang modes.

Assuming sizeof(int) is neither 1 nor 2, this example is invalid because the
template parameter lists of the two otherwise identical declarations of
S<int>::f are "functionally equivalent": They are not written equivalently,
but they both behave identically for all instances of the member template.
Specifically, they behave like the following simpler template parameter list

    template<typename U = int, typename I<sizeof(U) == 2>::type> ...

because "sizeof(T) == 1" and "sizeof(T) == 2" are both false for T = int.
The language does not require a diagnostic for cases like these and it appears
GCC and Clang accept the code above and other cases like it.  The front end now
approximates that behavior in GNU and Clang mode (it accepts the example above
and others like it).


7/10/18  [EDGcpfe/17882]
Disambiguation with initializer containing member function call

A spurious error could result if a declaration that started with "typename"
contained an initializer of the form "x.y<...".  Note that the error
did not occur with "x.template y<...".  Now fixed.

  template <typename T, int N> struct A {
    typedef int B;
  };
  struct D {
    template <typename T, int N> typename A<T, N>::B f();
  };
  template <typename T> struct C {
    void g() {
      D d;
      typename A<T, 1>::B ab = d.f<T, 1>();
    }
  };
 
template class C<int>;


7/10/18  [EDGcpfe/18346,EDGcpfe/19456,EDGcpfe/19661]
Spurious errors on attempts to fold constants in template contexts

Consider:

  template<typename> struct S;
  template<typename T, int = (int)S<T>()> struct R: R<T> {};

When the front end parses the base-specifier "R<T>" it attempts to evaluate
the default template argument "(int)S<T>()" (whose type is nondependent because
of the cast to int).  Previously, this caused a spurious error to be emitted
about the default argument expression not being a constant.  That is now fixed:
The front end recognizes that the argument might be dependent in that context
and creates a generic representation for the default argument accordingly.


7/9/18   [EDGcpfe/19374]
Clang and Microsoft compatibility: "this" in call arguments in SFINAE contexts

The changes for EDGcpfe/16412,EDGcpfe/16428 (in version 4.11) caused the front
end to treat calls with an argument that implicitly or explicitly involves
"this" in a template as being unconditionally template-dependent in Clang and
Microsoft modes.  However, this could result in spurious errors ("template
instantiation resulted in unexpected function type") in SFINAE substitution
contexts.

  struct S {
    template <class T1, class T2>
      auto f(T1 t1, T2 t2) -> decltype(g(t1, t2));
    template <class T1, class T2, class T3>
      auto f(T1 t1, T2 t2, T3 t3)-> decltype(f(f(t1, t2), t3));
  };
  struct X {
    template <class T> friend T g(T, X);
  };
  int r = S().f(r, X(), X());  // Previously triggered a spurious error in
                               // Clang and Microsoft modes because the call
                               // "f(f(t1, t2), t3)" was considered to have
                               // a template-dependent type even after it
                               // was fully substituted with concrete types.

This is now fixed.


7/6/18   [EDGcpfe/19805]
Internal error on rescanning of alias template

In some complex cases involving the rescanning of alias templates, the
front end previously aborted with an internal error in function
push_expr_rescan_context_if_necessary.  That problem is now fixed.


7/6/18   [EDGcpfe/19815]
Missing diagnostic on redefinition of C++17 inline static data members

Consider:

  struct S {
    static inline int i;
  };
  int S::i = 3;

In C++17, the in-class declaration of the inline static data member is a
definition, and so is the out-of-class declaration with an initializer.  The
front end, however, previously failed to diagnose the duplicate definition.
That is now fixed.


7/6/18   [EDGcpfe/11739,EDGcpfe/16302,EDGcpfe/18966,EDGcpfe/17053,
          EDGcpfe/19083]
Template parameter packs in nontype template parameters

Core issue 778 allowed pack expansions in the declarations of nontype
template parameters.  This is now supported.

  template <class ... T> struct A {
    template <T... t> void f();
  };


7/5/18   [EDGcpfe/19816]
Lowering of __builtin_choose_expr

A call to __builtin_choose_expr that escapes to lowering is now lowered
(by replacing the call with the second or third operand depending on the
value of the first operand).  This had caused problems (an assertion failure
in lower_expr_full) in the Linux kernel build (with --gcc):

  void f() {
    asm("" : : "re"(__builtin_choose_expr(8, 0, ({}))));
  }


7/3/18   [EDGcpfe/19159,EDGcpfe/19800]
Abort on Microsoft-mode in-class specialization

Consider:

  template<int N> struct S {
    template<bool> struct B { using X = int; };
    typedef typename B<!N>::X Y;
    template<bool> void f(Y, int);
    template<> void f<true>(Y, int);
  };

This previously aborted with an internal error ("missing default rescan info",
in exprutil.c) because the front end attempted to substitute the dependent
member typedef Y as if it were an alias template, as part of matching the
in-class specialization to the member template S<N>::f.  This is now fixed:
The front end no longer attempts to match in-class function template
specializations during prototype instantiations.


7/2/18   [EDGcpfe/17957]
Allow an implementation-defined "using" attribute

As a result of the changes for EDGcpfe/17695, the attribute "[[using]]" had
resulted in an error (because an identifier had been expected to follow the
"using" keyword).  A change has been made to treat this case as an
implementation-defined "using" attribute (rather than a potential
attribute-using-prefix), thus resulting in a warning rather than an error in
this case (with --c++17):

  int x [[using]];


7/1/18   [EDGcpfe/19762]
Routine to determine if an entity is nonreal

In versions 4.11 and newer, information about prototype instantiations and
other nonreal types is always included in the IL.  Interfaces were provided to
let back-ends detect top-level entities that should be ignored to retain the
previous behavior.  These interfaces are only available when DO_IL_LOWERING
is TRUE.  A new interface is now provided to allow this kind of check to
be done even without lowering.  The routine "entity_is_nonreal" can now
be used for this purpose.


6/29/18  [EDGcpfe/19802]
No destructions performed if an exception is thrown during some partial
aggregate initialization

In certain cases, no IL had been generated to perform destruction of
objects created during partial aggregate initialization.  Now fixed.
In the example below, c[0] had not been destroyed as a result of the throw:

  int dtor_count = 0;
  struct C {
    int m;
    ~C() { dtor_count++; }
  };
  int main() {
    try {
      static C c[] = { {4}, {(throw 1, 7)}, {dtor_count} };
    } catch (...) {}
    return !(dtor_count == 1);
  }


6/28/18  [EDGcpfe/18187]
Set the "referenced" flag on iterator variable of range-based-for

Previously the "referenced" flag had not been set on iterator variables
in range-based-for statements.  Now fixed.  For example (with --c++11):

 #include <initializer_list>
 void f() {
   for (auto i : {1, 2, 3}) {}  // "i" is now "referenced"
 }


6/27/18  [EDGcpfe/19662]
Spurious error on template-dependent constant expression

Consider:

  struct S { unsigned x; };
  template<int I> void g() {
    constexpr S t{I};
    int ai[t.x];  // Previously an error.  Now okay.
  }

The expression t.x here is not template-dependent when viewed as an lvalue,
but its value as the "constant expression" for an array dimension is in fact
dependent on the template parameter I.  Previously, the lack of a direct
template dependence caused the front end to enforce the requirement of a known
constant value, which in turn triggered a spurious error.  That is now fixed.


6/26/18  [EDGcpfe/17445,EDGcpfe/19792]
Spurious exception specification error on overriding destructor in C++11 mode

Consider:

  template<typename> struct S {};
  struct B { virtual ~B(); };
  void g() {
    struct D: B {
      ~D() {}  // Previously a spurious error.
      S<int> si;
    };
  }

Previously, the front end issued a spurious error claiming the exception
specification of the destructor of D does not match that of the overridden
destructor of B.  That is now fixed.


6/26/18  [EDGcpfe/19796]
C++-generating back end: Extraneous ellipsis in rendering of fold expressions

The C++-generating back end previously sometimes generated extraneous ellipses
when rendering certain C++17 fold expressions.  For example:

  template<typename> bool V = false;
  template<bool> struct S {};
  template<typename ...Ts> S(Ts...) -> S<(V<Ts> && ...)>;

Previously, the deduction guide was rendered as follows by some configurations
of the C++-generating back end:

  template< class ...Ts> S(Ts ...)->S< (V< Ts> ... && ... )> ; 

That is now fixed.


6/26/18  [EDGcpfe/19452]
GNU compatibility: Return expression checking in templates

In GNU C++ mode, the front end no longer performs complete type checking on
return expressions during the prototype instantiation of a template for cases
where the types involved are nondependent.  For example:

  template<typename T> int* f() {
    return 42;  // Normally an error.  Now accepted in GNU mode
  }             // even with --no_defer_parse_function_templates.

Although previously an error was issued during the prototype instantiation of
the template in GNU C++ modes, those modes deferred prototype instantiations
by default in configurations without the C++-generating back end (see entry of
12/13/05).  Now these invalid cases are accepted even when the prototype
instantiation actually takes place.


6/25/18  [EDGcpfe/19027,EDGcpfe/19280]
Jumping past initializations in condition declarations

The front end now diagnoses attempts to jump past condition declarations that
contain initializations.  For example:

  int main() {
    goto L;           // Now an error in strict mode, because this jumps
    if (int x = 4) {  // past the "int x = 4" initialization.
  L:
      return 0;
  }


6/21/18  [EDGcpfe/19753]
Missing error on explicit instantiation of variable with in-class initializer

A non-inline variable template that is initialized in-class is not allowed in
an explicit instantiation directive because the in-class declaration is not
considered a "definition" in that case.  A diagnostic is now issued.

  struct A {
    template <typename T> static const T x = 1;
  };
  int i = A::x<int>;
  template const int A::x<int>; 


6/21/18  [EDGcpfe/19791]
C++-generating back end: incorrect output for deduction guides

In modes where template declarations are generated using saved strings,
deduction guides were not emitted properly.  Now fixed.

  template <class T1, class T2> struct A {};
  template <class T1, class T2> A(T1, T2) -> A<T1, T2>;



6/20/18  [EDGcpfe/19571]
"if constexpr" not processed properly when not parsing non-class templates

In modes where non-class templates are not parsed (e.g., permissive
Microsoft mode), "if constexpr" statements in template contexts were
sometimes not parsed properly.  Now fixed.

  template <int I> struct A {
    void f(int ch) {
      if constexpr (I == 0) ; else if (ch == 0) ; else ;
    }
  };
  int main() {
    A<0> a;
    a.f(1);
  }


6/20/18  [EDGcpfe/19755]
Referring to local variables from nested local types

The front end now more broadly permits referring to local variables from
nested local types if that reference is from an unevaluated expression
context.  For example:

  void g() {
    int x = 1;
    struct S {
      void f() { decltype(x) y; }  // Previously an error.  Now okay.
    };
  }

As part of this change, member functions of local class types are now stored
in the memory region of the enclosing function (as was already the case for
the member functions of local closure classes).


6/19/18  [EDGcpfe/19575]
Ambiguous inheriting constructors in C++17 mode

Consider:

  struct B1 { B1(double); };
  struct B2 { B2(double); };
  struct D: B1, B2 {
    using B1::B1;
    using B2::B2;  // Previously an error about a duplicate constructor
  };               // declaration.
  D d(1.0);        // Now an ambiguity error is issued here instead.

In C++17 mode (and in Microsoft mode with microsoft_version >= 1914) the
front end no longer issues an error on the using-declaration that triggers a
duplicate inheriting constructor declaration.  Instead, the error is postponed
to the point of use (an ambiguity error is issued there).


6/19/18  [EDGcpfe/19486]
Coroutine operations in prototype instantiations

The front end's preliminary support for coroutines (see the entries for
EDGcpfe/16687 and EDGcpfe/15431) previously did not support co_await and
co_yield applied to template-dependent operands.  Now it does.  For example:

  template<typename T> auto coro(T p) {
    co_await p;  // Previously aborted in Microsoft modes that perform
  }              // prototype instantiations.  Now accepted.

Note that the representation of such operations is different from that of
the nondependent version (the template-dependent case is represented using
new eok_await/eok_yield operation kinds, whereas the nondependent case still
uses enk_await/enk_yield nodes).


6/19/18  [EDGcpfe/19664]
Microsoft compatibility: constant expressions as arguments to alignas

A spurious error had been issued in Microsoft emulation mode when parsing
certain constant expressions in an alignas (or possibly other) attributes.
Now fixed.  For example, with --microsoft_version 1913:

  template <int N> struct A;
  template <int T> struct alignas(A<T>::X ? 1: 2) B {};


6/19/18  [EDGcpfe/19751]
IA-64 ABI: explicit specialization of variable template no longer in COMDAT

An explicit specialization of a variable template in IA-64 ABI configurations
is no longer placed in a COMDAT group.  That matches the behavior of GCC and
clang.  For example (with --c++14):

  template<typename T> int vt;
  template<> int vt<double> = 0;  // No longer marked weak and in COMDAT


6/18/18  [EDGcpfe/19263]
Configuration macros for IA64 ABI ARM variants are now target-specific

The following configuration macros have been re-named with a TARG_ prefix
and are now target-specific (see the Changes entry for EDGcpfe/15604 et al.):

  IA64_ABI_USE_GUARD_ACQUIRE_RELEASE
  IA64_ABI_USE_INT_STATIC_INIT_GUARD
  IA64_ABI_USE_VARIANT_ARRAY_COOKIES
  IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR
  IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS
  IA64_ABI_VARIANT_KEY_FUNCTION

Each of these target-specific configuration macros has an associated global
variable (whose value is initially set to the value of the configuration
macro for the selected target).  These variables may be changed during
initialization of the front end (but not during a compilation).

Note that a number of these configuration macros affect the configuration of
the runtime library, so care must be taken to ensure that an object file
generated by the front end is linked with a similarly configured runtime
library (i.e., each target must have a matching runtime library that was
built with --building_runtime with the same settings).  Using the --target
command-line option enables linking with a target-specific library directory.

Any existing settings of the old configuration macros will be used as
default values for the new configuration macros.


6/15/18  [EDGcpfe/13277,EDGcpfe/19047,EDGcpfe/19572,EDGcpfe/19776]
Explicit default constructors

The front end now ignores explicit default constructors when considering
default initialization in copy-initialization contexts.  For example:

  struct S { explicit S() {} };
  S x[3] = {};  // Previously accepted.  Now an error.
  S y({});  // Previously accepted.  Now an error.

This implements the resolution to core issue 1518.


6/15/18  [EDGcpfe/19654]
Microsoft compatibility: constexpr lambdas not interpreted in Microsoft mode

An incorrect test for constexpr lambda mode was done in the interpreter
causing constexpr lambdas to not be considered constant in Microsoft
mode.  Now fixed.


6/15/18  [EDGcpfe/19752]
Incorrect processing of attributes on a declarator

The front end had incorrectly processed cases with multiple attributes on
a declarator, resulting in some attributes being processed multiple times.
The following case (with --clang) had given a spurious error and then
an assertion failure (in enable_if_attribute_fails) and is now fixed:

  void x(void)
         __attribute__((overloadable))
         __attribute__((enable_if(true, "")))
         {}
  void f(void) {
    x();
  }


6/15/18  [EDGcpfe/19756]
Explicit instantiation of partially specialized variable template

A spurious "cannot be instantiated" error could be issued if a variable
template was partially specialized and then explicitly instantiated for
an instance that would make use of a partial specialization.  Now fixed.

  struct A {
    template <typename U> static U x;
    template <typename U> static const U* x<U*>;
  };
  template <typename T> const T* A::x<T*> = nullptr;
  template const int* A::x<int*>;


6/14/18  [EDGcpfe/19764]
Specialization of member variable template not handled properly

If a member variable template was specialized, the specialization was not
actually used to produce the value of the instantiated variable.  Now fixed.

  template <typename T> struct A {
    template <typename U> static const U x = 1;
  };
  template <> template <typename U> const U A<int>::x = 2;
  static_assert(A<int>::x<char> == 2, "wrong value");


6/14/18  [EDGcpfe/19570]
Aggregate class types

The front end erroneously failed to disqualify certain class types from being
aggregate class types.  Specifically, class types with defaulted constructors
marked "explicit" and class types that inherit virtual functions without
declaring their own were sometimes treated as aggregate types.  For example:

  struct S {
    explicit S() = default;
    int i;
  };
  static_assert(!__is_aggregate(S), "Unexpected");  // Previously an error.
                                                    // Now okay.

This is now fixed.


6/13/18  [EDGcpfe/19744]
C++-generating back end: constexpr static data members without initializers

In configurations with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to
TRUE, the C++-generating back end might have to emit C++ code representing the
instantiation of a class template with a constexpr static data member whose
initializer has not been instantiated.  For example:

  template<typename T, T V> struct X {
    static constexpr T value = V;
  };
  int main() {
    X<bool, false> obj;
  }

Here the value of X<bool, false>::value is never accessed and therefore the
associated initializer is never instantiated.  The C++-generating back end
previously rendered the specialization as (slightly reformatted):

  template< class T, T V> struct X { 
    static constexpr T value = (V); 
  }; 
  # 1
  template<> struct X<bool, false>  { 
    static constexpr bool value; 
  }; 
  int main() { 
    X<bool, false>  obj;
    return 0; 
  } 

which is invalid because the constexpr static data member in the explicit
specialization has no initializer.  Forcing the instantiation of that
initializer is in general not an option because it may result in spurious
errors (if that particular instance does not produce a valid initializer).
Instead, the C++-generating back end now leaves out the constexpr specifier
in such cases and instead emits the underlying const type.  The explicit
specialization above is thus rendered as:

  template<> struct X<bool, false>  { 
    static const bool value; 
  }; 

which is valid on its own (it may result in one-definition rule (ODR)
violations if the same specialization is rendered with an initializer
in another translation unit, but back end compilers typically do not
check for such violations).


6/13/18  [EDGcpfe/18905,EDGcpfe/19691,EDGcpfe/19715]
GCC compatibility: Lookup in exception specification operands

Version 4.5 of the front made a change to GNU C++-mode lookup when rescanning
exception specification operands.  That change caused spurious errors in some
cases such as:

  struct E {};
  template<typename> struct X { static const bool value = true; };
  template<typename> struct S {
    typedef E EA;
    template<typename T> struct N {
      N() noexcept(X<EA>::value);  // Previously EA was not found during
    };                             // the instantiation of S<int>::N<int>.
    N<int> n;
  };
  S<int> s;

Here, the typedef name EA was not found during the instantiations kicked off
by the use of S<int>.  That is now fixed.


6/13/18  [EDGcpfe/19771]
Abort in find_base_class_of_full when template parameter type is provided

In some configurations, an abort could occur (in find_base_class_of_full)
when called with a base or derived type that was actually a template
parameter type.  The example below could abort in Microsoft mode when
find_explicitly_overridden_member indirectly resulted in a call of
find_base_class_of_full.  Now fixed.

  template <typename Base> struct Derived : public Base {
    virtual void A::f() {
      return Base::f();
    }
  };


6/13/18  [EDGcpfe/19426]
C++-generating back end, GNU compatibility: nested dependent friend template

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end generated nested
dependent friend template declarations in a form that, although correct,
caused g++ to issue spurious compilation errors.  This now fixed.  For
example, with --gnu_version=60300:

  template <typename a> class b {
    template <typename> struct c {
      using d = c<int>;
      friend d;  // Previously caused spurious compilation errors with g++
    };
  };


6/12/18  [EDGcpfe/19639]
C++-generating back end: call via qualified object to trivial destructor

In cases when a trivial destructor is explicitly invoked via a qualified
object expression, the C++-generating back end erroneously included the
qualifier(s) in the destructor name, producing code that could not be
compiled.  This is now fixed.  For example:

  struct S { };
  void f(S volatile* p) {
    p->S::~S();  // Previously generated as p->volatile S::~volatile S()
  }


6/11/18  [EDGcpfe/19445]
Lookup issue with generic lambdas used in variable template initializers

If a variable template was initialized with a generic lambda, the lookup
of the variable template's template parameters could fail in an instantiation
of the generic lambda that was done via the variable template instance.
Now fixed.

  template <typename T> auto x = [](auto a) { return T(); };
  int y = x<int>(1);


6/11/18  [EDGcpfe/19741]
Assertion failure on alias to entity in secondary translation unit

An assertion failure (remap_ptr_to_entry_number: pointer in secondary trans
unit) would occur if an alias in one translation unit referred to an entity
in another translation unit. Now fixed.  For example, with --g++
--no_il_lowering:

  // file 1:
  static void foo(void) __attribute__((weakref("bar")));

  // file 2:
  void bar(void);


5/30/18  [EDGcpfe/19745]
Caching tokens and user-defined literals

The literal operator associated with a user-defined literal appearing in a
function template or member function of a class template must be looked up
when the function is instantiated from cached tokens, because the result of
the lookup may depend on a using-directive in the function that will only
be parsed during the instantiation, not when the tokens are originally
cached.  Because the results of a lookup performed at the time the tokens
are initially cached would have no effect on the ultimate outcome, as an
optimization, find_literal_operator simply skipped the lookup when
caching_tokens is TRUE.  This approach violates the reasonable expectation,
however, that caching and retrieving tokens should behave the same as
simply fetching the tokens directly.  As a result, the optimization for
caching_tokens has now been removed from find_literal_operator and full
lookups are performed on each call, regardless of whether tokens are being
cached or fetched from a cache.


5/29/18  [EDGcpfe/19701]
Missing diagnostic on auto in typedef

Certain cases of the auto type placeholder in a typedef declaration would not
be correctly diagnosed as erroneous. The invalid typedef declaration would
result in an assertion during the lowering phase. This has now been fixed.
For example: 

  typedef auto f(); // Used to cause an assertion failure.


5/28/18  [EDGcpfe/19667]
Additions and changes to standard feature-test macros

The front end now defines a number of new feature-test macros, as well as
the __has_cpp_attribute preprocessing operator, as described in C++
Committee document P0941R0, and the values of a few existing feature-test
macros have been updated to reflect the values from that document.  The new
macros include: __cpp_deduction_guides, __cpp_guaranteed_copy_elision,
__cpp_nontype_template_args, and __cpp_template_template_args.  The new
__has_cpp_attribute operator takes a single argument, which can be either
the attribute-token of a standard attribute or the name of a GNU attribute
or a Microsoft __declspec attribute.  If the attribute is applicable in the
current emulation, the value for a standard attribute is the six-digit
year and month the attribute was added to the C++ working paper and the
value 1 for a GNU or Microsoft attribute; otherwise the value is 0.  For
example, with --c++14, the variable i will be defined:

  #if __has_cpp_attribute(deprecated)
  int i = 5;  // Will be defined with --c++14 but not with --c++11
  #endif


5/25/18  [EDGcpfe/19223]
Internal error on noexcept on function template default argument

An internal error could occur (in alloc_template_cache_segment) if a
function template default argument contained a function declarator with
a noexcept specifier.  Now fixed.

  template <class T> void f(T x = [](auto) noexcept(false) {return 0;}(0)){}
  int main() {
    f<int>();
  }

5/25/18  [EDGcpfe/19641]
Substitution of local signatures with noexcept (or similar) operator

Consider:

  template<bool B> bool f();
  void g() {
    [](auto x)->decltype(f<noexcept(x)>()) { return 1; }(2);
      // Previously triggered an abort.
  }

The template argument "noexcept(x)" is allocated in the file scope memory
region (as are all template arguments).  However, the entry representing the
operand "x" (and enk_param_ref expression node) is allocated in function
memory scope because that expression could potentially refer to entities local
to the function g().  To bridge the memory region mismatch, an implicit
reference is created using the a_local_expr_node mechanism (see the entry of
4/28/06).  However, previously, that mechanism didn't reliably function during
template substitution of generic lambdas, causing the front end to abort (with
a null pointer dereference) in copy_type_with_substitution.  That is now fixed.


5/25/18  [EDGcpfe/19446]
Spurious error on specialization of variable template

A spurious error was issued on an explicit specialization of a class member
variable template that had an in-class initializer.  Now fixed.

  template <typename T> struct A {
    template <typename U> static constexpr int v = 1;
  };
  template <> template<typename U> constexpr int A<int>::v = 2;


5/24/18  [EDGcpfe/19731]
Constexpr interpreter handling of "this" in default member initializers

Consider:

  struct B {
    int x;
    int y = this->x+1;
  };
  struct D: B {
    int d = B{this->x+2}.y;
  };
  constexpr int r = D{{1}}.d;
  static_assert(r == 4);

The front end produces IL for the cast "B{this->x+2}" that looks somewhat
like the IL for "B{this->x+2, this->x+1}" (where the default initializer for
B::y has been made explicit).  The two occurrences of "this->x" refer to two
different B objects, however: The first refers to the subobject B of the D
object being initialized whereas the second refers to the temporary object
produced by the cast itself.  The two can be distinguished by the flag
"implicit_aggr_element" in the constant entries representing the various
data member initializers (the flag is FALSE for "this->x+2" but TRUE for
"this->x+1" in the expanded aggregate initializer).

The constexpr interpreter, however, failed to respect that distinction,
which caused it to access invalid interpreter storage.  That in turn could
result in an abort or an invalid outcome (e.g., the static_assert in the
example above spuriously failed).  That problem is now fixed.


5/23/18  [EDGcpfe/19716]
GNU and Clang C++ compatibility: matching of template template parameters

When the C++17-style matching of template template parameters is not being
done (see EDGcpfe/18746), g++ and clang accept slightly more general
template template parameter matching.  In the example below, the "int..."
parameter is considered to match the "U..." from the template template
parameter.  We now emulate this when gnu_version >= 60000 and when
clang_version >= 50000.

  template <template <typename U, U... K> class TT> struct A { };
  template <typename T, int... V> struct B { };
  A<B> a;


5/22/18  [EDGcpfe/15023,EDGcpfe/19451]
New command-line option: --vcmeta_directory

A new command-line option, --vcmeta_directory, available only in configurations
where CPPCX_ENABLING_POSSIBLE is TRUE, can be used to specify a directory name
where a suitable vcmeta.dll file can be found.  In the absence of this
command-line option, the default continues to be to search for vcmeta.dll in
the same directory as the module that contains the front end.


5/21/18  [EDGcpfe/19084]
Type of __STDCPP_DEFAULT_NEW_ALIGNMENT__ macro

According to the C++17 Standard, the __STDCPP_DEFAULT_NEW_ALIGNMENT__
predefined macro (see EDGcpfe/17696) is supposed to be "an integer literal
of type std::size_t".  However, the front end simply used the numeric value
of the TARG_DEFAULT_NEW_ALIGNMENT configuration macro as the definition of
__STDCPP_DEFAULT_NEW_ALIGNMENT__, implicitly giving it type int.  This is
now fixed; the value has the appropriate suffix to specify the same type as
std::size_t.  For example, with the front end configured with
TARG_SIZE_T_INT_KIND as ik_unsigned_long_long and
TARG_DEFAULT_NEW_ALIGNMENT as 16, and with the --c++17 command-line
argument:

  int i = __STDCPP_DEFAULT_NEW_ALIGNMENT__;  // macro value is now 16ull


5/21/18  [EDGcpfe/19700]
Abort in add_constant_to_aggregate in Microsoft-mode overload resolution case

Consider the following Microsoft-mode example:

  struct S { char const str[]; };
  struct X { int n; char const *p; };
  struct Y { X x; };
  int f(S);
  int f(Y);
  int r = f({{ 48, "123" }});

Previously, this caused the front end to abort with a null-pointer indirection
in add_constant_to_aggregate (il.c) because the front end attempted to make an
actual IL change when only tentatively matching up the argument of the call to
f() to the first candidate function (for overload resolution purposes).  That
is now fixed.


5/21/18  [EDGcpfe/19660]
User-defined literals in default arguments

The change for EDGcpfe/18711 (not part of a release, but widely distributed
as a patch) resulted in a regression, causing spurious "not found" errors
when a user-defined literal appears in a default argument.  This is now
fixed.  For example, with --c++14:

  double operator "" _f(long double f) { return 0.0; }
  struct Vec3 {
    Vec3(double x);
  };
  struct Test {
    void foo(Vec3 v = Vec3(1.0_f)); // Previously a "not found" error
  };


5/18/18  [EDGcpfe/17429]
Incorrect comparison of semi-dependent types such as void_t

Aliases such as void_t are strange in that the underlying type is always
known, but it must be treated as dependent in certain contexts.  In
some contexts, such as the declaration of a partial specialization in
the example below, different dependent instantiations of void_t were
incorrectly treated as equivalent, resulting in a spurious error.  Now
fixed.

  template <typename...> using void_t = void;
  template <typename, typename = void> struct A {};
  template <typename U> struct A<U, void_t<U>> { };
  template <typename U, typename = void> struct S {};
  template <typename U> struct S<U, void_t<typename A<U>::T1>> { };
  template <typename U> struct S<U, void_t<typename A<U>::T2>> { };


5/17/18  [EDGcpfe/19695]
GNU compatibility: alignment attributes on enumeration types

It appears that GCC ignores alignment attributes on enumeration types in
GCC versions before 6.0.0.  The front end now does the same (with a warning).
A previous check in GCC emulation mode had also generated a spurious error
in cases where an alignment attribute had specified an alignment larger than
the base alignment of the enumeration type.  For example (with --c++11
--gnu_version 50200):

  enum struct alignas(16) E;
  typedef enum struct alignas(16) E { e = 1 } x;


5/17/18  [EDGcpfe/18303,EDGcpfe/19582]
Abort on use of enumerator constant with [[deprecated]] attribute

The front end previously aborted on the following example:

  enum E { z [[deprecated]] };
  template <E e> struct S {
    enum { N = e };
  };
  int main() {
    S<z> sz;
  }

(This triggered an assertion failure in check_use_of_deprecated_entity in
symbol_ref.c.)  That is now fixed.


5/17/18  [EDGcpfe/19696]
C++-generating back end: default member initializer with aggregate expression

When an aggregate-valued constant expression (e.g., a call to a constexpr
function that returns an aggregate) is used as a brace-enclosed default
member initializer, the C++-generating back end failed to enclose the
expression in braces, resulting in uncompilable code.  This is now fixed.
For example, with --c++11:

  struct S {
    constexpr S(int) {}
    static constexpr S f1() { return 0; }
  };
  struct B {
    S s{ S::f1() };  // Previously generated as "s(S::f1())"
  };


5/16/18  [EDGcpfe/17952,EDGcpfe/18905,EDGcpfe/19531]
Instantiation of defaulted noexcept specifiers in class template instances

Consider:

  template<typename> struct X;
  template<typename T> struct C {
    template<typename> struct N {
      N() noexcept(X<T>::value);
    };
    N<int> n;
    C() = default;
  };
  struct D {
    C<int> c;
  };

Previously, the use of C<int> in D caused the front end to force the generation
of the exception specification of the defaulted default constructor of C<int>.
That in turn triggered an error because X has no definition.  Now, the
generation of the exception specification is not forced for defaulted members
of class template instances (unless an explicit exception specification is
also specified on the defaulted member).


5/15/18  [EDGcpfe/16797,EDGcpfe/18532,EDGcpfe/18545,EDGcpfe/19675]
has_flexible_array_initializer and flexible_array_initializer

In Microsoft modes and in GNU C mode, the front end accepts aggregate
initializers for flexible array members (see the entry of 9/1/04).
The original implementation of that feature included setting the flag
has_flexible_array_initializer to TRUE in the associated variable entry.
When aggregate initialization was reworked in version 4.5, that setting
of the flag was lost.  It is now restored.  Similarly, the setting of
the flag flexible_array_initializer in a_constant entries was lost for
cases like these: That too is now restored.


5/10/18  [EDGcpfe/19665]
Freeing of memory too early when FREE_MEMORY_REGIONS_EARLY is TRUE

In configurations where FREE_MEMORY_REGIONS_EARLY is TRUE, it had been possible
to free a memory region while it was still being accessed.  That could happen
when a lambda and its top-level function share the same memory region and led
to undefined behavior (e.g., segfault or assertion failure).  The following
example triggered this behavior in some configurations:

  struct A {
    virtual ~A() { }
    virtual int f() {
      int a;
      [&]() { a = 0; }();
      return a;
    }
  };
  struct B {
    virtual void f() {
      new A;
    }
  };
  void f() {
   B();
  }


5/9/18   [EDGcpfe/19096]
GCC and Clang compatibility: "aligned" attribute on parameters

It appears that GCC accepts the "aligned" attribute on parameter types in some
cases (e.g., when parameter types are pointers or references):

  void foo(float *__attribute__((aligned(256))) p); // GCC accepts
  void bar(float  __attribute__((aligned(256))) p); // GCC rejects

Clang accepts the attribute on all tested types, but doesn't appear to apply
the attribute to the parameter type itself.  A change has been made to accept
the "aligned" attribute when applied to a pointer or reference type (i.e., the
GCC behavior) in both GCC and Clang modes.  The attribute does not affect the
pointer or reference type itself, but a typeref entry is used to carry the
attribute description (so that it can be rendered by the C++-generating back
end).


5/8/18   [EDGcpfe/19482]
decltype applied to function template specialization

When the operand of the decltype operator is an id-expression, whether that
id-expression is parenthesized or not matters.  Previously, the front end
failed to correctly record the absence of parentheses when the operand is the
name of a specialization of a function template.  E.g.:

  template<typename T> void f(T);
  decltype(f<int>) *p;

That caused the back end to render type of p as "decltype((f<int>))*".  That
type is normally a reference to function type, but the front end also failed
to take the presence of parentheses on a function name into account.  It thus
erroneously accepted the C++-generating back end output of the case above.
Both issues are now resolved.


5/8/18   [EDGcpfe/19671]
GNU compatibility: pragma attaching to GNU statement expression

A pragma applied to a statement that contains a GNU statement expression
had mistakenly been applied to the block of the GNU statement expression rather
than to the statement itself.  For example:

  int f(void) {
    #pragma test_next_statement
    return ({ 0; });    // pragma now applies to return statement
  }


5/7/18   [EDGcpfe/19205]
C-generating back end abort on initializer with default member initializer

Consider:

  struct S {
    double d[3] = { 1, []{ return 42.0; }() };
  };
  int main() {
    S{}.d[0];
  }

In C++14 mode, this previously aborted because the front end failed to mark
the constant entry representing the initializer for the temporary produced by
"S{}" as being "partially initialized" (flag is_partially_initialized).  That
is now fixed.


5/7/18   [EDGcpfe/17450,EDGcpfe/19604]
Spurious error on member function definition in Microsoft-mode base class

Consider:

  template<typename T> struct B {};
  template<typename T> struct C: B<T> {
    using B<T>::operator=;
    C& operator=(C const&);
  };
  template<typename T> struct D: C<T> {};

In Microsoft mode, the front end performs a "nonreal instantiation" of
dependent base classes (to emulate certain nonstandard behaviors of the
Microsoft compilers).  In this example, that caused the declaration of
C<T>::operator= to conflict with a declaration implied by the member
using-declaration, which in turned triggered a spurious error claiming
"operator=" has already been declared in C<T>.  That problem is now fixed
(and the example is now accepted in Microsoft modes as it is in other
modes).


5/4/18   [EDGcpfe/19489]
GCC compatibility: #pragma GCC system_header

Previously a header file included by a file that had been designated a
system header by virtue of a "#pragma GCC system_header", had not itself been
considered a system header file, resulting in spurious diagnostics (that
are typically suppressed in system headers).  For example (with --g++ -I.):

  // x.c:
  #include "h1.h"
  extern int x;

  // h1.h:
  #pragma GCC system_header
  #include <h2.h>

  // h2.h:                        Now considered a system header
  extern int * foo () throw ();
  #define x (* foo ())


5/2/18   [EDGcpfe/19545,EDGcpfe/19658]
Mapping corruption during constexpr interpretation of string literals

The constexpr interpreter maintains mappings between the IL representation of
a_constant entries and the temporary storage used in the interpreter to hold
the associated values.  Under some circumstances, that mapping was corrupted,
causing, e.g., string constants to be duplicated instead of shared.  For
example:

  struct S {
    constexpr S(char const *str): str(str) {}
    const char *str;
  };
  void f() {
    S("abc");
    S("abc");
  }

In some configurations, the two instances of the string "abc" produced
distinct entries when instead they should have been shared.  That is now
fixed.


5/2/18   [EDGcpfe/19646]
Member function qualifiers and alias template declarations

The front end previously issued a spurious error on an alias template
declaration denoting a qualified member function type.  For example:

  template<class T> using X = T() const;  // Previously an error.  Now okay.

That is now fixed.


5/2/18   [EDGcpfe/19655]
GNU compatibility: Add builtins for GCC 8.1

512 new builtin functions have been added when gnu_version >= 80100.
Additionally, several builtin functions have different signatures.


5/1/18   [EDGcpfe/19650]
Distinguishing original variable template declarations and redeclarations

While processing a declaration, the front end maintains a state object of type
a_decl_parse_state.  One of the flags in that object is "first_decl", which
reflects whether this is the first declaration of the associated entity that
is seen or whether it is a later declaration (usually, a redeclaration).
However, the flag was previously never set for variable template declarations.
For example:

  template <class T> extern T x;  // (1)
  template <class T> T x = 1;     // (2)

The flag is now set to TRUE for declaration (1) and to FALSE for (2).


5/1/18   [EDGcpfe/19643]
__uuidof constants

Previously, the front end always shared the representation of constants
produced by the __uuidof operator.  Now, that sharing is avoided if a
specific type is recorded in the corresponding ck_address/abk_uuidof entry.
For example:

  struct _GUID {
    char a[16];
  };
  struct __declspec(uuid("{01234567-89ab-cdef-0123-456789ABCDEF}")) S;
  struct __declspec(uuid("{01234567-89ab-cdef-0123-456789ABCDEF}")) T;
  void g() {
    _GUID uuidS = __uuidof(S);  // (1)
    _GUID uuidT = __uuidof(T);  // (2)
  }

Previously, the constant produced for line (2) was the same one as the one
produced for (1), causing, e.g., the C++-generating back end to render the
second line as "... = __uuidof(S);".  Now, distinct constants are recorded,
and the second line is rendered as "... = __uuidof(T);".


4/30/18  [EDGcpfe/19341]
Lowering of lambda members in secondary translation units

The front end previously sometimes failed to lower local lambda members in
secondary translation units (when simultaneously compiling multiple
translation units).  For example, given an empty primary translation unit and
the following secondary translation unit:

  void g() {
    auto lm = [](auto p) { return p; };
  }

the front end previously failed to lower the constructors of the closure
class associated with the lambda local to function g().  That is now fixed.


4/30/18  [EDGcpfe/18996]
Assertion failure: alloc_substitution: missed mangling substitution

In IA-64 ABI configurations where EXPENSIVE_CHECKING is TRUE, an assertion
failure ("alloc_substitution: missed mangling substitution") could occur when
mangling certain types for which the IA-64 ABI pre-defines a substitution.
That has been fixed.  For example (with --c++11):

  namespace std {
    template <class _Ty> using remove_reference_t = _Ty;
    template <class> struct char_traits;
    template <class> class allocator;
    template <class _Ty> void forward(remove_reference_t<_Ty> &);
    template <class, class, class> struct basic_string {
      basic_string();
      basic_string(basic_string &&p1) { forward(p1); }
    };
    basic_string<char, char_traits<char>, allocator<char>> name() {
      return  basic_string<char, char_traits<char>, allocator<char>>();
    }
  }


4/27/18  [EDGcpfe/19637]
Exception specifications on pointer-to-member-function types

The changes for EDGcpfe/17685 added support for exception specifications as
a part of function types, but those changes didn't include pointer-to-member-
function types.  Those changes have now been made.

One note: As mentioned in the Changes entry for EDGcpfe/17685, the
ETS_IS_ELLIPSIS macro has the same value as the
ETS_IS_POINTER_TO_NOEXCEPT_FUNCTION macro and these two are now distinguished
by either ETS_IS_POINTER_TO_MEMBER_FUNCTION or ETS_IS_POINTER being set (prior
to this change, only ETS_IS_POINTER was used to differentiate the two cases).
This is a subtle IL CHANGE.

For example (with --c++17):

  struct S {
    void m(void);
  };
  void f(void) {
    try {
      throw &S::m; // throw of potentially-throwing member function
    }
    catch(void(S::*)(void) noexcept) { }  // not caught
    catch(void(S::*)(void))          { }  // caught
  }


4/26/18  [EDGcpfe/19568]
C++-generating back end and GNU-mode static data member instantiation

In GNU C++ mode, the in-class initializer of a static data member of a class
template is not instantiated unless it is needed (see the entry for
EDGcpfe/16403,EDGcpfe/16644).  When the static data member itself is
instantiated without its initializer also being instantiated, the corresponding
variable entry will have its has_explicit_initializer flag set to TRUE, but
its init_kind field set to initk_none.  The C++-generating back end, when
configured with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE,
previously aborted on such situations.  For example:

  template <typename T> struct S {
    static bool const sdm = false;
  };
  S<int> x;  // Instantiates S<int>::sdm, but not its initializer.
             // Previously caused an abort in some configurations.

That is now fixed.


4/25/18  [EDGcpfe/19566]
Remove DO_C99_IL_LOWERING configuration macro

The DO_C99_IL_LOWERING configuration macro has been removed (its functionality
is now controlled by the DO_IL_LOWERING macro).  A check has been added to
ensure that, if set, the DO_C99_IL_LOWERING macro has the same value as the
DO_IL_LOWERING macro.


4/24/18  [EDGcpfe/19602]
Incorrect handling of temporary for array rvalue bound to reference

Consider:

  struct S {
    double s;
    S(double d): s(d) {}
  };
  typedef S A[3];
  A const &r = A{ S(1), S(2), S(3) };

This involves the direct binding of an rvalue array (temporary) to a reference
(r), which was enabled through the resolution of Core issue 450 (see the entry
of 3/13/07).  However, our implementation of that resolution failed to
implement the possibility of having to extend the lifetime of the array
temporary to match that of the reference: Previously, lowering the example
above caused the lifetime of the temporary array to be limited to the generated
function that performs the initialization.  (I.e., after the initialization was
completed, r became a dangling reference.)  That is now fixed.


4/23/18  [EDGcpfe/19564]
Microsoft compatibility: allow __inline to be used with namespace

In Microsoft mode, __inline could not be used to declare an inline 
namespace. This has now been fixed. For example (with 
--microsoft_version 1913 --c++):

  __inline namespace literals {} //declares an inline namespace
 

4/20/18  [EDGcpfe/19388]
Spurious error on attribute applied to friend definition in class template

A spurious error had been emitted when an attribute appertained to a
friend definition in a class template.  For example (with --c++11):

  template <class T> struct S {
    [[noreturn]] friend int f() { while(1); }
  };


4/20/18  [EDGcpfe/19569]
Microsoft compatibility: --ms_c++latest with microsoft_version 1914

Four C++17 features are now enabled when microsoft_version == 1914 (i.e.,
Visual Studio 2017 version 15.7) and either --ms_c++17 or --ms_c++latest is
specified.  Those features are: variadic using-declarations, strict evaluation
ordering, base classes for aggregates, and auto template parameters.


4/20/18  [EDGcpfe/17499]
Qualified enum names in non-namespace scope

Enum declarations using qualified enum names were erroneously allowed in 
non-namespace scope. This would in certain cases cause a segmentation fault.
Both handling of qualified enums and the segmentation fault are now fixed.

  template <typename T>
  class D1
  {
    enum A : int;
    enum D1::A : int { foo } c; // This line would cause a compiler crash
  };  

  class D2
  {
    enum A : int;
    enum D2::A : int { foo } c; // This used to erroneously compile 
  };


4/18/18  [EDGcpfe/19173]
Error type in IL from lambda with parameter that is an empty pack expansion

In C++14 (or newer) mode, an error type could end up in the IL if a lambda
was declared with a parameter pack with an empty expansion.  The IL for
the lambda was correct, but an error type was created during a prescan
operation.  The presence of that error type could result in an internal
error during name mangling.  Now fixed.

  template <typename> void g();
  template <typename T> struct A;
  template <typename T, typename ... Ts> void f(T...){ }
  template <typename T, typename ... Ts> static void h(T) {
    f([](typename A< Ts >::type...){});
  }
  int main() {
    h(g<int>);
  }


4/18/18  [EDGcpfe/19506]
GNU C++ compatibility: missing "template" keyword bug fixed in g++

The front end emulates a g++ lookup bug (see EDGcpfe/9232) that treats
certain names as templates without use of the "template" keyword.  This
bug has been fixed in g++, so the emulation is no longer done when
gnu_version is >= 60000.  The emulation caused us (and the bug caused g++)
to issue spurious errors on examples such as this one.

  namespace N { template <typename T> int g(); }
  template <typename T> struct A {
    A() : g(0) {}
    int g;
  };
  using namespace N;
  template<typename T> inline void f() {
    A<T> a;
    while (a.g < 10) { }  // Formerly: expected a ">"
  }
  int main() {
    f<int>();
  }


4/18/18  [EDGcpfe/19563]
Incorrect value for export_template_allowed when EXPORT_ENABLING_POSSIBLE is
FALSE

It had previously been possible to have export_template_allowed set to TRUE
even in configurations where EXPORT_ENABLING_POSSIBLE is FALSE.  Now fixed.


4/17/18  [EDGcpfe/19562]
Spurious error on label in a lambda function

The presence of a label in a lambda function disqualifies the lambda function
from being considered constexpr (see the Changes entry for EDGcpfe/17690),
but a spurious error had been issued previously.  Now fixed.  For example
(with --c++17):

  auto l = []() {
    label01: return 0;      // No spurious error.
  };
  constexpr auto x = l();   // But, can't be used in a constant expression.


4/17/18  [EDGcpfe/19098]
Microsoft compatibility: sizeof(T::X) incorrectly treated as a type

In Microsoft mode (actually in modes in which implicit typename is
enabled), a dependent operand of a sizeof that was a parenthesized
expression was incorrectly considered to be a type, resulting in
incorrect behavior.  Now fixed.

  template <class T> void f(typename T::template X<sizeof(T::Y)>*);
  struct A {
    template <int I> struct X {};
    static const int Y = 1;
  };
  int main() {
    f<A>(nullptr);  // Formerly "no instance ... matches"
  }


4/16/18  [EDGcpfe/18002,EDGcpfe/19387]
Spurious partial ordering ambiguity involving default template arguments

Partial ordering could fail to select a more specialized function in
some cases involving a function template with a function parameter that
did not participate in partial ordering (because it had a default function
argument) and if the type of the defaulted function parameter used a template
parameter that had a default template argument and was not otherwise
deduced by the partial ordering process.  Now fixed.

  template <typename T, typename U, typename V = int> void f(T, U, V* = 0);
  template <typename T> void f(T, int);
  int main() {
    f(1, 2);
  }


4/13/18  [EDGcpfe/19554]
Abort on defaulted special member with explicit exception specification

Consider:

  struct B { B(B&&) noexcept(false); };
  struct D: B {
    D(D&&) noexcept(false) = default;
  };

In C++14 mode (and some GNU C++11 modes) this previously aborted in
def_arg_and_eh_spec_fixup_for_class (class_decl.c) on a null-pointer
indirection.  That is now fixed.


4/12/18  [EDGcpfe/19544]
New-expressions and decltype(auto)

In C++14 mode, the front end now accepts new-expressions where the type is
specified as decltype(auto).  For example:

  int *p = new decltype(auto)(42); // Now accepted.


4/11/18  [EDGcpfe/19543]
Diagnostic on invalid use of decltype(auto) in typedef declaration

Consider:

	typedef decltype(auto) X; // Invalid.

Previously, the diagnostic for this invalid use of decltype(auto) referred to
the "auto" type specifier.  Now, it mentions "decltype(auto)" instead.


4/11/18  [EDGcpfe/19546]
Out-of-bounds numeric parts of user-defined literals appearing in templates

The front end previously reported spurious errors for user-defined literals
appearing in templates when the numeric part of the literal overflowed or
underflowed the parameter type for an ordinary literal operator, even when
a raw literal operator or literal operator template is visible.  This is
now fixed.  For example, with --c++14:

  template<char...> int operator ""_xyz() { return 0; }
  template<typename T> int f() {
    return 0x1'0000'0000'0000'0000_xyz;  // Too large for 64-bit unsigned long
                                         // long, previously an error
  }
  int i = f<int>();


4/11/18  [EDGcpfe/19087]
Spurious error on decltype(auto)  with --auto_storage

Use of decltype(auto) would result in a compilation error when --auto_storage
was in effect. That has now been fixed.  For example, with --c++14 
--auto_storage:

  decltype(auto) x = 2; // Previously resulted in invalid combination of type
                        // specifiers


4/11/18  [EDGcpfe/19335]
C++-generating back end: decltype as target of dependent reference cast

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end failed to use a
decltype operator that results in a dependent reference type in a cast,
instead using the dependent type directly as the target type.  For example,
with --c++14:

  auto const lambda = [](auto &&... x) {
    return [&](auto&& y) -> decltype(auto) {
      return y(static_cast<decltype(x)>(x)...); // Previously generated as
                                                // static_cast<auto &&>(x)
    };
  };


4/10/18  [EDGcpfe/19497]
Attributes on variable template definitions

Due to a logic error, attributes were not being attached to variable
templates.  That has now been fixed.  For example (with --gnu_version 60000):

  template <class T> __attribute__((aligned(16))) int x = 0;


4/6/18   [EDGcpfe/19520]
Segfault in is_nothrow_spec on use of typedef for function

In configurations that do lowering, certain uses of typedefs for function
types had resulted in a segmentation fault in is_nothrow_spec.  For example
(with --c++17):

  void f(int) noexcept {}
  typedef void (FP)(int);
  int main() {
    try {
      throw f;
    }
    catch (FP) {
    }
  }


4/5/18   [EDGcpfe/18813]
Clang compatibility: alias declarations in non-C++11 mode

Alias declarations and alias template declarations are now accepted (with a 
warning) in clang C++98/03 modes.


4/4/18   [EDGcpfe/16738,EDGcpfe/16996,EDGcpfe/19207,EDGcpfe/19416]
_Pragma operator with UTF and raw string literals

The C++ Standard only requires that the _Pragma operator accept unprefixed
and wide (L"...") string literals as operands, and the front end failed an
assertion (in copy_pragma_string) if a different form of string literal is
used.  In anticipation of action by the C++ Committee to address this
limitation, the front end now accepts all forms of string literals as
operands for _Pragma.  For example, with --c++11:

  __Pragma(R"abc(some_pragma)abc")  // Previously aborted


4/3/18   [EDGcpfe/19508]
Microsoft compatibility: --[no_]ms_cplusplus_std_value command-line options

The --[no_]ms_cplusplus_std_value command-line options have been added to
emulate Microsoft Visual Studio's /Zc:__cplusplus[-] command-line options.
When --ms_cplusplus_std_value is specified, the __cplusplus macro has the value
specified in the C++ Standard corresponding to the language version, e.g.,
201402L for C++14. (This is the same value as the _MSVC_LANG macro).
Otherwise, __cplusplus has the value 199711L for all language versions in
Microsoft mode.  Specifying this command-line option also implies Microsoft
emulation mode.

This change also enables terse static_asserts and nested namespace definitions
in modes where Visual Studio also enables them.


4/2/18   [EDGcpfe/17489]
C++-generating back end: missing "template" keyword in friend declaration

In a configuration in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end failed to add a
necessary "template" keyword in a friend declaration with a dependent
nested-name-specifier.  This is now fixed.  For example, with --c++11:

  template <class T> struct S2 {
    typedef typename T::template v<1> C;
    friend C;  // Previously generated as "friend class T::v<1>"
  };


4/2/18   [EDGcpfe/19478]
Clang compatibility: __has_feature vs language version

The front end previously treated the clang __has_feature and __has_extension
feature-test macros identically, giving the value 1 if the named feature is
supported in the current invocation of the front end and 0 otherwise.  The
clang compiler, however, only gives the value 1 for __has_feature if the
named feature is part of the specified version of the C++ Standard, even if
the feature actually is supported.  The front end has now been changed to
emulate this behavior.  For example, with --clang --c++03:

  int i = __has_feature(cxx_atomic);  // Previously 1, now 0


3/30/18  [EDGcpfe/19260]
Internal error on diagnostic issued in rescan of variable template parameter

An internal error could occur (in include_in_context_output) if a diagnostic
was issued during the rescan of a dependent template parameter of a
variable template declaration.  Now fixed.

  template <class T, T t = 1.0> T x = t;
  int i = x<int>;


3/29/18  [EDGcpfe/19504]
Microsoft compatibility: TARG_DEFAULT_NEW_ALIGNMENT and
TARG_MAXIMUM_INTRINSIC_ALIGNMENT

In the defines.h.win32 sample configuration file, the default value for
TARG_MAXIMUM_INTRINSIC_ALIGNMENT is now 8 on both 32-bit and 64-bit
configurations.  The default value for TARG_DEFAULT_NEW_ALIGNMENT is now 8 on
32-bit configurations and 16 on 64-bit configurations.  See the Changes entry
for EDGcpfe/17696 for more information.


3/29/18  [EDGcpfe/18118,EDGcpfe/19499]
Microsoft compatibility: __declspec(empty_bases)

The "empty_bases" __declspec attribute is now accepted in Microsoft emulation
mode.  The presence of the attribute is recorded in the IL but has no effect
(as the EDG front end does not emulate the layout of the Microsoft compiler).
For example:

  struct S1 {};
  struct S2 {};
  struct __declspec(empty_bases) S3 : S2, S1 {
    char c;
  };


3/29/18  [EDGcpfe/19501]
Precision of numeric value in user-defined float literals

The front end previously lexed the numeric value of a user-defined float
literal as a double, converting the value to long double to pass to the
associated user-defined literal operator.  This could lead to loss of
precision in the value.  The front end now lexes such values as long
doubles.  The effect of this issue can be seen in the output of the
C++-generating back end.  For example, on some architectures with --c++11:

  long double operator "" _foo(long double p){
    return p;
  }
  long double d = 1.12e1_foo;  // Previously generated as
                               // 11.199999999999999289_foo



3/28/18  [EDGcpfe/17558,EDGcpfe/19264]
Incorrect matching of arguments to variadic template template parameter

If a non-variadic class template is matched to a variadic template
template parameter, and the non-variadic template has additional parameters
with default arguments, a spurious error could result.  Now fixed.

  template <typename T, typename = void> struct A {};
  template <template <typename...> class T, typename U> void f(T<U>) {}
  int main() {
    A<int> a;
    f(a);
  }


3/28/18  [EDGcpfe/19242]
Incorrect evaluation of noexcept operator of variadic member function template

In C++17 mode, the evaluation of a noexcept operator of a variadic function
template that is a member of a class template could result in a spurious
error.  Now fixed.

  template <typename T> struct A {
    A(T t){}
    T g() noexcept { return T(); }
    template <typename... Args>
        decltype(auto) operator()(Args... args)
                       noexcept(noexcept(this->g()(args...))) {
      return this->g()(args...);
    }
  };
  template <typename T> A<T> f(T t) { return A<T>(t); }
  struct B {
    bool operator()(int) { return true; }
  };
  int main() {
    auto h = f(B{});
    h(10);
  }


3/28/18  [EDGcpfe/19463]
C++-generating back end, GNU compatibility: compound literals and constructors

The C++-generating back end previously failed an assertion (in
gen_compound_literal) when C++ source has a C99-style compound literal that
results in invoking a constructor (a situation that can arise in g++ mode).
This is now fixed.  For example, with --g++:

  struct S1 { S1(unsigned); };
  S1 d = (S1){1};  // Previously resulted in an assertion failure


3/27/18  [EDGcpfe/18851,EDGcpfe/19408,EDGcpfe/19409,EDGcpfe/19496]
Spurious error on lambdas with non-constexpr constructs in C++17 mode

Consider:

  struct D { ~D() {} };
  void g() {
    auto x = []()->D { D d; return d; }();  // Previously an error.  Now okay.
  }

In C++17 mode the front end issued a spurious error complaining that the
return type of the lambda cannot be a nonliteral type (because the front end
erroneously treated the lambda call operator as a constexpr function).  That
is now fixed, as are a few similar issues (e.g., a "try block" in a C++17
lambda expression was incorrectly diagnosed as being invalid in a constexpr
function).


3/27/18  [EDGcpfe/17883]
Exception specification of defaulted member established too late

In some cases, the front end did not establish the exception specification of
a defaulted member in time to produce a correct result for the "noexcept"
operator.  For example:

  template<typename T> struct B { B() noexcept {} };
  template<typename T> struct D: B<T> { D() = default; };
  template<bool Cond> struct V { static constexpr bool value = Cond; };
  struct N: V<noexcept(D<int>())> {};
  static_assert(N::value, "Unexpected");
    // Previously failed.  Now okay.

Previously, this example failed the static assertion because the exception
specification of D<int>::D() was not established by the time the "noexcept"
operator in the definition of N is evaluated.  That is now fixed.


3/27/18  [EDGcpfe/19492]
C++-generating back end: macro expansion in unrecognized pragmas

In C++-generating back end configurations in which
INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL is TRUE, the front end has now been
changed to expand macro invocations appearing in the text of unrecognized
#pragma directives.  For example, with --microsoft:

  #define _STL_WARNING_LEVEL    4
  #pragma warning(push,_STL_WARNING_LEVEL)  // Now generated as
                                            // #pragma warning(push,4)


3/26/18  [EDGcpfe/19490]
Configuration macros are no longer target-specific

The configuration macros TARG_MINIMUM_PACK_ALIGNMENT and
TARG_MAXIMUM_PACK_ALIGNMENT are no longer target-specific (see the Changes
entry for EDGcpfe/15604 et al.).  These macros are closely tied to the
setting of the non-target-specific configuration macro TYPE_FOR_TARG_ALIGNMENT
(whose value is used as the type for various fields in the front end), so
requiring target-specific values for each target (where the value must be
the same for all targets) seemed overly restrictive.


3/26/18  [EDGcpfe/19063]
Incorrect substitution of template template parameter used by alias

If an alias template used a template template parameter, and that alias
was then used in a default argument of a function template, the alias
was sometimes not substituted properly, resulting in spurious errors.
Now fixed.

  struct A { static const bool value = true; };
  template <class T> struct B {};
  template <template <class> class T> struct C {
    template<template <class> class U, class = U<void>> static A f();
    using type = decltype(f<T>());
  };
  template <template<class> class T> struct D {
    template<class W> using my_f = T<W>;
  };
  bool b = C<D<B>::my_f>::type::value;


3/26/18  [EDGcpfe/19434]
Microsoft compatibility: __builtin_launder

In Microsoft modes with microsoft_version >= 1914, the front end now accepts
the built-in pseudo-function "__builtin_launder".  It is modeled as a function
with type "void* (void*)", but calls to it are treated specially:

  (1) The argument must be a pointer type after array-to-pointer and
      function-to-pointer conversions are applied (user-defined conversions
      are not considered).
  (2) The type of the call is the same as the type of the argument pointer.
  (3) The constexpr interpreter treats calls to __builtin_launder as
      equivalent to the evaluation of its argument.

This utility is meant to help the implementation of C++17's std::launder
template.


3/26/18  [EDGcpfe/19057]
GNU C++ compatibility: static data member initializer ending with ">>"

In g++ mode, class template static data members are cached and only
instantiated if they are used.  This processing did not correctly handle
a ">>" that closes two template argument lists, resulting in spurious
errors.  Now fixed.

  template <typename T> constexpr bool v = true;
  template <typename T> using v2 =  int;
  template <typename T> struct A {
    static constexpr bool value = v<v2<int>>;
  };
  A<int> a;


3/22/18  [EDGcpfe/19095]
C++-generating back end, GNU compatibility: asm names and attributes

For a function declaration with both an asm name and an attribute, the
C++-generating back end previously put out the attribute first followed by
the asm name.  This order is the reverse of the syntax expected by gcc.
The C++-generating back end has now been changed to put out these
constructs in the correct order.  For example, with --g++:

  int foo() { return 0; }
  __typeof(foo) foo  __asm__("x");
  __typeof(foo) bar __asm__("foo");
  // Previously generated as __attribute__((alias("x"))) __asm__("foo"):
  __typeof(foo) bar __attribute__((alias("x")));


3/22/18  [EDGcpfe/19477]
Unneeded code for handling of control flow descriptors

Various fragments of code handling control flow descriptors were removed from
statements.c either because they could never be exercised or because they had
no real effect and reduced overall performance.


3/22/18  [EDGcpfe/19460]
Assertion failure in mangled_encoding_for_sizeof_pack

In some (mostly C++-generating) configurations where MANGLE_ALL_NAMES is TRUE,
the mangling of a tpck_member or tpck_unknown template parameter type as
an argument to sizeof... had resulted in an assertion failure in
mangled_encoding_for_sizeof_pack.  These template parameter types can occur
when mangling prototype instantiations and as there is no standard mangling
string for such entities, a "?" is inserted into the mangled name (as is
currently done when such template parameters occur in other contexts).  For
example (with --c++11):

  template <int N> struct MI { };
  template<typename T> struct BE { };
  template<typename T> using BE_T = typename BE<T>::type;
  template<typename... Ts> using CT = typename MI<sizeof...(Ts)>::type;
  template<typename... Args> auto f(Args &&... args) ->
                                          decltype(CT<BE_T<Args>...>{args...});


3/22/18  [EDGcpfe/19358]
Internal error on variable template with missing template argument list

An internal error could occur (in scan_field_selection_operator or
scan_identifier) if a variable template was used without a template
argument list in certain contexts.  Now fixed.

  struct A {
    template <class T> static int i; 
  };
  template <int*> struct B { };
  A a;
  int A::i;
  B<&a.i> b;


3/20/18  [EDGcpfe/17642]
C++-generating back end: assertion failure with decltype in template argument

The C++-generating back end previously failed an assertion (in function
get_param_for_param_ref) when a template instance for which a template
argument refers to a function parameter via a decltype operator is referred
to in a different context.  This is now fixed.  For example, with --c++11:

  template <typename T> using type_t = T;
  template <typename T> T fn1(T a, T b);
  template <typename T, typename U>
  auto fn2(T t, U u) -> type_t<decltype(t*u)>;
  void fn3(int a) {
    fn2(a, a);                         // Instantiates type_t<int> as
                                       // type_t<decltype(t*u)>
    fn1<type_t<decltype(a+a)>>(a, a);  // Uses type_t<int> but t and u are
                                       // unavailable in this context, which
                                       // led to an assertion failure
  }


3/20/18  [EDGcpfe/19285]
Duplicate static data member definitions and class templates (IL CHANGE)

Consider:

  template<typename T> struct S {
    static constexpr int x = 0;
  };
  template<typename T> constexpr int S<T>::x;
  template<typename T> constexpr int S<T>::x;

In pre-C++17 modes this is invalid, but the front end previously failed to
issue an error on the second static data member definition.  (In C++17 the
example is valid because the out-of-class declaration is not a definition.)
Furthermore, in all modes, the C++-generating back end aborted with an internal
error in gen_template.  These problems are now fixed.  As part of this fix,
an IL CHANGE was made: The primary source sequence entry for a static data
member that has an initializer associated with it is now always the entry
describing the declaration that includes the initializer (even if that
declaration is not technically the definition).


3/20/18  [EDGcpfe/19427]
Variable templates and multiple translation units

Previously, the front end did not handle variable templates when simultaneously
compiling multiple translation units: Often such cases resulted in internal
errors.  That support has now been added.


3/20/18  [EDGcpfe/16021,EDGcpfe/19432]
Calls to "final" member functions

Previously, declaring a virtual member function (or its enclosing class)
"final" or (in some Microsoft modes) "sealed" did not affect the representation
of calls to that function: The associated is_virtual_call flag could be TRUE.
Now, the is_virtual_call flag is always set to FALSE when calling such a
function directly.


3/20/18  [EDGcpfe/18791]
Microsoft compatibility: Additional changes for overaligned allocation

The behavior associated with overaligned allocation (EDGcpfe/17696, a C++17
feature first supported in version 4.14) has been slightly modified in
Microsoft modes, as follows: __STDCPP_DEFAULT_NEW_ALIGNMENT__ is
unconditionally defined in all Microsoft C++ modes, regardless of whether
overaligned allocation is supported, and the macro _ALIGNED_NEW_SUPPORTED
is predefined to the value 1 in Microsoft modes when overaligned allocation
is supported.  In addition, the front end now allows control of this
feature via the --[no_]aligned_new command-line option.


3/19/18  [EDGcpfe/19457]
Build issue with LOWER_DESIGNATED_INITIALIZERS set to FALSE

IA-64 ABI configurations where LOWER_DESIGNATED_INITIALIZERS is set to FALSE
did not build due to a change introduced by EDGcpfe/16860 (4.11).  Now fixed.


3/17/18  [EDGcpfe/19133]
Microsoft compatibility: spurious error on in-class constructor specialization

When Microsoft base class processing is enabled (which is the default in
Microsoft mode), a spurious error could be issued on an in-class specialization
of a constructor template.  Now fixed.

  template<typename T> struct  A {
    template<typename U> A(const A<U>& p) : x(0) { }
    template<typename U> A(U* p) : x(0) { }
    template<> explicit A(A* p) : x(0) { }
    int x;
  };
  template<typename T, class U> struct B : public A<T> { };


3/15/18  [EDGcpfe/19435]
Exception specifications as part of function types disabled when exceptions
are disabled

When exceptions are disabled, exception specifications as part of function
types (see the changes for EDGcpfe/17685 et al.) are now also disabled.
That has the effect of disabling the __cpp_noexcept_function_type feature
test macro which allows certain versions of the <type_traits> header file
to compile with --no_exceptions.


3/15/18  [EDGcpfe/19443]
Clang compatibility: const-qualified argument to __builtin_nontemporal_load

A call to __builtin_nontemporal_load with a pointer to a const-qualified type
had resulted in a spurious error and is now fixed.  For example (with
--clang_version 50000):

  typedef long long __m128i __attribute__((__vector_size__(16)));
  typedef long long __v2di __attribute__ ((__vector_size__ (16)));
  __m128i foo (__m128i const *__V) {
    return (__m128i) __builtin_nontemporal_load ((const __v2di *) __V);
  }


3/15/18  [EDGcpfe/19448]
Clang compatibility: default to C++14 mode when clang_version >= 60000

Clang 6.0.0 has enabled C++14 features by default.  Accordingly, when
clang_version >= 60000 and no explicit C++ mode has been specified, C++14
features are now enabled in Clang emulation mode.


3/13/18  [EDGcpfe/19444]
Assertion failure in make_make_integer_seq_internal_template

An assertion failure (in make_make_integer_seq_internal_template) had resulted
in clang emulation mode if gnu_version <= 40300 and C++11 mode is not enabled.
Now fixed.


3/13/18  [EDGcpfe/19941,EDGcpfe/19942]
Clang compatibility: Clang 6.0.0 builtins

The signatures for builtin functions have been updated to match those in
clang 6.0.0.  A total of 159 new builtins were added.


3/7/18   [EDGcpfe/19399]
Abort on explicit template arguments for function with fold expression

The front end previously could abort with an internal error in function
rescan_pack_expansion when processing a call with explicit template arguments
to a function whose signature involves a C++17 fold expression.  For example:

  template<int> struct N {};
  template<int... Is> void f(N<(b + ...)>) {
    f<3>({});  // Previously triggered an internal error.
  }

That issue is now fixed.


3/5/18   [EDGcpfe/17698]
C++17: auto nontype template parameters

C++17 "auto" nontype template parameters (originally described in P0127R2)
are now implemented.

  template <auto x> struct A { };
  A<2> a1;   // template parameter type is int
  A<'a'> a2; // template parameter type is char


3/6/18   [EDGcpfe/19400]
Zero-initialization of vector types in constexpr evaluation

The interpreter previously was not equipped to zero-initialize vector type
objects.  Attempting to do so resulted in an internal error.  That is now
fixed.  For example, in GNU C++11 mode:

  using VI4 = __attribute((vector_size(16))) int;
  struct S { VI4 v; };
  S &&rs = S{};  // Previously triggered an internal error.  Now okay.


3/5/18   [EDGcpfe/17486]
C++-generating back end: non-standard opaque enumeration declarations

The C++ Standard only permits opaque enumeration declarations as standalone
declarations, not as an elaborated-type-specifier.  However, other
compilers do not enforce this restriction, so the front end accepts such
nonstandard elaborated-type-specifiers in non-strict modes.  The
C++-generating back end, however, did not correctly generate these
constructs, omitting the "class" keyword.  This has now been fixed.  For
example, with --c++11:

  using E = enum class E;   // Previously generated as "enum E"


3/1/18   [EDGcpfe/19380]
Incorrect interpretation of default array member initialization

Consider:

  struct C {
    int d[2][2];
    C C::*pm = pm;
  };
  constexpr C c = {};

This example requires the constexpr interpreter to zero-initialize the array
member of variable c.  This initialization was previously done incorrectly,
causing the subsequent member (c.pm) to be marked as "initialized".  In this
example, that resulted in the interpreter not noticing that the use of the
default initializer of C::pm accesses an uninitialized member (which should
trigger an error).  The resulting use of uninitialized memory was likely to
result in an abort.  That problem is now fixed.


3/1/18   [EDGcpfe/19389]
__func__ in constexpr functions

The front end previously failed to diagnose the use of __func__ (and similar
constructs) in constexpr functions: It defines a local static variable, which
is not permitted in constexpr function definitions.  However, the interpreter
also failed to evaluate the construct.  Now, a diagnostic is issued, except in
GNU and Clang modes, where the construct is correctly interpreted.  For
example:

  constexpr char f() { return __func__[0]; }
    // Now a compilation error, except in GNU and Clang modes.
  static_assert(f() == 'f', "Unexpected!");
    // Now accepted in GNU and Clang modes.


2/28/18  [EDGcpfe/14779,EDGcpfe/18590,EDGcpfe/18731]
Clang attribute "overloadable"

In Clang mode, the front end now accepts the attribute "overloadable" on
function declarations.  It has no effect in C++ mode, but in C mode it
enables C++-style overloading of functions.  For example:

  __attribute((overloadable)) void f(int);     // (1)
  __attribute((overloadable)) void f(double);  // (2)
  int main() {
    f(3.0);  // Calls (2).
  }

If lowering is enabled, the function name is mangled according to the C++
ABI that is configured.


2/28/18  [EDGcpfe/17745]
C++-generating back end: aggregate initialization of a reference

The C++-generating back end previously failed an assertion (in
gen_initializer_constant) when a reference is initialized with an aggregate
constant.  This is now fixed.  For example:

  typedef const char (&T)[4];
  T r = T{};   // Previously caused an assertion failure


2/28/18  [EDGcpfe/18892]
Friend template declarations in prototype instantiations

Consider the following two translation units:

  // File 1:
  template<typename> struct H;
  template<typename> struct V {
    template<typename> friend struct H;
  };

  // File 2:
  template<typename> struct V {
    template<typename> friend struct H;
  };
  template<typename> struct H;

During the prototype instantiation of V, the friend declaration finds a
template in the first file, but not in the second file.  In the second file,
therefore, a nested class placeholder is created to represent the friend
template declaration.  However, that difference between the two files caused
spurious correspondence errors when simultaneously compiling them.  The front
end has therefore been changed to represent the friend template in the first
file as it already was done in the second file.


2/26/18  [EDGcpfe/18318]
C++-generating back end: decltype-specifiers as template arguments

When the source code contains a decltype-specifier used as a template
argument and the type designated by the specifier is an unnamed class type,
the C++-generating back end put out an undeclared temporary name (of the
form __T12345678) as the argument.  This is now fixed.  For example:

  template <typename T> T x;
  struct { } s1;
  void f() {
    x<decltype(s1)>;  // Previously generated as x<__T12345678>
  }


2/26/18  [EDGcpfe/19386]
Failure to diagnose bool parameter for user-defined literal operator

The front end previously failed to diagnose an attempt to declare a
user-defined literal operator with a parameter of type bool, which is not
one of the allowed parameter types.  This is now fixed.  For example, with
--c++11:

  void operator "" _b (bool) { }   // Invalid but previously undiagnosed


2/26/18  [EDGcpfe/18648,EDGcpfe/19337]
Clang compatibility: _Alignof, _Generic, _Noreturn, _Thread_local

The _Alignof, _Generic, _Noreturn, and _Thread_local keywords (and their
associated behaviors) are now enabled in Clang C++ mode (when clang_version
>= 30000 for _Generic, when clang_version >= 30200 for _Alignof, and when
>clang_version >= 30300 for _Noreturn and _Thread_local).


2/23/18  [EDGcpfe/19331]
Deduction of additional argument in a function template-id passed to reference

Consider:

  template<typename, typename T> void f(T);
  typedef void F(int);
  struct S {
    S(F* const&);
  };
  S s(&f<long>);  // Previously an error.  Now okay.

Previously, the front end failed to match &f<long> (whose second template
argument still needs deduction) against the constructor of S because it
did not consider the possibility of an rvalue pointer-to-function matching
an lvalue reference type (when such a match is possible if the reference is
to a const pointer type).  That is now fixed.


2/23/18  [EDGcpfe/19371]
Incorrect "optimization" during lowering leads to incorrect code

In some cases, lowering attempts to determine if an expression has a known
value, or failing that, whether the expression will always evaluate to a
non-zero value.  A logic error in is_constant_valued_expression had resulted
in incorrectly determining that some eok_dot_field and eok_points_to_field
expressions would always return a non-zero value.  That could lead to
incorrect optimizations such as:

  struct S {
    int m1;
    int m2;
  };
  S f(void) {
    S s;
    s.m1 = 0;
    s.m2 = 0;
    return s;
  }
  int g(int a) {
    return f().m2 || a;   // "|| a" had inadvertently been dropped
  }
  int main() {
    return g(1);          // Had returned 0, now returns 1
  }

This is a regression introduced by EDGcpfe/16550 in 4.11.


2/23/18  [EDGcpfe/17927,EDGcpfe/19372]
Clang/Microsoft compatibility: predefined Microsoft macros

Previously, predefined Microsoft macros (like _MSC_VER and _WIN32) were
defined when ms_extensions was TRUE (i.e., with --ms_extensions).  A change
has been made to define these only when microsoft_mode is TRUE.  This better
aligns with Clang's behavior (with -fms-extensions).


2/23/18  [EDGcpfe/18496]
Invalid multibyte sequences in #line directives

The front end has reported all invalid multibyte character sequences as a
discretionary error.  This severity is appropriate in most contexts, since
an incorrect interpretation of the meaning of a character or string literal
or identifier could result in link- or run-time failures.  The character
string identifying the file name in a #line directive, however, is less
sensitive, typically used only in diagnostic output to identify source
locations, so the front end has now been changed to report invalid
sequences in #line directives as warnings.


2/23/18  [EDGcpfe/19287]
C++-generating back end: parenthesized initializer for decltype(auto)

When generating the declaration of an automatic variable declared with the
decltype(auto) specifier and initialized with a parenthesized variable
name, the C++-generating back end failed to add the parentheses to the
initializer.  As a result, the variable had the wrong type in the generated
code.  This is now fixed.  For example, with --c++14:

  int a;
  void f() {
    decltype(auto) r = (a);  // Previously generated as "r = a", changing
                             // the type of r from int& to int.
  }


2/22/18  [EDGcpfe/18339,EDGcpfe/19375]
Abort on use of __has_assign in some Microsoft modes

In Microsoft modes with microsoft_version >= 1800, the front end previously
failed an assertion check in fold_unary_type_trait_helper (folding.c) on code
using the __has_assign type traits helper.  This regression was introduced in
version 4.11 (through the changes for EDGcpfe/16871) and is now fixed.


2/21/18  [EDGcpfe/18739,EDGcpfe/18901,EDGcpfe/19143,EDGcpfe/19684]
Empty classes and constant expressions

Non-constant variables of empty class types with trivial copy constructors can
now be copied in constant expressions.  For example:

  struct S {};
  constexpr int z(S) { return 0; }
  void g(S x) {
    constexpr int r = z(x);  // Now permitted.
  }

(An error is still issued in Microsoft mode and in some Clang and GNU modes
for compatibility with the corresponding compilers.)


2/21/18  [EDGcpfe/17440,EDGcpfe/18755]
Function modifiers and parenthesized member declarators

The front end previously did not correctly parse function modifiers like
"final" when the underlying function declarator is parenthesized.  For example:

  struct S {
    virtual int (f()) final;  // Previously a spurious error.  Now okay.
  };

This is now fixed.


2/20/18  [EDGcpfe/19370]
__is_standard_layout and duplicate base class types

The C++ standard specifies that a class with two distinct base subobjects of
the same type is not a standard-layout class (this was clarified by the
resolution of Core issue 1813).  However, Clang and GCC appear not to implement
that particular rule.  The front end now emulates that behavior in the
corresponding modes.  For example:

  struct B { };
  struct C : B { };
  struct D : B , C { char d; };
  static_assert(!__is_standard_layout(D), "Nonstandard");
    // Now fails in GNU and Clang modes.


2/20/18  [EDGcpfe/19328]
Mutable members and constant expressions

The front end previously ignored the "mutable" specifier when loading a data
member from a constant in the evaluation of a constant expression, thereby
accepting invalid constant expressions.  For example:

  struct S { mutable int x; };
  constexpr S s{42};
  constexpr int r = s.x;  // Previously accepted.  Now an error.

This is now fixed.


2/20/18  [EDGcpfe/19346]
Abort on Microsoft-mode using-declaration in multi-translation unit check

When simultaneously compiling multiple translation units with corresponding
using-declarations, the front end sometimes aborted with an internal error
in function equiv_base_using_decls (trans_corresp.c).  For example:

  template<typename> struct B {};
  template<typename T> struct D: B<T*> {
    using typename B<T*>::Type;  // Correspondence checking did not expect
  };                             // the Microsoft-mode representation of this
                                 // using-declaration.

Compiling two identical files with the code above previously resulted in an
internal error.  That is now fixed.


2/19/18  [EDGcpfe/19343]
Pack expansion in scalar mem-initializers

Consider:

  struct S {
    template<typename... Ts> S(Ts ...ps): m(0, ps...) {}
    int m;
  };
  S s;

Previously, this triggered an error because the front end did not consider
the possibility of pack expansions in the mem-initializer for a scalar
subobject.  That is now fixed.


2/17/18  [EDGcpfe/18675]
C++-generating back end: linkage specifications on function definitions

The C++-generating back end previously added a linkage specification to a
function definition whenever its language linkage does not match that of
the context in which it appears, regardless of whether the definition has
an explicit linkage specification in the original source or not.  This can
result in incorrect code, however, because such a linkage specification
affects the language linkage of declarations nested within the function
body.  The C++-generating back end has now been modified to emit a linkage
specification for a function definition only if one is present in the
original source code.  For example:

  extern "C" void foo();
  void foo() {   // Previously generated with an explicit extern "C"
    int bar ( int );
    int bar ( int, int );  // Invalid overloading with explicit extern "C"
                           // on the function definition
  }


2/16/18  [EDGcpfe/18483]
C++-generating back end: single-argument constructor call as initializer

When an initializer consists of a constructor call with a single argument,
the C++-generating back end generated the initializer as a C-style cast to
the type of the object being initialized, including any const and/or
volatile qualifiers.  The inclusion of the type qualifiers resulted in
errors in the generated code, so the C++-generating back end has now been
modified to cast to the class type rather than the type of the object.  For
example:

  struct S {
    S(int);
  };
  void foo() {
    volatile S t = S(0);  // Previously generated as ((volatile S)(0)), now
                          // as ((S)(0))
  }


2/16/18  [EDGcpfe/18647]
Default arguments of lambdas in variadic templates

The front end previously did not record the default argument of a lambda during
the prototype instantiation of a variadic template.  For example:

  template<typename ...> void g() {
    auto f = [](int = 0) {};  // Default argument was previously not recorded
    f();                      // during the prototype instantiation of g().
  }

That omission was for example visible in the C++-generating back end output
(where the default argument would be missing).  Note that in some modes (such
as GNU C++11 modes), all templates are treated as variadic, causing the
issue to be more widespread.  This is now fixed.


2/16/18  [EDGcpfe/19345]
Abort on invalid sizeof construct

Consider in a non-C++17 mode:

  template<typename...> struct S {
    int f() { return sizeof(...); }
  };

This previously caused the front end to access uninitialized memory because of
changes for C++17 fold expressions (EDGcpfe/17691,EDGcpfe/18560), causing a
subsequent abort in most cases.  This regression, introduced in version 4.14,
is now fixed.


2/16/18  [EDGcpfe/18959]
Defaulted move functions and exception specifications

Consider, in C++14 mode:

  struct W { W& operator=(W const&); };
  template<typename> struct B {
     B& operator=(B const&);
     B& operator=(B&&) noexcept(true) = default;
     W w;
  };
  struct C {
    B<int> m;
  };
  C g() {
    C c;
    c = g();  // Previously selected C's move assignment operator, triggering
  }           // an error.  Now the copy assignment operator is called.

Previously the generated move assignment operator of C called the move
assignment operator of B<int>, which is implicitly deleted ("= delete").
However, the C++ standard specifies that defaulted move assignment operators
that are implicitly deleted should be ignored in overload resolution, which
means the move assignment operator of C should call the copy assignment
operator of B<int>.  This is now fixed in the front end, as is the similar
issue with move constructors.


2/15/18  [EDGcpfe/18586]
C++-generating back end: befriending a template parameter

The C++-generating back end sometimes erroneously prefixed the name of a
template parameter in a friend declaration with the global scope operator
"::".  This is now fixed.  For example, with --c++11:

  namespace NS {
  template <class T> class S {
    friend T;  // Previously generated as "friend ::T"
  };
  }


2/15/18  [EDGcpfe/19149]
C++-generating back end: name hiding in class base list

The C++-generating back end failed to account for the effect of template
parameters and the class name on names mentioned in the base class list of
a class definition.  As a result, necessary qualification for some such
names was omitted, resulting in incorrect code.  This is now fixed.  For
example:

  template <typename... Ts> struct S1 { };
  namespace ns {
    template <int> struct S2 { };
    template <unsigned int S2>
      struct S3 : S1<ns::S2<S2>> {  // Previously omitted "ns::" because the
                                    // template parameter S2 was not considered
                                    // to hide class template S2's name
      };
  }


2/15/18  [EDGcpfe/18123]
C++-generating back end: array decay and parentheses

The C++-generating back end unnecessarily parenthesized the name of an
array used in such a way that the array lvalue is implicitly converted to
a pointer to its first element.  In some contexts, some versions of g++
issued spurious errors if an array name is parenthesized.  This has now
been addressed and the C++-generating back end no longer adds parentheses
in such cases.  For example:

  template <bool> struct A {
    static long a[];
    void m_fn1() { a + x; }  // Previously generated as "(a) + x"
    long x;
  };


2/15/18  [EDGcpfe/18026]
C++-generating back end: decltype-specifiers as nested-name-specifiers

When the source code contains a decltype-specifier used as a
nested-name-specifier in a qualified-id and the type designated by the
specifier is an unnamed class type, the C++-generating back end put out
an undeclared temporary name (of the form __T12345678) as the qualifier.
This is now fixed.  For example:

  struct { static int f() { return 0; } } x;
  int i = decltype(x)::f();  // Previously generated as __T12345678::f


2/15/18  [EDGcpfe/19262]
IL write-read error on use of nontype template parameter in multi-TU mode

When simultaneously compiling multiple translation units in a mode that defers
prototype instantiations (i.e., default GNU or Clang mode), the front end
sometimes aborted with an internal error ("IL entry write-read difference")
when a member of a class template using a nontype template parameter is
instantiated in a secondary translation while the primary translation unit
does not instantiate the template at all.  For example:

  // File_1.cpp:
  template<int N> struct S {
    typedef int I;
    I f() { return N; }
  };

  // File_2.cpp:
  template<int N> struct S {
    typedef int I;
    I f() { return N; }  // Use of N here caused an internal error.
  };
  int r = S<42>().f();

This is now fixed.


2/14/18  [EDGcpfe/18125]
C++-generating back end: clang and user-defined literal operators

The change for EDGcpfe/17988 (in version 4.13) used an incorrect test to
determine when to put out a space before the literal suffix when declaring
a user-defined literal operator.  In particular, except for the one special
case of "if" as a suffix, clang always requires the space before the
literal suffix, regardless of the C++ version being compiled.  The
C++-generating back end has now been changed to add the space before every
suffix except "if" whenever clang_is_generated_code_target is TRUE.  For
example, with --clang:

  // Previously generated as operator ""LL, which clang rejects:
  unsigned long long operator "" LL(unsigned long long a) {
      return a+1;
  }


2/14/18  [EDGcpfe/19303]
Attribute enable_if and using-declarations

Consider the following example in Clang mode:

  namespace N { extern void g(); }
  using N::g;
  __attribute((enable_if(true, ""))) void g() {}  // Previously an error.
                                                  // Now okay.

The front end previously issued an error in that example because it did not
consider the enable_if attribute when looking for declaration conflicts with
using-declarations.  That is now fixed.


2/14/18  [EDGcpfe/19344]
Partial ordering of member vs. non-member function templates

Our implementation of partial ordering of member vs. non-member function
templates (core issue 532) could result in spurious ambiguity because the
front end incorrectly applied the core issue 532 transformation when 
comparing a non-static member function template and a static member
function template.  Now fixed.

  struct A {
    template <typename T> static T* f(A*) { return nullptr; }
    template <typename T, typename U> T* f(const U&) { return nullptr; }
  };
  int main() {
    A x;
    x.f<int>(&x);  // Formerly ambiguous
  }


2/14/18  [EDGcpfe/18127]
C++-generating back end: clang and dependent friend declarations

The C++-generating back end generally suppresses the argument list on a
template name when it appears in the scope of that template and refers to
the current instantiation.  In a friend member function declaration,
however, clang requires that the template argument list be supplied.  The
C++-generating back end has now been modified to add the template argument
list in such friend declarations when clang_is_generated_code_target is
TRUE. For example, with --clang:

  template <class T> struct S1;
  struct S2 {
    template <class T> int foo(S1<T>* p);
  };
  template <class T> struct S1 {
    friend int S2::foo<T> (S1<T> * p);  // Parameter type previously generated
                                        // as "S1", now "::S1<T>" with
                                        // clang_is_generated_code_target
  };


2/14/18  [EDGcpfe/19334]
Configurations with IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS set to FALSE

In configurations where IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS is set to
FALSE, some references to thread-specific run-time library calls had been
generated during lowering.  In such configurations, for thread_local variables,
the a_variable::is_thread_local flag is still set to TRUE in the IL, but
lowering now uses a new macro, is_effective_thread_local, to determine if
thread-specific treatment is required.  is_effective_thread_local always
returns FALSE when IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS is FALSE (and
returns a_variable::is_thread_local in other configurations).  The following
example had generated a reference to __cxa_thread_atexit (in IA-64 ABI
configurations) with --c++14:

  struct S {
    ~S() {}
  };
  thread_local S s;


2/13/18  [EDGcpfe/16859]
C++-generating back end: accessible typedefs for inaccessible class qualifiers

The C++-generating back end failed to substitute an accessible typedef for
an inaccessible qualifier in some qualified names, resulting in code that
could not be compiled.  For example:

  template<typename T> struct S1 { };
  template <typename T> struct S2 {
    typedef S1<T> type;
  };
  class C1 {
    class C { };
  public:
    typedef S2<C> t;
  };
  struct S3 {
    S3(const C1::t::type&) {  // Parameter type previously generated as
                              // "const S1<C1::C>&", which is an access error
    }
  };


2/13/18  [EDGcpfe/19325]
Abort on interpretation of unusual eok_padd_assign

In some cases, adding a pointer value to a boolean could result in an abort
in conv_integer_value_to_host_large_integer (const_ints.c) during the
interpretation of an eok_padd_assign node.  For example:

  void f(bool b) {
    int x[1];
    constexpr auto z = ( b += x );  // Previously aborted.  Now an error.
  }

This is now fixed.


2/13/18  [EDGcpfe/19339]
Spurious error on generic lambda with array parameter declarator

Consider:

  int x = [](auto [3]) { return 42; }((int*)nullptr);

The front end previously issued an error about the use of "auto" combined
with an array type.  That error, however, does not apply for the "auto"
parameters of a generic lambda.  The problem is now fixed and the example
above is now accepted.


2/13/18  [EDGcpfe/17895]
C++-generating back end: incorrect qualification of otherwise-inaccessible
base class members named in a using-declaration

The C++-generating back end incorrectly used a qualified-id to name an
inaccessible base class member when the derived class has a using-declaration
that makes the name accessible.  This is now fixed.  For example:

  struct S1;
  struct S2;

  class S3 {
    friend struct S1;
    static void foo(S1&);
    static void foo(S2&);
  };

  struct S1 : private S3 {
    using S3::foo;
  };

  void bar() {
    S1 s;
    s.foo(s);  // Previously generated as s.S3::foo
  }


2/10/18  [EDGcpfe/19234]
C-generating back end: const volatile initialized static data members

The C-generating back end previously put out both an extern declaration
with no initializer and an extern declaration with an initializer for a
static data member that is both const- and volatile-qualified and
initialized in the class definition but is not defined in the translation
unit.  The declaration with the initializer acts as a definition, which
would result in a linker conflict if the static data member were actually
defined in another translation unit.  This is now fixed, and the
declaration with the initializer is now suppressed.  For example, with
--c++14:

  struct S {
    static constexpr volatile char x = 'a';
  };
  char f() { return S::x; }


2/9/18   [EDGcpfe/19307]
Static data member template with "auto" type specifier

In some cases involving a data member template declared with an "auto" type
specifier, the front aborted in prescan_initializer_for_auto_type_deduction.
For example:

  struct A {
    template <class T> static auto const x = 42;  // Previously aborted.
  };                                              // Now okay.

That is now fixed.


2/7/18   [EDGcpfe/19246]
Abort in find_subobject_for_interpreter_address

Trying to access a member of a class through a pointer "one position past the
end" of a variable could trigger an internal error in the interpreter (in
function find_subobject_for_interpreter_address).  For example:

  struct S { int x; } s;
  constexpr S *p = &s+1;
  int *q = &p->x;  // Previously triggered an assertion failure.
                   // Now elicits a normal error.

This is now fixed.


2/7/18   [EDGcpfe/19300]
Spurious error on braced base class initializer

Previously, the front end issue a spurious error on a braced initializer for
a base class if the corresponding base class constructor is protected.  For
example:

  class B { protected: B(B const&); };
  class D: B { D(D const &o): B{o} {} };  // Previously an error.  Now okay.

That is now fixed.


2/6/18   [EDGcpfe/19279]
Default arguments of generic lambdas not prototype-instantiated

The front end previously failed to parse the default arguments of a generic
lambda unless a real instantiation (as opposed to a prototype instantiation)
was performed.  For example, in C++14 mode:

  int r = [](auto x = int){ return x; }(1);  // Previously accepted.
                                             // Now an error.

Previously, the ill-formed default argument "int" was not parsed and therefore
no diagnostic was emitted.  That is now fixed.


2/6/18   [EDGcpfe/19298]
GNU and Microsoft compatibility: Deleted operator delete and new-expressions

The GNU and Microsoft compilers fail to check that an "operator delete"
corresponding to a new-expression is not "deleted" (i.e., defined with
"= delete").  For example:

  struct S {
    S();
    void operator delete(void*) = delete;
  };
  int main() {
    S *p = new S;  //  Ordinarily an error, but now accepted in GNU
  }                //  and Microsoft modes.

The front end now emulates that behavior in GNU and Microsoft modes.


2/6/18   [EDGcpfe/15362,EDGcpfe/15778,EDGcpfe/18542,EDGcpfe/19213]
GNU compatibility: folding __builtin_bswap functions

The __builtin_bswap{16,32,64} functions are now folded when called with
constant arguments.  For example, with --gcc:

  unsigned short x = __builtin_bswap16(0x1234);   // x = 0x3412

Also, these functions can now be used in constexpr functions, e.g.,
(with --c++14 --g++):

  static_assert(__builtin_bswap16(0x1122) == 0x2211, "");


2/6/18   [EDGcpfe/19292]
Abort in should_delay_lowering_on_function in some Microsoft modes

The changes for EDGcpfe/18142 (in version 4.14) introduced a regression in
Microsoft mode on certain member functions declared "constexpr" but found not
to be constexpr.  This caused an assertion to fail in
should_delay_lowering_on_function.  For example, with microsoft_version=1900:

  int g();
  template<typename T> struct S {
    typedef int(* const F)() ;
    static constexpr int f() {
      return g();
    }
    static constexpr F af[1]={ &f };
  };
  int r = S<int>::f();

This previously triggered an internal error.  That is now fixed.


2/6/18   [EDGcpfe/18979]
C++-generating back end: typedef using unnamed tag type as template argument

The C++-generating back end sometimes used an undeclared temporary type
name (of the form __T12345678) in a template argument in the generated
code when the original source is a typedef that refers to a class, struct,
union, or enumeration type that has no name.  This is now fixed.  For
example:

  typedef struct { } *S1;
  template<typename T> struct S2 { };
  S2<S1> x;  // Previously generated as "S2<__T12345678 *>"


2/6/18   [EDGcpfe/19296]
Microsoft compatibility: _MSVC_LANG

The value of the predefined macro _MSVC_LANG has been updated to the following
values (when microsoft_version >= 1911):

  201402L when --ms_c++14 is specified
  201703L when --ms_c++17 is specified
  201704L when --ms_c++latest is specified

The value of _MSVC_LANG is unchanged when microsoft_version < 1911.


2/2/18   [EDGcpfe/19258]
Relaxed range-based-for loop iterator requirements

In C++17 mode, the iterator requirements for range-based-for loops were relaxed
(see the entry for EDGcpfe/17338).  However, the front end failed to fully
check the remaining constraints.  For example:

  enum E { e = 42 };
  E* begin(E const&);
  float end(E const&);
  void g() {
    for (int i : E()) {}  // Previously accepted.  Now an error.
  }

This example previously failed to diagnose the fact that the begin() and end()
iterators have types that cannot be compared.  This is now fixed.


2/2/18   [EDGcpfe/19235]
IA-64 ABI: Setting of explicit_instantiation flag on alternate entry points

Lowering now sets the explicit_instantiation, class_explicitly_instantiated,
and explicit_do_not_instantiate flags on alternate entry points the same as
the values on the primary entry point.


2/2/18   [EDGcpfe/19081,EDGcpfe/19135,EDGcpfe/19170,EDGcpfe/19288]
Abort on invalid uses of decltype(auto)

Consider (in GNU C++14 mode):

  auto f() -> __attribute((deprecated)) decltype(auto) { return 0; }

This example previously aborted in get_template_arg_by_list_pos (templates.c)
because the (inapplicable) attribute caused the front end to treat 
"decltype(auto)" as if it were "auto" in some places.  The example:

  struct S { operator decltype(auto)*() { return nullptr; } };

aborted for similar reasons.  That is now fixed.


2/2/18   [EDGcpfe/19240]
Microsoft compatibility: nested namespaces

Nested namespaces (see the Changes for EDGcpfe/16712 et al.) had been enabled
when microsoft_version >= 1912, but only with --ms_c++latest.  They are now
also enabled with --ms_c++17.


2/1/18   [EDGcpfe/19277]
Spurious error on non-dependent using-declaration in local dependent class

Consider:

  struct B { int x; };
  template<typename T> void f() {
    struct L: T {
      using B::x;  // Previously an error.  Now okay.
    };
  };

The front end previously emitted an error for the using-declaration because it
failed to recognize the presence of a dependent base class that might match the
class (B) named in the using-declaration.  That is now fixed.


2/1/18   [EDGcpfe/19245]
Spurious C++17 error on range-based-for loop in lambda

In C++17 mode, a range-based-for loop appearing in a lambda previously elicited
a spurious error if the loop variable has a non-literal type.  For example:

  struct D { ~D(); } da[1] = {};
  auto lm = []{ for (auto x: da) ; };  // Previously a spurious error.
                                       // Now okay.

The error mistakenly mentioned a "constexpr" function because the front end
tentatively considers the lambda call operator a "constexpr" function in C++17
mode.  This is now fixed.


1/30/18  [EDGcpfe/19284]
Spurious failure to fold certain pointer arithmetic cases

In some cases, the front end failed to correctly handle the folding of pointer
arithmetic involving a pointer pointing one position past the end of an array.
For example:

  constexpr int z(int const*) { return 0; }
  struct S {
    int x[1];
    constexpr int const* e() const { return x+1; }
  };
  static constexpr S s = {};
  static constexpr int r = z(s.e());  // Previously failed in some
                                      // configurations.

This is now fixed.


1/30/18  [EDGcpfe/19075]
Abort in lowering on use of __FUNCDNAME__ in generic lambda

In Microsoft C++ modes that perform lowering, the front end previously aborted
with an internal error (in function call_operator_function_type_for_lambda in
lower_name.c) on uses of __FUNCDNAME__ in a generic lambda.  For example:

  auto g = [](auto a) {
    char const *n = __FUNCDNAME__;  // Previously triggered an internal error.
  };

This is now fixed.


1/30/18  [EDGcpfe/19007]
C++-generating back end: unnecessary qualification of anonymous union members

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end previously emitted
references to members of anonymous union members of class templates using
unnecessarily-qualified names.  This unnecessary qualification, although
correct, triggered bugs when compiling the generated code with some C++
compilers.  This is now fixed.  For example, with --strict:

  template<typename T> struct S {
    union { int i; };
    int j;
    S() : i(5), j(i) { }  // Previously generated as "j(::S<T>::i)"
  };


1/30/18  [EDGcpfe/19212]
Microsoft/GNU compatibility: Cast of zero address in constant-expression

GCC and Microsoft Visual C++ appear to accept in a constant-expression a cast
of a constant zero address (not just a null pointer constant) to an integer
type.  For example:

  constexpr int f(void *p) {
    return (long)p;
  }
  constexpr int x = f(3-3);  // Now accepted in GNU and Microsoft C++11 modes.


1/30/18  [EDGcpfe/19243]
Spurious redefinition error on function templates with small type difference

Consider the following example:

  template <typename T> auto g(T&& t) -> decltype(f(&T::operator())) {}
  template <typename T> auto g(T&& t) -> decltype(f(&T::N::operator())) {}

The front end previously issued an error on the second definition because it
mistakenly treated it as a redeclaration of the first template.  The underlying
issue was that the front end failed to fully record the presence of an explicit
name qualifier on "...::operator()".  That is now fixed.


1/30/18  [EDGcpfe/19209,EDGcpfe/19233]
Internal error on rescanning of generic cast

Consider the following example:

  template<bool B> struct S {
    template<typename T> int f(T) noexcept(T());
  };
  int r = S<true>().f(42);  // Previously triggered an internal error.
                            // Now okay.

The front end previously failed to record some information needed for SFINAE
processing on the expression "T()".  In C++17 mode, this later triggered an
internal error in make_cast_rescan_operands.  That is now fixed.


1/30/18  [EDGcpfe/19241]
Abort on deduced return type in secondary translation unit

In some cases, deducing a return type in a secondary translation unit could
result in an internal error in force_instantiation_to_deduce_return_type (in
templates.c).  For example, when using an empty file as a primary translation
unit and the following as a secondary translation unit (C++14 mode):

  // Secondary translation unit:
  template<int> struct N;
  struct P {
    N<0> *operator->();
  };
  template<int> struct N {
    auto f() { return 0; }  // Deduced return type sometimes triggered an
  };                        // internal error.  Now okay.
  auto x = P()->f();

That is now fixed.


1/28/18  [EDGcpfe/19131]
Spurious C++17 error on static member template

In C++17 mode, the front end previously issued a spurious error on a static
data member template declared with an array type of unspecified bound.  For
example:

  struct S {
    template<typename T>
      static constexpr T x[] = { 1, 2, 3 };  // Previously an error
  };                                         // in C++17 mode.

This is now fixed.


1/26/18  [EDGcpfe/19156]
GNU compatibility:  __builtin_offsetof

Previously, in all GNU C++ modes, the front end disallowed uses of
__builtin_offsetof that do not produce a constant.  Now, such uses are
permitted when gnu_version >= 40600.  Furthermore, the constexpr interpreter
has been updated to fold the corresponding bok_offset entries.  For example:

  struct S { char buf[1]; };
  constexpr unsigned g(unsigned n) {
    return (unsigned)__builtin_offsetof(S, buf[n]);  // Now accepted in some
  }                                                  // GNU C++ modes.
  static_assert(g(10) == 10, "");  // Okay in some GNU C++ mode.


1/25/18  [EDGcpfe/19152]
Abort on invalid use of designator in some C++ modes

In C++ modes that accept both C++11-style initializer lists and C99-style
designated initializers, the front end could abort on certain invalid uses of
designators.  For example, in Clang C++11 mode:

  void f() {
    g({ .a = 0 });  // Previously triggered an internal error.
  }

This is now fixed: Ordinary errors are issued.


1/25/18  [EDGcpfe/19214]
Source sequence entries for constexpr static data members

In C++17 mode, declaring a constexpr static data member with an initializer in
a class definition and following it by an out-of-class declaration of that same
member could result in an internal error in some configurations with the macro
GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE.  For example:

  struct S { constexpr static int m = 3; };
  constexpr int S::m;  // Previously could trigger an internal error.

(The internal error could occur in reconcile_static_data_member_types or in the
C++-generating back end.)  That is now fixed.


1/25/18  [EDGcpfe/19216]
Backing expressions in interpreter results

The functions interpret_expr and interpret_constexpr_call no longer record a
backing expression in the result constant (when interpretation is successful)
if an expression stack is active for an expression where backing expressions
are not recorded.  This avoids problems in code (such as the function
do_binary_operation_full) that copies and updates a_constant entries assuming
they have no backing expression in such situations (the unexpected backing
expression then becomes invalid).


1/24/18  [EDGcpfe/19218]
Incorrect initializers for null_source_position and preinclude_source_position

In configurations in which FULLY_RESOLVED_MACRO_POSITIONS is TRUE, the
changes for EDGcpfe/14305 (in version 4.8) resulted in incorrect values
for the orig_column and orig_seq fields of null_source_position and
preinclude_source_position.  This is now fixed.


1/22/18  [EDGcpfe/19178]
Abort in lowering on lambda in template parameter declaration

In C++17 mode, lambdas can be part of constant-expressions and therefore can
be evaluated as part of template parameter declarations.  However, doing so
could previously result in aborts during lowering (in function type_pointed_to
called from function lower_call).  For example:


  template <int A[+[]{return [=]{ return 42;}(); }() ]> void f () {}
    // Previously aborted during lowering.  Now okay.

This problem is now fixed.


1/22/18  [EDGcpfe/19184]
Spurious constant-expression evaluation error on pointer-to-member selection
on a temporary

The constexpr interpreter previously did not correctly handle a pointer-to-
member selection on a temporary (rvalue).  For example:

  struct X {
    int i = 42;
  };
  constexpr auto pdm = &X::i;
  constexpr auto f() {
    return X().*pdm;
  }
  constexpr int r = f();  // Previously an error.  Now okay.

This is now fixed.


1/22/18  [EDGcpfe/19048]
Abort on dependent inheriting constructor in multi-translation unit check

When simultaneously compiling multiple translation units with corresponding
template-dependent inheriting constructor declarations, the front end aborted
in function equiv_base_using_decls (trans_corresp.c) in some configurations.
For example:

  template<typename> struct B;
  template<typename T> struct D: B<T> { 
    using B<T>::B;  // Dependent inheriting constructor.
  };

Compiling two identical files with the code above could result in an internal
error.  That is now fixed.


1/19/18  [EDGcpfe/19161]
Abort after interpretation of eok_derived_class_cast node

The interpretation of eok_derived_class_cast contained a bug that resulted in
corrupt result addresses.  Using such an address later on could trigger various
kinds of aborts in the interpreter.


1/18/18  [EDGcpfe/18942,EDGcpfe/18180]
Spurious errors in complex multi-translation-unit cases

A bug in the front end caused it to incorrectly determine the equivalence of
certain template-dependent constants when multiple translation units are
simultaneously compiled.  This could lead to spurious errors of various kinds.
This problem, only observed in complex situations so far, is now fixed.


1/18/18  [EDGcpfe/18024]
Incorrect handling of sizeof... in dependent alias template instantiation

If an alias template was instantiated with a dependent template argument
list, it was incorrectly represented in the IL.  This could result in
incorrect code being generated in the C++-generating back end.  Now fixed.

  template <typename> struct A;
  template <bool> struct B;
  template <bool, typename...> struct C {
    template <typename... Ts> static bool f() { A<Ts...> a; return true; }
  };
  template <typename... Ts> struct C<false, Ts...>;
  template <typename... Ts1> struct D {
    template <typename... Ts2>
    using T = C<sizeof...(Ts1) == sizeof...(Ts2)>;
    template <typename... Ts2, typename B<T<Ts2...>::f()>::type = true>
      D(Ts2 &&...);
  };
  D<> f();
  auto c = f();


1/18/18  [EDGcpfe/17663]
C++-generating back end: explicit instantiations of variable templates

The C++-generating back end previously failed to put out the template
argument list on an explicit instantiation directive for a variable
template.  This is now fixed.  For example:

  template <typename T> T h;
  template int h<int>;   // Previously omitted "<int>"


1/18/18  [EDGcpfe/19155]
Assertion failure with attribute with no name

In error cases where an attribute has not been given a name, error reporting
mechanisms had aborted (in process_fill_in) when attempting to produce
an error.  Now fixed.  For example (with --c++11):

  struct A {};
  struct B {
    friend struct [[]] A;
  };


1/17/18  [EDGcpfe/18391,EDGcpfe/18783]
__is_assignable

The type trait helper __is_assignable is now enabled in all modes and
configurations that support type traits helpers.  (Previously, it was treated
as a Microsoft-mode-specific helper; see the entry for EDGcpfe/16544.)


1/17/18  [EDGcpfe/18903]
GNU C++ compatibility: __integer_pack

In GNU C++ modes with gnu_version >= 80000 the front end now accepts template
arguments of the form "__integer_pack(N)" where N is a nonnegative integer
constant.  Such a construct expands to template arguments 0, 1, ..., N-1 (an
empty list of arguments if N is zero).  For example:

  template<short ... N> struct B {};
  template<int N> int f(B<__integer_pack(N)...>) { return 1; }
  int r = f<3>(B<0, 1, 2>{});  // Okay.

GCC uses this feature in the standard <utility> header.  Our implementation
is slightly different from GCC's because of internal representation issues,
but it supports the use cases intended by the GCC feature.


1/16/18  [EDGcpfe/19148]
Segfault in IL display program

Previously, in configurations in which unneeded entries are removed from
the IL, removing a class type entry resulted in setting its
variant.class_struct_union.extra_info field to NULL, to ensure that if the
entry did somehow end up in the IL, the pointers in its class type
supplement could not be walked.  This approach violated an intended
invariant, however, that every class type should have an associated class
type supplement, which could result in dereferencing a NULL pointer in
scp_is_lambda_closure_class in the edgcpdisp IL display program.  Instead
of setting the extra_info field of a removed class type entry to NULL, the
associated class type supplement is now cleared and a flag set to indicate
the removal.  For example, using the sample Linux configuration with the
--g++ option, the following source code triggered the segfault and no
longer does so:

  namespace N {
    class B {};
    typedef B T;
    template<typename _Tp> inline void f(_Tp *p) { p->~_Tp(); }
  }

  struct G {
    void g() { N::f<int *>(0); }
  };

  int main() {
    N::T a;
  }


1/16/18  [EDGcpfe/17984,EDGcpfe/19141]
GNU C++ compatibility: abort on use of member variable template

An abort (in ensure_inclass_static_member_constant_initializer_is_scanned)
could occur in g++ mode on the use of a class member variable template
that is const or constexpr and is initialized in-class.  Now fixed.

  template <int I> struct B { };
  template <typename T> struct A {
    template <typename U> static constexpr int s = 1;
    template <typename U> using X = B<s<U>>;
  };


1/16/18  [EDGcpfe/19147]
Variable template access checking and lookup context in declarator

When scanning an explicit specialization of a class member variable template,
a spurious access error could be issued on the declarator.  In addition,
names from the class scope that should be visible in the declarator, were
not.  Now fixed.

  class A {
    template <typename T> static const T arr[];
    static const int q = 2;
  };
  // Formerly A::arr was not accessible and q was considered undefined
  template <> const int A::arr<int>[q];


1/16/18  [EDGcpfe/19142]
Incorrect value of inline flag for redeclaration of explicit specialization

If an explicit specialization was declared inline and then redeclared
or defined later without the inline flag, the flag was erroneously cleared.
Now fixed.

  template<typename T> inline void f();
  template<> inline void f<void>();
  template<> void f<void>() {}  // Formerly not inline


1/15/18  [EDGcpfe/19136]
Copying an aggregate constant with multiple abk_temporary constants referring
to the same constant

The copy_constant utility is used to copy all manners of constants, but in the
case of an aggregate constant containing multiple abk_temporary constants
referring to the same constant, each abk_temporary constant in the resulting
copy referred to a separate copy of the base constant and no longer to a single
constant.  Now fixed.  This manifested itself in the following example in
configurations that do lowering and have the fix for EDGcpfe/19037 (with the
Microsoft version of <initializer_list>) with --c++11:

  #include <initializer_list>
  extern "C" int printf(const char *,...);
  void f(std::initializer_list<int> in) {
    for (auto x : in) {
      printf("%d ", x);
    }
    printf("\n");
  }
  int main() {
    static auto v = {10, 20, 30};
    f(v);
    return 0;
  }

This had printed "10 20 30 10 20 30" and now prints "10 20 30".


1/15/18  [EDGcpfe/18100]
C generating back end: declaration of builtin with attributes

Typically the C generating back end suppresses declarations for builtin
functions but a change has been made not to suppress declarations for builtin
functions that have attributes.  For example (with --gcc):

  void foo(void)  {}
  void __builtin_abort(void) __attribute((alias("foo")));
  void f() {
    __builtin_abort();
  }


1/15/18  [EDGcpfe/18983]
Underlying type of scoped enumerator

If unspecified, the underlying type of a scoped enumerator is supposed to
be "int".  That was not always true in configurations where
enum_types_can_be_smaller_than_int is TRUE.  Now fixed.  For example (with
--c++17):

  enum class X;
  static_assert(sizeof(X) == sizeof(int));


1/12/18  [EDGcpfe/19130]
Microsoft compatibility: update to C++17 features enabled

The new matching of template template arguments (see EDGcpfe/18746) is now
enabled when microsoft_version >= 1912 and --ms_c++latest or --ms_c++17 is
specified.  Note that while this is enabled in default C++14 mode (because it
is a defect report) it is not enabled in --ms_c++14 mode.  Mandatory copy
elision is now enabled when microsoft_version >= 1913 and --ms_c++latest
or --ms_c++17 is specified.


1/11/18  [EDGcpfe/18945]
GCC/Clang compatibility: generic builtin atomics

A change has been made to suppress casts on generic atomic builtins (which
had cast the arguments to void * types, making it difficult for a back end
to deal with).  For example (with --clang):

  struct S { int i; } a, b, c;
  void f(void) { __atomic_exchange(&a, &b, &c, 0); }


1/10/18  [EDGcpfe/18746]
C++17: Matching of template template arguments

The process for matching template template arguments with template
template parameters has been revised to allow a wider variety of
template template arguments to match a template template parameter.
For example, in the case below, B now matches the template template
parameter of X because the presence of the default argument is considered.
Although this is generally considered a C++17 feature, it was actually
approved as a defect report on C++14, so the processing is also
enabled in C++14 mode.  This also resolves core issue 150.

  template <class T, class U = T> class B {};
  template <template <class> class P> class X {};
  X<B> xb;


1/10/18  [EDGcpfe/19110]
C-generating back end: always_inline attribute and setjmp

During the lowering of certain constructs related to new/delete, lowering
may insert calls to setjmp.  When that happens in a function that has the
GNU always_inline attribute, the generated C code can't be compiled by a
back end GCC compiler (an error is issued indicating that an always_inline
function can never be inlined).  A change has been made to remove the
always_inline attribute and issue a remark in such cases.  For example:

  struct A {
    int m;
  };
  __attribute((__always_inline__)) inline void f() {
    new A[4] {1, 2};
  }
  int main() {
    f();
  }


1/10/18  [EDGcpfe/19105]
C-generating back end: overflow in enumerator constants

The C-generating back end only put out an explicit constant for an
enumerator in an enumeration definition if that value was other than that
of the preceding enumerator plus one.  This caused problems in a case like
the following (assuming 32-bit integers):

  enum E : unsigned { a = 0x7fffffff, b = 0x80000000 };

In this case, the value for b was omitted, potentially resulting in an
error complaining of integer overflow in the calculation of the implicit
value of b when the generated code was compiled.  This has now been
addressed by putting out any explicit constant that is explicitly specified
in the source using a hexadecimal or octal literal, regardless of the value
of the preceding enumerator.


1/9/18   [EDGcpfe/18352,EDGcpfe/19078]
Corrupt source sequence list for instantiation of GNU in-class initializer

The changes for EDGcpfe/16403,EDGcpfe/16644 introduced a bug (in version 4.12)
in configurations with CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
set to TRUE.  Specifically, the source sequence entries list associated with
the in-class initializer for a static data member of a class template instance
in GNU C++ mode was corrupted: The forward and backward traversal of the
source sequence list became inconsistent.  This could result in internal
errors.  For example:

  template<bool> struct B;
  template<typename> struct C {
    struct D {
        template<typename> void f();
    };
    static const bool value = sizeof(D);
    typedef B <value> type;
  };
  long N = C<int>::value;

This example previously triggered an internal error in GNU C++ mode, during the
execution of function inline_function_fixup_for_class.  That is now fixed.


1/8/18   [EDGcpfe/19090]
Microsoft compatibility: Static data member types and instantiation

Previously, the front end always instantiated a class template instance used
as the type of a static data member in Microsoft bugs mode (see the entry of
10/16/02).  Now that behavior is limited to Microsoft bugs modes with
microsoft_version < 1900.


1/8/18   [EDGcpfe/10945]
Representation of array objects in exception handling array table

In configurations where GENERATE_EH_TABLES is TRUE but
DO_FULL_PORTABLE_EH_LOWERING is FALSE, the "handle" field in the array table of
the exception handling tables had neglected to include any needed offset in the
case where the destroyed object has static storage duration.  That had
resulted, for example, in code that would attempt to do partial aggregate
destructions of the same object in the code below (because all of the array
table elements pointed to the same -- zeroth -- element):

  struct A {
    A();
    ~A();
    A(char *);
  };
  struct B {
    A a[2];
  } b[] = {
    { {""} },
    { {"foo"} },
    { {"bar"} },
  };


1/5/18   [EDGcpfe/19038]
C++-generating back end: partial specializations of variable templates

In configurations in which template definitions are generated from the
prototype instantiation IL, the C++-generating back end failed to add the
template argument list when generating the declaration of a partial
specialization of a variable template.  This has now been fixed.  For
example:

  template<typename T, typename U> constexpr bool same = false;
  template<typename T> constexpr bool same<T, T> = true; // Previously
                                                         // omitted <T, T>


1/5/18   [EDGcpfe/19015]
IA-64 ABI: Assertion failure in initialize_vptr

A failed assertion (in initialize_vptr) could occur in cases where an aggregate
constant is being used to initialize an object of class type where the IA-64
ABI layout rules dictate that the object layout be changed to accommodate
sharing of a vptr.  Now fixed.  For example (with --c++11):

  struct B1 {
    int m = 37;
  };
  struct B2 {
    virtual void f();
  };
  struct A : B1, B2 {};
  struct D : A {} d;


1/5/18   [EDGcpfe/19031]
Incorrect substitution of C++17 exception specification

In some C++17 cases involving default template arguments, the front end did not
correctly substitute the exception specification of a member template during
the deduction process for that member template.  This could result in spurious
errors later on.  For example:

  template<typename T> struct X {
    template<typename U = T> X() noexcept(__is_nothrow_constructible(U)) {}
  };
  static_assert(__is_nothrow_constructible(X<int>));
    // Previously, this static_assert failed because the noexcept specifier
    // for the constructor template was not correctly substituted.

This is now fixed.


1/4/18   [EDGcpfe/19040]
Premature removal of unneeded instantiations leads to assertion failure

During wrap up processing the front end removes unneeded instantiations, but
that processing had occurred a little too early, resulting in an assertion
failure (in set_parent_scope) in some cases.  For example (with --c++14):

  template<typename F> int f(F &&);
  auto l = [](auto) {
    return [](auto){};
  };
  decltype(f(l(0))) x;


1/4/18   [EDGcpfe/19042]
Incorrect setting of is_local_to_function on alias template instance

In some cases, the is_local_to_function flag could be set on an alias
template instance type when it should not be.  This could result in
an internal error (in enclosing_routine_for_local_type).  Now fixed.

  namespace {
    template<typename T> using type = int;
    template<typename T> void f(T f) {
      f(0);
    }
     void g() {
       f([](auto u) {
         type<decltype(u)> t;
       });
     }
   }


1/3/18   [EDGcpfe/19085]
Clang compatibility: remove builtin for version 5.0.1

The only change in builtins between clang version 5.0.0 and 5.0.1 is the
removal of __builtin_ia32_pbroadcastq512_mem_mask.


1/2/18   [EDGcpfe/18312,EDGcpfe/18347,EDGcpfe/19018]
C++17 compatibility: __is_aggregate type traits helper

The front end now recognizes the __is_aggregate type traits helper, which
supports the std::is_aggregate trait.  It returns TRUE if the type is an
aggregate as described in the C++ Standard or if the type is a vector or
complex type in modes that support those types.  For example:

  typedef int arr[10];
  bool b = __is_aggregate(arr);  // b is initialized to true


12/19/17 [EDGcpfe/16735,EDGcpfe/17501,EDGcpfe/18076,EDGcpfe/18599,
          EDGcpfe/18926,EDGcpfe/18988,EDGcpfe/19013,EDGcpfe/19041]
Clang compatibility: better support for certain clang builtins

There are a number of clang builtins (__builtin_nontemporal_store,
__builtin_nontemporal_load, __c11_atomic_init, __c11_atomic_load,
__c11_atomic_store, __c11_atomic_exchange,
__c11_atomic_compare_exchange_strong, __c11_atomic_compare_exchange_weak,
__c11_atomic_fetch_add, __c11_atomic_fetch_sub, __c11_atomic_fetch_and,
__c11_atomic_fetch_or, __c11_atomic_fetch_xor, and __sync_swap) where
the builtin type can vary from one invocation of the builtin to another.
A change has been made to handle these cases (and restructure the way
the front end currently handles __sync_* and __atomic_* cases to make
it easier to handle other cases like this).

A consequence of this change is that a back end may now see multiple routines
with the same name and different types.  For example, with --clang:

  int f(_Atomic(char) *pac, char c,
        _Atomic(int)  *pai, int  i) {
  return __c11_atomic_load(pac, c) +
         __c11_atomic_load(pai, i);
  }

In this case there will be two __c11_atomic_load a_routine entries in the
IL, with different types.


12/18/17 [EDGcpfe/19049]
Address type mismatches between arguments and parameters when calling run-time
library routines

A change has been made to add a cast to the proper type for the first argument
to __throw_alloc, __throw_setup_dtor, and __throw_setup.  The declarations of
these same routines have had the type of the third argument (flags) changed
from a tk_int to a targ_ets_flag_type_int_kind integer (see EDGcpfe/18732) to
match the signature of the run-time library.

Additionally, a cast has been added to the dynamic type and static type
expressions in calls to __dynamic_cast and __dynamic_cast_ref to match the
signature in the run-time library.


12/14/17 [EDGcpfe/19043]
Incorrect deduction of decltype(auto) return type

The front end previously incorrectly applied certain operand transformations
on the returned expression of a function declared with decltype(auto) before
performing the return type deduction.  That caused it to deduce the wrong
return type in some cases.  For example:

  decltype(auto) g() {  // Return type should be "char const (&)[1]", but
    return "";          // previously deduced as "char const*".
  }
  static_assert(sizeof(g()) == 1, "Unexpected!");  // Previously failed.
                                                   // Now okay.

This is now fixed.


12/13/17 [EDGcpfe/19035]
Spurious errors on use of dependent pointer-to-member constants

Consider:

  struct S { void m() {} };
  template<typename> struct X {};
  template<typename T> struct N {
    using A = X<decltype(&T::m)>;  // (1)
  };
  template <typename T> X<decltype(&T::m)> g();  // (2)
  decltype(g<S>()) x;

The construct X<decltype(&T::m)> looks identical in (1) and (2), and the front
end previously reused the representation in (1) for the appearance in (2).
However, that is not valid: (2) needs a richer representation to handle SFINAE
(i.e., rescanning information is needed in (2), and that is not available in
(1)).  As result of the missing rescanning information, the front end produced
a spurious error on the declaration of x.  That is now fixed: (1) and (2) now
use distinct representations for the nonreal type X<decltype(&T::m))>.


12/13/17 [EDGcpfe/18929]
Spurious error on use of generic lambda parameter in return type

In some fairly complex cases the front end issued a spurious error in strict
mode on generic lambdas whose return type is expressed in terms of a parameter
of that lambda (e.g., "decltype(p)" where p is a parameter of the lambda).
That is now fixed.


12/13/17 [EDGcpfe/18555]
GNU C++ mode: Deduction of conversion function template returning reference

The changes for EDGcpfe/10521 (see entry of 3/10/10) described an odd behavior
of the GCC compiler when deducing conversion function templates that return
reference types.  It turns out that that behavior only occurred for
conversion function templates where the returned type is template-dependent.
For example:

  struct S {
    template <bool = true> operator unsigned const&() const;
  };
  unsigned size = S();  // Previously an error in GNU C++11 mode.  Now okay.

This example is accepted by GCC because the destination type of the conversion
operator template is not dependent on a template parameter of that template.
The front end's behavior has been adjusted to match GCC's behavior.


12/12/17 [EDGcpfe/18113,EDGcpfe/19032]
Incorrect type used for type of nontype template parameter

A change made in version 4.12 (see EDGcpfe/17039) could cause a template
parameter whose type depends on another template parameter of the same
declaration to be considered to have the incorrect type during substitution.
Now fixed.

  class A {};
  template<typename T, T t> class B {
    template<typename U, U u> friend A& operator<<(A&, B<U, u>&);
  };
  class X {
    B<unsigned int, 0> x;
  };
  int main() {
    A a;
    B<int, 0> b;
    // Overload resolution fails because the "u" in B<U, u> has wrong type
    a << b;
 }


12/12/17 [EDGcpfe/18957]
Conversion function of generic lambdas

Consider:

  struct S {
    S() {}
    S(S &) {}
  };
  S (*pf)(S) = [](auto p) { return p; };

This example triggers the instantiation of the conversion function template of
the generic lambda.  That conversion template instance produces a pointer to
function type, but the function type previously did not reflect the fact that
its return type (S) is returned "by copy constructor" (indicated by the flag
value_returned_by_cctor in the associated routine type supplement).  A similar
problem existed with the alternate entry point for the call operator (which
is used by the conversion function).  This is now fixed.


12/12/17 [EDGcpfe/19037]
std::initializer_list in local static initializers

Consider the following example:

  #include <initializer_list>
  int main() {
    static auto lst = { 1, 2, 3 };
  }

Previously, the initialization of lst was represented as a "dynamic" operation
(initk_dynamic).  Now it is a "static" initialization (initk_static).


12/12/17 [EDGcpfe/18810,EDGcpfe/19030]
Microsoft compatibility: "this" in __if_exists

The Microsoft compiler allows "this" to be used in an __if_exists test
to determine whether "this" is valid in the current context.  We now
support this in Microsoft mode.

  class A {
    void f() { __if_exists(this) { this } __if_not_exists(this) { 0 }; }
    static void g() { __if_exists(this) { this } __if_not_exists(this) { 0 }; }
  };


12/11/17 [EDGcpfe/19021]
GNU C++ compatibility: Meaning of block-extern declarations in namespaces

The changes made by EDGcpfe/9830 and EDGcpfe/10238 to emulate a GCC bug appear
to have been fixed by GCC in version 4.6.0 and the conditions where these
workarounds had been applied are now limited to GCC emulation mode (and not
clang emulation mode) when gnu_version < 40600.  The change can have an
effect on mangled names for variables and non-class-member functions, for
example:

  extern void g(char);
  namespace N {
    void f();
  }
  void N::f() {
    extern char x;  // x is now mangled when gnu_version >= 40600
    g(x);
  }


12/11/17 [EDGcpfe/19025]
Abort on invalid constexpr variable initializer involving virtual destructor

Consider:

  struct S { virtual ~S(); };
  S* g() {
    constexpr S *p = new S[42];
    return p;
  }

Previously, this aborted (in unbundle_init_component_expressions in overload.c)
because the front end failed to consider error cases that might generate
unexpected object lifetime entries in constant-expression contexts.  That is
now fixed: An ordinary error is issued.


12/10/17 [EDGcpfe/19019]
Microsoft compatibility: internal error in hidden name processing

When RECORD_HIDDEN_NAMES_IN_IL is TRUE, an internal error could occur
(in inactive_scope_lookup) during hidden name processing in Microsoft
mode.  Now fixed.

  template<typename T1, int I1> struct S1;
  template<typename T1> struct S1<T1, 0> { };
  template<typename T1, int I1 = 1> struct S1 : public S1<T1, 0> {
    template <typename T2, int I2> friend class S1;
  };
  class S2 : public S1<S2> { };


12/10/17 [EDGcpfe/19016]
Incorrect disambiguation of template argument list followed by ">>"

Disambiguation is used to determine if a template argument to a nonreal
template is a type or nontype.  This could produce an incorrect result
when the template argument was followed by a ">>" that is intended to
terminate two template argument lists.  Now fixed.

  template <class T> struct A {};
  template <class T> struct B : A<typename T::template C<typename T::X>> {};


12/8/17  [EDGcpfe/18015,EDGcpfe/18138]
Declared type not set for variable template instantiations

In configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE, the
declared_type field of an instantiation of a variable template was not set.
This could cause an internal error in the C++-generating back end in
configurations with NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
set to TRUE.  Now fixed.

  template <typename T> constexpr T v = T(1);
  template<typename T> T f(T r) {
    return v<T> * r;
  }
  int main() {
    double d;
    d = f<double>(2);
  }



12/7/17  [EDGcpfe/19009]
Missing diagnostic on invalid references in GNU C99 inline functions

In C99, an inline function with external linkage cannot refer to a variable
with internal linkage.  However, the front end failed to emit any corresponding
diagnostic in GNU (and Clang) C99 modes.  For example:

  static int x = 0;
  inline int g(void) {
    return x;  // Invalid in C99 mode, but previously not diagnosed at all
  }            // in GNU/Clang C99 modes.  Now a warning in those modes.

This is now fixed.


12/7/17  [EDGcpfe/19011]
Excessive time spent on emulation of GNU ABI bug for complex class types

In some cases, the front end's algorithm to emulate a class of GNU ABI bugs
(specifically, function gnu_conflict_found in layout.c) spent excessive time
on class types with very deep and complex inheritance structures.  The
performance of such cases has been improved significantly.


12/7/17  [EDGcpfe/18951]
Local static default initialization with a constexpr constructor

The front end previously did not record as "static" the default-initialization
of a local static variable when that initialization corresponded to a foldable
constexpr constructor call.  For example:

  struct S {
    int i;
    constexpr S(): i{42} {}
  };
  int g() {
    static S s;  // Previously the initialization indicated initk_dynamic.
    return s.i;  // Now it is initk_static.
  }

That is now fixed.


12/7/17  [EDGcpfe/19014]
Spurious errors on unevaluated non-constant-expression operators in C++14 mode

C++14 relaxed the rules for constant-expressions compared to C++11.  However,
the front end still imposed some C++11 constraints in C++14 mode.  For example:

  template<bool B, double (&RA)[B ? 42 : throw]> struct S;
      // Previously an error in C++14 mode.  Now okay.

In C++11, the expression "B ? 42 : throw" is never a constant-expression
because of the "throw" expression, but in C++14 (and later) it is a constant-
expression when B is true.  The front end previously spuriously issued a
diagnostic in C++14 mode.  That is now fixed.


12/6/17  [EDGcpfe/19002]
Abort on certain invalid constant-expressions

The changes that enabled lambdas in constant-expressions (in C++17 mode; see
the entry for EDGcpfe/17690,EDGcpfe/17995) introduced a regression in version
4.14 that caused certain invalid constant-expressions to trigger aborts.
For example:

  struct A { ~A() {} };
  struct B {
    A b; 
    constexpr int f() { return 42; }
  };
  template <typename T> T x[B().f()];   // Previously triggered an abort.

That is now fixed.


12/6/17  [EDGcpfe/19001]
Abort on invalid enumerator value

In modes that support constexpr, the front end previously aborted with an
internal error (in in_range_for_integer_kind) on certain invalid enumerator
constant values.  For example:

  using A = int[2];
  enum E { e = (unsigned)A{} };  // Previously triggered an internal error.

That is now fixed.


12/6/17  [EDGcpfe/18968,EDGcpfe/18961,EDGcpfe/18971,EDGcpfe/19006]
C++-generating back end: invalid explicit specializations of templates

When the front end is configured with
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and/or
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, the
C++-generating back end attempts to generate an explicit specialization
corresponding to each implicit instantiation of a template.  Unfortunately,
not all implicit instantiations can be represented by valid explicit
specializations in C++.  The C++-generating back end has now been changed
to detect several cases where an explicit specialization would be invalid
and suppress them.  These cases include when the explicit specialization
would require use of an inaccessible class member; when the point of
instantiation of the template occurs before a class containing a member
that would be required in the explicit specialization; and when the
explicit specialization would appear in a non-namespace-scope context.
(The last restriction is relaxed somewhat when
microsoft_dialect_is_generated_code_target is TRUE; in that case, the
explicit specialization is permitted when the template being specialized is
a member of the class in which the explicit specialization would appear,
since the Microsoft compiler accepts such explicit specializations.)  If
the explicit specialization corresponding to a class template instance is
suppressed, the definitions of its members are also suppressed.  For
example:

  template <class T> struct A { };
  struct Outer {
    struct Inner { };
    A<Inner> m;  // Previously generated template<> A<Inner> specialization
                 // within Outer, now suppressed.
  };


12/6/17  [EDGcpfe/19003]
Abort on structured binding of array with template-dependent bound

The front end previously aborted with an internal error in num_array_elements
when processing a structured binding of an array with nontrivial copy semantics
and a template-dependent bound.  For example:

  struct S { S(S const&); };
  template<int N> void f(S (&sa)[N]) {
    auto [x] = sa;  // Previously an internal error.  Now okay.
  }

This is now fixed.


12/6/17  [EDGcpfe/19005]
Abort on reinterpret_cast in constexpr initializer

Consider:

  struct A { int x; };
  struct B: A {
    constexpr B(int i): A() { x = i; }
  };
  constexpr B b(29);
  constexpr A a = reinterpret_cast<A const&>(b); 

Previously, the front end aborted in type_change_constant_full attempting to
evaluate the reinterpret_cast construct.  That is now fixed: An error is issued
instead.


12/4/17  [EDGcpfe/18970]
Spurious error on assignment of vectors in GNU C mode

Consider:
  void g(double __attribute((vector_size(8))) *dst,
         double const __attribute((vector_size(8))) *src) {
    *dst = *src;
  }

Previously, the assignment in that example triggered a spurious error in GNU C
mode because the source operand includes an added type qualifier (const in this
case, but a volatile qualifier has the same effect).  That is now fixed.


12/4/17  [EDGcpfe/18982]
Abort on derived-to-base cast folding of decayed array element

Consider:

  struct B {};
  struct D: B {};
  void f(B*);
  void g() {
    D da[1][1];
    f(da[0]);  // Previously triggered an abort.  Now fixed.
  }

Version 4.13 introduced a regression (as part of the changes for EDGcpfe/17888)
that caused the front end to abort while attempting to fold the implicit
derived-to-base cast of the decayed value of da[0].  That is now fixed.


12/1/17  [EDGcpfe/18991]
C++-generating back end: Initializers for static data member template

The C++-generating back end previously did not always correctly render an
initializer for a static data member template.  For example, in C++14 mode:

  struct S {
    template<int I>
      static constexpr int X[10] = { I };
  };

Previously, the in-class initializer for S::X was not rendered by the
C++-generating back end.  That is now fixed.


12/1/17  [EDGcpfe/18991]
Pack expansion in initializer for variadic static data member

The front end previously did not correctly parse a pack expansion in an
in-class initializer for a variadic static data member.  For example:

  struct S {
    template<int ...Is>
      static constexpr int X[10] = { Is... };  // Previously an error.
  };                                           // Now okay.

That is now fixed.


11/30/17 [EDGcpfe/18344,EDGcpfe/18962]
Substitution failure in default argument of variadic function template

When a variadic function template had a default template argument containing
a pack expansion that made use of an enclosing non-variadic parameter, a
substitution failure could result.  Now fixed.

  struct C {};
  template <typename... Ts> struct A;
  template<typename, typename> struct B {
    static constexpr bool v = false;
  };
  template<bool... T> struct F;
  template <bool... Bs> using E = B< F<Bs...>, F<Bs...> >;
  template<typename T, typename... _Us> struct D {
    static constexpr bool v = true;
  };
  template<typename Ts, typename ...> struct H {
    template<typename... Us, bool b =  E<D<Ts, Us>::v...>::v> H(Us&&... us);
  };
  // Formerly "no instance of constructor ... matches the argument list"
  H<A<C(int)>> h{1};


11/30/17 [EDGcpfe/18953]
Default-const-constructible types

The front end now implements the resolution of Core issue 253 (via paper
P0490R0), which introduces the notion of default-const-constructible types:
Objects of such types can be default-initialized even when const-qualified.
For example:

  struct B {};
  struct D: B {};  // D and B are default-const-constructible.
  D const cd;      // Previously an error in strict mode because of a missing
                   // initializer.  Now okay (there aren't any members to
                   // initialize).


11/29/17 [EDGcpfe/18973]
C++-generating back end: Structured bindings not rendered

In some cases, the C++-generating back end failed to correctly render
structured bindings.  For example, given the following input:

  struct S { int x, y; }
  S f();
  void g() {
    const auto [a, b] = f();
  }

the C++generating back end previously failed to render the "[a, b]" part of
the structured binding declaration.  That is now fixed.


11/29/17 [EDGcpfe/18981]
Spurious constexpr evaluation failure on aggregate-initialized variable

Consider:

  struct S { int i; };
  constexpr S make_S(int i)  { return {i}; }
  constexpr S id(S const &s) { return s; }
  struct X {
    S s;
    constexpr X(int p): s{id(make_S(p))} {}
  };
  constexpr X x{0}; // Previously an error.  Now okay.

This example previously triggered an error about the initialization "x{0}" not
being constant because of some uninitialized object.  Specifically, the value
produced by "make_S(p)" through the aggregate initializer "{ i }" was not
correctly marked as fully initialized.  That is now fixed.


11/29/17 [EDGcpfe/18980]
Spurious error on defaulted constexpr constructor with protected base member

Consider:

  struct B {
  protected:
    B() = default;
  };
  struct D: B {
    constexpr D() = default;  // Previously an error.  Now okay.
  };

Previously, the front end issued a spurious error on the defaulted definition
of D::D() because it erroneously considered B::B() inaccessible from that
context.  That is now fixed.


11/28/17 [EDGcpfe/18934]
Virtual function tables for local class types

In some cases where a local class defined in a member function has a virtual
member function, the virtual function table that was emitted in the translation
unit had not been statically initialized.  That had resulted in a run time
error and is now fixed.  The bug had affected both Cfront and IA-64 ABIs.  For
example (with --c++11):

  template <class T> T *newT() { return new T; }
  struct A {
    virtual void f() = 0;
  };
  struct D {
    void g() {
      struct B : A {
        void f() {}
      };
      A *a = newT<B>();
      a->f();   // Had called through a NULL virtual function pointer.
    }
  } d;
  int main() {
    d.g();
    return 0;
  }


11/28/17 [EDGcpfe/18969]
Calls to static members in lambdas

Previously, the front end sometimes incorrectly forced the capture of a "this"
parameter for a call to a static member in a template-dependent context.
For example:

  template<typename> struct S {
    template<typename> static void sf();
    auto f() {
      return []{ sf<int>(); };  // Previously triggered a spurious error.
    }                           // Now okay.
  };

That is now fixed.


11/28/17 [EDGcpfe/18977]
Addition of custom name linkage code in routine_linkages_are_identical

A change has been made to routine_linkages_are_identical to handle a common
case that occurs when the front end is configured with custom name linkages.
Customers who use custom name linkages may still need to configure
routine_linkages_are_identical and routine_linkages_are_compatible to suit
their environment.


11/28/17 [EDGcpfe/17688]
C++17: Aggregates and base classes

C++17 extended the definition of "aggregate" to include class types with
public, nonvirtual bases.  Those bases can be initialized using aggregate
initialization syntax.  E.g.:

  template<typename ... BTs> struct D: BTs... { int d; };
  struct B1 { int b1; };
  struct B2 { int b2; };
  D<B1, B2> d = { {1}, {2}, 3 };  // Now accepted in C++17 mode.

The front end now implements those extensions.  Note that this may break
existing code.  For example:

  class B {
    friend struct D;
    B();
  };
  struct D: B {};
  D d1;    // Okay in all modes.
  D d2{};  // Error in C++17 mode (invalid aggregate initializer).
           // Okay in C++14 mode (default initializer, but not aggregate
           // initializer).


11/21/17 [EDGcpfe/18897]
Calling the interpreter outside the front end

Previously, calling the interpreter (e.g., through interpret_expr, which may
be indirectly invoked through functions like node_has_side_effects) from a
back end resulted in a crash due to missing front end memory structures.
That is now fixed (attempting to interpret a nonconstant construct always
fails outside the front end, but it no longer aborts).


11/21/17 [EDGcpfe/18958]
Clear bits in internal floating-point representation

In some cases (mostly involving NaNs), the internal representation of
floating-point constants could vary based on the contents of the stack at the
time a floating-point constant was loaded or stored.  These bits are now
zeroed.  This example (with --g++ -d-folded_builtin) had produced different
output as a result of unrelated changes:

  constexpr long double ld1 = __builtin_nanl("0");


11/21/17 [EDGcpfe/18553]
Qualification conversions

The C++ standardization committee's paper N4261 made some changes to the rules
regarding conversions involving const/volatile qualifiers, particularly when
array types are involved.  The front end now implements these changes (in
default and strict modes, but not in GNU, Clang, or Microsoft modes since the
corresponding compilers do not yet implement the new rules).  For example:

  void g(double *pa[2][3]) {
    double * (*p1)[3] = pa;            // Previously valid.  Still valid.
    double *const (*p2)[3] = p1;       // Previously valid.  Still valid.
    double const *const (*p3)[3] = p2; // Previously invalid.  Now valid.
  }

Some explicit conversions (using const_cast) are also affected by these
changes.


11/21/17 [EDGcpfe/18950]
clang compatibility: __is_identifier

The front end now supports the clang __is_identifier feature-test macro.
It takes a single token as an argument and has the value 1 if the token is
an identifier and 0 if it is anything else (e.g., a keyword).  For example,
with --clang:

  int i = __is_identifier(int);  // Expands to 0
  int j = __is_identifier(abc);  // Expands to 1


11/20/17 [EDGcpfe/16172,EDGcpfe/18602,EDGcpfe/18635,EDGcpfe/18781]
Pack expansion issues with generic lambdas

Spurious errors and/or an abort (in make_field_for_lambda_capture) could
occur when a generic lambda containing a pack expansion was defined inside
a function template.  Now fixed.

  template<class... T> inline void f(T... args) {
    auto lambda = [&](auto g) {
      g(args...);
    };
  }
  int main() {
    f(1, 2, 3);
  }


11/17/17 [EDGcpfe/18638]
C++17: Pack expansions in using-declarations

In C++17 mode, the front end now accepts pack expansions in using-declarations
(as well as using-declarations referring to multiple names).  For example:

  struct B1 { void f(); };
  struct B2 { int f(int); };
  template<typename ... Ts> struct D: private Ts... {
    using Ts::f...;
  };
  D<B1, B2> d;
  int r = d.f(42);  // Calls B2::f(int).


11/17/17 [EDGcpfe/18935]
Lowered throw expression is incorrect

In configurations that use lowering, but where DO_FULL_PORTABLE_EH_LOWERING is
FALSE, the expression generated for a leck_thrown_object_address had not
properly incorporated any modifiers into the thrown expression.  That omission
resulted in an attempt to assign the value of "x" to the
leck_thrown_object_address itself, rather than trying to assign it to the "m"
field of the object pointed to by leck_thrown_object_address in the example
below (with --c++11):

  struct A {
    int m;
  };
  void f() {
    int x = 0;
    throw A{x};
  }


11/17/17 [EDGcpfe/18948]
C++-generating back end: redundant #pragma pack directives

The changes for EDGcpfe/18626 caused a regression (in version 4.14) in
the output of the C++-generating back end, causing each #pragma pack
directive in the source to be represented by two redundant #pragma pack
directives in the generated code.  This is now fixed.  For example,

  #pragma pack(push, 1)   // Previously generated an additional pack(1)
  typedef struct S { char c1; } packed;
  #pragma pack(pop)       // Previously generated an additional pack()


11/16/17 [EDGcpfe/18930]
IA64-ABI: Function signature for thunks of virtual destructors

In IA-64 ABI configurations where IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS
is TRUE, complete (i.e., "D1") destructors return "void *" and deleting
destructors return "void".  In some cases, involving virtual destructors and
virtual base classes, the function signature for a deleting destructor had
been given a "void *" return type -- potentially causing conflicts for a linker
or even causing undefined behavior at run time.  This is now fixed.


11/16/17 [EDGcpfe/18947]
C++-generating back end: line break in #pragma

A change in 4.14 (see EDGcpfe/18667) could cause a line break to appear in
the middle of a #pragma directive that is output by the C++-generating
back end.  Now fixed.

  template <typename T> void f() {
    #pragma diag_suppress 1107
  }


11/15/17 [EDGcpfe/18943]
Using the --long_long command-line option in strict mode

The use of --long_long command-line option to enable the "long long" type
didn't work in some cases (e.g., with --strict --c++03) and is now fixed.


11/15/17 [EDGcpfe/18916]
Variable template partial specializations declared outside of the class

Variable template partial specializations declared outside of the enclosing
class template did not work properly in some cases.  Now fixed.

  template<typename T> struct A {
    template<typename U> static const int v;
  };
  template<typename T> template<typename U> const int A<T>::v<U*> = 1;
  int arr[A<int>::v<int*>];  // Formerly: cannot be used as a constant


11/14/17 [EDGcpfe/18730]
Digit separators in invalid locations

In modes in which digit separators are accepted, the front end previously
erroneously treated an apostrophe as a digit separator in preprocessor
tokens in cases when the apostrophe should terminate the token, i.e., when
the character following the apostrophe is not an acceptable character for
continuing the number.  Similarly, the front end failed to diagnose a
putative digit separator appearing at the end of the mantissa portion of a
floating-point literal.  These are now fixed.  For example, with --c++14:

  #define STR(s) #s
  const char *p = STR(1' ');  // Previously an error, now same as STR(1 ' ')
  double d1 = 1.0';           // Previously undiagnosed error
  double d2 = 1.0'e1;         // Previously undiagnosed error


11/15/17 [EDGcpfe/17932,EDGcpfe/18938]
Incorrect code generated for array delete of zero elements when the element
type is a class with a virtual destructor

In GCC and Microsoft emulation modes, an array delete of an entity whose
element type has a virtual destructor invokes the virtual destructor (see the
changes for EDGcpfe/10873).  In cases where the array has zero elements,
the code that had been generated incorrectly dereferenced the _vptr pointer,
resulting in an abort at run time.  A change has been made to suppress this
dereference (by generating code that does a run time check of the number
of elements in the array).  For example (with --g++):

  struct S { virtual ~S() {} };
  int main() {
    S *p = new S[0];
    delete[] p;
  }


11/14/17 [EDGcpfe/18928]
Failure to handle brace-notation cast failure as SFINAE

In some cases, substituting a brace-notation cast with template arguments that
make that case invalid produced an immediate error instead of a (SFINAE)
deduction failure.  For example:

  template <typename T> T&& declval();
  struct Y { static constexpr bool value = true; };
  struct N { static constexpr bool value = false; };
  struct A { A() {} };
  struct B {};
  template<typename T> struct H {
    template<typename... Us>
      static decltype(static_cast<void>(A{declval<Us>()...}), Y{}) test(int);
    template<typename...>
      static N test(...);
    using type = decltype(test<T>(0));
  };
  static_assert(!H<B>::type::value, "");

Previously this triggered an error while substituting A{declval<Us>()...}.
That is now fixed: The corresponding test template is discarded and the
ellipsis version is selected instead.


11/14/17 [EDGcpfe/18937]
Interpretation of eok_pdiff operator

The constexpr interpreter previously did not correctly handle certain pointer
differences with operands are not array element addresses.  For example:

  constexpr int f(int x) {
    int *p1 = &x+1;
    int *p2 = &x;
    return p1 - p2;
  }
  constexpr int d = f(4);  // Previously an error.  Now okay.

That is now fixed.


11/13/17 [EDGcpfe/18682]
Abort in scan_template_argument_constant_expression

The changes for EDGcpfe/17888 (which unified C++11 and C++14 constexpr
evaluation) introduced a regression in version 4.13 when scanning certain
nontype template arguments.  For example:

  template<int N> struct S {
    constexpr S(): a() {}
    int a[N];
  };
  template <int N> struct X {
    int a[N+1];
  };
  X<S<1>().a[0]> x;  // Previously triggered an internal error.

Specifically, it triggered an internal error due to an unexpected backing
expression (in scan_template_argument_constant_expression).  That is now fixed.


11/13/17 [EDGcpfe/18933]
New default value for TARG_LITTLE_ENDIAN

The default value for the TARG_LITTLE_ENDIAN configuration macro had been
FALSE, but most (x86-based) target architectures are little endian, so the
default value has been changed to TRUE.  In order to avoid an unexpected
configuration change in configurations where the default value had been used,
an internal error is now generated when targ_little_endian and
host_little_endian have different values, unless the value of a new
host configuration macro, HOST_TARGET_ENDIAN_MISMATCH_OKAY, is set to TRUE.


11/13/17 [EDGcpfe/18921]
New __EDG_INT128_EXTENSIONS_ALLOWED macro with --building_runtime

A new macro, __EDG_INT128_EXTENSIONS_ALLOWED, is now defined (to the value
of the configuration macro INT128_EXTENSIONS_ALLOWED) when --building_runtime
is specified as a command-line option.  This is used by the run time library
to determine whether or not to generate typeinfo information for the
__int128_t and __uint128_t types.


11/12/17 [EDGcpfe/18116,EDGcpfe/18927]
Substitution of sizeof... operator during SFINAE processing

In some relatively complex cases of function template argument deduction the
front end incorrectly substituted the sizeof... operator during SFINAE
processing, which could result in spurious errors about a call to a function
template not being valid.  This is now fixed.


11/7/17  [EDGcpfe/18925]
Core issue 1920: qualifier mismatching in pseudo-destructor call

The front end now implements core issue 1920, which clarifies that top-level
cv-qualifiers should be ignored when comparing the type before the "::" and
the type after the "~" in a pseudo-destructor call.

  typedef char A;
  typedef const A B;
  void f(A* p) {
    p->B::~A();  // Now accepted
  }


11/7/17  [EDGcpfe/18924]
Missing file name in macro context diagnostics

When FULLY_RESOLVED_MACRO_POSITIONS is being used, the macro context
information that is generated sometimes omitted the file name from the
diagnostics in cases where it should be included.  The file name should be
omitted only when it is the same as the file name given on the initial line
of the diagnostic.  Now fixed.


11/7/17  [EDGcpfe/18867]
C++-generating back end: generated explicit specializations of in-class
specializations

In configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
DEFAULT_FORM_OF_NAME_REFERENCE set to TRUE, the C++-generating back end
used an unqualified name when generating the (out-of-class) definition of
an in-class explicit specialization of a member function template of a
class template.  This is now fixed.  For example, with --microsoft:

  template <typename T> struct S {
    template <typename U> void f(U) { }
    template <> void f(int) { }
  };
  void g() {
    S<int> si;
    si.f(0);
  }
  // Previously generated the definition of S<int>::f<int>(int) here as:
  //   template<> inline void f(int) { }
  // Now correctly generated as:
  //   template<> inline void S<int>::f(int) { }


11/5/17  [EDGcpfe/18918]
C++-generating back end: template argument with constexpr function returning
std::nullptr_t

The C++-generating back end produced incorrect code for a non-type template
argument consisting of a call to a constexpr function returning
std::nullptr_t.  This is now fixed.  For example, with --c++11:

  constexpr decltype(nullptr) x() { return nullptr; }
  template <decltype(nullptr) I = x()>  // Previously generated as "I = 0",
                                        // now as "I = nullptr"
  void f() {}


11/4/17  [EDGcpfe/17567,EDGcpfe/18915,EDGcpfe/19807]
IA-64 ABI: mangling of vector types

Previously the IA-64 ABI mangling for vector types used the vendor-extension
mangling (i.e., "U8__vector").  This matched GCC's behavior until 5.1.0 when
GCC began to use the new IA-64 vector type mangling (i.e.,
"Dv<number>_<type>").  The front end now uses that mangling for vector types
unless gnu_abi_version < 50000 (in which case the old mangling is used).  When
ABI_COMPATIBILITY_VERSION < 415, the old behavior is maintained.  The Cfront
mangling for vector types is unchanged.


11/3/17  [EDGcpfe/18737]
Failure to deduce return type due to mutually dependent instantiations

When calling a template function with a deduced return type, the function
must be instantiated immediately to determine its return type.  In some cases,
that instantiation can trigger the instantiation of an inline function with a
known return type, but that instantiation in turn may require the original
deduced return type.  Such a mutual recursive situation previously produced a
spurious error about the return type not being deducible.  For example:

  template<typename Fn> struct F {
    Fn f;
    decltype(auto) operator()() { return f(*this); }
  };
  template<typename Fn> F<Fn> g(Fn f) { return { f }; }
  int main() {
    auto zero = g([](auto& self) -> int {
                    return 0;
                    self();  // Previously triggered an error about
                  });        // F::operator()'s return type not being
    return zero();           // deducible.
  }

This problem (which did not occur in GCC, Clang, or Microsoft modes) is now
fixed.


11/3/17  [EDGcpfe/18911]
Handling of destructions involving lowered default member initializers

Classes that have default member initializers require lowering to copy any
default member initializations into the scope of the class constructor.
In certain cases (mostly involving constructors with temporary expression
lifetimes), the resulting order of destructions generated for exception
handling purposes had been incorrect, possibly leading to incorrect cleanup if
an exception were to be thrown.  In the example below, the cleanup state after
the temporary for A is created had erroneously pointed to a destruction of "c"
(which hadn't been created yet).  With --c++11:

  struct A { ~A(); };
  struct B { B(A); };
  struct C { C(int); ~C(); };
  struct D {
    B b;
    C c = 0;
    D() : b(A()) {}
  } d;


11/3/17  [EDGcpfe/18758]
Unbounded loop after name linkage conflict in GNU and Clang modes

Consider:

  namespace N { void f(); }
  extern "C" {
    namespace N { void f() {} }
  }

This triggers an error because the linkage for the two declarations of N::f
differ.  In GNU and Clang modes, however, the front end did not recover
correctly from that error, and ended up in an unbounded loop in
perform_scheduled_routine_moves.  That is now fixed.


11/2/17  [EDGcpfe/18869]
Abort on use of [[nodiscard]] function in template-dependent context

In C++17 mode, the front end sometimes aborted (while evaluating the function
check_expression_for_nodiscard_warning) when processing a function call
involving a function marked with the [[nodiscard]] attribute in a template-
dependent context.  For example:

  void g(char, ...);
  struct S {
    [[nodiscard]] char f();
  };
  template<typename T> void h(T p) {
    S s;
    g(s.f(), p);  // Previously triggered an abort.
  }

That problem is now fixed.


11/2/17  [EDGcpfe/18908]
Spurious variadic template deduction error

The changes for EDGcpfe/18524 introduced a regression (in version 4.14) in
certain cases involving argument deduction for variadic function templates.
For example:

  template<char...> struct S {};
  template<char... Cs> auto f(S<Cs...>) -> S<Cs...>;
  template<char C, char... P1, char... P2>
    auto f(S<P1...>, S<C>, S<P2>...)->decltype(f(S<P1..., C>(), S<P2>()...));
  template<char... Cs>
    auto g(S<Cs...>)->decltype(f(S<Cs>()...));
  template<typename...> struct C {};
  using CT = C<decltype(g(S<'a', 'a' ,'a'>()))>;
    // Previously triggered an error for failing to deduce the arguments
    // for the call to g.

This is now fixed.


11/1/17  [EDGcpfe/17707,EDGcpfe/18676]
Generic casts: tpck_cast and tpck_expression (IL CHANGE)

The front end previously generated both tpck_cast and tpck_expression entries
for generic casts in contexts that may require a constant-expression.  In some
cases, this distinction led to spurious mismatches that in turn produced
spurious errors.  For example:

  template<bool> struct X;
  template<typename T> struct V {
    static const int value = 1;
  };
  template<typename T, typename = void> struct R;
  template<typename T, bool cond> struct R<T, X<cond>> {};
  template<typename T> struct R<T, X<V<T>::value>> {};
  R<int, X<1>> r;  // Previously an error.

Previously, the front end was unable to distinguish the two partial
specializations; now it picks the second one.  The resolution of this issue
required the elimination of the tpck_cast variant of ck_template_param
constants, which is an IL CHANGE (such entries are now represented instead by
tpck_expression entries pointing to a cast expression).


10/31/17 [EDGcpfe/18719]
Incorrect handling of SFINAE failures due to failed constexpr evaluations

Consider:

  constexpr bool d_zero(int i, int j) {
    return 1 + j/(i == 0);  // Valid when i == 0.
  }
  constexpr bool d_nonzero(int i, int j) {
    return 1 + j/(i != 0);  // Valid when i != 0.
  }
  template <int I> constexpr int f(int (*)[d_zero(I, 0)] = nullptr) {
    return 0;
  }
  template <int I> constexpr int f(int (*)[d_nonzero(I, 0)] = nullptr) {
    return 1;
  }
  static_assert (f<0>() == 0, "");  // Previously an error.

Previously, the fact that the invocation of d_nonzero(I, 0) cannot be folded
was ignored by the front end's SFINAE processing, causing both candidate
function templates f to be considered valid matches.  That in turn triggered
a spurious ambiguity error.  This problem is now fixed.


10/31/17 [EDGcpfe/18728,EDGcpfe/18743]
Spurious constexpr evaluation failure on default member initializer

Consider:

  struct S {
    int i;
    char const *str;
    int n = str[i];
  };
  constexpr int f(S const &s) { return s.i; }
  constexpr int r = f(S{ 2, "msg" });

This previously failed because the constexpr evaluation of "str[i]" in the
default initializer of S::n failed.  That is now fixed.  This issue is a
regression introduced in version 4.11 of the front end.


10/31/17 [EDGcpfe/18797]
Missing error on variadic lambda parameter default argument

The front end failed to issue an error on the declaration of a variadic
lambda parameter with a default argument.  Now fixed.

  template <class... Ts> void f(Ts... args) {
    auto l = [](Ts... x= args...){};
  }
  int main() {
    f(1, 2, 3);
  }


10/31/17 [EDGcpfe/18910]
Abort on use of deleted function with deducible return type

Consider:

  struct S {
    static auto f() = delete;
  };
  template<class T> int g() {
    return T::f();  // Previously triggered an abort when instantiated for
  }                 // T == S.
  int r = g<S>();

The front end previously aborted on this example (with an internal error in
generic_cast_operand).  That is now fixed.


10/30/17 [EDGcpfe/18750]
Spurious error on variable template specialized with different type

A spurious "incompatible type" error could be issued if a variable
template was specialized with a type that did not match the one that
would have been generated from the template.  Now fixed.

  struct A { void f() {} };
  struct B { void f() {} };
  template <class T> A a;
  template <> B a<int>;
  template <class T> void g() { a<T>.f(); }
  int main() {
    g<int>();
  }


10/30/17 [EDGcpfe/18689]
Internal error parsing a variadic declaration with C-style ellipsis

An internal error could occur (in end_potential_pack_expansion_context)
when parsing a top-level function declarator that contains both a pack
expansion and a C-style ellipsis parameter.  Now fixed.

  template <typename F> void g(int i, F f){ f(); }
  template <typename ...T> void f() {
    g(1, []{ void i(T..., ...); });
  }
  int main() {
      f();
  }


10/30/17 [EDGcpfe/18877]
Abort deducing empty variadic generic lambda template argument list

An abort could occur (in get_enclosing_template_params_and_args) while
deducing an empty template argument list for a call of a variadic generic
lambda. Now fixed.

  template <typename T> T&& declval();
  template <typename...> using void_t = void;
  template <typename, typename=void> struct A;
  template <typename T> struct A<T, void_t<decltype(declval<T>()())>> {
    static constexpr bool x = true;
  };
  int main() {
    auto l = [](auto... xs){};
    bool v = A<decltype(l)>::x;
    return !v;
  }


10/30/17 [EDGcpfe/18777]
Various variable template issues regarding out-of-class definitions

A number of issues regarding class member variable templates (i.e.,
static data member templates) involving out-of-class definitions have
been fixed:

- A variable template with an incomplete array type in the in-class declaration
  but a complete out-of-class definition resulted in spurious errors.

- A variable template where the template parameter names differed between
  the in-class declaration and the out-of-class definition could result
  in spurious errors.

The definition of A<T>::iarr is an example of the first issue and the
definition of A<T>::i is an example of the second.

  template <typename T> struct A {
    template<typename V> static int iarr[];
    template<typename V> static const int i;
  };
  template <typename T> template <typename V> int A<T>::iarr[10];
  template <typename T> template <typename Z> const int A<T>::i = sizeof(Z);
  int j = A<int>::iarr<int>[0];
  constexpr int k = A<int>::i<char>;

  
10/28/17 [EDGcpfe/18904]
Incorrect lookup in instantiation of member variable template

In the instantiation of a variable template declared in an explicitly
specialized class, the lookup in the initializer could fail to find
a template parameter if it had a different name in an out-of-class
definition.  Now fixed

  template<typename> struct A;
  template<> struct A<int> {
    template<bool B> static constexpr int v = B;
  };
  template<bool> constexpr int A<int>::v;
  int i = A<int>::template v<true>; // "B is undefined" during instantiation


10/28/17 [EDGcpfe/18748]
Abort on template-id that refers to non-template member function

An abort could occur (in copy_template_argument_list_with_substitution)
during SFINAE processing when the substitution of a dependent template-id
produced a non-template member function (which should result in a substitution
failure).  Now fixed.

  struct A {
    void f();
  };
  template <class T> auto f() -> decltype(T::template f<T>()) {}
  int main() {
    f<A>();
  }


10/27/17 [EDGcpfe/18680]
Incorrect comparison of dependent decltype expressions

When the front end was comparing two nontype template arguments that
are constants from dependent class template instances (e.g., something
like C<D<decltype(x1)>::v vs C<D<decltype(x2)>::v) the expressions in
the decltype were sometimes considered to match when they should not have.
This resulted in a spurious "has already been defined" error on the second
partial specialization of E in the example below.  Now fixed.

  struct A { };
  struct B { };
  int f(A);
  int f(B, B);
  template <bool B> struct C { };
  template <> struct C<true> { typedef void t; };
  template <class T> struct D { static constexpr bool v = true; };
  template<class, class = void> struct E;
  template <class T> struct E<T, typename C<D<decltype(f(T()))>::v>::t> {
    static constexpr int v = 1;
  };
  template <class T> struct E<T, typename C<D<decltype(f(T(),T()))>::v>::t> {
    static constexpr int v = 2;
  };


10/27/17 [EDGcpfe/18899]
GCC compatibility: Core issue 429

Previous changes for Core issue 429 (see EDGcpfe/7107 and EDGcpfe/16465)
did not include GCC as it seemed that GCC did not issue a diagnostic when
a non-placement deallocation function was selected for deallocation of a
placement new function.  It seems that GCC does implement this behavior, but
only when invoking a virtual destructor.  The example below now issues
an error (with --g++ --c++11):

  typedef decltype(sizeof(int)) size_t;
  struct A {
    virtual ~A(){}    // No diagnostic issued if destructor is not virtual
    void* operator new(size_t, size_t) noexcept;
    void operator delete(void*, size_t) noexcept;
  };
  void f(void) {
    A* a = new(2) A;
  }


10/27/17 [EDGcpfe/18870]
Spurious errors on conditional operators in constexpr contexts

In modes supporting constexpr evaluation, the front end previously too-eagerly
issued errors on certain uses of the conditional operator (?:).  For example:

  constexpr int g() {
    constexpr int arr[] = { 1 };
    constexpr int r = arr ? 1 : 0;  // Previously triggered a spurious
    return r;                       // "constant value is not known" error.
  }

This problem is now fixed.


10/27/17 [EDGcpfe/18902]
Microsoft compatibility: _INLINE_VARIABLES_SUPPORTED macro

The _INLINE_VARIABLES_SUPPORTED macro is now defined by the front end when
inline variables are enabled in Microsoft emulation mode (i.e., when
microsoft_version >= 1912 and --ms_c++latest or --ms_c++17 is specified).


10/27/17 [EDGcpfe/18808]
Partial specializations of class member variable templates

Partial specializations of class member variable templates (i.e., static
data member templates) were sometimes not handled properly.  In particular,
out-of-class definitions were sometimes not considered constant when
they should be, and some invalid out-of-class definitions were incorrectly
accepted.

  struct A {
    template <typename T> static const int v;
    template <typename T> static const int v<T*>;
    template <typename T> static const int v<T**> = 1;
  };
  template <typename T> int const A::v<T*> = 1;  // previously non-constant
  template <typename T> int const A::v<T**> = 2;  // previously accepted
  constexpr int i = A::v<int*>e; // previously rejected as non-constant


10/27/17 [EDGcpfe/18895]
Non-mutable lambdas and the type of unevaluated variable references

Consider:

  void g(int x) {
    [=]{
      decltype((x)) r = 1;
    }();
  }

Previously, this triggered an error because the type of x was considered
non-const, despite the lambda being non-mutable so that the capture of x
would result in an immutable copy.  This is now fixed: r now has type
"int const&".  Although the standard unambiguously makes this case valid,
there is an open issue (Core issue 1913) in this area when the lambda does
not permit the capture of the variable involved.  The front end changes
implement the anticipated resolution of that open issue.


10/27/17 [EDGcpfe/18893]
Microsoft C++ compatibility: internal error with C++/CLI, PCH, and preusing

An internal error (in translation_unit) could occur when doing a --preusing
of an assembly when precompiled header processing is enabled and the
primary source file did not contain any preprocessing directives.  Now
fixed.


10/26/17 [EDGcpfe/18833]
Abstract classes and virtual bases

Core issue 1658 clarified that the generated constructor or destructor of an
abstract class does not initialize its virtual bases.  This affects whether
certain generated members are deleted or not.  For example:

  struct Z;
  class X {
    X() {}
    friend struct Z;
  };
  struct Y: virtual X {
    virtual void f() = 0;  // Y is an abstract class with a virtual base.
  };
  struct Z: Y {
    virtual void f();
  };
  Z z; // Previously an error.

Previously, Y's generated default constructor was deleted because X's default
constructor is inaccessible from Y.  That in turn caused Z's default
constructor to be deleted, which triggered an error for the initialization of
variable z.  Now, the case is accepted because the default constructor of Y
does not attempt to initialize its virtual base subobject.


10/26/17 [EDGcpfe/18493,EDGcpfe/18725]
Errors instantiating variadic partial specialization of variable template

The instantiation of a variadic partial specialization of a non-variadic
primary variable template could result in spurious errors.  Now fixed.

  struct A { };
  template<typename T> class B;
  template<typename T> A v;
  template<typename... T> A v<B<T...>>;
  A a = v<B<int>>;


10/26/17 [EDGcpfe/18688]
Internal error on invalid decl-specifiers in enum template declaration

An internal error would occur (in enum_template_declaration) if invalid
decl-specifiers came before the enum keyword in a template enum declaration.
An error is now issued.  A friend declaration, such as the one in the
example below, is currently ill-formed, but there is some question about
whether the changes that cause it to be ill-formed were intended.  A
core issue is being opened to address this.

  template <typename T> struct A {
    enum E { };
  };
  struct B {
    template <typename T> friend enum A<T>::E;
  };


10/25/17 [EDGcpfe/18889]
Internal error on unneeded function with deduced return type

When writing an IL file and FREE_MEMORY_REGIONS_EARLY is TRUE, an
internal error could occur (in scope_for_routine) when attempting to
remove the definition of A<int>::f, which was only needed to determine
its return type.  Now fixed.

  template <class T> struct A {
    auto f();
  };
  template <class T> auto A<T>::f(){ return T(); }
  int main() {
    A<int> ai;
    auto x = ai.f();
  }
  extern template auto A<int>::f();


10/25/127 [EDGcpfe/18864]
Result of __has_unique_object_representations type traits helper

The result of the __has_unique_object_representations type traits helper
(see [EDGcpfe/17964,EDGcpfe/17999]) is largely left by the C++ Standard as
implementation-defined.  The front end has now been updated to mimic the
behavior of Microsoft Visual Studio and g++; if other values are desired
for a different ABI or emulation, the function
type_has_unique_object_representations (folding.c) should be changed.  In
addition, the front end previously aborted when the operand of the helper
function is a function type; this has now been fixed.


10/24/17 [EDGcpfe/18887]
Fold expressions and packs referenced in template arguments

In some cases, the front end issued spurious errors (e.g., about a pack being
referenced but not expanded) if a C++17 fold expression referred to a template
parameter pack from within a template argument list.  For example:

  template<int> void ft();
  template<int... Ns> void g() {
    (ft<1+Ns>(), ...);  // Previously triggered a series of spurious errors.
  }

This is now fixed.


10/24/17 [EDGcpfe/18733,EDGcpfe/18888]
Abort on partial specialization of pointer-to-function template

When partially specializing a variable template whose type is a
pointer-to-function type, the front end aborted with an internal error in
check_exception_specification.  For example (in C++14 mode):

template<typename T> T (*pft)();
template<typename T> T (*pft<T&>)();  // Previously triggered an
                                      // internal error.

This is now fixed.


10/24/17 [EDGcpfe/18880]
Abort in pop_object_lifetime_full with decltype(auto) variable declaration

Previously, certain decltype(auto) variable initializers requiring nontrivial
object lifetime management could abort with an internal error in 
pop_object_lifetime_full.  For example (C++14 mode):

  decltype(auto) x = new int(42);  // Previously triggered an internal error.

That is now fixed.


10/23/17 [EDGcpfe/18711]
User-defined literals appearing in template arguments

The front end previously failed in some cases to find the correct literal
operator for a user-defined literal appearing in a template argument,
either issuing a spurious "not found" diagnostic or silently choosing an
incorrect literal operator.  This is now fixed.  For example, with --c++11:

  namespace N {
    constexpr int operator"" _c(unsigned long long val) {
      return val;
    }
  }
  template <typename T, T VAL> struct A {
    static constexpr int value = VAL;
  };
  void f() {
    using namespace N;
    A<int, 25_c> a;  // Previously literal operator not found, now okay
  }


10/20/17 [EDGcpfe/18231,EDGcpfe/18878,EDGcpfe/18879]
GNU compatibility: Complex float128/float80 types

A change has been made to accept __attribute__(mode(TC)) and
__attribute(mode(XC)) attributes on types, thereby enabling complex __float128
and complex __float80 types, respectively.  These types appear in some system
header files (e.g., quadmath.h and floatn.h).  When LOWER_COMPLEX is TRUE,
these types are lowered in a similar fashion to other complex types.
For example (with --g++):

  typedef _Complex float __attribute__((mode(TC))) __complex128;
  typedef _Complex float __attribute__((mode(XC))) __complex80;


10/19/17 [EDGcpfe/18840]
Internal error in find_subobject_for_interpreter_address

In some cases, when constexpr evaluation produces the address one past the end
of an array member inside a base class subobject, the front end aborted with an
internal error in find_subobject_for_interpreter_address.  For example:

  struct B {
    float s[2];
    constexpr B(): s{ 1.0f, 2.0f } {}
    constexpr auto cbegin() const { return this->s; }
    constexpr auto cend() const { return this->s+2; }
  };
  struct D: public B {
    constexpr D() : B{} {}
  };
  constexpr float g() {
    constexpr D d;
    for (auto it = d.cbegin(); it < d.cend(); ++it) {}  // Previously aborted.
    return 0.0;                                         // Now okay.
  }

Previously, the evaluation of "d.cend()" produced an address that the constexpr
interpreter failed to translate back to a target representation (resulting in
the internal error).  That is now fixed.


10/19/17 [EDGcpfe/18564]
Abort in record_partial_aggregate_cleanup_destruction with --no_exceptions

The front end previously aborted with an internal error on the following case:

  struct S {
    S(char const*);
    ~S();
  };
  struct F { S host = ""; };
  struct X {
    X(F);
  };
  void g() {
    X(F{});  // Previously triggered an internal error.
  }

This is now fixed.


10/18/17 [EDGcpfe/18780]
Memory corruption in interpreter for certain address constants

In some cases where the type of a constant reflects an implicit conversion
applied to that constant (such as array decay for a string literal), the
interpreter's representation of the value of that constant was sometimes
corrupted.  This could lead to spurious errors or aborts.  For example:

  struct S {
    char m = 0;
    constexpr S(char const[]) {
      char min = 127;
      m = min;
    }
  };
  constexpr S x("Msg");  // Previously triggered a spurious error in
                         // some configurations.

This is now fixed.


10/17/17 [EDGcpfe/18633]
Abort in lowering on lambda with init-capture when exceptions turned off

Consider the following C++14 case:

  void g() {
    struct D { ~D() {} } d;
    [c = d]{}();
  }

Lowering previously aborted with an internal error handling the init-capture
in the lambda expression when support for exceptions is disabled (e.g., with
the option --no_exceptions).  This is now fixed.


10/17/17 [EDGcpfe/18779]
Core issue 1601: Enum promotion rules

The front end now implements core issue 1601, which specifies that during
overload resolution promotion of an unscoped enum type to its explicitly-
specified underlying type is a better match than other promotions.  This change
takes effect in C++14, but not in Clang and GCC modes (since those compilers do
not appear to implement the new rules yet).  For example:

  enum E: char { e };
  void f(char);
  void f(int) = delete;
  void g() {
    f(e);      // Previously ambiguous.  Now okay in C++14 mode.
  }            // (The call selects the non-deleted function f.)


10/13/17 [EDGcpfe/18710]
Injected class name incorrectly used in generic lambda instantiation

In some cases, the injected class name of a class template was found by
lookup when the class template should have been found.  This occurred when
scanning an explicit template argument list in the call of a function
template and resulted in incorrect overload resolution.  Now fixed.

  template <typename T> struct A {
    template <typename F> A(F f) { f(0); }
  };
  template <template <typename> class TT> TT<int>* f(int i) { return 0; }
  int main() {
    auto l = [](auto x) { f<A>(x); return 0; };
    A<int> a(l);
  }

10/13/17 [EDGcpfe/18824]
GNU C++ compatibility: typename lookup regression with --ms_extensions

A change in version 4.14 (see EDGcpfe/18326) could result in incorrect
lookup results when using both g++ mode and ms_extensions mode.  The
incorrect behavior occurred when the name after "typename" referred
to a fundamental type.  Now fixed.

  template <class T> struct A {
    typedef char X;
  };
  template <typename T, typename U = A<T> > class B {
    typedef typename U::X Y;  // formerly '"A<char>" has no member "X"'
  };
  B<char> b;


10/13/17 [EDGcpfe/18319]
C++-generating back end: decltype of cv-qualified lambda variable

The changes of EDGcpfe/17073, which allowed using a decltype-specifier
naming a variable whose type is a lambda closure class when forming a
pointer-to-member constant, failed to handle the case when the type of the
variable is cv-qualified.  This is now fixed, and typedefs are added for
both the cv-qualified and cv-unqualified versions of the closure class
type in such cases.  For example, with --c++14:

  template<typename C> int f(void (C::*)() const) { return 0; }
  const auto l = []{};
  // The following pointer to member constant was previously generated
  // using an undeclared temporary name, e.g., &__T12345678::operator():
  int i = f(&decltype(l)::operator());


10/12/17 [EDGcpfe/18855]
Spurious error on specialization of member template

The front end could issue a spurious "specialization ... must precede the
first use" error on an explicit specialization if the instance being
specialized was referenced in a context that did not actually require
its instantiation (in the example below it is used in the definition
of a templated function that is never instantiated).  An error should only
be issued if the prior use would result in the instantiation of the instance.
Now fixed.

  struct A {
    template<typename T> void f();
  };
  template<typename T> void A::f() {
    A a;
    a.f<bool>();
  }
  template<> void A::f<bool>() { }
  int main() {
    A a;
    a.f<bool>();
  }


10/12/17 [EDGcpfe/18857]
Constexpr interpreter and casts of scalars to function addresses

Explicitly casting a scalar value to a reference or pointer to a function is
possible.  The interpreter previously failed to notice that such a cast is not
a valid constant expression (even though it might be represented through an
entry of type a_constant) and instead produced a corrupt interpreter
representation of the construct.  In at least one complex case, this resulted
in an unbounded loop in translate_interpreter_offset.  That problem is fixed
now.


10/12/17 [EDGcpfe/18856]
Constexpr lambda captures and class hierarchy representation

The internal representation of class type objects in the interpreter includes
metadata determining whether such an object is a base subobject of a more
derived object.  Previously, however, class type objects created through
lambda captures did not always initialize that metadata, which could lead to
aborts on base-to-derived casts.  Now fixed.


10/12/17 [EDGcpfe/18846]
Diagnose transfer of control bypassing initialization for range-based-for loops

Previously the front end had failed to diagnose cases where a transfer of
control bypassed the initialization of a range-based-for or other similar
loop types (e.g., a Microsoft for-each loop).  These are now diagnosed with
a warning or error depending on the mode.  For example (with --c++11):

  int main() {
    int z[] = { 1, 2, 3 };
    goto label;
    for (auto x: z) {
      label:;
    }
  }


10/11/17 [EDGcpfe/18809]
Member string constants and multiple translation units

Previously, when simultaneously compiling the following two translation units,

  // File 1:
  struct S {
    static constexpr char const *s = "";
  };

  // File 2:
  struct S {
    static constexpr char const *s = "";
  };

the front end issued a correspondence error, because the member S::s is
initialized with two distinct addresses.  Now, such cases are accepted in
nonstrict modes if the strings have the same contents.


10/11/17 [EDGcpfe/17181,EDGcpfe/18722]
Constexpr interpreter and switching into loops

The handling of switch statements in the constexpr interpreter has been
improved to handle cases that switch into the body of a loop statement.
For example:

  constexpr int g(int x, int y) {
   switch(x) {
     case 1:
       for (y = 0; y < 10; ++y) {
         if (y == -1)
           return 42;
     case 2:
         ;
       }
       break;
     default:
       break;
     }
     return x+y;
  }
  static_assert(g(2, -2) == 42, "Unexpected");   // Previously failed.
                                                 // Now okay.


10/11/17 [EDGcpfe/18818]
Promotion of local static temporary when ENSURE_LOWERED_TYPE_LIST_ORDERING is
FALSE

In configurations that do lowering but have ENSURE_LOWERED_TYPE_LIST_ORDERING
set to FALSE, lowering had failed to promote a temporary local static variable
to the file scope resulting in a lowering-generated destruction routine that
refers to an automatic variable defined in a different function scope.
Now fixed.  For example (with --c++11):

  #include <initializer_list>
  struct A {
    template <class T> A(T &);
    ~A();
  };
  void f() {
    static std::initializer_list<A> a = { "foo" };
  }


10/10/17 [EDGcpfe/18845]
GCC compatibility: Incorporate changes for builtin functions from GCC 5.5.0

A number of builtin functions have slightly different signatures in the 5.5.0
release of GCC.  Those have now been integrated into the front end.  No
new builtins were added.


10/10/17 [EDGcpfe/18729]
Interpreter and ++/-- on run-time addresses

The interpreter previously did not correctly handle increment (++) and
decrement (--) operations applied to the addresses of run-time entities.
Both the pre-increment/decrement and the post-increment/decrement varieties
were affected.  For example:

  constexpr int* pred(int *p) {
    p--;
    return p;
  }
  int x[3];  // Run-time array.
  static_assert(pred(x+2) == &x[1], "Unexpected");
      // Previously a spurious error.  Now okay.

This is now fixed.


10/10/17 [EDGcpfe/18742]
Abort on use of implicit "this" in generic lambda

In some cases, the front end aborted in make_field_for_lambda_capture (due to
a null pointer dereference) during the instantiation of a generic lambda whose
body contains a call to a member function template that relies on an implicit
"this" selector.  For example:

  struct S {
    template<typename T> void ft(T);
    void f();
  };
  void S::f() {
    auto lm = [&](auto p) { ft(p); };
    lm(0);
  }

This is now fixed.


10/10/17 [EDGcpfe/18787]
Explicit instantiation and noexcept specifiers

In C++17 mode, noexcept specifiers are part of function types.  However, they
need not be specified in explicit instantiation directives.  The front end,
however, did not permit them to be omitted in such cases.  For example:

  template<typename T> void f() noexcept(true) {}
  template void f<int>();  // Previously an error in C++17 mode.  Now okay.

That is now fixed.


10/9/17  [EDGcpfe/18843]
Microsoft bugs: typename behavior emulation in member templates

The changes for EDGcpfe/8401 caused the front end to emulate nonstandard
behavior of the Microsoft compiler (in Microsoft bugs mode) with respect to the
semantics of "typename".  However, in some cases involving member templates,
they also caused the front end to reject valid code that the Microsoft compiler
accepts.  For example:

  template<typename> struct S {
    S();
  };
  template<typename T> struct X {
    using P = S<const T>;
    template<typename U = T>
      static auto f() -> decltype(U::g(typename U::P())) {
        return 0;
      }
    virtual int d() const { return f(); }
  };
  struct Z: X<Z> {
    static int g(S<const Z> const&);
  };
  X<Z> xz;

Previously, in Microsoft bugs mode, this case triggered a warning on the
"typename" keyword and the call to f() in the definition of d() resulted in an
error.  That is now fixed: The case is now accepted.


10/9/17  [EDGcpfe/18484]
C++-generating back end: default args for reference non-type template params

The C++-generating back end previously incorrectly added an ampersand to
default arguments for reference non-type template arguments.  This is now
fixed.  For example:

  int x = 1;
  int y = 1;
  template <int &I, int &J=x>  // Previously generated as "int &J = &x"
  struct S { };


10/9/17  [EDGcpfe/18830]
Enumerator constants and multiple translation units

When simultaneously compiling multiple translation units the front end
previously issued errors on conflicts between an enumerator name and another
non-tag name in the same scope of another translation unit.  For example:

  // File 1:
  int i;

  // File 2:
  enum E { i };  // Previously triggered an error in multi-translation-
                 // unit mode.

Such errors were not justified, however, because enumerator constants do not
actually have linkage.  The front end has been adjusted to avoid issuing such
errors (the conflicting entries are renamed by the C-generating back end to
avoid errors issued by the target C compiler).


10/9/17  [EDGcpfe/18841]
Microsoft compatibility: type of first argument to __annotation builtin

The type of the first argument to the __annotation builtin function has been
changed from "wchar_t *" to "const wchar_t *".


10/6/17  [EDGcpfe/18031]
C++-generating back end: unnecessary global scope qualifier on namespace name

In C++-generating back end configurations in which template definitions are
generated from their prototype instantiations, a namespace name used in a
qualified-id in some contexts was previously generated with an unnecessary
global namespace qualifier.  The resulting code sometimes caused older
versions of the Microsoft compiler to encounter an internal compiler error.
This is now fixed, and these unneeded global qualifiers are no longer put
out.  For example, with --microsoft:

  namespace NS {
    template<class T> struct S1 { template<typename> using t = int; };
  }

  template<class A> struct S2 : public A {
    typedef NS::S1<A> T1;
    typedef typename T1::template t<char> T2; // Previously generated as
                                              // ::NS::S1<A>::template...
  };


10/5/17  [EDGcpfe/18030]
C++-generating back end: Microsoft-mode dependent friend declarations

In some cases, the C++-generating back end generated a dependent friend
declaration as if the befriended class were defined in the global
namespace.  This is now fixed.  For example, with --microsoft:

  namespace NS {
    template<class T> struct S1 {};
  }
  template<class T> struct S2: public NS::S1<T> {
    friend class S1;  // Previously generated as "friend class ::S1;"
  };


10/5/17  [EDGcpfe/18837]
C++-generating back end: Use of __make_integer_seq

The use of the builtin template __make_integer_seq had caused issues in
C++-generating back end configurations when dependent template arguments
were used.  That has now been fixed.  In the example below (with --c++11
--clang_version 40000), the generated C++ code was invalid:

  template <class> struct S {
    template <long> using T = int;
  };
  template <int N>
    using x = typename __make_integer_seq<S, int, N>::template T<N>;


10/4/17  [EDGcpfe/16748]
C++-generating back end: use of typedef naming dependent destructor

In C++-generating back end configurations in which template definitions are
generated from their prototype instantiations, naming a dependent
destructor using a typedef name in the original source code previously
resulted in using the underlying type of the typedef in the destructor name
in the generated code.  This mismatch resulted in incorrect generated code
in some cases and in spurious errors in some compilers when compiling the
generated code in other cases.  This has now been fixed so that the typedef
name is preserved in the generated code.  For example:

  template <typename T1> void foo(T1 *val) {
    typedef T1 T2;
    val->T2::~T2(); // Previously generated as T2::~T1(), now T2::~T2()
  }


10/4/17  [EDGcpfe/18811]
Spurious error on this->x() in noexcept specifier

Consider the following example:

  void g(...);
  template<typename> struct S {
    template<typename... Ts>
      int f(Ts &...ps) noexcept(noexcept(g(this->x(), ps...)));
    int x();
  };
  int r = S<int>().f();

Previously, this triggered a spurious error because during template argument
substitution for the expression "S<int>().f()", the sub-expression "this->x()"
in the noexcept specifier did not find "x".  That is now fixed.


10/3/17  [EDGcpfe/18834]
Failure to fold initializer for static-lifetime variable

In C++ modes, the front end sometimes failed to fold an initializer expression
for a static-lifetime variable, thereby causing it to use dynamic
initialization when static initialization is required.  For example:

  extern char const C = "x"[0];
  int z[C];  // An error in versions 4.13 and 4.14.  Now okay.

This regression, introduced in version 4.13, is now fixed.


10/3/17  [EDGcpfe/18793]
C++-generating back end: generated function template instances with
parameter types deduced from rvalue references

In C++-generating back end configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
generated code contains an explicit specialization for each
implicitly-instantiated template function.  Versions of the Microsoft
compiler earlier than 1910 have a bug that results in an error if an
attempt is made to explicitly specialize a function template when a
function parameter type reflects the special deduction rule that changes
an rvalue reference to an lvalue reference if the function argument is an
lvalue.  For example, given

  template<typename T> int f(T&& t) { return 0; }
  int i = f("abc");

the generated code would normally contain the explicit specialization

  template<> int f(const char (&)[4]) { return 0; }

which cannot be compiled successfully by older Microsoft compilers.  The
C++-generating back end has now been changed not to put out such explicit
specializations when msvc_is_generated_code_target is TRUE and
msvc_target_version_number is less than 1910.


10/3/17  [EDGcpfe/18836]
Clang compatibility: 5.0.0 builtin functions

The builtin function information was updated to include builtin signatures from
clang 5.0.0.  Seven new builtins were added and some signatures were changed.


10/3/17  [EDGcpfe/18650]
Back ends and traverse_type_tree

Previously, the function traverse_type_tree (which is a general-purpose way to
visit the various components of the representation of a type) was not available
to back ends because it relied on the symbol table -- which only exists during
front end processing -- to find the template type parameter entry associated
with a proxy class.  That has been remedied and traverse_type_tree can now be
called from back ends.  The field template_param_for_proxy_class has been
removed from class symbol supplement entries; use the proxy_of_type field in
the class type supplement instead (that field is now unconditionally present).


10/2/17  [EDGcpfe/18829]
Microsoft mode assertion failure in expand_macro_buffer

The changes for EDGcpfe/15923 (in version 4.10.1) could result in a failed
assertion in expand_macro_buffer when certain complex and lengthy macro
expansions occurred in Microsoft mode.  This is now fixed.


10/2/17  [EDGcpfe/18695]
Clang compatibility: Conditional operators and std::common_type

The front end emulates an old GCC behavior where a conditional operator whose
second and third operands are xvalues of identical types did not produce an
xvalue (see the entry for EDGcpfe/17851).  It turns out that Clang follows that
GCC behavior during the definition of std::common_type (but is otherwise
standard compliant), presumably to be able to handle the GNU implementations
of std::common_type that rely on GCC's old behavior.  The front end now
emulates Clang's behavior in Clang mode.


9/29/17  [EDGcpfe/18796]
C++17: Trigraphs

The C++17 Standard removes support for trigraphs, and the front end has now
been changed to disable them by default in C++17 modes.  Support can still
be enabled explicitly using the --trigraphs command-line option.  For
example, with --c++17:

  const char s[] = "??!";
  static_assert(sizeof(s) == 4);  // Now succeeds


9/29/17  [EDGcpfe/18554,EDGcpfe/18679]
Deduction failure with template using enclosing template parameter pack

A change in version 4.12 (see EDGcpfe/17035) introduced a regression in
template argument deduction in cases where a member function template
included a nondeduced template parameter pack from an enclosing class
template.  Now fixed.

  template <class T> struct A {};
  template <typename... Args> struct B {
    template <typename T> B(Args... args, A<T>) {}
  };
  int main() {
    B<int> b(1, A<int>());
  }


9/28/17  [EDGcpfe/18707]
Spurious declaration mismatch with alias instance differences

A change in version 4.13 (see EDGcpfe/17737) introduced a regression in
declaration matching in cases where alias instances with different, but
compatible, template arguments were used in an in-class declaration and
an out-of-class definition of a member of a class template.  Now fixed.

  template <typename T> struct A {};
  template <typename U> using B_t = typename U::D_t;
  template <typename U> struct C {
    using C_t = B_t<U>;
    A<C_t> f();
  };
  template <typename U> A<B_t<U>> C<U>::f() {
    A<B_t<U>> f;
    return f;
  }
  struct D {
    typedef int D_t;
  };
  int main() {
    C<D> cd;
    cd.f();
  }


9/27/17  [EDGcpfe/18691]
Microsoft compatibility: Deferral of function prototype instantiations

Our implementation of variadic templates requires that prototype instantiations
be done of variadic templates.  Because the Microsoft compiler does not do
similar processing, some code that is accepted by the Microsoft compiler could
be rejected by the front end.  To reduce the number of cases in which this
occurs, the function prototype instantiations deferral is now enabled in
Microsoft mode when FUNCTION_PROTOTYPE_INSTANTIATION_DEFERRAL_ALLOWED is
set.  Deferral is only enabled if C++/CLI mode is not being used, Microsoft
permissive mode is being used, --stricter_template_checking has not been
requested, and nonclass prototype instantiations were not specifically
enabled or disabled by --[no_]parse_templates.

Formerly, it was possible to request deferral of function prototype
instantiations in Microsoft mode, but this did not work properly in
Microsoft mode because it previously assumed that nonclass prototype
instantiations were always being done when deferral was enabled.  Those
issues have also been fixed as part of this change.

  template <class T> struct A;
  template <typename... Ts> void g(Ts&&... args) {
    // Now accepted when prototype instantiations are deferred
    A<int> a;
  }
  template <> struct A<int> { };
  int main() {
    g(0);
  }


9/27/17  [EDGcpfe/18614]
C++-generating back end: spurious pack expansion in generated code

The C++-generating back end could sometimes introduce a spurious pack expansion
ellipsis in some cases involving aliases.  In this example, the definition
of C3 in was incorrect in the generated code.  Now fixed.

  template <bool b, typename T, typename F> struct A { };
  template <class...> using void_t = void; 
  template <class... Args> struct B { using t = int; }; 
  template <class... Args> using E = typename B<Args...>::t; 
  template <class TU, class... Ts> struct C;
  template <class TU, class... Ts> using C2 = typename C<TU,Ts...>::type;
  template <class TU, class... Ts> using D = E<TU, Ts...>;
  template <class T, template <class...> class F, class... Ts>
  using C3 = A< D<T,Ts...>::value, int, int >;


9/27/17  [EDGcpfe/18250,EDGcpfe/18350,EDGcpfe/18585]
Faulty substitution of braced cast notation

Consider the following example:

  template <bool> struct I { typedef bool type; };
  template<bool B> struct P {};
  template<bool B> auto f() -> P<typename I<B>::type{true}>;
  auto r = f<true>();

While substituting f<true>, the front end incorrectly handled the construct
"typename I<B>::type{true}" (a functional-notation cast), resulting in a
spurious error about an "unexpected function type".  That is now fixed.


9/26/17  [EDGcpfe/18577,EDGcpfe,18753,EDGcpfe/18817]
Regression in handling of GNU __extension__ keyword

The changes for EDGcpfe/15044 caused the front end to sometimes issue a
spurious error on the use of the __extension__ keyword in some contexts.
That regression introduced in version 4.14 of the front end is now fixed.


9/26/17  [EDGcpfe/18467,EDGcpfe/18582,EDGcpfe/18800]
Volatile and trivial copyability

Some years ago, the C++ standards committee made a change (through its Core
issue 496) that caused volatile types and classes with volatile members not
to be "trivially copyable".  Recently, that decision has been reversed through
the resolution of Core issue 2094.  The front end now implements the revised
rules by default.  For example:

  static_assert(__is_trivially_copyable(volatile int), "");  // Now okay.
  struct V { volatile int vi; };
  static_assert(__is_trivially_copyable(V), "");  // Now okay.

(Unfortunately, existing practice in this area varies: The front end attempts
to emulate the currently-known behaviors of various versions of MSVC, GCC, and
Clang in their respective emulation modes.)

Interestingly, some types that are now "trivially copyable" are still not
copyable through ordinary copy syntax:

  struct X {};
  struct Y { X volatile x; };
  static_assert(__is_trivially_copyable(Y), "");  // Now okay.
  Y y, c(y);  // Error: y cannot be copied to c because the copy constructor
              // is deleted.

See also the changes for EDGcpfe/16025.  This change affects the result of the
type traits helpers __is_trivially_copyable and __is_pod, but not the ABI.


9/26/17  [EDGcpfe/18705]
Microsoft compatibility: hexadecimal floating-point literals

Hexadecimal floating-point literals (see EDGcpfe/17694) are now enabled in
Microsoft C mode and with --ms_c++17 or --ms_c++latest when
microsoft_version is 1912 or larger.


9/26/17  [EDGcpfe/18805]
Initialization of static data member can lead to incomplete COMDAT section

In configurations that use lowering and where needed flag processing is
enabled, the initialization of a static data member for which no lowered
initialization is generated had resulted in the creation of an
initialization routine where the static guard variable is used but the
static data member is not.  Needed flag processing then marks the static data
member as unneeded while the guard variable is needed, resulting in a COMDAT
section that will be unlike other translation units in which the static data
member is referenced.  A dummy reference to the static data member is now
emitted so that needed flag processing will treat the two variables similarly.
For example (with -tused):

  struct A {
    A() {}
  };
  template <typename T> struct B {
    static T m;
  };
  template <typename T> T B<T>::m;
  static void f() {
    A a = B<A>::m;
  };


9/25/17  [EDGcpfe/18448,EDGcpfe/18790]
__edg_wchar_type__ now considered a type

The changes for EDGcpfe/18155 introduced __edg_wchar_type__ as a new type,
internal to the front end, used in declarations of builtin functions.
That type was not, however, interpreted as a type in some cases resulting
in errors (and even an assertion failure in enter_builtin_function) when
using a builtin function with a wchar_t type.  For example (with --microsoft):

  extern "C" void __cdecl __annotation(wchar_t*, ...);


9/25/17  [EDGcpfe/18807]
Parenthesized values for FLT_MAX/DBL_MAX

If the values of the macros FLT_MAX or DBL_MAX are parenthesized, the global
variables host_fp_flt_max/host_fp_dbl_max may be uninitialized which could
result in undefined behavior.  Now fixed.  See the Changes entry for
EDGcpfe/13041 for a similar change.


9/25/17  [EDGcpfe/18814]
Internal error on invalid template declaration

A change made in the way in which template declarations were prescanned in
version 4.14 (see EDGcpfe/16986 on 4/2/17) could cause an internal error (in
copy_tokens_from_cache) following an invalid member template declaration.
Now fixed.

  template <typename> struct A {
    // Note that B and C are undefined
    template <typename> static B<C<int>, int> f() {}
  };


9/21/17  [EDGcpfe/18804]
Feature test macros for fold expressions and exception specifications in
function types

The standard feature test macros for fold expressions (__cpp_fold_expressions)
and exception specifications in function types (__cpp_noexcept_function_type)
were previously not defined when the associated feature was enabled.  This
is now fixed.


9/19/17  [EDGcpfe/17701]
C++17: Evaluation order

The forthcoming C++17 standard mandates the evaluation order of operands in
various circumstances.  Calls resulting from call syntax, the subscript
operator, pointer-to-member selection operators (.* and ->*) and shift
operators now must have their operands evaluated in left-to-right order.
Conversely, assignments and compound assignments must have their right operand
evaluated before their left operand.  (Those orderings are required even if the
operator invocation is implemented as a call to an operator function.)  The IL
variant for enk_operation expression nodes has been augmented with two flags
indicating whether strict left-to-right or right-to-left evaluation order is
required.  Furthermore, the constexpr interpreter has been updated to switch
to right-to-left evaluation order when required (it otherwise always evaluates
operands in left-to-right order).  However, currently, the C-generating back
end does not attempt to control evaluation order.

These changes were added to the working paper for the C++17 standard through
paper P0145R3.

When enabled, this feature disables issuing of remarks about sequencing of
operations (see Changes entry for EDGcpfe/10525).


9/19/17  [EDGcpfe/18788]
GNU and Clang C++ compatibility: Abort in noexcept deduction in an explicit
instantiation

When the exception specification is part of the type, an abort could occur
(in strip_implicit_casts_if_template_param_constant) on an explicit
instantiation in which the noexcept operator did not have an explicit
operand.  Now fixed.

  template <typename T> void f() noexcept(true) {}
  template void f<int>() noexcept;
 

9/19/17  [EDGcpfe/18772]
Spurious error on pack expansion in noexcept when noexcept is part of the type

A spurious error could occur on a pack expansion in a noexcept specifier
of a member function template in modes where the exception specification
is part of the type.  Now fixed.

  void g(...) {}
  template <typename> void h(...) {}
  template <typename> struct S {
    template <class... Ts>
      void f(Ts... ts) noexcept(noexcept(g(h<Ts>(ts)...))) {}
  };
  S<int> s;


9/19/17  [EDGcpfe/18665]
SFINAE involving implicit "this" selector

In some cases, the front end failed to resolve a call appearing in a function
signature during SFINAE processing if the call relied on an implicit "this"
member selector.  For example:

  struct S1 {};
  void g1(S1) {}
  struct S2 {};
  void g2(S2) {}
  struct X {
    template <typename... Ts> auto f(Ts... ps) -> decltype(g1(ps...)) {
      return g1(ps...);
    }
    template <class... Ts> auto f(Ts... ps) -> decltype(g2(ps...)) {
      return g2(ps...);
    }
    template <class... Ts> auto operator()(Ts... ps) -> decltype(f(ps...)) {
      return f(ps...);
    }
  };
  int main() {
    X()(S2{});  // Previously found no match.  Now okay.
  }

Previously, the call to operator() failed because the call f(ps...) in the
return type of that operator was not correctly handled (specifically, that
call involves an implicit "this" selector, which was incorrectly ignored by
the front end).  That is now fixed.


9/19/17  [EDGcpfe/18668]
Deducible return types and functions defined as friends in class templates

Consider:

  template<typename T> struct S {
    friend auto f(S&) { return 0; }
  };
  int g(S<void> p) {
    return f(p);  // Previously an error.  Now okay.
  }

Previously, the front end issued a spurious error about f not being defined.
This was due to a failure to force the "instantiation" of functions defined
in friend declarations appearing in class templates.  That is now fixed.


9/18/17  [EDGcpfe/18778]
Microsoft compatibility: _NOEXCEPT_TYPES_SUPPORTED predefined macro

In Microsoft modes when exception specifications are part of function types
(see EDGcpfe/17685,EDGcpfe/18637), the front end now defines the macro
_NOEXCEPT_TYPES_SUPPORTED to the value 1.


9/18/17  [EDGcpfe/18773]
Partial function template ordering and exception specifications

During overload resolution the front end sometimes failed to correctly
distinguish candidate function templates based on their partial ordering if
those function templates included template-dependent exception specifications.
(The problem only occurred when exception specifications are part of the
function type, as is now the case by default in C++17 mode).  For example:

  template<typename X, typename... Ts> struct NC {
    static constexpr bool val = __is_nothrow_constructible(X, Ts...);
  };
  template<typename X, typename... Ts>
    constexpr bool nc = NC<X, Ts...>::val;
  template<typename T> int f(T&, T&) noexcept(nc<T, T>);
  template<typename T> struct S {};
  template<typename T> int f(S<T>&, S<T>&);
  S<int> si;
  int r = f(si, si);  // Previously an error in C++17 mode.  Now okay.

This is now fixed.


9/15/17  [EDGcpfe/18770]
Microsoft compatibility: Diagnostic on dynamic exception specifications

The changes for EDGcpfe/17685,EDGcpfe/18637 caused the front end to emit a
discretionary error on dynamic exception specifications when exception
specifications are part of the function type (as they are by default in C++17
modes).  Now, that error is weakened to a warning in Microsoft modes.


9/15/17  [EDGcpfe/18769]
TCF_LAST

The macro TCF_LAST in version 4.14 was not updated for a recent addition to
the set of TCF_... flags.  Now fixed.


9/15/17  [EDGcpfe/18747]
C++17: Nontype template arguments

The forthcoming C++17 standard generalizes the permitted forms of nontype
template arguments slightly, particularly when it comes to nontype template
parameters of pointer, reference, or pointer-to-member type.  The front end
now enables the new rules in C++17 mode.  For example:

  template<int*> struct X {};
  struct S { static int m; } s;
  X<&s.m> x;  // Now okay in C++17 mode.  (Previously an error.)

These changes were added to the working paper for the C++17 standard through
paper N4268.


9/14/17  [EDGcpfe/17997]
C++17: Elision of temporary class object copies

The forthcoming C++17 standard reformulates the handling of temporaries such
that the copying of class-type temporaries must be elided in many contexts.
This eliding, which was previously permitted but not required, was already
performed by the front end, but the elided copy constructor was still checked
(e.g., to ensure that it is accessible).  Now those checks are no longer
performed in C++17 mode.  For example:

  struct S {
    S();
    S(S const&) = delete;
  };
  S f() { return S(); }  // Now accepted in C++17 mode.
  S s = f();             // Now accepted in C++17 mode.

This example still elicits warnings or errors in pre-C++17 modes.

The changes for this C++17 feature also affect some pre-C++17 cases.  For
example:

  template<typename T> T val() noexcept; 
  struct E { E(const E&) = delete; };
  template<typename T> struct B {
    B() noexcept(noexcept(T(val<T>())));
  };
  struct D: B<E> {
    D() = default;
  };

Previously this produced an error in all C++11 modes.  Now, the diagnostic is
reduced to just a warning in nonstrict C++11 modes.


9/13/17  [EDGcpfe/18767]
Microsoft compatibility: typeid and incomplete class types

In Microsoft C++ modes with microsoft_version >= 1912, the front end no longer
accepts the typeid operator applied to an incomplete class type (see the entry
of 5/2/08).  For example:

  #include <typeinfo>
  struct S;
  void f() {
    typeid(S);  // Previously a warning in all Microsoft C++ modes.
  }             // Now an error if microsoft_version >= 1912.


9/13/17  [EDGcpfe/18632,EDGcpfe/18694]
Structured bindings in range-based-for iterator declarations

The original implementation of structured bindings in version 4.14 omitted the
case where that feature is used in range-based-for iterator declarations.
For example:

  struct A { int a, b; };
  extern "C" int printf(char const*, ...);
  int main() {
    A ar[] = { 1, 2, 3, 4, 5, 6 };
    for (auto [x, y] : ar) {       // Previously an error.  Now okay.
      printf("(%d, %d)\n", x, y);
    }
  }

This is now fixed.


9/13/17  [EDGcpfe/18765]
Incorrect folding of certain dependent logical operators

Under certain circumstances, rescanning a dependent logical operator in a
context requiring a constant-expression could produce an invalid result.
This is now fixed.  Below is an example of a case that previously produced
the wrong result in C++17 mode (causing the final static_assert to fail).

  template<bool V> struct B {
    static bool const value = V;
  };
  template<typename D, typename S>
  struct NA: B<__is_nothrow_assignable(D, S)> {
  };

  template<typename H, typename... Ts> using F = H;

  template<typename... Ts> struct S {
    template<typename U>
      void operator=(U) noexcept(!!NA<F<U, Ts...>&, U>::value) {
    }
  };
  static_assert(NA<S<int>, int>::value, "");  // Previously failed in C++17
                                              // mode.

This particular case only started failing in version 4.14 due to the noexcept
specifier becoming part of C++17 function types in that version.  However, the
underlying issue exists in prior versions too.


9/13/17  [EDGcpfe/18764]
Internal error creating substituted exception specification

When exception specifications are part of the type (e.g., C++17 mode),
an internal error could occur in create_pack_instantiation_descr on
a class member function template declaration that contains a parameter
pack expansion.  Now fixed.

  void f(...) {}
  template<class T> struct A {
    template<class... Ts> void g(Ts... ts) noexcept(noexcept(f(ts...))) {}
  };
  A<int> s;


9/13/17  [EDGcpfe/18495]
Abort on noexcept in Microsoft in-class specialization

An abort could occur (in add_token_cache_segment_to_string) if a Microsoft
in-class specialization of a class contained a noexcept specifier and
RECORD_TEMPLATE_STRINGS is TRUE.  Now fixed.

  template<typename T> class A { 
    template<bool> struct B { };
    template<> struct B<true> {
      template<typename U> void f() noexcept(true) { }
    };
  };
  int main() {
    A<int> a;
  }


9/12/17  [EDGcpfe/18550]
Abort on invalid reference to inlined namespace member

Consider:

  inline namespace N {
    void f();
    void f(int);
  }
  int N::f;  // Previously triggered an abort.  Now a normal error.

The last declaration is invalid.  Previously, however, it triggered an abort
due to a null pointer indirection.  That is now fixed.


9/12/17  [EDGcpfe/18598]
Abort in add_reference_indirection for tuple-like reference structured binding

The front could previously abort on a case like:

  #include <tuple>
  auto t = std::tuple<int>{42};
  auto &[i] = t;

The abort occurred in add_reference_indirection because the expression stack
was not set up (i.e., expr_stack was null).  This is now fixed.


9/12/17  [EDGcpfe/18761]
Internal error in copy_exc_spec_from_prototype_template

In some C++17 modes (particularly, Microsoft C++17 mode with microsoft_version
at least 1912), the front end aborted in copy_exc_spec_from_prototype_template
on some uses of function templates with an exception specification.  For
example:

  template<typename> struct S {
    template<typename U>
      void f() noexcept(true) {}
  };
  template struct S<int>;  // Previously triggered an internal error.

This is now fixed.


9/12/17  [EDGcpfe/18692]
Designated initializers and reference parameter binding

In C++ modes that accept designated initializers, the front end previously did
not correctly handle the following example:

  struct S { int i, j; };
  void f(S&&) {}
  int main() {
    f({.i = 1, .j = 2});  // Previously an error.  Now okay.
  }

because the parameter of f has a reference type.  In some more elaborate cases
this could even lead to an internal error.  That is now fixed.


9/12/17  [EDGcpfe/18588]
Internal error on variable template used in dependent non-type template
default argument

An internal error could occur (in strip_types_from_template_arg_list)
if a function template used a dependent variable template instance as
a default template argument.  Now fixed.

  template <typename T, int I> struct A {
    static constexpr int v = 1;
  };
  template <typename T, int I> constexpr int A_v = A<T, I>::v;
  template <typename T, int = A_v<T, 1>> void f() { }
  int main() {
    f<int>();
  }


9/12/17  [EDGcpfe/18762]
Incorrect type used in constant for flag describing exception type

As a result of the changes for EDGcpfe/18732, the type used to pass exception
type flags changed from an unsigned char to an int (the default value of the
new configuration macro TARG_ETS_FLAG_TYPE_INT_KIND), but one instance of that
change (in add_exception_type_spec_array_entry) was missed and is now fixed.


9/12/17  [EDGcpfe/18757]
Compilation error in some configurations

A compilation error (in pch_fixup_part_1) had occurred in some configurations.
Now fixed.


9/11/17  [EDGcpfe/18727]
Representation of dynamic_cast with static effect

The front end previously unconditionally optimized the representation of a
dynamic_cast operation known to have a static effect by replacing it with IL
for a static_cast or reinterpret_cast.  For example:

  struct V { virtual ~V(); };
  struct C1: virtual V {};
  struct C2: virtual V {};
  struct D: C1, C2 {};
  D *p = dynamic_cast<D*>((V*)nullptr);

This change of representation causes a problem for the C++-generating back end
which renders the initialization in this example as:

  D *p = ((D *)((V *)nullptr));

which is an error because a virtual base class cannot be cast to a derived
class using an ordinary cast.  This problem is now fixed by disabling the
optimization when DOING_SOURCE_ANALYSIS or BACK_END_IS_CP_GEN_BE is TRUE.
The slightly-relaxed semantic constraints for such cases remain in effect,
however (e.g., the destination class type need not be complete in all cases).


-------------------------------------------------------------------------------
Version 4.14, September 12, 2017

9/6/17   [EDGcpfe/18741]
Feature test macro refresh

The list of standard feature test macros supported by the front end has
been updated to reflect the latest version of the WG21 document (P0096R4,
dated 2017-07-26).


9/6/17   [EDGcpfe/17703]
C++17: if constexpr

The front end now implements the C++17 if constexpr feature as described
in P0292R2.

This is an IL CHANGE as there is a new stmk_constexpr_if statement kind
that must be handled in both the unlowered and lowered IL.  In lowered IL,
a back end should only generate code for the non-discarded statement.

  void do_this(int){}
  template <class T> inline void f(T t) {
    if constexpr(sizeof(T) == sizeof(int)) {
      do_this(t);
    } else {
      do_that(t);
    } 
  }
  int main() {
    f(1);  // okay
    f('c'); // error: do_that is undefined
  }


9/6/17   [EDGcpfe/18317]
GNU and Clang C++ compatibility: deduction of the noexcept flag

g++ and clang allow deduction of the noexcept flag of a function type.
This is not currently part of the C++17 standard.  This is now allowed
in g++ and clang modes.

  template <typename R, typename ... Args, bool Noex>
  void f(R (*fp)(Args...) noexcept(Noex)) {}

  void g1(int);
  void g2(int,int) noexcept(true);
  void g3(int,int,int) noexcept(false);
  int main() {
    f(g1);
    f(g2);
    f(g3);
  }


9/5/17   [EDGcpfe/18732]
New configuration macro for passing exception type flags to run time library

A new configuration macro, TARG_ETS_FLAG_TYPE_INT_KIND, has been added to
allow configuration of the type used to pass exception type flags to the
run time library.  The type, previously a_byte in some places in the front end
and int in others, now defaults to int unless ABI_COMPATIBILITY_VERSION < 414
in which case it is an unsigned char.  The change is made in anticipation of
adding other bits to the ETS_* set of bits (currently limited to 8 because
the flags are stored in a_byte in the run time library).  This type is passed
to the run time library with --building_runtime as the new __EDG_ETS_FLAG_TYPE
configuration macro.

This is an IL CHANGE for customers that use lowering to generate exception
handling tables (unless TARG_ETS_FLAG_TYPE_INT_KIND is set to
((an_integer_kind)ik_unsigned_char)).


9/1/17   [EDGcpfe/18712]
Spurious folding error on return of empty class type

The front end previously issued a spurious error on the following example:

  struct B {};
  struct D: B {};
  constexpr D f() { return {}; }
  constexpr auto x = f();  // Previously an error.  Now okay.

That is now fixed.


9/1/17   [EDGcpfe/18704]
Spurious folding error on use of alias template with known type

Consider:

  template<bool> struct F;
  template<bool B> using X = F<((void)B, true)>;
  template<bool U> X<U> x;  // Previously a spurious error.  Now okay.

Previously, the front end issued a spurious error on the expansion of X<U> for
the prototype instantiation of x<U> (complaining the template argument of F is
not constant).  That is now fixed.


9/1/17   [EDGcpfe/18723]
Spurious error on constexpr variable template with no initializer

The front end previously issued a spurious error on a variable template
definition like:

  template<typename T> constexpr T x;

because it is constexpr and has no explicit initializer.  That is now fixed.


9/1/17   [EDGcpfe/18541]
Spurious exception specification error on inheriting constructor with
default member initializer

The front end previously issued a spurious error about a circular dependency
when processing an inheriting constructor with an exception specification in
a derived class with a default member initializer.  For example:

  struct B {
    B(int) noexcept;
  };
  struct D: B {
    using B::B;  // Previously produced a spurious error.  Now okay.
    int i = 42;
  };

This is now fixed.


8/31/17  [EDGcpfe/18626]
C++-generating back end: reordering of #pragma pack directives

In some previous versions of the front end, #pragma pack was treated as an
immediate pragma, processed as soon as it was encountered in the source.
The result of this setting was that the source sequence entry for a
#pragma pack directive could appear out of order with respect to the
end-of-construct entry for a preceding class.  The C++-generating back end
compensated for this problem by deferring putting out #pragma pack
directives until the next declaration, or the end of the source file, was
encountered.  As a result, #pragma pack directives could be emitted out of
order with respect to other non-declaration elements such as other pragmas.
The #pragma pack directive was changed some time ago to be a "next token"
pragma, eliminating the need for this special handling in the
C++-generating back end, and the code has now been updated to preserve the
source order of these pragmas.  For example, with
INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL set to TRUE and with --microsoft, the
code generated for the following example is the same as the input
(previously the #pragma pack directives were all moved to the end of the
file):

  #pragma warning(push)
  #pragma warning(disable : 4159 4127)
  #pragma pack(push, 4)
  #pragma pack(push, ATL_PACKING)
  #pragma warning (push)
  #pragma warning (disable: 4127) 
  #pragma warning (pop)
  #pragma warning (push)
  #pragma warning (disable: 4127) 
  #pragma warning (pop)
  #pragma pack(pop)
  #pragma warning(pop)


8/29/17  [EDGcpfe/18458]
Assertion failure in mark_entry

In some Cfront configurations (e.g., where INSTANTIATE_EXTERN_INLINE is
FALSE), mangling certain entities that have the GNU "abi_tag" attribute
had caused an assertion failure in mark_entry.  The failure seems limited
to cases where multiple translation units are being compiled.  For example,
with --gnu_version=40900, if an empty translation unit and the following
one are given, the assertion had triggered and is now fixed:

  namespace {
    struct A {
      __attribute((__abi_tag__(""))) float f() {
        typedef struct {} x;
      }
    };
  } 


8/28/17  [EDGcpfe/18597]
Clang compatibility: enable terse static_assert in C++11 mode

The C++17 terse static_assert construct (see the Changes entry for
EDGcpfe/17408) is now accepted in C++11 clang emulation mode.


8/25/17  [EDGcpfe/18644]
GNU compatibility: __builtin_types_compatible_p and const array elements

In GNU C mode with gnu_version >= 40000, the front end now ignores type
qualifiers on array element types when evaluating the GNU intrinsic function
__builtin_types_compatible_p (in GNU C++ mode, this was already the case).
For example:

  _Static_assert(__builtin_types_compatible_p(int const[8], int[8]), "");
    // Now accepted in recent GNU C modes.


8/24/17  [EDGcpfe/18687]
Abort in determine_correspondence on proxy class

When simultaneously compiling multiple translation units the front end
sometimes aborted in determine_correspondence when handling a member of a
proxy class (i.e., a class representing a template parameter).  This is now
fixed.


8/24/17  [EDGcpfe/18697]
Internal error in lowering after SFINAE case with throw expression

A SFINAE failure in a throw expression could result in an error type leaking
into the IL, which in turn could lead to an abort during IL lowering.  For
example:

  template<typename T> auto f(T y)->decltype(throw 1<<y);
  template<typename T> auto f(T y)->decltype(1<<(int)y);
  int r = f(12.34);  // Previously caused an abort in lowering.

In this example, the first candidate is discarded because of an error in the
throw expression (a built-in shift operator cannot have a floating-point
operand).  However, the SFINAE process creates an error type, and in the
context of a throw expression, that error type previously ended up in the IL
tree.  IL lowering then triggered an internal error when attempting to lower
that error type.  This is now fixed.


8/22/17  [EDGcpfe/18667]
C++-generating back end: invalid pragma output

In some cases, the C++-generating back end would emit two pragma directives
without a newline between them.  Now fixed.


8/17/17  [EDGcpfe/17696]
C++17: overaligned storage allocation

In C++17 mode, the front end now supports extended-alignment storage
allocation as described in Committee document P0035R4.  In particular, the
type std::align_val_t is predeclared (but not visible to user code until
explicitly declared), along with overloads for the standard allocation and
deallocation functions, to support allocation and freeing of objects with
more stringent alignment requirements than fundamental alignments, and the
predefined macro __STDCPP_DEFAULT_NEW_ALIGNMENT__ is also defined to the
value of the configuration macro TARG_DEFAULT_NEW_ALIGNMENT.  Allocation
and deallocation requests for types whose alignment is greater than this
value will result in calls to the appropriate function with a parameter of
type std::align_val_t.  For example, with --c++17 (and configured with
TARG_DEFAULT_NEW_ALIGNMENT set to 16):

  struct alignas(64) S { int j; };
  S *p = new S;  // Calls operator new(std::sizeof, std::align_val_t)


8/17/17  [EDGcpfe/18678]
Spurious error on specialization of member template

The front end could issue a spurious "specialization ... must precede the
first use" error on an explicit specialization of a member template if an
instance of the member template was used in an unevaluated context prior
to the specialization.  An error should only be issued if the use would
result in the instantiation of the instance.  Now fixed.  In addition,
the diagnostic issued for such errors has been changed to a discretionary
error.

  template <class T> struct A {
    template <class U> static int f(U){ return 0; }
  };
  decltype(A<int>::f(1)) x;
  template <> template <class U> int A<int>::f(U){ return 0; }


8/16/17  [EDGcpfe/18646]
Parameter pack reference incorrectly dropped from IL

Consider:

  template<bool> struct X;
  template<bool... Bs> using Y = X<((void)Bs, true)...>;

Previously, the front end folded the comma expression "(void)Bs, true" to just
"true", dropping the "(void)Bs" from the IL altogether.  That caused the C++-
generating back end to produce incorrect code, since the pack expansion no
longer referred to any packs.  This is now fixed.


8/14/17  [EDGcpfe/18664]
Constexpr interpreter: Value-initialization of empty derived class

The C++ interpreter failed to correctly record the value-initialization of an
object of an empty class type derived from another (empty) class type.  This
could lead to aborts, particularly when attempting to perform a cast from the
empty base class to the empty derived class.  For example:

  struct B {};
  struct D: B {};
  constexpr int f() {
    D d = D();
    D *p = (D*)(B*)&d;  // Previously aborted.  Now okay.
    return 42;
  }
  constexpr int r = f();

This is now fixed.


8/11/17  [EDGcpfe/18661]
Incorrect evaluation of init-capture in constexpr lambda

In some cases where an init-capture was represented as a zero initialization,
the constexpr interpreter failed to actually perform that initialization,
causing unpredictable results.  For example:

  struct S { int x ; };
  auto x = [y = S()]() { return [&]{ return y; }(); }();

Previously, the init-capture "y = S()" in the outer lambda expression left the
underlying closure member uninitialized and x ended up with an unpredictable
value.  That is now fixed.


8/11/17  [EDGcpfe/18662]
Failure to diagnose deducible return type leads to potential aborts

The front end previously failed to diagnose deducible return types in contexts
that do not permit them.  This could potentially lead to aborts in the front
end.  For example:

  #include <typeinfo>
  std::type_info const &x = typeid(auto());  // Invalid use of "auto".

Previously, the front end did not diagnose the invalid use of "auto" in this
example, and aborted during lowering in get_typeinfo_var.  This is now fixed.


8/9/17   [EDGcpfe/18659]
Abort in IL traversal after decltype(auto) deduction failure

The front end aborted during IL traversal on cases like the following after
issuing an error.

  template<typename T> void f(T);
  template<typename T> void f(int);
  void g() {
    decltype(auto) p = f<double>;
  }

This is now fixed.


8/9/17   [EDGcpfe/18658]
Friend variable templates

In C++14 mode, the front end previously aborted on the following case:

  struct S {
    void f();
    template <class U> friend int f;
  };

and silently accepted the case if the member function declaration is omitted.
This is now fixed.


8/9/17   [EDGcpfe/18657]
Abort on malformed anonymous union containing an exception specification

In some cases, a malformed anonymous union containing an invalid member
declaration with an exception specification could lead to an abort in
rescan_reusable_cache.  For example:

  template<typename> struct X {
    union {
      void f() noexcept(false);
    };
  };
  X<short> v;

That is now fixed.


8/9/17   [EDGcpfe/18652]
Temporaries and constexpr subobjects

The constexpr interpreter previously did not always correctly record a
subobject constructed from a temporary value as actually being initialized.
This could result in spurious constant-expression evaluation errors.
For example:

  struct X { int x; };
  constexpr auto makeX(int) { return X{}; }
   
  struct Y { X m; };
  constexpr auto makeY(int p) { return Y{makeX(p)}; }
  
  constexpr auto y = makeY(0);  // Previously an error because member x
                                // was not seen as initialized.

This is now fixed.


8/9/17   [EDGcpfe/17378]
Ordering of initialization in lowered range-based-for loops

The ordering of initialization of temporary variables created during the
lowering of range-based-for loops could result in incorrect initialization of a
temporary variable.  A lowered range-based-for loop is decomposed into multiple
scopes and in the example below the initialization of one of these temporary
variables had been inadvertently placed in a scope outside of the scope in
which the variable was declared, resulting in invalid generated C code in the
C-generating configuration.  Now fixed.  For example (with --c++11):

  struct A {
    virtual void vf();
    A& begin();
    A& end();
    int operator!=(A);
    int operator*();
    void operator++();
    void f();
  };
  void A::f() {
    for (auto i:*this);
  }


8/9/17   [EDGcpfe/18086,EDGcpfe/18562]
Unbounded loop in subobject_conflict on Microsoft property field

In Microsoft C++ mode, the front end could previously get stuck in an unbounded
loop in subobject_conflict (layout.c) for certain class types containing
nontrivial properties or events (which are represented in the IL as fields, but
are not directly mapped in object layout).  This is now fixed.


8/8/17   [EDGcpfe/18237]
Duplicate mangled name for local string literals

Consider:

  struct S {
    const char *str;
    constexpr S() : str("aaa") {}
    void f(char const*);
  };
  extern inline void g() {
    S().f("bbb");
  }
  int main() { g(); }

With the IA-64 ABI, lowering creates global variables for the local string
literals "aaa" and "bbb", and uses a sequence number unique within the
enclosing function to distinguish them from potential other string literals
in that enclosing function.  In this case, there is only one string literal
in each function and thus the sequence numbers of both literals is 1.
However, because the S() constructor is constexpr, the "aaa" literal was
previously referred to from function g(), which resulted in its associated
variable being mangled identically to the variable associated with "bbb".
That in turn led to linker errors.  That problem is now fixed.


8/8/17   [EDGcpfe/18616]
Incorrect diagnostic position with FULLY_RESOLVED_MACRO_POSITIONS

In versions with FULLY_RESOLVED_MACRO_POSITIONS set to TRUE, some diagnostics
could incorrectly refer to the position of a macro definition instead of the
use.  If the macro definition was supplied on the command line, this would
result in a diagnostic being issued with no associated position.  Now fixed.

  #define U8 char
  typedef unsigned char U8;  // diagnostic pointed to line 1


8/3/17   [EDGcpfe/17685,EDGcpfe/18637]
C++17: Exception specifications as part of function types

C++17 makes exception specifications part of the function type.  The front end
now implements that behavior in C++17 mode or when the new command-line option
--exc_spec_in_func_type is specified (the C++17 behavior can also be overridden
with --no_exc_spec_in_func_type).  For example:

  void g1() noexcept;
  void g2();
  template<typename T> int f(T*, T*);
  int x = f(g1, g2);    // Okay in C++14.  Now an error in C++17 mode.

Here, the function type deduced for T is different for both parameters because
exception specifications are now part of the type.

C++17 also removes dynamic exception specifications.  In modes that make
exception specifications part of the type, such dynamic exception
specifications now elicit a discretionary error (and if the effective
severity of the message is lower than an error, the exception specification
is ignored).  For example:

  void e() throw(int);  // Now an error in strict C++17 mode.

Making exception specifications part of function types affects the ABI.
For example, the mangled name of

  void h(void (*)() noexcept);

has to reflect the "noexcept".  The configuration macro
EXC_SPEC_IN_FUNC_TYPE_ENABLING_POSSIBLE can be set to FALSE to disable this
feature in all modes, thereby maintaining ABI stability at the expense of
standards conformance.

To support the throwing of pointers to function types with noexcept
exception specifications in configurations where lowering generates
exception tables, a new bit, ETS_IS_POINTER_TO_NOEXCEPT_FUNCTION, is introduced
to indicate the presence of a noexcept exception specification on the
underlying function type.  Due to the lack of bits in the run time library's
an_ETS_flag_set type, ETS_IS_POINTER_TO_NOEXCEPT_FUNCTION uses the same bit
as ETS_IS_ELLIPSIS with (ETS_IS_POINTER_TO_MEMBER_FUNCTION | ETS_IS_POINTER)
being used to distinguish between the two cases.  This is a subtle IL CHANGE.


8/2/17   [EDGcpfe/18098]
Microsoft compatibility: missing "template" keyword in template template arg.

The Microsoft compiler allows a dependent name used as a template template
argument to omit the "template" keyword.  We now emulate this behavior
in Microsoft mode.

  template <template <class> class T> struct A {
    static const int value = 1;
  };
  template <class T, class U> struct D {};
  template <class T> struct B {
    template <class U> using type = D<T,U>;
  };
  template <class T> struct C {
    static const int i = A<B<T>:: /*template */ type>::value;
  };


8/2/17   [EDGcpfe/18394]
Microsoft compatibility: redeclaration of class template via using-declaration

In Microsoft (permissive) mode, a class template made visible via a
using-declaration can now be redeclared or defined in the scope containing
the using-declaration.

  namespace N {
    template <class T> struct A {};
  }
  using N::A;
  template <class T> struct A;


7/28/17  [EDGcpfe/18620]
Default value of DEFAULT_MAX_DEPTH_CONSTEXPR_CALL

The default value of DEFAULT_MAX_DEPTH_CONSTEXPR_CALL has been reduced for
DEBUG builds to reduce the possibility of stack overflows (because optimized
builds use much less stack space than unoptimized ones).  The non-DEBUG
default has also been reduced from 1000 to the standard-suggested value
of 512 to avoid stack overflow issues on some systems.


7/26/17  [EDGcpfe/18603]
Missing diagnostic on invalid variable template default template arguments

The front end failed to diagnose a variable template declaration that
contained a default template argument that was followed by a parameter
without a default argument.  This could result in an internal error
in IL lowering (in lower_type).  Now fixed.

  template < class T = int , class U > int A = 1;
  A<> a;


7/25/17  [EDGcpfe/18389]
Abort in lowering on lambda in default argument of another lambda

The front end previously aborted on cases like the following:

  auto x = [](int p = [](int q){ return q; }(42)) { return p; }();

where a lambda expression appears in the default argument of another lambda
expression (with linkage).  This is now fixed.


7/24/17  [EDGcpfe/18596]
Abort on variadic member function called within class definition

Consider:

  struct S {
    template<typename... Ts> auto f(Ts ...ps) { return 42; }
    int x[f()];
  };

Previously, this triggered an internal error in prelower_class_type
(lower_il.c).  Now, an error is issued on the call of f() in the array
declarator.


7/24/17  [EDGcpfe/18536]
Defaulted constructors and constexpr

The front end no longer issues an error for defaulted constexpr constructors
that could not possibly be evaluated in a constant-expression context.
For example:

  struct F { F(int) {} };
  template <int i> struct S {
    constexpr S(): f(0) {}
    F f;
  };
  struct X {
    constexpr X() = default;
    S<0> s;
 } x;

Previously, an error was issued while generating the default constructor of X
because the initialization of member s requires a call to a non-constexpr
constructor.  Now, this example is accepted, but calls to the default
constructor of X are never evaluated at compile time.


7/22/17  [EDGcpfe/18591]
Type of second argument to __cxa_vec_cctor library call

As a result of the changes for EDGcpfe/17482 (in 4.13), the second argument to
the __cxa_vec_cctor library call had an incorrect type which has now been
fixed.  Only affects configurations where IA64_ABI is FALSE and DO_IL_LOWERING
is TRUE.


7/21/17  [EDGcpfe/18589]
Clang compatibility: _Static_assert enabled in C11 mode

_Static_assert is now enabled in clang C11 emulation mode.


7/18/17  [EDGcpfe/17704,EDGcpfe/17954]
C++17: Inline variables

As described in C++ Committee document P0386R2, the front end now supports
inline variables and static data members.  Like inline functions, inline
variables can be defined in multiple translation units without creating
linker errors, but have a unique identity (address and value) in the
resulting program.  Such variables are identified in the IL via the
is_inline field of a_variable.  During lowering, inline variables are
assigned to COMDAT groups, even in the Cfront ABI (COMDAT groups were
previously used only in the IA-64 ABI).  For example, with --c++17:

  inline const int i = 15;
  struct S {
    inline static int j = 25;
  };


7/11/17  [EDGcpfe/18568,EDGcpfe/18570]
Incorporate changes for builtins from GCC 6.4.0

The front end has been updated to incorporate changes in builtin signatures
for the recently-released GCC 6.4.0 release.


7/11/17  [EDGcpfe/18569]
Type of fourth argument to __vec_delete library call

As a result of the changes for EDGcpfe/17482 (in 4.13), the type of the fourth
argument to the __vec_delete library call had an incorrect type which has now
been fixed.  Only affects configurations where IA64_ABI is FALSE and
DO_IL_LOWERING is TRUE.


7/11/17  [EDGcpfe/18565]
Incorrect partial ordering involving variadic template parameters

In some cases, the front end incorrectly reported an ambiguity when partial
ordering should prefer a template that deduces more non-variadic template
parameters over one that deduces fewer non-variadic template parameters.
Now fixed.

  template <class T1> struct A;
  template <template <class...> class TT, class... Ts>
  struct A<TT<Ts...>> {
    static constexpr bool value = false;
  };
  template <template <class...> class TT, class T, class... Ts>
  struct A<TT<T, Ts...>> {
    static constexpr bool value = true;
  };
  template <class ...> struct B { };
  // Previously ambiguous
  static_assert(A<B<int>>::value == true,  "");


7/7/17   [EDGcpfe/17691,EDGcpfe/18560]
C++17: Fold Expressions

The front end now accepts "fold expressions", a feature that allows folding
binary operators over parameter packs.  For example:

  template<typename ... Ts> auto g(Ts ... ps) {
    return (1 * ... * ps);
  }
  int main() {
    return g(2, 3, 7);  // Returns 42 == 1*2*3*7
  }

Prototype instantiations represent this construct using a new enk_fold node
kind, but real instantiations represent the expanded construct using existing
IL patterns.


7/7/17   [EDGcpfe/18528]
Incorrect behavior when lambdas are used with ALTERNATE_IL_FILE_FORMAT=0

Various kinds of incorrect behavior (e.g., aborts, internal errors) could
occur when lambdas were used with the non-alternate IL file format.  This
problem was introduced in version 4.11 with the changes for EDGcpfe/16292.
Now fixed.

  int main() {
    auto lambda = [](int x, int y) { return x + y; };
    auto res = lambda(1, 2);
    if (res != 3) return 1; 
  }


7/3/17   [EDGcpfe/18535]
Incorrect folding of subscript applied to integer cast to pointer type

Consider:

  int *p = &((int*)0x1000)[1];  // Previously incorrectly folded.

The front end previously accidentally discarded the offset implied by the
subscript operation.  This regression introduced in version 4.13 of the front
end is now fixed.


6/29/17  [EDGcpfe/18514]
Abort on decltype of non-class type in qualified name

An abort could occur (in class_qualified_id_lookup) if a decltype was
used in a qualified name and the resulting type was not a class type
(in the example below it is a reference to class type).  Now fixed.

  struct A { int i; };
  void f(const A& a) {
    a.decltype(a)::i ;
  }


6/26/17  [EDGcpfe/18534]
Unneeded null-pointer tests removed in interpreter

Some unneeded null-pointer tests were removed from the interpreter (in function
do_constexpr_range_based_for_statement) because they triggered warnings by
certain static analysis tools.


6/26/17  [EDGcpfe/18519]
Internal error on complex template-dependent reference return type

In function templates involving a somewhat complicated template-dependent
return type known to be a reference type the front end sometimes aborted with
an internal error in convert_operand_into_temp.  For example:

  template<typename T>
  auto f(T const &p) -> decltype(p)&& {
    return (decltype(p)&&)p;  // Previously aborted with an internal error.
  }                           // Now okay.

This is now fixed.


6/26/17  [EDGcpfe/18489]
Internal error on namespace with typedef and multiple using-declarations

An internal error could occur (in lookup_in_namespace) if a namespace
contained a typedef to a struct and also multiple using-declarations
that refer to the same struct to which the typedef refers.  Now fixed.

  namespace A { struct S {}; }
  namespace B { typedef A::S S; }
  namespace B { using A::S; }
  namespace B { using A::S; }
  B::S x;

6/22/17  [EDGcpfe/18518]
Spurious qualification conversion error on pointer-to-member array

The front end previously issued a spurious error on a case like the following:

  typedef char AT[8];
  struct S { AT arr; };
  int main() {
    AT const S::*pm = &S::arr;  // Previously triggered a spurious error.
  }                             // Now okay.

because of a bug handling qualifiers on array types.  This is now fixed.


6/22/17  [EDGcpfe/18524]
Spurious unbounded recursive template substitution

Consider the following example:

  auto f(...)->int;
  template<class T> auto f(T x)->decltype(f(x), int{});
  int r = f(42);

Previously, this triggered an error due to excessive recursive substitution
because the call "f(x)" found the template declaration in which is appears.
This is now fixed (it no longer finds the template, and only considers the
ellipsis function).


6/20/17  [EDGcpfe/16621,EDGcpfe/17959,EDGcpfe/18497]
Spurious error on constexpr defaulted constructor with trivial base constructor

The front end previously issued a spurious error on the following case:

  struct B {};
  struct D: B {
    constexpr D() = default;  // Previously an error.  Now okay.
  };

because it failed to notice that the trivial construction of the empty base
class B is valid in a constant-expression context.  That is now fixed (i.e.,
the case is now accepted).


6/20/17  [EDGcpfe/18162]
Microsoft compatibility: Case labels

Case labels cast to pointer types (e.g., "case (int*)0x1234:") are no longer
accepted in Microsoft mode when permissive mode is turned off.  (See also
the entry of 12/9/01 that describes this Microsoft case label extension.)

6/20/17  [EDGcpfe/18383]
Spurious error during brace-notation cast in SFINAE context

Consider the following example:

  template < typename T> int f();
  template < typename T, typename = decltype(T{})> int f(); // (1)
  struct S { S() = delete; S(int); };
  int r = f<S>();  // (2)  Previously an error.  Now okay.

This substitution of T = S in the declaration (1) of function template f
should fail in a "SFINAE" sense (i.e., silently, causing that declaration
to be discarded when resolving the call in (2)).  However, the front end
previously failed to notice the SFINAE context, and emitted an actual error
in all cases.  This is now fixed.


6/19/17  [EDGcpfe/17989]
Binding a reference to const pointer parameter of an overloaded function
to a function template instance

Consider the following example:

  template <typename U> void f(U);
  int g(int);
  int g(void (* const &)(int));
  int r = g(f);  // Previously an error.  Now okay.

Previously, the front end failed to consider a possible match between an
instance of f and the reference to const pointer parameter in the second
declaration of function g.  That is now fixed.


6/15/17  [EDGcpfe/18320]
GNU C++ compatibility: Conversion from lambda to function pointer

The front end previously unconditionally emulated a GCC bug that causes a
conversion function to exist for closure types associated with lambda
expressions that include a "capture default" (i.e., "[=]" or "[&]"); see
the entry for EDGcpfe/14585.  Now, that emulation is disabled when
gnu_version >= 60200, since GCC 6.2.0 apparently fixed the bug.


6/15/17  [EDGcpfe/18233]
Spurious error on scoped enum operation

The front end sometimes emitted a spurious error for an operation on values
of a scoped enum type when different type qualifiers are involved.  For
example:

  enum class E { e };
  struct S {
    S();
    E const g;
  };
  int main() {
    return S{}.g == E::e;  // Previously elicited a spurious error.  Now okay.
  }

This is now fixed.


6/15/17  [EDGcpfe/18360]
Spurious correspondence error on conversion function template

When simultaneously compiling multiple translation units containing conversion
function templates, the front end sometimes issued a spurious correspondence
error on matching conversion functions.  This is now fixed.


6/15/17  [EDGcpfe/18488]
Spurious assertion failure when BUILTIN_FUNCTIONS_ENABLED is TRUE and
GNU_VECTOR_TYPES_ALLOWED is FALSE

In configurations where BUILTIN_FUNCTIONS_ENABLED is TRUE but
GNU_VECTOR_TYPES_ALLOWED is FALSE, an assertion check in check_target_config
could fire if integer types don't have certain prescribed sizes.  Now fixed.


6/15/17  [EDGcpfe/18042,EDGcpfe/18482]
Spurious SFINAE failure on nested member template reference

In some fairly complex situations, the front end did not correctly substitute
a reference to a member template in a function template signature, thereby
triggering a spurious SFINAE failure (i.e., discarding a candidate template
that should be treated as a viable candidate instead).  For example:

  template<bool b> struct E;
  template<typename ... Ts> struct V { V(); };
  template <typename Head, typename ... Tail> struct V<Head, Tail...> {
    Head f; 
    V<Tail...> r;
    V(Head d,  Tail ...args) : f(d), r(args...) {}
    template<int N>
      auto e() -> decltype ( E<(bool)N>::template g<N>(*this) );
  };
  template<bool b> struct E {
    template<int N, typename ... Ts>
      static auto g(V<Ts...> &p) -> decltype(p.r.template e<N-1>());
  };
  template<> struct E<false> {
    template<int N, typename ... Ts>
      static auto g(V<Ts...> &a) -> decltype(a.f);
  };
  struct S {} s;
  V<S*, S*> v(&s, &s);
  static_assert(sizeof(v.e<1>()) == sizeof(&s), "");

Previously, this elicited a compiler error claiming no match for the call
"v.e<1>()" due to a failure to correctly substitute "p.r.template e<N-1>()"
in the declaration of E::g.  This problem is now fixed and this case is
now accepted.


6/13/17  [EDGcpfe/15649,EDGcpfe/16799,EDGcpfe/17813,EDGcpfe/18071,
          EDGcpfe/18167,EDGcpfe/18459]
Constexpr interpretation and complex floating-point types

The constexpr interpreter can now handle complex and imaginary floating-point
types in modes that enable all the required features (e.g., GNU C++11 mode).


6/12/17  [EDGcpfe/18471]
Abort in determine_function_viability on empty pack expansion

In some overload resolution cases involving a variadic function template
candidate with an empty pack expansion but too many arguments (a somewhat
unusual combination), the front end aborted with an internal error in
determine_function_viability (overload.c).  For example:

  template<class T> T* f(unsigned, long const &);
  template<class T, class ... Ts> T* f(Ts ..., const long&);
  char *b = f<char>(0, 'x');  // Previously triggered an abort.  Now okay.

This is now fixed.


6/9/17   [EDGcpfe/17937,EDGcpfe/18479]
GNU compatibility: __builtin_addressof

__builtin_addressof (see the changes for EDGcpfe/16955) is now available
when gnu_version >= 70000.


6/9/17   [EDGcpfe/17901,EDGcpfe/18362]
Invalid IL for some array aggregates initialized in conditional operations

In cases where aggregates are initialized inside a conditional operation and
the conditional operation is contained within a block scope that is different
than the temporary it initializes, the local static variable initializer had
been created in the wrong scope.  In C-generating back end configurations
this had resulted in an assertion failure (find_local_static_variable_init:
none found for specified variable and scope).  This regression was introduced
in 4.12 (by the changes for EDGcpfe/17317).  For example (with --c++11):

  struct A {
    int x, y;
  };
  void f(int p) {
    {
      0 ? A{0, 0} : A{p, 0};
    }
  }


6/8/17   [EDGcpfe/18451]
Error in handling of address of reference to variable in interpreter

The constexpr interpreter previously did not correctly handle taking the
address of a reference to a non-constexpr variable.  For example:

  int x;
  constexpr bool f() {
    int *p = &x;
    int &r = x;
    return &r == &x;
  }
  static_assert(f(), "");  // Previously sometimes failed.

Previously, the expression "&r" was not correctly handled by the interpreter,
causing the result of "&r == &x" to be unpredictable.  That is now fixed.


6/8/17   [EDGcpfe/18460]
Spurious interpretation failure on cast to private base class

The front end sometimes spuriously failed to interpret a cast to a private
base class (reporting it as an attempt to access run-time storage).  For
example:

  struct B {};
  struct D: private B {
    static constexpr B* g(D *p) { return p; }
  };
  D d{};
  constexpr B *pb = D::g(&d);  // Previously triggered an error.  Now okay.

This is now fixed.


6/8/17   [EDGcpfe/18461]
Constexpr and address of static-lifetime temporary

Consider:

  #include <initializer_list>
  template<typename T> struct S {
    constexpr S(T p): p(p) {}
    T p;
  };
  template<typename T> constexpr S<T> g(T p) {
    return S<T>(p);
  }
  constexpr std::initializer_list<int> x{1, 2};
  constexpr auto y = g(x.begin());  // Previously an error.  Now okay.

Previously, this elicited an error because the evaluation of g(x.begin())
produces a value that embeds the address of a temporary.  Now, the case is
accepted because that temporary has a static lifetime.


6/8/17   [EDGcpfe/18324,EDGcpfe/18468]
Abort on dependent array bound

The front end sometimes aborted with an internal error in num_array_elements
when handling a default-initialized array variable with a dependent bound.
For example:

  struct S { constexpr S() {} };
  template<typename T> void g() {
    S xs[T::N][2];  // Previously triggered an internal error.  Now fixed.
  }

This regression introduced in version 4.13 (by the changes for EDGcpfe/17934)
is now fixed.


6/7/17   [EDGcpfe/17328,EDGcpfe/18463]
Constexpr interpretation of certain constructor calls

Consider:

  struct A {
    void *p;
    constexpr A(): p(this) {}
  };
  constexpr A x = A();

The copying of A() to x is elided: The constructor call "A()" is evaluated
directly into x.  Previously, the interpreter failed to see that the "this"
pointer value for that constructor call is therefore not the address of the
temporary but that of the variable x.  As a result of this failure it did
not successfully complete the interpretation of that constructor call and
issued a spurious error.  That is now fixed.


6/7/17   [EDGcpfe/18370]
Abort due to faulty correspondence of dependent alias template instantiations

The front end no longer attempts to establish cross-translation-unit
correspondences for dependent alias template instances (other than the
prototype instantiation).  Our prior attempt to do so was faulty and it
turns out that it cannot be done in general with our current IL constraints.
This fixes internal errors in some relatively complex situations.


6/7/17   [EDGcpfe/18465]
Uninitialized fields in a_recorded_diagnostic when CHECKING is FALSE

Two fields of a_recorded_diagnostic, scope_of_prev_check and
number_of_times_suppressed, were initialized only when CHECKING is TRUE,
potentially producing undefined behavior in configurations where CHECKING is
FALSE.  Now fixed.


6/2/17   [EDGcpfe/18435]
Abort in expand_statement_inline

A segfault (in expand_statement_inline) could occur in some cases when inlining
a function that has an empty block statement.  For example (with --c++17):

  template <int i> bool f();
  struct A {
      int x = f<[]{ return 29; {} }()>();
  };


6/1/17   [EDGcpfe/18454]
GCC compatibility: -0.0 and GCC builtins

The __builtin_abs* and __builtin_signbit* GCC functions now handle -0.0
properly during constant folding (previously they returned -0.0 and 0
respectively).  For example, with --g++:

  int main() {
    return __builtin_signbit(-0.0);   // had returned 0, now 1
  }


5/31/17  [EDGcpfe/18340]
GNU/clang compatibility: __asm keyword with --ms_extensions

In g++ and clang mode, when --ms_extensions is used, the __asm keyword
can be used for both Microsoft and GNU purposes.  Formerly, the front
end would always expect the Microsoft syntax.  Now fixed.

  void f()
    __asm ("f");
  int main() {
     __asm nop
  }


5/30/17  [EDGcpfe/18450]
Assertion failure in record_substitution_for_type

In some IA-64 ABI configurations where MANGLE_ALL_NAMES is TRUE, the mangling
of a prototype instantiation containing a pointer-to-member type where the
class of the pointer-to-member is a dependent typedef could cause an
assertion failure (in record_substitution_for_type).  This only occurs in
GNU emulation mode.  This is a regression introduced in 4.13 by the changes
for EDGcpfe/17822.  For example (with --g++):

  template <typename T> struct A {
    typedef T O;
    typedef void (O::*M)();
    A(O* o, M m) {}
  };

Now fixed (when ABI_COMPATIBILITY_VERSION >= 414).


5/30/17  [EDGcpfe/18310]
Clang compatibility: __type_pack_element builtin

When clang_version >= 30900, the __type_pack_element builtin is now enabled.
This builtin takes at least two template arguments.  The first template
argument is for a non-type template parameter of type size_t that specifies
which of the remaining template arguments to select as the returned type for
the builtin.  The index argument is zero-based.  For example (with
--clang_version 30900):

  __type_pack_element<0, int, double, bool> i = 0;    // declares an int
  __type_pack_element<1, int, double, bool> d = 1.0;  // declares a double
  __type_pack_element<2, int, double, bool> b = true; // declares a bool

__has_builtin(__type_pack_element) is now TRUE when __type_pack_element is
available.


5/29/17  [EDGcpfe/18438]
Spurious "declared with type with no linkage" error

A spurious "function ... declared using a type with no linkage, must be
defined" error could be issued if a template function was used in a way
that did not actually require its instantiation.  Now fixed.

  Enum { e0 };
  template<typename T> struct A {
    static T f()
    static int (&g(...));
    static const bool value = sizeof g(f);
  };
  template<typename T> inline int g(const T &) {
    return A<T *>::value;
  }
  int i = g(e0);


5/29/17  [EDGcpfe/18417]
Incorrect matching of dependent template variables

The front end did not properly compare dependent template variable
references.  This could result in spurious errors.  In the example
below, the definition of E::f was not considered to match the declaration
in the class.  Now fixed.

  template <bool B> struct A {};
  template <typename T> constexpr bool var = 0;
  struct E {
    template <typename U> void f(U, A<var<U>>);
  };
  template <typename U> void E::f(U, A<var<U>>){}


5/24/17  [EDGcpfe/18046]
Spurious error on comparison of dependent function address

The front end previously issued a spurious error on certain comparisons
involving the address of a dependent function.  For example:

  template <typename> void g();
  template <typename T> bool  f() {
    return &g<T> != nullptr;  // Previously, this triggered a spurious error.
  }

This is now fixed.


5/22/17  [EDGcpfe/18413]
Bad interpretation of <integer> @= <floating-point>

The constexpr interpreter previously did not correctly handle expressions of
the form x @= y where x is an integer expression and y is a floating-point
expression (and @= is one of +=, -=, *= or /=).  The result of interpreting
such a construct was near-random (it could just fail interpretation, or it
might abort because of corrupted interpreter storage).  This is now fixed.


5/22/17  [EDGcpfe/18419]
Spurious error on __builtin_addressof in template

During prototype instantiations, an invocation of __builtin_addressof (see
the entry for EDGcpfe/16955) could produce a spurious error about its operand
not being an lvalue.  For example (in Clang mode):

  template<typename T> struct S { int i; };
  template<typename T> void f(S<T> *p) {
    __builtin_addressof(p->i);  // Previously elicited a spurious error.
  }                             // Now okay.
  template void f(S<int>*);

This is now fixed.


5/19/17  [EDGcpfe/18418]
Abort rescanning variable template reference

An abort could occur (in update_template_param_symbols) during template
argument substitution of an expression involving a variable template
instance.  Now fixed.

  template <bool B> struct A { };
  template <> struct A<true> { using t = void; };
  template <bool B> using C = typename A<B>::t;
  template <class T, class... Args> struct D {
    static constexpr bool v = true;
  };
  template <class T, class... Args> constexpr bool D_v = D<T, Args...>::v;
  template <class A, class B> struct E {
      E() { }
      template <class X, class Y, typename = C<D_v<A, X>>> E(E<X, Y>&&) { }
  };
  int main() {
    typedef E<int, int> T;
    T t(T{});
  }


5/19/17  [EDGcpfe/18359,EDGcpfe/18416]
Spurious error on conditional operator in template-dependent context

Consider the following example:

  template<bool> struct B { };
  template<typename T> bool b = sizeof(T) < 42;
  template<typename T, typename = B<b<T> ? true : false>> void f();
      // Previously an error.  Now okay.

Previously, this elicited an error claiming b<T> does not have a known value.
That is now fixed.


5/17/17  [EDGcpfe/18392]
Spurious overload resolution error in Microsoft bugs mode

Consider the following example:

  struct S {
    void f(double const* const&);
    void f(double*);
  };
  void g(S s, double *p) {
     s.f(p);  // Previously ambiguous in Microsoft bugs mode.  Now okay.
  }

Previously, the call "s.f(p)" was treated as ambiguous in Microsoft bugs mode.
Now it is accepted and selects the second member function (as in other modes)
when microsoft_version >= 1400.


5/16/17  [EDGcpfe/18366]
Instability in interpreter on use of array initialized with string literal

The constexpr interpreter in the front end maintains mappings between the
object representations it operates on and the IL entries that represent those
objects.  For example:

  constexpr char msg[] = "A Message";
  constexpr char const *ptr = msg+2;

Here the storage for the string "A Message" has a mapping to the constexpr
variable msg, so that the evaluation of msg+2 can eventually produce a
ck_address/abk_variable entry pointing to msg.  However, previously, this
mapping was corrupted in a way that is rarely observable.  That is now fixed.


5/16/17  [EDGcpfe/18378]
Spurious diagnostic on nontype parameter in partial specialization

In C++11 and newer modes, a spurious diagnostic could be issued if a
nontype template parameter in a partial specialization resulted in
an implicit cast in the IL.  The diagnostic was an error, except in
g++ mode where it was a warning.  Now fixed.  In this example, the type
of Y is T but the type of the corresponding template parameter of B
is T::type, so an implicit cast is added.

  template <typename T, T X> struct A { typedef T type; };
  template <typename T, typename T::type> struct B {};
  template <typename T, T X, T Y> struct B <A <T,X>, Y> {};
 

5/15/17  [EDGcpfe/17825,EDGcpfe/17998]
C++17 compatibility: capturing *this by value

In modes enabling C++17 compatibility, the front end now accepts "*this" as
a lambda capture, signifying that the entire object to which "this" points
(and not just the value of the "this" pointer) is to be copied into the
closure object (see Committee document P0018R3).  Support for this feature
involves a small IL CHANGE: when the captured.variable field of
a_lambda_capture designates a "this" parameter, the capture_by_reference
flag is TRUE to indicate that the pointer value of "this" is captured and
FALSE when the entire "*this" object is captured. (That flag was previously
FALSE when "this" was captured.) For example, with --c++17:

  struct S {
    int i;
    void f() const {
      auto L = [*this]{ return i; };  // lambda captures the entire S object
    }
  };


5/14/17  [EDGcpfe/18369]
GNU C++ compatibility: spurious error on friend template in class template

When deferral of function prototype instantiations is being done in g++
mode, spurious errors resulted from doing additional prototype instantiations
of friend function templates of a class template.  Only the prototype
instantiation in the original definition context should be done, but
with deferral of function prototype instantiations, additional prototype
instantiations could be done in the context of the instantiated containing
classes.  Now fixed.

  template <class T> struct A {
    A();
  };
  template <typename T> struct B : A<T> {
    template <typename U = int> constexpr friend B f1(B b) { return b; }
    constexpr void f2() { f1(*this); }
  };
  void f3(B<int> d) {
    d.f2();
  }


5/13/17  [EDGcpfe/18283]
IL write-read error on object lifetimes

In configurations where KEEP_OBJECT_LIFETIME_INFO_IN_LOWERED_IL_WHEN_EH_ENABLED
is TRUE and HANDLE_VIRTUAL_BASES_IN_SUBOBJECT_CTOR_DTORS is FALSE, an IL
write-read error could occur when lowering certain constructors that
contain gotos or labels (or constructs that are lowered to gotos or labels).
For example:

  struct B {
    ~B();
  };
  struct D : virtual B {
    D();
  };
  D::D() {
    while (true) {
      break;
    }
  }


5/13/17  [EDGcpfe/18364]
Internal error on mismatched #if/#endif when producing debug output

An internal error could occur (in db_include_guard_info) if a file
was missing a #endif statement and a debug level >= 4 was specified
(e.g., -d5 on the command line).  Now fixed.


5/13/17  [EDGcpfe/18281]
Microsoft compatibility: [[deprecated]] attribute support

Support for the standard form of the deprecated attribute is now enabled
when microsoft_version >= 1910.  For example:

  [[deprecated]] void f(void) { }
  void g(void) {
    f();    // Now gives a suitable warning when microsoft_version >= 1910.
  }


5/9/17   [EDGcpfe/18265]
IA-64 ABI: missing substitution for template template parameter

In IA-64 configurations the front end had missed allocating a substitution
for a template template parameter, resulting in mangled names that could not
be properly demangled.  A change has been made (when ABI_COMPATIBILITY_VERSION
>= 414) to perform this allocation.  This change affects mangled names for
prototype instantiations.  For example (in a configuration where
MANGLE_ALL_NAMES and BACK_END_IS_CP_GEN_BE are TRUE):

  template<template<typename> class TT, typename T, typename U>
  class ct {
    void mf(TT<T>, TT<U>);
  };

The mangled name for ct<TT, T, U>::mf had been
_ZN2ctIT_T0_T1_E2mfET_IS0_ES3_IS1_E and is now
_ZN2ctIT_T0_T1_E2mfES0_IS1_ES0_IS2_E.  Mangled names for instantiations of
this template are unchanged.


5/8/17   [EDGcpfe/18342]
Spurious error on dependent inheriting constructor

Consider the following example:

  template<typename T> using Type = typename T::Type;
  struct S {
    template<typename T> struct B {
      using Type = T;
    };
    template<typename T> using BA = Type<B<T>>;
  };
  template<typename T> struct D: S::BA<T> {
    using Base = S::BA<T>;
    using Base::Base;  // Previously an error.  Now okay.
  };

Previously, the front end failed to note that D<T>::Base is the same type as
S::BA<T>, and therefore issued a spurious error suggesting it does not refer
to a direct base class (during the prototype instantiation of D<T>).  That is
now fixed.


5/8/17   [EDGcpfe/17690,EDGcpfe/17995]
C++17 compatibility: constexpr lambdas

In modes enabling C++17 compatibility, lambdas may now be declared constexpr
and invocations of qualifying lambdas may appear in constant expressions,
as described in Committee document P0170R1.  For example, with --c++17:

  auto ID = [](int n) constexpr { return n; };
  constexpr int I = ID(3);  // Now permitted in C++17 mode


5/8/17   [EDGcpfe/18293]
Binding a nontype template parameter of reference type

A nontype template parameter of reference type should bind to a function or
to a complete object.  However, the front previously failed to diagnose
attempts to bind such a parameter to a null address.  For example:

  template<int &R> struct X {};
  constexpr int *p = nullptr;
  X<*p> x;  // Previously accepted.  Now an error.

This is now fixed (an error is issued).


5/8/17   [EDGcpfe/18000]
Microsoft/Clang compatibility: constexpr evaluation support for string builtins

The following new builtins have been added in Microsoft emulation mode (when
microsoft_version >= 1911): __builtin_char_memchr, __builtin_memchr,
__builtin_memcmp, __builtin_strchr, __builtin_strcmp, __builtin_strlen,
__builtin_strncmp, __builtin_wcschr, __builtin_wcscmp, __builtin_wcslen,
__builtin_wcsncmp, __builtin_wmemchr, and __builtin_wmemcmp.
Additionally, these builtins are now evaluated in a constant expression
context.  In clang mode, when clang_version >= 40000,
__has_feature(cxx_constexpr_string_builtins) is now TRUE.


5/8/17   [EDGcpfe/17992]
Microsoft compatibility: Conditional operator

In Microsoft compatibility mode, the front end emulates several nonstandard
behaviors of Visual C++ with respect to the ternary conditional operator (?:).
Now, those behaviors are disabled when Microsoft permissive mode is turned off
(option --no_ms_permissive) or when the new option --ms_strict_ternary is
specified (that option matches the option /Zc:ternary available in recent
previews of Visual C++).  For example:

  struct C {
    C(void*);
    operator void*();
  } c(0);
  void g(bool b, void *p) {
    b ? c : p;  // Accepted in normal Microsoft mode.  Ambiguous in
  }             // non-permissive Microsoft mode.


5/8/17   [EDGcpfe/18288]
Passing a scoped enum value through an ellipsis parameter

Previously, passing a scoped enum value through an ellipsis parameter could
cause the C-generating back end to trigger an internal error.  That is now
fixed by having such arguments be converted to the promoted underlying integer
type.  For example:

  enum class E: short { e };
  int f(...) { return 1; }
  int main() {
    return f(E::e);  // Previously triggered an internal error.  Now okay.
  }                  // E::e is now implicitly "promoted".


5/5/17   [EDGcpfe/18326]
GNU C++ compatibility: typename influences lookup

The standard specifies that the "typename" keyword, when used for syntactic
disambiguation, does not affect the lookup result.  However, g++ does ignore
non-types when the typename keyword is used.  We now emulate this in g++ mode.

  struct A {
    struct B {};
    int B;
  };
  struct C {
    typename A::B ab;
  };


5/4/17   [EDGcpfe/18323]
Pack expansion in brace-notation cast during function template substitution

The front end did not correctly handle the expansion of a parameter pack
inside a brace-notation cast during the substitution of a function template
declaration.  For example:

  struct I { I(int); };
  template<int P> auto f()->int;
  template<int...Is> auto g() -> decltype(I{f<Is>()...});
  I i  = g<0>();

Here, the expansion of "I{f<Is>()...}" failed while substituting the argument
list "<0>" in function template g, and the call "g<0>()" was diagnosed as an
error as a result of that failure.  This is now fixed.


5/4/17   [EDGcpfe/18322,EDGcpfe/18487,EDGcpfe/18608]
GCC compatibility: Builtin functions for 7.1.0

The builtin function definitions have been updated to reflect the builtin
functions declared in GCC 7.1.0.  109 new builtin functions were added.


5/4/17   [EDGcpfe/18155]
Clang compatibility: Builtin functions for 4.0.0

The builtin function definitions have been updated to reflect the builtin
functions declared in clang 4.0.0.  85 new builtin functions were added
and some of the function signatures were updated (e.g., to include exception
specifications).


5/4/17   [EDGcpfe/18232]
Function templates referenced during deduction

Consider the following example:

  template<int> struct S { typedef int I; };
  class C {
    template<int n> struct N {
      void f() {
        static_assert(n<0, "");  // Previously triggered an error.
      }
    };
  public:
    C() {}
    template<typename... Ts, bool = S<N<sizeof...(Ts)>::f>::I> C(...);
  };
  C g() {
    C x;
    return x;  // Copy construction.
  }

In the final return statement, the value of x must be copied to the caller of
g().  The front end considers not only the generated copy constructor of C,
but also the member constructor template C::C(...).  That member template
requires template argument deduction, which in this case deduces an empty
argument pack for Ts, which substituted in the default argument that follows
creates a reference to N<0>::f.  Previously, that reference triggered the full
instantiation of C::N<0>::f and therefore a error due to the failing
static_assert in that member function, even though, in the end, the member
constructor template referring to C::N<0>::f is not used.  This is now fixed:
References to template functions during template argument deduction no longer
force their instantiation.


5/3/17   [EDGcpfe/18164]
Microsoft compatibility: Enabling C++17 features

A new command-line option, --ms_c++17, has been added to emulate the /std:c++17
option that Microsoft Visual Studio 2017 version 15.3 provides.  This option is
only available when microsoft_version >= 1911.  Additionally, when
microsoft_version >= 1911 and one of --ms_c++17 or --ms_c++latest is specified,
support for these C++17 features is now enabled: direct-list-initialization of
enums from numeric values (P0138R2), using attribute namespaces without
repetition (P0028R4), removal of deprecated operator++ for bool types, and
deprecation of the "register" keyword.


5/3/17   [EDGcpfe/18179]
Tag names and declarations in condition scopes

A name declared in a condition scope cannot also be declared in the scope that
it immediately encloses.  The front end was previously enforcing that rule
strictly in all modes (as indicated by the C++11 standard).  Now, in nonstrict
modes, tag names can coexist with non-tag names.  For example:

  void g() {
    if (int N = 3) {
      struct N {} n;  // Previously an error.  Now okay in nonstrict modes.
    }
  }


5/2/17   [EDGcpfe/18311]
Memory exhaustion in copy_variant_path

A bug in variant path entry management in the constexpr interpreter could
lead the front end to enter an unbounded loop allocating variant path entries
(in copy_variant_path).  Eventually, the front end ran out of memory.  This
is now fixed.


5/2/17   [EDGcpfe/18315]
Performance issue with deeply nested function explicit template argument lists

Certain unusual cases involving nested function template explicit template
argument lists where the template parameter is a nontype parameter with
pointer-to-function type, and that rely on the ability to use an expression
such as &f<x> as a function pointer when it identifies a unique function
template instance, could require exponential compilation time and space
use.  Now fixed.

  template <int(*fp)()> int f() { return 0; }
  int g() { return 0; }
  int h() {
    auto v = f<&f<&f<&f<&f<&f<&f<&f<&f<&f<&f<&g>>>>>>>>>>>();
    return v;
  }
  int main() {
    h();
  }


4/28/17  [EDGcpfe/18305]
Incorrect IL for repeated aggregate initialization in C++14 mode

The changes for EDGcpfe/15900 (version 4.10.1) introduced a regression when
an aggregate initializer for an array called for the implicit initialization
of trailing array elements with a nontrivial default constructor: It
default-initialized those elements when they should have been
value-initialized.  This was particularly observable for class types
containing a pointer-to-data-member field in the IA-64 ABI, because such
fields must be initialized to an underlying offset of -1.  For example:

  struct S {};
  int main() {
    using PM = char S::*;
    struct { PM pm; int i = 42; } x[3] = {{0}};
  }

Previously, the IL produced for this example left x[1].pm and x[2].pm
uninitialized (often, they would be zero); now it is value-initialized
(the underlying offset is set to -1).


4/28/17  [EDGcpfe/18306]
Interpreted base-class cast sometimes fails to preserve null pointer

Version 4.13 introduced a regression causing the front end to fail to
preserve null pointer values in certain base-class casts.  For example:

  struct I { I* n; };
  struct K { int i; };
  struct V: K, I {};
  struct M {
     using P = V*;
     constexpr bool f() {
       return (I*)P() == nullptr;
     }
  };
  static_assert(M().f(), "Unexpected");  // Previously failed.  Now okay.

Previously, the cast "(I*)P()" turned the null address produced by "P()" into
an offset from a null address.  Now, the null address is preserved.


4/26/17  [EDGcpfe/18286]
Constexpr functions and function-try blocks

The front end previously failed to diagnose a constexpr function defined with
a function-try block (it only issued an error when trying to evaluate a call
to the function in a context requiring a constant result).  For example:

  constexpr int f() try { return 1; } catch (...) { return 2; }
    // Previously, the definition above was accepted in C++11 mode.
    // Now it is an error.
  double z[f()];
    // This call was (and still is) diagnosed as an error.

This is now fixed.


4/26/17  [EDGcpfe/18008,EDGcpfe/18236]
Scoped enumerations are no longer lowered (slight IL CHANGE)

Now that prototype instantiations are included in the IL, it was possible to
get an unlowered enumerator from a scoped enumeration in the IL.  That posed
problems because lowering removes the scope associated with the enumeration,
resulting in an IL write-read error in some configurations.  A change has been
made to forgo lowering of scoped enumerations.  This should also provide better
information for debuggers.  For example (with --c++11 -tused):

  enum class E { e };
  template <class T, E> void h();
  template <class T> void g() {
    h<T, E::e>();
  }
  void f() {
    g<int>();
  }


4/25/17  [EDGcpfe/18258]
Abort in generic_cast_constant after local deduced-return type declaration

In some elaborate examples, the front end could abort with an internal error
in generic_cast_constant after processing a local declaration of a function
with a deduced return type.  For example (C++14 mode):

  auto f() try {
    throw 42;
  } catch (...) {
    auto f();
    return [x = [](auto y){ return y; }](auto z){ return x (z); }(42);
  }
  int main() {
    int x = f();  // Previously triggered an internal error.
  }

This is now fixed.


4/25/17  [EDGcpfe/18242]
Abort on constexpr call in invalid template-id

In configurations that systematically record backing expressions in constants,
the front end previously aborted (with an internal error in function
scan_template_argument_constant_expression) if a template argument list was
specified on a nontemplate entity and one of its arguments included a call to
a constexpr function.  For example:

  constexpr int f() { return 42; }
  int x<f()>;  // Previously aborted in some configurations.  Now okay.

This is now fixed.


4/25/17  [EDGcpfe/18285]
Unbounded loop on address of array element subobject

The front end sometimes entered an unbounded loop in the constexpr interpreter
(in function translate_interpreter_offset) when attempting to fold an address
of a subobject of an array element.  For example:

  struct X { int x = 1; };
  constexpr X ax[2] = {{}};
  int const *p = &ax[1].x;
                  // Previously triggered an unbounded loop.  Now fixed.

This is now fixed.


4/25/17  [EDGcpfe/18252]
Conversion function templates and qualification conversions

When a conversion function template is called, a qualification conversion
can be used as part of the template argument deduction process.  The
resolution of core 349 indicated that cv-qualifiers should be dropped from
the deduced type (so that T would be deduced as "int" and not "const int"
in the example below).  It appears that other compilers did not implement
this rule and that the rule may not be desirable.  The front end no longer
drops the cv-qualifiers pending reconsideration of this issue by the
standards committee.

  struct A {
    const int *p;
    A() : p(0){}
    template <typename T> operator T**() { return &p; }
  };
  int main() {
    int const * const * ip = A();  // now succeeds
  }


4/24/17  [EDGcpfe/18268]
Incorrect exception handling cleanup state

In configurations where lowering generates exception handling tables, in cases
where a static aggregate requiring partial aggregate destruction is followed by
a file scope initialization requiring destructions, the generated cleanup state
was incorrect (potentially destroying a portion of the aggregate twice).  For
example:

  struct A {
    A();
    ~A();
  };
  A aa[] = { A() };
  struct C {
    C();
  };
  C *c = new C();
  int main() {
    delete c;
    return 0;
  }


4/24/17  [EDGcpfe/18192]
Assertion failure on __builtin_choose_expr with parenthesized operand

In GNU mode with PARENS_IN_IL set to TRUE, the front end could abort with an
assertion failure in conv_glvalue_expr_to_prvalue if its selected operand is
a parenthesized expression.  For example:

  void g(int i) {
    __builtin_choose_expr(0, i, (i));  // Previously aborted in some
  }                                    // configurations.

This is now fixed.


4/24/17  [EDGcpfe/18262]
Assertion failure in record_substitution_for_type

In IA-64 ABI configurations where all names are mangled and
emulate_gnu_abi_bugs is TRUE, an assertion failure (in
record_substitution_for_type) could be triggered when mangling a dependent type
that refers to a typedef.  This regression was introduced in 4.13 by the
changes for EDGcpfe/17822.  For example (with --set_flag emulate_gnu_abi_bugs
--g++ --c++11):

  typedef int iterator;
  template <typename T> auto f(T x) -> decltype(iterator{x});


4/24/17  [EDGcpfe/18251]
Spurious error on constexpr constructor definition

Consider the following example in C++14 mode:

  template<typename> struct N { N() {} };
  template<typename B> struct C: B {
    constexpr C(): B() {}
  };
  struct D: C<N<int>> {
    constexpr D(): C<N<int>>() {}  // Previously an error.  Now okay.
  };

Previously, the front end issued an error because the default constructor of
C<N<int>> is not actually "constexpr" (because its base class N<int> doesn't
have a constexpr constructor).  Now the error is no longer issued because the
constructor was declared "constexpr" (and became non-constexpr only after
instantiation).


4/21/17  [EDGcpfe/18278]
Scanning small integer literals

A small change was made to optimize the scanning of numbers for the case of
single-digit integer literals.


4/20/17  [EDGcpfe/18249]
GNU C++ compatibility: injected template name following "template"

g++ allows the use of constructs such as "T:: template X", where X
is an injected class name of a class template.  This was accepted by the
front end when gnu_version <= 40400 because of a related GNU compatibility
feature.  In version 4.13 the default gnu_version was changed, so
some code that was previously accepted was now rejected.  Now, in g++
mode, we allow an injected class name of a class template to be used
following the "template" keyword.

  template <class T> struct A { };
  template <class T, template<class> class U = T::template A> struct B { };
  B< A<int> > b;


4/19/17  [EDGcpfe/18215]
Abort in constexpr evaluation of array element access in union

In some cases, the constexpr interpreter aborted with an internal error in
translate_il_address_offset while attempting to represent the folded result
of accessing an array element in a union.  For example:

  union U {
    int x[3] = {1, 2, 3};
  };
  constexpr int& f(int& p) {return p;}
  int r = f(U().x[0]);  // Previously triggered an internal error.

This is now fixed.


4/19/17  [EDGcpfe/17964,EDGcpfe/17999]
C++17 compatibility: __has_unique_object_representations type traits helper

The front end now recognizes the __has_unique_object_representations type
traits helper, which supports the std::has_unique_object_representations
trait (described in Committee document P0258R2).  It returns TRUE if every
bit of the object representation is part of the value and every bit pattern
represents a different value.  The current implementation assumes that the
result is true for integers, void, pointers, and pointers to members and
false for other fundamental data types.  For architectures and/or ABIs
where that assumption is not correct, the logic of the function
type_has_unique_object_representations (folding.c) will need to be adjusted
appropriately.  For example:

  struct A {
    char c;
    int  i;
  };
  bool b = __has_unique_object_representations(A);  // false: padding bits
                                                    // are not part of value


4/17/17  [EDGcpfe/18230]
Representation of folded array decay operation

When folding an array decay operation on a file-scope array, the changes for
EDGcpfe/17888 caused the resulting address constant to no longer set the
"implicit_cast" flag.  This was disadvantageous for certain code-generating
back end (and caused the C-generating back end to emit an extraneous cast).
For example, in C mode:

  int a[10];
  void f(int*);
  void g() {
    f(a);  // Previously rendered as "f(int*)(&a))" by the C-generating
  }        // back end.

The previous behavior is now restored.


4/14/17  [EDGcpfe/17414,EDGcpfe/17706]
C++17: Selection statements with initializers

The front end now accepts a leading "initializer statement" as part of the
control value construct of a selection statement (i.e., "if" or "switch"
statement).  For example:

  int f();
  void g() {
    int x;
    if (f(); int x = 1) {}
    if (int x = 1; f()) {}
    if (x = 1; f()) {}
    if (int x = 1; int y = 1) {}
    if (int x = 1, h(), z = f(); int y = 1) {}
  }

This feature was added to the working paper for C++17 through paper P0305R1.


4/12/17  [EDGcpfe/18185]
Abort when folding result of accessing anonymous union members

In some cases, when an expression producing a pointer or reference to an
anonymous member was interpreted, the front end aborted with an internal
error in find_subobject_for_interpreter_address.  This is now fixed.


4/10/17  [EDGcpfe/18160]
Microsoft compatibility: Binding of "this" to deduced lvalue reference

In Microsoft mode, the front end previously permitted binding of "this" to an
lvalue reference parameter with a deduced type (see the entry of 10/5/04) even
though the type underlying the reference is not "const".  Now, this nonstandard
behavior is only enabled when microsoft_version < 1910.  For example:

  template<typename T> void g(T&);
  struct X {
    void f() {
      g(this);  // Previously accepted in all Microsoft C++ modes.  Now
    }           // an error if microsoft_version >= 1910.
  };


4/10/17  [EDGcpfe/18182]
Microsoft compatibility: internal error on nonstandard elaborated type
specifier

Microsoft allows an elaborated type specifier to declare a type that
hides an existing typedef name in that scope.  An internal error could
occur (in symbols_may_coexist_in_curr_scope) if the type being hidden was
a typedef to a type that was not a class or enumeration type.  Now fixed.
The problem was caused by an assertion check that was too strict, so
versions without CHECKING enabled worked properly.

  typedef void *t;
  class A {
    struct t *v;
  };


4/10/17  [EDGcpfe/18165]
Microsoft compatibility: Default arguments and out-of-class member definitions

Ordinarily, an out-of-class definition of a member function of a class template
cannot specify default arguments.  In Microsoft mode, however, this was
accepted with a warning.  Now, it is an error in non-permissive Microsoft
modes when microsoft_version >= 1911.  For example:

  template<typename> struct S { void f(int); };
  template<typename T> void S<T>::f(int = 0) {}
    // Now an error in non-permissive Microsoft modes.  (Still accepted
    // with a warning in permissive Microsoft modes.)


4/10/17  [EDGcpfe/18178]
GNU compatibility: References to static data members

Ordinarily, static data members of class templates are instantiated whenever
they are referenced (with some exceptions for constant-valued members or
references from unused default arguments).  In GNU C++ modes, this is no
longer the case if the address of the member is not taken and its value is not
needed.  For example:

  namespace {
    template<typename T> struct S {
      static int m;
    };
  }
  int main() {
    (void)S<int>::m;
  }

Ordinarily, this example leads to an error because S<int>::m is referenced
but it has no definition.  In GNU C++ mode, this is now accepted (the program
also successfully links) because S<int>::m doesn't have its value or address
used.


4/10/17  [EDGcpfe/18181]
G++ and Clang compatibility: Enable __decltype to be used as a base specifier

GCC version 4.7.0 and later, as well as Clang, accept __decltype as a
base specifier and now so does the front end.  For example (with --clang):

  struct B {};
  struct A : __decltype(B()) {};


4/7/17   [EDGcpfe/18153]
Invalid folding result with certain constexpr array variables

In some cases, the folded value of accessing an element of a constexpr array
variable produced random results.  For example:

  int main () {
    constexpr char d[2] = "";
    constexpr char l = d[1];
    constexpr wchar_t f[2] = L"";
    constexpr wchar_t n = f[1];
    static_assert(n == 0, "Unexpected");  // Failed on some platforms.
  }

This is now fixed.


4/7/17   [EDGcpfe/18109]
Clang compatibility: Accepting patch-level "version number" in attribute

The Clang "availability" attribute can take "version numbers" as arguments,
but when those version numbers specify patch-level information, e.g., 10.12.1,
the value cannot be parsed as a floating-point token and a spurious error
is given.  A change has been made (only in Clang emulation mode) to parse
such strings (i.e., a series of decimal digits and periods) as a new
tok_clang_version token.  The following example (with --clang) now compiles
(but the "availability" attribute is still ignored):

  void f1() __attribute__((availability(tvos,introduced=10.12.1)));


4/6/17   [EDGcpfe/18151]
Spurious "limited lifetime" folding error

The front end sometimes issued a spurious error claiming a subexpression
is not a constant due to a reference addressing a temporary with a limited
lifetime.  For example, in C++11 (or later) mode:

  struct S {};
  struct X {
    constexpr X(S const&) {}
  };
  constexpr X x{{}};  // Previously, triggered a spurious error.

This is now fixed.


4/6/17   [EDGcpfe/18124]
Clang compatibility: Enable __make_integer_seq in all configurations

Support for __make_integer_seq in clang was added by EDGcpfe/17337, but only
when MICROSOFT_EXTENSIONS_ALLOWED was TRUE.  A change has been made to
support it in all configurations.


4/6/17   [EDGcpfe/18089,EDGcpfe/18142]
Spurious Microsoft-mode error on call to constexpr template member function

In Microsoft mode, a call to a constexpr member function instance from within
the same parent class sometimes failed to fold because the instance was not
full instantiated.  In constant-expression context, this resulted in spurious
errors.  For example (with microsoft_version == 1900):

  template<typename T> struct C {
    template<typename U> static constexpr int f(U*) { return 1; }
    template<typename> static constexpr int f(...) { return 0; }
    static constexpr int v = f<T>(nullptr);
  };
  int t = C<int>::v;  // Previously a spurious error in Microsoft mode.

This is now fixed.


4/6/17   [EDGcpfe/18141]
Abort in interpreter on member access from a null pointer value

Consider the following example:

  struct S {
    int x, y[1];
  };
  int* g() {
    return ((struct S *)0)->y;
  }

The interpreter produced a ck_integer run-time constant for the returned
expression but later treated it as a ck_address constant instead, potentially
triggering an abort in variable_has_constant_address.  That is now fixed.


4/5/17   [EDGcpfe/18158]
Unbounded loop in constexpr interpreter on default member initializer

In some cases where a default member initializer depended on the address of a
data member, the front end could end up in an unbounded loop in the constexpr
interpreter (in function translate_interpreter_offset).  For example:

  struct B {};
  struct D: B {} ;
  struct X { B *x; };
  struct L {
    X const *p;
    constexpr L(X const &x): p(&x) {}
  };
  struct S {
    D d;
    L l{X{&d}};  // Previously triggered an unbounded loop.
  };

This is now fixed.


4/5/17   [EDGcpfe/18169]
Reference to uninitialized storage

With the changes for EDGcpfe/17722 (in 4.13), the front end can access
uninitialized storage in cases where an attribute appertains to a parameter,
resulting in undefined behavior.  For example (with --c++14):

  int func([[deprecated]] int arg) {
    return arg;
  }


4/5/17   [EDGcpfe/18175]
Clang compatibility: Builtin functions with --clang --ms_extensions

A change has been made to enable "Microsoft builtins" when ms_extensions
is TRUE (previously they were only enabled when microsoft_mode was TRUE).
A separate change has also been made to disable the diagnostic that occurs
when a difference in dllimport/dllexport flags is detected on a builtin
function.  For example (with --clang --ms_extensions):

  __declspec(dllimport) __declspec(noreturn) void __cdecl _exit(int _Code);
  void f() {
    __debugbreak();
  }


4/5/17   [EDGcpfe/17413,EDGcpfe/17705]
C++17: Structured Bindings (IL CHANGE)

The front end now supports "structured bindings" (also known as "decomposition
declarations") as introduced into the working paper for C++17 by P0217R3.  For
example:

  struct S { int i:3, j; } s = { 1, 2 };
  auto [x, y] = s;
  int r = x;   // r is set to 1.
  int p = &x;  // Error: x is a bit field.

A few IL changes are of note.  First, the assoc_param_type field of
a_variable has been moved to a "variant" sub-field.  Second, the array case
requires copying built-in arrays.  In the case of array elements requiring
copy constructor invocations, this is represented by an aggregate
initializer with a dik_constructor entry whose first "argument" is the
array (and a flag is_array_copy indicating that this is a special case);
when no constructor invocations are required, an eok_bassign with an array
rvalue second operand (which could not previously occur in the IL) is used.
See il_def.h for details.  Finally, the individual bindings are always
represented with a_variable entries.  However, when binding fields or array
elements, these do not represent traditional stored variables but
"expression aliases".  A new initializer kind initk_binding characterizes
these cases.


4/4/17   [EDGcpfe/15044]
GNU compatibility: Non-object pointer arithmetic and __extension__

In GNU modes, the front end often accepts pointer arithmetic on pointer to void
and pointer to function types.  Ordinarily, a warning is issued in those cases,
but now that warning is not issued if the expression is prefixed with the GNU
keyword __extension__.  For example:

  extern void *p;
  int g() {
    void *q = p+1;                // Accepted with a warning in GNU C mode.
    void *r = __extension__(p+1); // Accepted with no warning in GNU C mode.
    return q == r;
  }


4/4/17   [EDGcpfe/17693,EDGcpfe/17993]
C++17 compatibility: Direct-list-initialization of enums from numeric values

The front end now supports the C++17 feature described in Committee
document P0138R2.  This capability allows conversion of a numeric value to
an enumeration type if the enumeration has a fixed underlying type, the
initialization is direct-list-initialization, and the conversion does not
involve narrowing.  For example, with --c++17:

  enum byte : unsigned char { };
  byte b{ 42 };   // Permitted by C++17

This feature is also enabled in Microsoft mode when microsoft_version is
at least 1911.


4/2/17   [EDGcpfe/16986,EDGcpfe/17029]
Initializers with braces in template declarations

The template processing in the front end used a prescan that did not
work properly in some cases involving braced initializers.  This could
result in spurious errors when such initializers were used in contexts
such as the return type of a function and the template argument list
of a partial specialization.  Now fixed.

  struct A {
    constexpr operator bool() const { return true; }
  };
  template<bool> struct B {
    typedef int type;
  };
  template<typename T> typename B<A{}>::type f() { return false; }


4/2/17   [EDGcpfe/18047,EDGcpfe/18159]
Incorrect symbol variant used for static data member declarations

A change made in version 4.13 could cause an incorrect symbol variant
to be used in certain error cases.  This could result in an abort
(in reconcile_template_param_lists).  Now fixed.

  template<class T> struct A { static int const i = 1; };
  template<class T> int const A<T>::i;
  // Invalid redefinitions:
  template<class T> struct A { static int const i = 1; };
  template<class T> int const A<T>::i;


3/31/17  [EDGcpfe/18156]
Exponential-time deduction situations

The C++11 SFINAE rules may require the recursive partial instantiation of
function templates.  The front end detects when this recursion exceeds a limit,
but previously such a situation just caused it to discard a candidate at the
level at which the recursion exceeded the limit.  It then proceeded trying the
next candidate at that level.  Since every recursion level can contain more
than one candidate, this process could potentially result in an exponential
time process.  For example:

  template<typename T> auto split(T p) -> decltype(start(p));
  template<typename T> auto split(T &p) -> decltype(start(p));
  template<typename T> auto start(T p) -> decltype(split(p));
  struct X {} x;
  int r = start(x);

Here, a call of "start" considered two candidates for "split" during the
deduction process for "start".  Each of those candidates recursively triggered
a new deduction for "start", and the next level now had double the number of
candidates to consider.  This process continued creating a binary tree of a
depth determined by the recursion limit, but the total number of examined tree
nodes was an exponential function of that depth, causing the front end to
seemingly be stuck in an unbounded loop.  Now, when the first branch of the
tree is trimmed to the recursion limit, the complete deduction process is
abandoned and an error message is issued indicating the problem.


3/31/17  [EDGcpfe/18136]
Internal error in prep_generic_operand_full with variadic templates and SFINAE

In somewhat complicated situations involving SFINAE tests performed on calls
that involve variadic template expansions, the front end sometimes aborted with
an internal error in prep_generic_operand_full.  This problem is now fixed.


3/23/17  [EDGcpfe/18144]
Microsoft compatibility: lookup in variadic function templates

Our implementation of variadic templates requires that a prototype
instantiation be done on variadic functions and function templates.
The emulation of what we call "Microsoft nonreal base class lookup"
had been suppressed for variadic templates.  That emulation is now
enabled for variadic templates (allowing the example below to be
accepted).

  template<typename... Ts> struct A : Ts...  {
    template <typename T, typename... U> void f(int i) { }
  };
  template<typename ... Ts> struct B : A<Ts...> {
    virtual void g() {
      f<Ts...>(1);  // should be "this->template f<Ts...>(1)"
    }
  };
  class C {};
  B<C> b;


3/23/17  [EDGcpfe/9829,EDGcpfe/18126]
Incorrect cleanup during a throw after initialization of static aggregate

In some cases where a static aggregate that involves partial aggregate
initialization is present, subsequent destructible entities had caused an
incorrect cleanup sequence to be generated by lowering, potentially destroying
some objects multiple times.  For example (with --g++):

  extern "C" int printf(const char *,...);
  struct A {
    A() { printf("A::A()\n"); }
    ~A() { printf("A::~A()\n"); }
  };
  struct B {
    B(A) { printf("B::B(A)\n"); }
    ~B() { printf("B::~B()\n"); }
  };
  template<int I> struct C {
    C(int x) { printf("C::C(%d)\n", x); if (x) throw 0; }
    static C *sdm;
  };
  template<int I> C<I> *C<I>::sdm = new C(I);
  B ba[1] = {B(A())};     // inadvertently destroyed on terminate
  C<0> *p1 = C<0>::sdm;
  C<1> *p2 = C<1>::sdm;   // throws
  int main() {
    return 0;
  }

In the example above, ba[0] had been inadvertently destroyed (in this example
ba is completely constructed and therefore should not be destroyed because
std::exit is not called).


3/22/17  [EDGcpfe/18114]
GNU C++ compatibility: friend function template injection and parsing

Version 4.13 was changed to no longer inject friend function template names
in g++ mode (see EDGcpfe/18023).  However, while g++ does not inject function
template names in a way that necessarily allows them to be called, it appears
that they still make the name visible for lookup purposes, and in particular
the name is recognized as a template name for parsing purposes.  We now
emulate this behavior in g++ mode when gnu_version >= 50000.

  class A {
    template <typename> friend void f(A *);
    template <typename> friend void g(void *);
  };
  void g(A *a, void* v) {
    f<int>(a);  // now accepted (again)
    g<int>(v);  // now parses, but function not visible to ADL
  }



3/21/17  [EDGcpfe/18135]
Memory corruption on interpreting some derived-to-base conversions

The constexpr interpreter sometimes corrupted its own stack when evaluating a
derived-to-base conversion applied to a run-time address.  For example:

  struct B1 {};
  struct B2 {};
  struct D: B2, B1 {
     constexpr D(D const &src): B2(src) {}  // This corrupted memory, likely
     constexpr explicit D(int) {}           // leading to an abort.
  };
  int main() {
    D d(42);
    D e = d;  // Address of d is passed as a "run-time" address.
  }

This is now fixed.


3/21/17  [EDGcpfe/18133]
Microsoft-mode abort on cast of xvalue to lvalue reference

In Microsoft mode, the front end sometimes aborted with an internal error in
conv_class_prvalue_operand_to_lvalue when processing a cast of an xvalue to an
lvalue reference type.  For example:

  struct S {};
  S&& f();
  S &s = static_cast<S&>(f());  // Previously aborted in Microsoft mode.
                                // Now okay.

This regression introduced by the changes for EDGcpfe/12021 (version 4.8) is
now fixed.


3/19/17  [EDGcpfe/18132]
Spurious error on some calls to constexpr functions in templates

In some relatively complex situations, the front end produced a spurious
"expression must have a constant value" calls appearing in templates.
For example:

  template<int... Ns> struct C;
  template<int N> struct C<N> { static constexpr int V = N; };
  template<int N, int... R> struct C<N, R...> { static constexpr int V = N; };
  template<typename T> struct X {
    constexpr operator int() { return sizeof(T); }
  };
  struct S {
    template<typename... Ts> void f() {
      static_assert(C<(int)X<Ts>()...>::value != 0, "");
    }
  };

Previously, an error was issued for the static_assert condition in this
example.  Now it is accepted.


3/19/17  [EDGcpfe/18120]
Abort when rescanning array new-expression in return type

In some complex cases, rescanning a function template declaration with a
return type containing a array new expression could result in an internal
error in get_expr_rescan_info ("missing default rescan info").  This is now
fixed.


3/19/17  [EDGcpfe/18119]
Incorrect partial ordering in some cases involving pack expansions

A change made in 4.13 (see EDGcpfe/17184) could result in incorrect
partial ordering in some cases involving pack expansions.  Now fixed.


3/17/17  [EDGcpfe/18091]
Comparing string literal address in Microsoft mode

The front end usually represents identical string literals within a
translation unit as sharing storage.  One exception is Microsoft mode.
Now, Microsoft C++ mode (but not C mode) with microsoft_version >= 1910
also represents string literals as sharing storage.  For example:

  static_assert("a" == "a", "");  // Now accepted in some
                                  // Microsoft C++ modes.
  

3/16/17  [EDGcpfe/18068]
Spurious constexpr initialization error with class type subobject

In some cases, the front end failed to evaluate a constexpr constructor
claiming an uninitialized class type subobject.  For example:

  struct A {
    constexpr A(int i = 0) : i(i) {}
    int i;
  };
  struct B {
    constexpr B(A a = A{}) : a(a) {}
    A a;
  };
  struct C {
    constexpr C() {}
    B b;
  };
  C constexpr c;  // Previously an error in some configurations.  Now okay.

In C++11 mode (but not C++14 mode), this was a regression introduced by
version 4.13 of the front end.  Now fixed.


3/15/17  [EDGcpfe/18099,EDGcpfe/18112]
Representation of constant-folded call returning a reference

In some cases, the result of a call returning a reference was reduced to just
an enk_variable node.  Doing so lost information about the call and could lead
the C++-generating back end to produce incorrect code.  For example:

  constexpr int&& m(int &x) { return static_cast<int&&>(x); }
  int x = 42;
  int &&rr = m(x);  // Previously incorrectly rendered by the C++-generating
                    // back end as "int &&rr = (x);"

This regression, introduced by version 4.13, is now fixed.


3/15/17  [EDGcpfe/18110]
Constant-folding and pointers to weak variables/functions

In GNU C++11 mode, the front end previously folded a comparison of a pointer-
to-function value with a null pointer value even when the function pointed to
is declared to be "weak" (in GNU mode).  For example:

  static int w() __attribute((weakref("wf")));
  bool g() {
    static void *const ptr = (void*)&w;
    return ptr != 0;  // Previously folded to "return 1;".
  }

This was incorrect since the address of a weak function (or variable) may be
null.  This is now fixed.


3/15/17  [EDGcpfe/17665]
Microsoft compatibility: this->enumerator

In Microsoft mode, accessing an enumerator constant e with the form "this->e"
is now treated as a valid constant-expression.  For example:

  struct S {
    enum { e = 42 };
    void f() {
      static_assert(this->e, "");  // Now accepted in Microsoft mode.
    }
  };


3/15/17  [EDGcpfe/18105]
Assertion failure in attach_tag_attributes

The changes for EDGcpfe/17548 (in 4.13) caused an assertion failure
(in attach_tag_attributes) when parsing a qualified redeclaration that
included attributes (or alignas).  The failure is only seen in configurations
where GENERATE_SOURCE_SEQUENCE_LISTS is TRUE.  For example, with --c++11:

  struct alignas(int) S2 {};
  struct alignas(int) ::S2;


3/15/17  [EDGcpfe/17514]
Dependent static_assert conditions

The front end previously incorrectly handled certain dependent static_assert
conditions.  For example:

  template<typename T> void g() {
    constexpr T cond;
    static_assert(static_cast<bool>(cond), "Unexpected");
  }

Previously the front end issued an error claiming the static_assert condition
is not constant.  This is now fixed.


3/14/17  [EDGcpfe/18029]
C++-generating back end: qualified field names in member access expressions

The C++-generating back end previously used a qualified field name in a
member access expression when the field is a member of a base class of the
class of the object expression.  Recent versions of g++ give an error when
compiling the generated code, so member access expressions are now put out
using a qualified name only if the field is hidden by a name in an
intermediate base class.  For example:

  struct A {
    struct B {};
    B m1[1];
    B m2;
  };

  template <typename> struct C : A {
    void m_fn1() {
      &m2 != m1;  // Previously generated as &(A::m2) != A::m1
    }
  };


3/14/17  [EDGcpfe/18104]
C-mode difference between string offsets

Prior to version 4.13, the front end accept the following case in C mode:

	int d = &"string"[1] - &"string"[0];

4.13 no longer considered the result of the subtraction a constant making that
initializer invalid in C mode.  (The standard leaves unspecified whether the
two "string" literals denote the same object, and therefore whether the
subtraction is valid.)  Now, the case is accepted again, fixing what is
arguably a regression introduced by version 4.13.


3/10/17  [EDGcpfe/18096]
Incorrect end_position with builtin functions

The changes for builtin functions (in 4.12) introduced the possibility that
curr_construct_end_position could be overwritten during the processing of
a builtin function (in configurations where EXTRA_SOURCE_POSITIONS_IN_IL is
TRUE).  In the example below (with --gcc), the end_position of the "if"
statement was incorrect.  Now fixed.

  typedef __builtin_va_list __gnuc_va_list;
  typedef __gnuc_va_list va_list;
  void f(va_list ap) {
    if (0) { }
    __builtin_va_end(ap);
  }


3/9/17   [EDGcpfe/18093]
Type keywords as vacuous destructor names disallowed in most modes

The front end allowed a type keyword to be used in a vacuous destructor
call, except in strict mode.  This usage is now allowed only in Sun
mode, cfront mode, and g++ mode when gnu_version <= 30300.

  void f(int *p) {
    p->~int();
  }


3/9/17   [EDGcpfe/17991]
Diagnose non-scalar type used in vacuous destructor call

The front end failed to diagnose a vacuous (a.k.a., pseudo) destructor
call in which the object expression was a non-scalar type.  Now fixed.
This is still silently accepted in permissive Microsoft mode.

  typedef void V;
  void f(V *p) {
    p->~V();
  }


3/9/17   [EDGcpfe/17987]
Incorrect IL flag for nested class of class template instantiation

The flag nested_class_defined_outside_of_parent was sometimes incorrectly set
to TRUE for nested classes of class template instantiations.  This is now
fixed.  (See also EDGcpfe/11936, which addresses a similar issue for nested
class templates.)


3/9/17   [EDGcpfe/18061]
Spurious excessive interpreter memory use for zero-length types

The front end sometimes attempted to allocate very large blocks of memory to
represent values of zero-length types in the interpreter (possible in GNU C
mode).  This attempt could fail on some platforms, resulting in a spurious
"out of memory" error.  This regression introduced in version 4.13 is now
fixed.


3/9/17   [EDGcpfe/18070]
Spurious constexpr failure when adding/subtracting zero from null pointer

The constexpr interpreter previously treated adding or subtracting zero from a
null pointer as an evaluation failure, which in turn could lead to spurious
errors.  For example:

  constexpr int* f() { return nullptr; }
  constexpr int* g() { return f()+0; }
  constexpr int* r = g();  // Previously an error.  Now okay.

In C++11 mode, this is a regression introduced by version 4.13.  This is now
fixed.


3/9/17   [EDGcpfe/18053]
Spurious error on constructor inheriting from constexpr base constructor

Consider:

  template<typename T> struct B {
    constexpr B(T) {}  // (1)
  };
  template<typename T> struct D: B<T> {
    using B<T>::B;  // (2)
  };
  struct N { N(); } n;  // Nonliteral type.
  D<N> d(n);  // Previously triggered an error.  Now okay.

The inheriting constructor (2) "acquires" the constexpr specifier from the
base constructor B, but when instantiating these constructors for T = N the
resulting parameter lists do not satisfy the requirement that the parameter
types be literal types.  This should not be an error for parameter lists that
are the result of template instantiation (as is the case here), but the front
end previously failed to make that allowance for inheriting constructors and
an error was issued as a consequence of that.  This is now fixed.


3/9/17   [EDGcpfe/17828]
C++-generating back end: dependent expression values for enumerators

In configurations in which template definitions are generated from
prototype instantiations, the C++-generating back end previously sometimes
omitted the expression value for an enumerator for certain complex
expressions involving template parameters.  This is now fixed.  For
example, with --c++11:

  template <int R, int... E> struct S;

  template <int R, int... Tail> struct S<R, 0, Tail...> : S<R+1> {
    enum : int { X = 1 + S<R+1>::X }; // Previously "{ X }" with no expression
  };



3/8/17   [EDGcpfe/18065]
GNU C++14-mode abort on member variable template

The changes for EDGcpfe/18004 introduced a bug causing the front end to abort
(in ensure_inclass_static_member_constant_initializer_is_scanned, class_decl.c)
with an internal error in GNU C++14 mode when an expression refers to a member
variable template.  For example:

  struct S {
    template<typename T> static typename T::type vt;
  };
  struct X {
    using type = int;
  };
  int *p = &S::vt<X>;  // Previously triggered an internal error in
                       // GNU C++14 mode.

This regression introduced in version 4.13 is now fixed.


3/8/17   [EDGcpfe/18080]
Microsoft compatibility: error during disambiguation in Microsoft mode

A spurious missing template argument list error could be issued during
disambiguation in Microsoft mode.  Now fixed.

  template <class T> struct A {};
  int f(int i) { return 0; }
  int main() {
    int i = 1;
    int A(f(i));  // spurious 'argument list for ... "A" is missing'
    return A;
  }


3/8/17   [EDGcpfe/18048]
noexcept and constant-expressions

The C++11 standard specifies that "noexcept(<expr>)" is true if <expr> is a
"core constant expression".  Previously, the front end only applied this rule
to a subset of core constant expressions that are also "constant expressions".
In particular, this excluded calls to constexpr functions that attempt to
return the address of a local variable.  For example:

  constexpr int const* f(int const *p) { return p; }
  int main() {
    constexpr int i = 42;
    static_assert(noexcept(f(&i)), "Unexpected!");  // Previously an error.
  }                                                 // Now accepted.

Here "f(&i)" is a "core constant expression" but not a "constant expression".
Previously, the noexcept operator produced "false" for this case (leading to
an error).  Now, it produces "true" and the case is accepted.


3/8/17   [EDGcpfe/18033]
Internal error on constexpr notes when creating raw listing file

An internal error could occur (in write_diag_to_raw_listing) when a
constexpr "note" message is issued when a raw listing file is being
generated.  Now fixed.  This example would result in an internal error
when compiled with the --list option.

  constexpr int f() {
    return *(new int);
  }
  int main() {
    constexpr int i = f();
  }


3/7/17   [EDGcpfe/18039]
C++-generating back end: accessible alias template specializations

As described in the change for EDGcpfe/11015, when the IL uses a type that
is inaccessible in the current context, the C++-generating back end attempts
to substitute an accessible typedef naming that type in the generated code.
This mechanism did not previously consider instances of alias templates as
potential substitutes, leading to some cases of an inaccessible type
erroneously appearing in the generated code.  This has now been fixed.  For
example, with --c++14:

  namespace Ns {
  template <int i, typename T> struct C {
  protected:
    template <int j, typename T1> struct B {
      static const T1 value = i + j;
    };
    template <int j> struct D: public B<j, int> { };
  };

  template <int i, typename T> struct E: private C<i, T> {
    template <long v> struct S: public C<i, T>::template D<v> {
    };
  };
  }

  template <long v> using S = Ns::E<1, int>::S<v>;

  void m(int i) {
     m(S<1>::value);  // Previously generated as
                      // Ns::C<1, int>::B<1, int>::value, which is invalid
  }


3/7/17   [EDGcpfe/18077]
Unbounded loop on prefix enable_if attribute

The changes for EDGcpfe/17738 (the Clang enable_if attribute) contained a bug
causing the front end to enter a non-terminating loop when the enable_if
attribute appeared as a prefix to a declaration along with other prefix
attributes.  For example:

  __attribute((deprecated)) __attribute((enable_if(true, ""))) void f() {}
    // Triggered an unbounded loop in Clang C++11 mode.

This is now fixed.

  
3/7/17   [EDGcpfe/18045]
Spurious "access to uninitialized object" evaluation failure

The constexpr interpreter previously did not correctly handle certain
constructor calls when the is_copy_constructor_with_implied_source flag in the
corresponding dynamic initializer entry was set to TRUE.  In contexts where a
constant-expression is required this manifested itself in version 4.13 with a
note reporting "access to uninitialized object" (prior versions of the front
end also failed these constexpr evaluations, although the note was not always
emitted).  This is now fixed.


3/7/17   [EDGcpfe/18081]
Invalid IL tree generated when IA64_ABI_USE_GUARD_ACQUIRE_RELEASE is TRUE

The changes for EDGcpfe/17482 (in 4.13) inadvertently caused the same
expression to be used in calls to __cxa_guard_acquire and __cxa_guard_release,
causing an inconsistent IL tree.  This issue only affects IA-64 configurations
where IA64_ABI_USE_GUARD_ACQUIRE_RELEASE is TRUE.


3/6/17   [EDGcpfe/18075]
Unintended mangling of IA-64 names in some cases

The changes (introduced in 4.13) for EDGcpfe/17873, which were intended to
increase performance during IA-64 name mangling, introduced a subtle bug that
caused a mangled and unmangled name to be used for the same lowered class.
Those changes have now been backed out.  For example:

  struct B {
    virtual void f();
  };
  void B::f() {}
  #if USED_IN_BASE_CLASS
  struct D : B {
    virtual void f();
  };
  #endif

In the example above, using "B" as a base class caused it to be given a mangled
name (whereas it would not have a mangled name in another translation unit
where it was not used as a base class).


3/5/17   [EDGcpfe/18062]
Function signatures for prototyped runtime routines

The changes for EDGcpfe/17482 (in 4.13) added prototypes for all library
routines, but in some cases library routines that have no parameters were
mistakenly given a "void" parameter; that has now been fixed.  Note that
routines declared with "(void)" and "()" are both represented in the IL as
having no parameters (and this change matches that).


3/2/17   [EDGcpfe/18057]
Some struct types inadvertently pre-lowered in gcc mode

Due to the changes for EDGcpfe/17888 (in 4.13), in gcc mode a struct type could
be "prelowered" (and have its name mangled) if it is used as the type of a
variable with designated initializers. These operations should only be
performed in C++ mode.  Now fixed.  For example (with --gcc):

  struct A {
    int i;
  } a[1] = { [0] = { 0 } };


2/28/17  [EDGcpfe/18052]
Spurious error on dependent unary operators in constant operand contexts

The front end sometimes produced a spurious error on certain unary operators
with template-dependent operands in contexts requiring a constant-expression.
(The spurious diagnostic suggested the result is not constant.)  For example:

  template<typename T> constexpr bool x = T();
  template<typename T> struct Y {
    static constexpr bool v = !x<T>;  // Previously triggered a spurious error.
  };

This is now fixed.


2/24/17  [EDGcpfe/17935]
Microsoft compatibility: hexadecimal literals and preprocessing numbers

According to the C++ Standard, a construct like 0xE+0x1 is a single
preprocessing number that is ill-formed (i.e., requires an error diagnostic)
because it cannot be converted to a numeric literal.  MSVC accepts such
constructs, however, treating the "+" character as terminating the
hexadecimal literal 0xE.  The front end has now been changed to do the same
in Microsoft mode.  For example, with --microsoft:

  int i = 0xE+0x1;   // Now equivalent to 15 (0xE + 0x1) in Microsoft mode


2/23/17  [EDGcpfe/18043]
C-generating back end: taking the address of a non-lvalue

In similar circumstances to the issue addressed by EDGcpfe/17944, the
C-generating back end put out incorrect C code that attempted to take the
address of a non-lvalue expression.  This additional case is now fixed.


2/23/17  [EDGcpfe/17925]
Microsoft compatibility: incorrect substitution of namespace member call

In Microsoft mode, substitution of a dependent call in a decltype expression
could produce an incorrect result if the global scope contained a function
template with the same name.  Now fixed.

  template<typename T> void f();
  namespace N { template<typename T> int f(); }
  template<typename T> decltype(N::f<T>()) g();
  int i = g<int>();


2/23/17  [EDGcpfe/17929]
Lookup in class member alias template instantiations

Name lookup in the instantiation of an class member alias template formerly
found names declared later in the class, which could result in spurious
errors or incorrect behavior.  Now fixed.

  template<typename _Tp> struct A {
    static constexpr int j = 1;
  };
  template <typename T> using B = A<int>;
  struct C {
    template <typename Arg> using D = B<Arg>;  // formerly found C::B
    using B = A<int>;
    static constexpr int i = D<int>::j;
  };


2/22/17  [EDGcpfe/18027]
Standard C strlen, abs, and constexpr evaluation

In GNU C++ modes, a declaration of strlen or abs matching the standard
library specification can be called in constant-expression contexts.
Furthermore, the corresponding built-in functions __builtin_strlen and
__builtin_abs can now also be called in constant-expression contexts.


2/22/17  [EDGcpfe/18037]
Designators and constexpr initializers

The changes for EDGcpfe/17888 accidentally broke support for designated
initializers in constexpr initializers (see the entry of 5/19/16 for
EDGcpfe/16807).  This regression introduced in version 4.13 is now fixed.


-------------------------------------------------------------------------------
Version 4.13, February 22, 2017

2/17/17  [EDGcpfe/17800]
Microsoft compatibility: coclass and no_injected_text Microsoft attributes

The "coclass" Microsoft attribute is attached to a class or struct and
creates a COM object.  Visual Studio accomplishes this by "injecting"
various base classes and member functions.  The front end now adds
ATL::CComCoClass<class_type, &__uuidof(class_type)> as a direct base class
to any class type that is annotated with this attribute.  Note that this
is only a small part of the injected code that Visual Studio generates.

Also, the "no_injected_text" attribute now controls whether or not the
front end injects code (i.e., adding the base class described above).


2/16/17  [EDGcpfe/17694]
C++17 compatibility: hexadecimal floating-point literals

Hexadecimal floating-point literals (as described by C++ Committee
document P0245R1) are now supported by the front end in C++17 mode.  For
example, with --c++17:

  double f = 0xC.68p+2;


2/16/17  [EDGcpfe/17686]
C++17 compatibility: __has_include

The C++17 __has_include operator (as described by C++ Committee document
P0061R1) has been implemented.  The draft C++17 Standard requires that this
operator appear only in the constant-expression of a #if statement; this
restriction is enforced in strict C++17 mode, but in all other aspects the
processing is identical to the clang and SG10 version of the operator as
described in the change for EDGcpfe/14634.


2/16/17  [EDGcpfe/18004]
Spurious error on use of array constant in GNU C++ mode

Consider the following example:

  template<typename> struct S {
    static constexpr int cs[] = { 1, 2, 3 };
  };
  constexpr int x = S<int>::cs[1];  // Previously an error in GNU C++11 mode.

Previously, the front end issued a spurious error on the use of cs[1] in
GNU C++11 mode.  This is now fixed.


2/16/17  [EDGcpfe/18025]
C++-generating back end: qualified names for anonymous union members in
decltype

The C++-generating back end generated incorrect code for the name of a
member of an anonymous union member of a class when the member name is
used without an object expression as the operand of a decltype operator.
Such a use requires a qualified name, and the name reference was put out
without the qualifier.  This is now fixed.  For example:

  struct S {
     union { int x, y; };
  };
  decltype(S::x) a;  // Previously generated as "decltype(x)"


2/16/17  [EDGcpfe/18013]
Microsoft-mode abort on friend function template in secondary translation unit

In Microsoft C++ mode, the front end sometimes aborted (with an internal error
in trans_unit_for_source_corresp) when processing a friend function template
during a "nonreal" class template instantiation (a kind of instantiation done
only in some Microsoft modes).  For example:

  // file1.cpp:
  /* Empty. */

  // file2.cpp:
  template<typename T, T> struct X {
    template<typename> friend int f(int, X);
  };
  template<int N> struct Y: X<int, N> {};

In Microsoft modes, X<int, N> was instantiated for the nonreal argument N, and
the declaration of the friend template during that instantiation produced an
abort.  That is now fixed.


2/16/17  [EDGcpfe/18023]
GNU/Clang compatibility: Injection of friend function templates

The entry of 9/9/11 for EDGcpfe/12130 describes how GCC injects friend function
template names in the surrounding scope (nonstandard behavior).  Newer versions
of GCC no longer do this and the front end now matches GCC by disabling that
injection when gnu_version >= 50000.  The front end previously also enabled the
injection in Clang mode (accidentally) and that is now also fixed.  For
example:

  class C {
    template<typename T> friend void f(T) {}
  };
  int main() {
    f(1);  // Now an error in GNU C++ modes with gnu_version >= 50000 and
  }        // in all Clang C++ modes.


2/15/17  [EDGcpfe/17988]
C++-generating back end: format of user-defined literal-operator-ids

When generating code for g++ and clang target compilers, the C++-generating
back end previously put out user-defined literal-operator-ids using the
format with a space between the "" and the suffix identifier. As a result,
a literal-operator-id like ""if was put out as "" if, which is a syntax
error. The C++-generating back end has now been changed to use this format
only when actually required by the target compilers: only in C++11 mode
and, for g++, only for versions prior to 4.8. In all other cases, the
format without the space is used. For example:

  long double operator""if(long double);  // previously put out as "" if
                                          // for all gnu and clang targets


2/15/17  [EDGcpfe/18020]
Internal error on invalid variable template declaration

An internal error could occur (in variable_template_declaration) on an
invalid variable template declaration that finds a prior declaration of
a non-template variable.  Now fixed.

  namespace A { int i = 1; }
  template <class T> A :: i { } ;


2/14/17  [EDGcpfe/18003]
Defaulted default constructor and constexpr

A defaulted default constructor was sometimes not treated as a constexpr
constructor when it should have been.  For example:

  struct S {
    S() = default;  // Previously not implicitly "constexpr".
    virtual void f() {}
  };
  constexpr S s{};  // Previously an error.  Now okay.

This is now fixed.


2/13/17  [EDGcpfe/17803]
Warnings when building with Microsoft Visual C++

A number of warnings emitted by the Microsoft Visual C++ compiler when building
the front end (with option -W3) have been addressed.


2/13/17  [EDGcpfe/15944,EDGcpfe/16165]
NULL pointer dereference in add_mv_distinction

In some configurations (C++-generating back ends that do mangling), having
two function definitions with the same "target" attribute had resulted in
dereferencing a NULL pointer (in add_mv_distinction).  Now fixed.  For example
(with --gnu_version 40800):

  void __attribute((target("sse"))) f() {}
  void __attribute((target("sse"))) f() {}


2/13/17  [EDGcpfe/17738]
Clang compatibility: enable_if attribute

Preliminary support has been added for the enable_if attribute in Clang C++
mode.  For example (in Clang C++11 mode):

  void f() __attribute((enable_if(true, ""))) {}
  void f() = delete;
  int main() {
    f();  // Now accepted in Clang C++11 mode.
  }

Note that the attribute permits overloading functions that would otherwise not
be distinguishable and that, all other things being equal, the presence of an
enable_if attribute in a viable candidate makes the candidate preferable over
one without the attribute.

A few caveats:
  - The string literal recorded in the attribute is currently not used in
    call failure diagnostics.
  - If the condition in the attribute depends on parameters, any attempt to
    call the function or an overload set containing the function results in
    an error.
Despite these limitations, this support is sufficient to handle the uses of
this attribute in current standard header files shipped with Clang.


2/13/17  [EDGcpfe/17184]
C++-generating back end: incorrect pack expansions

Incorrect output could be created by the C++-generating back end in some
cases involving alias template instantiations.  In the example below,
the "X<U>::x" was incorrectly emitted as "B<T>::x", but is now emitted
as "B<T...>::x".

  template <int> struct A;
  template <typename> struct B;
  template <typename... T> class C {
    template <typename> using X = B<T...>;
    template <typename U, typename A<X<U>::x>::t> C();
  };


2/12/17   [EDGcpfe/16042,EDGcpfe/17978]
Assertion failure in mangled_template_arguments_or_parameter_pack

In configurations that use mangling, but not lowering, an assertion failure
(in mangled_template_arguments_or_parameter_pack) could occur while mangling
certain nonreal types that are created during the substitution and deduction
process.  Those top-level types are now ignored during mangling.  For example
(with --c++11):

  template <class T> struct A { typedef T type; };
  template <template <class...> class T, class... U>
  void f(typename T<U...>::type);
  int main() {
    f<A,int>(42);
  }


2/12/17  [EDGcpfe/17299]
Less stack usage during IL walks

The primary routine used to perform IL walks (i.e., WALK_ENTRY_ROUTINE_NAME
whose name is a macro set to various function names as needed) has been
updated to use fewer local variables, thereby potentially decreasing the
stack usage on each invocation.  That should decrease the likelihood of a
stack overflow on deeply nested constructs.  Note that the effectiveness of
this optimization depends on how well the compiler that is used to compile
the code detects and eliminates local variables that are not in range (and
may not result in any savings in some cases).


2/10/17  [EDGcpfe/18009]
Memory corruption and possible aborts in C++/CLI mode

In unpredictable circumstances, a C++/CLI compilation could abort or have
other incorrect behavior due to use of an uninitialized variable while
reading metadata.  This is now fixed.


2/7/17   [EDGcpfe/17710]
Address constants pointing into unions

The constexpr interpreter previously could not consume address constants
pointing into unions because the IL representation of such constant was
potentially ambiguous: Two identical constants could be produced by taking
the address of different field components of the union.  The representation
of address constants has now been extended with a "subobject path" that
records which specific subobjects are selected by the address.  The
interpreter's restriction has been lifted by using this new information.


2/7/17   [EDGcpfe/17990]
Assertion failure in insert_code_to_indicate_cleanup_state

The changes for EDGcpfe/17148 (in version 4.12) caused an assertion failure (in
insert_code_to_indicate_cleanup_state) for any code that used a function
try block in configurations that use lowering but have
INDICATE_CLEANUP_STATE_IN_UNREACHABLE_CODE set to TRUE.  That has now been
fixed.  For example:

  void f() try {
  } catch (...) {
  }


2/3/17   [EDGcpfe/17473,EDGcpfe/17961]
Function with deduced return type as template static data member initializer

An internal error (in force_instantiation_to_deduce_return_type) could
result if a static member function with a deduced return type was used
in a way that required the return type to be determined, and that use was
in a context that was part of the "normal" parsing of the class template
(i.e., not one of the contexts in which parsing is done once the class
definition is complete).  This usage is not allowed in normal (non-template)
classes and the validity in class templates is unclear.  The front end now
accepts this usage pending possible clarification by the standards committee.

  template <class ...> struct A {
    static auto f() {}
    static constexpr auto I = f;
  };
  auto g () -> A<>;
  int main() {
    g();
  }


2/3/17   [EDGcpfe/17888]
Unification of constexpr evaluation

The implementation of C++11 constexpr evaluation significantly extended the
existing infrastructure for folding constant-expressions in the front end.
That approach was impractical to implement to the new capabilities added by
C++14, which prompted the addition of an IL interpreter to the front end.
However, that interpreter was originally only used to evaluate calls to
constexpr functions and constructors in C++14 mode.  The interpreter has now
been extensively reworked to be usable for, potentially, all constant-
expression evaluations.  In particular, it is now used for constexpr calls
in both C++11 and C++14 modes, as well as several other contexts that expect
constant expressions.  Although the traditional folding code is also still
used in various places, the extensions supporting C++11 constexpr evaluation
(a significant amount of the code in folding.c) have been removed.


2/2/17   [EDGcpfe/17983]
Inlining of nested "if" statements had caused aborts

Inlining nested "if" statements where the "then" branch of the inner "if"
statement has no effect had caused an abort (in insert_statement_full or
expand_statement_inline).  Only occurs in some C modes.  For example
(with --gcc):

  inline int f(void) {
    if (1) if (0);
  }
  void g(void) {
    f();
  }


2/2/17   [EDGcpfe/17980]
Internal error on use of ambiguous inline namespace

An internal error could occur (in add_symbol_to_lookup_set) if a global
scope qualifier was ambiguous as a result of finding a namespace directly
in the global scope and also one made visible via an inline namespace.
Now fixed.

  inline namespace N1 { namespace N2 { void f(){} } }
  namespace N2 { void f(){} }
  int main() { ::N2::f(); }


2/2/17   [EDGcpfe/17982]
Microsoft compatibility: auto variable templates not accepted

In modes in which nonclass prototype instantiations are not done (e.g.,
Microsoft mode) a spurious error was issued on a variable template
declaration with an auto type.  This was followed by an internal error
(in check_use_of_auto_type).  Now fixed.

  template <class T> auto X = T();


1/31/17  [EDGcpfe/17953]
Return value optimization and returning braced initializers

The front end previously failed to disable the return value optimization if
a potentially optimizable return statement is followed by a return statement
with a braced initializer.  For example:

  #include <initializer_list>
  struct S {
    S() {}
    S(std::initializer_list<int>) {}
    ~S() {}
  };
  S f(bool b) {
    S s;
    if (b) {
      return s;
    } else {
      return { 42 };  // Should disable the return value optimization.
    }
  }

Previously, function f was incorrectly marked as being subject to the return
value optimization (i.e., s was constructed directly in the return value
storage), even though that would produce incorrect results if the "else"
branch of the "if" statement is followed.  That is now fixed.


1/31/17  [EDGcpfe/17934]
Failure to fold constexpr calls while matching template declarations

When matching template declarations it is sometimes necessary to evaluate calls
to constexpr functions in template arguments.  For example:

  template<typename,int> struct A;
  constexpr int z() { return 0; }
  template<typename T> struct A<T, 0> {
    A<T, 0>* f();
  };
  template<typename T> A<T, z()>* A<T,0>::f() {  // Previously an error.
    return 0;                                    // Now okay.
  }

Previously, the front end failed to fold the call to "z()" in the template
argument of the out-of-class member definition (treating it instead as a
template-dependent expression), which in turn resulted in a spurious
incompatibility error.  That is now fixed.


1/31/17  [EDGcpfe/17970]
Memory corruption with lambda in explicitly specialized static data member

When a lambda appears in the initializer for an explicitly-specialized static
data member, the front end modified data at a negative offset in the scope
stack (in make_closure_class).  For example:

  template<typename> struct X {
    static void (*fn_ptr)();
  };
  template<> void (*X<void>::ptr_fun)() = [](){};
     // Previously potentially corrupted memory.

This is now fixed.


1/31/17  [EDGcpfe/17798]
Microsoft compatibility: String literals in array of character initializers

The Microsoft extension that allows a character array to be initialized with
a braced list of character values and string values (see the entry of 7/9/14
for EDGcpfe/14985) is now disabled when permissive mode is disabled.


1/31/17  [EDGcpfe/17802]
Defaulted special members and constexpr

Defaulted special members may be implicitly constexpr.  However, the front end
sometimes failed to recognize this, leading to spurious errors.  For example:

  struct B {
    constexpr B() {}
    constexpr B(B const&) {}
  };
  struct D: B {
    constexpr D(): B() {}
    D(D const&) = default;  // Should be implicitly constexpr.
  };
  constexpr D d1, d2(d1);   // Previously an error.  Now okay.

This is now fixed.


1/30/17  [EDGcpfe/17155]
Internal error on "extern template" in class template

An internal error could occur (in push_template_instantiation_scope) if
an "extern template" directive appeared in a class template.  Now fixed.
Such a directive is not allowed in class scopes, but is permitted in
Microsoft mode.  The Microsoft mode emulation is now restricted to
microsoft_version < 1600.

  template <typename> struct A {
    template <typename> class B;
    typedef B<char> B2;
    struct A {
      template<typename T > B<T>& f(B<T  >&);
      extern template B2& f(B2&);
    };
  };


1/29/17  [EDGcpfe/17958]
GNU C++ compatibility: abort substituting arguments into variadic template
template parameter

An abort could occur (in update_template_param_symbols) in g++ mode when
substituting template arguments into the argument list of a template
template parameter when the associated template template argument was
non-variadic.

  template <bool> struct A {
    typedef bool t;
  };
  template <template <typename ...> class TT>
      decltype(typename A<TT<int>::v>::t()) f();
  template <typename I> struct B {
    static constexpr bool v = 0;
  };
  int main() {
    f<B>();
  }


1/29/17  [EDGcpfe/17945]
Abort substituting pack into multiple template parameters

An abort could occur (in update_template_param_symbols) in some cases
where a pack expansion is being substituted into a template argument
list in cases where some elements correspond to non-pack parameters and
some correspond to a pack parameter.  The actual conditions needed to
reproduce this seem to be uncommon.  In this example, the problem
occurred during partial order checking of NC when substitution argument
values into B (via BT).  Now fixed.

  namespace std {
    template<class U> struct Z { typedef U TT; };
    template<class U> typename Z<U>::TT dv();
  }
  template <long...> struct Q {};
  template <class...> using void_t = void;
  template <class U, long I> struct A {
    typedef decltype (std::dv<U> () + std::dv<long> ()) TT;
    static constexpr TT g(U && u) { return u + I; }
  };
  template <class U, long I> using AT = typename A <U, I>::TT;
  template <class H, class... T> struct B {
    typedef H TT;
    static constexpr TT g(H && h, T &&...) { return h; }
  };
  template <class... U> using BT = typename B <U...>::TT;
  namespace N {
    template <class, class, class, class, class> struct NC {};
    template <class U, class V, long... I, long... J> struct NC
      < U, V, Q <I...>, Q <J...>,
        void_t < BT <AT <U, I>..., AT <V, J>...> >
      > {
          typedef BT <AT <U, I>..., AT <V, J>...> TT;
          static constexpr TT g(U && u, V && v) {
            return B <AT <U, I>..., AT <V, J>...>::g
              ( A <U, I>::g(u)..., A <V, J>::g(v)...);
          }
    };
  }
  template <class U, class V, class K, class L>
  struct C : N::NC <U, V, K, L, void> {};
  template <class U, class V, class K, class L>
  using CT = typename C <U, V, K, L>::TT;
  typedef C <int &, int &, Q <1,2>, Q <3,4,5>> F;
  int main() {
    int u = 1;
    int v = 2;
    F::TT r = F::g(u, v);
  }


1/26/17  [EDGcpfe/17963]
Incorrect matching of dependent decltype in partial specialization

In some cases a partial specialization that makes use of a dependent
decltype expression was incorrectly considered as a redeclaration of
a previous partial specialization, resulting in spurious errors or
incorrect behavior.  Now fixed.

  template <typename> struct A;
  template <typename T> using C = decltype(static_cast<A<T>>(nullptr));
  template <typename, typename> struct B;
  template <typename U> struct B<U, C<typename U::X>> {};
  // Formerly resulted in "... has already been defined" error
  template <typename V> struct B<V, C<typename V::Y>> {};


1/25/17  [EDGcpfe/17933]
Microsoft compatibility: spurious error on destructor call on built-in
type used as a class type

In C++/CLI a built-in type can be used as if it were a class time in some
cases.  This is done by replacing a type such as "int" with a C++/CLI
library class type such as "System::Int32".  An explicit destructor call
could fail if the object type had been converted to a class type, but the
destructor name was specified using the built-in type.  Now fixed.

  template<class T> struct A {
    T* arr;
    void f(int n) {
      arr[n].~T();
    }
  };
  int main() {
    A<int> ai;
    ai.f(1);
  }


1/24/17  [EDGcpfe/17409]
C++17 compatibility: "fallthrough" standard attribute

The C++17 "fallthrough" standard attribute (as described by P0188R1) has
been implemented and is now available in C++17 emulation mode as well as
when microsoft_version >= 1910.  Note that the front end doesn't currently
diagnose falling from one switch case to another, so the attribute doesn't
have any meaningful effect.


1/24/17  [EDGcpfe/17411]
C++17 compatibility: "maybe_unused" standard attribute

The C++17 "maybe_unused" standard attribute (as described by P0212R1) has
been implemented and is now available in C++17 emulation mode as well as
when microsoft_version >= 1910.


1/23/17  [EDGcpfe/17948]
Internal error on nonreal instance of variable template

An internal error could occur (in f_entity_can_be_instantiated) during
the end-of-scope symbol processing for a nonreal instantiation of a
variable template.  Now fixed.

  struct A {
    template <char ...c> static constexpr char const x [sizeof...(c)+1] = {0};
    template <char ...c> static constexpr char const *f() {
      return x<c...> ;
    }
  };
  template <char ...c> constexpr char const A::x[sizeof...(c)+1];
  int main() {
    A::f();
  }


1/20/17  [EDGcpfe/17410]
C++17 compatibility: "nodiscard" standard attribute

The C++17 "nodiscard" standard attribute (as described by P0189R1) has
been implemented and is now available in C++17 emulation mode as well as
when microsoft_version >= 1910.


1/18/17  [EDGcpfe/17730]
GNU compatibility: "used" attribute on static data member

Setting the GNU "used" attribute on a static data member had failed to
instantiate the static data member and is now fixed.  The example below
now prints "Initialized" (with --g++):

  extern "C" int printf(const char *,...);
  template<class T> class A {
    __attribute__((used)) static int sdm;
  };
  template<class T> int A<T>::sdm(printf("Initialized\n"));
  A<int> f;
  int main() {
    return 0;
  }


1/18/17  [EDGcpfe/17519]
Microsoft compatibility: comma suppression in macro argument

The Microsoft preprocessor suppresses a comma appearing in a macro argument
preceding an empty variadic macro expansion.  The front end now emulates
that behavior in Microsoft mode.  For example, with --microsoft:

  #define M(...) __VA_ARGS__
  #define X(...) __VA_ARGS__, b;
  #define Y(x,...) X(a, M(__VA_ARGS__))
  int Y(xyz)  // Previously expanded to "int a,, b;", now "int a, b;"


1/16/17  [EDGcpfe/17944]
C-generating back end: incorrect code with prvalue and xvalue class objects

In some cases involving prvalue or xvalue class objects, the C-generating
back end put out incorrect C code that attempted to take the address of a
non-lvalue expression.  This is now fixed.  For example:

  struct A {
    bool operator==(A);
  };
  struct B : A {};
  struct C { B b; };
  B f();
  C g();
  bool x = g().b == f();  // Previously an error in the generated code


1/11/17  [EDGcpfe/17928]
Assertion failure in edgcpdisp on certain decltype types

Due to memory region issues, certain decltype types that refer to entities
local to a function had caused an assertion failure ("scope for routine is
NULL") when using edgcpdisp to display the IL.  For example (with --c++11):

  template<typename T> void f(T x) {
    [](decltype(*x) e) { };
  }
  void print() {
    int i;
    f(&i);
  }


1/9/17   [EDGcpfe/17822]
Small IA-64 mangling performance gains

Some changes were made to speed up substitution processing in the mangling of
names in the IA-64 ABI.  These resulted in some small performance gains in
some cases.


1/6/17   [EDGcpfe/17921]
GNU compatibility: alignment of routines

Although non-standard, GNU allows applying an alignment directive to a
routine.  That code was inadvertently broken by the changes for EDGcpfe/16750
and has now been fixed (the attribute had been accepted but not actually
applied to the routine type).  For example (with --gnu_version 40800):

  void func(void) __attribute__((aligned(64)));
  void func(void) { }
  int main() {
    return (__alignof__(func) != 64);   // Now returns 0.
  }


1/5/17   [EDGcpfe/17915]
Suppress walk of entity pointer on pragmas

Previously the entity pointer of a pragma was traversed during a "needed" walk,
but that resulted in excessive execution times in some cases (e.g., when
checking pragmas are used).  The traversal turns out to be unnecessary (since
the entity will be found by other means) and has been removed.


1/4/17   [EDGcpfe/17910]
Assertion failure in find_linked_symbol on invalid code

An assertion failure in find_linked_symbol had occurred if a namespace and
a function definition were given the same name in an inline namespace.
Now fixed.  For example (with --c++14):

  inline namespace {
    namespace B {}
    void B() {}
  }


1/4/17   [EDGcpfe/17912]
Spurious substitution failure in C++14-mode call expression

Consider the following example:

  template<typename T> constexpr T f(T const &p) { return p; }
  template<int I> struct X {};
  template<int I> void f(X<f(I)>) {}
  void g(X<42> p) {
    f<42>(p);  // Previously a spurious error in C++14 mode.  Now okay.
  }

Previously, this was accepted in C++11 mode, but not in C++14 mode because the
front end failed to correctly substitute the explicit template argument 42 into
the call "f(I)".  This is now fixed.


1/3/17   [EDGcpfe/17898]
Abort after initializer folded despite an associated nontrivial destructor

In C++14 mode, the front end sometimes folded certain initializers too
aggressively (in the interpreter), ignoring the fact that a nontrivial
destructor would have to be called on the constant.  This could then result
in an abort in wrap_up_constant_full_expression.  For example:

  #include <initializer_list>
  struct A { virtual ~A() {} };
  A a;
  auto b = {a};  // Previously the initializer_list construction was
                 // folded too aggressively, resulting in an abort later on.

This is now fixed.


12/29/16 [EDGcpfe/17797]
Microsoft compatibility: Disallow constructor declaration using typedef except
in permissive mode

In Microsoft mode, a typedef to the current class name can be used to
declare a constructor.  This is now allowed only in Microsoft permissive mode.

  struct A {
    typedef A C;
    C() {}
  };


12/28/16 [EDGcpfe/17796]
Diagnostics for forward declarations of enums

Formerly, a forward declaration of an enum was silently allowed in non-strict
C++ mode.  This is now a discretionary error in all modes except for Microsoft
permissive mode (where it is silently accepted).  

  enum E;
  enum E2 *p;


12/23/16 [EDGcpfe/17880]
Invalid source position on namespace redeclaration error

An uninitialized value had been used as the source position for a diagnostic
on a redeclaration of an inline namespace (possibly resulting in an internal
error "write_orig_source_line: could not find line").  Now fixed.  For
example (with --c++17):

  namespace A {
    inline namespace B { }
  }
  namespace A::B { }


12/23/16 [EDGcpfe/17881,EDGcpfe/17879]
Ill-formed nested namespace declaration

An assertion failure ("pop_scope: curr_construct_pragmas != NULL") had been
given on certain ill-formed nested namespace declarations and now an error
is given.  For example (with --c++17):

  namespace A::B = A;


12/22/16 [EDGcpfe/17878]
GCC compatibility: Add builtins for GCC 6.3.0

The following functions have been added (when gnu_version >= 60300):
__builtin_ia32_lzcnt_u16, __builtin_ia32_lzcnt_u32, __builtin_ia32_lzcnt_u64,
__builtin_ia32_tzcnt_u16, __builtin_ia32_tzcnt_u32, __builtin_ia32_tzcnt_u64.
__builtin_ia32_pcommit has been deprecated (and is no longer recognized when
gnu_version >= 60300).


12/21/16 [EDGcpfe/17875]
Microsoft-mode abort on inherited nonreal member using-declaration

In some cases, a member using-declaration involving a nonreal template type
argument produced an internal error in Microsoft mode (in function
conflicts_with_previous_function_decl in class_decl.c) when another level of
derivation adds another using-declaration for the same name.  For example:

  template<typename> struct B {};
  template<typename T> struct C: B<T> {
    using B<X>::f;  // X is treated as a nonreal argument in Microsoft mode.
    template<typename> void f() {}
  };
  template<typename T> struct D: C<T> {
    using C<T>::f;  // Previously triggered an internal error.  Now okay.
  };

This is now fixed.


12/21/16 [EDGcpfe/17842]
constexpr member initializers referring to previously-initialized members

The front end issued a spurious diagnostic when a constexpr constructor
initializes one member using the value of a previously-initialized member.
This is now fixed.  For example, with --c++11:

  struct S {
    int a = 2;
    int b = a + 1;
    constexpr S() {}
  };
  constexpr S d; // Previously a spurious error


12/20/16 [EDGcpfe/17854]
Invalid constructor for lvalue-to-rvalue conversion in conditional expression

Consider the following code:

  struct B {
    B();
    B(B const&);
    B(B&&) = delete;
  };
  struct D: B {
    D(B const&);
  };
  D d{B()};
  D x = true ? B() : d;
    // Previously an error (move constructor is deleted).  Now okay.

In the conditional expression, the lvalue operand "d" must be converted to its
base and then to an rvalue (to match the other potential result of the
conditional expression).  Previously, the front end attempted to perform the
conversion to an rvalue using B's move constructor instead of its copy
constructor.  In this example, that produces an error because the move
constructor is deleted (in other cases, this could result in a silent call to
the wrong constructor).  That is now fixed.


12/20/16 [EDGcpfe/17873]
Performance improvement when mangling many base classes in IA-64 ABI

A change has been made to mangle and re-use the type of a base class when
creating a dummy name for a base class rather than regenerating a mangled
name each time it was required.  Only affects IA-64 ABI configurations.


12/20/16 [EDGcpfe/17872]
Lookup performance improvement in g++ mode

The front end does additional lookup processing in g++ mode to emulate
a nonstandard lookup that is done by g++.  This emulation could be very
expensive in programs with a large number of instantiated classes that
each have a large number of base classes.  The emulation has been improved
so that the extra processing is required in a much smaller number of cases.


12/20/16 [EDGcpfe/17856]
Positions in template instantiation tracebacks

The changes for EDGcpfe/17235 accidentally caused positions reported in
template instantiation tracebacks to be incorrect.  This is now fixed.


12/19/16 [EDGcpfe/17861]
--implicit_noexcept constraints

A command-line error is now issued if --implicit_noexcept is specified in a
mode that does not enable the noexcept specifier (previously the combination
was permitted, but it was likely to produce cryptic diagnostics).


12/19/16 [EDGcpfe/17830,EDGcpfe/17843]
GCC compatibility: Secondary declarations in C++ mode

For many builtin functions, GCC declares two symbols, one with the "__builtin_"
prefix and one (the "secondary") without.  Previously (since the changes for
EDGcpfe/16431) the front end had predeclared both sets of declarations, but
a change has been made to predeclare only the primary declaration in C++ modes.
The secondary declaration is still predeclared in C modes (where a
redeclaration will result in a warning).  The following example had given a
spurious error with --g++:

  struct _IO_FILE;
  typedef struct _IO_FILE FILE;
  extern int __fprintf_chk(FILE *, int, const char *, ...);


12/19/16 [EDGcpfe/17866]
Internal error due to wrong value category

In prototype instantiations the front end produces IL representing "generic
operations" on entities with dependent types, but with an lvalue array operand
that is dependent only due to the array length, a generic operation known to
require rvalue operands was sometimes left with an lvalue operand.  This could
subsequently trigger an internal error in the C++-generating back end.  For
example:

  template<unsigned N> struct S {
    char c[N];
    bool f(char const* ptr) const {
      return c <= ptr;  // The node for "ptr" was previously left as an
    }                   // lvalue; now it represents an rvalue.
  };

This is now fixed.


12/19/16 [EDGcpfe/17853]
Dependent exception specifications and redeclarations

The front end previously issued a spurious compatibility error on some
redeclarations of a function template with a dependent exception specification
containing an unqualified call to an unknown function if a candidate for that
function was introduced in an unnamed namespace following the initial
declaration.  For example:

  namespace N {
    template<typename T> void f(T p) noexcept(noexcept(f(p)));
    namespace { void f(); }
    template<typename T> void f(T p) noexcept(noexcept(f(p)));
      // Previously triggered a spurious redeclaration error.  Now okay.
  }

This is now fixed.


12/19/16 [EDGcpfe/17792]
C++14 constexpr interpreter and backing expressions

The top-level constant entry produced by a call to the C++14 constexpr
interpreter did not record a backing expression.  In some cases, that could
lead to invalid code generated by the C++-generating back end.  Now fixed.


12/18/16 [EDGcpfe/17520]
Inline namespace member should not hide enclosing name

In a lookup done within an inline namespace, a member of the inline
namespace could hide members of the enclosing namespace instead of
overloading with them.  Now fixed.

  namespace N {
    inline namespace inl1 {
      template <class T> void f(T x);
    }
    template <class T> void f(T*){}
    template <> void f<int>(int) {
      void* vp;
      // called N::inl1::f, now calls N::f
      f(vp);
    }
  }


12/16/16 [EDGcpfe/17852]
__is_constructible/__is_nothrow_constructible/__is_trivially_constructible

In non-Microsoft modes, the type traits helper functions __is_constructible,
__is_nothrow_constructible, and __is_trivially_constructible now also require
that the corresponding __is_...destructible type traits helper be "true" to
produce a "true" value (std::is...constructible is defined in terms of a
hypothetical variable definition that requires destruction).  For example:

  struct N { ~N(); };
  static_assert(__is_trivially_constructible(N), "");
    // Now an error in non-Microsoft modes.


12/16/16 [EDGcpfe/17852]
Unions and __is_base_of

The front end previously produced a "true" value for __is_base_of(U, U) where
U is a union type.  Now it produces a "false" value, because that is the
expected behavior of the std::is_base_of type trait.


12/16/16 [EDGcpfe/17869]
Clang compatibility: Invalid type specifier combinations

Clang mode previously inadvertently failed to diagnose certain invalid type
specifier combinations (corresponding to GCC-specific behavior).  For example:

  # 1 "syshdr" 3 4
  typedef int wchar_t;   // Previously accepted in Clang mode.  Now an error.

This is now fixed.


12/16/16 [EDGcpfe/17867]
Invalid C++14 constexpr evaluation of string address constant

In some circumstances, the C++14 constexpr interpreter incorrectly handled a
constant address of a string literal with an nonzero offset.  For example:

  template <typename T> struct X {
    T x;
    constexpr X(T const& p): x(p) {}
  };
  X<char const*> xc("abc"+1);

Previously, this caused xc.x to point to "c" instead of "bc" in some
configurations.  This is now fixed.


12/15/16 [EDGcpfe/17851]
GNU compatibility: Conditional operator with xvalues

In C++11, a conditional operator whose second and third operands are xvalues
of identical types produces an xvalue.  In GNU mode, that rule was disabled,
but now it is enabled when gnu_version >= 40900.  (See the entry for
EDGcpfe/14753 for a similar issue.)


12/15/16 [EDGcpfe/17847]
Positions for lambda capture initialization expressions

Some expression nodes created to initialize a closure object according to the
corresponding lambda capture entries were previously missing an end position
in configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE.  This is now
fixed.


12/15/16 [EDGcpfe/17865]
Clang compatibility: c_thread_local and cxx_thread_local extensions

A couple of changes have been made to better align with the way clang handles
thread local support.  Previously __has_extension(cxx_thread_local) could be
true in C mode; that is no longer the case.  Also,
__has_extension(c_thread_local) is now true whenever the "__thread" specifier
is enabled.

Also fixed was a bug that would have prevented some extensions from ever
reporting that an extension was enabled in C mode.


12/15/16 [EDGcpfe/17829]
GNU compatibility: "false" as a null pointer constant

The changes for EDGcpfe/17058 caused the literal "false" to be an invalid null
pointer constant in GNU C++ modes with gnu_version >= 60000.  It appears,
however, that GCC 6.0 and later do not impose that restriction in pointer
comparison contexts.  For example:

  void g(int *p) {
    if (p != false)  // Now accepted in all GNU C++ modes.
      p = false;     // Still an error.
  }

The front end now emulates that behavior in GNU C++ modes.


12/15/16 [EDGcpfe/17821]
Explicit inheriting constructors

The front end previously failed to inherit the "explicit" character of a
base constructor when synthesizing an inheriting constructor.  For example:

  struct B { explicit B(int); };
  struct D: B { using B::B; };
  D d = 1;  // Previously accepted.  Now an error.

This is now fixed.


12/14/16 [EDGcpfe/17818]
Microsoft compatibility: Address of dllimport variable

In Microsoft C++ mode, the address of a dllimport variable can now appear in
any constant-expression context (previously, the only constant-expression
contexts where this was accepted were template arguments).  For example:

  __declspec(dllimport) int v;
  constexpr int *pv = &v;  // Previously an error.  Now okay.


12/14/16 [EDGcpfe/17810]
C-generating back end: Rendering of rvalued eok_lvalue_adjust nodes

The C-generating back end previously did not correctly render rvalued
eok_lvalue_adjust nodes applied to bit fields.  This is now fixed (since such
nodes have no real effect on their operands, only the underlying operand is
now rendered).


12/14/16 [EDGcpfe/17811]
Access to uninitialized value in processing of range-based "for" statement

When processing a range-based "for" statement whose iterator type requires a
user-defined conversion to implement an inequality test, the front end
performed a comparison that involved an uninitialized value.  For example:

  struct I {
   void operator++();
     int& operator*();
    operator int();
  };
  struct C {
    friend I begin(C*);
    friend I end(C*);
  };
  void g(C c) {
    for (int i : &c) {}  // Triggered access to an uninitialized value.
  }

This is now fixed.


12/14/16 [EDGcpfe/17808]
Microsoft compatibility: Default member initializers and value classes

In Microsoft C++/CLI or C++/CX mode, the front end now issues an error on a
default member initializer appearing in a value class.  For example:

  value struct V {
    int i = 0;  // Now elicits an error in C++/CLI and C++/CX modes.
  };


12/14/16 [EDGcpfe/17806]
Microsoft compatibility: Non-const member functions and const temporaries

In Microsoft mode, the front end accepts calling a non-const member function
on a const temporary.  Now that behavior is limited to Microsoft C++ modes with
microsoft_version < 1900.  For example:

  struct S {
    S(int);
    int f();
  };
  int r = ((const S)0).f();  // Previously accepted in all Microsoft C++
                             // modes.  Now only if microsoft_version < 1900.


12/13/16 [EDGcpfe/17823,EDGcpfe/17850]
Spurious error on multiple declarators in templates with auto type specifier

The front end previously issued a spurious diagnostic on a case like the
following:

  struct S { int f(); };
  template<typename T> void g(T p) {
    auto x = p.f(), y = 0;  // Previously elicited a spurious error.
    return x+y;             // Now okay.
  }

This is now fixed.


12/13/16 [EDGcpfe/17795]
Microsoft non-permissive mode and function pointer conversions

In Microsoft non-permissive mode, the front end no longer accepts a conversion
from pointer-to-function type to pointer-to-void type for nontype template
arguments.  For example:

  template<void *P> struct X {};
  void g();
  X<g> xg;  // Previously accepted in all Microsoft C++ modes.  Now an error
            // in non-permissive Microsoft C++ modes.


12/13/16 [EDGcpfe/17794]
Microsoft compatibility: Disallow qualified in-class member names except in
permissive mode

A change has been made to disallow qualified names for in-class member
declarations in Microsoft mode except when "permissive" mode is enabled.
For example, the following non-standard code will now be diagnosed unless
--no_ms_permissive is specified:

  struct A {
    void  A::A() {}
  };


12/13/16 [EDGcpfe/17832]
Core issue 2076

The front end now implements the resolution of Core issue 2076 by default
(previously, it effectively already did so in Clang and GNU modes).  This
change is a tweak on the resolution of Core issue 1467 (see the changes for
EDGcpfe/16425) that disables user-defined conversions when considering a
copy or move constructor (and certain similar constructor contexts) and
matching it to a braced initializer that contains a single element that is
itself a braced initializer.  For example:

  struct A { A(int); };
  struct B { B(A); };
  B b{{0}};

Previously, this was ambiguous because the initializer could be interpreted
as "B b{A{0}};" or "B b{B{A(0)}};".  Now, the latter interpretation is
disabled.


12/13/16 [EDGcpfe/17702]
C++17 compatibility: Unrecognized attribute namespaces

The C++17 standard makes it clear (in P0283R2) that unrecognized attribute
namespaces should be accepted by the compiler.  That was the behavior
previously and continues to be, however, a new warning is generated
specifically for the case where an attribute namespace is unrecognized (rather
than the more general "unknown attribute" warning that was previously
emitted).  A change has also been made to emit the attribute namespace
(if any) along with the attribute name in diagnostic messages.


12/13/16 [EDGcpfe/17848]
Possible invalid memory reference with #pragma push_macro

In configurations without MICROSOFT_EXTENSIONS_ALLOWED enabled, the variable
avail_saved_macro_states could be corrupted if COMPILE_MULTIPLE_SOURCE_FILES
or MAKE_FRONT_END_CALLABLE was also enabled.  Now fixed.


12/12/16 [EDGcpfe/17695]
C++17 compatibility: Using attribute namespaces without repetition

A C++17 feature that introduces a "using" prefix to standard attribute lists
has been implemented (see P0028R4).  For example, with --g++ --c++17:

  [[ using gnu: noreturn, deprecated ]] void f() { while(1); }

This construct has the same effect as:

  [[ gnu::noreturn, gnu::deprecated ]] void f() { while(1); }

The "using" prefix is represented by a new ak_attr_using_prefix attribute that
back ends should be prepared to handle (and typically ignore since the
attributes that follow will have the proper namespace name).  This is a slight
IL CHANGE.


12/12/16 [EDGcpfe/17755]
GNU C++ compatibility: abort on template template parameter used as
default template argument

In g++ mode, an abort could occur in (in scan_template_argument_list) if a
template template parameter was used as a default template argument.  Now
fixed.

  template <template <typename> class TT1,
            template <typename> class TT2=TT1> struct A {
    template <typename T> struct B {};
  };
  template <typename U> struct C {
    template <typename T> using T2 = typename A<U::template D>::template B<T>;
  };



12/12/16 [EDGcpfe/17641]
Default function call arguments followed by parameter packs

The front end previously issued a spurious error when redeclaring a function
template whose original declaration includes a parameter with a default
argument followed by a parameter pack.  For example:

  template<typename... T> void g(int i = 0, T... ps);
  template<typename... T> void g(int i, T... ps);
    // Previously, an error was issued for the redeclaration.  Now okay.

This is now fixed.


12/12/16 [EDGcpfe/17799]
Diagnostics on transfer of control past initialization

A change has been made to the severity of the diagnostic issued when transfer
of control bypasses initialization of an automatic variable, e.g., in a case
like this:

  void f(int x) {
    if (x == 5) goto label;
    int y = 10;
  label:
    return;
  }

In most cases a warning had been generated, but that diagnostic is now an error
in GNU and clang emulation modes as well as in Microsoft mode (except in
"permissive" mode).


12/9/16  [EDGcpfe/17824,EDGcpfe/17831]
Spurious dependent pointer comparison error

The front end sometimes issued a spurious error on certain pointer comparisons
in which one of the operands has an unknown template-dependent type.  For
example:

  template<class T> void g();
  template<class T> bool f(void (*p)()) {
    return p == &g<T>;  // Previously elicited a spurious error during
  }                     // the prototype instantiation.
  template bool f<void>(void (*)());

This is now fixed.


12/9/16  [EDGcpfe/16140]
Partial substitution of parent type of class template reference

During template argument substitution, if the parent type of a reference
to a class template instance was partially substituted (e.g., in the
example below when the explicit argument C is substituted into A<T,U>) a
spurious substitution failure could occur.  Now fixed.

  template <typename T, typename U> struct A {
    template <int> using B = int;
  };
  struct C {};
  template <typename T, typename U> typename A<T, U>::template B<0> f(U t) {
    return 0;
  }
  int main() {
    return f<C>(0);
  }


12/9/16  [EDGcpfe/17719]
IA-64 ABI: Substitutions for templated types in mangled names

The change made for EDGcpfe/13764 caused a regression in the way substitutions
are used in mangled names in the IA-64 ABI.  That change has now been reversed
(when ABI_COMPATIBILITY_VERSION >= 413) to produce proper mangling for cases
that involve repeated template types with the same template parameter, like
this case:

  template <int N> struct A {};
  template <int N> void f(A<N> a1, A<N> a2);
  void f(A<3> a) {
    f(a, a);
  }


12/9/16  [EDGcpfe/16390,EDGcpfe/16389]
Template parameter pack as argument for non-variadic template parameter

The front end could issue a spurious error during a prototype instantiation
when a template parameter pack was passed as an argument for a non-variadic
template argument, and the pack was followed by a template argument
of a different kind than the pack (e.g., nontype vs. type).  Now fixed.

  template <typename, typename, int N> struct C {};
  template<typename... Ts> struct A {
    template<typename U, U u> using B = C<Ts..., u>;
  };


12/9/16  [EDGcpfe/17836]
Spurious ambiguity in converted constant expression

The front end previously issued a spurious ambiguity error on the following
case:

  struct S {
    constexpr operator int() const { return 1; }
    constexpr operator long() const { return 2; }
  };
  void g(int i) {
    constexpr const S s{};
    switch (i) {
      case s: break;  // Previously an ambiguity error.  Now okay.
    }
  }

This was a regression caused by the changes for EDGcpfe/17050.  Now fixed.


12/9/16  [EDGcpfe/17837]
Spurious error on multiple declarators with braced initializers

A declaration with multiple declarators with braced initializers could
be incorrectly disambiguated, resulting in spurious errors.  Now fixed.

  template<typename T> void f() {
    typename T::x x1{}, x2{};
  }


12/8/16  [EDGcpfe/17620]
C++-generating back end: Abort on member variable template declaration

The C++-generating back end previously aborted when attempting to render a
C++14 member variable template declaration lacking an in-class initializer.
For example:

  struct S {
    template<typename T> static T m;  // Previously triggered an internal
  };                                  // error in cp_gen_be.c.

Although the abort occurred in the C++-generating back end (in function
gen_template) it was due to the front end producing an unintended sequence of
source sequence entries.  This is now fixed.


12/8/16  [EDGcpfe/17510]
Clang compatibility: const/volatile constructors

The front end previously accepted extraneous type qualifiers on constructors in
all Clang C++ modes (see the entry for EDGcpfe/12128 etc.).  Now, that behavior
is limited to Clang C++ modes with clang_version < 30500.


12/8/16  [EDGcpfe/17838]
Out-of-class definition of variable template with in-class initializer

The front end rejected an out-of-class definition of a member variable
template that had an in-class initializer.  Now fixed.

  template <class T> struct A {
    template <class U> static constexpr U var = {};
  };
  template <class T> template <class U> constexpr U A<T>::var;


12/7/16  [EDGcpfe/17788]
Microsoft compatibility: Additional versioning tweaks

Some additional tweaks have been made to be more compatible with later versions
of Microsoft Visual Studio (in particular when microsoft_version == 1910).


12/7/16  [EDGcpfe/17159,EDGcpfe/17662]
Clang compatibility: Vector type conversions

In Clang mode, the front end now supports implicit conversions between vectors
of identical lengths if the implicit conversion for the underlying types is
permitted.  For example:

  typedef long V2L __attribute((vector_size(2*sizeof(long long))));
  typedef double V2D __attribute((vector_size(2*sizeof(double))));
  V2L vl;
  V2D vd = vl;  // Now accepted in Clang mode.


12/6/16  [EDGcpfe/17722]
Attribute on friend declaration

A standard attribute is allowed only on friend definitions -- not friend
declarations.  An error is issued in all modes except GNU emulation mode.
For example, with --c++11:

  struct A {
    friend class alignas(16) C;
  };


12/6/16  [EDGcpfe/16988]
Conversion functions and template arguments

When constexpr is enabled, the front end now considers conversion functions to
match nontype template arguments to their parameters.  For example:

  template<int N> int g() { return N; }
  struct X {
    constexpr operator int() const { return 42; }
  };
  constexpr X x{};
  int r = g<x>();  // Previously an error.  Now okay.


12/6/16  [EDGcpfe/17548]
Standard attributes on elaborated-type-specifier declaration

The presence of standard attributes in a declaration (but not definition) with
an elaborated-type-specifier and a qualified identifier had been treated as a
redeclaration, but now elicits a warning or error (in strict mode).  For
example (with --c++11):

  struct S1 {};
  struct ::S1;              // A warning or error depending on the mode.
  struct alignas(int) S2 {};
  struct alignas(int) ::S2; // Now also a warning or error.


12/5/16  [EDGcpfe/17068]
Performance improvement in type traversal

The performance of the type traversal routines has been significantly
improved for operations such as checking whether a type is dependent.
This can result in significantly better performance for cases that
involve complex types as template arguments.


12/2/16  [EDGcpfe/17460]
Internal error on member function declared with decltype

The front end previously aborted with an internal error in copy_param_type_list
(il.c) on a case like the following:

  struct S {
   static void g(int = 42);
   decltype(g) f;  // Declares a member function.
  };

The problem was triggered by the presence of default function call arguments on
the original function declaration.  This is now fixed.


12/2/16  [EDGcpfe/17271]
Friend enum declarations

Consider the following example:

  enum E {};
  namespace N {
    struct S {
      friend enum E;  // Previously ::E.  Now N::E and an error
    };                // in strict mode.
  }

Previously, the front end resolved the friend declaration to the enum type
defined in global scope (i.e., ::E).  However, the standard rule for looking
up the name in a friend declaration limits the lookup to the immediately
enclosing namespace scope.  The front end now implements that limitation.
In strict mode, an error is now issued on this example because the standard
doesn't permit forward declarations of enum types.


12/2/16  [EDGcpfe/17125]
Iterator variable redeclarations

The front end now issues a discretionary error if the outermost block of a
range-based "for" loop declares a name matching the name of the iterator
variable of that loop.  For example:

  #include <initializer_list>
  void g() {
    for (int N: { 1, 2 }) {
      struct N {};  // Now an error.
    }
  }

In Microsoft mode, the discretionary error is reduced to a warning.


12/2/16  [EDGcpfe/17801]
Performance for IA-64 mangling

Some changes have been made to improve the performance during the processing of
substitutions used when mangling names in the IA-64 ABI.


12/2/16  [EDGcpfe/17086]
Spurious error on [[noreturn]] when GNU extensions disabled

For certain member function definitions, the front end issued a spurious error
when attempting to specify the C++11 attribute [[noreturn]] on that definition
if GNU_EXTENSIONS_ALLOWED is FALSE.  For example:

  struct S {
    [[noreturn]] operator int();
  };
  [[noreturn]] S::operator int() { return 42; }
    // Previously elicited an error in some configurations.  Now okay.

This is now fixed.


12/2/16  [EDGcpfe/17643]
Spurious error on non-evaluated access to variable in C++11 mode

In C++11, a built-in logical operator (&& or ||) with a constant first operand
that short-circuits the evaluation of the second operand is a valid constant-
expression even if the second operand is not (that is not the case in C++03).
The front end, however, sometimes issued a spurious error in such cases.
For example:

  struct U { bool operator&& (U const& rhs); };
  bool b;
  double x[1+(0 && b)];  // Previously triggered an error in C++11 mode
                         // because b is nonconstant.  Now okay.

That is now fixed.


12/2/16  [EDGcpfe/17523]
Constexpr interpreter and addresses of local variables

In some cases where a constexpr function returns a value that includes the
address of a local variable, a constant representing the result of evaluating
that function could violate memory region constraints (a file-scope constant
entry pointed to a function-scope IL entry).  This was likely to result in an
internal error during IL traversal.  For example:

  struct S { int const &r; };
  constexpr S f(int const &p) {
    return { p };
  }
  int main() {
    const int x = 0;
    f(x);  // Previously produced IL violating memory region constraints.
  }

This is now fixed.


12/1/16  [EDGcpfe/17608]
Generic lambdas and local object lifetimes

The front end previously did not correctly handle object lifetimes in local
scopes that may be reactivated due to the presence of generic lambdas.  This
manifested itself typically as an internal error in pop_scope_full (in file
scope_stk.c, with message "unexpected curr_object_lifetime for function or
block scope").  The changes for EDGcpfe/17300 (in release 4.12) attempted to
address this issue, but did so incompletely (fixing some cases, but causing
regressions for some others).  A more comprehensive change is now implemented.


12/1/16  [EDGcpfe/17812]
Performance issue with hashing of template argument lists

Hashing of template arguments lists did not take into account the order
of the types, so <A,B,C> would produce the same value as <C,B,A>.  This
could result in poor performance for certain kinds of usage.  Now fixed.


12/1/16  [EDGcpfe/17732]
Missing immediate pragma IL entries

A change in version 4.12 could cause immediate pragmas that should be
automatically included in the IL to be omitted.  Now fixed.


11/30/16 [EDGcpfe/17714]
Spurious GNU-mode error on functional-notation cast in function signature

For certain member functions of class templates whose signature involves a
functional-notation cast, the front end was unable to match an out-of-class
definition with the corresponding in-class declaration in GNU C++ mode.
For example:

  struct I { I(int); };
  struct X { int f(I); };
  template<typename T> struct S {
    X x();
    auto m(int i)->decltype(x().f(I(i)));
  };
  template <typename T>
    auto S<T>::m(int i)->decltype(x().f(I(i))) { return 0; }
      // Previously triggered a spurious error because the "I(i)" cast could
      // not be matched to the identical cast in the in-class declaration.

This is now fixed.  (This problem could manifest itself as a regression in
some cases.  Specifically, the changes for EDGcpfe/17302 made an existing bug
more visible.)


11/30/16 [EDGcpfe/17804]
Abort on invocation of compute_has_nothrow_copy

Certain invocations of compute_has_nothrow_copy could result in a null pointer
dereference.  For example:

  class S {};
  struct A { int i; };
  struct B: A { S s; };
  struct C: B { C() {} };
  static bool b = __has_nothrow_copy(C);  // Previously aborted.  Now okay.

This is now fixed.


11/30/16 [EDGcpfe/17737]
Incorrect type comparisons for certain dependent alias template instantiations

The front end sometimes treated as identical two distinct template-dependent
alias template instantiations.  This issue is now fixed.  Known situations
where this bug manifested itself are fairly complex and involve simultaneously
compiling multiple translation units.


11/29/16 [EDGcpfe/17491]
constexpr pointer-to-member expressions

The front end previously issued a spurious "must have a constant value"
diagnostic for a pointer-to-member expression in which the object expression
is a constexpr value. This is now fixed. For example, with --c++11:

  struct A {
   int i;
   static constexpr int A::*p = &A::i;
  };
  constexpr A a = { 42 };
  static_assert(a.*A::p == 42, "");  // Previously an error, now accepted


11/29/16  [EDGcpfe/17080,EDGcpfe/17149,EDGcpfe/17217,EDGcpfe/17360]
Internal error on function parameter pack reference in decltype

An internal error could occur (in create_pack_instantiation_descr) if a
function parameter pack was referenced in a decltype in the function
declarator of a function template.  Now fixed.

  template <typename ...> void g ();
  template <typename> struct A {
    static int i;
  };
  template <typename> struct B;
  template <typename ... Ts>
      auto f(Ts & ... args) -> B<decltype(A<decltype(g(args ...))>::i)>;
  auto f (int)->decltype (f());


11/28/16  [EDGcpfe/17781]
Microsoft nonreal instantiations and overriding exception specifications

The front end approximates the behavior of Microsoft compilers with respect to
dependent base classes by performing a "nonreal instantiation" of such base
classes (i.e., an instantiation where the template parameters are treated as
generic types).  Previously, the front end attempted to check that exception
specifications on overriding virtual functions are compatible with those of
the overridden functions, but that occasionally triggered spurious warnings
because of incomplete type information.  For example:

  struct B { virtual ~B(); };
  template<typename T> struct C: B {
    virtual ~C();
  };
  template<typename T> struct D: C<T> {
    virtual ~D();  // Previously elicited a warning in some Microsoft modes.
  };

This is now fixed: The checks are no longer performed for nonreal
instantiations.


11/28/16  [EDGcpfe/17604]
Incorrect lookup in specializations of class template members

In the specialization of a member of a class template, names from base
classes that are no longer dependent (as a result of the specialization)
should be visible.  This was not true in some cases.  Now fixed.

  template <class T> struct B {
    typedef int I;
  };
  template <class T> struct A : B<T> {
    template <class U> void f(U);
  };
  template <> template <class U> void A<int>::f(U) {
    // Formerly, "I" was considered undefined
    I i = 1;
  }


11/23/16  [EDGcpfe/17785]
Increment/decrement operators and bool types

Decrementing a bool value using the "--" operator is invalid in all C++ modes.
Previously, this was handled by issuing an error whenever an attempt was made
to do so.  However, that is not sufficient in more complex overload resolution
contexts.  Consider the following example:

  struct S {
    operator int&();
    operator bool&();
  } s;
  bool b1 = s--;  // Previously an error.  Now okay.

Previously, the front end considered how to convert s to an arithmetic type
to which the "--" operator would then be applied.  That is ambiguous, however,
since both int and bool are arithmetic types.  The standard, however, specifies
that only arithmetic types other than bool should be considered: That removes
the ambiguity above.  The front end now implements the standard rule (also for
"++" in C++17 modes -- see the entry for EDGcpfe/17684).


11/23/16  [EDGcpfe/17684]
C++17 compatibility: Remove deprecated operator++ for bool types

A change has been made in C++17 mode (except for GNU and Microsoft emulation
modes) to give an error on the use of a pre- or post-increment operator for
bool types.  Such usage has been deprecated since the original 1998 standard
and is now removed (in C++17 mode).  This example now elicits two errors with
--c++17:

  void f(bool b) {
    b++;
    ++b;
  }


11/23/16  [EDGcpfe/17683]
C++17 compatibility: Remove deprecated use of "register" keyword

Use of the "register" keyword as a storage-class specifier was deprecated in
C++11 and has been removed from the language in C++17 (P0001R1).  A change has
been made to issue a warning (C++11 mode) or error (C++17 mode) on the first
use of the "register" keyword when used outside of a system header file.  These
diagnostics are suppressed in GNU and Microsoft emulation modes (until such
time as those compilers issue similar diagnostics).


11/23/16  [EDGcpfe/17720]
C++/CLI-mode abort due to handling of mangled names for boxed enum types

In C++/CLI mode, the front end sometimes creates "box types" for enum types:
These are C++/CLI value class types that wrap the enum type.  Previously, these
box types were given a "name collision discriminator" value if the associated
enum type is unnamed.  However, that violates assumptions made elsewhere in the
front end about the order in which discriminator values are assigned.  That in
turn could lead to an internal error in cancel_name_collision_discriminator
(scope_stk.c) in some cases.  For example:

  enum { e1 = 1 };
  typedef enum { e2 = 1+e1 } E;  // Previously triggered an internal error.
                                 // Now okay.

Such box types are now no longer assigned a discriminator value (none is needed
since lowering does not actually handle managed C++/CLI code).  That also fixes
the internal error.


11/23/16  [EDGcpfe/17784]
Microsoft compatibility: using --ms_extensions/--ms_compatibility when
DEFAULT_MICROSOFT_MODE is TRUE

In configurations where DEFAULT_MICROSOFT_MODE is TRUE, specifying
--ms_extensions or --ms_compatibility command-line options did not work
properly (when combined with another mode like --clang or --gcc).  Now fixed.


11/22/16  [EDGcpfe/17776]
Spurious correspondence failures for alias template instantiations

The front end previously did not handle correspondence processing for alias
template instantiations.  This resulted in spurious correspondence errors when
simultaneously compiling multiple translation units.  For example:

  // TU1:
  template<class T> struct S {
    template<class U> using A = U*;
  };
  S<int> x;  // S<int>::A not instantiated.

  // TU2:
  template<class T> struct S {
    template<class U> using A = U*;
  };
  S<int> y;
  S<int>::A<void> p = nullptr;
    // Instantiation of S<int>::A previously cause a correspondence error
    // claiming S<int> is incompatible with the version in TU1.

This is now fixed.


11/21/16  [EDGcpfe/17751]
Abort with nonconstant __builtin_offsetof construct in inline function

The GNU __builtin_offsetof construct can produce nonconstant results when
referring to array elements.  Previously, the front end could abort (in
different places, depending on the configuration) if such a nonconstant
construct was invoked through an inline function.  For example, in GNU C mode:

  struct S { int i[42]; };
  static inline int g(int n) {
    return __builtin_offsetof(struct S, i[n]);
  }
  int main() {
    return g(0);  // Previously triggered an abort in various
  }               // configurations.

This is now fixed.


11/21/16  [EDGcpfe/17773]
Core issue 1579: Return statement and move-conversion

The front end now implements the resolution of Core issue 1579, which allows a
returned lvalue to be "moved from" even though the type of the lvalue is of a
class type different from the return type of the function.  For example:

  struct A {};
  struct B { B(A&&) {} };
  B g(A a) {
    return a;  // Previously an error.  Now accepted.
  }


11/21/16  [EDGcpfe/17184]
Incorrect pack expansions when using C++-generating back end

Incorrect output could be created by the C++-generating back end in some
cases involving alias template instantiations.  In the example below,
the "X<U>::x" was incorrectly emitted as "B<T>::x", but is now emitted
as "B<T...>::x".

  template <int> struct A;
  template <typename> struct B;
  template <typename... T> class C {
    template <typename> using X = B<T...>;
    template <typename U, typename A<X<U>::x>::t> C();
  };


11/21/16  [EDGcpfe/17752,EDGcpfe/17771]
Microsoft compatibility: constexpr compatibility

When microsoft_version >= 1910 (i.e., when emulating Microsoft Visual Studio
"15"), the C++14 relaxed constexpr feature is now enabled.  Also, in this mode,
a constexpr non-static member function is not implicitly const-qualified
(see the Changes entry for EDGcpfe/16092).


11/21/16  [EDGcpfe/17741]
Spurious failure on cast in template argument

Consider the following example:

  template<int I> struct S {};
  template<unsigned U> void g(S<(int)~U>) {}
  template void g<42U>(S<(int)~42>);  // Previously a spurious error.

In strict C++11 mode, this previously triggered a spurious error because the
front end treated the substitution of U = 42U into (int)~U as a narrowing
conversion on a template parameter.  That shouldn't be the case since the
conversion is done for the explicit cast and not the binding of the template
parameter.  That is now fixed.


11/17/16  [EDGcpfe/17756]
Internal error in C++14 constexpr interpreter on use of subobject address

In somewhat unusual situations where the address of a subobject is passed into
a constexpr function or constructor, the front end could abort with an internal
error in the C++14 constexpr interpreter (in extract_value_from_constant).
For example:

  struct B { int v[2]; };
  struct D: B {
    constexpr D(int *p): B() {}
  } x(&x.v[1]);  // Previously triggered an abort while attempting to
                 // process the address &x.v[1] in the interpreter.

This is now fixed.


11/17/16  [EDGcpfe/17744]
Erroneous folding of !X with X a template-dependent construct

The front end sometimes erroneously folded the logical-not operator applied to
a template-dependent construct (the folded result was "false").  This could
lead to spurious errors while parsing template definitions.  This is now fixed.


11/17/16  [EDGcpfe/17747]
Constant-expressions

The C and C++ standard describe a grammatical construct constant-expression
along with constraints that give such expressions a constant value.  The
grammar actually excludes assignment-expressions like "n = 2", but the front
end previously parsed such an expression as a constant-expression anyway,
assuming that semantic checking would later trigger a diagnostic as required
by the standard because assignments don't usually produce constant values.
However, with the introduction of constexpr evaluation it is possible for
assignments to produce constant values and therefore leaving the diagnostic
to semantic checking is no longer standard-conforming.  For example:

  struct N {
    constexpr N() {}
    constexpr int operator=(int) const { return 5; }
  };
  constexpr N n{};
  int x[n = 42];  // "n = 42" is not grammatically a constant-expression,
                  // but evaluation would produce a constant.

The front end therefore now parses constant-expressions as indicated by the
standard grammar (i.e., as a conditional-expression instead of an
assignment-expression).  However, the old behavior is retained in GNU and
Microsoft modes, since GCC and MSVC also have this defect.


11/17/16  [EDGcpfe/17739]
Memory region violation in constant produced by constexpr evaluation

In some relatively complex cases, the C++14 constexpr interpreter could
produce an address constant pointing to an aggregate constant, both allocated
in file scope memory, but with the aggregate constant pointing to a constant
in a function scope memory region.  This memory region violation could then
result in aborts later on.  This is now fixed.


11/16/16  [EDGcpfe/17746]
User-defined literal value errors

The front end contained a bug causing the literal operator templates to be
passed incorrect template arguments in some situations.  For example:

  template<typename, typename> struct Eq {
    static constexpr bool value = false;
  };
  template<typename T> struct Eq<T, T> {
    static constexpr bool value = true;
  };
  template<int N> struct F {};
  template<char D> struct D2I {
    static constexpr int value = D-'0';
  };
  template<char... Ds> F<D2I<Ds...>::value> operator "" _F();
  template <typename T> void f(T);
  struct C {
    static void unused() { f<F<0>>(0_F); }
  };
  static_assert(Eq<F<2>, decltype(2_F) >::value, "Unexpected!");

This test case should be accepted, but was previously handled as if 2_F were
replaced by 0_F, causing the final assertion to fail.  This is now fixed.


11/16/16  [EDGcpfe/17765]
Point of declaration for an alias template (core issue 1044)

The point of declaration of an alias template was changed by core issue
1044 to be following the type-id in the alias (i.e., at the point of
the semicolon in the declaration).  The front end now implements the
revised rules.

  class A {};
  namespace N {
    template <typename T1, typename T2> class B {};
    template <typename T> using A = B<A, T>;  // formerly ill-formed
  }


11/16/16  [EDGcpfe/17743]
Internal error on user-defined literal when instantiating class template

The front end previously could abort with an internal error (in function
make_func_operand_for_literal_operator_call) when a user-defined literal was
the current token at the point of instantiation of a class template.  For
example:

  template<char...> int operator""_udl();
  template<typename T> struct X {
    X(T);
  };
  X<int> x(0_udl);  // Previously triggered an internal error.

This is now fixed.


11/15/16  [EDGcpfe/17211]
Invalid casts in template-dependent constant-expression contexts

In GNU, Clang, and Microsoft modes, the front end now accepts certain invalid
casts in template-dependent constant-expression contexts.  For example:

  template <class T> struct B { int s; };
  template <class T> struct D: B<T> {
    static_assert(
      (unsigned long)&reinterpret_cast<char&>(((B<T> *)0)->s) == 0, "");
  };

Previously, this example triggered an error because reinterpret_cast
constructs are not permitted in constant-expression contexts.  Now, however,
it is accepted in some modes.  (Instantiating the template may also be
accepted because this particular pattern is used for certain implementations
of the "offsetof" macro, even though it is nonstandard.)


11/15/16  [EDGcpfe/17760]
Scope stack corruption from exception specification prototype instantiation

In some unusual circumstances the scope stack could be left in an incorrect
state after the prototype instantiation of an exception specification.  This
could result in some kind of internal error or other incorrect behavior.
Now fixed.


11/14/16  [EDGcpfe/17403]
Internal error on same-type const_cast in Microsoft bugs mode

In Microsoft C++ bugs mode with same-type lvalue casts disabled (i.e., with
"--ms_rvalue_cast" or "--no_preserve_lvalues_with_same_type_casts" -- see the
entries for EDGcpfe/14628 and EDGcpfe/17677) the front end aborted with an
internal error in expr.c ("lvalue_cast: lvalue cast in unexpected mode") on
certain const_cast constructs.  For example:

  int *a;
  int *b = const_cast<int*>(a);
    // Previously triggered an internal error when command-line options
    // "--microsoft --ms_rvalue_cast" are selected.

This is now fixed.


11/10/16  [EDGcpfe/17679]
Microsoft compatibility: --no_ms_permissive compatibility

The --no_ms_permissive flag (which emulates Visual Studio's /permissive-
command-line option) now has these additional consequences when microsoft_mode
>= 1910:

- The deprecated string literal conversion (i.e., to a char* or wchar_t* type)
  is disabled.  The --deprecated_string_conv command-line option can be used
  to override this.
- The "for each" statement is disallowed.
- Alternative token representations are provided for some operators and
  punctuators.


11/10/16  [EDGcpfe/17145]
Attributes appertaining to declarator-ids of friend member functions

The attributes appertaining to the declarator-id of a friend function that is a
class member had previously not been applied to the member function.  That
omission had caused the lack of a diagnostic in a case like the one below and
is now fixed (with --c++11):

  struct A {
    void f(void) { }
  };
  struct B {
    friend void A::f [[carries_dependency]] (void);
  };


11/10/16  [EDGcpfe/17734]
Elide assignment of empty class in lowering

Lowering typically elides assignments from types of empty classes, but that was
not the case in the placement new case below.  In configurations where an empty
base class has size 1, the assignment caused the ptr_ member to be overwritten.
Now fixed.  For example (with --c++11):

  extern "C" int printf(const char *,...);
  inline void* operator new(__SIZE_TYPE__, void* p) {
    return p;
  }
  struct B {};
  struct D : B {
    void *ptr_;
    D(const B& __base, void* ptr) : ptr_(ptr) {
      new(static_cast<B*>(this)) B(__base);
      if (ptr != ptr_) {
        printf("%p != %p\n", (void *)ptr, (void *)ptr_);
      }
    }
  };
  D d(B(), nullptr);


11/8/16  [EDGcpfe/17742]
Using debug code while reading a precompiled header

If a debug option such as "-d3" is used in a compilation in which a
PCH is used, an internal error could occur (in add_mem_alloc_history_entry)
as a result of curr_stop_token_stack_entry referring to memory that has
not yet been loaded.  Now fixed.


11/4/16  [EDGcpfe/17727]
ELF visibility attribute and explicit class template instantiations

The changes for EDGcpfe/17461 introduced a regression causing the front end to
lose an ELF visibility attribute specified on an explicit class template
instantiation directive.  For example:

  template<typename T> struct S {
    static int f();
  };
  template<typename T> int S<T>::f() { return sizeof(T); }
  template struct __attribute__((visibility("hidden"))) S<int>;
    // Previously, S<int>::f lost the "hidden" attribute.  Now it is
    // preserved.

This is now fixed.


11/3/16  [EDGcpfe/12825]
Member operator new and delete definitions in secondary translation units

In configurations with configuration macros NEW_CAN_BE_FOLDED_INTO_CTOR and/or
DELETE_CAN_BE_FOLDED_INTO_DTOR set to TRUE, certain constructor and destructor
entries call associated operator new and delete, respectively.  These calls are
not always explicit in the IL, however; in particular, they are not present in
the unlowered IL of a secondary translation unit.  That previously could result
in the front end assuming that a definition for an operator new or delete is
not needed when in fact it is needed for the implementation of a constructor
or destructor.  For example, when simultaneous compiling the following two
translation units:

  // tu1.cpp:
  // (empty)

  // tu2.cpp:
  typedef __EDG_SIZE_TYPE__ size_t;
  struct X {
    virtual ~X() {}
    void operator delete(void *p, size_t sz) {}
  };
  int main() {
    X x;
  }

a linker error was produced because the definition of "operator delete" was
erroneously discarded.  This is now fixed.


11/3/16  [EDGcpfe/17318]
Member using-declarations and class/enum names

Previously, the front end issued an error when a member using-declaration
referred to function declaration from a base class in a derived class with a
class or enum type of the same name.  For example:

  struct B { void X(); };
  struct D: B {
    struct X {};
    using B::X;  // Previously an error.  Now accepted.
  };

This is now fixed.


11/2/16  [EDGcpfe/17725]
C++14 constexpr interpreter: Base-class casts and null pointers

The C++14 constexpr interpreter contained a bug causing it to access
uninitialized storage when handling eok_base_class_cast nodes applied to
null pointers.  The bug could result in invalid evaluations or aborts,
depending on the overall state of the front end.


11/2/16  [EDGcpfe/6091,EDGcpfe/6874,EDGcpfe/11689,EDGcpfe/12710,EDGcpfe/12965,
          EDGcpfe/13817,EDGcpfe/13971, EDGcpfe/14218,EDGcpfe/14975,
          EDGcpfe/16440, EDGcpfe/16488, EDGcpfe/16497, EDGcpfe/17067,
          EDGcpfe/17667,EDGcpfe/17733]
__float128 and __float80

The front end now includes support for __float128 and __float80 floating-point
types.  These are patterned after the similar feature in GCC (and, to some
extent, Clang): When enabled, __float128 and __float80 are predefined typedefs
for floating-point types with, respectively, 128- and 80-bit value
representations.  Associated floating-point literal suffixes are also
supported ('q' and 'Q' for __float128 literals, 'w' and 'W' for __float80
literals).  Configuration macros FLOAT80_ENABLING_POSSIBLE and
FLOAT128_ENABLING_POSSIBLE control whether these extensions can be enabled
at all; when they can, GNU modes enable both __float128 and __float80, whereas
Clang modes enable __float128 only.

The new types can map to existing floating-point kinds or to the new kinds
fk_float128 and fk_float80.  This is controlled by the global variables
float_kind_for_float128 and float_kind_for_float80, which are initialized by
default with the configuration macros DEFAULT_FLOAT_KIND_FOR_FLOAT128 and
DEFAULT_FLOAT_KIND_FOR_FLOAT80.  If not configured explicitly, __float128 maps
to fk_float128 and __float80 maps to fk_long_double (i.e., __float80 is a
synonym for type "long double").  This addition of new floating-point kinds
means that the floating-point kinds are no longer necessarily numbered in
increasing order of precision (e.g., fk_float80 comes after fk_long_double,
but fk_long_double could be a 128-bit floating-point type).

To enable support for __float128, USE_FLOAT128_FOR_HOST_FP_VALUE (another new
configuration macro) must be set to TRUE and, as a result, the front end must
be built with a host compiler that itself supports __float128.  In addition,
routines are needed to convert to and from string representations of 128-bit
floating-point values.  Currently, the front end relies on strtoflt128 and
quadmath_snprintf, which are APIs implemented by the GNU QuadMath library
(called when USE_QUADMATH_LIBRARY is configured TRUE).  If that library is not
available or usable, the functions fp_to_string and str_to_float128 must be
modified to make use of an alternative.  (For testing purposes, a configuration
macro APPROXIMATE_QUADMATH can be set to TRUE; it uses the "long double"
routines to perform approximate conversions instead).


11/2/16  [EDGcpfe/17723]
Build issue on Windows when not using UNICODE_SOURCE_SUPPORTED

Building the front end with UNICODE_SOURCE_SUPPORTED == 0 on Windows
would result in a compilation error in CreateFile_interface.  Now fixed.

11/1/16  [EDGcpfe/17718]
File closed more than once with MAKE_FRONT_END_CALLABLE

A file could be closed more than once (which could cause an abort or other
undefined behavior) in a version configured with MAKE_FRONT_END_CALLABLE.
The problem occurred when compiling a file containing #line directives
if the front end terminated via a catastrophic error (e.g., if the error
limit was reached).  Now fixed.


10/31/16 [EDGcpfe/17712]
Unbounded loop with malformed __has_include invocation

If the __has_include operator fails to have the correct syntax (i.e., it
is not followed by a parenthesized file name), the front end could
sometimes enter a non-terminating loop.  This is now fixed.  For example,
the front end looped continuously with a file containing the single line,

  __has_include


10/31/16 [EDGcpfe/17717]
Spurious error using template template parameter as template template argument

A spurious error could result when a variadic template template parameter
of one template was passed as a template template argument to another
template.  Now fixed.

  template <typename T, template <typename, T...> class> struct A;
  template <template <typename U, U...> class TT> struct B {
    using X = A<char, TT>;
  };


10/31/16 [EDGcpfe/17675]
GNU C++ compatibility: operator names and using-directives

The front end does quite a bit of processing to emulate the behavior
of using-directives in g++ mode.  g++ seems to handle overloaded
operator functions differently than other functions.  In particular,
the location of the using-directive does not seem to matter.  We now
emulate this behavior in g++ mode.

  class A {};
  template <class T> struct B { T f(); };
  class C {};
  template <class T> inline void operator<<(C& c, B<T>& b) {
    // Formerly, no match for C << A
    c << b.f();
  }
  namespace N { void operator<<(C& c, const A& a); }
  using namespace N;
  int main() {
    C c;
    B<A> b;
    c << b;
  }


10/31/16 [EDGcpfe/17674]
Generated assignment operators and indirect virtual base classes

Consider the following example:

  struct B { B& operator=(B const&) = delete; };
  struct C: virtual B {
    C& operator=(C const&);
  };
  struct D: C {
    void f(D const &rhs) {
      *this = rhs;  // Previously an error.  Now okay.
    }
  };

Previously, the generated assignment operator for type D was marked as deleted
because the corresponding operator in the virtual base class is deleted.
However, since the virtual base class is indirect, the generated D::operator=
can assume that the direct base class C's assignment operator will implement
the assignment of the virtual base class subobject.  Therefore D's inability
to call B::operator=(B const&) does not impede the generation of D's copy
assignment operator and the case above is valid.  The front end now implements
that observation (except in Clang mode, because Clang issues an error for this
case).


10/31/16 [EDGcpfe/17682]
Incorrect lowered code generated for inlined operator new []

In some cases where an operator new [] is inlined and the body of the inlined
function doesn't refer to the first argument (i.e., the number of bytes to
allocate), the lowered code that was previously generated might use an
uninitialized variable when initializing the allocated storage, thereby having
undefined results at run time.  This is now fixed.  For example (with --c++11):

  typedef __EDG_SIZE_TYPE__ size_t;
  inline void* operator new[](size_t, void* p) noexcept {
    return p;
  }
  int v[2];
  int main() {
    size_t count = 2;
    int* x = new (&v) int[count]();
    return 0;
  }


10/31/16 [EDGcpfe/17678]
Microsoft non-permissive mode: Copy- vs. direct-initialization

In Microsoft mode, the front end treats common cases of "copy-initialization"
as if they were "direct-initialization" (see the entry of 1/18/98).  In
"non-permissive" Microsoft mode (see the entry for EDGcpfe/17455) that
nonstandard behavior is now disabled.  For example:

  struct A {
    operator const char*() ;
  };
  struct B {
    B(const char*) ;
  };
  B f(A a) {
    B x = a;   // Accepted in permissive Microsoft mode only.
    return a;  // Accepted in permissive Microsoft mode only.
  }


10/31/16 [EDGcpfe/17713]
Regression with builtin referenced in preprocessing directive

As a result of the changes for the new builtin mechanism (Changes entry
EDGcpfe/16431 et al.), referring to a builtin function name in a
preprocessing directive had resulted in a segfault in normal_id_lookup and is
now fixed.  For example (with --gcc):

  #if defined(alloca) && (alloca == __builtin_alloca)
  #endif


10/31/16 [EDGcpfe/17716]
Argument-dependent lookup not done in some constant contexts

When an identifier is used in what looks like a function call and the
identifier is undefined, argument-dependent lookup should be done to
possibly find a function or function template from a namespace.  This
was not done in some contexts in which a constant was required.  Now fixed.

  void g();
  namespace N {
    struct A {};
    template <class T> constexpr int f(T) { return 0; }
    template <class T> constexpr int g(T) { return 0; }
  }
  int main() {
    constexpr N::A a;
    constexpr int i = f(a);  // failed
    constexpr int j = g(a);  // worked, first found ::g then later N::g
  }


10/30/16 [EDGcpfe/17711]
Regression with pack expansion in non-top-level function declarator

A change in version 4.12 could result in incorrect behavior when a
template declaration contained a function declarator, other than the
top-level one in a function declaration, and that function declarator
included a pack expansion.  Now fixed.

  struct C { void f(int); };
  template <typename T> struct A {
    template <typename, typename> class B;
    template <typename T2, typename... Args_>
    struct B<T2, void (Args_...)> {
      template <typename U, void (U::*)(Args_...)> struct D;
      template <typename U> static constexpr int g(D<C, &U::f>*) { return 1; }
      template <typename> static constexpr int g(...) { return 0; }
      constexpr static int i = g<T2>(0);
    };
    static constexpr int i = B<T, void(int)>::i;
  };
  static_assert(A<C>::i, "wrong i");


10/28/16 [EDGcpfe/17677]
Microsoft compatibility: --ms_rvalue_cast/--no_ms_rvalue_cast

Command-line options --ms_rvalue_cast and --no_ms_rvalue_cast have been added
to the front end.  Option --ms_rvalue_cast is equivalent to the option
combination "--microsoft --no_preserve_lvalues_with_same_type_casts" (see the
entry for EDGcpfe/14628), whereas "--no_ms_rvalue_cast" is equivalent to
"--microsoft --preserve_lvalues_with_same_type_casts".  By default, the option
"--no_ms_permissive" also implies "--ms_rvalue_cast".


10/27/16 [EDGcpfe/17689]
Precompiled headers and unique file IDs

When using unique file identifiers (e.g., inode numbers) to see if a
file has already been included, a file could incorrectly be considered
as a match if a PCH file was created on one machine and used on another,
and the program included a file that matched the unique file ID of
a file included when the PCH was generated.  Now fixed.


10/27/16 [EDGcpfe/17650]
Internal error on string initializer for variable-length array in GNU mode

The changes for EDGcpfe/16811 permit variable-length array declarations to
include an initializer in some GNU C++ modes.  However, those changes failed
to update code handling the case of an array initializer with a string
literal, causing the front end to abort with an internal error in function
check_string_constant_initializer_full (decl_inits.c) in such cases.  For
example:

  void f(int n) {
    char str[n] = "";
  }

This is now fixed.


10/26/16 [EDGcpfe/17676]
Microsoft compatibility: enabling/disabling dependent name lookup

The effect of the --[no_]dep_name options when used in Microsoft mode have
been changed.  Formerly, --dep_name did not cause nonclass prototype
instantiations to be enabled, but should have.  In addition, --no_dep_name
can now be used in conjunction with --no_ms_permissive to disable most
permissive behavior, but still enable normal (permissive) Microsoft-mode
template lookup processing.


10/25/16 [EDGcpfe/17672]
GNU compatibility: Additional builtin functions

Builtin functions available with the -mavx512er, -mavx512pf, and -mtbm command-
line options to GCC have now been added.


10/24/16 [EDGcpfe/17659]
Variable template partial specialization issues

A partial specialization of a variable template could result in a spurious
"explicit template argument list is not allowed" error.  In addition,
the partial specialization processing did not properly handle certain
aliases, such as void_t, in which the result of the alias is not dependent.
These are now fixed

  template <class...> using void_t = void;
  template <class, class = void> constexpr bool test = false;
  template <class T> constexpr bool test<T, void_t<typename T::type>> = true;
  struct A {};
  static_assert(!test<A>, "");


10/24/16 [EDGcpfe/17670]
GCC compatibility: warning on redeclaration of builtin function

Previously, a redeclaration of a builtin function with a different function
signature in gcc emulation mode triggered an error; now a warning is given.
For example (with --gcc):

  void _Exit() {}


10/23/16 [EDGcpfe/17668,EDGcpfe/17504,EDGcpfe/17320]
C++11 constexpr folding and values returned by copy constructor

With constexpr functions in which copy elision is not performed and the
value is returned by means of a constexpr copy constructor, the front end
previously issued spurious "must have a constant value" diagnostics when the
program was compiled in C++11 mode.  This is now fixed.  For example, with
--c++11:

  struct S {
    constexpr S(const S &rhs) : val_(rhs.val_) { }
    constexpr S(int val) : val_(val) { }
    constexpr S operator|(const S &rhs) const {
      return S(val_ | rhs.val_);
    }
    int val_;
  };

  constexpr S Join() {
    return S(0);
  }

  template<class... Args>
  constexpr S Join(const S &head, Args... tail) {
    return head | Join(tail...);
  }

  static constexpr S x = Join(1, 2, 4, 8);  // Previously not constant


10/21/16 [EDGcpfe/14798,EDGcpfe/15093]
Attributes on enumerators

The C++17 standard allows for attributes on enumerators (see the Changes entry
for EDGcpfe/16270) and now the front end enables support for these in all
clang emulation modes as well as GNU emulation mode when gnu_version >= 60000.
__has_extension(enumerator_attributes) is now enabled in clang modes.
The following is now accepted with --clang or --gnu_version 60000:

  enum {
    e __attribute__((deprecated))
  };


10/20/16 [EDGcpfe/17649]
Clang compatibility: builtin signatures for concrete __sync_* builtins

A change has been made to the type of the first argument of signatures for the
concrete __sync_* builtin routines.  Previously those routines took a pointer
to an appropriately-sized volatile integer type and now these routines take
"volatile void *".  Clang apparently allows passing pointers to signed/unsigned
data types for these arguments, necessitating the change.  For example (with
--clang):

  char f(signed char *p, char c) {
    return __sync_fetch_and_add_1(p, c);
  }


10/20/16 [EDGcpfe/17657]
Spurious error on constexpr constructor constructing a member with a destructor

The front end previously diagnosed an error for a constexpr constructor that
relies on a default member initializer for a member with a nontrivial
destructor.  For example:

  struct N {
    constexpr N() {}
    ~N() {}
  };
  struct S {
    N n{};
    constexpr S() {}  // Previously elicited an error.
  };

This is now fixed.


10/19/16 [EDGcpfe/17655]
Use of "register" storage class eliminated from the front end

The front end no longer uses the keyword "register" (a storage class specifier)
because that feature was deprecated in C++11 (modern compilers mostly ignore
the keyword).


10/19/16 [EDGcpfe/16990,EDGcpfe/17648]
_Pragma use in functions could cause assertion failure

In C++-generating configurations, the use of an immediate _Pragma in a function
would lead to an assertion failure (alloc_copy_of_pending_pragma: copied pragma
has source sequence entry).  Now fixed.  For example (with --g++):

  struct A {
    void f() {
      _Pragma ("GCC diagnostic push")
      _Pragma ("GCC diagnostic pop")
    }
  };


10/19/16 [EDGcpfe/17651]
Segmentation violation on invalid use of _Noreturn

As a result of the changes for EDGcpfe/17383, a segmentation violation (in
apply_c11_noreturn) had occurred on invalid uses of the C11 _Noreturn function
specifier in GNU emulation mode.  Now fixed.  For example (with --c11 --gcc):

  typedef _Noreturn void f(void);


10/18/16 [EDGcpfe/17644]
GCC pragmas in C++-generating configurations

A change has been made to process most "GCC" pragmas in C++-generating
configurations.  Some "GCC" pragmas (i.e., system_header) are still ignored
by the back end.  For example (with --gnu_version 50200):

  #pragma GCC push_options
  #pragma GCC target("xsavec")
  extern __inline void
  __attribute__((__gnu_inline__, __always_inline__, __artificial__))
  _xsavec (void *__P, long long __M) {
    __builtin_ia32_xsavec (__P, __M);
  }


10/18/16 [EDGcpfe/17638]
Segfault in instantiate_make_integer_seq

As a result of the changes for EDGcpfe/17282, a segfault could occur in some
configurations when using __make_integer_seq.  This is now fixed.  For example
(with --microsoft_version 1900):

  template<class T, T... v> struct I {};
  template<class T, T s> using X = __make_integer_seq<I, T, s>;
  X<int, 5> x;


10/17/16 [EDGcpfe/17610]
Logical operators and constexpr conversion functions

The front end previously issued a spurious error when a built-in logical
operator included a short-circuited second operand convertible to bool via a
constexpr conversion function that would not evaluate to a constant (but need
not be evaluated at all since it is short-circuited).  For example:

  struct V {
    int v;
    constexpr operator bool() const { return v; }
  };
  V x;
  constexpr bool r = 0 && x;  // Previously a spurious error.  Now okay.

This is now fixed.


10/17/16 [EDGcpfe/17630,EDGcpfe/17635]
Internal error with macro definition of builtin function name

After the changes for the new builtin mechanism (Changes entry EDGcpfe/16431
et al.), using a macro with the same name as a builtin function caused
an internal error (assoc_source_line_modif: bad address).  Now fixed.
For example (with --gcc):

  #define __builtin_vsnprintf __mingw_vsnprintf
  void f() {
    const int __ret = __builtin_vsnprintf();
  }


10/17/16 [EDGcpfe/17625]
Binding nontype template parameters of reference type.

The front end did not always diagnose invalid nontype template arguments for
nontype template parameters of reference type.  For example:

  template<int&> struct X {};
  int x[2];
  struct X<x[1]> xx;  // Previously erroneously accepted.  Now an error
                      // because nontype template arguments cannot refer to
                      // proper subobjects.

This is now fixed.  (The problem was more prevalent in modes that support the
"constexpr" feature, but even in other modes the problem could arise, as the
example above demonstrates.)


10/17/16 [EDGcpfe/17639]
Undefined "end" source position for inline namespaces

As a result of the changes for EDGcpfe/16712, the "end" source position for
inline namespaces had been uninitialized in configurations where
EXTRA_SOURCE_POSITIONS_IN_IL is TRUE.  Now fixed.


10/17/16 [EDGcpfe/17634]
Possible use of invalid scope stack pointer

template_directive_or_declaration could potentially make use of a scope
stack pointer after a call that could cause the scope stack to be resized,
resulting in an invalid memory access.  Now fixed.


10/15/16 [EDGcpfe/17596]
Error on use of template template argument with multiple default arguments

An "unexpected function type" error could result if a template template
argument has more than one default template argument that is used for a
given reference and those default arguments correspond to a template
parameter pack of the template template parameter.  Now fixed.

  template<typename T1, typename T2 = int, typename T3 = char> class A {};
  template <template <class...> class T> T<int> f() { return T<int>(); }
  int main() {
    auto a = f<A>();
  }


10/14/16 [EDGcpfe/17628]
C++14 constexpr: Derived-to-base conversions on address constants

When attempting to interpret a derived-to-base conversion (eok_base_class_cast)
applied to an address constant for a run-time entity, the front end always
failed interpretation.  In fact, such casts can often be folded to produce
another address constant.  For example:

struct B { constexpr bool f() const { return true; } };
struct D: B {};
struct X {
  constexpr X(D const &p): x(p) { }
  constexpr bool f() const { return x.f(); }
  D x;
};
int main() {
  constexpr D d{};
  const X z(d);
  constexpr bool r = z.f();
}

The call "x.f()" during the evaluation of "z.f()" requires a cast of the
address constant representing a reference to z.x cast to a reference to B.
Previously, that triggered a spurious error.  Now it is accepted (because
the value referred to is never accessed).


10/14/16 [EDGcpfe/17623]
Incorrect name lookup in generic lambda instantiation

Name lookup sometimes produced incorrect results for a generic lambda
defined in a function in a namespace.  Now fixed.

  namespace N {
    template <class> using A = void;
    template <class T> constexpr void f(const T& t) { t(1); }
    void g() {
      // Formerly: A is not a template
      f([](const auto&) { using T = A<int>; });
    }
  }


10/14/16 [EDGcpfe/17622]
Trivial copy/move members and variant members

The front end previously erroneously "deleted" the generated move constructor
of a class that has a variant member with a trivial move constructor.  For
example:

  struct M {
    M() = default;
    M(M&&) = default;
  };
  struct S { union { M m; }; };
  S&& g();
  S x{g()};  // Previously elicited an error because the move constructor
             // of S was considered "deleted".  Now okay.


10/14/16 [EDGcpfe/17619,EDGcpfe/17627]
Abort with dependent nontype template argument

A change in version 4.12 (see EDGcpfe/17088, 7/11/16) caused the front end
to abort with a segfault in check_for_routine_scope_variable when a
dependent expression was passed as a nontype template argument.  This is
now fixed.  For example, with --c++11:

  template<typename T, T t> struct A { };
  template<bool b> using B = A<bool, b>;
  template<typename T> struct C {
    void f() {
      const bool b = T::x;
      B<b> bb;  // Previously caused a segfault
    }
  };


10/14/16 [EDGcpfe/17626]
Missing diagnostic on use of ambiguous injected class name in template

The front end failed to issue a diagnostic if a class template made use
of an ambiguous injected class name.  An error was issued if the template
was ever instantiated.  The error is now diagnosed when the template
is defined.

  template <class T> struct A { };
  template <class T> struct B : A<int>, A<char> {
    B::A b;
  };


10/13/16 [EDGcpfe/17607]
Core issue 1344: Special members and default arguments

In C++14 mode, the front end now issues an error if an out-of-class definition
of a constructor adds default arguments in such a way that the constructor
becomes a special member function (i.e., a default constructor or copy/move
constructor).  For example:

  struct S { S(int); };
  S::S(int = 0) {}  // Now an error in C++14 mode since adding the default
                    // argument makes the constructor a default constructor.

This corresponds to the resolution of Core issue 1344.


10/13/16 [EDGcpfe/17095]
Microsoft compatibility: abort importing C++/CLI type with nested constraint

The front end could abort (as a result of unbounded recursion) when importing
a type with a constraint that referred to a nested class of the containing
type.  Now fixed.  Such a type can't be written in C++, but can be written
in C#.  The C# definition would be of the form:

  class A<T> where T : A<T>.B { class B { } }


10/13/16 [EDGcpfe/14942,EDGcpfe/17618]
GNU compatibility: Accept __final as a synonym for "final"

In g++ emulation mode when gnu_version >= 40700, the __final keyword is
now accepted as a synonym for "final".  For example (with --gnu_version 40700):

  struct A __final {};


10/13/16 [EDGcpfe/17621]
Assertion failure when attribute is applied to variable template

An assertion failure (in get_attribute_link) had occurred in cases where
an attribute is applied to a variable template.  Now fixed.  For example
(with --c++14 --g++):

  struct A {
    template <typename T> static __attribute__((aligned(2))) T m;
  };


10/13/16 [EDGcpfe/17347,EDGcpfe/17348,EDGcpfe/17549]
GNU compatibility: Lowering now re-writes individual vector elements

Prior to the changes for EDGcpfe/14580, the IL didn't have the capability to
address individual vector elements, so lowering of vector elements was limited.
Lowering now uses the eok_vector_subscript operation to enable assignment to
vector elements as needed.  The following example (with --c++11 --g++) had
failed an assertion check and now generates valid lowered IL:

  struct A {
    int __attribute__((vector_size(8))) m;
    A(int x) : m{x,x} {};
  };
  A a(1);


10/13/16 [EDGcpfe/17612]
C++14 constexpr: Internal error in find_subobject_for_interpreter_address

In some cases involving the evaluation of a constant object of a class type
with one data member and one base class, the front end aborted with an
internal error in find_subobject_for_interpreter_address (interpret.c).
This is now fixed.


10/12/16 [EDGcpfe/17614]
Microsoft-style std::initializer_list and C++14 constexpr interpreter

The <initializer_list> implementation that ships with the front end includes
a constructor that produces a std::initializer_list object from a pointer to
the underlying array and the length of that array (this is also what GCC and
Clang implementations use).  The front end can also handle an alternative
std::initializer_list constructor which takes a pointer to the same array and
another pointer one position past the last element of that array (this is what
the Microsoft compiler uses; see the entry of 5/30/13 for EDGcpfe/14088).
However, the C++14 interpreter did not correctly handle the latter alternative
(it never produced a constant std::initializer_list object in that case).  That
is now fixed.


10/12/16 [EDGcpfe/17614,EDGcpfe/17726]
C++14 constexpr interpreter and pointers into array constants

If the constexpr interpreter produced a composite value with two pointers into
a common array constant, it sometimes represented those pointers as two
ck_address entries pointing to two distinct ck_aggregate entries, when instead
it should have made the two address constants refer to a single aggregate
constant.  This is now fixed.


10/12/16 [EDGcpfe/17073]
C++-generating back end: pointers to members of lambda closure classes

In C++-generating back end configurations, the front end previously
produced uncompilable code for a pointer-to-member expression in which the
class of the member is a lambda closure class: because the closure class is
unnamed, the qualifier for the member name was generated as an undeclared
temporary name (a name of the form __T12345678).  This has now been fixed;
whenever a variable is declared with the auto specifier to have a lambda
closure class type, a typedef is emitted using a decltype specifier to
declare the temporary name that would be used in a subsequent
pointer-to-member expression.  For example, with --c++11:

  void f() {
    auto l = [] { };
    decltype(&decltype(l)::operator()) pmf;
  }

This is now generated as:

    auto l = [] { }; typedef decltype(l) __T12345678;
    decltype(&__T12345678::operator()) pmf;


10/12/16 [EDGcpfe/17613]
Array binding failure in C++14 constexpr interpreter

The C++14 constexpr interpreter previously failed to handle binding an array
to a reference to array parameter if the reference includes added type
qualifiers.  For example:

  using A = int[2];
  constexpr bool f(A const&) { return true; }
  constexpr bool g() {
    A x = { 1, 2 };
    return f(x);  // The parameter bound to x adds a "const" qualifier.
  }               // Previously, this caused interpretation to fail.
  constexpr bool r = g();  // Previously triggered an error because the call
                           // to g() did not produce a constant.  Now okay.

This is now fixed.


10/11/16 [EDGcpfe/17603]
Abort on certain constexpr evaluations of default member initializers

In some cases, default member initializers involving a std::initializer_list
instance could trigger memory corruption in the C++14 constexpr interpreter,
often leading to aborts.  For example:

  #include <initializer_list>
  typedef std::initializer_list<int const> &&L;
  struct X {
    int x;
    X(): x(1) {}
    L y = { x, 2, 3 };
    L z = { 4, y.begin()[1] };  // Previously could trigger an abort on
  };                            // some platforms.

This is now fixed.


10/11/16 [EDGcpfe/17528]
Predefine __STDC_HOSTED__ in all modes

Previously the __STDC_HOSTED__ macro had only been defined in C99 and later
C modes and C++11 and later C++ modes.  The macro is now defined in all cases
(to the value of the STDC_HOSTED configuration macro).


10/10/16 [EDGcpfe/17482]
Prototyping of library routines used by lowering

Previously some of the library routines invoked by lowering had been declared
in the IL as prototyped routines and some were unprototyped; a change has been
made to make all of the library routines invoked by lowering prototyped (when
MAKE_ALL_FUNCTIONS_UNPROTOTYPED is FALSE) and to add casts when necessary to
coerce arguments to the proper types.


10/10/16 [EDGcpfe/17576]
C++14: Empty class member declarations

In C++14 modes, the front end now silently accepts empty class member
declarations.  In other modes it still elicits a warning or (in strict mode)
an error.  For example:

  struct S { ; };  // Now silently accepted in C++14 mode.


10/10/16 [EDGcpfe/17592]
Spurious constexpr evaluation failure when subtracting null pointer values

The C++14 interpreter previously treated the subtraction of two null pointers
as undefined behavior (due to a misreading of the standard), and failed
constexpr evaluation in such cases.  This is now fixed: Subtracting two null
pointer values now produces a zero result, as required by the standard.


10/10/16 [EDGcpfe/17593]
Spurious constexpr evaluation failure when accessing certain subobjects

The C++14 interpreter keeps track of which parts of an object have been
initialized, and attempting to access an uninitialized part of an object during
constexpr evaluation causes that evaluation to fail (possibly eliciting an
error later on).  A bug in the interpreter caused it to fail to mark subobjects
as initialized in some parts, which in turn could result in spurious errors
(typically with a note "access to uninitialized subobject").  That is now
fixed.


10/7/16  [EDGcpfe/17581]
Unevaluated operands in constant expressions vs overloaded operators

An unevaluated operand of a short-circuiting logical operator (|| or &&)
does not contribute to the determination of whether the expression is
constant or not and thus should not be evaluated.  The front end followed
this rule except when a declaration of a corresponding overloaded operator
is in scope.  In that case, the front end previously unconditionally
evaluated the second operand, even if the first operand is such that the
second will not be evaluated.  This could result in spurious errors.  This
is now fixed.  In the following example, the expression 1 << 1000 cannot
appear in a constant expression because the result is undefined, but the
first operand of && evaluates to false and thus should suppress
consideration of the second operand.  It now does so, even in the presence
of the overloaded operator&& declaration.

  struct A {
     bool operator&& (A const& rhs);
  };
  constexpr bool b = 0 && (1 << 1000);  // Previously an error


10/7/16  [EDGcpfe/17590]
Clang compatibility: __builtin_va_arg missing

Due to the recent changes to builtin functions (see the Changes entry for
EDGcpfe/16431 et al.), the __builtin_va_arg builtin feature was missing
in clang emulation mode.  Now fixed.


10/7/16  [EDGcpfe/17575]
Slight performance tweak

A change has been made to move some code out of get_token to give a slight
increase in performance.


10/6/16  [EDGcpfe/17589]
Abort in interpreter on invalid access to anonymous union member

The C++14 interpreter could abort (e.g., with an internal error in diagnostic
processing) on certain cases involving invalid uses of anonymous union
members.  For example:

  struct A { union { int z = 59 ; } ; 
    union {
      int x;
      long y;
    };
    constexpr A(int i): x(i) {}
    constexpr A(long i): A(y) {} 
    constexpr operator int() {return x;}
    constexpr operator long() {return y;}
  };
  int x[int(A(37)) + long(A(47L))];  // Previously triggered an abort.

This is now fixed (the interpreter now checks that an anonymous union is
initialized before checking whether its active member is correctly accessed).


10/6/16  [EDGcpfe/17573]
Abort in interpreter on invalid code with empty base class

In somewhat complex invalid cases involving a template-dependent empty base
class the front end could abort in the C++14 constexpr interpreter (null
pointer indirection in function extract_value_from_constant).  This is now
fixed.


10/6/16  [EDGcpfe/17583]
Substitution failure during substitution of alias in SFINAE context

A change in 4.11 (see EDGcpfe/16743 on 1/24/16) could result in substitution
failure as a result of an incorrect position being used to determine
the visibility of functions in overload resolution.  Now fixed.  The example
below was accepted (because of an unrelated GNU compatibility feature) in g++
mode with gnu_version >= 40400.

  struct A  { static constexpr bool b = true;  };
  struct B { static constexpr bool b = false; };
  template <template <class...> class TT1, class... T> struct C {
    template <template <class...> class TT2, class = TT2<T...>>
      static A f(int);
    template <template <class...> class>
      static B f(...);
    using X = decltype(f<TT1>(0));
  };
  template <typename T> T&& declval() noexcept;
  template <class T1> using D = decltype(declval<T1>());
  int main() {
    static_assert(C<D, int>::X::b, "");
  }


-------------------------------------------------------------------------------
Version 4.12, October 5, 2016

10/3/16  [EDGcpfe/17216]
Feature test macro refresh

The list of clang and standard feature test macros supported by the front
end has been updated to reflect the latest versions of the relevant
documents: version 4.0 of the clang documentation at
clang.llvm.org/docs/LanguageExtensions.html and WG21 P0096R2 (2016-02-23).


10/3/16  [EDGcpfe/17319]
Repeated elements of constant arrays

In constant expression evaluation, the front end failed to allow for some
cases in which the IL is created with a repeated constant in the
initializer, resulting in incorrect values and/or spurious errors.  Such
cases can arise with arrays of classes with default member initializers.
For example, with --c++11:

  struct A { int i,j; };
  struct X {
    A a = {1,1};
  };
  constexpr X table[2][2] = {{ {} }};
  static_assert(table[1][1].a.i == 1, "");  // Previously element was
                                            // incorrectly set to 0


9/30/16  [EDGcpfe/17535]
GNU C++ compatibility: Conversion of function and exception specifications

Consider the following example:

  void g();
  void g(int);
  void (*pf)() throw(int) = g;

Although the initialization is invalid due to an exception specification
mismatch, GCC does not diagnose it.  The front end now emulates that
behavior in GNU C++ mode by just issuing a warning in cases like these.
The front end already emulated similar GCC behavior in other contexts, but
it accidentally extended that emulation to Clang modes also; that is now
fixed (i.e., the invalid conversions that are accepted in GNU C++ mode are
now treated as errors in Clang mode).


9/30/16  [EDGcpfe/17542]
Abort when testing trivial copyability of a class with a using-declaration

Previously, the front end sometimes aborted with an internal error in
"is_trivially_copyable_type" (types.c) when testing trivial copyability of a
class with a using-declaration for an assignment operator.  For example:

  struct B {};
  struct D: B {
    using B::operator=;
  };
  static_assert(__is_trivial(D), "Unexpected");
    // Previously triggered an internal error.  Now okay.

This is now fixed.


9/29/16  [EDGcpfe/17021]
Deduction failure on pointer-to-member with member class mismatch

Core issue 1153 eliminated the requirement that the member class of a
pointer to member function type be the same as the destination type when
forming a pointer-to-member function.  Instead, the types are checked later
(e.g., in the example below, when the initialization is done).  Previously,
examples like the one below failed in template argument deduction, but
are now accepted.

  class A {};
  struct B : public A {
    template <class T> void f(T);
  };
  int main () {
    void (A::*pmf)(int) = &B::f;
  }


9/29/16  [EDGcpfe/17553]
IL write-read error on scoped enumerator constant used as template argument

In some complex situations, the front end could abort with an IL write-read
error when a scoped enumerator constant was used as a template argument (in
configurations with IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE).  That is now
fixed.


9/28/16  [EDGcpfe/17562]
Internal error on zero-length array string initializer

In GNU C mode, a zero-length array can be declared and initialized with a
string initializer.  This previously triggered an internal error in il.c
("num_array_elements: array with unspecified bound").  For example:

  char x[0] = { "" };  // Previously triggered an internal error.  Now okay.

This is now fixed.


9/27/16  [EDGcpfe/17565]
Spurious warnings about digit separators

The front end previously unconditionally issued a warning when an
apostrophe occurs within a numeric literal and digit separators are not
enabled.  This was true even in text appearing in the unselected branch of
a conditional compilation directive and in C modes, where such apostrophes
should not be considered as a failed attempt to use a C++-14 digit
separator.  This is now fixed.  For example, with --c:

  #if 0
  float f = 0x0'0.0p0;  /* Previously elicited a warning. */
  #endif


9/27/16  [EDGcpfe/17376]
Dependent decltypes and overloaded function template declarations

The front end sometimes failed to distinguish dependent decltype constructs in
overloaded function template declarations.  As a result, it treated a later
declaration as redeclaring a former one, and spurious errors often ensued.
For example:

  template<typename> struct C {};
  template<typename T> C<decltype(T::x)> g() { return 0; }
  template<typename T> C<decltype(T::y)> g() { return 0; }
    // Previously triggered a spurious error claiming that the template
    // has already been defined.  Now accepted (there are two overloaded
    // templates g).

This is now fixed.


9/27/16  [EDGcpfe/17379]
Spurious error on aggregate initialization with default member initializers

In C++14 mode, some braced initializations of aggregate classes with default
member initializers produced a spurious error.  For example:

  template<typename T> struct A { T m = 0; };
  void g() {
    A<int> x{};  // Previously triggered a spurious error in C++14 mode.
  }              // Now okay.

This is now fixed.


9/27/16  [EDGcpfe/17300]
Abort on generic lambda in range-based "for" loop

In C++14 mode, instantiating a generic lambda used in the body for a range-
based "for" loop could trigger an internal error in pop_scope_full (saying
"unexpected curr_object_lifetime for function or block scope") in some
configurations.  For example:

  struct S { template<class F> void f(F p) { p(42); } };
  struct I {
    ~I();
    S operator*() const;
    void operator++();
    bool operator!=(I const&) const;
  };
  struct C {
    I begin(), end();
  };
  void g() {
    for (auto s : C()) s.f([](auto){});
  }

This example previously triggered the abort because S::f instantiates the
generic lambda passed in from within the range-based "for" loop in function g.
This is now fixed.


9/27/16  [EDGcpfe/16554,EDGcpfe/17152,EDGcpfe/17332]
Failure matching template template argument with template parameter pack

In some cases, the front end failed to allow a template template argument
to match a template template parameter.  This occurred when the template
template argument had multiple template parameters that were matched with
a template parameter pack of the template template parameter.  Now fixed.

  template <char, template <class> class, template <class> class> struct A {};
  template <template <char, template <class> class ...> class> struct B {};
  B<A> b;
 

9/26/16  [EDGcpfe/17538]
GNU C++ compatibility: spurious error on static data member initializer

Version 4.11 included a g++-mode change to only instantiate a static data
member of class template if it used.  This change could result in a spurious
error during the caching of the initializer because a "<" was incorrectly
considered to start a template argument list in some cases.  Now fixed.

  template <typename T> struct A {
    static const int i = 1;
  };
  template <typename T> struct B {
    static const bool b = A<T>::i < A<T>::i;
  };


9/23/16  [EDGcpfe/17511]
Constructor initializers for virtual bases of abstract base classes

The front end no longer issues an error if the constructor for an abstract
class fails to provide an initializer for a virtual base class that has no
default constructor.

  struct V { V(int); };
  struct D: virtual V {
    D() {}  // Previously an error.  Now okay.
    virtual void f() = 0;
  };


9/23/16  [EDGcpfe/17289]
Problems with variadic partial specialization declared outside of its class

A variadic member class template partial specialization that was defined
outside of its parent class was not handled properly.  This could result
in spurious errors or an internal error (in find_placeholder_arg_for_pack).
Now fixed.

  template <typename T> struct A {};
  template <typename T> struct B {
    template <template <typename...> class TT, typename... Ts> struct C;
  };
  template <typename T>
  template <template <typename...> class TT, typename... Ts>
  struct B<T>::C<TT, int, Ts...> {
    const static int value = 1;
  };
  int i = B<int>::template C<A, int, char>::value;


9/23/16  [EDGcpfe/17339]
Spurious error on pack reference in lambda declarator

A spurious error could be issued on a lambda declarator (for a generic or
non-generic lambda) that contained a pack expansion in modes where
generic lambdas are enabled.  Now fixed.

9/23/16  [EDGcpfe/17560]
Clang compatibility: __builtin_convertvector

In Clang modes the front end now supports the builtin vector operator
__builtin_convertvector (GNU_VECTOR_TYPES_ALLOWED must be configured TRUE).


9/22/16  [EDGcpfe/17417]
Overload resolution and copy constructor templates

The changes for EDGcpfe/16793 tweaked the overload resolution algorithm to
avoid substituting a copy assignment template candidate if the front end can
determine early that a nontemplate candidate will always be a better match
than any potential candidate template.  Those changes have been extended
slightly to handle cases involving move assignment operators.  For example:

  template<class T> struct S {
    typedef typename T::X Type;
  };
  struct X {
    X& operator=(X&&);
    template<class T> typename S<T>::Type operator=(T &&);
  };
  struct Y {
    X x;
  };

Previously, the generation of a move assignment operator for Y resulted in an
error due to the substitution of the member template.  Now this case is
accepted.  Furthermore, similar changes have now been made to the algorithm
that selects a copy constructor.  For example:

  template<class T> struct S {
    typedef typename T::X Type;
  };
  struct X {
    X(X const&);
    template<class T> X(T const&, typename S<T>::Type = 0);
  };
  struct Y {
    X x;
  };

Previously, this example triggered an error while considering the constructors
of X needed to generate the copy constructor of Y.  The error occurred while
substituting the constructor template of X.  The error is now avoided because
the nontemplate copy constructor of X is recognized as being a better match
without substituting the member template.


9/22/16  [EDGcpfe/17358]
Spurious error on nested declarator in template static data member definition

Version 4.11 introduced a regression that could cause a spurious error
on the definition of a static data member of a nested class of a class
template when the definition made use of a nested declarator.  Now fixed.

  template <typename T> struct A {
    struct B {
      void f() {}
    };
  };
  template <typename T> struct C {
    static void (A<T>::B::*bfp)();
  };
  template <typename T> void (A<T>::B::*(C<T>::bfp))();


9/22/16  [EDGcpfe/17517]
IL write-read error on type declared in function template declaration

In configurations with the configuration macros GENERATE_SOURCE_SEQUENCE_LISTS
and IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE, the front end could abort with
an IL write-read error (an internal error) when a class is first declared in a
function template declaration but parsing of function templates is disabled.
For example (in default C++03 mode):

  template<class V> void g(struct C*) {}
    // C is first declared in this function template.  Previously,
    // this could result in an internal error in some configurations.

This is now fixed.


9/21/16  [EDGcpfe/17506,EDGcpfe/17544]
GNU compatibility: "target" attributes and function multiversioning

Changes have been made to update the way the "target" attribute/pragma is
handled in GNU emulation mode.  GNU and clang have added a large number of
"target" attributes in their system headers, so any unknown "target" attribute
in a system header is silently accepted.  For unknown "target" attributes
outside of a system header, a warning is generated in C mode and a
discretionary error is generated in C++ mode.

For configurations that support function multiversioning (see the Changes entry
for EDGcpfe/14759), ten new "target" ISA architectures are supported: sse4,
sse4a, aes, pclmul, bmi, fma4, xop, fma, bmi2, and avx512f.  These, in addition
to the ones already supported, appear to be the only target architectures that
are used by GCC when it creates a resolver function.  If lowering needs to
create a resolver function and a target-specific routine has an unknown
"target" attribute (i.e., one that is not in the list of known attributes), a
discretionary error is emitted and that routine is not considered by the
resulting resolver function.

A couple of other bugs were also fixed: spaces in "target" attribute strings
are now skipped in clang mode and the handling of the a_mv_target_bitset type
has been updated (so that the type can grow to 64 bits if 32 bits is not
enough).


9/21/16  [EDGcpfe/17551]
Incorrect symbol variant used for enum templates

An incorrect symbol variant was used for enum templates in configurations with
EXTRA_SOURCE_POSITIONS_IN_IL (although the cases still worked properly because
the correct memory was accessed).  Those references have been corrected.


9/21/16  [EDGcpfe/17550]
Incorrect symbol variant used for variable templates

In a few places, the incorrect symbol variant was used when processing
a variable template (although the cases still worked properly because
the correct memory was accessed).  Those references have been corrected.


9/20/16  [EDGcpfe/17543]
Microsoft compatibility: Unused default member initializers

Microsoft compilers treat default member initializers (a C++11 feature) that
are not actually used in the translation unit in a way that prevents certain
template instantiations.  For example:

  struct I;
  
  template<class T> struct M {
      M(int) { T i; }
  };
  
  struct S {
    S();
    virtual ~S();
    M<I> m{1};  // Normally an error.  Now accepted with the option
  };            // --set_flag lazy_field_initializers.

Ordinarily, the constructor of M<I> is instantiated when the initializer for
S::m is parsed; that in turn triggers an error because the type I of the local
variable i is incomplete.  Microsoft compilers, however, do not issue such a
diagnostic.  To approximate that behavior, the front end now delays parsing of
the initializer until it is actually used if the global variable
always_delay_field_initializer_processing is set to TRUE (which can be achieved
with the command-line option "--set_flag lazy_field_initializers").  Doing so
means that the IL will have no representation of the initializer, however,
which in turn implies that the C++-generating back end cannot render it.


9/20/16  [EDGcpfe/17546]
Precompiled header created when no files were included

One of the factors involved in the decision to create a PCH file is the
number of declarations seen.  Predefined entities such as macros and
types could cause a PCH to be created even if no files were included.
An explicit test for the presence of included files is now done.


9/20/16  [EDGcpfe/15635]
C++11: Exception specifications for standard allocation/deallocation functions

In C++03, the default operator new/operator new[] includes an exception
specification "throw(std::bad_alloc)".  In C++11, however, the standard dropped
those exception specifications.  Similarly, other allocation and deallocation
functions went from a "throw()" exception specification to a "noexcept"
specification.  The <new> header shipped with the front end (for demonstration
purposes; implemented in file "new.stdh") now reflects that distinction and
the actual implementation of the operators now reflects the C++11 semantics
(which are nearly indistinguishable from the C++03 semantics).


9/20/16  [EDGcpfe/17536]
Microsoft compatibility: p->x in constant expressions

In Microsoft mode, an expression like p->x may be constant-folded if x is a
constant-valued member (e.g., an enumerator constant); see the entry of 1/5/05.
This feature, however, was accidentally disabled in Microsoft modes that enable
the constexpr feature (e.g., when microsoft_version >= 1900).  That is now
fixed.


9/19/16  [EDGcpfe/17490,EDGcpfe/17541]
GNU compatibility: assertion failures in walk_parents with abi_tag attribute

A couple of issues that ended up failing an assertion check in walk_parents
as a result of using the abi_tag attribute have been fixed.  For example
(with --gnu_version 60100):

  inline namespace N __attribute__((abi_tag)) {}
  template <class T> T x;

or:

  inline namespace N __attribute__((abi_tag)) {}
  struct A {
    A(int i);
  };
  const A& a = A(77); 


9/16/16  [EDGcpfe/17537]
Microsoft compatibility: (void*)N as case labels

For several years the front end has accepted case labels like "(void*)1" in
Microsoft mode (see the entry of 12/9/01).  However, that capability was
accidentally dropped in Microsoft modes that enable the C++11 "constexpr"
feature (including, by default, Microsoft modes with microsoft_version larger
than 1900).  The capability has now been restored for all Microsoft modes.


9/16/16  [EDGcpfe/16431,EDGcpfe/16852,EDGcpfe/16897,EDGcpfe/17135,
          EDGcpfe/17142,EDGcpfe/17323,EDGcpfe/17527]
Restructure the handling of builtin functions

Previously, the handling of the large majority of GCC builtin functions
(and more recently clang and Microsoft) had largely been a manual process that
relied on accurate documentation.  As thousands of builtin functions have been
recently added, that task became too unwieldy.

A set of tools has been developed to use the plugin feature of GCC and clang
to automatically extract the signatures of builtin functions from those
compilers.  The result of this process is the new file: builtin_defs.h.  This
file contains information about each builtin, including its signature(s) and
the various modes in which it is valid.  This should allow the front end to
keep pace with future GCC and clang releases.  Microsoft builtin functions are
also represented in the file (though the input for Microsoft builtin functions
remains a manual procedure).

Note that the plugin architecture is only available in GCC 4.5.0 and later, so
the tools obtain builtin function signatures for earlier versions from the EDG
front end in GCC emulation mode (which also provides for backward
compatibility).

Along with automatically generating the builtin function signature information,
there are two other significant changes: declarations for builtin functions are
now created only when they are referenced, and the types of the builtin
functions themselves are stored in strings as C declarations and parsed by the
front end to generate a routine type.  Lazily loading builtin functions can
result in considerable performances gain in some cases (and keeps the IL
smaller).

To make the builtin function signatures more concise, three new tokens have
been added: __edg_size_type__, __edg_ptrdiff_type__, and __edg_vector_type__,
which represent size_t, ptrdiff_t, and a shorthand for
__attribute__((vector_size)), respectively.

Customers who want to add their own builtin functions should not modify
builtin_defs.h; rather they should modify builtin_user_table in sys_predef.h
(see the comment at the beginning of sys_predef.h for more information).

As part of these changes, the configuration macros
GNU_BUILTIN_IA32_VECTOR_FUNCTIONS_ALLOWED and
GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED have been removed (the builtins enabled by
those macros are now always enabled when BUILTIN_FUNCTIONS_ENABLED is TRUE --
assuming other conditions are met such as GNU_VECTOR_TYPES being enabled).

The builtin function signatures are current through GCC 6.2.0 and clang 3.9.0.


9/16/16  [EDGcpfe/16420]
Multiple default union member initializers via anonymous unions

The front end previously failed to diagnose unions with multiple default
member initializers if one of the members was declared within an anonymous
union.  Having multiple initializers in the IL could then cause expression
folding to abort later on.  For example (C++11 mode):

  union U {
    int i = 1;
    constexpr U() {}
    union { float f = 2.0; };  // Previously not diagnosed.  Now an error.
  };
  float r = U().f;  // Previously triggered an abort in folding.c.

This is now fixed.


9/15/16  [EDGcpfe/17290]
Rescanning noexcept operands with constexpr function calls

When instantiating a function template whose declaration involves a noexcept
operator, that operator's operand must be "rescanned".  Previously, that
rescanning did not correctly handle foldable calls to constexpr functions,
which in turn could result in spurious errors.  For example:

  template<bool> struct S;
  template<> struct S<true> { using Type = bool; };
  template<typename T> constexpr int f(T p) { return p; }
  template<typename T> constexpr typename S<noexcept(f(42))>::Type g() {
    return true;
  }
  static_assert(g<void>(), "Unexpected");

This is now fixed.


9/15/16  [EDGcpfe/17385]
GNU C compatibility: Negation of constant cast to pointer type

In standard C, an expression like "!(void*)0" is not a valid integral
constant-expression (because such expressions cannot involve casts to
pointer types).  In GNU C mode, however, such expressions are now accepted
in contexts expecting an integral constant-expression.  E.g., in GNU C11:

  _Static_assert(!(void*)0, "Okay in GNU C11");


9/15/16  [EDGcpfe/17395]
GNU compatibility: decltype(auto) and type qualifiers

Ordinarily, a decltype(auto) specifier in a variable declaration cannot have
added type qualifiers.  GCC, however, does accept them and we now emulate that
behavior in GNU C++14 mode.  For example:

  decltype(auto) const x = 3;  // Now accepted in GNU C++14 mode.


9/15/16  [EDGcpfe/17530]
Build issue when GENERATE_EH_TABLES is FALSE

lower_init.c had failed to build in configurations where GENERATE_EH_TABLES is
FALSE and DO_UNORDERED_EH_PROCESSING is TRUE.  Now fixed.


9/14/16  [EDGcpfe/16846]
C++-generating back end, GNU compatibility: this-> in decltype expressions

Until very recently, g++ issued a spurious error message in some cases when
the operand of decltype is a member function call that explicitly specifies
this->.  The C++-generating back end has now been modified to work around
this g++ bug by suppressing this-> in such contexts when
gcc_is_generated_code_target is TRUE and gnu_target_version_number is less
than 70000.  For example, with --parse --no_defer --gnu_version=40802 --c++11:

  struct S {
    char f() const { return 0; }
    template<typename T>
    auto g() const -> decltype(f()) {  // Previously generated as
                                       // decltype(this->f())
      return 0;
    }
  };


9/14/16  [EDGcpfe/17389]
Error on consecutive left square brackets that don't introduce an attribute

The C++ standard is clear that the occurrence of two left brackets must
introduce an attribute list, but previously that rule was not enforced
in some cases.  The example below now gets a discretionary error in
configurations where C++ standard attributes are allowed (e.g., --c++11):

  void f() {
    int a[1];
    a[[]{return 0;}()] = 0;   // previously accepted, now an error
  }


9/13/16  [EDGcpfe/17524]
Microsoft compatibility: default Microsoft version changed

The default Microsoft version number (specified by DEFAULT_MICROSOFT_VERSION)
is now 1900.  This corresponds to the value of _MSC_VER used with Visual
C++ 2015.  Note that newer versions of Visual Studio implement features
from C++11 and C++14, so the change in DEFAULT_MICROSOFT_VERSION means that
most C++11 features and some C++14 features are now enabled in Microsoft
mode when our DEFAULT_MICROSOFT_VERSION value is used.


9/13/16  [EDGcpfe/17524]
GNU compatibility: default GNU version changed

The default GNU version number (specified by DEFAULT_GNU_VERSION) is now
40800.  This corresponds to gcc/g++ version 4.8.0.


9/12/16  [EDGcpfe/17512]
Reused temporary values in constant expressions

The front end previously reported a spurious "must have a constant value"
error when a reused temporary value appears in a context requiring a
constant expression.  (Such reused temporaries arise in uses of initializer
lists, Microsoft properties, and the GNU abbreviated conditional operator.)
This is now fixed.  For example, with --microsoft_version=1900:

  namespace std {
  template<class _Elem> struct initializer_list {
    constexpr initializer_list(const _Elem *_First_arg,
                               const _Elem *_Last_arg) noexcept
          : _First(_First_arg), _Last(_Last_arg) { }
    constexpr const _Elem *begin() const noexcept {
      return (_First);
    }
    const _Elem *_First;
    const _Elem *_Last;
  };
  }
  struct Y {
    int i;
    int j;
    constexpr Y(std::initializer_list<int> il)
          : i(il.begin()[0]), j(il.begin()[1]) { }
  };
  int main() {
    constexpr Y y{3, 1};  // Previously a spurious error
  }


9/12/16  [EDGcpfe/16900]
constexpr copy construction from value-initialized members

The front end previously reported a spurious "must have a constant value"
error for cases in which bitwise copy initialization is required from a
value-initialized class member in a context requiring a constant
expression.  This is now fixed.  For example, with --c++11:

  template <typename... Ts> struct A;
  template <> struct A<> {
    constexpr A() { }
    constexpr A(const A&) { }
  };
  template <typename First, typename... Rest>
  struct A<First, Rest...> : A<Rest...> {
    typedef A<Rest...> Base;
    constexpr A() : Base(), elem() { }
    First elem;
  };
  constexpr A<int, int, int> t1;
  constexpr A<int, int, int> t2(t1);  // Previously a spurious error


9/9/16   [EDGcpfe/17522]
Deduction failure with template alias that refers to nondeduced context

Template argument deduction did not correctly handle an alias template
instance that referred to a type that should be treated as a nondeduced
context.  This could result in a spurious deduction failure.  Now fixed.

  template <typename T> struct A { typedef int type; };
  template <typename U> using B = typename A<U>::type;
  template <typename T> void f(const B<T>& b, T t) {}
  template void f(const int& b, int t);  // formerly rejected


9/7/16   [EDGcpfe/17012]
Lookup of conversion functions with virtual base classes

Consider:

  struct V { operator int () const; };
  struct B: virtual V { operator int () const; };
  struct D: B, virtual V {};
  int r = D();  // Previously ambiguous.  Now okay.

Previously, the front end considered the conversion functions in both direct
base classes of D (B and V) viable candidates for conversion and, because both
candidates provide equally good conversions, an ambiguity error ensued.
However, the standard actually specifies that "B::operator int" hides
"V::operator int", which avoids the ambiguity.  The front end now implements
that rule.


9/6/16   [EDGcpfe/17404]
Bad result for decltype applied to a call producing a reference to function

The front end did not correctly determine the result type of a decltype
construct whose operand is a call producing a reference to a function; it
produced a function type instead of a reference to function type.  For
example:

  typedef void F();
  F &g();
  decltype(g()) rf = g();  // Previously elicited a spurious error.
                           // Now okay.

This is now fixed.


9/6/16   [EDGcpfe/17392]
Variable template default template argument issues

If a variable template was first declared with a default template argument
and was later redeclared, the default argument was not considered when
scanning the template argument list.  This could result in spurious errors.
In addition, an internal error (in form_template_arg_info) could result if
a diagnostic was issued that involved a variable template instance that
was produced when a "too few arguments" error was (incorrectly) issued.
Now fixed.

  template <int N, class T = int> extern T x;
  template <int N, class T> T x = T();
  int i = x<33>;


9/4/16   [EDGcpfe/17398]
Spurious error on variable template partial specialization

A spurious error could be issued on a partial specialization of a variable
template that is a member of a non-template class.  Now fixed.

  struct X {
   template <class U, class T> static T x;
  };
  template <class T> T X::x<T, T> = T(1);


9/2/16   [EDGcpfe/16241,EDGcpfe/17453,EDGcpfe/17474]
Exception specifications and defaulted special member functions

Previously, declaring a defaulted special member function with an exception
specification that does not match that of a corresponding generated special
member always resulted in an error.  Now, in C++14 mode (or GNU C++11 mode),
when the special member is defaulted in the class definition, the member
becomes deleted.  For example:

  struct S {
    ~S() throw(int) = default;  // Previously an error.  Now accepted in
  };                            // C++14 mode.

This change reflects the resolution of Core issue 1778.


9/2/16   [EDGcpfe/17503]
Bit fields in IL entries

Bit fields in IL entries are always declared with type a_bit_field.  When
building the front end with a Microsoft compiler a_bit_field was previously
a typedef for "unsigned char" to allow for more compact layouts of some IL
entries.  That is, however, not always sufficient to hold bit fields
representing type qualifier sets (and, theoretically, large name
linkage sets), particularly with the recent addition of the C11 _Atomic
qualifier and the Clang nullability qualifiers.  a_bit_field is now always
a typedef for "unsigned int".  To mitigate the potential increase in memory
usage by front ends built with a Microsoft compiler, a few changes were made
to some types (in particular, the "kind" field of an_expr_node is now a bit
field).


9/2/16   [EDGcpfe/17494]
Spurious error on capture of constant-valued variable used as an lvalue

The front end previously issued a spurious error when attempting to capture a
constant-valued variable used as an lvalue.  For example:

  int main() {
    int const OK = 0;
    return [=]{ return *&OK; }();  // Previously triggered a spurious error.
  }                                // Now okay.

This is now fixed.


8/25/16  [EDGcpfe/17455]
Microsoft compatibility: addition of "non-permissive" Microsoft mode

New command-line options, --[no_]ms_permissive, have been added to emulate
Microsoft's /permissive[-] option.  These options apply to all Microsoft modes
(i.e., C, C++, C++/CLI, and C++/CX).  A new configuration macro,
DEFAULT_MS_PERMISSIVE, has been added to control the default behavior.
When --no_ms_permissive mode is used:
  - Standard dependent name lookup is done (e.g., unqualified lookup
    ignores dependent base classes, 2-phase lookup is done, the implicit
    typename feature is disabled) 
  - nonclass prototype instantiations are done
  - Names declared only in friend declarations are only visible to ADL
  - The special Microsoft nonreal base class lookup is disabled
  - "default" is not allowed as an identifier
  - Only one member of a union can be initialized in a constructor
    initializer of that union
  - The anachronism that allows binding a reference to nonconst to a class
    rvalue is disabled


8/18/16  [EDGcpfe/17471]
Deduced reference return type with array/function lvalue expression

The front end incorrectly applied the array-to-pointer and
function-to-pointer conversions to the expression in a return statement
when deducing the return type for a function returning a reference type.
This is now fixed.  For example, with --c++14:

  auto & f() {
    return "";   // Previously a "must be an lvalue" error, now okay
  }
  const char (&r)[1] = f();   // Previously a type mismatch, now okay


8/15/16  [EDGcpfe/17469]
Missing ak_may_alias case

The ak_may_alias case was missing from a switch statement in disp_attribute
which could cause "** BAD KIND **" to be displayed rather than "may_alias"
in edgcpdisp output.


8/16/16  [EDGcpfe/17013]
Spurious access error on out-of-class definition of local nested class

A spurious access error could be issued if a nested class of a local class
was defined outside of its parent class.  Now fixed.

  int main() {
    class A {
      class B;
    };
    class A::B { };
  }


8/15/16  [EDGcpfe/17388]
GNU compatibility: Multiple _Alignas alignment specifiers

The C11 standard dictates that when multiple _Alignas alignment specifiers
are present, the strictest alignment is used.  That had been true except when
gnu_version < 40800.  Now fixed.  For example (with --c11 --gnu_version 40700):

  long _Alignas(4) _Alignas(8) _Alignas(1) x;
  _Static_assert(__alignof(x) == 8, "");


8/12/16  [EDGcpfe/17158]
GCC and Clang compatibility: Uninitialized variables in constexpr function

In Clang and GNU C++14 modes, the front end now accepts declarations of
uninitialized variables of empty class type in constexpr functions.  For
example:

  struct S {};
  constexpr void g() {
    S s;  // Error in default C++14 mode; accepted in GNU/Clang C++14 mode.
  }


8/11/16  [EDGcpfe/17463]
Microsoft compatibility: template argument list on primary template declaration

A template argument list is now allowed on a redeclaration of a primary
class template in Microsoft mode when microsoft_version <= 1600.  A
warning is issued.

  template <class T> struct A;
  template <class T> struct A<T> {};


8/10/16  [EDGcpfe/17461]
ELF visibility attribute and implicit class template instantiations

In GNU C++ modes in configurations with GNU_VISIBILITY_ATTRIBUTE_ALLOWED set
to TRUE, the front end previously failed to apply the "visibility" attribute
of an enclosing namespace to the implicit instances of a class template.
For example:

  namespace N __attribute((visibility("hidden"))) {
    template<typename T> struct S { ~S(); };
    template<typename T> S<T>::~S() {}
  }
  S<int> si;  // S<int>::~S() was previously not given "hidden" visibility;
              // now it is.

This is now fixed.


8/9/16   [EDGcpfe/17432]
Unbounded loop in C++14 constexpr interpreter

The C++14 constexpr sometimes got stuck in an unbounded loop in the C++14
constexpr interpreter (specifically, in function translate_interpreter_offset).
The following example triggered the bug:

  template<int...> struct S {};
  template<int> struct L {
    double v;
    constexpr L(): v() {}
  };
  template<typename, typename ...Ts> struct U;
  template<int... Is, typename ...Ts> struct U<S<Is...>, Ts...>: L<Is>... {};
  template<typename> struct X {
    U<S<0>, double> x;
    constexpr X(double) {}
  };
  constexpr double const& val(X<double> const &p) {
    return ((L<0> const&)(p.x)).v;
  }
  void g() {
    constexpr X<double> xd(1.0);
  }
  double h() {
    constexpr X<double> xd(2.0);
    return val(xd);
  }

The problem was caused by the interpreter treating fields added by IL lowering
(to represent base class subobjects) as if they were user-declared fields.
This is now fixed.


8/9/16   [EDGcpfe/17195]
Base-class casts in constant expressions

The changes for EDGcpfe/17117 (in version 4.11) introduced a regression in
which the front end reported spurious errors when a derived class glvalue
is cast to a base class prvalue.  This is now fixed.  For example, with
--c++11:

  struct base {
    constexpr base(int l) {}
    constexpr base() {}
  };
  struct derived : public base {
    constexpr derived() {}
    constexpr derived(const derived& d) : base(d) {}
  };
  constexpr derived s;
  constexpr derived t(s);  // Previously a spurious "must be constant" error


8/8/16   [EDGcpfe/17051]
GNU compatibility: Late template overload resolution tie-breaker

Overload resolution includes a tie-breaker rule that prefers non-template
functions over template functions.  That rule applies very late in the
overload resolution process, but a long time ago it applied slightly earlier
and GCC implemented the earlier rule for a long time (see the entry of
12/22/04): We therefore previously emulated GCC in this regard for all values
of gnu_version (in GNU mode).  Now, we only emulate it when gnu_version is
less than 40700.  Also, the GCC behavior was previously accidentally enabled
in Clang mode; that is now no longer the case.  Here is an example where this
change is observable (C++11 mode):

  struct S {
    template <class T1> operator T1() { return 0; }
    operator int() = delete;
  };
  int main() {
    S s;
    return (char)s;  // Previously always an error in GNU C++11 mode.
  }                  // Now accepted when gnu_version >= 40700.

In this example, early versions of GCC discard the member template early,
which results in the deleted conversion function being selected and an error
being issued.  The front end now only emulates that behavior when gnu_version
is less than 40700.


8/5/16   [EDGcpfe/17050]
User-defined conversions for array bounds

With the C++11 constexpr feature, an array bound can be obtained through a
user-defined conversion from a class type.  In C++11, obtaining an array
bound from an expression involves a "converted constant expression" (this is
a specific term from the C++11 standard) with a destination type of size_t.
The front end previously only retained the "conversion to size_t" part,
ignoring constraints implied by the "converted constant expression" part.
In particular, conversions from floating-point types should not be considered.
For example, assuming size_t is unsigned long:

  struct S {
    constexpr S() {};
    constexpr operator float() const { return 1.0; }
    constexpr operator bool() const { return true; }
  };
  float x[S()];  // Previously ambiguous.  Now okay.

Previously, both conversion operators were considered valid, equally-good
matches to produce an array bound of type size_t; an ambiguous conversion
error was emitted.  Now, the "operator float" candidate is discarded since a
float-to-size_t conversion is not permitted in this context; "operator bool"
is therefore successfully selected.


8/4/16   [EDGcpfe/17283]
GNU/clang C++ compatibility: imaginary vs user-defined literals

In g++ and clang modes in which user-defined literals are enabled, numeric
literals with suffixes "i", "il", and "if" were previously treated as
imaginary literals.  They are now parsed as user-defined literals, matching
the behavior of g++ and clang.  For example:

  void * operator "" il(long double ld) { return nullptr; }
  void *p = 12.34il;   // Previously treated as imaginary literal, eliciting
                       // an error; now a user-defined literal with no error


8/4/16   [EDGcpfe/17418]
Abort with constexpr function template as nontype template argument

In C++11 modes, the front end could abort with a segfault (in
copy_template_param_expr_as_rvalue) when an invocation of a constexpr
function function template appears as a nontype template argument and the
return value of the function involves a template parameter of the constexpr
function template.  This is now fixed.  For example:

  template <int N> struct S { };
  constexpr int g(int N) {
    return N + 1;
  }
  template <int N> S<g(N)> f() {   // S<g(N)> previously caused a segfault
    return {};
  }
  auto x = f<1>();


8/4/16   [EDGcpfe/17447]
GNU/Microsoft compatibility: Using-declarations and extern "C" functions

In GNU and Microsoft modes, matching extern "C" declarations in different
namespaces are not always treated as declaring the same entity.  See for
example the entries of 10/6/99 (Microsoft mode) and 7/28/04 (GNU mode).
When two such entities are brought together with a using-declaration, a
reference to these entities produced an ambiguity error.  For example:

  namespace N {
    extern "C" int c();
  }
  extern "C" int cf();
  using N::cf;
  int r = N::cf();  // Previously ambiguous in GNU and Microsoft mode.
                    // Now okay.

Now, the ambiguity is avoided by not having the using-declaration import an
extern "C" declaration matching one already present in the scope.


8/4/16   [EDGcpfe/17202]
C++14-mode abort on variable with an initializer that references itself

In C++14 mode, the front end sometimes aborted with an internal error in
extract_value_from_constant (interpret.c) when processing the initializer for
a constexpr variable that references the variable itself.  For example:

  constexpr int g(int const&) { return 0; }
  constexpr int i = g(i);  // Previously triggered an internal error.
                           // Now okay.

This is now fixed.


8/4/16   [EDGcpfe/17202]
Spurious failure to fold copying of literal object in C++14 interpreter

In C++14 mode, the front end sometimes failed to fold the copying of a literal
object produced by another constexpr call.  For example:

  struct X { constexpr X(int const&) {} };
  struct Y {
    constexpr Y(X const &x0): x(x0) {}
    X x;
  };
  constexpr X mx() { return 0; }
  constexpr Y my() { return mx(); }
  constexpr Y y = my();

Here the call to my was considered non-constant because the object produced by
the call to mx was incorrectly treated as uninitialized.  This is now fixed.


8/4/16   [EDGcpfe/17324,EDGcpfe/17333]
Internal error folding type traits in deferred-access contexts

An internal error could occur (in record_access_error) if certain type
trait operations were folded in contexts in which access checking was
being deferred.  Now fixed.

  class A {
    operator int();
  };
  bool b = __is_convertible_to(A, int);


8/3/16   [EDGcpfe/17340]
GNU/Clang compatibility: Folding of __builtin_signbit

In GNU and Clang modes the front end now folds calls to __builtin_signbit (and
__builtin_signbitf and __builtin_signbitl) for constant operands.  (Like Clang,
but unlike GCC, the front end will not fold those functions if the operand is
"not a number".)  For example:

  static_assert(__builtin_signbit(-1.0), "Unexpected");
    // Now accepted in GNU and Clang C++11 modes.


8/3/16   [EDGcpfe/17285]
Microsoft compatibility: pack expansion in nontype template default argument

In Microsoft mode, a spurious error was issued if a member template of a
variadic class template used an enclosing template parameter pack in a
default argument for a nontype template parameter.  Now fixed.

  template <typename... Args> struct A {
    template <int i = sizeof...(Args)> static void f() {}
  };
  int main() {
    A<int, int>::f<>();
  }


8/3/16   [EDGcpfe/16825]
Microsoft compatibility: __if_exists not allowed after access specification

In C++-generating back end versions, an __if_exists or __if_not_exists
directive was not allowed immediately following an access specification.
Now fixed.

  template <class T> class A : T {
  public:
    __if_not_exists(B) { int a; }
  };


8/2/16   [EDGcpfe/17316]
Spurious error on variadic constructor called with same type as class

A spurious error was issued if a variadic constructor was called with
more than one argument, and the first argument had the same type as the
class of which the constructor was a member.  Now fixed.

  struct A {
    template<typename... Args> A(Args... args);
  };
  int main() {
    A a;
    A a2(a, a);
  }


8/2/16   [EDGcpfe/17270]
Microsoft compatibility: class template used in same-named default argument

A spurious "may not have a template argument list" error was issued in
Microsoft mode if a class template was used in a default template argument
for a type template parameter with the same name as the class template.
Now fixed.

  template <class T> struct A;
  template <class T, typename A = A<T> > class B;


8/2/16   [EDGcpfe/17336]
Microsoft compatibility: abort on variable template with default argument

In Microsoft mode, default template arguments are not scanned until needed.
This processing did not work properly for variable templates and could
result in an abort (in delayed_scan_of_template_param_default_arg).  Now
fixed.

  template <int = 0> int x = 0;
  int i = x<>;


8/2/16   [EDGcpfe/17434]
GNU/Clang/Microsoft compatibility: explicit instantiation via derived class

In g++, Clang, and Microsoft mode a class can now be explicitly instantiated
using a class name inherited from a base class.

  class A {
    template <class X> class B {};
  };
  class C : A {};
  template class C::B<C>;  // should be "A::B<C>"


8/1/16   [EDGcpfe/17428]
Extra braces on singleton expression for aggregate initializer

Consider the following example:

  struct S { int i, j; } x;
  S ax[] = { { x } };  // Previously an error.  Now accepted.

Previously, this was rejected in C++11 mode because the outer level of braces
were matched to the array type and the inner braces were matched to type S (an
aggregate class type).  Now, per the C++11 standard, it is accepted and the
construct "{ x }" is treated as a single initializer for ax[0] because it is a
braced singleton expression with a class type that matches the type of ax[0].


8/1/16   [EDGcpfe/17274]
C++-generating back end: use of dependent expression in enumerator value

In C++-generating back end configurations in which code is generated from
the prototype instantiation IL, the front end aborted with a segfault in
gen_enum_definition when the value of an enumerator was specified using
a dependent expression.  This is now fixed.  For example, with --c++11:

  constexpr int f(int x, int p = 0) {
    return x > 1 ? x : p;
  }
  template<int nt> struct S {
    enum { x = f(nt) };   // Previously caused a segfault
  };


7/29/16  [EDGcpfe/17054]
Constant comparison of addresses for equality

The front end previously reported a spurious error when constant addresses
are compared for equality in a context requiring a constant expression.
This is now fixed.  For example, with --c++11:

  int i1 = 1;
  int i2 = 2;
  constexpr int *pi1 = &i1;
  constexpr int *pi2 = &i2;
  static_assert(&i1 != &i2, "");   // Previously an error, now okay
  static_assert(pi1 != pi2, "");   // Previously an error, now okay


7/29/16  [EDGcpfe/17093]
Spurious template template argument mismatch

In some cases, the substitution of a template argument list of a template
template parameter with a variadic template parameter (e.g., TT<int> in
the example below) would result in a substitution failure if the template
template argument was a non-variadic class template (C in the example
below).  Now fixed.

  template <typename T1, typename T2> struct A {
    static constexpr bool value = true;
  };
  template <bool b_val, typename T = void> struct B { typedef T type; };
  template <typename R> struct C { };  // Worked if R was pack
  template <template <class ...> class TT> using D = A<C<int>, TT<int>>;
  template <template <typename ...> class TT, typename ... Args>
  typename B<D<TT>::value>::type f(void);
  int main() {
    f<C>();
  }


7/29/16  [EDGcpfe/17056]
Overloaded literal operator templates

The front end previously did not correctly handle overloaded literal operator
templates (reporting an ambiguity in all cases).  For example:

  template<bool, typename = void> struct enable_if {};
  template<typename T> struct enable_if<true, T> { typedef T type; };
  template <char... cs>
    typename enable_if<sizeof...(cs) == 1, int>::type operator""X();
  template <char... cs>
    typename enable_if<sizeof...(cs) >= 2, int>::type operator""X();
  int r = 42X;  // Previously triggered a spurious error.  Now okay.

This is now fixed.


7/29/16  [EDGcpfe/13555,EDGcpfe/17041]
Core issue 1423, conversion of std::nullptr_t to bool

The resolution of core issue 1423 requires that the implicit conversion of
a prvalue of type std::nullptr_t to bool be allowed only in
direct-initialization contexts; previously such conversions were also
permitted in copy-initialization.  The front end now implements this
restriction.  For example, with --c++11:

  bool b0 = nullptr;   // No longer permitted
  bool b1{nullptr};    // Still allowed


7/29/16  [EDGcpfe/16929]
constexpr reference cast to same type

The front end previously issued a spurious error for a cast of a constant
lvalue to a reference to the same type that appeared in a context requiring
a constant expression.  This is now fixed.  For example, with --c++11:

  constexpr int i = 2;
  constexpr int j = static_cast<const int&>(i);  // Previously an error,
                                                 // now okay


7/27/16  [EDGcpfe/17008]
Access error on explicit specialization of a class template

An access error was reported on an attempt to explicitly specialize
an instance of a non-public member class template.  Now fixed.

  class A {
    template<typename T> struct B;
  };
  template <> struct A::B<int>;


7/27/16  [EDGcpfe/17143]
Internal error on constructor of variadic class template

An internal error could occur (in scan_function_body) if a constructor
of a variadic class template had an empty pack expansion as its first
parameter, and the pack expansion was followed by one or more other
parameters.  Now fixed.

  template<class T, class ... Ts> struct S {
    S(Ts ... ts, T t) {}
  };
  S<int> s(2);


7/27/16  [EDGcpfe/17439]
Constructor/destructor calls when IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS
is TRUE

A change has been made to lowering when constructor and/or destructor calls
return "this" (i.e., when IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS is
TRUE).  For such calls, the call expression nodes in the unlowered IL have
"void" type, but lowering lowers the return type of the constructor/destructor,
resulting in a "void" call node that invokes a routine returning a pointer.
A change has been made in such cases to change the call node to the appropriate
type (i.e., that returned by the constructor/destructor), but add a cast to
"void" thereby preserving the original expression type.  This had caused
invalid IL in some cases where a destructor was invoked in an "if" statement
that was then inlined as an eok_question operator, resulting in the second
and third operands of the eok_question operator having different types.


7/26/16  [EDGcpfe/13966,EDGcpfe/17035]
Member function template with parameter pack expanded from enclosing class
template parameter

Consider the following example:

  template<class ... Ts> struct S {
    template<class F> auto m(F f, Ts... p)->decltype(f(p...));
  };
  struct C { void operator()(int); };
  void g(S<int> s, C c) {
    s.m(c, 3);
  }

Previously, the parameter pack p of S<int>::m was not recognized as a parameter
pack when parsing "p..." in the return type (because the enclosing template
is already expanded at that point).  This is now fixed.


7/25/16  [EDGcpfe/17422]
Microsoft compatibility: dllimport static data members of class templates

When parsing templates in their generic form in Microsoft C++ mode, the front
issued an error on the prototype instantiation of the definition of a dllimport
static data member of a class template that includes an initializer.  Now, an
error is only issued if the static data member is instantiated.  For example:

  template<typename T> struct S {
    __declspec(dllimport) static int const m;
  };
  template<typename T> int const S<T>::m = 1;
    // Previously an error in some Microsoft modes.  Now okay.


7/25/16  [EDGcpfe/17431]
Spurious error on constexpr constructor with variant member initializer

In modes accepting constexpr constructors, the front end issued a spurious
error claiming an anonymous union is left uninitialized when a constexpr
constructor initializes a variant member that is not the first data member
of its enclosing anonymous union.  For example:

  struct S {
    union {
      float first;
      short second;
    };
    constexpr S(): second(0) {}  // Previously triggered an error.  Now okay.
  };

This is now fixed.


7/25/16  [EDGcpfe/17338]
C++17: Relaxed range-based-for loop requirements

In C++17 mode and in Microsoft mode with microsoft_version >= 1903, the front
end now permits the "begin" and "end" iterators implied by the definition of
the range-based-for statement not to have compatible types.  For example:

  struct S { operator int const*() { return nullptr; } };
  struct I {
    int i;
    I(): i(42) {}
    I const &begin() const { return *this; }
    S end() const { return S(); }
    int operator*() const { return i; }
    void operator++() const {}
    operator int const*() { if (i++ != 45) return &i; else return nullptr; }
  };
  extern "C" int printf(char const*, ...);
  int main() {
    for (int x: I()) {
      printf("%d\n", x);
    }
  }

This example prints 43, 44, and 45 on separate lines.  It works despite the
"begin" and "end" iterators having different types (I and S, respectively)
because user-defined conversion operators allow those two types to be compared.
This relaxation was introduced into the working paper for C++17 by the
standardization committee's paper P0184R0.


7/22/16  [EDGcpfe/17189]
Microsoft compatibility: Instantiating templates to find candidates

The changes for EDGcpfe/14716 cause the front end to avoid instantiating
class templates in cases where such an instantiation might be needed to find
a function or operator candidate.  It appears MSVC no longer exhibits that
nonstandard behavior and the front end now no longer emulates it when
microsoft_version >= 1900.  For example:

  template<typename T> T val();
  template<typename, typename = void> struct X;                 // (1)
  template<typename T> struct X<T, decltype(f(val<T&>()))> {};  // (2)
  template<typename> struct S {
    friend void f(S&) {}                                        // (3) 
  };
  X<S<int>> x;

Previously, in Microsoft C++ modes, X<S<int>> did not match the partial
specialization (2) because the call to f with T = A<int> in the decltype
construct did not force the instantiation of A<int> and therefore the friend
declaration (3) was not found.  Instead, X<S<int>> was considered an instance
of the primary template (1), triggering an incomplete type error for the
definition of x.  Now, that behavior is limited to microsoft_version < 1900;
when microsoft_version >= 1900, the example is accepted.


7/22/16  [EDGcpfe/17226]
Stricter template checking

A new command-line option --stricter_template_checking (and associated global
variable stricter_template_checking) now causes the front end to more strictly
check prototype instantiations in modes that ordinarily weaken such checks.
For example:

  template<typename> struct S {
    void f();  // (1)
    void g() {
      f(42);   // (2)
    }
  };

When performing prototype instantiations of nonclass entities this code is
accepted by default in Clang, GCC, and Microsoft modes.  When the new option
--stricter_template_checking is enabled, an error is issued because call (2)
has more arguments than the function declaration (1) it resolves to.  (That
error is always issued in strict mode.)


7/21/16  [EDGcpfe/17192,EDGcpfe/17423]
Abort on constexpr call producing an address in a base class subobject

In C++14 mode, the front end sometimes aborted with an internal error in
find_subobject_for_interpreter_address (interpret.c) processing a call
returning an address (pointer or reference) into a base class subobject.
For example:

  struct B1 { int i; };
  struct B2 { int i; };
  struct D: B1, B2 {
    constexpr D(): B1{1}, B2{2} {}
    constexpr int const& f() const { return B2::i; };
  };
  int main() {
    constexpr D d;
    return d.f();  // d.f() returns a reference in the base class subobject
  }                // of d.  Previously aborted.  Now okay.

This is now fixed.


7/21/16  [EDGcpfe/16527,EDGcpfe/16916]
Clang compatibility: _Nullable, _Nonnull, and _Null_unspecified

In Clang modes, the front end now supports new type qualifiers _Nullable,
_Nonnull, and _Null_unspecified that indicate whether a pointer or
pointer-to-member type admits a null value.  These qualifiers are unusual
in that they do not affect type equivalence; for example, given a template
X<T>, X<int *_Nullable> and X<int *_Nonnull> are the same type (the
qualifiers are stripped from the IL for template arguments).


7/20/16  [EDGcpfe/17408]
C++17 compatibility: terse static_assert

Paper N3928 introduced the "terse" static_assert, i.e., a static_assert with
only a single argument.  That is now implemented in C++17 mode, as well as
when microsoft_version >= 1903 and --ms_c++latest is specified, or when
gnu_version >= 60000 and C++11 mode (or later) is specified.  For example:

  static_assert(true);    // Now accepted in various modes.


7/19/16  [EDGcpfe/17039]
Spurious deduction failure of with dependent nontype template parameter that
acquires a reference type

In some cases, the front end triggered a deduction failure when attempting to
bind a nontype template argument with a template-dependent type that becomes a
reference type after substitution.  This could lead to spurious errors later
on.  For example:

  extern constexpr int v = 0;
  template<typename T> struct Id {
    typedef T Type;
  };
  template<typename T, typename Id<T>::Type V> struct X {};
  template<typename T> void f(X<const T&, v>) {}
  void g() {
    X<const int&, v> x;
    f(x);  // Previously an error because v was not successfully bound to
  }        // nontype template parameter V in X<const T&, v>.  Now okay.

This is now fixed.


7/18/16  [EDGcpfe/17033]
Spurious error on pack expansion in function template default argument

A spurious error could result if a pack expansion appeared at the top
level in a function template default argument.  Now fixed.

  template <typename... T> void f(int i = sizeof...(T)) {}


7/18/16  [EDGcpfe/10202,EDGcpfe/17018]
Spurious error on default template template argument

A spurious error could be issued if a template template parameter had
a template parameter type that depended on another template parameter
of the same template, and that template template parameter had a default
template argument.  Now fixed.

  template <int> class A;
  template <class T, template <T> class TT = A> class B { };


7/18/16  [EDGcpfe/17062]
Injected class name as template template argument (core issue 1004)

In C++11 an injected class name can be used as a template template
argument.  This is now supported in C++11 (and newer) modes.  Note that
it was already supported in g++ mode.

  template <template <class> class T> struct B {};
  template <class T> struct A {
    B<A> x;
  };


7/17/16  [EDGcpfe/17055]
Operators producing incomplete types and decltype

The changes for EDGcpfe/11740,EDGcpfe/14277 permit a top-level function call in
a decltype operand to produce an rvalue with an incomplete class type.  These
changes did not, however, handle the case of a call resulting from invoking an
overloaded operator (using operator notation).  For example:

  struct I;
  I operator+(int, I&);
  void g(I &p) {
    decltype(1+p) *q;  // Previously an error.  Now okay.
  }


7/17/16  [EDGcpfe/17019]
Nesting depth of friend member template declarations

Formerly, the number of template parameter clauses in a friend member
template declaration was required to match the nesting depth of the
declaration to which the friend refers, except in g++ and Microsoft
mode.  When the friend refers to a nested class of an enclosing class
template, it is now permitted to have a single template parameter
clause in all modes.

  template <typename V> struct A {
    template <typename T> struct B {
      template <typename> friend class B;
    };
  };
  A<int>::B<int> ab;


7/14/16  [EDGcpfe/17394]
Microsoft compatibility: abort on variable template in C++/CLI mode

An abort could occur (in access_for_symbol) if a variable template was
declared in a namespace in C++/CLI mode.  Now fixed.

  namespace N {
    template <class T> T v = 1;
  }


7/13/16  [EDGcpfe/17308]
C++-generating back end: template argument list in variable template
declaration

In configurations in which code is generated for template definitions from
the prototype instantiation IL, the C++-generating back end added an
incorrect template argument list to the declaration of a variable template.
This is how fixed.  For example, with --c++14:

  template<class T> struct S { };
  template<class T>
    constexpr bool v = S<T>::value;  // Previously generated as "v<T>"


7/13/16  [EDGcpfe/17043]
Spurious error on call to template member that is later overloaded

The front end sometimes failed to match an out-of-class definition to its
in-class declaration if the two declarations involve a call to an overloaded
set of which only one member is declared at the point of the in-class
declaration.  For example (in C++11 mode):

  template<typename T> struct X {
    auto f() -> void;
    auto g() -> decltype(this->f());
    template<typename> auto f() const -> void;
  };
  template<typename T>
  auto X<T>::g() -> decltype(this->f()) {}
    // Previously triggered an incompatibility error.  Now okay.

This is now fixed.
    

7/12/16  [EDGcpfe/17354]
Spurious error on template-dependent compound literal in GNU C++ mode

In GNU C++ mode, the front end accepts C99-style compound literals, but it
failed to instantiate class templates before checking for the completeness
of the type underlying an array with unknown bounds.  This could result in
spurious errors.  For example:

  template<typename T> struct X { T i; };
  X<int>* x[] = { (X<int>[]){{42}} };
    // Triggered a spurious error about "X<int>[]" not being a valid
    // type for a compound literal.

This is now fixed.


7/11/16  [EDGcpfe/17088]
Local variable references in non-type template arguments

In cases where a function template uses a member-access expression naming a
dependent static data member as a nontype template argument and the object
expression in the member access uses a local variable, the IL produced by
the front end violated the memory region constraints by pointing to the
local variable from the file scope memory region.  Depending on the
configuration, this could result in aborts or other undefined behavior.
This is now fixed.  For example:

  template <typename> struct A {
    static const int i = 0;
  };
  template <int I> struct B { };
  template <typename T> void f(T& t) {
    B<t.i> bt;  // Use of "t" caused violation of memory regions
  }
  void g() {
    A<int> ai;
    f(ai);
  }


7/11/16  [EDGcpfe/17382]
GCC compatibility: _Alignas attributes in C11 mode

A change has been made to restore the previous behavior of giving an error
in GNU C11 mode when an _Alignas alignment specifier is used to attempt to
reduce the alignment below the default alignment of a type.  For example
(with --c11 --gcc):

  float _Alignas(1) f1; // error (alignment is less than default for type)


7/11/16  [EDGcpfe/17383]
GCC compatibility: Allow _Noreturn on "main"

Although the C11 standard is explicit that the _Noreturn function specifier
should not be allowed on the "main" function, GCC (and clang) give only a
warning, and now so does the front end.  For example (with --c11 --gcc):

  _Noreturn int main() {}


7/8/16   [EDGcpfe/17381]
C++14 constexpr constructors calling non-constexpr subobject constructors

In C++14 mode, the front end previously failed to diagnose a constexpr
constructor directly calling a non-constexpr constructor to initialize one of
its subobjects (a diagnostic required by the C++14 standard).  For example:

  struct S { S(); };
  struct C {
    S s;
    constexpr C(): s() {}  // Previously accepted in C++14 mode.
  };                       // Now an error.

This is now fixed.


7/8/16   [EDGcpfe/17034,EDGcpfe/17052]
SFINAE and C++11-style casts with braced operand

When testing the validity of a C++11-style cast with a braced operand in a
SFINAE context, the front end erroneously used a set of conversion criteria
different from non-SFINAE contexts.  This could result in a candidate in an
overload set being selected for a call (when it should have been discarded)
and then triggering an error when trying to materialize the actual conversion.
For example, in GNU or Microsoft C++11 mode:

  template<typename T> decltype(long{ T() }) g(int);  // (1)
  template<typename> int g(...);  // (2)
  int main() {
    return g<int*>(42);  // (3)  Previously an error.  Now selected (2).
  }

Here, substituting the cast "long{ T() }" with T = int* should disqualify
candidate (1), but SFINAE processing used a conversion criterion that
permitted the case.  Resolving the call (3) then produced an error explaining
that an int* cannot be converted to type long.  This is now fixed (candidate
(1) is discarded and (2) is selected).


7/7/16   [EDGcpfe/17101]
Partial specialization matching issue with template template parameters

In some unusual circumstances, partial specialization matching of
templates with template template parameters could result in a spurious
"more than one partial specialization matches..." error.  Now fixed.


7/6/16   [EDGcpfe/14807,EDGcpfe/16063,EDGcpfe/16627, EDGcpfe/16735,
          EDGcpfe/17005,EDGcpfe/17359]
C11 _Atomic types

In C11 mode, the front end now accepts _Atomic types.  Such types are modeled
as qualified types; e.g., _Atomic(int) is type int with an _Atomic qualifier
(a tk_typeref entry) on top.  The size and alignment of an _Atomic type must
therefore match the underlying non-_Atomic type.  That matches the behavior of,
e.g., the GCC compiler, but not of the Clang compiler.  In Clang mode, the
front end therefore disables _Atomic class types, because Clang treats them
differently (their sizes differ from those of the underlying class types, and
some operations -- like member access -- are not allowed on them).  A global
variable c11_atomic_classes_disabled controls that behavior.  However, all
Clang modes accept _Atomic scalar types (not just Clang C11 mode).
Furthermore, the _Atomic feature is supported in all GNU C modes with
gnu_version >= 40900 (not just GNU C11 mode).


7/5/16   [EDGcpfe/17317]
Lowering of aggregate in conditional operator leads to assertion failure

The lowering of certain conditional operators (where the second and third
operands return a class prvalue) could produce an assertion failure (in
lower_dynamic_init) when one or more of the operands contained aggregates
whose lowered form included keeping a constant value.  That has now been
fixed.  For example (with --c++11):

  struct A { int val[2]; } a;
  void f(bool b, int in) {
    a = b ? A{{in,2}} : A{{3,in}};
  }


7/1/16   [EDGcpfe/17047]
GNU compatibility: Allow standard attributes on friend declarations

The C++ standard expressly forbids standard attributes on a friend declaration
that is not a definition, but GCC seems to disregard this.  The following is
now accepted (with --g++ --c++14):

  struct A {
    friend void f [[deprecated]] (void);
  };
  void f [[deprecated]] (void) { }


7/1/16   [EDGcpfe/17369]
Undiagnosed ambiguous variable use corrupts IL

An expression in a template referring to an ambiguous variable name was
previously sometimes not diagnosed, but the resulting IL included an error
node.  This could later trigger an error in a back end (e.g., in the
C++-generating back end).  For example:

  int v;
  namespace N { int v; };
  using namespace N;
  template<typename T> void g(T) {
    v = 3;  // "v" is ambiguous.  Previously, this was accepted by the
  }         // front end, but produced an error node in the IL, likely
            // causing an abort later on.


6/30/16  [EDGcpfe/17345]
Invisible friend declaration found in some cases with using-directives

In a lookup involving using-directives, an invisible friend declaration
was sometimes incorrectly included in the resulting overload set.  Now
fixed.

  struct A { operator int(); };
  namespace { template<typename T> void operator==(T &, T &); }
  template<typename T> bool operator==(T &, T &);
  struct B {
     B(A);
     friend bool operator==(const B &, const B &);
  };
  struct C { A f(); };
  bool f(C &c1, C &c2) {
    return c1.f() == c2.f();  // Spurious ambiguity
  }


6/29/16  [EDGcpfe/17325]
C++14 constexpr: Abort on cast to derived class

The front end sometimes aborted when evaluating a cast to a derived class in
the C++14 constexpr interpreter.  The abort was due to corrupt interpreter
data and could be difficult to reproduce, but the root cause of the issue was
the incorrect initialization of base class subobjects with an associated
dynamic initializer of kind dik_none.  The issue is now fixed.


6/29/16  [EDGcpfe/17343]
Nested class defined in alias declaration not handled correctly

The front end previously treated nested classes defined in alias declarations
as if they weren't nested at all if the alias appeared in a class template.
This in turn was likely to lead to spurious errors.  For example:

  template<typename T> struct X {
    using A = struct N {};  // Previously N was not considered a member of
                            // X<T>.
    A m;  // A spurious error was issued here claiming m's type is incomplete.
  };
  X<void> x;

This is now fixed.


6/29/16  [EDGcpfe/16800]
Spurious access error reported in rescan contexts

A spurious access error could be issued during template argument
substitution.  This would occur even in modes without SFINAE access
checking (e.g., Microsoft mode).  Now fixed.

  struct A {
    template <void pf(int)> static void f();
  };
  class B {
  public:
    static void f() {
      A::f<g<int> >();  // Spurious "B::g(T)" is inaccessible
    }
  private:
    template <typename T> static void g(T);
  };


6/28/16  [EDGcpfe/17356]
GNU and Clang C++14 compatibility: Direct braced initializers and placeholder
types

The changes described by the entry for EDGcpfe/15918 now apply in GNU C++14
mode with gnu_version >= 50000 and in Clang C++14 mode with clang_version >=
30800.


6/28/16  [EDGcpfe/17357]
C++14 constexpr: Spurious failure on address equality comparison

Given a complete object X, comparing for equality a pointer to that complete
object and a pointer "one past the end" of that object previously triggered a
spurious constexpr evaluation failure.  For example:

  constexpr bool g() {
    int x = 1;
    return &x+1 == &x;  // Previously triggered a constexpr evaluation
  }                     // failure.  Now evaluated to false.
  static_assert(!g(), "Unexpected");  // Previously a compilation error.
                                      // Now okay.

This is now fixed.


6/28/16  [EDGcpfe/16811]
GNU C++ compatibility: VLA declarations with initializers

In GNU C++ mode with gnu_version >= 40900, the front end now accepts
initializers for variable length arrays.  For example:

  void g(int n) {
    double x[n] = { 0.0 };  // Now accepted in some GNU C++ modes.
  }


6/28/16  [EDGcpfe/17267]
GNU/Microsoft compatibility: Defaulted exception specifications

When explicitly defaulting a special member function, a declared exception
specification on the defaulting declaration cannot conflict with the implicit
exception specification.  In special members of template instantiations, GCC
and MSVC mark the special member as deleted instead of diagnosing the conflict.
The front end now does the same in Microsoft and GNU C++ modes.  For example:

  struct E { E() {} };
  template<typename T> struct X {
    X() noexcept = default;
    T t;
  };
  struct S { X<E> m; };

In this example, when T is E, the noexcept specification on X::X() conflicts
with the generated one (because E::E() is not noexcept).  Ordinarily, that
triggers an error, but in GNU and Microsoft mode it is now accepted and
X<E>::X() is marked as deleted (as is S::S()).


6/28/16  [EDGcpfe/17301,EDGcpfe/17322]
Internal error in alloc_expr_ctor_dynamic_init

In some relatively complex cases, the front end failed an "expect_error()"
assertion check on certain constructor invocations during SFINAE processing
(the "expect_error()" check was invalid in such cases).  For example:

  struct M { M(M&); };
  template<typename T> auto f(T p)->decltype(T(p.u));  // (1)
  template<typename T> auto f(T)->T;
  void foo(M a) {
    f(a);
  }

When processing the call "f(a)", candidate (1) triggers a SFINAE failure
(because M has no member u), but the handling of the constructor invocation
containing that failure ("T(p.u)") mistakenly asserted that any failure should
have triggered a diagnostic.  That triggered an internal error, which is now
fixed.


6/27/16  [EDGcpfe/16967,EDGcpfe/17000]
Microsoft compatibility: add --ms_c++14 and --ms_c++latest command-line options

The --ms_c++14 and --ms_c++latest command-line options have been added to the
front end to emulate the behavior of Visual Studio's /std:c++14 and
/std:c++latest command-line options respectively.  These new options are
available only when microsoft_version >= 1903 (i.e., when emulating Visual
Studio 2015 Update 3 or later).  In addition, the predefined macro, _MSVC_LANG,
is now defined with an appropriate value for the emulation mode.

This fix also changes the value used for the __cplusplus predefined macro to
201500L when using --c++17 in GNU emulation mode and 201406L when using --c++17
in Clang emulation mode.  Both of these are temporary values until the next
version of the C++ standard is ratified.


6/25/16  [EDGcpfe/17337]
Clang compatibility: Enable __make_integer_seq

The builtin alias template __make_integer_seq is now enabled in Clang emulation
mode (see the Changes entry for EDGcpfe/16545).


6/24/16  [EDGcpfe/17355]
Abort on value-initialized pointer-to-member in C++14 constexpr evaluation

In C++14 mode, the front end aborted in init_subobject_to_zero when evaluating
the value-initialization of a pointer-to-member in a mem-initializer.
For example:

  class C {};
  typedef void (C::*PMF)();
  struct P {
    PMF v;
    constexpr P(): v() {}  // The evaluation of "v()" previously triggered
  };                       // an internal error.
  P g() {
    return P();
  }

This is now fixed.


6/24/16  [EDGcpfe/17353]
Spurious error on friend class template that matches member name

A spurious error was issued if the name of a friend class template
declaration is the same as that of a member of the class in which the
friend declaration appears.  Now fixed.

  template <class T> class A {};
  class B {
    void A() {}
    template <class T> friend class A;
  };


6/23/16  [EDGcpfe/17223]
Some file operations with extended characters failed on Windows

On Windows, when NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is TRUE,
the front end did not handle certain file operations properly when the
file name contained characters that were converted to Unicode in the
internal representation (e.g., Latin-1 characters).  The is_directory
routine (which validates directory names from the command line) would
fail, as would several routines used in the creation and use of
precompiled header files.  Now fixed.


6/21/16  [EDGcpfe/17346]
Assertion failure on cv-qualified _Complex type in aggregate

An initial value for a member of an aggregate where the member has a
cv-qualified _Complex type had resulted in an assertion failure (in
aggr_init_complex).  Now fixed.  For example (with --gnu_version 60100):

  struct S {
    const _Complex float cf;
  };
  void f() {
    const S s = {{0.0f, 0.0f}};
  }


6/21/16  [EDGcpfe/17330]
Abort on trivial value-initialization of array member

In C++11 mode, a mem-initializer performing value-initialization of an array
whose element type has a trivial defaulted constructor triggered an internal
error in scan_parenthesized_mem_init_args (decl_inits.c).  For example:

  struct S {
    S() = default;
  };
  struct X {
    X(): arr() {}  // Previously triggered an assertion failure; now okay.
    S arr[1];
  };

This is now fixed.


6/19/16  [EDGcpfe/17321]
Missing diagnostic on duplicate enumerator name

In C++11 mode, when an opaque enum type is declared in a class definition and
later defined outside that class definition, the front end failed to detect
duplicate enumerator names in the enum type definition.  For example:

  struct S {
    enum E: int;
  };
  enum S::E: int { e, e };  // Previously accepted with no diagnostic.
                            // Now an error.

This is now fixed.


6/16/16  [EDGcpfe/17334]
Microsoft compatibility: variadic variable templates not accepted

Variadic variable templates were not processed properly in Microsoft mode,
resulting in spurious errors.  Now fixed.

  template <typename... Types> struct A {
    static constexpr int i = sizeof...(Types);
  };
  template <typename... Types> constexpr int v = A<Types...>::i;
  static_assert(v<char, short, int, long> == 4, "unexpected value");


6/16/16  [EDGcpfe/17329]
C++/CLI and C++/CX: Delegate types and template parameters

The front end previously incorrectly handled delegate type declarations based
on template parameter types.  This was likely to result in aborts, particularly
in modes parsing templates in their generic form.  For example:

  template<typename T> ref struct S {
    delegate T D;  // Likely to trigger an abort (e.g., in
  };               // decl_member_function).

This is now fixed.


6/15/16  [EDGcpfe/17185]
C++-generating back end: unneeded qualification of in-class member names

The C++-generating back end previously used an unnecessary qualified name
when referring to a member of a class within the class scope.  Ordinarily
this unneeded qualification was harmless, but in some cases the result was
generated code that could not be compiled.  This unneeded qualification is
now suppressed.  For example, with --c++11:

  template <typename> struct S {
    int v;
    int foo() noexcept(noexcept(v));  // "v" was previously generated as
                                      // "::S<__T12345678>::v" (using an
                                      // invented name for the unnamed
                                      // template parameter)
  };


6/15/16  [EDGcpfe/17306]
GNU compatibility: Cast to incomplete class type in template default argument

In GNU C++ modes, the front end now accepts functional-notation casts to
incomplete types if they appear as an unevaluated operand in a template default
argument.  For example:

  struct S;
  template<typename = decltype(S(0))> void g() {}
    // Normally an error (S is incomplete), but now accepted in
    // GNU C++11 mode.
  int main() {
    g<>();
  }


6/14/16  [EDGcpfe/17314]
C++14 constexpr conversion from unsigned to signed value incorrect

The C++14 interpreter did not correctly convert values of unsigned types to
larger signed types in some contexts: It extended the most significant bit of
the unsigned value as if it were signed.  For example:

  constexpr bool f() {
    unsigned short m = (unsigned short)65535U;
    return (unsigned short)65535U == m;
  }
  static_assert(f(), "Unexpected");
    // Previously failed because the promotion of m to int in function f
    // incorrectly produced a negative value.

That is now fixed.


6/14/16  [EDGcpfe/17313]
GNU C++-mode abort on C++14 constexpr use of member constant

In GNU C++ mode, the in-class initializer of a static data member of a class
template is not instantiated unless it is needed (see the entry for
EDGcpfe/16403,EDGcpfe/16644).  Previously, if the first need of such a static
data member was during the evaluation of a C++14 constexpr function call, the
front end aborted with an assertion failure in extract_value_from_constant.
For example:

  template<typename T> constexpr int f(const T &p) { return p; }
  template <class T> struct S {
    static constexpr int N = 0;
  };
  void g() {
    f(S<int>::N);  // Previously aborted in GNU C++14 mode.  Now okay.
  }

This is now fixed.


6/14/16  [EDGcpfe/17307]
GNU C++ compatibility: Local __thread variables

In GNU C++ modes with gnu_version >= 40800, the front end now accepts local
static __thread variables requiring dynamic initialization.  For example:

  int f();
  int g() {
    static __thread int r = g();  // Now accepted in some GNU C++ modes.
    return r;
  }


6/14/16  [EDGcpfe/17312]
No longer ignoring prototype instantiations in non-lowering configurations

The changes for EDGcpfe/15902 et al. introduced a set of macros/routines
named ignore_*_in_back_end that are used to curtail unneeded processing on
prototype instantiations.  A change has been made to have these macros return
FALSE in configurations where DO_IL_LOWERING is FALSE, thereby restoring
the ability to produce mangled names for prototype instantiations (when
MANGLE_ALL_NAMES is TRUE).  Note however that mangling of names for
prototype instantiations has always been on a "best effort" basis and that
not all mangled names for prototype instantiations will generate a unique
name (and some may contain question mark characters).


6/14/16  [EDGcpfe/17194,EDGcpfe/17310]
Assertion failure processing large macro expansions

The changes of EDGcpfe/15293 (in version 4.10.1) introduced a regression
that sometimes caused an assertion failure in expand_macro_buffer when
processing very large macro expansions in Microsoft mode.  This is now
fixed.


6/13/16  [EDGcpfe/17305]
Spurious error on final modifiers in class templates

The front end previously issued spurious errors on some members of class
template with final modifiers.  For example (in C++11 mode):

  struct B {
    virtual void f(int) = 0;
  };
  template<typename T> struct D: B {
    void f(T) final {}  // Previously triggered a spurious error.  Now okay.
  };

This is now fixed.


6/13/16  [EDGcpfe/17302]
Spurious correspondence error on member constants in GNU mode

In GNU C++ mode, the in-class initializer of a static data member of a class
template is not instantiated unless it is needed (see the entry for
EDGcpfe/16403,EDGcpfe/16644).  Until that instantiation occurs, the member is
not marked as being a member constant, which means that, when simultaneously
compiling multiple translation units, the is_member_constant flag may not
match for corresponding a_variable entries.  Previously, this could trigger
spurious correspondence errors.  For example:

  // file1.cpp:
  template<class T> struct S {
    static int const N = 3;
  };
  template<class T> int const S<T>::N;
  extern S<float> s;
  int const *p1 = &S<int>::N;
  int r = S<int>::N;

  // file2.cpp:
  template<class T> struct S {
    static int const N = 3;
  };
  template<class T> int const S<T>::N;
  S<float> s;
  int const *p2 = &S<int>::N;

When simultaneously compiling these two translation units in GNU C++ mode, the
front end previously diagnosed a compatibility error for the declaration of
S<int>::N.  That is now fixed.


6/13/16  [EDGcpfe/17282]
Microsoft compatibility: __make_integer_seq

Typically the first template argument to __make_integer_seq is a template
with two template parameters, the second one being a parameter pack.  In the
case where the specified template has a single template parameter, the front
end had failed an assertion check(equiv_template_arg_lists: unequal arg list
lengths) or in some cases, segfault'ed in update_template_param_symbols.
Now fixed.  For example (with --microsoft_version 1900):

  template <class T> struct S {};
  template<class T, T sz>
  using m = __make_integer_seq<S, T, sz>;
  m<int, 0> x;    // Okay
  m<int, 1> y;    // An error


6/13/16  [EDGcpfe/17302]
Abort on missing rescan info

In some relatively complex cases, the front end aborted in get_expr_rescan_info
("missing default rescan info") during SFINAE processing for members of
namespace (or members of classes that are members of namespace).  This is now
fixed.


6/13/16  [EDGcpfe/17286]
__cplusplus value in ms_extensions mode

The value of the __cplusplus macro when --clang --ms_extensions is specified
now mirrors the value given by Clang, not Microsoft Visual Studio.  That is,
when --clang --ms_extensions --c++14 is specified, __cplusplus has the value
201402L (and 201103L when --c++11 is specified).


6/13/16  [EDGcpfe/17303]
Assertion failure on pointer/reference cast

The changes for EDGcpfe/17115 (in version 4.11) introduced a regression
causing an assertion failure in addr_con_target_type_is_const while
processing certain pointer and reference casts.  This is now fixed.  For
example, with --c++11:

  typedef struct O {} O;
  typedef O* OPtr;
  void foo() {
    O o2;
    O o = *(OPtr)&o2;  // Previously aborted, now okay
  }


6/13/16  [EDGcpfe/17292]
wchar_t macros now defined in ms_extensions mode

The builtin macros _WCHAR_T_DEFINED and _NATIVE_WCHAR_T_DEFINED are now defined
when ms_extensions is TRUE (previously they were only defined when
microsoft_mode was TRUE).    (This improves compatibility with Clang when its
-fms-extensions option is used.)


6/10/16  [EDGcpfe/17284]
Access SFINAE in ms_extensions mode

The front end no longer implicitly disables access SFINAE when ms_extensions is
TRUE in non-Microsoft modes.  (This improves compatibility with Clang when its
-fms-extensions option is used.)


6/10/16  [EDGcpfe/17291]
Spurious errors on operator new[]/operator delete[] in ms_extensions mode

When ms_extensions is TRUE in non-Microsoft modes (see the entry for
EDGcpfe/16502) the front end predeclared operator new[]/operator delete[] as an
alias for the corresponding non-array operators (see also the Changes entry of
9/11/07).  However, it did not displace those aliases when a user-declared
version of such an operator appeared, leading to spurious errors.  For example:

  void* operator new(size_t size) { return 0; }
  void * operator new[](size_t size) { return 0; }
    // Previously triggered a spurious redefinition error in some modes.
    // Now okay.

This is now fixed by not predeclaring the array versions of those operators as
aliases for the non-array versions in the affected modes (that matches the
behavior of Clang with options -fms-extensions or -fms-compatibility).


6/10/16  [EDGcpfe/17295]
Spurious error on singleton braced initializer for aggregate class object

An aggregate class object can be initialized with a braced list containing a
single value of that class type (or a related type); this is different from
ordinary aggregate initialization in that the element in braces does not
represent a proper subobject value but the whole object's value.  In some
contexts, however, the front end did not correctly recognize that special
case and issued a spurious error as a result.  For example:

  struct E {};
  struct S {
    E e;
    S(E p): e{p} {}  // Previously triggered a spurious error
  };                 // ("too many initializer values").  Now okay.

This is now fixed.


6/10/16  [EDGcpfe/17010]
Cast type vs. expression disambiguation

An expression like

	(T ())()

where T is a type name was previously erroneously treated as an attempt to
cast "()" to type "T ()" (i.e., a function type taking no arguments and
returning type T).  Now, it is instead treated as the invocation of a call
with no arguments on the value-initialization of an object of type T.
For example:

  struct S {
    int operator()();
  };
  int r = (S())();  // Previously a syntax error.  Now okay.

Note that the following similar arrangement is still invalid (as mandated by
the standard):

  struct S {
    int operator()(int);
  };
  int r = (S())(42);  // Invalid attempt to cast 42 to type "S()".

Changes were also made to expressions of the form "(T())++" and "(T())--"
(which are now accepted if the ++/-- is not followed by another expression).


6/9/16   [EDGcpfe/16833,EDGcpfe/17262]
Move optimization and bitwise copyable class types

Consider the following example:

  struct M {  // Move-only type
    M() = default;
    M(M&&) = default;
  };
  M g() {
    M v;
    return v;  // Previously an error; now okay.
  }

M is a move-only type because the declaration of the move constructor causes
the implicitly-declared copy constructor to be deleted.  Prior to the changes
for EDGcpfe/16788, M was not considered bitwise copyable and consequently the
return statement was subject to the named return value optimization: No copy
or move constructor was involved in returning v, and the code was accepted.
After EDGcpfe/16788, M is now correctly considered bitwise copyable, and the
named return value optimization can no longer be applied (at least, using the
Cfront or IA-64 ABIs).  However, in such cases the front end failed to
consider the standard-mandated "move optimization" (which requires the
variable to be returned using the move constructor) and instead just attempted
to use the copy constructor: An error ensued since that constructor is deleted.
This is now fixed: The move optimization is applied and the (bitwise) move
constructor is selected.


6/8/16   [EDGcpfe/17256]
Constant folding of references to functions

In some cases the front end incorrectly handled constant expressions
involving references to functions, leading to spurious errors.  This is
now fixed.  For example, with --c++11:

  using fptr = void(*)();
  struct A {
    constexpr A(fptr f) : m(f) { }
    fptr m;
  };
  template<class T> constexpr A make(T&& t) {
    return A(t);
  }
  constexpr fptr&& get(A&& a) {
    return static_cast<fptr&&>(a.m);
  }
  void f() { }
  void g() {
    get(make(f)) == f;  // Previously an error
  }


6/7/16   [EDGcpfe/17002]
User-defined conversions in nontype template arguments

The front end previously sometimes failed to consider constexpr user-defined
conversion functions when matching a nontype template argument to its
corresponding parameter.  For example:

  struct B {
    constexpr operator bool() const { return true; }
  };
  template<bool> struct F;
  template<> struct F<true> {
    using Type = float;
  };
  template<int> struct C {
    static constexpr B cond = B{};
  };
  template<int N>
  typename F<C<N>::cond>::Type f();
  void g() {
    f<0>();  // Previously triggered a spurious error because the conversion
  }          // of C<0>::cond to bool was not considered.

This is now fixed.


6/7/16   [EDGcpfe/17230]
Failure to initialize virtual tables of some local classes

In some cases (more likely with --c++14 and relaxed constexpr), the virtual
function tables for a local class had failed to be initialized, causing the
potential for undefined behavior at runtime.  A change has been made to
delay lowering on functions with local classes which contain functions that
themselves have had lowering delayed.  For example (with --c++14):

  struct A {
    virtual int f() {return 1;}
  };
  template <class T> struct B {
    A* f() {
      struct X : A {
        virtual int f() {return 2;}
      };
      return new X;
    }
  };
  int main() {
    return B<A>().f()->f() != 2;
  }


6/7/16   [EDGcpfe/17238,EDGcpfe/17258]
Internal error on use of carries_dependency in friend declaration

The use of a carries_dependency attribute on a parameter in a friend
declaration where no carries_dependency attribute appeared in the first
declaration had resulted in an internal error (in
check_carries_dependency_for_params) rather than an error.  Now fixed.
For example (with --c++11):

  struct S {
    void f(int);
  };
  struct A {
    friend void S::f([[carries_dependency]] int);
  };


6/7/16   [EDGcpfe/17251,EDGcpfe/17275,EDGcpfe/17529]
Abort in define_member_function on attempt to define invalid class member

The changes for EDGcpfe/16170 introduced a regression in GNU C++ modes with
gnu_version < 40700 whereby the front end aborted (null pointer indirection)
after issuing an error for attempting to define a non-existing member function.
For example:

  struct S { void f(int); };
  void S::f(char) {}


6/7/16   [EDGcpfe/17278]
Abort in C++14 interpreter due to misaligned access

On some platforms (notably, Win32) the front end could abort in the C++14
constexpr interpreter because the function release_constexpr_stack failed to
correctly align pointer offsets.  This is now fixed.


6/7/16   [EDGcpfe/17060]
SFINAE and nontype template argument conversions

The front end previously failed to trigger a SFINAE failure on certain
seemingly innocuous conversions on nontype template arguments.  This could
lead to spurious errors later on.  For example:

  struct B {
    int f();
    void f() const;
  };
  struct D: B {};
  template<typename T, T> struct V {};
  template<typename T> decltype(V<int (T::*)(), &T::f>(), 42) g(T);  // (1)
  template<typename T> char g(...);
  static_assert(sizeof(g<D>(D{})) == 1, "Unexpected!");
    // Previously triggered a spurious error about an incompatible type
    // for the second template argument of V.

In this example, candidate (1) is considered with T = D.  The argument &T::f
becomes &D::f which much be matched to type int (D::*)().  In many contexts,
&D::f can be resolved to the first member of B, producing a value of type
int (B::*)(), but when matching a nontype template parameter, that is not a
valid conversion and hence (1) must be discarded.  Previously, that discarding
did not happen and candidate (1) was selected, causing spurious errors later
on.  That is now fixed.


6/6/16   [EDGcpfe/16835,EDGcpfe/17222]
Parameter packs in attribute arguments

The changes for EDGcpfe/15940 added the mechanism for variadic parameter
packs in attribute (or alignas) arguments, but the parameter pack expansion
was never performed.  That has now been fixed.  For example (with --c++11):

  template <class... T> struct alignas(T...) A {};
  template <int... T> struct alignas(T...) B {};
  void f() {
    static_assert(alignof(A<char, double, int>) == alignof(double), "");
    static_assert(alignof(B<1, 8, 4>) == 8, "");
  }


6/6/16   [EDGcpfe/17235]
GNU compatibility: Static data member initializers and explicit specialization

In GNU C++ mode, the in-class initializer of a static data member of a class
template is not instantiated unless it is needed (see the entry for
EDGcpfe/16403,EDGcpfe/16644).  Previously, explicitly specializing such a
static data member did not disassociate the initializer from the specialized
member, which could cause unexpected behavior.  For example:

  template<typename T> struct X {
    enum E { e };
    constexpr static E const sm = E(e|e);
  };
  X<int>::E operator|(X<int>::E, X<int>::E);
  template<> constexpr X<int>::E X<int>::sm;  // Explicit specialization.
  X<int>::E xe = X<int>::sm;
    // Previously instantiated the in-class initializer of X<T>::sm for
    // T == int, triggering an error because the user-defined operator|
    // doesn't produce a constant-expression.  Now, the initializer is no
    // longer instantiated.

Furthermore, if such a static data member is instantiated after the
out-of-class definition is seen, it is no longer assumed to be a constant
initializer.  For example:

  template<typename T> struct X {
    enum E { e };
    static E const sm = E(e|e);
  };
  X<int>::E operator|(X<int>::E, X<int>::E);
  template<typename T>
    typename X<T>::E const X<T>::sm;
  X<int>::E xe = X<int>::sm;
    // Previously triggered an error because the user-defined operator|
    // doesn't produce a constant-expression.  Now, the initializer is no
    // longer required to be a constant-expression.


6/6/16   [EDGcpfe/17268,EDGcpfe/16646,EDGcpfe/16589]
Assertion failure in constant_value_at_address

The lowering process had neglected to properly set the
size_without_virtual_base_classes field of the subobject type of a class,
causing an assertion failure in constant_value_at_address in some
configurations.  For example (with --c++11):

  template<typename _Head> struct _Head_base {
    static constexpr const _Head&
    _M_head(const _Head_base& __b) { return __b._M_head_impl; }
    _Head _M_head_impl;
  };
  template<typename... _Elements> struct _Tuple_impl;
  template<typename _Head, typename... _Tail>
  struct _Tuple_impl<_Head, _Tail...>
    : public _Tuple_impl<_Tail...>, public _Head_base<_Head> {};
  template<typename _Head>
  struct _Tuple_impl<_Head> : public _Head_base<_Head> {};
  class tuple : public _Tuple_impl<float, double> {};
  constexpr bool foo(const tuple& t) {
    return _Head_base<float>::_M_head(t);
  }
  void f() {
    foo(tuple());
  }


6/3/16   [EDGcpfe/17058]
Core issue 903: "false" as a null pointer constant

In C++11 mode, the front end no longer accepts the boolean literal "false" as
a null pointer constant.  This falls out of the resolution of Core issue 903.
A global variable false_literal_is_not_null_pointer_constant is available to
control this behavior.  The previous behavior is retained in Microsoft modes
and in GNU modes with gnu_version < 60000.


6/3/16   [EDGcpfe/14594]
Cast of call with incomplete return type in call not handled correctly in
some SFINAE contexts

A function call can return an incomplete type if it is the direct operand of
a decltype construct.  However, the front end failed to trigger a SFINAE
failure (i.e., discard the associated candidate) if the call is under a cast.
For example:

  struct I f(int);  // Incomplete return type.
  template<typename T> int g(decltype((void)f(T()))*);  // (1)
  template<typename T> char g(...);
  static_assert(sizeof(g<int>(nullptr)) == 1, "Unexpected!");
    // Previously triggered an "incomplete return type" error after selecting
    // candidate (1).

This is now fixed.


6/3/16   [EDGcpfe/17040]
Incomplete return type in call not handled during SFINAE processing

The front end sometimes diagnosed a call to a function with an incomplete
return type directly during SFINAE processing instead of discarding the
associated candidate function.  For example:

  struct I f();  // Incomplete return type.
  template<typename T> int g(decltype(f(T{}), 0));  // (1)
  template<typename T> char g(...);
  static_assert(sizeof(g<int>(42)) == 1, "Unexpected!");
    // Previously triggered an "incomplete return type" error while
    // considering candidate (1).

This is now fixed.


6/3/16   [EDGcpfe/17038]
Ambiguous member access not detected during SFINAE processing

The front end previously did not detect certain ambiguous member accesses when
rescanning a member selection during SFINAE processing.  It instead proceeded
with the first member it found in the ambiguity set.  This could trigger
spurious errors.  For example:

  struct B1 { int x; };
  struct B2 { int x; };
  struct D: public B1, B2 {};
  template<typename T> decltype(T().x) f(T*);  // (1)
  template<typename T> char f(T);
  static_assert(sizeof(f((D*)0)) == 1, "Unexpected!");

Previously, this triggered an ambiguity error for "T().x" because candidate (1)
was not discarded during SFINAE processing.  This is now fixed.


6/3/16   [EDGcpfe/17272,EDGcpfe/17188,EDGcpfe/17263]
Spurious error on UDL referenced from cached context

A spurious error could be issued if a user-defined literal was referenced
from a context rescanned from a token cache, and the UDL operator was
found via a using-directive.  Now fixed.

  namespace N {
    int operator "" _XX (unsigned long long) { return 0; }
    int operator "" _XX (long double) { return 1; }
  }
  using namespace N;
  template <typename T> T f() {
    int i= 1_XX;
  }


6/2/16   [EDGcpfe/17036]
Spurious error on class template with pure virtual member instantiated with
local type

The front end spuriously issued an error message requiring the definition of
a pure virtual member function of a class template instantiated over a local
type.  For example:

  template<typename T> struct B {
    virtual void pv() const = 0;
  };
  template<typename T> struct D: B<T> {
    virtual void pv() const {}
  };
  int main() {
    enum E {};
    B<E> const &r = D<E>();  // Previously triggered an error requiring the
    r.pv();                  // definition of B<E>::pv() const.
  }

This is now fixed.


6/2/16   [EDGcpfe/10970,EDGcpfe/15318,EDGcpfe/17032]
Core issue 941: Specialization of deleted function templates

The front end now permits the explicit specialization of deleted function
templates and deleted member functions of class templates.  This reflects the
resolution of Core issue 941.  For example:

  template<typename T> T f(T) = delete;
  template<> int f(int p) { return p; }  // Now accepted.
  int main() {
    f(42);  // Valid, since the specialization f<int>(int) is not deleted.
  }


6/2/16   [EDGcpfe/17257]
Microsoft compatibility: va_list type in 64-bit mode

Previously the predefined type used for va_list in Microsoft mode in 64-bit
mode was an array of __va_list_tag structures (as is used in most Linux
instances).  A change has been made to use "char *", as is used currently
in the 32-bit mode.  For example, with --microsoft (in a configuration where
TARG_SUPPORTS_X86_64 is TRUE):

  #include <stdarg.h>
  void f(char *);
  int main() {
    va_list vl;
    f(vl);
  }


6/2/16   [EDGcpfe/10994]
Microsoft compatibility: __event __interface

The "__event __interface" construct is now supported for COM event sources.
No lowering of this construct is performed.  For example, with --microsoft:

  __interface IEvents {
    void MyEvent(int value);
  };
  class CSource {
    __event __interface IEvents;
  };


6/2/16   [EDGcpfe/17031]
Defaulted default constructors and constexpr

The front end previously did not mark defaulted default constructors as being
"constexpr" even when the conditions for doing so hold.  This could lead to
spurious errors, particularly in strict C++11 mode.  For example:

  struct S {
    S() = default;  // Previously, this constructor was not constexpr.
    constexpr S(S const&) {}
  };
  constexpr S s{};  // Previously triggered a spurious error in strict mode.

This is now fixed.


6/2/16   [EDGcpfe/17204,EDGcpfe/17239,EDGcpfe/17406]
Microsoft compatibility: unbounded recursion in macro expansion

The change for EDGcpfe/16200 (in version 4.11) introduced a regression that
resulted in unbounded recursion when a macro definition directly invokes
the macro from a position other than the first token.  This is now fixed.
For example, with --microsoft:

  int M(int i) { return i; }
  #define M(a) 1+M(a)
  int j = M(M(2));    // Previously caused unbounded recursion

In addition, that change caused a regression in which the behavior of the
front end differed from that of the Microsoft preprocessor for recursive
macro invocations occurring within the expansion of an argument in the
top-level invocation of a macro; recursion is no longer allowed in this
context, which matches the behavior of the Microsoft preprocessor.  For
example:

  #define STR(a) NXSTR(a)
  #define NXSTR(a) #a
  #define f h
  #define h(a) a+f

  STR( f(1)(2) )  // Previously expanded to "1+2+h", now "1+h(2)"


6/2/16   [EDGcpfe/17022]
Core issue 1684: constexpr member functions in non-literal types

The original specification for constexpr member functions required constexpr
member functions to have literal parent class types.  Core issue 1684 dropped
that requirement.  The front end now now follows the more relaxed rule.
For example:

  struct S {                                // Not a literal class type.
    S();
    constexpr int f() const { return 42; }  // Previously an error; now okay.
  } s;
  constexpr int r = s.f();


6/2/16   [EDGcpfe/16882]
GNU C compatibility: Volatile return types

In GNU C mode, volatile type qualifiers are dropped (possibly after issuing a
warning) on non-void return types.  This avoids errors in cases like this:

  volatile int g();  // A warning is issued; "volatile" is otherwise ignored.
  int g();           // No longer an error in GNU C mode.


6/1/16   [EDGcpfe/17007,EDGcpfe/17057]
Glvalue conditional operator and cv-qualifier differences

The resolution of Core issue 587 allows a conditional operator whose second and
third operands are glvalues to have those operands have identical types except
for cv-qualification and still produce a glvalue result.  The front end now
implements that rule (except in Microsoft mode and in some GNU modes).
For example:

  int x = 1;
  int const y = 2;
  int const *p = &(1 ? x : y);  // Previously an error.  Now okay.


5/31/16  [EDGcpfe/17030]
Spurious error on destructor call with dependent qualifier

A spurious error was issued if a destructor call used a dependent type for
the qualifier but a non-dependent name for the destructor.  Now fixed.

  template<typename T> void f(T* p) {
    p->decltype(T{})::~X();
  }


5/26/16  [EDGcpfe/17037]
Spurious access error on braced constructor initializer

In C++11 mode, a braced constructor initializer for a base class, selecting a
protected default base class constructor previously elicited a spurious access
error.  For example:

  struct B {
  protected:
    B();
  };
  struct D: B {
    D(): B{} {}  // Previously triggered a spurious error about B::B() not
  };             // being accessible.  Now okay.

This is now fixed.


5/26/16  [EDGcpfe/17224]
Flag to prevent diagnostic overrides from affecting SFINAE

The severity of some diagnostics can be overridden by command-line
options and/or pragmas.  The overridden severity has been used for
both diagnostics and to determine if a construct should cause
a substitution failure, under the assumption that a given construct
should have the same semantics in and out of SFINAE contexts.  Some
customers would like to be able to override diagnostic severities
without impacting SFINAE behavior.  This is now controlled with the
variable diag_override_does_not_affect_sfinae, which is initialized
with the macro DEFAULT_DIAG_OVERRIDE_DOES_NOT_AFFECT_SFINAE.  The
macro is FALSE by default (so there is no behavior change unless this
macro is set).  The flag is also used in other processing that can
affect overload resolution (e.g., validity of initializations and
accessibility of certain entities).


5/26/16  [EDGcpfe/17231]
Missing error on use of UDL operator as class or alias template name

A user-defined literal operator name was incorrectly allowed as a class
or alias template name.  Now fixed.

  template <class T> class operator "" _X {};
  template <class T> using operator "" _Y = int;


5/26/16  [EDGcpfe/16994]
Spurious attempt to implicitly invoke copy constructor

When a reference to a const class type is bound to the result of a function
call, the front end sometimes attempted to invoke the copy constructor on the
result of the call, even though that is unnecessary.  In cases where the copy
constructor could not be called (e.g., because it is deleted) this caused
spurious errors.  For example:

  struct S { void operator=(S&&); };  // Copy constructor is deleted.
  S sf();
  void g() {
    S const &rsc = sf();  // Previously triggered an error about S(S const&)
  }                       // being deleted.  Now okay.

This is now fixed.


5/26/16  [EDGcpfe/16939,EDGcpfe/17208]
GNU C++ compatibility: spurious lookup error in noexcept

In g++ mode a nonstandard lookup is done of names in noexcept contexts of
member functions and member function templates of class templates (the
lookup ignores member functions declared later in the class).  This
did not work properly in some cases when deferral of function prototype
instantiations was being done, causing some lookups of members to fail.
Now fixed.

  struct A {};
  template <typename T> struct B {
    typedef decltype(T()(0)) type;
  };
  template <typename T> struct C {
    int i;
    // Formerly: "i" is undefined at instantiation time
    template <typename U> int operator ()(U) noexcept(noexcept(i));
  };
  int main() {
    typedef C<int A::*>  c;
    typedef B<c>::type type;
    c()(0);
  }


5/25/16  [EDGcpfe/16987]
auto/decltype(auto) variables and template-dependent template-id initializers

The front end previously incorrectly handled the initializer of an auto or
decltype(auto) variable that consists of a template-dependent template-id
identifying a function template instance.  In the "auto" case, a spurious
error was issued during prototype instantiation.  In the "decltype(auto)"
case, a spurious error followed by an internal error (and abort) was issued
during a real instantiation.  For example (in C++11 mode):

  template<typename T> T ft() { return 1; };
  template<typename T> T g() {
    auto pf = ft<T>;  // Previously triggered a spurious deduction error.
    return pf();      // Now okay.
  }
  int main() { return g<int>(); }

This is now fixed.


5/25/16  [EDGcpfe/12386,EDGcpfe/16977,EDGcpfe/17015]
Casting a template-id for a function template instance to void

The front end previously issued a spurious error when a template-id denoting a
single template instance is cast to void.  For example:

  template<int i> void f() {}
  int main() {
    static_cast<void>(&f<1>);  // Previously a spurious error; now okay.
  }

This is now fixed.


5/25/16  [EDGcpfe/17001]
Template argument deduction with default arguments and variadic parameter

Deduction could fail when a template template parameter has a variadic
template parameter and the deduced template template argument has
a default argument.  Now fixed.

  template <typename T1, typename T2 = int> struct A { };
  template<class T, template <class, class...> class C> void f(T,  C<T>){}
  int main() {
    A<int> ai;
    f(1, ai);
  }


5/24/16  [EDGcpfe/16571]
User-defined literals in precompiled headers

The front end previously failed to save user-defined literals in precompiled
headers.  This is now fixed.


5/24/16  [EDGcpfe/16900]
Folding bitwise-copied class members

The front end previously failed to fold an invocation of a compiler-generated
copy constructor for a class if one or more of the members involved a
bitwise copy.  This is now fixed.  For example, with --c++11:

  struct A {
      constexpr A() {}
      constexpr A(const A&) {}
  };
  struct B : A {
      constexpr B() : A(), m() { }
      int m;
  };
  constexpr B t1;
  constexpr B t2(t1);  // Previously erroneously diagnosed as non-constant
                       // because of the bitwise copying of B::m


5/24/16  [EDGcpfe/17175]
Microsoft compatibility: __is_convertible_to

The changes for EDGcpfe/16645 updated the implementation of the type traits
helper __is_convertible_to to more accurately model std::is_convertible as
specified in the standard.  Specifically, the standard specification describes
the conversion being tested in terms of the conversions that occur when
returning a value from a function.  Ordinarily, that is a kind of "copy
initialization", but in Microsoft mode, returning a value is a form of "direct
initialization" (see the entry of 1/18/98).  However, it appears that the
Microsoft compiler does not treat the "simulated" return operation involved
in the computation of __is_convertible_to as a direct initialization (even
though it still treats actual return operations that way).  For example:

  struct F {
    template<typename T> explicit operator T() const;
  };
  struct T {};
  static_assert(!__is_convertible_to(F, T), "Not like MSVC");
    // Previously failed in Microsoft mode; now okay.

Here the conversion function from F to T is explicit and therefore not
applicable in a standard return value (explicit conversion functions are not
considered for copy initialization).  MSVC does consider it in an actual
return statement (because there it is treated as direct initialization), but
not for the __is_convertible_to(F, T) evaluation.  The front end now matches
MSVC in Microsoft mode.


5/24/16  [EDGcpfe/15599]
Template argument deduction with multiple matching base classes

Template argument deduction allows a derived class to match a function
parameter that is a base class.  Formerly, if more than one base class
matched, deduction would always fail.  Now, if one of the matching base
classes is a base class of the other, the most derived class is used.

  template <typename... T> struct A;
  template <> struct A<> {};
  template <typename T, typename... Ts> struct A<T, Ts...> : A<Ts...> {};
  struct B : A<int> {};
  template <typename... T> void f(const A<T...>&);
  int main() {
    f(B{});  // Now calls f(const A<int>&)
  }


5/24/16  [EDGcpfe/17154]
Assertion failure in apply_class_modifiers

The use of an alias template in certain cases had resulted in an assertion
failure in apply_class_modifiers.  That is now fixed.  The following example
(with --c++11) had generated such an assertion and now generates the
appropriate error:

  template <class T> using V = T;
  struct C {
    template <class> friend class V;
  };


5/24/16  [EDGcpfe/16842]
GNU compatibility: ignore carries_dependency standard attributes

GCC doesn't yet support the carries_dependency attribute, issuing a warning
on its use, and the front end now does the same.  The following example is
accepted (with two warnings) where it had been diagnosed with errors previously
(with --c++11 --g++):

  struct S {
    friend int f[[carries_dependency]](void);
  };
  int f[[carries_dependency]](void) { return 0; }


5/24/16  [EDGcpfe/17213]
Abort in make_node_from_operand on braced initializer in template

The changes for EDGcpfe/16312 introduced a regression in the handling of
certain braced initializers in templates (in GNU and Clang mode), causing the
front end to abort in make_node_from_operand (exprutil.c).  For example,
with "--g++ --no_defer_parse_function_templates":

  template<typename> void ft();
  struct S { void (*pf)(); };
  template<typename T> void g() {
    S s = { ft<T> };  // Previously triggered an abort in GNU and Clang
  }                   // modes during prototype instantiation.
 
This is now fixed.


5/23/16  [EDGcpfe/17220]
Front end erroneously selects copy constructor over trivial move constructor

In some situations, the front end erroneously selected an ordinary copy
constructor to copy an rvalue when a trivial move constructor is available.
This could result in spurious errors.  For example:

  struct A {
    A(int &&i): m(static_cast<int&&>(i)) {}
    int &&m;  // Causes the generated copy constructor to be deleted.
  };          // A also has a trivial move constructor.
  struct B {
    B(): a(1) {}  
    A a;
  };
  B g() {
    return B();  // Triggers the generation of B's move constructor, which
  }              // should select A's move constructor, but previously the
                 // deleted copy constructor was selected instead (causing
                 // an error to be issued).

This is now fixed.


5/23/16  [EDGcpfe/15481]
Incorrect processing matching template template argument with parameter

The processing to determine whether a template template argument matches
a template parameter was done incorrectly in some cases.  This could result
in a deduction or partial ordering failure or (as in the case below) an
abort (in get_template_arg_by_list_pos).  Now fixed.

  template<typename T, template<T> class TTP> struct A {
    static const unsigned value = 0;
  };
  template<template<int> class TTP> struct A<int, TTP> {
    static const unsigned value = 1;
  };
  template<int> struct B;
  template<long> struct C;
  int arr1[A<long, C>::value == 0 ? 1 : -1];
  int arr2[A<int, B>::value == 1 ? 1 : -1];


5/23/16  [EDGcpfe/15623]
Microsoft compatibility: abort on function template in in-class specialization

An abort could occur, in set_friend_info_for_prototype, when a friend
function template was declared inside a Microsoft in-class specialization.
Now fixed.

  template <class T> struct A {
    template <class U> struct B {};
    template <> struct B<double> {
      template <class V> friend void f() {}
    };
  };


5/23/16  [EDGcpfe/17179]
Folded initializer not rendered by C++-generating back end

The changes for EDGcpfe/16501 introduced a regression causing the C++-
generating back end not to render an initializer consisting of a functional-
notation style cast folded to an aggregate constant.  For example:

  constexpr struct S {
    explicit S() = default;  // Implicitly constexpr.
  } s = S();  // Previously "S()" was not rendered by the C++-generating
              // back end.

This is now fixed (although, in the case above, the constant is rendered as
"S{}").  The folded constant is now marked has having an explicit cast
applied.


5/23/16  [EDGcpfe/17187]
Destructions with --no_exceptions

A change (EDGcpfe/16372) had been made to suppress destructions in certain
cases when exceptions are disabled, but that change caused a regression in
a case like this (--c++11 --no_exceptions):

  extern "C" int printf(const char *,...);
  struct A {
    A(const void*) {}
    ~A() { printf("here\n"); }    // Not called previously.
  };
  int main() {
    int *pi = 0;
    A a{&pi};
    return 0;
  }

The change for EDGcpfe/16372 has been backed out (so the test above now works)
and the issue described in EDGcpfe/16372 has since been addressed by the
changes for EDGcpfe/16432.


5/23/16  [EDGcpfe/17173]
Default value for RUNTIME_SUPPORTS_SIZED_DEALLOCATION

The default value for RUNTIME_SUPPORTS_SIZED_DEALLOCATION had been TRUE,
but that caused build issues when ABI_COMPATIBILITY_VERSION is set to a
value less than 411.  It is now set to FALSE by default in those cases.


5/20/16  [EDGcpfe/17210]
Error on opaque enum declaration with typename

A spurious error could result if an opaque enum declaration specified
an underlying type using the "typename" keyword.  Now fixed.

  template <class T> struct A {
    typedef int Type;
    enum E : typename A<T>::Type;
  };


5/20/16  [EDGcpfe/17212]
Spurious errors on definition of member of class nested in class template

The changes for EDGcpfe/16371 triggered a regression in GNU C++ mode when
processing template arguments while parsing the definition of a member of a
class nested in a class template.  For example:

  template<typename> struct X {
    struct N {
      N(N const&);
      template<typename U> N(typename X<U>::N const&);
    };
  };
  template<typename T> X<T>::N::N(N const&) {}     // (1)
  template<typename T>
    template<typename U> X<T>::N::N(typename X<U>::N const&) {}
      // Previously erroneously considered a malformed redefinition of (1).

This is now fixed.


5/20/16  [EDGcpfe/17182]
Named return value optimization and braced initializers

The changes for EDGcpfe/16778 in version 4.11 introduced a regression by
failing to disqualify the "named return value optimization" (see the entry of
4/27/94) when a return statement in the function returns a braced initializer
list.  This resulted in invalid IL and generated code.  For example:

  struct S { S(); ~S(); };
  S f(bool b) {
    if (!b) return {};
    S s;
    return s;
  }
  S r = f(false);

Here, the front end erroneously considered the return value of f to be the
content of the variable s (mapped by lowering to the returned object).  The
default constructor was never called for the "return {};" statement.  This is
now fixed.


5/19/16  [EDGcpfe/16325]
Microsoft compatibility: commas in unexpanded macro argument text

The Microsoft preprocessor generally treats commas appearing in macro
arguments as not being macro argument delimiters when the argument appears
in a macro argument within the expanded text; see the entry of 4/15/06.
The front end previously only emulated this behavior when the macro
argument was used in its expanded form in the macro definition.  However,
the Microsoft preprocessor gives commas this special treatment even if the
expansion of the macro argument is suppressed by using the parameter as an
operand of the ## operator.  The front end has now been changed to do the
same.  For example, with --microsoft:

  #define CAT(a, b) CAT_I(a, )
  #define CAT_I(a, b) CAT_II(a##)  // "a" is used in unexpanded form
  #define CAT_II(a) a
  #define REM(a, b) a, b
  struct S { S(int, int); };
  S s(CAT(REM(0,0),));  // Previously expanded to "S s(0)" and warned of too
                        // many arguments in the invocation of CAT_II


5/19/16  [EDGcpfe/17207]
Variable template specialization not marked as constexpr

A variable template explicit specialization that was declared "constexpr"
was not being treated as constexpr.  Now fixed.

  template <class T> constexpr T x = 10;
  template <> constexpr int x<int> = 59;
  int arr[x<int>];


5/19/16  [EDGcpfe/16078]
Microsoft compatibility: operator template-ids in dependent member selection
expressions

In a template-dependent context, the Microsoft compiler does not accept the
"template" prefix in an expression like "x.template operator+<int>()" where
x is dependent.  However, previously the front end required the prefix during
prototype instantiations.  Now, in Microsoft C++ mode, the selection of an
operator name followed by a "<" token but not prefixed with "template" in a
template-dependent context is treated as if the "template" prefix were present.

Furthermore, when MSVC_IS_GENERATED_CODE_TARGET is TRUE, the C++-generating
back end now omits the "template" prefix in such cases.


5/19/16  [EDGcpfe/16807]
GNU/clang C++ compatibility: designated initializers and constexpr

The front end previously did not fully support the g++ and clang extension
of designated initializers in constexpr initializers: the initialization
was permitted, but the resulting object could not be used in a constant
expression.  This capability has now been added.  For example, with --clang
--c++11:

  constexpr struct {
    int x;
  } foo[] = {
    [0] = { 0 }
  };
  constexpr int bar = foo[0].x;  // Previously rejected as not constant


5/19/16  [EDGcpfe/17094]
Redundant ::template and operator names

In some modes, a "::template" prefix is accepted for a name that is not
followed by a template argument list.  The changes for EDGcpfe/15656 dropped
that relaxation for operator names.  Now, the previous behavior is restored
(while still addressing the problem fixed by the change for EDGcpfe/15656).
For example:

  template<typename T> class A {
    template<typename U> void operator<<(U const&);
  };
  template<typename T>
    template<typename U>
      void A<T>::template operator<<(U const&) {}
        // Extraneous "template" now accepted in GNU and Microsoft modes.


5/19/16  [EDGcpfe/16801]
Core issue 393: Reference/pointer to unknown-bound array in parameter type

C++ originally prohibited parameters that are pointers or references to arrays
of unknown bound (i.e., a parameter declaration like "int (&p)[]").  The
resolution of Core issue 393 (and its duplicate 550) lifts that restriction
and the front end now permits such parameters in all modes.  For example:

  void g(double (&z)[]);  // Now allowed in all C++ modes.

The front end already relaxed the old restriction in various modes, in part
under control of DEFAULT_PTR_TO_UNKNOWN_BOUND_ARRAY_ALLOWED_IN_PARAM_TYPE and
DEFAULT_REF_TO_UNKNOWN_BOUND_ARRAY_ALLOWED_IN_PARAM_TYPE: Those macros are no
longer used by the front end.


5/19/16  [EDGcpfe/17199]
Variable template specialization issues

Explicit specializations of variable templates were not handled properly
in some cases.  A spurious error would result if the variable template
was declared constexpr.  In addition, a spurious error was issued if
the type of the specialization did mot match the type that would have
resulted from the instantiation of the template.  Now fixed.

  template <typename T> constexpr T x = T { 1.1 };
  template <> constexpr int x<int> = 4;


5/18/16  [EDGcpfe/17196]
Variable template not accepted in using-declaration

A using-declaration of a variable template results in a spurious
"argument list ... is missing" error.  Now fixed.

  namespace N {
    template <class T> T x = T();
  }
  using N::x;
  int i = x<int>;


5/17/16  [EDGcpfe/16812]
Microsoft C++ compatibility: Class type temporaries in conditional operators

The front end normally attempts to avoid creating unneeded temporary copies
of class type objects in various contexts, including conditional operators.
However, in Microsoft C++ mode it avoids the elision of a temporary copy of
one of the operands of a conditional operator if that operand is an lvalue
operand.  For example:

  struct X {
    X();
    X(X const&);
    X(X&&);
  };
  X g() {
    X x;
    return true ? x : X();  // Previously did not call the copy constructor
  }                         // to return the value of x.  Now, the copy is
                            // made in Microsoft C++ mode.

5/18/16  [EDGcpfe/15648]
Microsoft compatibility: spurious errors with Microsoft nonreal base classes

Spurious "duplicate base class" and "redeclaration of member function"
errors could occur in Microsoft mode as a result of Microsoft nonreal base
class processing.  The out-of-class definition of the constructor
caused such errors to be issued on the base class and constructor
declarations in B.  Now fixed.

  template <typename T> struct A {
    A();
    A(const A<T> & a){}
  };
  template <typename T> struct B: A<T> {
    B() : A<T>(){};
    B(const B<T> & b);
  };
  template <typename T> struct C: B<T> {
    template <typename T1> B<T> f();
  };
  template <typename T> B<T>::B(const B<T> & b) : A<T>(b) { }


5/17/16  [EDGcpfe/17124]
Incorrect column positions after a multibyte character and a line splice

When a line in the source code contains both a multibyte character and a
line splice, the front end incorrectly calculated the column positions of
tokens on the physical line following the splice.  This is now fixed.  For
example (with --multibyte_chars --unicode_source_kind=UTF-8, where the
character in the comment is the UTF-8 encoding of 'e' with a grave accent),
the caret in the error message diagnosing "x" as undefined pointed to the
space before the identifier:

  int j = /* è */ \
   x;


5/17/16  [EDGcpfe/16873]
Internal error on nontype template argument first deduced as array bound

An internal error could occur (in copy_template_param_con) when a
nontype template argument has its value first deduced from an array
bound and is then used later in a nondeduced context.  Now fixed.

  template <bool> struct A { typedef void type; };
  template <unsigned O> struct B {
    template <typename T, unsigned N,
              typename E = typename A<(N > O)>::type>
    static auto f(T (&t)[N]) -> unsigned char(&)[N - O];
  };
  template <class T, unsigned N> auto f(T (&t)[N]) -> decltype(B<4>::f(t));
  char arr[]{0, 0, 0, 0, 1, 2};
  static_assert(sizeof(f(arr)) == 2, "error");


5/17/16  [EDGcpfe/15566]
Microsoft compatibility: handling of member function qualifiers in deduction

In Microsoft mode we emulated a Microsoft bug where member function
qualifiers were sometimes ignored in template argument deduction.  This
seems to have been corrected in recent versions of the Microsoft compiler.
We now only do this emulation when microsoft_version < 1700.  See the entry
for EDGcpfe/9743 on 4/28/09 for information about the original change.

  struct A {
    void f() const {}
    void f() {}
  };
  template<typename T> void g(void (T::*f)() const) {}
  int main() {
    g(&A::f);  // Formerly "no instance ... matches"
  }


5/17/16  [EDGcpfe/16761]
C++/CLI: Lookup of default properties

In C++/CLI mode, when default properties are inherited from base classes at
different derivation depth, the "deeper" declarations were not always found
(a failure of "hide-by-sig" lookup), which in turn could lead to spurious
errors.  For example:

  class X {};
  ref struct B {
    property int default[int] {
        int get(int) { return 0; }
    }
  };
  ref struct C: B {
    property int default[X] {
        int get(X) { return 1; }
    }
  };
  ref struct D: C {};
  void g(D^ hd) {
    hd[0];  // Previously triggered an error because B::default::get was not
  }         // found.  Now accepted.

This is now fixed.


5/17/16  [EDGcpfe/16712,EDGcpfe/16713]
C++17 compatibility: Add nested namespace definitions

The front end now accepts nested namespace definitions as outlined in N4230
in C++17 mode as well as when microsoft_version >= 1903.  For example:

  namespace A::B::C {}
  // Equivalent to: "namespace A { namespace B { namespace C {}}}"


5/17/16  [EDGcpfe/16839]
Default constructor initializers and class templates

The front end no longer checks implicit constructor initializers when parsing
a constructor in its generic form.  This avoids some problems that can occur
during that parsing; in particular, a spurious error could occur in Microsoft
mode:

  template<typename T> struct B {
    B(T = T());
  };
  template<typename T> struct D: B<T> {
    D() {}  // Previously an error with "--microsoft --parse_templates"
  };        // ("no default constructor exists").  Now accepted.

Previously, this example elicited an error in Microsoft mode with prototype
instantiations of nonclass templates enabled (option "--parse_templates")
because the implicit initializer for the base class B<T> cannot reliably
determine whether B<T> has a default constructor.  Now that check is not
performed and the code is accepted.

This also generalizes the change for EDGcpfe/16896 to apply to all modes.


5/16/16  [EDGcpfe/15094,EDGcpfe/14777]
GNU C++ compatibility: disambiguation and qualified names

Disambiguation is supposed to be "syntactic", but g++ considers whether
an identifier is qualified when determining whether a name is a nested
declarator or an expression in disambiguation.  We now emulate this in
g++ mode.

  struct B {
    enum E {e};
    B(int i) {}
    void f(int){}
  };
  int main() {
    B g(B(B::e));  // now declares object in g++ mode
    g.f(1);
  }

5/16/16  [EDGcpfe/15937]
Spurious error on Microsoft-mode constructor declaration in template

Version 4.5 introduced a change that caused certain nonreal classes used as
base classes to have actual instantiations done on them in Microsoft mode.
During such instantiations, constructors with explicit template arguments were
not always handled correctly, causing the front end to emit spurious errors
claiming the type associated with the constructor name does not match the
enclosing class type.  For example:

  template<typename T, int N> struct B {
    B<T, N>() {}
  };
  template<int N> struct D : B<int, N> {};
    // Previously triggered a spurious error on the constructor of B<int, N>.

This is now fixed.


5/16/16  [EDGcpfe/16878]
Attempt to form a pointer or reference to qualified function type not always
treated as SFINAE

Forming a pointer or reference to a qualified function type is invalid, but
doing so through template parameter substitution is subject to SFINAE.  The
front end, however, only applied the SFINAE rules in the reference case and
only if the qualified function type was not expressed through a typedef or
alias.  This is now fixed.


5/16/16  [EDGcpfe/16650]
Issues with nested inline namespaces and overloaded functions

Name lookup did not produce the correct result in some cases involving
nested inline namespaces containing overloaded functions.  Now fixed.

  namespace N1 {
    inline namespace I1 {
      void f1(int) {}
      inline namespace I2 { void f1(int, int) {} }
    }
  }
  namespace N2 {
    inline namespace I2 {
      void f2(int) {}
      inline namespace I2 { void f2(int, int) {} }
    }
  }
  using N1::f1;
  using namespace N2;
  void g() {
    f1(10);  // spurious "too few arguments"
    N2::f2(10);  // spurious "too few arguments"
  }


5/13/16  [EDGcpfe/16955]
__builtin_addressof

The builtin, __builtin_addressof, has been added in Clang and Microsoft
emulation modes.  See http://clang.llvm.org/docs/LanguageExtensions.html for
information.  For example (with --clang):

  int fail = 0;
  int main() {
    const int ci = 22;
    int i = 33;
    volatile int vi = 44;
    const volatile int cvi = 55;
    if (__builtin_addressof(i) != &i) fail++;
    if (__builtin_addressof(ci) != &ci) fail++;
    if (__builtin_addressof(vi) != &vi) fail++;
    if (__builtin_addressof(cvi) != &cvi) fail++;
    return fail;
  }


5/13/16  [EDGcpfe/17183]
C++14 constexpr: Accessibility and address comparisons

Comparing pointers to fields of the same class type does not produce a
constant expression if the fields have different accessibility.  The C++14
interpreter previously used the wrong accessibility to check this criterion
in some cases.  For example:

  struct S {
    constexpr S(): i(1), j(2), k(3) {};
    constexpr bool nonconstant() const { return &i < &k; }
    int i;
    int j;
  private:
    int k;
  };
  
  constexpr S s{};
  constexpr bool b = s.nonconstant();
     // Previously erroneously accepted.  Now an error (because k is private
     // and i is not).

This is now fixed.


5/13/16  [EDGcpfe/16715]
Microsoft compatibility: Enable member initializers for aggregates

The changes described in the Changes entry for EDGcpfe/14146 are now also
enabled when microsoft_version >= 1903.


5/13/16  [EDGcpfe/17091]
C++/CX: Abort on __is_ref_array

Most invocations of __is_ref_array aborted in C++/CX mode.  That is fixed now.


5/13/16  [EDGcpfe/17107]
C++-generating back end: Generic GNU built-in rendered with concrete name

The changes for EDGcpfe/16510 introduced a regression in the C++-generating
back end, causing it to render an invocation of a "generic" GNU built-in
function (e.g., __atomic_store_n) using its concrete ABI name for that
particular call (e.g., __atomic_store_8).  For example:

  struct S {
    void f() { __atomic_store_n(&v1, v2, 0); }
      // Previously rendered as __atomic_store_8(&(v1), v2, 0);
    int *v1, *v2;
  };

This is now fixed.


5/13/16  [EDGcpfe/17133]
Abort on nonstandard anonymous union with default initializer in template

In configurations that accept nonstandard anonymous unions in C++11 mode, the
front end triggered an internal error during IL lowering (in lower_constant)
after attempting to instantiate a class template containing a nonstandard
anonymous union with a default member initializer.  For example:

  template<typename T> struct S {
    struct {
      float f = 0;
    };  // Nonstandard anonymous union.
  };
  S<int> si;

This is now fixed.


5/12/16  [EDGcpfe/17174]
Missing diagnostic on invalid use of "operator auto"

When deduced return types are enabled (e.g., in C++14 mode), the front end
erroneously accepted explicit invocations of "operator auto" on an object with
a conversion function template.  For example:

  struct S { template<typename T> operator T(); };
  void g() {
    S().operator auto();  // Previously accepted; now an error.
  }

This is now fixed (i.e., an error is now issued in such cases).


5/12/16  [EDGcpfe/17148]
Exception stack handling incorrect at run time

In configurations where DO_FULL_PORTABLE_EH_LOWERING and
LOWERING_REMOVES_UNNEEDED_CONSTRUCTIONS_AND_DESTRUCTIONS are both TRUE,
it was possible for lowering to emit code to modify the global variable
__eh_curr_region in cases where no exception stack had been pushed onto
the stack (potentially resulting in incorrect behavior at run time during
exception handling).  Now fixed.  For example (with -x):

  struct A {
    ~A() { while(0); }
  };
  struct B {
    ~B() { /* Must be empty. */ }
  };
  void f() {
    B b;
    for (;;) { break; }
    throw 1;
  }
  int main() {
    A a;
    try {
      f();
    } catch (...) { }
  }


5/12/16  [EDGcpfe/17146]
Initialization of some multi-dimensional arrays could result in overrunning
array bounds

In configurations with lowering, certain initialization of multi-dimensional
arrays could end up overrunning the bounds of the array at run time.  In
the example below, a helper routine had been invoked to initialize 3600 entries
((10-1)*20*20) rather than 180 ((10-1)*20):

  struct A {
    int x;
    constexpr A() : x(37) {}
  };
  int main() {
    A a;
    new A[10][20]{ {a} };
    return 0;
  }


-------------------------------------------------------------------------------
Version 4.11, May 12, 2016

5/9/16   [EDGcpfe/17160]
Eliminate warnings when compiling with Visual Studio in 64-bit mode

A number of places in the front end assume that a pointer can be converted
to a host unsigned long without loss of data.  Such conversions cause
warnings when the front end is compiled by Microsoft Visual Studio in
64-bit mode.  A change has been made to eliminate some of the conversions.
In other cases the remaining conversions now use the new
possible_lossy_cast_from_pointer macro to allow the conversion without
warning.


5/8/16   [EDGcpfe/17118]
C++14: Variable templates

C++14 variable templates (the initial specification of which was specified
in N3641) are now supported.

  template <typename T> T x = 1;
  int main() {
    return x<int> + x<double>;
  }


5/8/16  [EDGcpfe/17166]
IL changes for variable templates (IL CHANGE)

The addition of variable templates and their instantiations required a
number of changes to the IL.  Most of these were done to provide more
uniform names for entities, but there were a few structural changes.  The
most significant structural change was moving some template-related fields
out of the a_variable entry into a separate a_variable_template_info
entry.  The template_arg_list and assoc_template fields are the fields
formerly in a_variable.  The new entry is pointed to by the template_info
field of a_variable.

The following names were changed or added:
  - in a_variable, is_template_static_data_member -> is_template_variable
  - in a_variable, is_nonreal was added
  - a new templk_variable kind was added
  - a new sk_variable_template symbol kind was added
  - in a_template_symbol_supplement, the static_data_member variant was
    renamed variable


5/5/16   [EDGcpfe/17108]
Spurious error in const static data member initializer in GNU C++ mode

In GNU C++11 modes, the front end previously issued a spurious error when a
const static data member of non-dependent type is initialized with a dependent
expression containing a potentially-constant call-like construct.  For example:

  template<typename> struct S {
    constexpr operator int() const { return 42; }
  };
  template<typename T> struct X {
    static const bool B = S<T>() == 42;  // Previously triggered a spurious
  };                                     // error.

This is now fixed.


5/4/16   [EDGcpfe/8647,EDGcpfe/8225]
GNU C++ compatibility: template parameter name declared as function parameter

g++ allows a template parameter name to be used as a function parameter
name, hiding the template parameter.  Such hiding is not allowed by
the standard.  We now accept this (with a warning) in g++ mode.

  template<int I, void (*fp)(int I)> static void f() {
    fp(I); 
  }


5/4/16   [EDGcpfe/17115]
Reference to non-const erroneously treated as constant-valued

The front end previously incorrectly allowed a reference to a non-const
object to appear in a constant expression.  This is now fixed.  For example,
with --strict --c++11:

  void f() {
    static constexpr int &&r = 2;
    r = 1;
    static_assert(r == 2, "Fail");  // Previously succeeded, now correctly
                                    // diagnosed as not a constant expression
  }


5/4/16   [EDGcpfe/17147]
Undefined behavior in std::initializer_list<T>::end

Previously, the implementation of std::initializer_list<T>::end provided with
the front end returned the expression

    this->__array + this->__length

which technically resulted in undefined behavior for empty initializer lists,
where __array is a null pointer and __length is zero.  (Although this is
usually benign with most code generators, the constexpr interpreter -- see
entry for EDGcpfe/14149 -- must diagnose any undefined behavior.) This is now
fixed.


5/3/16   [EDGcpfe/17123]
Sign extension for folding subscripted character string literal

The front end previously failed to do sign extension when folding a
subscripted reference to a character string literal in a configuration
in which TARG_HAS_SIGNED_CHARS is TRUE.  This is now fixed.  For
example, with --strict --c++11:

  bool f() {
    constexpr const char* p = "\200";
    return p[0] == '\200';   // Previously returned false with signed chars
  }


4/29/16  [EDGcpfe/17127]
Rename DEFAULT_CPP11_MODE to DEFAULT_CPP_MODE

Rather than have a binary configuration macro to enable/disable each
version of the C++ standard, a new configuration macro, DEFAULT_CPP_MODE,
has been introduced.  Its value should correspond to the value of the
__cplusplus predefined macro in the desired standard (e.g., 201402 for C++14).
The default remains 199711.  If DEFAULT_CPP11_MODE is TRUE, DEFAULT_CPP_MODE
will be set to 201103.


4/28/16  [EDGcpfe/17121]
Microsoft compatibility: emulating Visual Studio Update 1 and Update 2

Visual Studio 2015 has been incrementally upgraded, including the release of
new features, without updating the release number (i.e., 19.00), making it
difficult to specify the set of features that should be supported by the front
end when emulating Visual Studio.  A change has been made to map the
microsoft_version value of 1901 to Update 1 (build number 23506) and 1902 to
Update 2 (build number 23918).  These are used purely for internal distinction
between these releases; the value of MSC_VER is still 1900 in both cases, for
compatibility with the corresponding Visual Studio releases.

Variable templates are now enabled when microsoft_version >= 1902.


4/28/16  [EDGcpfe/17113]
GNU compatibility: default to C++14 mode when gnu_version >= 60000

GCC 6.1.0 has enabled C++14 features by default.  Accordingly, when
gnu_version >= 60000 and no explicit C++ mode has been specified, C++14
features are now enabled in GNU emulation mode.


4/21/16  [EDGcpfe/17066]
constexpr decltype(auto)

In C++14 mode, the front end previously failed to treat variables declared
with constexpr and decltype(auto) as const.  That is now fixed.


4/20/16  [EDGcpfe/17017]
Union failed to match template template parameter

An instance of a union template failed to match a function template
parameter based on a template template parameter.  Now fixed.

  template <template <typename> class TT, class T> void f(TT<T>) {}
  template <typename T> union U { };
  int main() {
    f(U<int>());
  }


4/14/16  [EDGcpfe/16840]
GNU compatibility: alignas on a typedef

The C++ standard does not allow alignas on a typedef, but GNU accepts it.
The front end now gives a warning instead of an error on such cases.
For example (with --c++11 --g++):

  typedef int A alignas(8);
  typedef int B __attribute__((aligned(8)));
  A a;
  B b;
  static_assert(alignof(a) == 8, "Oops");
  static_assert(alignof(b) == 8, "Oops");


4/14/16  [EDGcpfe/17028]
Incorrect expansion of nested pack expansion

In some cases the use of a nested pack expansion could result in an incorrect
value being used in the outer expansion.  Now fixed.

  #include <stdio.h>
  inline int f1(int a1, int a2) {
    return a1 + a2;
  }
  inline int f2(int a1, int a2) {
    return a1 + a2;
  }
  template <class ... Args> inline int g(Args ... args) {
    // Incorrect value used for "+ args" in some cases
    int i = f1(f2(args ...) + args ...);
    return i;
  }
  int main() {
    int result = g(2, 20);
    printf("%d\n", result);  // should be 66, was 84
  }


4/13/16  [EDGcpfe/17016]
Template substitution of sizeof/alignof

The front end previously failed to treat as a failure (error or SFINAE) certain
substitutions of sizeof with an operand of incomplete type or function type.
For example:

  template<typename U, int N = sizeof(U)> int g();
  struct I;
  int r = g<I>();  // Now an error.  Previously erroneously accepted with
                   // N == 0.

This is now fixed (as is the similar problem with alignof).


4/13/16  [EDGcpfe/17063]
routine_might_exist_in_multiple_copies for member functions

In cases where routine_might_exist_in_multiple_copies is called on a member
function and its parent class has multiple enclosing routines, the result
had been based on the immediately enclosing function and not the outermost
enclosing function.  That had resulted in spurious mangling differences
for the abi_tag mangling.  For example (with --gnu_version 60000 --c++11):

  inline namespace N __attribute__((abi_tag("abi_tag"))) {
    struct A { };
  }
  inline void f() {
    struct T {
      void g() {
        struct S {
          A h() {}    // Now incorporates implicit abi_tag mangling for A.
        };
        S().h();
      }
    };
    T().g();
  }
  void F() {
    f();
  }


4/12/16  [EDGcpfe/14159]
Value category of conditional operators with one throw operand

The resolution of core issues 1550 and 1560 resulted in the value category of
a conditional operator where either the second or third operand (but not both)
is a throw expression, to be the value category of the other operand.  The
front end now implements the revised rule (except in non-Clang GNU modes and
Microsoft modes).  For example:

  void f(bool b) {
    int i;
    int& r = b ? throw 0.0 : i;  // Previously an error.  Now okay.
  }


4/11/16  [EDGcpfe/16709]
User-defined literals in member functions and templates

The front end previously reported spurious errors when a user-defined
literal appearing in a member function or in a template relies on a
using-directive in that same function or template to find the associated
literal operator or literal operator template.  This is now fixed.  For
example, with --c++11:

  namespace NS {
    double operator "" _w(long double d) {
      return d;
    }
  }
  struct S {
    void f() {
      using namespace NS;
      double d = 2.3_w;  // Previously reported literal operator not found
    }
  };


4/11/16  [EDGcpfe/17042]
Constexpr conversion functions and templates

The front end sometimes issued spurious "expression must have constant value"
diagnostics in templates because it failed to consider constexpr conversion
functions.  For example:

  template<typename T> struct S {
    constexpr operator int() const { return 42; }
  };
  template<typename T> int g(S<T> p) {
    constexpr int r = p;  // Previously triggered a spurious error.
    return r;
  }

That is now fixed.


4/8/16   [EDGcpfe/16896]
Clang/GNU/Microsoft compatibility: Missing member initializer diagnostics

In Clang, GNU, and Microsoft C++ modes, the front end no longer diagnoses
missing member initializers for reference or const members when parsing a
constructor definition in its generic form.  For example:

  template<typename> struct S {
    S() {}    // Missing initializer for ri is no longer diagnosed in
    int &ri;  // some modes.
  };

(Note that a diagnostic was previously typically not emitted in Microsoft mode,
because by default no prototype instantiation of the constructor is performed
in Microsoft modes.)


4/7/16   [EDGcpfe/16321,EDGcpfe/17009]
GNU compatibility: Spurious error caused by incorrect disambiguation

The disambiguation rules have been updated to disqualify a template-id from
being used as a declarator, thereby getting rid of a spurious error in cases
like this (with --g++):

  template <class T> struct A { };
  struct B {
    B(A<int> a);
  };
  void foo () {
    B(A<int>());
  }


4/6/16   [EDGcpfe/16809,EDGcpfe/17014]
"operator" string appearing in mangled names

In certain cases, the string "operator", rather than a mangled representation
of an operator, had appeared in mangled names (in both IA-64 and Cfront ABIs).
Now fixed.  For example:

  struct A {
    operator int ();
    template <typename T> int operator-();
  };
  typedef int (A::*P)();
  template <P> struct S {};
  template <typename T> void g(S<&T::template operator-<double> >) {}
  template void g<A> (S<&A::operator-<double> >);


4/4/16   [EDGcpfe/17006]
Representation of typeid(x)  (IL CHANGE)

The front end has two representations for typeid(x): enk_typeid expression
nodes, and ck_address/abk_typeid constant entries.  Until now, the latter was
mostly used in Microsoft mode to handle the use of typeid constructs in
template argument contexts.  However, C++11 made typeid(x) a valid core
constant expression if x is not an lvalue of polymorphic class type.  In such
cases, the front end now always uses the ck_address/abk_typeid representation.


4/4/16   [EDGcpfe/17004]
Diagnostic performance degradation in 4.10.1

The diagnostic processing restructuring in 4.10.1 (see EDGcpfe/16084 on
3/11/15) could result in a degradation of performance in compilations
that issued a large number of diagnostics.  This was the result of
can_locate_source_line being called twice for most diagnostics instead of
once.  This is not an issue for the most common case (where a diagnostic
is being issued on the current source line), but had a significant cost
when the source file had to be re-read to fetch the source line.  This
has been fixed by having can_locate_source_line save the result of the
most recent request so that the second of two consecutive requests for
the same location has virtually no cost.


4/4/16   [EDGcpfe/16913]
C++-generating back end: array-to-pointer decay in non-type template arguments

The C++-generating back end previously incorrectly added a cast to a
non-type template argument when the argument is an array variable and the
corresponding template parameter is a pointer to the element type with
added cv-qualification.  This is now fixed.  For example:

  template<const char *> struct S { };
  char x[10];
  S<x> y;   // Previously generated as S<(const char *)s>


4/4/16   [EDGcpfe/16844]
Accept enumerators as argument to alignas

Previously a spurious error was given when an enumerator was used as the
argument to the alignas alignment specifier.  For example (with --c++11):

  enum { sixteen = 16 };
  alignas(sixteen) int v = 99;


4/4/16   [EDGcpfe/16915]
GNU compatibility: incorrect walking of function multiversioning routine

The "walking" of a target-specific version routine had incorrectly walked the
targeted_version.representative routine as a pointer to a list, resulting
in undefined behavior.  A stack overflow could occur in extreme cases, for
example (with --gnu_version 40800):

  #pragma GCC push_options
  #pragma GCC target("avx")
  void f1() {};
  void f2() {};
  void f3() {};
  /*...*/
  void f9999() {};


4/4/16   [EDGcpfe/17003]
GNU compatibility: mangling of template argument packs in the IA-64 ABI

The IA-64 ABI had originally used "I" when mangling template argument packs
but was updated to use "J" instead.  The front end, in GNU emulation modes,
had also used "I" when emulate_gnu_abi_bugs was TRUE, but recent (later than
5.0.0) versions now use the updated mangling so a change has been made when
gnu_version >= 50000.  There is no change for the Cfront ABI.  For example
(with --gnu_version 50100 --c++11 --set_flag emulate_gnu_abi_bugs):

  template <typename... Args > void foo(Args...);
  void f(int args) {
     foo(args);  // Had been: _Z3fooIIiEEvDpT_ now _Z3fooIJiEEvDpT_
  }


3/30/16  [EDGcpfe/12133,EDGcpfe/14797,EDGcpfe/14854,EDGcpfe/16453,
          EDGcpfe/16847,EDGcpfe/16849,EDGcpfe/16912]
GNU compatibility: Additional support for GNU vector operations (IL CHANGE)

Additional support has been added for GNU vector operations.  In particular,
a number of new vector operations have been added to the IL.  New operations
were added in cases where the result type of the operation is different
than what would normally be expected.  For example, the logical and
relational operations when applied to vector operands return a vector of
integer element types (even if the operands have non-integer element types).
The new eok_vector_land and eok_vector_lor types are somewhat unique in
that they accept mixed scalar and vector types.  A new compiler-generated
eok_vector_fill operation indicates when a scalar value (used in a
mixed scalar-vector operation) is converted to a vector value.  These
new vector operations are not lowered (though their operands are).

Although not strictly speaking an IL CHANGE, a back end must now be prepared
to handle the new vector operations.


3/29/16  [EDGcpfe/16991]
GNU/clang C++ compatibility: T[] considered the same as T[0]

In g++ and clang modes, a zero sized array was incorrectly considered to
be the same as an array of unknown bound in many contexts.  Now fixed.

  template <typename> struct A {};
  template <typename T> struct A <T[]>{};
  template <typename T> struct A <T[0]>{};  // spurious error
  int main() {
    A<int[]> a1;
    A<int[0]> a2;
    return &a1 == &a2;  // missing "incompatible types" error
  }


3/25/16  [EDGcpfe/16963]
Assertion failure in corresponding_base_class

In cases where lowering is initializing the __vptr field in a constexpr
initialization, an assertion failure ("corresponding_base_class: base class not
found") could occur if a derived class shares a virtual function table with an
ambiguous base class.  For example, with --c++11 --no_exceptions:

  struct B1 {
    virtual ~B1() {}
  };
  struct B2 : B1 {};
  struct B3 : B2, B1 {} b3;


3/24/16  [EDGcpfe/16969]
Missing initialization of lowered constexpr array

In cases where constexpr initialization results in a dik_nonconstant_aggregate
where an empty aggregate constant is used to initialize an array, that
array initialization had not been incorporated into the lowered IL, resulting
in uninitialized array elements at run time.  Now fixed.  For example, with
--c++11:

  struct A {
    unsigned int m[10];
    constexpr A() : m() { }
  };
  struct B { };
  struct C {
    B b;
    A a;
  };
  int main() {
    unsigned int sum = 0;
    C c = { B(), {} };            // c.a.m had been uninitialized
    for (int i = 0; i < 10; i++)
      sum += c.a.m[i];
    return !(sum == 0);
  }


3/23/16  [EDGcpfe/16965]
Position range for generated operator calls

When the use of an operator results in the call of an overloaded operator,
the source position range (see an_expr_node::expr_range) is recorded in the
topmost node of the IL representing the operator invocation.  This node is
not always the actual call node, because of transformations on the return
type of the operator function or temporaries created to hold the return
value.  In such cases, the source position range is now also recorded in the
actual call node.  For example:

  struct S {
    S(S const&);
    S operator++(int);
  };
  void g(S s) {
    s++;
  }

The expression "s++" results in an IL tree where the topmost node is an
enk_temp_init node representing the allocation and initialization of a
temporary for the return value of the operator++ function: That node records
the source range of the expression "s++".  The actual call node (an operator
node of kind eok_dot_member_call) previously did not record a source range,
but now it records the same range as the topmost node.


3/22/16  [EDGcpfe/16541]
Incorrect SFINAE handling of variadic templates and explicit template arguments
leads to spurious errors

In some relatively complex circumstances, the front end did not correctly
substitute explicit template arguments in a variadic function template.  This
was likely to result in spurious errors.  For example:

  template<int N, typename... Ts> struct R {};
  template<int N, typename T0, typename... TTs> struct R<N, T0, TTs...>
                                                : R<N+1, TTs...> {
    static T0& hd(R&);
    R();
  };
  template<typename... Ts> struct S : public R<0, Ts...> {
    S(const Ts&... aTs);
  };
  template<int N, typename... Ts>
  auto getR(R<N, Ts...> &r) -> decltype(R<N, Ts...>::hd(r));
  template<int N, typename... Ts>
  auto getS(S<Ts...> &s) -> decltype(getR<N>(s));
  template<typename R> struct A {
    template<typename... Args> static int f(S<Args...>& args) {
      return getS<1>(args);
    }
  };
  void g() {
    S<int, int, int> args(11, 22, 33);
    A<void>::f(args);
  }

Here the partial substitution of getS<1> in the call getS<1>(args) produced
an incorrect type for getR<N>.  That triggered a spurious SFINAE failure, which
in turn caused the call getS<1>(args) not to find a matching function template.
This is now fixed.


3/22/16  [EDGcpfe/16962]
Clang C++ compatibility: generation of __restrict__ from token cache

When the C++-generating back end is being used, and a template is being
generated from the cached token representation (rather than IL), the
"__restrict__" keyword was emitted as "restrict".  While clang accepts
"restrict" in C mode, it does not accept it in C++ mode.  The "__restrict__"
form is now used when clang is the generated code target.  The example
below was emitted as "restrict" if the "--clang --no_parse_templates"
options were used.

  template <class T> void foo(int * __restrict__ p) { }


3/21/16  [EDGcpfe/16871]
__is_trivially_constructible

Previously, the type traits helper __is_trivially_constructible incorrectly
produced a false value for a class that is trivially constructible but not
trivially destructible.  This is now fixed.


3/21/16  [EDGcpfe/16871]
__is_pod and array types

The __is_pod type traits helper previously failed to consider the element
type of an array.  For example:

  struct D { ~D(); };
  static_assert(!is_pod(D[2]), "Unexpected");

Previously, this assertion check failed; now it is accepted.


3/21/16  [EDGcpfe/16871]
Microsoft C++ compatibility: Type traits helpers and deleted special members

In Microsoft mode, deleted special members are never treated as "trivial"
in the context of queries using type traits helpers.  For example:

  struct D {
    D();
    D& operator=(D const&) = delete;
  };
  static_assert(!__has_trivial_assign(D), "Standard");

In normal C++11 modes, the static_assert above should fail because the
copy assignment operator is considered trivial since it is deleted on its
first declaration.  However, in Microsoft C++ mode (with microsoft_version
>= 1800), the static_assert construct is accepted.


3/21/16  [EDGcpfe/16871]
Microsoft C++ compatibility: __is_trivially_copy_assignable

In Microsoft C++ mode, the front end now accepts the type traits helper
__is_trivially_copy_assignable.


3/21/16  [EDGcpfe/16831]
Missing parentheses in pack expansion passed to initializer_list constructor

In configurations that generate template definitions from prototype
instantiations, the C++-generating back end failed to parenthesize an
expression that is a pack expansion in the argument to an initializer_list
constructor.  This could result in incorrect code, since the ellipsis would
apply to the last subexpression instead of to the expression as a whole.
This is now fixed.  For example, with --c++11:

namespace std {
  template<class T> struct initializer_list {
    constexpr initializer_list(const T *x, unsigned long y) { }
  };
}
struct S {
  int x;
  static int f(std::initializer_list<int>);
  template<class... Ts> S(Ts&&... ts) :
    x(f({(ts+1)...})) { }  // Previously generated as f({ts+1...})
};


3/21/16  [EDGcpfe/14149]
C++14: Relaxed constexpr constraints

In C++14 mode, the front end now relaxes some of the C++11 constraints imposed
on constexpr functions.  In particular, C++14 constexpr functions can contain
multiple statements, including loops.  For example:

  constexpr unsigned long fact(unsigned long p) {
    unsigned long r = 1;
    while (p > 1) r *= p--;
    return r;
  }
  static_assert(fact(4) == 24, "Unexpected");  // Accepted in C++14 mode.

These changes required the addition of an IL interpreter to the front end: It
is mostly contained in the new source file "interpret.c".

(See also the Changes entry of 2/22/16 for EDGcpfe/16892: It describes new
options to control how much effort the front end should expend on evaluating
constant-expressions.)


3/21/16  [EDGcpfe/16834]
Scalars initialized with brace-enclosed pack expansions

The front end previously could not fully represent a template containing a
scalar of known type initialized with a braced initializer containing a pack
expansion.  As a result, such constructs were not rendered correctly by the
C++-generating back end.  For example:

  struct S {
   int x;
   template<typename ... Ts> S(Ts &...ps): x{ps...} {}
     // The mem-initializer "x{ps...}" was previously rendered in the
     // C++-generating back end without the pack expansion.
 };

This is now fixed.
 

3/21/16  [EDGcpfe/16860]
Field designators in templates (IL CHANGE)

In GNU C++ mode, the front end accepts designated initializers, but it
previously didn't permit them in templates.  The representation of designators
in the IL has now been changed to handle designators in generic contexts (i.e.,
without identifying the designated subobject).  For example:

  template<typename T> void g() {
    T x = { .field = 3 };  // Previously an error.  Now accepted in g++ mode.
    return x.field;
  };

This example previously triggered an error in GNU C++ modes when deferral of
prototype instantiations was disabled; it is now accepted.  (Array designators
with template-dependent subscripts are still not handled, but the new IL
representation will be able to accommodate them if needed.)


3/18/16  [EDGcpfe/16952]
Performance issue with constexpr member function in deeply-nested base class

The front end previously exhibited very poor performance when a constexpr
non-static member function is invoked in a non-constant context using a
pointer to a derived class in a deep inheritance hierarchy.  This is now
fixed.


3/18/16  [EDGcpfe/16875]
C++-generating back end: Rendering of GNU C99 inline functions

Traditionally, GCC interprets "extern __inline__" specifiers as a way to
indicate that a function definition should be used for inlining, but should
not be emitted in an object file.  However, in newer versions of GCC this is
not always the case, particularly in C99 mode.  The C++-generating back end
previously assumed the traditional GCC behavior (when targeting GCC); now
it takes into account the mode (like C99) in which the source is compiled.
For example:

  __inline__ int f() { return 42; }
  int main() { return f(); }

compiled with "--gnu_version=40600 --c99" previously produced:

  extern __inline__ int f() { return 42; } 
  int main() { return f(); } 

Now the "extern" keyword is no longer added.


3/16/16  [EDGcpfe/16741]
Internal error caused by variadic type based on error type

A lookahead done in abstract declarator processing could result in
the evaluation of a pack element that should instead be bypassed
because the pack is empty, resulting in an error type being passed
through the IL.  This could result in an internal error in name mangling
(in mangled_encoding_for_type_full in the example below).  Now fixed.

  template <typename T> struct A {};
  template <typename U> using B = U;
  struct C {};
  template <typename... Ts> struct D {
    using E = B<C(A<Ts>...)>;
  };
  D<> f() { return {}; }


3/15/16  [EDGcpfe/16919]
C++/CLI: Spurious "multiple overrides" diagnostics

Using recent versions of mscorlib.dll shipped by Microsoft frequently results
in spurious errors reporting that the method System::Object::Finalize is
overridden multiple times by higher-level classes in that library.  Here is
an example of such a diagnostic:

  "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.DLL": error: member
          function overrides function "System::Object::Finalize" (declared in
          "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll") which
          is already overridden by function
          "System::ComponentModel::Component::Finalize" (declared )

This is now fixed.


3/14/16  [EDGcpfe/16549,EDGcpfe/16935]
C++/CX and C++/CLI: Importing delegates with attributes

When importing delegates with attributes, the "source code equivalent" was
incorrectly generated by ms_metadata.cpp, leading to spurious errors and
invalid IL (a class type marked as a delegate class type, but without an
invocation type).  This is now fixed.


2/28/16  [EDGcpfe/16519]
Regression determining physical line and file during parsing

The changes for EDGcpfe/15925 (part of version 4.10.1) resulted in the
function conv_seq_to_physical_line_and_file returning incorrect values for
files containing both GNU-style line directives and #include directives when
it was invoked for files that had not yet been completely processed.  This
is now fixed.


2/26/16  [EDGcpfe/16784]
Initialization of a_type::alignment_set_explicitly

The initialization of the field alignment_set_explicitly in a_type was
conditional on GNU_EXTENSIONS_ALLOWED || MICROSOFT_EXTENSIONS_ALLOWED, but
the field itself is present in all configurations, therefore it was
uninitialized in configurations that don't support GNU or Microsoft emulation.


2/25/16  [EDGcpfe/16889]
Empty virtual function table entries in some construction vtables (IA-64 only)

In cases outlined in EDGcpfe/15864 where references to virtual destructors
in construction vtables are eliminated, if such a destructor appeared before
other virtual functions in the construction vtable, then those virtual
function table entries were also inadvertently eliminated.  Affects only the
IA-64 ABI.  The following example, with --gnu_version 40900, had a segmentation
fault when attempting to invoke vf at run time and is now fixed:

  struct B {
    virtual ~B() {}       // ~B occurs before vf:
    virtual void vf() {}
    void f() {
      vf();
    }
  };
  struct D: virtual B {
    D() {
      f();
    }
  };
  struct DD : D { };
  int main() {
    DD dd;
    return 0;
  }


2/25/16  [EDGcpfe/16836]
Thread-local specifiers and anonymous unions/structs

A number of changes have been made to the handling of thread-local specifiers
(i.e., _Thread_local in C11 mode, or thread_local in C++11 mode) and
anonymous unions/structs.  These changes are bring the front end closer to
standard compliance as well as to emulating the behavior of other compilers.
For example, with --c++11:

  static thread_local union {
    char x;
    int y;
  };


2/23/16  [EDGcpfe/15632,EDGcpfe/16617,EDGcpfe/16810]
Noexcept specifiers and member function declarations

The front end now delays the parsing of the operand of a noexcept specifier for
a member function declaration until the enclosing class has been completed
(similar to the processing of default arguments).  This allows the noexcept
specifier to depend on members of the class that have not been seen yet at the
point where the noexcept specifier is encountered.  For example:

  struct S {
    void f() noexcept(noexcept(g()));  // Previously an error; now okay.
    void g();
  };

The checking of exception specifications for overriding virtual functions has
been delayed accordingly.  In Microsoft mode with microsoft_version == 1800
this avoids spurious warnings on defaulted virtual destructors in some cases.
For example:

  struct B { virtual ~B() = default; };
  struct D: B {
    virtual ~D () = default;  // Previously triggered a spurious warning;
  };                          // now silently accepted.

In GNU C++ mode, parsing of the noexcept operand is not delayed; not even in
template contexts.  The front end already attempted to emulate the GCC
behavior in template contexts, but in some cases where a member function is
defined outside the class (template) definition, this resulted in spurious
errors.  For example:

  template<typename T> struct X { void f() noexcept(T()); };
  template<typename T> void X<T>::f() noexcept(T()) {}
    // Previously triggered spurious errors ("T" is undefined) in
    // GNU C++11 mode.

This is now fixed.


2/22/16  [EDGcpfe/16892]
Constexpr call cost control options renamed

The command-line options to control the maximum cost of evaluating a call to
a constexpr function are renamed from --max_constexpr_call_count and
--max_constexpr_call_depth to, respectively, --max_cost_constexpr_call and
--max_depth_constexpr_call.  This is both to improve usability with abbreviated
command-line options and to better reflect the C++14 "relaxed constexpr" rules
(where "cost" is not conveniently reduced to a count of calls).  Macros and
global variables associated with these options have been similarly renamed.


2/22/16  [EDGcpfe/16894]
Microsoft C++/CLI compatibility: preusings processed when doing preprocessing

In C++/CLI mode, assemblies specified as "preusings" were loaded even when
only doing preprocessing.  This could result in code being executed that
expects certain initializations to have been performed that are not done
in this case.  In addition, the combination of "-E --no_preproc_only"
did not work properly (the preusings and explicit #using directives
would be ignored when they should not have been).  Now fixed.


2/20/16  [EDGcpfe/16854,EDGcpfe/16891]
GNU C++ compatibility: member access expressions for constant members

The C++ Standard requires that in a member access expression like x.y or
p->y, where "y" is a member that is not a nonstatic data member, the object
expression is evaluated and discarded.  As a result, in standard C++, such
expressions can only appear in constant expressions if both the member and
the object expression are constant.  In C++11 mode, g++ does not enforce
this rule for an object expression with no side effects, and the front end
has now been changed to emulate this behavior in g++ mode.  For example,
with --g++ --c++11:

  struct S {
    enum { z, y };
  } s;
  void g(const S* x) {
    static_assert(x->y == 1, "");  // Previously an error, now accepted
  }


2/19/16  [EDGcpfe/16828]
Invalid substituted types of nontype template parameters

Consider the following example:

  struct L { char x[2]; };
  template<typename U, U N = 0> char f(int);
  template<typename> L f(...);
  static_assert((sizeof(f<double>(0)) == sizeof(L)), "Unexpected");

Ordinarily, this should be accepted because a nontype template parameter (N in
this case) cannot have type "double" according to the standard.  The front end
previously failed to check that constraint -- now it does.

Note that the front end does in some modes and configurations accept nontype
template parameters of floating-point type (see configuration macro
DEFAULT_FLOATING_POINT_TEMPLATE_PARAMETERS_ALLOWED); in those cases the
static assertion above fails since the first candidate would then be preferred
in the call f<double>(0).


2/17/16  [EDGcpfe/16776]
GNU compatibility: Expanded abi_tag attribute compatibility

Support for the GNU abi_tag attribute (originally introduced by EDGcpfe/15897)
has been expanded.  In particular, mangled names for functions and variables
now (when ABI_COMPATIBILITY_VERSION >= 411) will contain "implicit" abi_tags
(as well as any applicable explicit abi_tags).  The documentation for the
determination of "implicit" abi_tags consists of this single sentence: "When a
type involving an ABI tag is used as the type of a variable or return type of a
function where that tag is not already present in the signature of the
function, the tag is automatically applied to the variable or function."
Also, the abi_tag attribute is now accepted on variables and enum types.
Additionally, when a string is not specified in an abi_tag attribute that
appertains to an inline namespace, the inline namespace name is now used for
the abi_tag string.  For example (with --gnu_version 50000 --c++11):

  inline namespace N __attribute((abi_tag)) {
    struct A {};
  }
  A a;    // mangled as: _Z1aB1N (IA-64) or __ab1Na (Cfront)
  A f() { // mangled as: _Z1fB1Nv (IA-64) or __ab1Nf__Fv (Cfront)
    return A();
  }


2/16/16  [EDGcpfe/16411]
C++/CX: Allow static data of standard class type in managed class

The front end now accepts static data members of standard class types in
managed classes in C++/CX (but not C++/CLI) mode.  For example:

  struct A {};
  ref class B {
    static A a;  // Previously an error in C++/CX mode; now okay.
  };


2/16/16  [EDGcpfe/16876]
C++11 constexpr: Template function returning no value

Previously, in C++11 mode, the front end issued a misleading error for the
following example ("function must contain exactly one return").

  template<typename T> struct S {
    constexpr T f() { return; }  // Previously triggered an error; now okay.
  };
  void g() {
    S<void>().f();
  }

Although the example is ill-formed, the standard requires no diagnostic in
this case, and at least one other implementation accepts it silently. The
front has therefore been modified to also accept that case (but A<void>().f()
is not a constant-expression).


2/16/16  [EDGcpfe/16592]
GNU/clang C++ compatibility: function template redeclarations

g++ and clang allow certain dependent types to be specified differently
in the declaration and definition of a member function template.  In the
example below, the second template argument in the declaration of f() uses
"tp**" while the definition uses "B<T1, T2, 0>::tp", but at that point the
class type is not yet known to name the partial specialization.  We now
emulate this behavior in g++ and clang modes.

  template <class> struct A;
  template <class T1, template <class> class, int = A<T1>::value> class B;
  template <class T1, template <class> class T2> class B<T1, T2, 0> {
    typedef typename T1::tp tp;
    template <class U, int (tp **, U)> void f();
  };
  template <class T1,
            template <class> class T2> template <class U,
            int (typename B<T1, T2, 0>::tp **, U)> void B<T1, T2, 0>::f(){}


2/15/16  [EDGcpfe/16687]
Revised preliminary coroutine support

The front end's support for coroutines (see the entry of 5/13/15 for
EDGcpfe/15431) has been revised to more closely match the specification in the
standardization committee's paper P0057R1.  These changes include:

  - new keywords co_await, co_yield, and co_return;
  - "co_yield x" is now an expression rather than a statement; and
  - a unary "operator co_await" can be declared to dispatch the
    "await protocol" to a different object.

In Microsoft modes that accept coroutines, the Microsoft keywords are still
accepted and the keyword "await" and context-sensitive keyword "yield" are
still recognized if the option --set_flag=coroutine_keywords is specified.

Support for this feature is still considered "preliminary" (the committee's
specification remains in flux).


2/15/16  [EDGcpfe/16874]
Spurious remark when sized deallocation is enabled and exceptions are disabled

In modes where exceptions are disabled and sized deallocation is enabled
(i.e., C++-14 mode or when microsoft_version >= 1900), a spurious
"support for placement delete is disabled" remark had been issued.  Now fixed.


2/8/16   [EDGcpfe/16850]
Inadvertent removal of thread_local variable use

In configurations that use USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES
to initialize thread_local variables, lowering had inadvertently removed
lvalue references to thread_local variables that had no other effect, resulting
in a failure to initialize the variable (if it had any initialization).  In
the example below, the constructor had not been called (and is now).
With --c++11:

  extern "C" int printf(const char *,...);
  int result = 1;
  struct A {
    A() { result = 0; }
  };
  thread_local A a;
  int main() {
    (void)a;
    return result;
  }


2/7/16   [EDGcpfe/16843]
GNU C++ Compatibility: default arguments on referenced function templates

g++ versions before 5.0 allow a function template that has already been
used to have a default argument added (although the default argument
is ignored).  We now accept this (with a warning) in g++ mode when
gnu_version < 50000.

  template <class T> struct A {};
  template <class U> struct B {
    template <class T> friend void f(A<T>&, int = 1);
    static void g() { }
  };
  template <class T> void f(A<T>&, int) { T::g(); }
  int main() {
    A<B<int> > ab;
    f(ab, 2);
  }


2/5/16   [EDGcpfe/16808]
Range-based for loops in template instantiations

In template instantiations, range-based for loops that determine the bounds
of the range through an argument-dependent lookup of "begin(...)" and
"end(...)" incorrectly resolved the "end(...)" call to the corresponding
"begin(...)".  That resulted in the range always being treated as empty.
This is now fixed.


2/4/16   [EDGcpfe/16826,EDGcpfe/16827]
__is_standard_layout

The front end previously treated some classes with a nonstatic data member of
reference type as being "standard-layout" classes.  That is now fixed.  A class
whose first declared nonstatic data member has the same type as one of the base
classes of that class is not a "standard-layout" class.  However, GCC and Clang
appear to only consider direct base classes for that criterion: The front end
now emulates that behavior in GNU and Clang modes.  For example:

  struct R { int const &rci = 0; };
  static_assert(!__is_standard_layout(R), "Case 1");  // Now accepted.
  struct B {};
  struct C: B {};
  struct D: C {
    B b;
  };
  static_assert(__is_standard_layout(D), "Case 2");  // Now accepted in GNU
                                                     // and Clang modes.

(See also the entry of 3/16/11 for EDGcpfe/11495,EDGcpfe/11515, which
introduced the __is_standard_layout type traits helper.)


2/4/16   [EDGcpfe/16838]
Cfront ABI: issue with thread_local destructions

In the Cfront ABI, the lowered code to generate needed destructions of
objects with thread_local storage had inadvertently neglected to mark as
thread_local one of the temporaries used in the destruction, potentially
resulting in undefined behavior during the destruction of such entities.
Now fixed.  For example (with --c++11):

  struct A {
    ~A() { while(0); }
  };
  thread_local A a;


2/4/16   [EDGcpfe/16829]
Operator functions with incomplete return types and decltype

In C++11, the return type in a function call need not be complete if the
function call appears as the immediate operand of a decltype construct (see
the Changes entry of 7/19/13 for EDGcpfe/11740,EDGcpfe/14277).  The front end
failed to implement that rule for calls resulting from overloaded operator
uses.  For example:

  struct I;
  struct C {};
  I operator*(C);
  decltype(*C()) g();  // Previously an error.  Now okay.

This is now fixed.


2/1/16   [EDGcpfe/11673,EDGcpfe/14193,EDGcpfe/16381,EDGcpfe/16813]
Elimination of dual lookup of certain names in class member accesses

In C++98/03, certain names in class member access expressions were looked
up in both the class of the member access and the current context.  If
both lookups succeeded and produced different results, the program was
ill-formed.  In C++11 (as a result of core issue 1111), if the lookup in
the class succeeds, the lookup in the current context is not done.  We
now implement the new rules in C++11 (and newer) modes.

In addition, it was formerly the case that when a lookup conflict occurred,
the normal lookup result was used and a diagnostic (an error, in most modes)
was issued.  Now, the class lookup result is used (to make the behavior
consistent with C++11), and the diagnostic has been reduced to a warning
except in strict C++98/03 modes.

  struct A { };
  namespace N {
    struct B { int i; };
    struct A : public B {
      void g() { }
      template <class T> operator T();
    };
  }

  int main() {
    N::A a;
    a.operator A();     // calls N::A::operator N::A
    int j = a.A::B::i;  // now valid, refers to N::B::i base class member
  }


2/1/16   [EDGcpfe/16818]
Call via reference cast of constexpr function

The front end previously incorrectly indicated that a call to a constexpr
function was not a constant expression if the function is designated via a
cast to a reference type.  This is now fixed.  For example, with --c++11:

  constexpr int f() {
    return 3;
  }
  int arr[static_cast<decltype(f)&>(f)()];  // Previously an error, now okay


1/31/16  [EDGcpfe/16378]
Microsoft compatibility: visibility of template parameters

A change made in version 4.6 (see EDGcpfe/13170 on 12/13/12) made template
parameters visible in their own default arguments (except for some type
argument cases in Microsoft mode).  In Microsoft mode, however, default
template arguments are not scanned until they are used.  The EDGcpfe/13170
change did not work properly when in Microsoft mode.  Now fixed.

  template <typename T> struct A {
    static const bool value = true;
  };
  template <typename T, bool A = A<T>::value> struct B {};
  B<int> b;


1/28/16  [EDGcpfe/16716]
Microsoft compatibility, C++-generating back end: "this" in member function
return type

The front end previously had two problems with regard to implicit
references to "this" appearing in the return type of a member function.
First, the Microsoft compiler has accepted this usage since MSVC 11, but
the front end only implicitly enabled it with microsoft_version >= 1900,
emulating MSVC 13.  Also, the C++-generating back end previously put out an
explicit "this->" in such a reference in the generated code, but the
Microsoft compiler disallowed the "this" keyword in that context up through
early versions of MSVC 13.  These are both now fixed.  For example, with
--microsoft_version=1700:

  struct S {
    int f();
    auto g()->decltype(f()); // Previously rejected, now accepted; also,
                             // previously generated as decltype(this->f()),
                             // which was rejected by MSVC.
  };


1/27/16  [EDGcpfe/16793]
Overload resolution and operator= templates

The overload resolution algorithm for selecting an assignment operator has been
slightly modified to discard some assignment operator templates earlier
(before substituting the template), thereby avoiding instantiation errors.
This causes the front end to accept code that other compilers also accept.
For example:

  template<class T> struct S {
    typedef typename T::X Type;
  };
  struct X {
    X& operator=(X const&);
    template<class T> typename S<T>::Type operator=(T const&);
  };
  struct Y {
    X x;
  };

The generation of the copy assignment operator for Y requires the selection
of an assignment operator from X.  Previously, this required the substitution
of T by X in the member template operator, which triggered an instantiation
error.  Now, the front end determines early that no specialization of the
member template could be a better match than the nontemplate operator,
thereby avoiding the error.


1/27/16  [EDGcpfe/16806]
Assertion failure in dump_expr

In C-generating configurations that do partial lowering of exception
handling, an assertion failure (in dump_expr) had occurred on the following
example (with --g++) and is now fixed:

  struct A {};
  void f() {
    throw A();
  }


1/27/16  [EDGcpfe/16805]
GNU compatibility: return type of __builtin_va_arg_pack_len

The return type of __builtin_va_arg_pack_len has been changed from "int" to
"size_t" to match the documented interface of the function.


1/27/16  [EDGcpfe/16804]
Missing special_kind description in IL display program

An attempt to dump the "special_kind" field of some GNU __sync or __atomic
builtins had resulted in "**BAD SPECIAL FUNCTION KIND**" when using the
IL display program.  Now fixed.


1/27/16  [EDGcpfe/16788]
Bitwise copyability of class with deleted copy functions (ABI Change)

Previously, a class with a deleted copy/move constructor was also marked as
not being bitwise copyable.  This is no longer the case by default, but the
former behavior can be restored by setting the configuration macro
DELETED_COPY_FUNCTION_CLEARS_BITWISE_COPY_FLAG to TRUE.  This change affects
the "argument transfer method" for parameters of such a class type and
therefore the ABI.  For example:

  struct N {
    N(N const&) = delete;
  };
  void f(N p) {}

Previously, parameter p was marked as being "passed via copy constructor";
that is no longer the case.  This is unimportant for standard-conforming
C++ code, since a function like f cannot be invoked (due to the deleted
copy constructor), but nonstandard code that relies on a specific argument
transfer mechanism may be affected.


1/25/16  [EDGcpfe/16798]
GNU compatibility: Spurious error on abi_tag attribute applied to lambda

A spurious error had been given when an abi_tag attribute appertained to
a lambda.  Now fixed.  For example (with --c++11 --gnu_version 50000):

  void f() {
    []() __attribute__((abi_tag("test"))) {}();
  }


1/25/16  [EDGcpfe/16393]
Default argument from template template argument to variadic parameter

If a class template with a default argument was passed to a template
template parameter that takes a variadic template argument, the
default argument of the template template argument was not used when
needed.  Now fixed.  This is core issue 2057, so it is possible the
behavior of this case may change in the future.  But given that g++,
clang, and Microsoft all accept this case, there is a good chance that
something like this will eventually be adopted by the standards committee.

  template<template<typename...> class T> struct A {
    T<int> t;
  };
  template<typename, typename = void> struct B {};
  void f() {
    A<B> a;  // Formerly "too few arguments ..."
 }


1/24/16  [EDGcpfe/16743]
Alias template template argument substitution with invalid result

When the argument for a template template parameter is an alias template,
the expansion of the alias occurs in a SFINAE context, and the expansion
is invalid, this now results in a substitution failure instead of a hard
error.  The g++ 6.0 beta header files rely on this functionality.  We
now implement this in all modes.

  template <typename...> using __void_t = void;
  struct A {};
  template <typename T, template <typename...> class TT> struct B {
    using type = void*;
  };
  template <template <class...> class TT> struct B<__void_t<TT<A>>, TT> {
    using type = TT<A>;
  };
  template <typename T> using vp_alias = typename T::void_pointer;
  using void_pointer =  typename B<void, vp_alias>::type;


1/22/16  [EDGcpfe/14498,EDGcpfe/15550,EDGcpfe/16781]
GNU compatibility: folding constant vector arithmetic expressions

The front end previously aborted with an assertion failure in
unary_operation or binary_operation if an attempt was made to fold a
constant vector arithmetic expression.  This is now fixed.  For example,
with --gnu_version=50000 --c++11:

  typedef int __attribute__((vector_size (4*sizeof(int)))) vectype;
  void f() {
    constexpr vectype x {};
    constexpr vectype y {1,2};
    constexpr vectype z = x + y;   // Previously aborted, now z == {1,2,0,0}
  }


1/22/16  [EDGcpfe/16794]
Address of constexpr local variable in constexpr initializer

The front end previously failed to diagnose an initializer for a constexpr
variable that was the address of a local constexpr variable.  For example:

  int main() {
    constexpr int i = 0;
    constexpr const int *p = &i;  // Previously accepted in C++11 mode.
  }                               // Now an error.

This is now fixed.


1/21/16  [EDGcpfe/16792]
Closure types are nonliteral class types

The front end did not previously systematically treat closure types as
nonliteral class types (as required by the standard).  For example:

  auto L = []{};
  static_assert(!__is_literal_type(decltype(L)), "Unexpected!");
    // This assertion failed previously.  Now okay.

This is now fixed.


1/19/16  [EDGcpfe/16785]
Function calls and decltype

Early drafts of the decltype feature specified that when applied to a call
expression it produced the return type of the function.  This was later
changed (before final standardization in C++11) but the front end was never
updated, causing nonstandard results in some cases.  For example:

  template<typename T> T f();
  decltype(f<int const>()) x; // Previously a spurious error because x was
                              // declared with type "int const".  Now okay;
                              // the type of x is "int".

This is now fixed.
 

1/19/16  [EDGcpfe/16780]
GNU and Microsoft C++ compatibility: member calls in default arguments

In GNU and Microsoft C++ modes, the front end now accepts in the prototype
instantiation of a default argument of a member function declaration calls
to other member functions of the same class without a selector object.
For example:

  template<typename> struct S {
    void i();
    void f(int = i());  // Now accepted in GNU and Microsoft C++ modes.
  };

(Such uses produce an error during a real instantiation of the default
argument.)


1/19/16  [EDGcpfe/16749]
Incorrect lookup of globally qualified name when using inline namespaces

A globally qualified lookup could produce an incorrect result if the
global scope contained an inline namespace.  Now fixed.

  inline namespace IN1 {
   void f(int);
  }
  void f();
  int main() {
   ::f(0);  // incorrectly attempted to call ::f()
  }


1/19/16  [EDGcpfe/15860,EDGcpfe/16756]
Abort in C++14 mode on missing lifetime for default member initializer

In C++14 mode, the front end previously sometimes aborted with an internal
error in lower_dynamic_init when an aggregate initializer relies on a
default member initializer for a field requiring nontrivial destruction.
For example:

  struct D { ~D(); };
  struct X {
    D d = D();
  };
  void g() {
    X{};  // Previously triggered an internal error in lower_dynamic_init.
  }       // Now okay.

This is now fixed.


1/19/16  [EDGcpfe/16764]
Abort when importing an overriding method of a C++/CLI class

In C++/CLI mode, importing an internal method with named overriding could lead
to an abort in ms_metadata.cpp (due to an out-of-range vector subscript).
For example:

  // lib.cpp (compiled into an assembly):
  namespace Lib {
    generic <typename T> public ref class A {
    internal:
      virtual void f() {}
    };
    generic <typename S> public ref class B : A<S> {
    internal:
      virtual void f() new = A<S>::f {}
    };
  }

  // t.cpp:
  #using "lib.dll"
  void g(Lib::B<int>^ b) {
    b->f();  // Loading the metadata for B::f previously triggered an
  }          // abort.  Now a normal error is issued.

This is now fixed (in the example above, an error is issued since there is no
usable declaration of B<int>::f for the call in g).


1/18/16  [EDGcpfe/16778]
Copy constructors and "return { ... };"

Consider the following C++11 code:

  struct X {};
  struct S {
    S(X const&);
    S(S const&) = delete;
  };
  S g() {
    return { X() };  // Previously an error in strict mode; now okay.
  }

Previously, the return statement was handled as an elided copy of an implicit
form of "S{X()}" (i.e., the conversion to S is implicit).  Since the copy
constructor is deleted, an error was issued in various modes (despite the
elision).  A close reading of the standard, however, indicates that the return
value is list-initialized directly from the braced initializer, without any
involvement of the copy constructor (and hence the example should be accepted).
This is now fixed.


1/17/16  [EDGcpfe/16777]
Assertion failure in Microsoft mode with long macro expansions and pasting

With certain patterns of long macro expansions and use of the ##
token-pasting operator, the changes of EDGcpfe/15923 (in version 4.10.1)
could cause the front end to abort in Microsoft modes with an assertion
failure in expand_macro_buffer.  This is now fixed.


1/17/16  [EDGcpfe/16737,EDGcpfe/16774]
GNU Compatibility: Allow attributes on lambda before exception specification

A change has been made to allow attributes on a lambda before an exception
specification.  In addition, GNU attributes (but not standard attributes) are
allowed in that location in clang emulation mode.  For example (with --g++
--c++11):

  auto f = [] () __attribute__((noinline)) noexcept { };


1/17/16  [EDGcpfe/16753]
Error when alignas() applied to exception handler parameter variable

The standard forbids an alignas() attribute to be applied to an exception
handler parameter variable; an error is now issued.  For example (with
--c++11):

  void f() {
    try { } catch (alignas(16) int) { }
  }

Also fixed was the use of "-h" as an attribute constraint for variables in the
internal attribute processing mechanism (previously unused in the front end,
but possibly used by customers).


1/15/16  [EDGcpfe/16763]
Redeclarations of variadic function templates

When a variadic function template is redeclared using a form that is slightly
different from the original declaration, the front end sometimes corrupted the
type of the function template, causing the variadic nature of parameters to
be lost and incorrect deduction behavior later on.  For example:

  template<typename ...  Ts> void f(Ts&&...);
  template<typename ...  Ts> auto f(Ts&&...)->void {}
  void g() {
    f(1, 2);  // Previously triggered a spurious error.  Now okay.
  }

This is now fixed.


1/15/16  [EDGcpfe/16750,EDGcpfe/16762]
Standard alignment attributes

A number of changes have been made to the processing of standard alignment
attributes, i.e., alignas, _Alignas and the early draft standard
[[align(...)]].  As specified by the standard, only the strongest alignment on
a particular declaration is now considered (except when applied to types
in GNU emulation mode where the last alignment attribute is the effective one).
For example (with --c++11):

  struct X {
    alignas(short) alignas(long) int m;  // Previously a spurious error.
  };

Also, cases where a type declaration and its definition disagree on the
alignment are now diagnosed.  For example (with --c++11):

  struct alignas(8) A;
  struct A {};            // Previously accepted; now an error.

  struct B {};
  struct alignas(8) B;    // Previously accepted; now an error.


1/15/16  [EDGcpfe/16770]
Elided calls to deleted constructors and destructors

If a call to a constructor or destructor is about to be elided, the front end
should still issue an error if the elided call is to a deleted member, or, if
the call is in a SFINAE context, the candidate being considered should be
discarded.  Previously, the front end ignored the fact that the call appeared
in a SFINAE context (e.g., always triggering an actual error in strict mode).
For example:

  struct Zero { static constexpr int value = 0; };
  struct One { static constexpr int value = 1; };
  template <class T> T make();
  template <typename T, typename = decltype(T(make<T>()))> One f(int);
  template <typename> Zero f(...);
  template<class T> using elided_copy_okay = decltype(f<T>(0));
  struct S { S(const S &) = delete; };
  static_assert(!elided_copy_okay<S>::value, "Unexpected");
    // Previously failed; now okay.

This is now fixed.  Furthermore, an elided call to a deleted function was
simply ignored with a warning in all nonstrict modes.  Now, it is an error
(or SFINAE disqualification) in GNU and Clang modes.


1/15/16  [EDGcpfe/16402]
Microsoft/Clang/GNU compatibility: Use of static array data member in template

In GNU and Clang modes, an argument of a function call that is a reference to
a static data member of incomplete array type is now considered a dependent
argument.  Furthermore, in non-template-dependent contexts, referring to a
static data member of a class template instance whose type is an incomplete
array type triggers the instantiation of the initializer of that data member
(if applicable) so that the bound of the array can be determined.  That
causes the front end to accept in some modes cases that previously elicited
errors.  For example:

  template<unsigned N> unsigned count(int (&array)[N]) {  // (1)
    return N;
  }
  template<typename T> struct C {
    static int x[];
    unsigned n() { return count(x); }  // (2)
  };
  template<typename T> int C<T>::x[] = { 1, 2 };
  int main() {
    C<int> c;
    return c.n() != 2;
  }

Line (2) is normally invalid because x has a nondependent type that cannot be
unified with the parameter declaration in (1).  The case was already accepted
in GNU and Clang modes that defer prototype instantiations.  Now it is also
accepted in GNU and Clang modes that don't defer prototype instantiations, as
well as in Microsoft C++ modes.


1/15/16  [EDGcpfe/16227]
Spurious error on braced initializer for explicit specialization

The front end previously issued a spurious error on a braced initializer for
an explicit specialization of a static data member.  For example:

  template<typename> struct S {
    static int n;
  };
  template<> int S<void>::n{0};  // Previously triggered a spurious error.

This is now fixed.


1/14/16  [EDGcpfe/16767]
dllimport/dllexport, template base classes, and prototype instantiations

In Microsoft mode, if a dllimport or dllexport attribute is applied to a
derived class, the same attribute is applied to all its instantiated base
classes that have no dllimport/dllexport attributes yet.  Previously, this
was sometimes also applied to prototype instantiations, causing all further
instantiations of the affected template (not just the specific instantiation
denoted as the base class) to be marked with the dllimport or dllexport
attribute.  For example, in a configuration with PROTOTYPE_INSTANTIATION_IN_IL
set to TRUE:

  struct S {};
  template<typename T = int> struct B {
    template<typename U> B(U) {}
  };
  struct __declspec(dllimport) D: B<> {};
  B<S> b(42);

Previously, B<S>::B(S) was erroneously marked as dllimport (only B<int>::B(int)
should be so marked).  This is now fixed.


1/12/16  [EDGcpfe/16755]
Microsoft compatibility: issue with use of "." in place of "::"

Older Microsoft compilers (microsoft_version <= 1500) allow the use of "."
where "::" is required in qualified names.  The front end allowed mixed
usage such as "A::B.C" but rejected "A.B::C".  Now fixed.

  struct A {
    struct B {
      enum E { e0, e1 };
      E e;
    };
  };
  void f(A::B* ab) {
    if(ab->e == A.B::e0) { }
  }


1/10/16  [EDGcpfe/16582]
C++-generating back end: nested partial specializations and default arguments

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end incorrectly generated the template argument list
for a partial specialization of a class template nested within a class
template if the partial specialization relies on a default template
argument of the primary class template.  This is now fixed.  For example:

  template <typename T> struct outer {
    template  <T x,  typename D1, typename D2 = D1> struct inner { };
    template <typename T2> struct inner<20, T2> { };
    // Previously erroneously generated as inner<20, T2, D1>
    // Now generated correctly as inner<20, T2, T2>
  };


1/6/16   [EDGcpfe/16491]
Microsoft compatibility: comma preceding empty __VA_ARGS__ in macro argument

When __VA_ARGS__ is preceded in a macro definition by a comma and the
variadic argument is empty, the Microsoft preprocessor generally omits the
comma from the expanded text, as does the front end in --microsoft mode;
see the entry of 2/15/07.  However, the Microsoft preprocessor does not
suppress the comma if it appears in a macro argument to a macro with a
single parameter, while the front end did so in all contexts.  This is now
fixed.  For example, with --microsoft:

  #define MAC(...) __VA_ARGS__
  #define MF(x, ...) fun(x, __VA_ARGS__,<-)
  #define MM(x, ...) MAC(x, __VA_ARGS__,<-)
  MF(->);   // Expands to "fun(->,<-)" (first comma suppressed)
  MM(->);   // Now expands to "->,,<-" (first comma not suppressed)


1/6/16   [EDGcpfe/16645]
__is_convertible_to and class types

The front end's implementation of __is_convertible_to has been reworked to more
accurately test the criteria specified for the standard C++ library trait
std::is_convertible.  In particular, this corrects cases involving class types
with inaccessible constructors.  For example:

  struct N {
  private:
    N(N&);
  };
  static_assert(!__is_convertible_to(N&, N), "?");
      // Previously failed; now okay.

 
1/6/16   [EDGcpfe/16745]
GNU compatibility: Deduced return types in C++11 mode

In GNU C++11 mode (without C++14 features enabled) with gnu_version >= 40800
and gnu_version < 40900, the front end now accepts deduced return types with
a warning.


1/6/16   [EDGcpfe/16590]
Abort in get_expr_rescan_info

When a template-dependent non-type template argument is used both in a
nondeduced context and (later) in a deduced context, the front end sometimes
aborted in get_expr_rescan_info (exprutil.c; "missing default rescan info").
For example:

  template<int> struct I {};
  template<typename> constexpr int n() { return 42; };
  template<typename T> struct S {
    S(I<n<T>()>);  // n<T>() appears as an argument of I in a nondeduced
  };               // context here.
  template<typename T> int g(I<n<T>()>) { return 1; };
    // n<T>() appears as an argument of I in a deduced context here.
  int r = g<void>(I<42>());
    // Previously aborted during the rescanning of n<T>(); now okay.

This is now fixed.


1/5/16   [EDGcpfe/16587]
Explicit template arguments, parameter packs, and default arguments

The front end previously sometimes handled explicit function template arguments
incorrectly when they appear on a variadic function template whose signature
involves a nonvariadic class template with default arguments.  For example:

  template<typename T, typename U  = int> struct X { };
  template<typename... Ts> X<Ts...> g(X<Ts...>);
  void f(X<int, float> p) {
    g<int>(p);  // Previously triggered a spurious error; now okay.
  }

Previously, the substitution of g<int> produced a function type with parameter
type X<int, int> (instead of something like X<int, __T2> where T2 can still be
deduced to float), which cannot be matched with the argument p of type
X<int, float>.  This is now fixed.


1/5/16   [EDGcpfe/16542]
Default member initializers in template classes and generated constructors

The front end no longer forces the instantiation of default member initializers
(aka. nonstatic data member initializers) when generating a default constructor
declaration for a non-specialized template class.  For example:

  template<typename> struct I;
  template<typename T> struct B {
    int i = f(I<T>());
  };
  struct D: B<int> {};

Previously this example triggered an error about I<int> being incomplete, but
now it is accepted but the initializer for B<int>::i is not instantiated.


1/3/16   [EDGcpfe/15902,EDGcpfe/15946,EDGcpfe/16053,EDGcpfe/16054,
          EDGcpfe/16269,EDGcpfe/16466,EDGcpfe/16468,EDGcpfe/16665]
Core issue 1558: unused arguments in alias instantiation (e.g., void_t)

The front end now implements core issue 1558.  This is used by the g++
future, regex, and possibly other headers.

In order to implement this, PROTOTYPE_INSTANTIATIONS_IN_IL must now be
TRUE.  The largest part of the changes for this are those required to
allow IL lowering to be able to coexist with PROTOTYPE_INSTANTIATIONS_IN_IL.
Prototype instantiations are not actually lowered, but lowering has to
be able to ignore the prototype instantiation information.  Attempting
to set the flag to FALSE will now result in an #error at build time.  At
some point in the future, this flag and the tests of it will be removed.

Back ends will require some modifications to ignore prototype instantiation
information in the IL tree.  These changes are expected to be minor.
There are new functions/macros named ignore_type_in_back_end,
ignore_routine_in_back_end, and ignore_variable_in_back_end that can be
used to determine whether a given entity should be processed.  See
c_gen_be.c for examples.

A new configuration macro named ALL_TEMPLATE_INFO_IN_IL has been added.
This controls part of the functionality previously included as part of
PROTOTYPE_INSTANTIATIONS_IN_IL.  When it is TRUE, the prototype
instantiations of function definitions are included in the IL, and
certain IL data structures that mirror front end structures  (e.g.,
a_template_decl and a_template_parameter) are created.

  template <typename... > using __void_t = void;
  template <int, typename> struct A {};
  template <typename T> struct A <1, T> {
    typename T::type type;
  };
  template < typename, typename = void > struct B {
    static constexpr bool value = 0;
  };
  template < typename T > struct B<T, __void_t <typename T::type >> {
    static constexpr bool value = 1;
  };
  A<B<int>::value, int> b;


12/30/15 [EDGcpfe/16739]
Spurious deduction failure in a nondeduced context

When a function template parameter was a nondeduced context because of a
dependent qualifier, deduction incorrectly failed, resulting in an error
for examples like the one below.  Now fixed.

  template <class T> struct A {
    template <class U> struct B {
      B(U*){}
    };
  };
  template <class T> void f(A<T>, typename A<T>::template B<T>){}
  int main() {
    A<int> ai;
    int *p;
    f(ai, p);
  }


12/23/15 [EDGcpfe/16730]
Microsoft compatibility: Binding a const class temporary to a reference

Microsoft allows binding a reference to a nonconst class type to an rvalue
temporary that is the result of a constructor call.  This is possible even
when the rvalue has a const class type.  Previously, that behavior had been
approximated by dropping the cv-qualifiers on cast to a cv-qualified class
type (see entry of 3/17/08), but that approach produced results different from
the Microsoft compiler in some cases.  Now the const qualifier is dropped
only in specific reference bindings.  For example:

  struct S {
    S();
    int operator[](int) = delete;
    int operator[](int) const; 
  } s;
  int r = ((S const)s)[0];
     // Previously an error (selected the deleted operator[]).  Now okay.


12/23/15 [EDGcpfe/16734]
clang compatibility: __builtin_operator_new and __builtin_operator_delete

Two new builtins, __builtin_operator_new and __builtin_operator_delete, are
now available in --clang mode.  An implicit alias is created from these
builtin routines to the corresponding standard functions so that a back end can
either use the builtin or the alias as it sees fit.  For example, with --clang:

  void f() {
    void *x = __builtin_operator_new((__SIZE_TYPE__)2);
    __builtin_operator_delete(x);
  }


12/22/15 [EDGcpfe/16729]
__builtin_choose_expr

Previously, the front end scanned the GNU __builtin_choose_expr construct and
attempted to discard all the IL resulting from that process, except for the
selected expression.  This could lead to dangling pointers in some cases
(e.g., source sequence entries pointing to entities declared in the discarded
expression), which in turn could lead to aborts (e.g., while writing the IL to
a file).  Now, the front end represents the construct as a whole in the IL
(using a new enk_builtin_choose_expr node kind); this fixes the dangling
pointer issue, and provides more accurate information about the source code
(e.g., the C++-generating back end now renders the construct).


12/22/15 [EDGcpfe/16736]
Ensure guard variable is thread_local if guarded variable is

In configurations where TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE is TRUE,
the guard variable for a thread_local static data member had not itself been
marked as thread_local, leading to improper initialization of the static
data member.  For example (with --c++11):

  int f() {
    return 5;
  }
  template <typename T> struct A {
    static thread_local int sdm;
  };
  template <typename T> thread_local int A<T>::sdm = f();
  int x = A<int>::sdm;


12/21/15 [EDGcpfe/16733]
Remove unneeded guard variables for specialized static data members

In cases where the initialization of a static data member could happen in
multiple translation units and TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE is
TRUE, lowering introduces a guard variable to prevent multiple initializations.
In cases where a static data member is explicitly specialized, a guard variable
had been emitted, but that variable was unused.  The guard variable is now
suppressed in such cases.  For example:

  struct X {
    X();
  };
  template <typename T> struct A {
    static X sdm;
  };
  template <> X A<int>::sdm = X();
      // _ZGVN1AIiE3sdmE (IA-64 ABI) or __SDG__sdm__S__10A__tm__2_i (Cfront)
      // guard variable is suppressed.


12/17/15 [EDGcpfe/16721]
Missing substitution check for reference to qualified function type

Template argument substitution failed to check for the creation of
a reference to a qualified function type.  This could result in incorrect
overload resolution or partial specialization selection in cases where
SFINAE was being used to disqualify such cases.  Now fixed.

  template <class T> struct A {};
  template <class T> void f(A<T&>*);
  int main() {
    f<int (int) const>(0);  // previously accepted
  }


12/17/15 [EDGcpfe/16233]
Microsoft compatibility: internal error on specialization in variadic class

An internal error could occur (in find_placeholder_arg_for_pack) if a
variadic class template contained a Microsoft in-class specialization of
a member function template.  Now fixed.

  template<typename... Us> struct A;
  template<typename T, typename... Us> struct A<T, Us...> : A<Us...> {
    template<typename X> X f();
    template<> T f() { return T(); }
  };


12/17/15 [EDGcpfe/16693]
Attributes in class template declarations

The presence of an attribute (either a standard attribute or a GNU attribute)
immediately following a template parameter list in a class template declaration
had caused such templates to mistakenly be parsed as function templates,
typically resulting in spurious errors.  A change has been made to allow (and
ignore) attributes in this case, as well as after a "friend" keyword in
templated friend declarations.  For example, with --g++ --c++14:

  template <class T> [[deprecated]] class A {};
  template <class T> __attribute((deprecated)) class B {};
  struct X {
    template <class T> friend [[deprecated]] class Y;
    template <class T> friend __attribute((deprecated)) class Z;
  };


12/17/15 [EDGcpfe/16728]
Incorrect handling of multibyte characters following error fill-ins

If customers provided alternate error message text, and that text had
a fill-in immediately followed by a multibyte character sequence,
incorrect behavior (including a possible abort) could occur.  Now
fixed.


12/15/15 [EDGcpfe/16724]
USER_CONTROL_OF_STRUCT_PACKING removed

The configuration macro USER_CONTROL_OF_STRUCT_PACKING previously determined
if the front end supports extensions to control the alignment of class types,
variables, fields, etc.  The C and C++ languages have since evolved to include
standard features for such control, which means that with
USER_CONTROL_OF_STRUCT_PACKING set to FALSE the front end could not implement
the current language standards.  A FALSE value of
USER_CONTROL_OF_STRUCT_PACKING now triggers a preprocessing error when
building the front end, and not defining the macro has the same effect as
defining it to be TRUE had previously.  A separate global variable
pragma_pack_enabled is provided to control whether the "#pragma pack"
extension is enabled; it is always set to TRUE, but customers can modify its
value based on local preferences.


12/15/15 [EDGcpfe/16123,EDGcpfe/16300,EDGcpfe/16704]
Microsoft compatibility: __declspec(allocator)

The "allocator" __declspec attribute is now accepted (in Microsoft emulation
mode when microsoft_version >= 1900) on function types.  No action (other than
recording the attribute) is taken.  For example,
with --microsoft_version 1900:

  __declspec(allocator) void *f();


12/15/15 [EDGcpfe/16435]
clang and g++ compatibility: qualified friend declarations

When a qualified name occurs in a friend declaration, the standard mandates
that the name refers to a previously declared name, but g++ and clang seem to
only require that some function with that name exist in the proper scope.
clang only displays this behavior when the friend declaration is in a template.
The front end now emulates this behavior.  For example:

  int f();
  class A {
    friend int ::f(const A&);                       // g++ allows
    template <class T> friend int ::f(const A&, T); // g++ and clang allow
  } a;
  int x = f();
  int y = f(a);
  int z = f(a, 0);


12/14/15 [EDGcpfe/16545]
Microsoft compatibility: Builtin alias template __make_integer_seq

The front end now implements a builtin alias template __make_integer_seq,
which is meant to be an efficient implementation of std::make_integer_sequence.
The alias is available when microsoft_mode >= 1900.

  template <typename T, T... N> class seq {};
  __make_integer_seq<seq, int, 3> x;  // Has type seq<int, 0, 1, 2>


12/14/15 [EDGcpfe/16718,EDGcpfe/16719]
Default constructor generation error with constexpr constructor template

When generating a default constructor required a call to a constexpr
constructor template for a subobject, the front end sometimes issued a
spurious error.  For example:

  struct C { template<class = int> constexpr C() {} };
  struct S {
    C c;
  };
  S s;  // Previously, the generation of S::S() triggered an error claiming
        // S::c cannot be initialized.  Now accepted.

This is now fixed.


12/11/15 [EDGcpfe/16686]
Abort on invalid use of __FUNCTION__ etc.

In Microsoft mode, certain invalid uses of the special identifier __FUNCTION__
(and similar identifiers like __FUNCSIG__) could lead to an internal error in
set_curr_token_to_function_name_string (expr.c).  For example:

  #define _STR2WSTR(str) L##str
  #define STR2WSTR(str) _STR2WSTR(str)
  const wchar_t (*ss)[1] = &STR2WSTR(__FUNCTION__);
                                   // Previously triggered an internal error.

This is now fixed: An ordinary error is now issued.


12/11/15 [EDGcpfe/16699]
Explicit casts with lossy conversions

The front end optionally warns about conversions that may lose arithmetic
precision (see the entry of 6/10/13 for EDGcpfe/2155 etc.).  Now those
warnings are only issued for implicit conversions.  For example, with the
command-line options "--c99 --lossy_conversion_warning":

  unsigned long long f();
  void g() { unsigned r = (unsigned)f(); }
      // Previously elicited a warning.  Now silently accepted.


12/11/15 [EDGcpfe/16685]
Default arguments and parameter packs

The front end no longer diagnoses a member function template with a parameter
pack preceded by a parameter with a default argument.  For example:

  struct S {
    template<typename ... Ts> int f(int = 0, Ts ...ps);
      // Previously an error.  Now okay.
  };


12/11/15 [EDGcpfe/16697]
Pointer-to-member-function declarators and constexpr

In C++11 mode (but not C++14 mode), the front erroneously made const the
function type embedded in a pointer-to-member-function type if the declaration
for the pointer-to-member-function is constexpr.  This resulted in spurious
errors.  For example:

  struct S { void f(); };
  constexpr void (S::*pmf)() = &S::f;
    // Previously treated as "constexpr void (S::*pmf)() const", thereby
    // triggering an error claiming an incompatible initializer type.

This is now fixed.


12/11/15 [EDGcpfe/16692]
Abort on a coroutine returning a value when the promise type doesn't allow it

When a coroutine contains a "return <expr>;" statement, but its associated
promise type expects "return;" only, the front end aborted due to a null
pointer dereference in call_named_member_function (exprutil.c).  This is now
fixed.


12/11/15 [EDGcpfe/16408,EDGcpfe/16696]
__is_literal_type(void)

The "void" type is now treated as a "literal type" in C++14 mode and in
Microsoft C++ mode with microsoft_version >= 1900.  The type traits helper
__is_literal_type produces a true value accordingly.


12/11/15 [EDGcpfe/16681]
Alignment of a variable or field

In nonstrict C++11 modes, the front end accepts (with a warning) the alignof
operator applied to an expression (as opposed to a type).  However, if the
expression designates a variable or field with an explicit alignas specifier,
it ignored that specifier, unless GNU or (for variables only) Microsoft modes
were in effect.  Now, such a specifier affects the result of the alignof
operator in all nonstrict C++11 modes.  For example:

  alignas(16) int x[4];
  static_assert(alignof(x) == 16, "Unexpected");
    // Previously failed in default C++11 mode (assuming int has an
    // alignment other than 16).  Now okay.


12/11/15 [EDGcpfe/16688]
Spurious exception mismatch error on noexcept-specifier in class template

In some cases, a virtual function with a noexcept specifier overriding a
similar function for a template base class resulted in a spurious error
reporting an exception specification mismatch.  For example, in C++11 mode:

  template<typename T> struct B {
    virtual bool f(T) noexcept(false);
  };
  struct D : B<char> {
    virtual bool f(char) noexcept(false);  // Previously triggered a spurious
  };                                       // error.

This is now fixed.


12/10/15 [EDGcpfe/16689]
Spurious correspondence error on constant-valued template static data member

When simultaneously compiling multiple translation units containing
corresponding instantiations of constant-valued template static data members
whose instantiation is only required for the constant value, the front end
issued spurious duplicate-definition correspondence errors.  For example:

  // File 1:
  template<typename T> struct S { static int const N; };
  template<typename T> int const S<T>::N = 5;
  int y[S<int>::N];  // Instantiation of S<int>::N only needs the constant
                     // value of S<int>::N; the actual storage of the member
                     // need not be allocated.

  // File 2:
  template<typename T> struct S { static int const N; };
  template<typename T> int const S<T>::N = 5;
  int z[S<int>::N];  // Triggered a duplicate definition error.

This problem was introduced in C++11 modes by the changes for EDGcpfe/10300,
and then extended to other modes by the changes for EDGcpfe/16315.  This is
now fixed.


12/9/15  [EDGcpfe/16677]
Integral constant variables passed to constexpr reference parameters

Previously, the front end incorrectly allowed only constexpr variables to
be passed as constants to reference parameters of constexpr functions.  It
has now been changed to allow integral constant variables as arguments as
well.  For example, with --c++11:

  constexpr int f(const int& r) { return r; }
  void g() {
    const int i = 2;
    constexpr int j = f(i);   // Previously rejected as non-constant
  }


12/9/15  [EDGcpfe/15176,EDGcpfe/16691]
GNU C compatibility:  __auto_type

In GNU C modes with gnu_version >= 40900, the front end now accepts the
__auto_type specifier.  This specifier is similar to the C++11 "auto" type
specifier in that it allows the declaration of variables whose type is
derived from the associated initializer.  For example:

  __auto_type x = 3;  // Same as "int x = 3;".


12/9/15  [EDGcpfe/16700]
Corrupt IL pointer with "aligned" attribute in secondary translation unit

In some cases, a variable declaration in a secondary translation unit with an
alignment attribute and a corresponding declaration in the primary translation
unit (with or without that attribute) could result in an invalid attribute
pointer in the merged IL.  This could result in aborts if the IL is written to
a file or if a back end attempts to traverse the merged attribute list.
For example, in GNU C mode with removal of unneeded entities disabled:

  // Translation unit #1:
  int x;

  // Translation unit #2:
  extern int x __attribute((aligned(16)));

Previously, the merged IL representation for variable x pointed into freed
storage.  This is now fixed.


12/7/15  [EDGcpfe/16711]
Microsoft compatibility: Fix memory leaks in metadata processing

A few memory leaks have been plugged in the C++/CLI metadata processing.


12/7/15  [EDGcpfe/16710]
Microsoft compatibility: Crash on metadata initialization failure

A NULL pointer dereference could occur if the C++/CLI metadata initialization
process failed for some reason.  Such failures now result in a catastrophic
error.


12/7/15  [EDGcpfe/16708]
Microsoft compatibility: Support for Windows Runtime 1.4 metadata

A change has been made to add support for version 1.4 of the Windows Runtime
metadata.


12/4/15  [EDGcpfe/16698,EDGcpfe/14417]
Calling a constexpr function through a reference

The front end previously incorrectly rejected a call to a constexpr
function via a constexpr reference to that function in a context requiring
a constant expression.  This is now fixed.  For example, with --c++11:

  constexpr int foo() {
    return 11;
  }
  constexpr int (& r)() = foo;
  constexpr int i = r();   // Previously rejected as non-constant


12/2/15  [EDGcpfe/16695]
Single-element multi-dimensional arrays and constexpr constructors

The lowered IL generated for a default-initialized multi-dimensional array
having only one element and with a folded constexpr constructor sometimes
resulted in incorrect generated C code by the C-generating back end.  That
IL has been made more idiomatic.  For example (in C++11 mode):

  struct S {
    int s;
    constexpr S() : s(21) { }
  };
  int main() {
    int result;
    S x[1];
    result = x[0].s;
    S y[1][1];
    result += y[0][0].s;
    return result != 42;
  }

Previously, the C code generated for the initialization of y was incorrect.
This is now fixed.


12/1/15  [EDGcpfe/16502]
--ms_extensions and --ms_compatibility command-line options

Two new command-line options, --[no_]ms_extensions and --[no_]ms_compatibility,
have been added to emulate clang's -fms-extensions and -fms-compatibility
options respectively.  This creates a multi-tiered approach to Microsoft
compatibility, with --ms_extensions being the lowest level of compatibility,
then --ms_compatibility, and finally --microsoft.  Note that --ms_compatibility
implies --ms_extensions, and that --microsoft implies both --ms_compatibility
and --ms_extensions.  --microsoft is still a "major dialect" and as such cannot
be combined with other major modes (e.g., --g++ or --clang), but
--ms_extensions and --ms_compatibility may be combined with these modes.  Two
new globals, ms_extensions and ms_compatibility, have been added to correspond
to the new options.  Two new configuration macros, DEFAULT_MICROSOFT_EXTENSIONS
and DEFAULT_MICROSOFT_COMPATIBILITY, have also been added.


11/30/15 [EDGcpfe/16675]
Conditional operator and user-defined conversions

When processing a conditional operator the front end follows a number of
standard rules to find a "common type" for the second and third operands of
that operator.  Previously, the front end sometimes failed the process when
at least one of the operands requires a user-defined conversion to a pointer
type followed by a qualification conversion.  For example:

  struct S { operator volatile void*(); };
  void const *p;
  auto x = true ? p : S();  // Previously triggered a spurious error.
                            // Now okay: x has type "void const volatile*".

This is now fixed.


11/30/15 [EDGcpfe/16680]
VLAs and constexpr constructors

The front end previously aborted with an internal error in num_array_elements
("array with unknown bound"; in types.c) when processing a VLA declaration
whose elements are constructed using a constexpr constructor.  For example,
with --g++ --c++11:

  struct S { constexpr S() {} };
  void g(int n) {
    S vla[n]; // Previously triggered an internal error; now okay.
  }

This is now fixed (the constructor call is not constant-folded in such cases).


11/27/15 [EDGcpfe/16254]
GNU/clang compatibility: additional codes on line-identification directives

The GNU and clang preprocessors use additional codes on line-identification
directives to specify whether the directive represents the start of a new
header file or the resumption of a file after completion of a #include
directive, as well as whether the current file is from a system directory
or not.  The existing GEN_EXTRA_LINE_ID_INFO configuration macro controls
whether the entry/resumption codes appear in the front end's preprocessor
output in --old_c and --old_style_preprocessing modes (only).  The front
end has now been changed so that this macro also controls the generation of
the entry/resumption and system file indicators in GNU and clang
emulations.  This change enables consistent processing of the GNU header
files, whether compiled directly or from preprocessed output, since the
handling of some constructs differs depending on whether they appear in
system header files or in user code.


11/25/15 [EDGcpfe/15640]
Spurious incompatible linkage error and unbounded loop in Sun mode

A friend declaration referring to an extern "C" function could previously lead
to a spurious name linkage compatibility error, sometimes followed by an
unbounded loop (in perform_scheduled_routine_moves) in Sun mode.  For example:

  namespace {
    extern "C" { static int f(void); }
    class Foo {
      friend int f(void);
    };
    extern "C" {
      static int f(void) { return 0; }  // Previously resulted in a spurious
    }                                   // error and an unbounded loop.
  }

This is now fixed.


11/25/15 [EDGcpfe/16678]
Incorrect processing of function name strings with user-defined literals

In Microsoft mode and in gnu_mode with gnu_version < 30400, with
user-defined literals enabled, spurious errors could result if a function
template containing a use of __FUNCTION__, __PRETTY_FUNCTION__, or
__FUNCDNAME__ is instantiated.  This is now fixed.  For example, with
--user_defined_literals --no_microsoft_bugs:

  template <typename T> struct S {
    void f(int) {
      const char *p = __FUNCTION__;
    }
  };
  int main() {
    int i = 0;
    S<int>().f(i);  // Previously reported too few arguments in call
  }


11/25/15 [EDGcpfe/16544]
Microsoft compatibility: Add __is_assignable type trait

Recent versions of Microsoft Visual Studio have implemented a new
type trait: __is_assignable.  For example, with --microsoft:

  struct A {
    operator int();
  };
  static_assert(__is_assignable(int&, int), "ERROR");
  static_assert(__is_assignable(int&, A), "ERROR");


11/24/15 [EDGcpfe/16668]
Use of variadic template template parameter should cause substitution failure

A change made in version 4.10 (see EDGcpfe/15605 on 11/17/14) resulted in
a variadic function template being considered as usable even though
a substitution failure should have resulted because an empty pack was
used as a template argument for a template template parameter that had no
associated template parameter.  Now fixed.

  template < typename > struct B {
    typedef int I;
  };
  // Only this function should be considered callable
  template < template < typename > class TTP, typename T >
  void f(typename TTP < T >::I);

  // Should not be considered because it specifies too many arguments for B
  template <template <typename ... > class TTP, typename T1, typename ... Ts>
  void f(typename TTP < T1, Ts ... >::I);
  int main() {
    f<B, int>(0);
  }


11/23/15 [EDGcpfe/16661]
Floating-point literals in strict C-mode array bounds

The C standard only allows floating-point literals in integer constant
expressions if they are the immediate operands of a cast to an integer type.
That does not allow for a unary plus or minus operator on the literal.  The
front end now takes this rule into account in strict C modes.  For example:

  void g() {
    int x[(int)+2.0] = { 1, 2 };  // Now an error because x is treated as a
  }                               // as a variable-length array and may
                                  // therefore not have an initializer.


11/22/15 [EDGcpfe/16672]
get_definition_of_class and class fixups

When GET_DEFINITION_OF_CLASS_NEEDED is TRUE the get_definition_of_class
function is provided to allow a class to be defined on-demand.  This is
used in C++/CLI mode to load classes from assemblies, but can be used
by customers for other purposes.  If the call to get_definition_of_class
was done while some other class was in the process of being defined,
the fixup of things such as inline function bodies and default arguments
would not be done until all pending class definitions completed.  Now
the fixups for any classes loaded by get_definition_of_class are done
before get_definition_of_class returns.  In addition, the
classes_that_may_need_fixups list has been moved to the class fixup
header entry in the scope stack so that final class fixup processing
is also done when the last pending local class is completed or when
a class loaded by get_definition_of_class is finished.


11/19/15 [EDGcpfe/16387]
GNU compatibility: refinement of duplicate include directories

A change made in version 4.10.1 (see EDGcpfe/15809 on 3/17/15) caused
some include directories after a "-I-" option to be removed that were
not removed by the GNU compiler.  It appears that if a directory is
specified more than once using the -I option, and those options span the
-I- boundary, the duplicate entry is not removed.  But if there are
redundant include options (either both -I or both --sys_include) that
are both on the same side of the boundary, the later one is removed.  In
addition, as before, in any case (i.e., even when they span the -I-
boundary), if one is specified with --sys_include and the other with -I,
the -I option is removed.


11/19/15 [EDGcpfe/16667]
Incorrect value for __tls_init instantiation_needed_bit_number flag in
--one_instantiation_per_object mode

In cases where --one_instantiation_per_object is used and thread_local
variables required initialization, the instantiation_needed_bit_number
flag for the generated __tls_init routine that is used to perform the
initialization had inadvertently been set to 1 (it should be 0).  Now
fixed.  For example (with --c++11 --one_instantiation_per_object):

  int f(int i) { return i; }
  thread_local int x = f(99);
  int main() {
    return x != 99;
  }


11/19/15 [EDGcpfe/16666]
Incorrect return type for runtime routines

The return type used by lowering when creating the __throw_bad_array_new_length
and __cxa_throw_bad_array_new_length runtime library routines had been "void *"
and has been changed to "void" to match the actual runtime routine signatures.


11/17/15 [EDGcpfe/16660]
Generic lambdas and default arguments

The processing of default arguments in generic lambdas was previously
incomplete, leading to invalid IL and, in some configurations, internal
errors (e.g., in inline.c).  For example:

  void g() {
    auto lm = [](auto p, int = 0) {};
    lm(1);
  }

In some configurations, the example above triggered an abort in the front end.
In other configurations, the IL for the call did not make the default argument
explicit.  This is now fixed.


11/17/15 [EDGcpfe/16625]
Segfault in set_local_static_guard_var

In certain configurations that do lowering but don't promote local statics,
a segfault could occur (in set_local_static_guard_var) during the lowering
of a dynamic initialization of a local static.  Now fixed.  For example
(with --c++11):

  struct A {
    int m = 0;
  };
  void f() {
    static A a;
  }


11/17/15 [EDGcpfe/16653]
Abort in switch_to_scope_region on decltype in generic lambda

In some cases involving a decltype construct in a generic nested lambda, the
front end aborted in switch_to_scope_region.  For example:

  void g() {
    auto lm = []() {
      return [](auto p) ->decltype(p) { return p; };
    };
    int (*fp)(int) = lm();  // The instantiation of the inner lambda
  }                         // previously triggered an abort.

This is now fixed.


11/17/15 [EDGcpfe/16634]
Abort on lowering of lambda defined in static data member initializer

In some cases where a lambda in a static data member initializer triggered the
instantiation of templates, name mangling aborted with an internal error in
add_discriminator.  For example:

  typedef int (*PF)();
  template<typename> struct F {
    template<typename T> constexpr F(T &&) {}
  };
  struct X { X(F<PF>); };
  struct S { static X sdm; };
  X S::sdm = { []() { return 0; } };  // Previously triggered an abort.

This is now fixed.


11/17/15 [EDGcpfe/16637]
Invalid C11 _Generic representation

In configurations with REPRESENT_C11_GENERIC_CONSTRUCT_IN_IL set to TRUE, the
front end often produced invalid IL.  First, if the selected expression was
one immediately following the "default:" expression, the expressions were not
correctly recorded under the enk_c11_generic node.  This could, e.g., lead to
internal errors in the C++-generating back end.  Second, the value category
of the enk_c11_generic node was always set to "rvalue", which resulted in
invalid diagnostics when the selected expression is an lvalue or a function
designator.  This is now fixed.


11/16/15 [EDGcpfe/16642]
Discarding function template candidates early

When performing overload resolution, the front end now discards function
templates earlier if it can do so based on just comparing the number of call
arguments with the parameter list.  For example:

  template<typename T> struct S {
    typedef decltype(*T()) type;
  };
  template<typename T> typename S<T>::type g(int x); // (1)
  template <typename> void g();
  int main(){
    g<int>();
  }

Previously, the partial substitution of candidate (1) for the call g<int>()
triggered an error in the instantiation of S<int> (the expression "*T()" is
not valid when T is int).  Now, that candidate is discarded early (except in
GNU C++ mode) because the parameter list cannot match the number of arguments
in the call.


11/16/15 [EDGcpfe/16648]
Template static data members and source sequence entry elimination

In configurations with CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
set to TRUE but NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set
to FALSE, the front end sometimes aborted with an internal error in
eliminate_variable_definition_source_sequence_entry when eliminating the
instantiation of a template static data member that was needed only to
determine the constant-valued initializer of that static data member.
For example:

  template<typename T> struct S {
     static int const N;
  };
  template<typename T> int const S<T>::N = 3;
  void f() {
    int const x = S<int>::N;  // S<int>::N instantiated only for its value.
  }                           // The subsequent elimination of the definition
                              // previously triggered an internal error.

This is now fixed.


11/16/15 [EDGcpfe/16651]
Lambdas and VLAs

A variable-length array (VLA) cannot be captured by a lambda.  However, the
front end previously allowed referencing a variable-length array in a lambda
when the array was declared outside the lambda if the reference appeared
in an unevaluated context (like the operand of a sizeof operator).  Such
references are now diagnosed as errors (previously, they produced invalid IL,
and sometimes triggered internal errors during IL lowering).  For example
(with "--c++11 --vla"):

  void f(int x) {
    int n[x];
    auto lm = []{ return sizeof(n); };  // Now an error.  Previously
  }                                     // triggered an internal error in
                                        // some configurations.


11/15/15 [EDGcpfe/16608]
Assertion failure with unevaluated expressions in lambdas

As a result of the changes for EDGcpfe/16292 et al., an assertion failure
(in lower_expr_full) had been triggered when a local variable of an enclosing
routine appeared in an unevaluated context within a lambda.  The assertion
failure has been corrected, but back ends should be prepared to handle the case
where a variable with automatic storage is referred to from another scope (both
will have the same memory region).  For example (with --microsoft):

  void f(int n) {
    auto lm = []{ __assume(n); };
  }


11/12/15 [EDGcpfe/16403,EDGcpfe/16644]
GNU C++ compatibility: In-class initializers for template static data members

In GNU C++ mode, in-class initializers for static data members of class
template instantiations are now only instantiated when the associated
value is needed or the associated definition is instantiated.  For example:

  template<typename T> struct S {
    static unsigned const N = sizeof(T());
  };
  S<void> s;  // Now accepted in GNU C++ mode, because the initializer of
              // S<void>::N is not instantiated at this point.


11/11/15 [EDGcpfe/15312,EDGcpfe/16641]
Abort on friend function defined in variadic class template

An abort could occur (in increment_variadic_rescans_for_reusable_cache)
on a pack expansion in a friend function defined in a variadic class
template.  Now fixed.

  template <class T> struct A {};
  int g(...) { return 0; }
  int f(...);
  template <class ... T> struct B {
    friend int f(...) {
      return g(A<int(T...)>());
    }
  };
  int main() {
    B<int&> b;
    f(0);
  }


11/10/15 [EDGcpfe/16639]
Using-declarations and member templates in dependent base classes

Previously, the front end erroneously assumed that a using-declaration
importing a name from a dependent base class did not import a template.
This sometimes triggered spurious errors.  For example, in strict C++ mode:

  template<typename> struct B {
    template<typename> void b();
  };
  template<typename T> struct D: B<T> {
    void d() {
      this->template b<T>();  // Previously triggered an error because
    }                         // b was assumed not to name a template.
    using B<T>::b;            // Now okay.
  };

This is now fixed.


11/9/15  [EDGcpfe/16626]
Spurious error on template-dependent functional-notation cast with braces

When a C++11-style functional-notation cast with braces appears in a context
requiring a constant result (such as a template argument), the front end
sometimes issued a spurious error.  For example:

  template<bool> struct M { typedef int type; };
  template <typename> struct B {
    constexpr operator bool() const noexcept { return true; }
  };
  template <typename T,
            typename = typename M<B<T>{}>::type> struct S;
    // Parsing of the default argument previously produced a spurious error
    // implying that the cast isn't constant.  Now okay.

This is now fixed.


11/8/15  [EDGcpfe/16257]
Macros with extended characters and mixed UTF-8 and non-Unicode files

In configurations with UNICODE_SOURCE_SUPPORTED set to TRUE, the front end
could report spurious "unrecognized token" errors if a macro defined in a
file with one encoding and used in a file with a different encoding
contains an identifier with an extended (non-ASCII) character.  This
problem has been addressed by using a canonical form for identifiers
appearing in a macro definition in such configurations; the canonical form
replaces each extended character with a universal-character-name so that
the identifier will be scanned identically regardless of the encoding in
effect at the time.


11/7/15  [EDGcpfe/16629]
Mechanism to identify friend functions defined in class instantiations

Customers have requested a simple mechanism to determine whether a
function defined in a friend declaration resulted from an instantiation
of what was originally a definition in a dependent context.  The flag
friend_defined_in_instantiation has been added to a_routine to provide
this information.

  template <typename T> struct A {
    friend void f(A*) { /* Could make use of template parameters. */ }
  };
  A<int> a;  // f(A<int>*) has the new flag set


11/6/15  [EDGcpfe/15972]
Array to pointer decay in dependent constant expressions

The front end previously erroneously treated an array to pointer decay as
making a dependent expression non-constant.  Such expressions are now
accepted as constant during prototype instantiation.  For example, with
--c++11:

  template<typename T1, typename T2> struct A {
    static constexpr bool v = true;
  };
  template<typename T> struct B {
    typedef T t;
  };
  template<typename T> struct C {
    static constexpr const char* const x =
      A<T, typename B<T>::t>::v ? "t" : "f";  // Previously not constant
                                              // because of array to ptr decay
  };


11/6/15  [EDGcpfe/16630]
GNU compatibility: __builtin_ia32_pause

Previously the GNU builtin __builtin_ia32_pause had only been defined when
gnu_version >= 40800; it is now defined when gnu_version >= 40700.


11/6/15  [EDGcpfe/16633]
Memory region used for diagnostics

Typically the front end uses FRONT_END_REGION_NUMBER when allocating
diagnostic messages, except for severe errors or when running in a standalone
utility, in which case the general memory pool (NO_MEMORY_REGION_NUMBER) is
used.  A change has been made to also allocate the diagnostic in the
general memory pool when in_front_end is FALSE in order to allow the error
routines to be used by back ends.


11/6/15  [EDGcpfe/16532]
Friend declarations that could refer to member or member template

A change made in version 4.5 (see EDGcpfe/12244 on 1/18/12) changed
the way in which a friend declaration was treated when it referred
to an overload set that included both a member template and member
function declaration that could match.  This issue is being considered
by the standards committee (core issue 1665).  Our new behavior matches
the direction that we currently expect the committee to follow.  In a friend
declaration, we now (in all modes) prefer a non-template member unless an
explicit template argument list (even if empty) was specified.  This
changes does not affect other declarative contexts (explicit specializations
and explicit instantiations) that may or may not eventually be affected by
core issue 1665.

  template <class T> struct A;
  struct X {
    template <class T> int f(A<T>* pat);
    int f(A<int>* pai) ;
  };
  template <class T> struct A {
    A() : t(0) { }
  private:
    T t;
    // Should refer to f(A<int*>) when T is int
    friend int X::f(A<T>* pat);
  };
  template <class T> int X::f(A<T>* pat) { return pat->t; }
  int X::f(A<int>* pai) { return pai->t; }
  A<float> af;


11/5/15  [EDGcpfe/16628]
a_stmt_source_position removed

Previously, in configurations with FULL_SOURCE_POS_IN_IL_STATEMENT set to
FALSE, statement positions recorded only the sequence number (i.e., a
generalized line number) at which a statement begins and not the column
number.  That option is now removed: Statements now always record full
positions.  (This is a potential IL CHANGE.)


11/4/15  [EDGcpfe/16620]
Abort on lambda in default argument

In some cases, a lambda expression in a default argument (in C++11 mode)
could result in an abort (in type_is_lambda_in_default_argument) during name
mangling.  For example:

  void g() {
    extern int f(int p = ([]{ int i = 3; return [=]{return i;}; }()()));
  }

This is now fixed.


11/4/15  [EDGcpfe/16622]
Sun compatibility: Allow extended variadic macros

Sun Studio 12 update 1 allows extended variadic macros, so those are now
accepted by default in Sun emulation mode.  For example (with --sun -E):

  #define DEBUG(args...) printf(##args)


11/3/15  [EDGcpfe/16618]
Lambdas capturing "this" from within a default argument

A lambda is not permitted to capture any entity if that lambda appears in a
default argument.  Previously, the front end failed to diagnose that if the
captured entity is the "this" pointer.  The resulting IL was invalid and
could result in internal errors later on.  For example:

  struct S {
    void g() {
      void f(int x = [this]{ return 1; }());  // Invalid use of "this" was
    }                                         // previously not diagnosed.
  };                                          // Now this is an error.

This is now fixed.


11/3/15  [EDGcpfe/16607]
Microsoft C++ compatibility: Same-type casts in decltype constructs

In Microsoft mode, the front end usually ignores a cast of an lvalue to the
type of that lvalue.  Ordinarily, such a cast would produce an rvalue, but by
ignoring the cast the resulting expression remains an lvalue.  Now, the front
end no longer ignores the cast inside a decltype operand: That ensures that a
non-reference type is produced if such a cast appears at the top-level of a
decltype operand.  For example:

  void g(int i) {
    (int)i = 1;          // Accepted in Microsoft C++ mode.
    decltype((int)i) c;  // Previously an error; now okay.
  }

Previously, "decltype((int)i)" was treated as "decltype(i)" and therefore
produced an int& type (resulting in an error since the reference has no
initializer).  Now, the cast is not ignored and "decltype((int)i)" produces
an int type (which is standard behavior).


11/2/15  [EDGcpfe/16616]
Source sequence entries for prototype instantiations of class templates

In configurations with FRIEND_AND_MEMBER_DEFINITIONS_MAY_BE_MOVED_OUT_OF_CLASS
set to TRUE, the front end sometimes turns a member definition appearing in a
class definition into a non-defining member declaration, and then moves the
source sequence entries for the definition outside the class.  Now it no longer
performs this transformation for prototype instantiations.  This results, for
example, in a more faithful rendering by the C++-generating back end of the
original form of class template definitions.  For example:

  template<typename T> struct S {
    void f() {}  // In some configurations the source sequence list of
  };             //  S<T>::f() was as if the definition appeared outside the
                 // class.  Now the original arrangement is preserved.

Note that for real instantiations the rearrangement of source sequence entries
still occurs.


11/2/15  [EDGcpfe/16606]
Alignment attributes on enum types

A change has been made to the way attributes are applied to enum types.
Attributes are now applied before scanning the enumeration specifiers, which
means that attributes may be applied to an incomplete type (only opaque enum
types are complete at this point).  This has implications for attributes
that modify the alignment of the enum type as the underlying type (and
therefore the natural alignment) is not known until the closing } of the
enum-specifier.  The explicit alignment is now maintained (previously it had
been inadvertently discarded in the process of setting the underlying type).
Note that there seems to be some implementation divergence here and an effort
has been made to emulate Microsoft, GNU, and Clang modes as appropriate.  For
example (with --c++11):

  enum alignas(8) E { e };
  static_assert(alignof(E) == 8, "fail");


11/2/15  [EDGcpfe/16615]
GCC compatibility: Constant-valued variables and null pointer constants

The changes for EDGcpfe/10791,EDGcpfe/15927 (see entry of 1/23/15) caused the
front end to treat constant-valued variables as constant expressions in more
contexts in GCC mode.  It inadvertently also caused the front end to treat
zero-valued variables as null pointer constants in some cases, whereas GCC does
not do so.  That is now fixed.  For example:

  static const int zero = 0;
  int main() {
    int a, *p = &a;
    *(1 ? p : (void*)zero) = 3;  // Previously accepted in GNU C mode;
    return 0;                    // now an error.
  }

In C a conditional operator selecting between a null pointer constant and a
pointer operand has the type of the pointer operand.  Since previously the
expression "(void*)zero" was treated as a null pointer constant, the
conditional operator produced an int*.  Now, "(void*)zero" is not a null
pointer constant, and the type of the conditional operation is therefore
void*.


11/2/15  [EDGcpfe/16495]
C++-generating back end: access of typedef used in member declaration

The C++-generating back end failed to consider the fact that an
otherwise-inaccessible member typedef can be used in the declaration of
another member of the same class, and as a result it unnecessarily used the
underlying type of the typedef in the code generated for such declarations,
sometimes resulting in errors in the generated code.  This is now fixed.
For example, in configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to
TRUE:

  template<bool B> struct C { };
  class A {
    template<typename T> struct B {
      template<typename U> static char f(int);
      typedef C<sizeof(f<const T>(0)) == 1> type;
      static const type value;
    };
  };
  // Previously used the underlying type instead of A::B<T>::type in the
  // generated code for the following declaration:
  template<typename T> const typename A::B<T>::type A::B<T>::value;


11/1/15  [EDGcpfe/16457]
C++-generating back end: precedence of left operand of subscript operator

The C++-generating back end ignored the precedence of the left operand of
the subscript operator, always enclosing it in parentheses.  For most
expressions the unneeded parentheses were innocuous, but in some cases the
generated code was either erroneous or had a different meaning from that of
the original source.  This has now been fixed, and the left operand of the
subscript operator is parenthesized only when required by the syntactic
precedence of the operators.  For example, in a configuration with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, with --strict --c++14:

  template<typename T> void f() {
    T()[T::f()];   // Previously generated as (T())[T::f()], which elicits
                   // syntax errors from the front end and from clang
  }


10/30/15 [EDGcpfe/16578]
Partial substitution of constant expressions in pre-C++11 SFINAE contexts

The changes implementing C++11 SFINAE (see also the entry of 4/26/10 for
EDGcpfe/9169) accidentally changed the behavior of pre-C++11 SFINAE in certain
situations where a partial substitution of a template parameter list (through
an explicit but incomplete list of template arguments) results in a
constant-expression with remaining template parameters.  For example:

  template <bool B, class T> struct E {
    typedef T type;
  };
  template <class Ret, class T>
    typename ::E<true || (sizeof(T)<8), T&>::type m(T&);
  void g(int i) {
    m<int&>(i);  // Previously an error in C++03 mode; now okay.
  }

Here, the partial substitution for m<int&> (with T left unsubstituted)
triggered a spurious SFINAE failure in the substitution of the constant
expression "true || (sizeof(T)<8)", which in turn caused the front end to fail
to resolve the call.  This is now fixed.


10/30/15 [EDGcpfe/16599]
Member function calls with incomplete return types and decltype

In C++11, the return type in a function call need not be complete if the
function call appears as the immediate operand of a decltype construct (see
the Changes entry of 7/19/13 for EDGcpfe/11740,EDGcpfe/14277).  The front end
failed to implement that rule for member function calls.  For example:

  struct R;
  struct S {
    R f();
  } s;
  decltype(s.f()) g();  // Previously an error; now okay.

This is now fixed.


10/29/15 [EDGcpfe/16539]
Captured variables not consistently marked as referenced

When a variable is captured by a lambda, its "referenced" flag was not always
correctly set to TRUE.  That could, e.g., result in incorrectly lowered IL in
configurations with MINIMAL_INLINING set to TRUE.  This in turn could lead to
invalid C code generated by the C-generating back end or IL write-read errors
when working via an IL file.  For example:

  template <class ...T> inline void f(T... args) {
    auto lm = [&args...]()->void {};
  }
  int main() {
    f(1, 'a');
  }

Previously, the IL produced by the minimal inliner was invalid.  This is now
fixed.


10/28/15 [EDGcpfe/16388]
C++-generating back end: missing template arguments in alias template
specialization

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, a
dependent specialization of an alias template appearing in a template
definition was sometimes emitted in the generated code without a template
argument list.  This is now fixed.  For example, with --c++11 --strict:

  struct S { static const bool v = true; };

  template<typename F, typename A> S f(int);

  template<typename F, typename A> using X = decltype(f<F, A>(1));

  template <bool b> void g(void);

  template <typename T, typename U> void h() {
    g<X<T,U>::v>();  // Previously generated as g<X::v>()
  }


10/27/15 [EDGcpfe/15703]
Handling of immediate pragmas in cached contexts

When an immediate pragma is encountered while caching tokens, source
sequence entries and IL entries are now suppressed.  The IL entries were,
in general, benign.  But in versions that generate source sequence lists,
additional copies of the pragma could appear in output generated by the
C++-generating back end.  Now fixed.

  struct A {
    void f() {
      // Pragma would appear twice in C++-generating back end output
      #pragma GCC ivdep
      for(int i = 0; i < 1; ++i) { }
    }
  };


10/26/15 [EDGcpfe/15492]
GNU compatibility: Allow _Thread_local in C mode when gnu_version >= 40900

The _Thread_local storage class specifier is now enabled when using GNU C
emulation mode and gnu_version >= 40900.  For example (with --gcc --gnu_version
40900):

  _Thread_local int i;


10/23/15 [EDGcpfe/16595]
Spurious error on "typename :: template"

The resolution for core issue 1411 amended the grammar to allow "typename ::
template" and the front end has now been modified accordingly.  The following
example had resulted in a spurious error:

  template <class T> struct A {};
  template <class T> typename :: template A<T> f();


10/17/15 [EDGcpfe/16583]
Incorrect correspondence processing for fields in C modes

When simultaneously compiling multiple translation units in C mode, the front
end sometimes produced incorrect cross-translation-unit correspondences for
fields of struct and union types.  That resulted in incorrect IL and likely
aborts in the processing that followed.  For example:

  // File f1.c:
  struct S { char *s; };
  extern void g(const struct S*);

  // File f2.c:
  struct S { char *s; };
  void f(const struct S *ps) {}

  // File f3.c:
  struct S;
  void f(const struct S *ps);
  void g(const struct S *ps) {}

Simultaneously compiling these three translation units in the given order in
C99 mode resulted in a crash (configuration dependent).  This is now fixed.

A similar fix was made to handle enumerator constants of C-mode enumeration
types.


10/15/15 [EDGcpfe/16501]
GNU C++ compatibility: Array-wise initialization

Ordinarily, initializing an array variable with non-aggregate elements requires
braced initializer notation.  E.g.:

	struct S { S(); };
	S x[2] = { S(), S() };

In GNU C++ mode, the front end now accepts a notation like:

	S y[2] = S();

which implies that every element of the array is initialized by the initializer
expression (i.e., the initialization of y is equivalent to that of x in these
examples).


10/15/15 [EDGcpfe/16572]
Microsoft emulation: Spurious error on local class with alignas

When the keyword alignas appears on a local class definition in Microsoft
emulation mode, a spurious error had been reported.  Now fixed.  For example,
with --microsoft_version 1900:

  void f() {
    struct alignas(16) A {};
  }


10/15/15 [EDGcpfe/16581]
Build issue when TARG_ALL_POINTERS_SAME_SIZE is FALSE

As a result of the changes for EDGcpfe/15604 et al., the front end failed to
build in configurations where TARG_ALL_POINTERS_SAME_SIZE is set to FALSE.
Now fixed.


10/15/15 [EDGcpfe/16298]
C++-generating back end abort on function declared with decltype

When a function is first declared with a type expressed via a decltype
specifier, and later defined using an ordinary function declarator, the front
end incorrectly recorded the "declared type" of the function definition as
the type entry representing the decltype construct.  If the latter construct
appears in a local scope, this could trigger an internal error in the
C++-generating back end (gen_routine_specifiers_and_declaration).  For example:

  void f() {}
  void h() {
    decltype (f) g;
  }
  void g() {}  // Rendering of this definition triggered an abort in the
               // C++-generating back end.

This is now fixed.


10/14/15 [EDGcpfe/16580]
Performance improvements in template processing

A number of changes have been made to improve the performance of code
that makes heavy use of templates.  Specifically:

- inactive_scope_lookup now handles template parameter lookup specially to
  avoid looking through long lists of symbols on the inactive list.

- A hash table is used to find previously created function template
  instantiations.

- A hash table is used to find previously created substituted types.

An improvement of 2-10% is common for many large template cases, but
improvements of up to 3X have been observed for some extreme cases.


10/13/15 [EDGcpfe/16577]
Internal error with multiple translation units and constexpr templates

An internal error could occur (in update_instantiation_required_flag)
in a compilation involving multiple translation unit mode (i.e., the use
of secondary translation units in a single compilation, not multiple individual
translation units).  This could occur when a constexpr function template
was used in a secondary translation unit in a manner that did not require
that the function body be preserved for code generation purposes.  This has
only been observed in configurations in which LOWER_EXTERN_INLINE is TRUE.
Now fixed.  In a configuration with COMPILE_MULTIPLE_TRANSLATION_UNITS
set to TRUE, compiling the translation units below would illustrate the
issue.

  file: tu1.c:
  extern int x;

  file: tu2.c:
  constexpr int f ( int a, int b ) { return a * b; }
  const int i = f( 6, 7 );
  template <typename T > constexpr T g(T a, T b) { return a < b ? b : a; }
  const int i2 = g<int>(1,2);
  const int i3 = g<int>(3,2);
  const int i4 = g<int>(4,2);
  const int i5 = g<int>(-3,5);
  const int i6 = g<int>(-2,6);
  int main() { 
    int array[] = {i2,i3,i4,i5,i6};
    int a = i;
    return a + array[2];
   }


10/13/15 [EDGcpfe/16573]
IA-64 ABI: assertion failure in define_one_virtual_function_table

In cases where a local class contains a virtual function and there is no
reference to the virtual function table within that function, but the virtual
function table is required by a reference external to the function, an
assertion had occurred in IA-64 ABI configurations (in
define_one_virtual_function_table).  Now fixed.  For example, with
--c++11 -tused:

  template <class T> void f() {
    new T;
  }
  void g() {
    struct A {
      virtual void vf() {}
    };
    f<A>();
  }


10/13/15 [EDGcpfe/16385]
UTF-8 character literals

The front end now accepts UTF-8 character literals as described in
Committee document N4267, which is expected to be part of C++17.  This
feature is enabled by default in C++17 mode and in Microsoft mode with
microsoft_version >= 1900; it can be controlled explicitly via the
--[no_]utf8_char_literals command-line option.  For example, with --c++17:

  char a = u8'a';       // Now accepted
  char b = u8'\u00e0';  // Error, >1 code unit in UTF-8 character literal


10/12/15 [EDGcpfe/16575]
Gracefully fail to inline when certain assumptions are violated

As mentioned in the Changes entry for EDGcpfe/16550, inlining had assumed that
it is always possible to determine if the argument for "this" in a constructor
is non-null.  Cases where a complex expression's value could not be determined
to be non-null had resulted in an assertion failure.  A change has been made to
fail to inline the routine (with a remark) in such cases.


10/12/15 [EDGcpfe/16550]
Inlining of constructor when NEW_CAN_BE_FOLDED_INTO_CTOR is TRUE

The code that inlines constructors assumes that the "this" parameter will not
be used as an lvalue in the constructor, and relies on being able to optimize
the assignment to "this" that lowering introduces in configurations where
NEW_CAN_BE_FOLDED_INTO_CTOR is TRUE.  In the case below that assumption had
been violated (resulting in an assertion failure "remap_var_for_inlining: wrong
kind of remap").  In this case, when the call to A::A(E) is inlined, the
argument for "this" is &temp->m2, whose value had not been considered to be
non-null even though the offset for m2 is known to be non-zero.  Changes were
made to bool_value_is_known_at_compile_time and is_constant_valued_expression
to recognize this as an expression with a non-null value which allows the
routine to be successfully inlined (the latter change is needed in
configurations where LOWERING_NORMALIZES_BOOLEAN_CONTROLLING_EXPRESSIONS is
TRUE).  For example (with --c++11 --no_exceptions):

  enum E { e };
  struct A {
    A(E _e) { while(0); }
  };
  struct S {
    int m1;
    A   m2;
  };
  void f() {
    new S{ 0, e };
  }


10/9/15  [EDGcpfe/16565]
Access to uninitialized position variable in f_is_generalized_identifier_start

In some error cases, the front end sometimes copied an uninitialized position
variable (representing the position of a constructor or finalizer).  This
happened in f_is_generalized_identifier_start.  This is now fixed.


10/9/15  [EDGcpfe/16523]
Internal error on aggregate mem-initializer with nontrivial destruction

The front end previously sometimes generated invalid IL for mem-initializers
with nontrivial destruction, which in turn could lead to an internal error
during IL lowering (in lower_dynamic_init).  For example:

  struct A { ~A(); };
  struct B {
    ~B();
    B(const A&);
  };
  struct C {
    struct {
      B b;
      int i;
    } m;
    C() : m({A(), 0}) {}  // Previously generated invalid IL and an abort
  };                      // during IL lowering.  Now okay.

This is now fixed.  The change involved a minor IL CHANGE: The field
source_expr of a_constructor_init is now source.expr instead.

The current problem resulted from the earlier changes for EDGcpfe/15741 (a
related issue; see entry of 12/4/14).


10/9/15  [EDGcpfe/16570]
is_constexpr indication for alternate entry points in the IA-64 ABI

The is_constexpr and is_declared_constexpr flag settings were inadvertently
not transferred from the primary routine when creating alternate entry points
in the IA-64 ABI.  Now fixed.


10/8/15  [EDGcpfe/16528]
constexpr member function invocation during copy construction

When evaluating a mem-initializer of a constexpr copy constructor that
invokes a member function of the object being copied from and the source
object is not a constant, the front end previously incorrectly evaluated
the call as if the member function were invoked for the object being copied
to.  This is now fixed.  For example, with --c++11:

  struct S {
    constexpr S(): a(1), b(2) { }
    constexpr int f() const { return a; }
    constexpr S(const S& o): a(10), b(o.f()) { }
    int a, b;
  };
  void f() {
    S x;
    S y(x);   // Previously set y.b to 10, now to 1
  }

In the initialization of y, the expression o.f() in the initializer for
S::b is transformed to x.f(), which cannot be folded because x is not a
constant.  This previously caused the front end to evaluate y.f() instead,
giving the value 10; now the evaluation of x.f() is correctly deferred to
runtime, giving the value 1.


10/8/15  [EDGcpfe/16146]
Function deferral issue with partial specialization

A variable has been added to the front end that is TRUE if, when deferring
function prototype instantiations, partial specialization members should not
have their prototype instantiations deferred.  This feature was added to
work around the fact that parsing code in an unused function template or
member function of template class can result in the instantiation of a
class, and a different result would be obtained if the instantiation were
done later.  Compilers should complain about such position-dependencies
in partial specializations, but at this point, it appears that only the
EDG front end does.  This is essentially a heuristic to allow some open
source applications to build.  This feature can be enabled by default with
the DEFAULT_SUPPRESS_DEFERRAL_ON_PARTIAL_SPEC_MEMBERS macro.  It can
also be enabled with --set_flag suppress_deferral_on_partial_spec_members.
The value is only used if defer_function_prototype_instantiations is TRUE.

  template <class T1, class T2> class A;
  template <class T> struct A<T, void> { void f(); };
  template <class T> struct A<T*,void> {
    // This unused function binds A<char,void> to the partial
    // specialization above.
    void g() { A<char, void>().f(); }
  };
  template<typename T> struct A<char, T> {};
  // Ambiguous unless the prototype instantiation of g is done above
  A<char, void> f;


10/8/15  [EDGcpfe/15600,EDGcpfe/16558]
Allow use of inaccessible injected template name

Other compilers seem to (for an unknown reason) fail to do access
checking on the injected class name of class templates.  We did do
such checking, causing us to issue an error on examples like the one
below.  We now suppress those access checks in all but strict mode.

  template <typename T> struct A {};
  struct B : private A<int> {};
  struct C : B {
    void f() {
      A<int> A;
    }
  };


10/7/15  [EDGcpfe/16489]
Dependent constexpr conditional expressions

The front end previously issued a spurious "must have a constant value"
diagnostic for non-constant expressions appearing in conditional
expressions in contexts requiring a constant expression when the
controlling expression is value-dependent.  This is now fixed.  For
example, with --c++11:

   extern int i;
   template <bool B> struct S {
     static constexpr int n = B ? 0 : i;  // Previously a spurious error
   };


10/7/15  [EDGcpfe/16128,EDGcpfe/16376,EDGcpfe/16397]
Chains of variadic alias templates

The front end did not always correctly handle a chain of variadic alias
templates when instantiating a template declaration involving such a chain.
This resulted in spurious instantiation failures.  For example:

  template<typename ... Ts> struct V1 {};
  template<typename ... Ts> using V1alias = V1<Ts...>;
  template<typename ... Ts> struct V2 {};
  template<typename ... Ts> using V2alias = V2<V1alias<Ts...>>;
  template<typename ... Ts> V2alias<Ts...> ft(Ts...) {
    return V2alias<Ts...>();
  }
  int main() {
    ft(1);  // Previously failed to instantiate ft<int>.
  }

This case elicited a spurious error because the parameter pack for Ts in
V1alias was not correctly expanded during the instantiation of V2alias<Ts...>
in the declaration of ft.

The underlying problem was an erroneous representation of template argument
packs.  For example:

  template<typename ... T0> struct A {};
  template<typename ... T1> using B = typename A<T1...>::type1; 
  template<typename T2> struct C {};
  template<typename ... T3> using D = typename C<B<T3...> >::type2; 
  template<typename ... T4> using E = typename D<T4...>::type3; 

In the last line, the template argument T4 of D lost its "is_pack" flag
setting during the processing of the various layers of aliases.  This caused
erroneous output by the C++-generating back end when the configuration macro
PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE.

This is now fixed.


10/7/15  [EDGcpfe/16335]
Incorrect pack value following sizeof...

If a pack expansion included a sizeof... operator that used the same pack
both in the sizeof... and later in the expansion, the latter reference
would get an incorrect value.  Now fixed.

  template <int ... > class A;
  template <> struct A<3,4> {};
  template <int ... I> struct B {
      A <5 -  sizeof ... (I) + I ... > a;
  };
  B<0,1> c;


10/7/15  [EDGcpfe/16560]
PCH issue with new diagnostic processing routines

The reworked diagnostic routines in version 4.10.1 failed to restore some
variables when a precompiled header file was being read.  This could
cause an abort if the compilation using the PCH file issued diagnostics
prior to the PCH file being read.  Now fixed.

10/6/15  [EDGcpfe/16559]
Spurious error on virtual inline member of a class template

In strict mode, the front end issued a spurious error on a virtual inline
member of a class template with no function body.  For example:

  template<typename> struct S {
    virtual inline ~S();  // This previously triggered an error in strict
  };                      // mode, even when the template is unused.

This is now fixed.


10/6/15  [EDGcpfe/16547]
Facility to provide additional information about diagnostics

Version 4.10.1 included a reworking of the diagnostic mechanism to allow
additional information about the cause of an error (for example, the reason
for a constexpr evaluation failure) to be provided.  The interface
routines to make use of this have now been added, and are available for
customers to add similar facilities for other purposes.  The function
list_diagnostic can be used to add a "more information" diagnostic to a
list that may or may not be used later if an error is detected.  Later,
add_more_info_list or discard_more_info_list can be used to issue or
discard the information.  For example:

  list_diagnostic(ec_some_info, &pos, &my_list);
  /* ... */
  if (error_occurred) {
    dp = start_pos_error(ec_something, &pos);
    add_more_info_list(dp, &my_list);
    end_diagnostic(dp);
  } else {
    discard_more_info_list(&my_list);
  }  /* if */


10/5/15  [EDGcpfe/16009]
Microsoft compatibility: spurious error on in-class specialization

A problem with Microsoft nonreal base class processing could result in
a spurious error when attempting to match an in-class specialization
with the template declaration that it specializes.  This would occur
when the nonreal base class was being instantiated with a template
argument that involves a template parameter of a member class
template that is itself defined in another class template (e.g., when
A is instantiated with U2 in the example below).  Now fixed.

  template <typename T> struct A {
    template<typename U> void f(U& stream) {  }
    template<> void f<>(int& stream) { }
  };
  template <class T2> struct B {
    template <class U2> struct C : A<U2> { };
  };


10/5/15  [EDGcpfe/16552]
Missing error on uses of "operator auto" in C++14 mode

The front end failed to issue an error on some invalid uses of "operator auto"
in C++14 mode.  This could lead to internal errors later on or invalid IL.
For example:

  struct S {
    decltype(operator auto) f();  // Previously not diagnosed; now an error.
  };

This is now fixed.


10/5/15  [EDGcpfe/16463]
C++-generating back end: parentheses for expression in pack expansion

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end failed to parenthesize an expression that is a pack
expansion, causing the ellipsis to apply to the last subexpression instead
of to the entire expression.  This is now fixed.  For example:

  template<int I> int g() {
    return I;
  }
  template<int... Is> int f() {
    return g<(Is-0)...>();  // Previously generated as g<Is-0...>()
  }


10/2/15  [EDGcpfe/16546]
Add a new routine to cache type_info type

A new routine, make_ptr_to_const_typeinfo_type, has been added to reduce the
number of times make_user_typeinfo_type is invoked.  There should be no
discernible effect (affects only lowering configurations that do exception
handling).


10/2/15  [EDGcpfe/16548]
Missing diagnostic for "auto" as a function parameter return type

In C++14 mode, the front end previously failed to diagnose an "auto" return
type when it appears on a parameter declaration.  For example:

  void g(auto p()) {}  // Previously erroneously accepted.

This is now fixed.


10/1/15  [EDGcpfe/16531]
Attributes on a using-directive

A spurious error had been given for attributes that preceded a using-directive.
That restriction has been lifted except in GNU emulation modes.  Attributes are
still disallowed for using-declarations (in all modes).  For example (with
--c++11):

  namespace A {}
  [[ ]] using namespace A;  // Now allowed (except in GNU emulation mode).


10/1/15  [EDGcpfe/16543]
Microsoft compatibility: long long promotion

As a result of the changes for EDGcpfe/16219, "long long" promotion had
been enabled when microsoft_version >= 1900, but it appears that was
overzealous and has now been disabled.  For example (in 32-bit configurations
with --microsoft_version 1900):

  void g(int) {}
  void g(unsigned long int) {}
  void f() {
    g(2147483647);    // Okay -- calls g(int).
    g(2147483648L);   // Had been ambiguous because of "long long" promotion.
  }


10/1/15  [EDGcpfe/16534]
More flexibility in configuring entry_number field in an_il_entry_prefix

Each allocated IL entry has an associated an_il_entry_prefix structure and
one of the fields in this structure is entry_number.  The entry_number field
contains a unique number for the entry, and, particularly in cases where
there are many long mangled names, this field can overflow (resulting in
an ec_program_too_large catastrophic error).  To keep the prefix size small,
the entry_number field has always been a bit field whose size was engineered
to be the maximum possible while still allowing for four or five (depending
on configuration) additional one-bit flags.  A new configuration macro,
ENTRY_NUMBER_SHARES_BITS_IN_PREFIX, has been added to control whether or
not entry_number is a bit field.  When TRUE (the default), the effective size
of the entry_number field is reduced by the number of bit fields in the prefix;
when FALSE, the full size of the TYPE_FOR_PREFIX_ENTRY_NUMBER type is
available to store entry numbers (at a cost of a larger prefix due to padding).
These changes only affect configurations where ALTERNATE_IL_FILE_FORMAT is
TRUE.  Alternatively, a larger type can be used for
TYPE_FOR_PREFIX_ENTRY_NUMBER.


9/29/15  [EDGcpfe/16499]
Range-based "for" statements and user-defined iterator conversions

The processing of range-based "for" statements produces internal iterators to
which the "!=" operator is applied.  Previously, that application failed to
consider a match with the built-in "!=" via a user-defined conversion, leading
to spurious errors.  For example:

  struct I {
    void operator++();
    int& operator*();
    operator bool();  // User-defined conversion operator enables
  };                  // comparisons.
  struct C {
    friend I begin(C*);
    friend I end(C*);
  };
  void g(C c) {
    for (int i : &c) {  // Previously triggered a spurious error; now okay.
    }
  }

This is now fixed.


9/29/15  [EDGcpfe/16526]
Positions of rescanned call-like built-in operations

When rescanning a call-like built-in operation (like the type traits helper
__is_empty), the front end failed to restore the originally-recorded position
of that operation and its operands in the IL for the rescanned expression.
That is now fixed.


9/29/15  [EDGcpfe/16494]
Incorrect type of integer literals in C++11 mode preprocessor expressions

In C++03, integer literals in preprocessor expressions were treated as
having the long or unsigned long type.  The C++11 Standard changed that
specification to use intmax_t/uintmax_t.  The front end has now been
updated to implement this behavior.  For example, with --c++11 on a host
with 32-bit long and 64-bit intmax_t:

  bool correct_type =
  #if 0xffffffff + 1  // == 0 in 32-bit arithmetic
    true;             // Now correctly selected in C++11 mode
  #else
    false;            // Previously incorrectly selected in C++11 mode
  #endif


9/27/15  [EDGcpfe/16493]
Dialect differences for universal-character-names in identifiers

The front end previously used the table from Annex D of the C99 Standard in
all modes when determining whether a universal-character-name (UCN) is
acceptable in an identifier.  This table, however, differs from the
corresponding tables in the C++03, C++11, C++14, and C11 Standards in a
number of particulars.  The front end has now been changed so that the
handling of UCNs in identifiers correctly reflects the language dialect in
effect.  For example:

  int \u00b8;     // Previously incorrectly rejected in C++11 and C11 modes
  int \u00aa;     // Previously incorrectly accepted in C++03 mode
  int \U00010000; // Previously incorrectly rejected in c++11 and C11 modes


9/25/15  [EDGcpfe/16538]
Spurious errors on nonreal template arguments with constexpr conversions

The front end did not always correctly deal with template arguments of a
template-dependent class type that, when instantiated, could convert to the
needed nontype template parameter type through a constexpr conversion.  This
resulted in spurious errors.  For example, in C++11 mode:

  template<bool> struct X {};
  template<class T> struct B {
    constexpr operator bool() const { return true; }
  };
  template<typename T> void g(T) {
    X<B<T>()> x;  // Previously triggered spurious errors about B<T>() not
  }               // being compatible with bool and not being a constant.

This is now fixed.


9/25/15  [EDGcpfe/16536]
Avoid multiple manglings of IA-64 ABI constructor alternate entry points

A change has been made to reduce the number of times a mangled name is
generated for constructors and destructors in the IA-64 ABI.  Previously,
mangled names for alternate entry points for constructor and destructors
were generated by generating a mangled name for the primary routine and
modifying that name as appropriate, but then discarding the mangled name for
the primary routine.  A change has been made to retain the mangled name for
the primary routine (so it isn't regenerated later).  A change has also
been made to remove the setting of error_position during mangling.


9/24/15  [EDGcpfe/16432]
Abort on braced mem-initializer for aggregate class with destructor

In C++11 mode with exceptions disabled, the front end could abort with an
internal error in lower_dynamic_init when lowering a braced mem-initializer
for an aggregate class with a destructor.  For example:

  struct X { ~X(); };
  struct Y {
    X x;
    Y(): x{} {}  // Lowering of the mem-initializer could previously
  };             // trigger an internal error.

This is now fixed.


9/24/15  [EDGcpfe/16535]
GNU C-mode abort on use of ambiguous parameter

In GNU C mode, referring to a duplicate parameter name in a non-evaluated
context could result in an abort in make_param_ref_operand (due to a runaway
pointer).  For example:

  void g(x, x) {        // Error: duplicate parameter name.
    int r = sizeof(x);  // Usually triggered an abort.
  }

This is now fixed.


9/23/15  [EDGcpfe/16533]
Segfault in get_substitution_pairs_for_template_class

A segfault had occurred in cases where a template parameter is used as
an argument to an attribute (or attribute-like entity) in a member of
an explicit specialization.  Now fixed.  For example (with --c++11):

  template<typename> struct A;
  template<> struct A<void> {
    template<int N> struct alignas(N) B {};
  };
  A<void>::B<1> a;


9/20/15  [EDGcpfe/16522]
C++-generating back end: performance issue with complex template usage

In C++-generating back end configurations, the change in 4.10.1 for
EDGcpfe/16018 introduced a severe performance penalty for some translation
units involving very complex template usage.  This has now been addressed
by caching the results of access checks instead of repetitively performing
them.  The performance characteristics of the C++-generating back end after
this change are comparable to, or slightly better than, those of version
4.10.


9/20/15  [EDGcpfe/16525]
Template keyword in non-template context in C++11 mode

The template keyword used for syntactic disambiguation is allowed in
non-template contexts in C++11.  This has been allowed in qualified
names since version 3.9, but was incorrectly diagnosed in class member
accesses in C++11 mode.  Now fixed.

  struct A {
    template <typename T> static void f() {}
  };
  int main() {
    A a;
    A* ap = &a;
    a.template f<int>();
    ap->template f<int>();
  }


9/17/15  [EDGcpfe/16297]
Incorrect behavior and/or abort in substitution of default template argument

If a program substituted a pack into the template argument list of a
non-variadic template, default arguments of the non-variadic template
were sometimes not substituted properly.  This could result in incorrect
types, or an abort (in get_template_arg_by_list_pos) starting with version
4.10.  Now fixed.  Prior to 4.10 certain cases like this could get an
internal error in equiv_template_arg_lists.

  template <typename T> struct A {};
  template <typename V, typename T = int, typename S = A<T> > class B {};
  template <typename... A> void f(int n, B<A...>);
  int main() {
    B<int> b;
    f<int>(1, b);
  }


9/17/15  [EDGcpfe/16211]
Spurious "pack ... not expanded" error in disambiguation

A spurious "pack was referenced but not expanded" error could be issued on
a variadic constructor template.  Now fixed.

  template <int I> struct A {};
  template <int... J> struct B {
    template<int... K> B(const A<K>&... ak) { }
  };


9/17/15  [EDGcpfe/10609,EDGcpfe/16520]
Relaxed rules for scope of explicit specialization (core issue 374)

In C++11, an explicit specialization is no longer required to be first
declared in the namespace of the template.  Now it also may be declared in
an enclosing namespace.  This is core issue 374, resolved by paper N3064.
We now implement the new rules in C++11 and newer modes.

  namespace N {
    template<typename T> struct S { };
  }
  // Formerly resulted in an error in all strict modes.  Now only an error
  // in strict C++98/03 modes.
  template<> struct N::S<int> { };


9/16/15  [EDGcpfe/16516]
Explicit template arguments in call, with implicit variadic arguments

Overload resolution sometimes spuriously failed for a call to a function
template with variadic template parameters where a nonvariadic template
argument is specified explicitly, while the variadic arguments must be
deduced.  For example:

  struct S {
    template<template<int> class F, typename ... Ts >
      static auto f(int, Ts && ... ps) -> decltype (F<42>::run((Ts)(ps) ...));
  };
  template<int> struct X {
    static int run(int);
  };
  void g(int p) {
    S::f<X>(p, 0);  // Previously failed to resolve the call; now okay.
  }

This is now fixed.


9/16/15  [EDGcpfe/16517]
C++-generating back end: GNU __extension__ keyword

While cleaning up a few issues with integer values being used as booleans,
a pre-existing bug involving the marked_as_gnu_extension field in
a_source_correspondence was found and fixed (in C++-generating back end
configurations).  For example (with --gcc):

  __extension__ typedef struct S {} s;


9/15/15  [EDGcpfe/16380]
Array decay in gcc-mode constant expressions

The GNU C compiler allows a constant expression to contain a conversion of
an lvalue designating an array of automatic storage duration to a pointer
to the array's first element if the context is a comparison or subtraction
whose operands both involve the same array variable.  The front end
previously rejected such conversions as non-constant but has now been
adjusted to permit them when emulating gcc.  For example, with --gcc:

  void f() {
    int a[5];
    sizeof(struct { int f : a == a; });  // Previously an error
  }

In addition, this change fixes a bug introduced in version 4.10.1 by the
change for EDGcpfe/10791,EDGcpfe/15927.  In configurations in which the IL
is written to a file, the front end could abort with a failed assertion (in
EXPENSIVE_CHECKING configurations) or behave unpredictably if the width
expression of a bit-field refers to a local variable.  This is now fixed,
which required an IL CHANGE: in such cases, the new flag
bit_size_constant_expr_in_local_expr_node_ref in the a_field entry will be
set to TRUE and the backing expression for the entry to which the
bit_size_constant field points will be represented by an
a_local_expr_node_ref entry (see the entry of 4/28/06).  For example, again
with --gcc:

  void f() {
    const int i = 5;
    sizeof(struct { int f : i + 2; });  // Previously might abort
  }


9/15/15  [EDGcpfe/16514]
Braced function call arguments and partial ordering of function templates

The front end previously sometimes ignored the partial ordering of function
templates in calls involving braced function call arguments.  This could lead
to spurious ambiguity errors.  For example:

  template<class T> int f(T const&) = delete;
  template<class T> int f(T const(&)[2]);
  int r = f<int[2][2]>({ {1}, {2} });
    // Previously this call was treated as ambiguous.  Now the second
    // function template is selected because it is more specialized than
    // the first.

This is now fixed.


9/15/15  [EDGcpfe/16513]
__is_constructible and pointer-to-integer conversions

The front end previously produced a "true" value for an invocation of the type
traits helper __is_constructible like "__is_constructible(int*, int)"
(erroneously suggesting an integer is constructible from a pointer).  This is
now fixed.


9/14/15  [EDGcpfe/16399]
Spurious error on friend declaration that refers to inline namespace member

A friend declaration that refers to an inline namespace member failed to
find the member, resulting in a spurious error.  Now fixed.

  namespace N {
    inline namespace {
      template <int> void f();
    }
  }
  class B {
    template <int> friend void N::f();
  };


9/13/15  [EDGcpfe/16461]
Constant folding of cast to void in left operand of comma operator

The front end previously incorrectly rejected as non-constant a comma
expression whose left operand is an explicit cast to void, even when the
operands could otherwise have been folded to constants.  This is now fixed.
For example, with --c++11:

  struct X {
    constexpr X(const char *s, int l): str(s), len(l) { }
    constexpr const char &f() const {
      return ((void)0), str[len-1];  // Previously incorrectly non-constant
    }
  private:
    const char *str;
    int len;
  };
  void g() {
    constexpr X x("ABC", 2);
    static_assert(x.f() == 'B', "error");  // Previously a spurious error
  }


9/13/15  [EDGcpfe/16507]
C- and C++-generating back end: representation of extended characters in
literals

Depending on the locale settings, the output of the C- and C++-generating
back ends could represent extended characters (those with values larger
than 0x7f) as single bytes within character and string literals.  If the
generated code is later compiled assuming a different code page (e.g., as
UTF-8), those characters would be interpreted differently, perhaps as the
start of an invalid multibyte sequence.  This has now been addressed by
using octal escapes for all extended characters when generating compilable
code.  For example, using the C++-generating back end in a locale in which
'\xf6' is a valid printable character:

  template <char> struct C;
  C<(char)-10> *p;  // Template argument was previously generated using an
                    // extended character with value 0xf6, now "C<'\366'>"


9/11/15  [EDGcpfe/16510]
Expression nodes and positions (IL CHANGE)

Expression nodes (type an_expr_node) now include a "position" field in all
configurations.  For nodes representing operators, it replaces the field
"operator_position" (which was only defined when EXTRA_SOURCE_POSITIONS_IN_IL
is TRUE), but for other kinds of nodes that correspond to a construct in the
source code, it now records the starting position of that construct.

A number of changes have been made to mitigate the potential growth in memory
consumption:

  (1) the variant field variant.typeid_info.is_cli_typeid is now recorded
      as a nonvariant bit field is_cli_typeid;
  (2) the variant field variant.lowered_eh.variant.internal_try (and its two
      fields try_expr and catch_expr) have been replaced by a single pointer
      variant.lowered_eh.variant.try_and_catch_expr, which points to a list
      of two nodes (the two nodes that were previously recorded in separate
      fields); and
  (3) the fields "position" (formerly "operator_position") and "expr_range"
      have been moved to follow the top-level flags; and
  (4) the name_reference field has been moved to the variants for enk_field,
      enk_variable, enk_routine, and enk_constant, and some existing fields
      in the enk_routine variant are now recorded in name_reference instead;
      new macros (node_constant, node_variable, etc.) are now used to access
      entities referred to by the affected nodes.

This is a significant IL CHANGE.


9/4/15   [EDGcpfe/16496]
Abort on incomplete member type in Microsoft-mode class template

In Microsoft mode, class templates can have members of incomplete type (the
type has to be complete when a real instantiation is done).  In modes with
microsoft_version >= 1900, however, such class templates would trigger an
internal error in select_overloaded_copy_constructor ("NULL constructor").
For example:

  template<class T> struct A {
    A<int> a;  // Incomplete member type triggered an abort in some
  };           // Microsoft modes.

This is now fixed.


9/4/15   [EDGcpfe/16498]
Abort in Clang mode on context-sensitive __is_... keyword

The Clang-mode changes for EDGcpfe/14876,EDGcpfe/14934 (see entry of 3/21/14)
could lead to an internal error (in scan_unary_type_trait_helper) when a
context-sensitive __is_... keyword did not correspond to a unary trait (e.g.,
when it corresponds to a binary trait).  For example:

  struct __is_base_of {};
    // __is_base_of is now a context-sensitive keyword.
  bool r = __is_base_of(int, int);
    // Previously triggered an internal error; now okay.

This is now fixed.


9/4/15   [EDGcpfe/16417]
Representation of indirect captures

When an inner lambda nested in an outer lambda captures a variable from a scope
enclosing the outer lambda, the outer lambda also captures that variable.  For
example:

  int g(int n) {
    return [=]{  // Outer lambda captures n for inner lambda.
             return [=]{ return n; };  // Inner lambda captures n indirectly.
           }()();

The inner lambda's a_lambda_capture entry therefore points to the field of the
outer lambda holding the captured variable value (via its field
capture_info.source_closure_field).  Previously, the inner capture entry could
not safely point to the original variable entry because of memory region
constraints.  When the IL was written out to a file, the variable pointer
(the captured.variable field) was therefore cleared (but that clearing didn't
happen if the IL was not written to a file).

With the changes for EDGcpfe/16292,EDGcpfe/16359 (see entry of 8/24/15) the
problematic memory region constraint has been lifted.  A change has now been
made not to clear the captured.variable field, regardless of the configuration.


9/3/15   [EDGcpfe/16450]
Friend declaration incorrectly found through using directive

In modes where friend name injection is disabled (e.g., strict mode, recent
GNU modes, etc.) the front end sometimes incorrectly found a function only
declared in a friend declaration.  This could lead to spurious diagnostics or
incorrect overload resolution.  For example:

  namespace N {
    struct B {};
    struct D: B {};
    void operator+(B&, int);   // (1)
  }
  struct S {
    S(int);
    friend void operator+(N::D&, S const&);  // (2)
  };
  class C {};
  void operator+(N::B&, C const&);
  using namespace N;
  void g(D d) {
    d+1;  // (3)
  }

In strict mode, the addition operator at line (3) should normally only find
the declaration of operator+ at line (1), but the front end previously also
found the (normally invisible) declaration at line (2) because of the presence
of the using directive.  That in turn triggered a spurious ambiguity
diagnostic.  That is now fixed (in modes with friend injection enabled, the
example still leads to an ambiguity, of course).


9/3/15   [EDGcpfe/16174]
Unevaluated references to local variables in generic lambdas

The front end sometimes issued a spurious warning or error when a generic
lambda references a local variable without evaluating that variable.  For
example, in strict C++14 mode:

  void g(int i) {
    [&](auto x) -> decltype(i) { return 0; };
      // Previously, the reference to "i" elicited an error in
      // strict C++14 mode.  Now this is silently accepted.
  }

This is now fixed.


9/2/15   [EDGcpfe/16449]
Assertion failure in end_potential_pack_expansion_context

A function template with multiple attribute arguments in an attribute list
had caused an assertion failure in end_potential_pack_expansion_context.
Now fixed.  For example (with --gnu_version=40800):

  template <class T> void f() __attribute__((abi_tag("foo", "bar")));


9/2/15   [EDGcpfe/16472]
Issue with "constexpr" implying "const" on nonstatic member functions

The changes for EDGcpfe/16092 removed the implicit "const" declaration for
"constexpr" nonstatic member functions in C++14 mode, but that change was
incomplete, resulting in a spurious redeclaration error for cases like this:

  struct A {
    constexpr int f() const;
    constexpr int f();
  };

Now fixed.


9/1/15   [EDGcpfe/16477]
Microsoft C++/CLI compatibility: Incorrect floating-point literal
representation when importing metadata

The representation of floating-point literals when imported from an assembly
was incorrect and has now been fixed.  In the example below, when an assembly
with the following class is imported, X::f had been represented internally by
the binary value "0x.0p-3f" and is now represented by "0x1.000000p-3":

  public ref class X {
    public:
      literal float f = .125f;
  };


9/1/15   [EDGcpfe/16492]
__is_constructible and access SFINAE

The type traits helper __is_constructible sometimes produced an incorrect
result if a candidate conversion constructor was eliminated because it is
inaccessible (under access SFINAE rules).  For example:

  struct S {
    explicit S(int);
  private:
    S(char);
  };
  static_assert(__is_constructible(S, int) , "Unexpected!");
    // Previously failed because of the elimination of the candidate
    // S::S(char) because it is not accessible.

This is now fixed.


9/1/15   [EDGcpfe/16490]
GNU-mode assertion failure when binding a reference in a template

In GNU C++ modes, the front end sometimes aborted with an internal error in
wrap_up_constant_full_expression when handling a reference binding to a
temporary with a nontrivial destructor during the prototype instantiation of
a template (the problem only occurred when PROTOTYPE_INSTANTIATIONS_IN_IL is
TRUE).  For example:

  struct S { ~S(); };
  template<typename> void g() {
    auto &&r = S();  // Previously triggered an internal error in GNU mode
  }                  // in some configurations.
  template void g<void>();

This is now fixed.

As part of this change, the front end was also modified to be more lenient
with certain constant-expression requirements during prototype instantiations.
For example, the following template is now accepted in strict C++11 mode:

  template<typename T> void f() {
    T x = 0;
    constexpr T &&r = T{ x+1 };  // Previously triggered an error because
  }                              // x is not a constant.

Actual instantiations still trigger an error, of course.  (This new behavior
matches that of other C++11 compilers.)


9/1/15   [EDGcpfe/16470]
Assertion failure in constant_for_base_class

Due to the changes for EDGcpfe/16203, the following example (with --c++11) had
caused an assertion failure in constant_for_base_class.  Now fixed.

  struct A {
    virtual void f();
  };
  struct B {
    virtual void f();
  };
  struct C: A, B {};
  struct D: C {
    virtual void f();
  };
  D d;


8/31/15  [EDGcpfe/16487]
Microsoft compatibility: Calls to member functions in class templates

The changes for Clang compatibility made for EDGcpfe/16428 (see the entry of
8/12/15) are now also enabled for Microsoft mode.  These changes apply
primarily to the prototype instantiations of templates, which are usually not
performed in Microsoft mode.  However, prototype instantiations are performed
in Microsoft mode for variadic templates, and some source analysis applications
enable prototype instantiations more broadly in Microsoft mode.  This change
improves Microsoft compatibility under such circumstances.  For example:

  void g(int, int);
  template<typename ... Ts> struct S {
    void g(int p) {
      g(p, p);  // Previously an error during prototype instantiation
    }           // because S<Ts...>::g is found rather than ::g(int, int).
  };            // Now accepted during the prototype instantiation.
                // (An error is still issued during a real instantiation.
                // That matches the Microsoft compiler.)


8/28/15  [EDGcpfe/16464]
__is_pod

Previously, a user-declared constructor always made a class type non-POD (the
C++03 definition of POD requires a class type to be an aggregate type) and the
__is_pod type trait helper reflected that.  Now, in C++11 mode, the C++11
definition is used for __is_pod, and that definition does allow some
constructors.  For example:

  struct POD {
    POD() = default;
    POD(int);
  };
  static_assert(__is_pod(POD), "Unexpected!");
       // Now accepted in C++11 modes that support the __is_pod helper.

The is_POD flag in a_class_symbol_supplement has been renamed to is_cpp03_POD.
Except for the renaming, it is not affected by this change (it reflects the
C++03 definition in all modes); this ensures that the ABI implementations are
unaffected.  A new function is_pod_class is now available to test whether a
class is a POD in the current language mode (i.e., in C++11 mode it tests for
the C++11 definition of POD, and in other modes for the C++03 definition of
POD).


8/27/15  [EDGcpfe/16460]
Wrong disambiguation with C++11-style functional-notation cast with braces

In C++11 mode, the front end sometimes incorrectly disambiguated a
parenthesized initializer containing a function-notation cast with braces.
For example:

  template<typename T> void g() {
    T x(typename T::X{});
  }

The front end incorrectly parsed the declaration of x as the declaration of a
function, which produced a spurious syntax error.  This is now fixed.


8/27/15  [EDGcpfe/16462]
__is_convertible_to with a "void" destination type

The front end previously produced a "true" result for __is_convertible_to
whenever the destination type is a (possibly qualified) "void" type.  Now,
that is the case only if the source type is also a "void" type.  For example:

  static_assert(!__is_convertible_to(int, void), "Unexpected!");
     // Previously the assertion failed; now it is accepted.


8/27/15  [EDGcpfe/16459,EDGcpfe/16474]
__is_constructible with array or reference types

The front end did not always produce a correct result for the type traits
helper __is_constructible when the destination type is an array type or a
reference type.  For example:

  static_assert(__is_constructible(char[3]), "Unexpected!");
    // Previously an error because all array types produced "false".
    // Now accepted.
  struct X {};
  struct Y { Y(X&&); };
  static_assert(!__is_constructible(Y&, X), "Unexpected!");
    // Previously an error because the front end ignored the fact that an
    // lvalue reference to non-const cannot be initialized with a temporary
    // (and therefore the __is_constructible invocation produced a true
    // value).  Now accepted.

This is now fixed.


8/27/15  [EDGcpfe/16475]
Internal error on use of C++11 features in some C++03 modes

In some GNU, Clang, and Microsoft modes that do not enable C++11 mode (but that
do accept "defaulted" functions), the front end sometimes aborted with an
internal error in resolve_indeterminate_exception_specification (class_decl.c).
For example, the following caused an internal error when using the option
--microsoft_version=1800:

  struct S  {
    S() = default;
    constexpr S(S const&);
  };
  constexpr S::S(S const&) = default;  // Previously triggered an internal
                                       // error in some modes.

This is now fixed.


8/25/15  [EDGcpfe/16465]
Clang compatibility: Core issue 429 only in C++11 mode

When emulating clang, the changes for core issue 429 (see Changes entry for
EDGcpfe/7107) now apply only in C++11 emulation mode.  This example no longer
gives an error with --clang:

  typedef __EDG_SIZE_TYPE__ size_t;
  struct X {
    void *operator new(size_t, size_t);
    void operator delete(void*, size_t);
  };
  X *x = new(2) X;


8/24/15  [EDGcpfe/16292,EDGcpfe/16359]
Memory region issues with lambdas  (IL CHANGE)

Because local-scope lambdas were placed in memory regions separate from their
enclosing function, certain uses of entities from the enclosing function were
either incorrectly disallowed (as in the case of the non-capturing use of
"i" in the example below), or could result in invalid cross-region memory
references.

The front end now places lambdas and instantiations of generic lambdas in
the same memory region as the enclosing function.  This may require changes
to back ends, particularly if an IL file is being used.  Formerly, the
region_scope_table was used to take a region number (typically assoc_scope
in the routine entry) and get the actual scope entry pointers.  The
assoc_scope field of a_routine has been replaced with a field named
memory_region, and a new field named function_def_number has been added.
function_def_number is now used in place of assoc_scope as an index
into a new IL header field named function_def_table.  The function_def_table
entry contains the scope pointer and also the memory region number.
The memory region number here is used to get the memory region number when
you have only a function_def_number and not the associated routine pointer.

When an IL file is being used, the former mechanism for handling a
function was typically:

  read_memory_region(n);
  /* generate code */
  free_memory_region(n);

This will still work, but is less efficient than:

  if (mem_region_table[n] == NULL) read_memory_region(n);
  /* generate code */
  if (routine->is_top_level_in_mem_region) free_memory_region(n);

If you have a routine entry and want to get its memory region or scope,
mem_region_for_routine(rout) and (the existing) scope_for_routine(rout)
should be used.   If you have a function definition number, the new macros
mem_region_for_function_def(n) and scope_for_function_def(n) should be
used.

The region_scope_entry table still exists but now points to a list of
function scopes in the region instead of to a single scope.

This example resulted in a spurious "enclosing ... variable cannot be
referenced" error.  Now fixed.

  int main() {
    int i = 1;
    auto l = [](auto j) { decltype(i+j) k{}; return k; };
    return l(1);
  }

In addition, if a lambda made use of a constexpr array from an enclosing
function, the program could fail in a number of ways because of the memory
region issue.  In addition to the memory region issue, such examples
were not handled properly in IL lowering.  A change has been made in
lowering to make a copy of the constexpr array in the lambda call operator
in such cases.

  void f(int (*fp)(int), int i) { }
  int main() {
    constexpr int arr[] { 1,2,3,4,5,6 };
    auto l = [](int i) { return arr[i]; };
    f(l, 2);
  }

As part of this change, the diagnosis of a local class containing a VLA type
dimensioned with a variable from an enclosing function scope has been slightly
improved.  For example:

  int main() {
    int n = 10;
    struct S {
      int x;
      A() : x(sizeof(typeof(int[n]))) {}
        // Previously a warning; now an error.
    };
  }


8/22/15  [EDGcpfe/16279]
C++-generating back end, clang compatibility: elaborated-type-specifiers for
members of inline namespaces

The clang C++ compiler has a bug that results in spurious errors when a
qualified name appears in an elaborated-type-specifier used as a type
declaration ("forward declaration cannot have a nested name specifier").
The C++-generating back end previously used a qualified name in such
constructs when declaring a member of an inline namespace in a containing
scope, even though the name was presumably unqualified in the original
source.  This has now been addressed by suppressing the qualifier for an
inline namespace in these constructs when clang_is_generated_code_target is
TRUE.  For example, with --clang --c++11:

  inline namespace N { template <class T> struct A; }
  template <typename> class B;
  template <typename T> struct A<B<T>>; // Previously generated as N::A<B<T>>


8/22/15  [EDGcpfe/7422,EDGcpfe/11153,EDGcpfe/16433]
Not-a-Number builtin processing

A few changes have been made to the way GNU-style builtin function processing
is handled.  The first change is that __builtin_huge_val, __builtin_huge_valf,
__builtin_huge_vall, __builtin_nan, __builtin_nanf, __builtin_nanl,
__builtin_nans, __builtin_nansf, and __builtin_nansl are now available in
Microsoft emulation mode when microsoft_mode >= 1900 or in C++/CLI mode.

To support this change, support for GNU-style builtin functions is now
controlled by a new configuration macro, BUILTIN_FUNCTIONS_ENABLED, which
defaults to TRUE when either GNU_EXTENSIONS_ALLOWED or
MICROSOFT_EXTENSIONS_ALLOWED is TRUE.

Additionally, calls to __builtin_nan* that specify a non-empty string are
now folded (though at most 32 bits of the specified mantissa value are
represented in the resulting NaN).

A change has also been made in C-generating and C++-generating back ends to
more accurately reflect the exact NaN representation that was in the source
(by using the backing expression, if available, to retrieve the original
string used in the __builtin_nan* call).  Note that backing expressions are
not available in configurations that do lowering and have
RECORD_BACKING_EXPRS_WITH_IL_LOWERING set to FALSE.

Finally, the sign bit of a NaN constant is now zero, indicating a positive
NaN which aligns better with some existing compilers (the previous value
depended on the NaN generated by the host compiler when computing 0.0f/0.0f,
and frequently resulted in a negative NaN constant).

For example (with --microsoft_version 1900):

  int main() {
    constexpr float fi = __builtin_huge_valf();
    constexpr float fq = __builtin_nanf("0");
    constexpr float fs = __builtin_nansf("1");
    constexpr double di = __builtin_huge_val();
    constexpr double dq = __builtin_nan("0");
    constexpr double ds = __builtin_nans("1");
  }


8/21/15  [EDGcpfe/16448]
Prototype instantiation of coroutines

The preliminary support for coroutines (see entry of 5/13/15 for EDGcpfe/15431)
did not handle prototype instantiations of coroutine templates.  That is now
fixed.


8/21/15  [EDGcpfe/16452]
GNU, Microsoft compatibility: alignas

A declaration like

  double x[2] alignas(32);  // (1)

is nonstandard, because in that position the alignas attribute appertains to
the array type rather than the array variable declaration.  Correct
alternatives are:

  double y alignas(32) [2];  // (2)
  alignas(32) double z[2];

In Microsoft and GNU C++11 modes, however, the front now does accept the form
on line (1) (silently treating as the form on line (2)).


8/20/15  [EDGcpfe/16170]
GNU C++ compatibility: Redefining defaulted special members

In GNU C++11 modes with gnu_version < 40700, the front end now accepts (with a
warning) an out-of-class definition of a special member that was defined with
"= default" in its parent class definition (provided the member was not
previously used).  The defaulted definition is discarded in such cases.  For
example:

  struct S { S() = default; };
  S::S() {}  // Now accepted in some GCC modes.

(GCC 4.4.x, 4.5.x, and 4.6.x behave slightly differently in this regard.  The
front end emulates the most permissive behavior only.)


8/20/15  [EDGcpfe/16446]
constexpr reference to dependent value

The front end previously incorrectly handled references bound to dependent
values in constant contexts within template definitions, treating them as
nonconstant.  This is now fixed.  For example:

  template<typename T> constexpr const T& f(const T& a) {
    return a;
  }
  template<int N> struct S {
    static constexpr int x = N;
    static constexpr int z = f(x);   // Previously elicited a spurious
                                     // "must have a constant value" error
  };


8/20/15  [EDGcpfe/16294]
Spurious error on "auto" static data member with braced initializer

In C++11 mode, the front end issued a spurious error on an "auto" static data
member with a braced initializer.  For example:

  #include <initializer_list>
  struct X {
    constexpr static auto L = { 2 };  // Previously elicited an error.
  };

This is now fixed.


8/20/15  [EDGcpfe/16416]
Abort in lowering on nested init-captures

In C++14 mode (and other modes that support init-capture in lambdas) the front
end sometimes aborted with an internal error (in make_init_entity_node) when
lowering the (invalid) IL for an init-capture whose initializer contains a
lambda with its own init-capture.  The problematic cases involved captured
values requiring nontrivial destruction.  For example:

  struct S { ~S() {} };
  void g() {
    S s;
    [x = [x = s]{ return x; }()]{ return x; }();  // Previously triggered an
  }                                               // abort during lowering.

This is now fixed.


8/19/15  [EDGcpfe/16182]
C-generating back end: Microsoft-mode trailing zero-width bit-field

In C-generating back end configurations when msvc_is_generated_code_target
is TRUE, if the last field in a class or structure is a zero-length
bit-field, the front end could abort with a failed assertion (in
dump_struct_union_definition).  This is now fixed.  For example, with
--microsoft:

  struct S {
    int x;
    int :0;
    int y;
    int :0;  // Previously caused an abort, now okay
  } s;


8/19/15  [EDGcpfe/16444]
Microsoft compatibility: Binding an rvalue to a reference to volatile const

In Microsoft mode, the front end previously allowed binding an rvalue to a
reference to a volatile const type if either microsoft_version < 1600 (see also
the entry of 5/24/02) or the underlying type is not a class type and
microsoft_version < 1700.  However, it appears current Microsoft compilers
still permit the cases where the underlying type is not a class type: The
restriction that microsoft_version < 1700 has therefore been removed.  For
example:

  int g(int const volatile&);
  int i();
  int r = g(i());  // Now accepted in all Microsoft C++ modes
                   // (previously only when microsoft_version < 1700).


8/18/15  [EDGcpfe/16441]
C++14 aggregate initialization of a union with a NSDMI

In C++14 mode, a union with a nonstatic data member initializer (NSDMI) can be
an aggregate.  When such a union is initialized with empty braces, the front
end previously issued an error in cases like the following:

  union U {
    float f;
    int i[2] = {1, 2};
  } u{};  // Previously an error in C++14 mode; now accepted.

The front end now accepts such cases, and the member with the NSDMI is the one
initialized.  (Such cases are the object of the standardization committee's
Core issue 1622, and the front end's new behavior aligns with our expectation
of how that issue will be resolved.)


8/18/15  [EDGcpfe/16280]
C++-generating back end: call to static member function template from another
member function template

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL and
gcc_or_clang_is_generated_code_target are both TRUE, the C++-generating
back end incorrectly used the "template" keyword prefix when putting out a
call to a static member function template from another member function
template of the same class.  This is now fixed.  For example, with --g++:

  struct A {
    template <typename> void m_fn1() {
      m_fn2<1>();   // Previously generated as "template m_fn2"
    }
    template <unsigned> static A m_fn2();
  };


8/17/15  [EDGcpfe/16350]
Dependent constexpr conditional expression

The front end previously incorrectly rejected as nonconstant a conditional
expression appearing in a constexpr function template definition when its
controlling expression is dependent.  This is now fixed.  For example:

  template<class T> constexpr T f(T a, T b) {
    return (b < a) ? b : a;            // Previously treated as nonconstant
  }

  template<int X, int Y> struct S {
    static constexpr int x = X;
    static constexpr int y = Y;
    static constexpr int z = f(x, y);  // Previously a spurious error
  };


8/15/15  [EDGcpfe/16407]
Abort on increment/decrement of volatile property

In Microsoft mode, an increment or decrement operation applied to a property
could result in an internal error (in cast_operand_full, "operand is not a
prvalue") if the "get" accessor of the property produces a volatile lvalue.
For example:

  struct A {
    volatile long m;
    __declspec(property(get=p_get, put=p_put)) volatile long p;
    volatile long& p_get() { return m; }
    volatile long& p_put(volatile long const &x) { m = x; return m; };
    void f() { p++; }  // Previously triggered an internal error.
  };

This is now fixed.


8/15/15  [EDGcpfe/16430]
Tweak to code for lambdas with calling conventions

The type a_calling_convention is normally one byte large.  Some code for
lambdas inadvertently relied on this, making it more difficult to change that
size if needed (as some of our customers do).  That code has been changed to
be insensitive to sizeof(a_calling_convention).


8/13/15  [EDGcpfe/16429]
Variadic macros inadvertently disabled in C++11 strict mode

The combination of --c++11 and --strict (or -A) command-line options had
inadvertently disabled the variadic macro feature.  Now fixed.


8/12/15  [EDGcpfe/16412,EDGcpfe/16428]
GCC and Clang compatibility: "this" and template dependent calls

The expression "this" in a class template is always type-dependent, but
expressions involving "this" are not necessarily type-dependent.  Consider
the following example:

  struct S {} *gp;
  template<typename = void> class C {
    S *mp;
  public:
    void f1(int n) { g(mp, n*s()); }  // Accepted by GCC and Clang.
    void f2(int n) { g(gp, n*s()); }  // Accepted by GCC and Clang.
    void f3(int n) { g(mp, n*42); }   // Accepted by Clang.
    void f4(int n) { g(gp, n*42); }   // Not accepted by Clang or GCC.
    int s() const;
  };
  void g(S*, int);
  int main() {
    C<> c;
    c.f1(1);
    c.f2(2);
    c.f3(3);
    c.f4(4);
  }

According to the standard, every call to g (in f1, f2, f3, and f4) is
nondependent and therefore ill-formed because no g is declared at the point
of the call.  However, in Clang and GCC modes, some of these calls are now
treated as template-dependent (and therefore accepted).  Specifically, in
GCC and Clang mode, a call to "f" equivalent to a call to "this->f" is now
treated as type-dependent in a template-dependent context, and in Clang mode
an explicit or implicit use of "this" in the argument of a call makes that
call dependent, too.


8/12/15  [EDGcpfe/16425]
List initializers and user-defined conversions

Previously, the C++ standard required ignoring user-defined conversions in some
cases where a non-aggregate class is initialized with a single brace enclosed
element.  The front end no longer implements that rule because it has been
eliminated by the changes for the standards committee's resolution of Core
issue 1467.  For example:

  struct A {
    A() = default;
    A(A const&) {}
  };
  struct B {
    operator A() const { return A(); }
  };
  void g(B b) {
    A a{ b };  // Previously an error because the user-defined conversion
  }            // was ignored.  Now accepted.


8/11/15  [EDGcpfe/16419]
Abort or invalid IL on use of captured dependent-type const variable in lambda

In modes that perform prototype instantiations, the front end sometimes
incorrectly handled a lambda in a template containing a reference to a variable
(to be captured) with a const type.  When ALTERNATE_IL_FILE_FORMAT and
IL_SHOULD_BE_WRITTEN_TO_FILE are set to TRUE this led to an abort (in
ptr_remap_function, "address not in any mem block"); in other configurations
invalid IL was produced for the prototype instantiation.  For example, with
"--c++11 --parse_templates":

  template<typename T> struct S {
    void f() {
      auto const p = new S<T>;
      [=]{ p->m; };  // Previously triggered an abort in some modes.
    }
  };

This is now fixed.


8/11/15  [EDGcpfe/16421]
Internal error on init-capture following capture of "this"

In C++14 mode (and other modes that support init-capture in lambdas) the front
end sometimes aborted with an internal error when an init-capture follows the
capture of "this" (the abort was the result of invoking expect_error in
find_lambda_capture).  For example:

  struct S {
    int m;
    int f() {
      return [this, c = m]() { return c; }();
    }
  };

This is now fixed.


8/11/15  [EDGcpfe/16422]
Spurious error on alias using an elaborated type specifier with template-id

In C++11 mode, examples like the following:

  template<typename> struct X;
  struct S {
    using A = struct X<int>;
  };

previously triggered a spurious error saying that a specialization cannot
appear at that point.  This is now fixed.


8/11/15  [EDGcpfe/12971]
Microsoft compatibility: Flexible array members in unions (IL CHANGE)

Ordinarily, a flexible array member in a class type prevents that class type
from being used for a field that is not the last field of a class or struct
type, or as the underlying element type of an array.  However, those
restrictions are now lifted in Microsoft mode if the class type is a union
type and the flexible member is not the last member of the union.  For example:

  union U {
    char c[];
    int  i;
  };
  U x[2];  // Now accepted in Microsoft mode.

As a part of this change, the flag contains_flexible_array_member is no longer
set to TRUE for such union types.  This is a small IL CHANGE.


8/11/15  [EDGcpfe/15830]
GNU compatibility: Type of address label difference

In GNU modes, the front end accepts constructs to take the address of labels
and to compute their "difference".  In some GNU modes (e.g., GNU C mode)
address label differences are sometimes represented using a_constant entries
(ck_label_difference).  Previously, such constants always had a type
corresponding to ptrdiff_t, even when the label addresses had been explicitly
cast to a different integral type.  For example:

  void g(int x) {
    if (x < ((unsigned long)&&L2 - (unsigned long)&&L1)) { }
  L1:
  L2:
    ;
  }

Here the constant representing "(unsigned long)&&L2 - (unsigned long)&&L1"
previously had a signed type (the underlying type of ptrdiff_t); now it has
type unsigned long.


8/11/15  [EDGcpfe/16426,EDGcpfe/16593]
Microsoft compatibility: U-literal support when microsoft_version >= 1900

U-literal support (including char16_t and char32_t keywords) is now enabled
when microsoft_version >= 1900 in both C and C++ modes.


8/10/15  [EDGcpfe/15514,EDGcpfe/16406]
GNU/Clang compatibility: Trivial designators into non-POD class types

In GNU and Clang modes, the front end now accepts "trivial designators" for
fields in non-POD class types, where a "trivial designator" designates the
field that would be initialized if the designator were omitted.  For example:

  struct N { N(); };
  struct S {
    N n;
    int i;
  } s = { .n = N(), 42 };  // Now accepted in GNU and Clang modes.


8/2/15   [EDGcpfe/16404]
Internal error with #line directive naming the physical file

The changes for EDGcpfe/15925 (part of version 4.10.1) could cause an
internal error "optimum_file_start_position: missing file index entry" to
occur when a diagnostic is issued following a GNU-style #line directive
that names the actual source file in which it appears.  This is now fixed.
For example, with --g++ and assuming the file is named "test.cpp":

  # 1 "test.cpp"
  void foo(void) {
    char *test = "test";  // "never referenced" warning caused internal error
  }


7/31/15  [EDGcpfe/16362]
GNU C++ compatibility: Class definitions in __builtin_offsetof

In GNU C++ mode (but not in Clang C++ mode) the front end now accepts class
type definitions in __builtin_offsetof constructs.  For example:

  void g() {
    long a = (long)__builtin_offsetof(struct { char x; int y; }, y);
  }                                         // Now accepted in GNU C++ mode.


7/31/15  [EDGcpfe/16367]
Microsoft-mode abort on cast of data member to its const-qualified type

The changes for EDGcpfe/11654 allow the front end to treat the cast of a data
member access to the type of that data member but with modified type qualifiers
(e.g., an added "const") as an lvalue (it normally should be an rvalue).  The
changes for EDGcpfe/14628 introduced a global variable to control such
"lvalue cast" behavior explicitly, but they failed to condition this particular
case on that variable.  As a consequence, compiling such cases with
"--microsoft_bugs --no_preserve_lvalues_with_same_type_casts" triggered an
inconsistency that could lead to an internal error.  For example:

  struct S {
    S() : x() { static_cast<const int>(x); }
    int x;
  } s;

This case previously aborted in function lvalue_cast ("lvalue cast in
unexpected mode").  That is now fixed.


7/30/15  [EDGcpfe/16363]
Microsoft C compatibility: "Whole-struct" aggregate initialization

In Microsoft C mode, the front end now permits the initialization of a whole
struct subobject in an aggregate initializer.  For example:

  int main() {
    struct S { int i; } s = { 1 }, as[] = { 1, s };
  }     // Previously an error in Microsoft C mode; now okay.

(Such constructs were already accepted in C99 modes and in GNU C modes.)


7/30/15  [EDGcpfe/16400]
Microsoft/Clang/GNU compatibility: constexpr and template instantiations

In C++11 mode, the front end issues an error for an ordinary constexpr function
that returns a call to a constexpr template function whose return expression
can never be a constant expression.  For example:

  bool n() { return 0; }  // Not constexpr
  template<typename T>
  constexpr bool t() {
    return n();  // Never a constant expression, but no error reported
  }              // because t is a template.
  constexpr bool c() {
    return t<int>();  // Normally an error but now accepted in some modes.
  }

In Clang, GNU, and Microsoft modes, however, such invalid C++11 constexpr
functions are now accepted (an error is issued if they are called in a constant
expression context).


7/30/15  [EDGcpfe/16401]
Trivial copyability incorrectly determined in presence of deleted constructor

The front end incorrectly treated a class with a deleted non-copy constructor
as being "not trivially copyable" in some cases.  For example:

  struct S {
    S(int) = delete;
  };
  static_assert(__is_trivially_copyable(S), "Unexpected");
      // Previously failed; now okay.

This is now fixed.


7/30/15  [EDGcpfe/16394]
Defaulted functions sometimes not emitted out-of-line

In configurations with INSTANTIATE_EXTERN_INLINE set to TRUE the front end
maintains a list of inline functions that must be potentially "instantiated".
However, it failed to record defaulted special members on that list, which
caused an out-of-line copy never to be emitted.  That in turn could lead to
to linker failures (in somewhat unusual circumstances).  This is now fixed.


7/28/15  [EDGcpfe/16200]
Microsoft compatibility: recursive macro invocation

According to the C and C++ Standards, a macro name appearing in its own
expansion is not considered for further expansion.  The Microsoft
preprocessor, however, relaxes this rule, expanding such nested invocations
as long as they do not produce expanded text that is similar to that of the
earlier invocation, which could lead to unbounded recursion.  The front end
previously followed the standard rules for suppressing recursive macro
invocations, but it has now been changed in Microsoft mode to use the more
relaxed approach.  For example, with --microsoft:

  #define invoke(M, arg) M arg
  #define X(arg) invoke(Y, (arg))
  #define Y(arg) arg
  #define Z invoke(X, (0))
  int i = Z;   // Previously expanded Z to "invoke(Y, (0))", now to "0"


7/28/15  [EDGcpfe/16392]
Microsoft and Clang compatibility: noexcept and constexpr call folding

In Microsoft and Clang C++11 modes, the front no longer folds calls to
constexpr functions in the operand of the noexcept operator.  For example:

  constexpr int A() { return 42; }
  static_assert(!noexcept(A()), "Standard");  // Accepted in Microsoft and
                                              // Clang modes.


7/28/15  [EDGcpfe/16396,EDGcpfe/16398]
Incorrect handling of sizeof... operator during template declaration

The front end sometimes did not correctly record a sizeof...(<pack>) operation
while parsing a template, causing spurious errors when the template was later
instantiated (or used in a different template).  For example:

  typedef __EDG_SIZE_TYPE__ size_t;
  template <typename T, T val> struct C {
    static T const value = val;
  };
  template<typename... Ts> using A = C<size_t, sizeof...(Ts)>;
  template<typename... Ts> int g(Ts... args) {
    using X = A<Ts...>;
    static_assert(X::value == 6, "Unexpected size");
      // This assertion previously failed during prototype instantiation.
  }

This is now fixed.


7/25/15  [EDGcpfe/16011]
Clang compatibility: Predefined macros

A change has been made to define the following macros in clang emulation mode:
__clang__, __clang_major__, __clang_minor__, __clang_patchlevel__, and
__clang_version__.  Note that clang also defines values for __GNUC__,
__GNUC_MINOR__, __GNUC_PATCHLEVEL__, __GNUG__, and __VERSION__ but those are
static (and based on a GNU version of 4.2.1) and aren't defined by the front
end; instead, if needed, they should be defined in a predefined_macros.txt file
(the output of make_predef_macro_table with the --clang option will
automatically provide those definitions).

See also a related change to make_predef_macro_table that provides a mechanism
to capture other predefined macros from the clang compiler for use in a
predefined_macros.txt file.  In conjunction with this change, the front end
now accepts four new types of predefined macros in that file: "clang",
"clang_c", "clang_cpp", and "gnu_or_clang".


7/25/15  [EDGcpfe/16391]
Initial value for constexpr_implies_const

The global variable constexpr_implies_const controls whether "const" is implied
for "constexpr" non-static member functions (see the Changes entry for
EDGcpfe/16092).  That variable had not been properly initialized, resulting in
incorrect behavior when using Microsoft emulation mode.  The following example
is now accepted with --microsoft_version=1900:

  struct A {
    constexpr int f() { return 1; }
  };
  int (A::*p)() const = &A::f;


7/24/15  [EDGcpfe/15843]
Microsoft compatibility: token concatenation across macro invocation boundary

The Microsoft preprocessor allows concatenation of the last token of a
macro expansion with the token following the macro invocation to produce
a single token.  The front end previously preserved the token break between
a macro expansion and the following text but has now been changed to allow
the concatenation in Microsoft mode.  For example, with --microsoft:

  #define AB 1,2
  #define C(x) x
  #define D(x) x
  #define E D(D(A) ## B)
  int a[2] = C({E});   // Previously produced "{A B}", now "{1,2}"


7/24/15  [EDGcpfe/16368]
C++-generating back end: Abort on braced cast to array of unspecified bound

When attempting to render a functional-style cast with braced notation where
the type cast to is a typedef for an array of unspecified bound, the C++-
generating back end aborted with an internal error in function tag_kind
("bad type kind").  For example:

  void g() {
    using A = double[];
    A{1.0, 2.0};  // Previously triggered an internal error.
  }

This is now fixed.


7/23/15  [EDGcpfe/16375]
GNU/Microsoft compatibility: Inheriting constructors via typedef names

In GNU and Microsoft modes, the form
  using A::X;
is now treated as an inheriting constructor declaration if A is a typedef for
a template-dependent class type whose name is X.  (Ordinarily, for such
template-dependent names, the requirement is that the names on both sides of
the '::' token be the same.)  For example:

  template<int> struct X;
  template<> struct X<0> {};
  template<int N> struct X: X<N-1> {
    using A = X<N-1>;
    using A::X;  // Now treated as an inheriting constructor declaration
  };             // in GNU and Microsoft modes.

Note that in this particular case other modes issue an error because the
declaration "using A::X;" introduces a name that is identical to that of the
surrounding class.


7/23/15  [EDGcpfe/16384]
Microsoft compatibility: C++/CX internal static data members in ref classes

The front end previously issued a spurious error about a static data member
being public in a C++/CX ref class when the static data member was declared
with "internal" access.  For example:

  namespace NS {
    public ref class A sealed {
    internal:
      static int x;  // Previously triggered a spurious error.
    };
  }

This is now fixed.


7/23/15  [EDGcpfe/16382]
Spurious error on template-dependent expression in noexcept-specifier

The front end previously issued spurious errors on some template-dependent
expressions in noexcept-specifiers, claiming those expressions are not
constant.  For example:

  template<typename> struct C {
    constexpr operator bool() const { return true;}
  };
  template<typename T> void g() noexcept(C<T>()) {}
                                  // Previously triggered a spurious error.

This is now fixed.


7/22/15  [EDGcpfe/16143]
Microsoft-mode copy-initialization of class types

In cases where a class object is initialized through copy-initialization in a
context that permits the elision of the copy constructor invocation, Microsoft
compilers treat the initialization as a direct-initialization instead.  That,
for example, allows the use of conversion functions that would not have been
considered in the standard case.  The changes for EDGcpfe/15352 (version 4.10)
incorrectly disabled this behavior when microsoft_version >= 1900.  It has now
been restored in all Microsoft bugs C++ modes.  For example:

  struct A { operator int*(); };
  struct B { B(int*); };
  void g(A a) {
    B b = a;  // Previously an error with microsoft_version >= 1900.
  }           // Now accepted (i.e., treated as a direct initialization).


7/22/15  [EDGcpfe/16371]
Use of current instantiation in function declarator within a return type

Consider the following code:

  template<typename T> struct S {
    typedef int I;
    template<typename U> S<U(I)> f();
  };
  template<typename T> template<typename U>
    S<U(typename S<T>::I)> S<T>::f() {  // Previously triggered a spurious
      return 42;                        // error.
    }

S<T> should be treated as the "current instantiation" in the definition of
S<T>::f and S<T>::I can therefore be assumed not to be specialized to something
other than what appeared in the definition of S<T>.  However, the front failed
to determine that in cases like these where the name S<T>::I appears within a
function parameter list.  That triggered a spurious declaration incompatibility
error.  This is now fixed.


7/22/15  [EDGcpfe/16374]
Spurious warning on GNU __builtin_offset applied to class template instance

The front end sometimes issued a spurious warning about a class template
instance not being a POD type on GNU __builtin_offset operators applied to
the class template instance.  For example:

  template<typename> struct S { int x; };
  int r = (int)__builtin_offsetof(S<int>, x);  // Previously triggered a
                                               // spurious error.

This is now fixed.


7/22/15  [EDGcpfe/16379]
Microsoft compatibility: Accept "inline" specifier in C mode

When using Microsoft emulation and microsoft_version >= 1900, the "inline"
specifier is now allowed.  For example (with --microsoft_version 1900 --c):

  inline void x() {}


7/21/15  [EDGcpfe/15482]
Unbounded recursion on some Microsoft-mode SFINAE cases

Consider the following code:

  template<typename T, typename U>
  constexpr T max(T t, U u) {
    return t > u ? t : u;
  }
  template<typename T, typename ...Ts>
  constexpr auto max(T t, Ts ...ts) -> decltype(max(t, max(ts...))) {
    return max(t, max(ts...));
  }
  template<int... N> struct S {
    char x[max(N...)];
  };
  S<1, 2, 3> s;

Previously, this code led to unbounded recursion in Microsoft C++ modes that
support C++11-style SFINAE.  This was due to "max(t, max(ts...))" finding both
the first "max" function template and the second "max" template during template
argument deduction for the latter.  (In standard C++, only declarations
preceding the substituted expression are visible in the substitution.)  Now,
the function for which deduction is done is ignored in this context, thereby
resolving the circular dependence.

(Note that the example above is likely not working as intended.  For example,
S<1, 2, 3, 4> will not successfully instantiate.)


7/20/15  [EDGcpfe/16351]
Incorrect IL for folded constructor call that partially initializes a field

In C++11 mode, the front end sometimes failed to record the flag
"is_partially_initialized" in aggregate constants and dynamic initializer
entries resulting from a folded constructor call.  This could cause code
generators (like the C-generating back end) to fail to fully initialize the
corresponding aggregate object.  For example:

  struct S {
    int ia[4];
    constexpr S(int p) : ia{p} {}  // Partial initialization of S::ia.
  };
  struct N { N(); };
  void g() {
    N n;      // (This declaration forces the C-generating back end to
              // break down the initialization of x below into individual
              // statements.)
    S x(42);  // Previously, the dynamic initializer entry for x did not have
  }           // its "is_partially_initialized" flag set to TRUE.  The code
              // emitted by the C-generating back end failed to fully
              // initialize x as a consequence of this.

This is now fixed.


7/20/15  [EDGcpfe/16287]
C++-generating back end: assertion failure with parenthesized initializer

The C++-generating back end aborted with a failed assertion in
gen_paren_or_brace_dynamic_init in pre-C++11 modes when a variable is
direct-initialized with an explicit temporary created via a call to the
default constructor of a class.  This is now fixed.  For example, with
--c++03:

  struct X {
    X();
  };
  void f() {
    X a((X()));   // Previously aborted, now okay
  }


7/18/15  [EDGcpfe/16277]
C++-generating back end, clang compatibility: naming the current instantiation

The clang C++ compiler has a bug that sometimes causes it to issue a
spurious error for a name qualifier consisting of the name of the class
template being defined followed by its parameters as arguments.  The
C++-generating back end in configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE previously produced this form
unconditionally.  This has now been addressed; when
clang_is_generated_code_target is TRUE, the C++-generating back end will
suppress the template argument list in a qualifier naming the current
instantiation.  For example:

  namespace N {
    template <class T> class A {
      template <class M> void foo() {
        M a;
        a.A::foo();   // Previously generated as a.N::A<T>::foo(), provoking
                      // the clang bug
      }
    };
  }


7/17/15  [EDGcpfe/16289]
C++-generating back end: incorrect and missing typedef substitutions

As noted in the entry for EDGcpfe/11015, the C++-generating back end
attempts to substitute an accessible equivalent typedef when an inaccessible
type specifier would otherwise be generated from the IL.  In some complex
code examples, this processing could result in replacing the typedef name
being declared in a typedef declaration with a type reference, resulting in
incorrect and uncompilable code.  This is now fixed.

In addition, the changes for EDGcpfe/16101 (included in version 4.10.1)
introduced a bug that caused some necessary replacements no longer to be
done.  This also is now fixed.  For example:

  template<typename T> struct A { };
  class B {
    struct priv { };
    A<priv> ap;
    typedef priv PRIV;
  public:
    typedef PRIV PUB;
  };
  A<B::PUB> a;   // Generated as A<B::priv> in 4.10.1, now as A<B::PUB> again


7/16/15  [EDGcpfe/16372]
Assertion failure in lower_dynamic_init

In some configurations, an assertion failure (in lower_dynamic_init) had
occurred when exceptions are disabled and an initializer list element with a
destructor is used to initialize a non-aggregate class type.  For example (with
--no_exceptions --c++11):

  struct B {
    B() {}
    ~B() {}
  };
  struct A {
    A(B b) : b_{b} {}
    B b_;
  };


7/16/15  [EDGcpfe/16377]
Spurious error on template-dependent GNU asm output operands

The front end previously issued a spurious error on certain template-dependent
GNU asm output operands indicating they were not modifiable.  For example:

  template <typename T> void g() {
    typename T::X v;
    asm ("" : "+m" (v.x));  // Previously triggered a spurious error during
  };                        // prototype instantiation.

This is now fixed.


7/15/15  [EDGcpfe/16330]
Friendship not recorded in source sequence entry in some cases with attributes

In configurations with RECORD_UNRECOGNIZED_ATTRIBUTES set to TRUE, an unknown
attribute applied to a friend class declaration caused the secondary source
sequence entry for that friend declaration to have its friend_decl flag remain
FALSE.  That in turn caused the C++-generating back end not to render correct
code.  For example:

  class C {
    friend __attribute((Unknown)) class X;
    int i;
  };
  
Previously the friend declaration above was rendered as just "class X;".
This is now fixed.  The attributes are now also rendered (albeit after the
class specifier, which is an equivalent construct).


7/15/15  [EDGcpfe/16191]
Explicit calls to conversion function templates

The front end previously issued a spurious error when attempting to explicitly
call a conversion function template from another template (the error was issued
during the prototype instantiation of that other template).  For example:

  struct S {
    template<typename T> operator T();
    template<typename T> T g(T) {
      return operator T();  // Previously triggered a spurious error during
    }                       // the prototype instantiation of S::g(T).
  };

That is now fixed.


7/15/15  [EDGcpfe/16278]
Deduction from braced initializer list arguments

The front end can now deduce a parameter of a nested std::initializer_list type
from a corresponding multi-level braced initializer list.  For example:

  #include <initializer_list>
  template<typename T>
    void g(std::initializer_list<std::initializer_list<T>>) {}
  int main() {
    g({{1,2,3}, {4,5,6}});  // Now accepted, with T = int.
  }

Additionally, a parameter that is reference to an array type can also be
deduced from a braced initializer list.  For example:

  template<class T, int N> int f(T const (&)[N]);
  int r = f({7, 8});  // Now accepted, with T = int and N = 2.


7/13/15  [EDGcpfe/16317]
IL write-read difference abort on base class reference in template constructor

Under some circumstances an IL file consumer (like the C++-generating back end)
could abort with an "IL write-read difference" when attempting to load the IL
for a class template constructor with a mem-initializer that cannot be matched
to a specific base during prototype instantiation.  For example:

  template<typename> struct B {};
  template<typename T> struct D: public B<T> {
    D(): B<int>() {}  // The base class entry for B<int> in the prototype
  };                  // instantiation previously triggered an IL write-read
  D<int> m;           // error.

This is now fixed.


7/13/15  [EDGcpfe/16355]
GNU compatibility: Inheriting constructors from indirect base classes

GCC accepts using-declarations for inheriting constructors that name indirect
base classes, but does not appear to create usable constructors from such
constructs.  As an approximation, the front end now simply ignores these
constructs with a warning.  For example:

  struct B {};
  struct C: B { using B::B; };  // Okay.
  struct D: C { using B::B; };  // Normally an error, but now ignored in
                                // GNU C++11 mode (with a warning).
  D d;


7/12/15  [EDGcpfe/16369]
Member access expressions in constant expressions

In contexts requiring a constant expression, the front end in C++11 mode
incorrectly rejected member access expressions involving member enumerators
and static data members when the object expression is not an address
constant.  This is now fixed.  For example:

  struct X {
    enum Y { A };
  };
  void f(X::Y y) {
    X x;
    switch (y) {
      case x.A:   // Previously incorrectly rejected
        break;
    }
  }


7/12/15  [EDGcpfe/16361]
Creation of PCH file larger than 2 GB failed on 64-bit Windows

When the front end is built on a 64-bit Windows platform, the precompiled
header processing failed if a PCH file being created exceeded 2 GB.  Now
fixed.

7/10/15  [EDGcpfe/16312]
GNU/Clang compatibility: Current instantiation treated as template-dependent

While parsing class template members in their generic form, the enclosing class
is called the "current instantiation" in the C++ standard.  The types of
expressions referring to members of the current instantiation are not always
considered "template dependent".  Now, however, they are in Clang and GNU
modes.  For example:

  template<typename> struct S {
    int N;
    void f() {
      S s;
      g(s.N);  // Now accepted in GNU and Clang modes.
    }
  };

Here the type of s corresponds to the current instantiation, and therefore s.N
is known to be int and thus not dependent.  As a result, g in g(s.N) should be
looked up only when the template is first parsed, and since no g is visible
the case is in error (the front end issues an error in strict mode).  In GNU
and Clang modes, however, the front end now treats the type of s as an unknown
template-dependent type (and hence also the type of s.N), and so the code is
accepted assuming that looking up g will succeed if the template is eventually
instantiated with real arguments.


7/10/15  [EDGcpfe/16296]
Member using-declaration for member function template sometimes ignored

When a derived class overloads a member using-declaration that imports a member
function template with a member function template that differs only in its
qualifiers or its ref-qualifier, the front end previously erroneously dropped
the member function template imported from the base class.  This could result
in spurious errors.  For example:

  struct B {
    template<class T> void f(T) const {}
  };
  struct D: B {
    using B::f;
    D const *p;
    template<class T> void f(T) {  // Caused the removal of B::f from the D::f
                                   // overload set.
      p->f(42);  // Previously a spurious error because only the non-const
    }            // D::f was visible.  Now okay.
  };

This is now fixed.


7/9/15   [EDGcpfe/16349]
Abort on invalid "decltype(auto)" return type construct in C++14 mode

In C++14 mode, the front end sometimes aborted in get_template_arg_by_list_pos
(templates.c) after issuing an error on a malformed function declaration with
"decltype(auto)" in its return type (and no trailing return type).  For
example:

  decltype(auto)* g(int x) { return x; }  // Previously triggered an abort.

This is now fixed.


7/9/15   [EDGcpfe/16358]
Defaulted special members not always marked deleted when needed

A defaulted special member should be marked deleted under various circumstances
(typically when its generated definition would run into a problem).  However,
the front end failed to do so if it didn't also have to generate the
declaration of another special member.  That is now fixed.  For example:

  struct N { N(N const&) = delete; };
  struct S {
    N n;
    S();
    S(S const&);
    S(S&&) = default; // deleted because of n
    ~S();
    S& operator=(S const&);
  } s = S();  // Previously an error, now okay.

In this example, the move constructor was not marked as deleted and therefore
not ignored for the purpose of initializing the variable s.  During the
ensuing generation of the body of that move constructor, the front end issued
a spurious error because that body requires the use of the (deleted) copy
constructor of N.  Now the move constructor of S is no longer considered (the
copy constructor is used instead).


7/9/15   [EDGcpfe/16301]
Direct-initialization of a reference via an explicit user-defined conversion

The front end previously incorrectly ignored explicit user-defined conversion
functions when direct-initializing a reference.  For example:

  struct S { explicit operator float&(); } s;
  float &rf(s);  // Previously an error; now fixed.

This is now fixed.


7/9/15   [EDGcpfe/16015]
Spurious "too few arguments" on call of member of variadic class

A spurious "too few arguments" diagnostic could be issued on a call of
a member function of a variadic class template in which the member
function had a parameter pack that used a variadic parameter pack of the
enclosing class template.  Now fixed.

  template <typename... Xs> struct A {
    A() { f(); }
    void f(Xs... xs){}
  };


7/9/15   [EDGcpfe/16281]
Spurious error on friend template redeclaration with template default argument

Version 4.10 introduced a problem that could result in a spurious error
being issued on a friend function template declaration that redeclares
a template where the other (non-friend) declaration included a default
template argument.  Now fixed.

  template <typename T> struct A {
    template <typename U> friend void f(A<U>);
  };
  template <typename U = int> void f(A<U>) { }
  A<int> a;


7/8/15   [EDGcpfe/16247,EDGcpfe/16291]
Binding a reference to a function to a brace-enclosed overloaded function name

The front end previously issued an error when a brace-enclosed name of an
overloaded function is used to initialize a reference to a function.  For
example:

  bool f(bool);
  char f(char);
  bool (&rf)(bool) = { f };  // Previously an error; now okay.

Cases like these are now accepted (and handled as if the braces were omitted).


7/8/15   [EDGcpfe/16366]
GNU C++ compatibility: default template argument in class template member

Some versions of g++ allow the definition of a class template member
outside of its class to provide a default template argument (which is
ignored).  The front end now allows such usage in g++ mode when
gnu_version < 50100 (with a warning), and ignores the default argument.

  template <typename T> struct A { };
  template<typename T, typename U = A<T> > struct B {
    struct C;
  };
  template<typename T, typename U = A<T> > struct B<T,U>::C { };
  int main() {
    B<int> b;
  }


7/7/15   [EDGcpfe/16310]
Core issue 1512: Operations on pointers and pointers-to-members

The front end now implements the changes described in the C++ standards
committee's paper N3624 (resolving Core issue 1512).  This can affect the
common type used for comparisons and for the conditional ("?:") operator
when at least one of the operands is a pointer or pointer-to-member type.
For example:

  typedef int volatile AT1[3];
  typedef int const    AT2[3];
  typedef AT1 *const *volatile PPAT1;
  typedef AT2 *volatile *const PPAT2;
  void g(PPAT1 *p1, PPAT2 *p2) {
    int i1 = false;
    (void)(i1 ? p1 : p2);  // Now silently accepted in C++ modes.
  }

Previously, this triggered a warning or (in strict mode) an error because the
old standard rules did not consider p1 and p2 compatible in this context.
Now that code is silently accepted.


7/6/15   [EDGcpfe/16364]
C++-generating back end: comma operators in non-type template arguments

When generating a non-type template argument expression containing a comma
operator, the C++-generating back end failed to enclose the expression in
parentheses to prevent the comma from being interpreted as an argument
delimiter.  This is now fixed.  For example:

  template<typename> struct A { };
  template <bool... P>
  struct B : A<B<(P, true)...> > { };  // Previously generated as B<P,true...>


6/30/15  [EDGcpfe/16245,EDGcpfe/16288]
Reference binding vs. qualification adjustment

During overload resolution, any conversions needed to initialize a parameter
with the corresponding argument may need to be compared.  The standard
specifies a number of tie-breaking rules when comparing two conversions that
are of the same general form.  Among those rules, the following three should
be applied in order:

  (1) binding an rvalue reference to an rvalue argument is preferred over
      binding an lvalue reference (to a const type) to that rvalue argument.
  (2) if the conversions involve qualification conversions (i.e., adding
      const/volatile under pointers and pointers-to-members) and one such
      conversion is a subset of the other, the former is preferred.
  (3) when binding references that only differ in the const/volatile qualifiers
      under those references, the less-qualified reference is preferred.

The front end previously erroneously checked tie-breaking rule (3) before
rule (2).  That is now fixed.

In addition, GCC and Clang apply tie-breaking rule (1) after the two others
(i.e., they do not yet implement the resolution of Core issue 1374).  The
front end now emulates that behavior in corresponding modes.  For example
(from the Core issue 1374 write-up):

    typedef int *      *      *const *const T1;
    typedef int *const *const *const *const T2;
    void foo(T1 &);       // (1)
    void foo(T2 &&) { }   // (2)
    int main() {
       foo((int ****)0);  // Normally prefers (2), but now prefers
       return 0;          // (1) in GNU and Clang modes.
    }


6/30/15  [EDGcpfe/16356]
Standalone utility build issue on Windows

4.10.1 introduced a build issue for standalone utility programs on Windows
when USE_MMAP_FOR_MEMORY_REGIONS is TRUE.  There was an unresolved
reference to free_mapped_mem_blocks.  Now fixed.

6/29/15  [EDGcpfe/16343]
Noexcept on pointers to functions, etc.

The front end previously ignored noexcept specifiers on pointers to functions
and similar constructs; a warning was issued in such cases.  Now, the
exception specification is recorded as expected.


6/26/15  [EDGcpfe/16307]
Exception specifications on return types

Exception specifications are permitted on the return types of function
declarators (when the return type itself is, e.g., a pointer to function).
However, the front end previously did not accept such an exception
specification when the top-level declaration is that of a pointer-to-function
instead of a function.  Now it does.  For example:

  void (*f())() throw(int);      // Already accepted.
  void (*(*pf)())() throw(int);  // Previously triggered a spurious warning
                                 // or error.  Now silently accepted.


6/26/15  [EDGcpfe/16270]
C++17 compatibility: Add standard attributes to namespaces and enumerators

As outlined in N4266, standard attributes are now permitted on namespaces
and enumerators.  Only the "deprecated" attribute is currently supported in
these locations.  This feature is also enabled when microsoft_version >= 1900.
For example (with --c++17):

  namespace [[deprecated]] N {
    int x = 0;
  }
  enum E { y [[deprecated]] };
  int z = N::x + y;     // Generates warnings for uses of N and y.


6/26/15  [EDGcpfe/16348]
Add --c++17 command-line option

In preparation for the next version of the C++ standard, currently referred
to as C++17, the --c++17 command-line option has been added.  This option
currently has the same effect as --c++14.


6/25/15  [EDGcpfe/16332]
Microsoft C++/CLI compatibility: Value class constructors

In Microsoft C++/CLI mode, the front end now accepts value struct/class
constructors with a single parameter that is the class itself, if that value
class is loaded from metadata.  For example:

  value struct V {
    V(int);
    V(V);  // No longer an error if loaded from metadata.
  };

For standard C++ classes this is invalid because it implies unbounded recursion
for the copy process.  However, C++/CLI value classes are always copied
bitwise: The constructors are not considered, and so no unbounded recursion
occurs.  (Such constructors sometimes show up in metadata produced using other
programming languages, such as C#.)


-------------------------------------------------------------------------------
Version 4.10.1, June 23, 2015

6/19/15  [EDGcpfe/16331]
Multiply defined static data member when used as a constant

A change in C++11 allowed the use of certain static data members defined
outside of their class to be used in constant expressions.  This could
result in multiply defined symbols in certain configurations.  The C++11
behavior was first present in version 4.8.  The changes for EDGcpfe/16315
on 6/17/15 enable this behavior in all modes, which called attention to
this existing issue.  The potential multiple-definition error has now
been fixed.

  file: t1.c:
  template <class T> struct A {
    static const int i;
  };
  template <class T> const int A<T>::i = 1;
  void f(const int& t){}
  void g();
  int main() {
    int n[A<int>::i];
    f(A<int>::i);
    g();
  }

  file: t2.c:
  template <class T> struct A {
    static const int i;
  };
  template <class T> const int A<T>::i = 1;
  void f(const int& t);
  void g() {
    int n[A<int>::i];
    f(A<int>::i);
  }


6/18/15  [EDGcpfe/16319]
Abort in GNU mode on alias to replaced "for inlining only" function

In GNU modes, a function definition may be provided "for inlining purposes
only" and then displaced by a different declaration (see, e.g., the entry of
2/4/13 for EDGcpfe/13606).  Previously, when the original declaration of the
displaced function is given an "asm name", and that name is referred to by
a GNU "alias" attribute after the declaration is displaced, the front end
aborted while attempting to perform a string comparison operation on a null
pointer in compare_for_asm_name_map (attribute.c).  For example:

  extern int f() __asm__ ("X");;
  extern __inline int f() { return 0; }  // "For inlining purposes only".
  int f() { return 0; }                  // Displaces the previous definition.
  extern int g() __attribute__((alias("X")));  // Previously triggered an
                                               // abort.

This is now fixed.


6/18/15  [EDGcpfe/16329]
Performance improvements with deeply nested decltype constructs

In some cases involving many template instantiations leading to deeply nested
decltype representations, the front end performed exceptionally poorly when
testing whether a type is dependent or deprecated.  This is now fixed.


6/18/15  [EDGcpfe/16251]
GNU C++ compatibility: Type names followed by '::'

Ordinarily, if a user-declared type name T is followed by '::', T is assumed
to be a name-qualifier and an error is issued if T doesn't designate a class
type (or, in some modes, an enum type).  Now, in GNU C++ mode, however, if T
is not a valid type for the purposes of name qualification and the context is
not an expression context, the '::' is assumed to be a global qualifier of a
name that follows.  In the simple example:

  typedef int I;
  I ::x;

that means a warning is issued instead of an error because "I ::x;" is treated
like a declaration "I (::x);".  Similarly, the following:

  typedef int I;
  I g();
  struct S {
    friend I ::g();
  private:
    I i;
  };

is now also accepted in GNU C++ mode.


6/17/15  [EDGcpfe/16315]
Constant static data members

After reconsidering the intent of the resolution of Core issue 721, the changes
described in the entry of 6/20/13 for EDGcpfe/10300 have now been extended to
all C++ modes, including strict C++03 mode.  One exception remains: In
Microsoft bugs mode, a template static data member initialized outside its
enclosing class is never permitted in a constant expression (this matches the
behavior of the Microsoft compilers).


6/17/15  [EDGcpfe/16248]
Conversion of lvalue to rvalue when casting a volatile expression to void

In C++11 mode, the front end now converts to an rvalue (implying a "fetch"
operation) a volatile lvalue cast to void.  For example:

  volatile int x;
  void g() {
    (void)x;  // Fetches in C++11 (and C) mode, but not in C++03 mode.
  }

See also the Changes entry for EDGcpfe/11680, EDGcpfe/13645 of 3/8/13.


6/17/15  [EDGcpfe/16316]
Module id based on entity in a precompiled header file

Although uncommon, it is possible to have an externally-linked variable or
function definition in a header file and that header file may be included in a
precompiled header file.  In such cases the resulting module id (which is based
upon the first externally-linked variable or function) and names derived from
it, could differ depending on whether or not a precompiled header file was
used.  Now fixed.  For example (with --pch):

  A.h:
  ----
  int x = 5;    // Chosen as basis of module id in all cases now.

  B.cpp:
  ------
  #include "A.h"
  int y = 10;   // Had been chosen when using a previously created PCH.


6/17/15  [EDGcpfe/16219,EDGcpfe/15130]
Microsoft compatibility: additional features enabled in Microsoft mode

As Microsoft Visual Studio continues to implement C++11 and C++14 features,
these features are enabled in the front end when microsoft_version >= 1900.
The latest batch of features to be enabled includes "long long" types,
digit separators, C++11 attributes, as well as other smaller features.
Binary literals and digit separators are also enabled in Microsoft C mode
when microsoft_version >= 1900.

Additionally some features, which had been enabled when microsoft_version >=
1800, have now been enabled when microsoft_version >= 1700 to better match
the features enabled in later versions of Microsoft Visual Studio 2012.


6/12/15  [EDGcpfe/16309]
Parent pointers in statement entries

The front end now records a pointer to a "parent" statement in most
statement entries.  For example, the statements directly in a compound
statement point back to that compound statement.


6/12/15  [EDGcpfe/16231]
IA-64 ABI: mangling of template aliases

The IA-64 ABI specifies no mangling for template aliases (as their use is
transparent to mangling), nevertheless, a mangled name is produced by the
front end for template aliases (mirroring that of a class template).  In
such cases, in the IA-64 ABI, no substitution had been allocated for the
template alias itself, possibly resulting in surprising demangled names.
For example (with --c++11):

  template <class T, class U> struct A {};
  struct B {};
  template <class T> using C = T;
  template <class T> T f();
  void g() {
    f<C<A<B, B>>>();    // Alias was: _Z1CI1AI1BS0_EE (demangled: C<A<B, A>>)
                        // Alias now: _Z1CI1AI1BS1_EE (demangled: C<A<B, B>>)
  }

This change is conditional on ABI_COMPATIBILITY_VERSION >= 411 (though mangled
template alias names don't appear in external names, so there should be no
ABI breakage with this change).


6/12/15  [EDGcpfe/16314]
Use of TRUE and FALSE macros before basics.h is included

Due to a chicken-and-egg problem between basics.h and defines.h, the use of
the TRUE and FALSE macros may lead to unexpected behavior.  The TRUE and FALSE
macros are defined by basics.h, but basics.h includes defines.h (before the
macro definitions).  This leads to a sequence like this:

  // Only in defines.h:
  #define CONFIG_MACRO TRUE
  #if CONFIG_MACRO
    #error Never get here
  #else
    #error Always get here
  #endif

The uses of TRUE and FALSE in defines*.h have been replaced with 1 and 0
respectively and a note added at the top of these files.  The use of TRUE
and FALSE after basics.h has been included is unchanged.


6/11/15  [EDGcpfe/16308]
Spurious error on explicit instantiation of inline namespace member

A spurious error could be issued if a member of an inline namespace was
explicitly instantiated outside of the namespace containing the inline
namespace.  Now fixed.

  namespace N {
   inline namespace Inner {
     template <class T> void f(T&) {}
   }
   struct A {};
  }
  template void N::f(A&);


6/10/15  [EDGcpfe/16236]
Internal error in generic lambda instantiation

An internal error could occur (in update_template_param_symbol) during
the instantiation of a generic lambda declared in a member function
template.  Now fixed.

  template<int i> struct A {};
  template <typename F> inline void g(F f) {
    f(A<0>()); 
  }
  template <typename T> struct B {
    template <int N> static void h(A<N>) {
       g([] (auto i) { });
    }
  };
  int main() {
    B<int>::h(A<1>());
  }


6/9/15   [EDGcpfe/16255]
The "called" flag for constructors and destructors

Previously, the front end failed to mark constructors and destructors referred
to from a_dynamic_init entries as "called".  This is now done (by setting the
constructor's or destructor's "called" flag to TRUE), unless the associated
construct is not "potentially evaluated" (e.g., if it appears in a sizeof
operand).


6/9/15   [EDGcpfe/16295]
Microsoft compatibility: additional pre-defined macros

The predefined macros _CHAR_UNSIGNED, _M_CEE, and _MSC_BUILD are now
defined to appropriate values in Microsoft mode.


6/8/15   [EDGcpfe/16264]
Setting of is_specialized flag for member templates

The is_specialized flag was incorrectly being set to TRUE for member
templates of specialized member class templates when the member template
was defined outside of the class definition (e.g., for A<int>::B<U>::f in
the example below).  The incorrect setting was mostly benign, but could
result in incorrect mangled names for the routine entries created for the
prototype instantiations of such member templates when using the cfront name
mangling mechanism.  These names don't appear in names in generated code,
but might be used for some purposes in customer-written code.  Specifically,
the "__S" encoding for specializations was incorrectly being applied to the
"f" portion of the mangled name in the example below.

  template <typename T> struct A {
    template <typename U> struct B {
      template <typename V> void f(V);
   };
  };
  template<> template<typename U> struct A<int>::B {
    template <typename V> void f(V);
  };

  template <>
  template <typename U> template <typename V> void A<int>::B<U>::f(V) {}


6/8/15   [EDGcpfe/16163,EDGcpfe/16196]
Microsoft-mode abort on list initializer in function template return type

In Microsoft C++ modes, the front end sometimes aborted (dereferencing a null
pointer in expr_access_checking_should_be_done) during function template
argument deduction when a function template includes a list initializer in its
return type.  For example:

  struct A { A(); };
  template <class T> auto f() -> decltype(T(*new A[1]{}));
  void g() {
    f<A>();  // Previously triggered an abort.
  }

This is now fixed.


6/5/15   [EDGcpfe/16202]
Incorrect lookup in instantiation of generic lambda

The instantiation of a generic lambda of a function template could fail to
find the template arguments of the enclosing function template.  Now fixed.

  template <class T> inline auto f(T t) { return t(); }
  template <int I> inline void g() {
    // "I" not found in instantiation from f
    f([&](auto... args) { return I; });
  }
  int main() {
    g<2>();
  }


6/5/15   [EDGcpfe/16285]
NEW_CAN_BE_FOLDED_INTO_CTOR and constexpr constructors

The front end generated invalid IL when a new-expression invoked a constexpr
constructor: The folded constructor call drops the allocation.  This, e.g.,
triggered an internal error during lowering (in lower_new; see lower_init.c).
For example:

  struct L {
    L() {}
    constexpr L(L const&) {}
  };
  int main() {
    L x;
    L *p = new L(x);  // Previously triggered an internal error during
  }                   // IL lowering.

This is now fixed (by not folding constexpr calls in that particular
context).


6/5/15   [EDGcpfe/16282]
Spurious floating-point range errors

The front end relies on host library routines (i.e., sscanf, sprintf, strtod)
to do floating-point conversion from string to binary (and vice-versa).
For proper operation of the front end, these routines must treat the "."
character as the radix point.  Most implementations of these library
routines allow different representations based on the "locale" that is
in effect when they are called.  On all modern operating systems, the default
locale in effect when a program starts is the "C" locale, but if user
code modifies the locale, it can have an effect on these routines (e.g.,
setting the radix point to ",").  A change has been made to explicitly set
the LC_NUMERIC category to "C" using the setlocale library routine.


6/4/15   [EDGcpfe/16222]
C++-generating back end: Abort on Microsoft-mode default constexpr
initialization

In Microsoft mode, a constexpr variable declaration is permitted to have no
initializer even if its type is a class type with a trivial default
constructor.  For example:

   struct A {};
   struct B : A {};
   constexpr B b;  // Missing initializer for the const variable b.
                   // This is permitted in Microsoft mode, but previously
                   // caused a failure in the C++-generating back end.

However, the C++-generating back end previously aborted when trying to
reconstruct this case (with an internal error in gen_initializer_constant;
"ran out of fields").  That is now fixed.


6/4/15   [EDGcpfe/16209]
Abort on SFINAE through alias templates

The front end sometimes aborted with an internal error in get_expr_rescan_info
("missing default rescan info", in exprutil.c) when rescanning an expression
specified in an alias template (to check for SFINAE failures).  For example:

  template <class T> constexpr bool f() { return true; }
  template<bool b> struct B {};
  template<typename T> using BA = B< f<T>() >;
  template<typename U> B< f<BA<U>>() > g();
  decltype(g<int>) *pf;  // The substitution of g<int> previously triggered
                         // an internal error.

This is now fixed.


6/4/15   [EDGcpfe/16210]
Incorrect substitution of function templates with default template arguments

If a function template with default template arguments was called using
a partial explicit template argument list, a deduction failure or an
internal error (in copy_template_param_con) could occur.  Now fixed.
The example below resulted in a spurious deduction failure.

  template <bool> struct A { typedef int X; };
  template <class T, int i=1, typename A<(i==2)>::X=0>
                                            constexpr bool f() { return true; }
  template <class T1, typename A<(f<T1>())>::X=0>
                                   constexpr bool g(const T1&) { return true; }
  template <class T = decltype(g(4))> void h();


6/4/15   [EDGcpfe/16203]
Erroneous settings for __vptr fields in lowered code

As a result of the changes for EDGcpfe/8523, lowering became responsible
for inserting constants in aggregates to properly initialize __vptr fields
in certain constexpr constants.  Recent changes (EDGcpfe/16195) exposed
errors in the way these __vptr fields were initialized (which had resulted
in the fields being initialized to incorrect values).  The initialization
has been rewritten to share the same algorithm as is used when generating
executable code to initialize the fields.  For example (with --c++11):

  struct B {
    virtual void f() {}
  };
  struct D: B {
    int x;
    constexpr D(int): x(42) {}
  };
  D d{42};    // Had pointed to virtual table for B, not D.


6/3/15   [EDGcpfe/16040]
Default template arguments and template parameter packs

A change in version 4.10 could cause incorrect processing of a variadic
template that uses a template parameter pack as an argument to a template
that has default template arguments.  Now fixed.

  template<typename T, typename T2 = int > class A {};
  template <typename... Args> void f(A<Args>&... a);
  int main() {
    A<int> a, b;
    f(a, b);
  }


6/3/15   [EDGcpfe/14560,EDGcpfe/16225]
Non-constant return in prototype instantiations of constexpr function

A constexpr function template with a return statement that produces a non-
constant expression in all instantiations is invalid in C++11.  Although the
standard makes a diagnostic optional in such cases, the front end often does
manage to identify such errors.  Other compilers do not, however, and to
improve compatibility with such compilers the severity of the front end's
diagnostic has been lowered to a warning in such cases (except in strict
mode).  For example:

  template<typename> struct D {
    D();
    constexpr D m() const {
      return D();  // Previously this always triggered an error.  Now it
    }              // only elicits a warning in nonstrict C++11 modes.
  };


6/3/15   [EDGcpfe/16050]
Spurious SFINAE failure with function template parameter pack and partial
explicit template arguments

Consider the following example:

  double g(double);
  template<typename X, typename... Args>
    auto f(Args&& ...args) -> decltype(g(args...)) {
      return 42.0;
    }
  double z = f<void>(8.0);

This previously failed to compile because the combination of the explicit
(but incomplete) template argument list in the call "f<void>(8.0)" with a
leading function template parameter pack in the declaration of f resulted
in the call g(args...) in the return type of f to be always be treated as
g() due to a bug in the front end.  This is now fixed.


6/2/15   [EDGcpfe/16272]
__underlying_type and explicit enum base types

When an enum type specifies an explicit base type that itself has an underlying
integer type (e.g., bool), the type traits helper __underlying_type previously
produced the underlying type of the base type instead of the base type itself.
For example, with

  enum E: bool { no, yes };

the front end might have produced type char for "__underlying_type(E)" (if the
underlying representation of bool is char).  Now, the explicit base type is
produced instead.


6/2/15   [EDGcpfe/16261]
Generated copy/move constructors and constexpr

The front end previously never marked generated copy/move constructors as
constexpr.  That could result in spurious errors.  For example:

  struct X {
    constexpr X() {}
    constexpr X(X const&) {}
  };
  struct Y {
    X x;
    constexpr Y() {}
    constexpr Y(const X &p) : x(p) {}
  };
  struct Z {
    Y y;
    constexpr Z(Y p) : y(p) {}
  };

Previously, the generated copy constructor of Y was not considered "constexpr"
even though it meets the requirements for that property.  As a result, an
error was issued on the definition of the constexpr constructor for Z.  That
is now fixed: The generated copy constructor of Y is constexpr, and the
definition of the Z constructor is accepted.


6/2/15   [EDGcpfe/16218,EDGcpfe/16274]
Precompiled header files and COMPILE_MULTIPLE_SOURCE_FILES

The front end issued a command-line error if an attempt was made to use
precompiled headers in configurations with COMPILE_MULTIPLE_SOURCE_FILES
set to TRUE.  This limitation is only necessary for configurations that
have USE_FIXED_ADDRESS_FOR_MMAP set to FALSE.  The error is now only
issued in such configurations.  If you had already made a change to
disable that command-line error, there was a problem with the maintenance
of the memory allocation history information and reusable memory block
information that could prevent precompiled headers from being used
for source files after the first one in many cases.  This is now fixed.


6/1/15   [EDGcpfe/5907,EDGcpfe/7472]
Eliminate redundant assignments to __vptr field in IA-64 configuration

In cases where a class shares a virtual table with a base class, an assignment
had been generated to initialize the same __vptr field two times (with the
same value).  The second assignment is now suppressed.  Only affects IA-64 ABI
configurations that use lowering.  For example:

  struct B {
    virtual void f() {}
  };
  struct D : B { };
  D d;


5/27/15  [EDGcpfe/16253]
Precompiled headers change __func__/__FUNCTION__

The changes for EDGcpfe/10231 (see entry of 12/16/09) caused the front end to
produce for __func__ (or __FUNCTION__, in Microsoft mode) the mangled name of
the enclosing function if a prior declaration of that function was loaded from
a precompiled header (otherwise, the normal "unmangled" name is produced).
This is now fixed.


5/23/15  [EDGcpfe/14121,EDGcpfe/16076]
Definitions of entities involving local types

The front end sometimes issues a discretionary error if a function or static
data member lacks a definition while depending on a local type (because no
other translation unit could provide the definition).  However, this
diagnostic was issued even when the entity was only used in an unevaluated
context (where the definition is not required).  For example:

  template<class T> struct S {
    static T m;
    static const unsigned long s = sizeof(S<T>::m);
  };
  unsigned long g() {
    struct L {};
    return S<L>::s;
  }

Previously a discretionary error was issued because S<L>::m has no definition.
Now that error is no longer emitted because S<T>::m is only referenced in an
unevaluated context.


5/23/15  [EDGcpfe/16073]
Spurious warning on function object invocation in prototype instantiation

The warning added for EDGcpfe/15754 (see entry of 12/4/14) is now only emitted
for classes that are not instantiations of templates because the warning could
be spurious otherwise.  For example:

  template<class T> struct F { void operator()(); };
  template<class T> void g(F<int> &f) {
    f();  // Previously triggered a spurious warning in some modes.
  }


5/22/15  [EDGcpfe/14729]
__is_trivially_copyable  (IL CHANGE)

The type traits helper __is_trivially_copyable has been revised to produce
more correct results in somewhat unusual cases.  For example:

  struct DD { ~DD() = delete; };
  static_assert(__is_trivially_copyable(DD), "Unexpected");

Previously, a deleted destructor made a class type not trivially copyable
(i.e., the front end failed the static_assert above), but that doesn't match
the C++ standard.  Now this test case is accepted.

As part of this change, the class type supplement field "trivially_copyable"
has been removed.


5/22/15  [EDGcpfe/16220]
Unexpected function type diagnostic on use of template template parameter

An "unexpected function type" diagnostic resulting from a template
instantiation could occur when a template template parameter was used
in a function template declaration and a similar use was previously
used in a different template declaration.

  template <class ...Types> class M {};
  template <class ...Types> class N {};
  template <template <class ...> class ...Types> class A {};

  template <template <class ...> class ...Types>
  class B : A<Types...>, M<Types<>...> { };

  // Error goes away if this declaration is moved before the declaration of B
  template <template <class ...> class ...Types>
  void f(const A<Types...>&, const M<Types<>...>& = M<Types<>...>()) { }

  int main() {
    f(A<M>());
    f(A<M, N>());
  }


5/21/15  [EDGcpfe/15909]
Abort in Microsoft C++/CLI mode while loading a class delegate member

The front end previously aborted in Microsoft C++/CLI mode with an internal
error (in decl_spec.c, function update_membership_of_class) while attempting
to load a class delegate member definition from an assembly.  This is now
fixed.


5/19/15  [EDGcpfe/16234]
Value of __cplusplus and std_version

The front end in --clang mode incorrectly set the value of the __cplusplus
predefined macro as if it were emulating the g++ compiler.  This is now
fixed.  For example, with --clang --c++14 --gnu_version=40900:

  long l = __cplusplus;  // Previously 201300L, now 201402L

In addition, the value of the std_version global variable (but not the
__cplusplus macro) corresponding to C++14 was originally set to 201400
(before the Standard was officially approved) and was never updated to the
final value of 201402.  This has also been corrected as part of this
change.  Finally, g++ version 5.1 now sets the correct value of __cplusplus
with -std=c++14, and the front end has been changed to do the same in
--c++14 mode with gnu_version >= 50100.


5/19/15  [EDGcpfe/16178]
Spurious failure on substituted array dimensions

In modes that enable constexpr (e.g., C++11 mode) the front end did not
correctly handle the substitution of template-dependent array dimensions
during function template deduction.  This could lead to spurious errors.
For example:

  struct A {
    typedef int B;
    static int const D = 42;
  };
  template <typename T> void f(typename T::B[T::D]);
  template <typename T> void g() {
    int x;
    f<T>(&x);
  }
  void h() { g<A>(); }

Previously, the call f<T>(&x), substituted with T = A, triggered an error
because the array dimension "[T::D]" was not considered constant.  This is
now fixed.


5/19/15  [EDGcpfe/16238]
Abort while scanning switch case statement

The front end sometimes aborted while scanning a switch case statement
(function case_label in statements.c) in relatively complex cases.  This
is now fixed.


5/19/15  [EDGcpfe/16071]
Microsoft compatibility: Elision of invalid copy constructor

The resolution of EDGcpfe/15352 (see entry of 8/11/14) included a change to
elide copy construction early in some Microsoft mode cases (when
microsoft_version < 1900).  That change has now been extended to cover some
additional cases.  For example:

  template<class T> struct A {
    A(): m(T()) {}  // Previously triggered an error.  Now okay.
    T m;
  };
  class B {
    B(B const &) {}
  public:
    B() {}
  };
  struct C: B {};
  A<C> a;

Previously, the instantiation of the default constructor of A<C> triggered an
error, because the copy constructor of C cannot be fully generated (because
it requires a call to the inaccessible copy constructor of B).  Now, the
copy constructor of C is elided early, which prevents the error.


5/18/15  [EDGcpfe/15742,EDGcpfe/16168,EDGcpfe/16235,EDGcpfe/16239]
Microsoft mode dependent nontype template arguments

The changes for EDGcpfe/15084 etc. (see the entry of 6/10/14) caused some
nontype template arguments to be processed incorrectly in Microsoft modes.
This caused template deduction to spuriously fail in various situations
(typically leading to spurious errors).

One such situation is a member function definition appearing outside its
parent class template definition with the return type or a parameter of the
member function involving a nontype template argument expressed using a
constant-valued variable.  For example:

  int const K = 0xfff;
  template<typename T> struct D {
    template<int> struct N { typedef int Type; };
    typename D::template N<K>::Type f();            // (d)
  };
  template<typename T> 
  typename D<T>::template N<K>::Type D<T>::f() {    // (D)
    return 3;
  }

Previously, in Microsoft mode, the front end failed to connect definition (D)
with declaration (d), and that triggered a spurious error.  This is now fixed.

Another such situation occurred with a dependent default template argument
for a pointer-to-function template parameter.  For example:

  template<typename T> void f(T);
  template<typename T, void F(T) = f<T> >
  void g(T t) {
    F(t);
  }
  int main() {
    g<int>(42);
  }              

Previously, in Microsoft mode, the call "g<int>(42)" could not be resolved
because the default template argument "f<T>" was not correctly processed.
This too is now fixed.


5/18/15  [EDGcpfe/14960]
Elimination of "error", "warning", and "remark" functions

Until now, the front end has contained a function named "error".  The
GNU library also contains a function with that name.  As a result, linking
with the GNU library could have caused the incorrect version of the
function to be used.  Because the use of this function has been, in a sense,
deprecated within EDG (along with the similar "warning" and "remark"
functions) in favor of the versions that require an explicit position to
be provided, we have removed these functions and their uses, rather than
renaming them.  We are not aware of any similar issues with "warning" and
"remark", but those were likewise eliminated because their very generic
names could cause conflicts in the future.

Code that contains uses of these functions, such as "error(ec_xxx);",
should be changed to "pos_error(ec_xxx, &error_position);".


5/15/15  [EDGcpfe/16139]
Invalid ranking of builtin operator called with differing enumeration types

In somewhat unusual cases where certain binary operators were applied to
an expression of enumeration type and another expression of a class type
convertible to a different enumeration type, the front end incorrectly
ranked the conversion of the class type to an arithmetic type.  This could
lead to overload resolution errors.  For example:

  enum E { e };
  enum F { f };

  struct WF { operator F() const; } w;
  struct I { I(int); };

  bool operator!=(int, I const&);  // (1)

  bool b = w != e;  // Previously ambiguous; now the builtin operator
                    // is selected.

Previously, when considering the conversion of w to an arithmetic type for
the builtin operator !=, the front end incorrectly ranked that conversion
as if it were a conversion to type E.  That made the conversion of w worse
for the builtin operator that for the operator declared at (1), which in
turn caused an ambiguity between those two candidate operators.  Now, the
conversion of w is weighed equally for both operators, and since the
promotion of e for the builtin operator is a better conversion than its
conversion to I, the builtin operator is now selected.


5/15/15  [EDGcpfe/13858,EDGcpfe/14722,EDGcpfe/15652,EDGcpfe/15628]
Internal error on use of enclosing template parameter pack in deduction

An internal error could occur (in find_placeholder_arg_for_pack) on
the use of an enclosing template parameter pack in a deduction context.
Now fixed.

  template<typename...> struct A { };
  template<typename T, typename U> struct B { };
  template<typename ...T> struct X {
    template<typename> struct Y {
      static const unsigned int i = 1;
    };
    template<typename ...T2> struct Y<A<B<T, T2>...> > {
      static const unsigned int i = 0;
    };
  };
  int z[X<short, int, long>::Y<A<B<short, unsigned short>,
                               B<int, unsigned int>,
                               B<long, unsigned long>>>::i == 0? 1 : 1];


5/14/15  [EDGcpfe/16136]
Microsoft calling conventions on x86-64 targets

In Microsoft modes with targ_supports_x86_64 set to TRUE, the front end now
ignores calling conventions other than __vectorcall when determining type
compatibility.  For example:

  void __stdcall f() {}
  void g() {
    void (*pf)() = &f;  // Previously an error in all Microsoft modes.
  }                     // Now accepted in Microsoft modes with x86-64
                        // targets.


5/13/15  [EDGcpfe/15431]
Preliminary coroutine support

Some preliminary support for C++ coroutines has been added to the front end.
For this support to be available the front end must be built with the macros
COROUTINES_ALLOWED set to TRUE and DO_IL_LOWERING set to FALSE.  Microsoft
mode with microsoft_version >= 1900 enables the feature with keywords __yield
and __await; the option --set_flag=coroutines can also be used to enable
this in other modes.  A keyword await and a contextual keyword yield can be
activated with the option --set_flag=coroutine_keywords.

The goal of this preliminary support is to be able to parse coroutines as
specified by the C++ standardization committee's paper N4286 (with some
modifications), and as expected to be available in Microsoft VS 2015.  In
particular, yield statements and await expressions are handled sufficiently
well to produce correct types and the recorded IL can be rendered by the
C++-generating back end.  The C++ standardization committee's coroutines
proposal is still somewhat in flux, and the feature will likely undergo
significant changes before its possible final approval.  If and when the
committee finalizes this feature, we expect to provide support in all of the
appropriate modes and dialects.


5/13/15  [EDGcpfe/16129]
Microsoft compatibility: internal error using certain CLR assemblies

In C++/CLI mode, an internal error could occur (in add_to_ms_attributes_list)
for assemblies that used certain attributes on generic classes.  Now fixed.

5/13/15  [EDGcpfe/15928]
Short-circuit evaluation in constant expressions

The front end previously issued a spurious "must have a constant value"
error in C++11 mode if the unevaluated second operand of || or && appearing
in a constant expression involves creation of a temporary with a
non-trivial destructor.  This is now fixed.  For example, with --c++11:

  struct C {
    ~C();
  };
  bool f(C);
  void g() {
    static_assert(true || f(C()), "");  // previously a spurious error
  }


5/12/15  [EDGcpfe/16119]
Clang compatibility: builtin functions

A number of changes have been made to the signatures of various builtin
functions to better emulate the builtins provided by clang.  In addition,
five new builtins were added: __builtin_ia32_cmppd, __builtin_ia32_cmpps,
__builtin_ia32_cmpsd, __builtin_ia32_cmpss, and __builtin_shufflevector.
The __has_builtin(__builtin_shufflevector) macro is now defined to "1"
when --clang is specified.


5/12/15  [EDGcpfe/16224]
Multiple pointers to same attribute list

When copying an a_param_type, if the parameter type had attributes, those
attributes had not themselves been copied, resulting in two pointers pointing
to the same list of attributes.  That had caused problems (an internal error
"ptr_remap_function: address not in any mem block") in some configurations
(e.g., where ALTERNATE_IL_FILE_FORMAT is FALSE).  For example, with --c++11:

  void f(int x[[foo,bar]]);


5/12/15  [EDGcpfe/16197]
Assertion failure in constant_value_at_address with indirect base member

An attempt to access an indirect base class member in a derived class,
where intermediate base classes have no direct members, previously aborted
with an assertion failure in constant_value_at_address.  This is now fixed.
For example, with --c++11:

  struct A {
    constexpr A(float r) : v(r) { }
    float v;
  };
  struct B : A {
    constexpr B(float r) : A(r) { }
  };
  struct C : B {
    constexpr C(float r) : B(r) { }
  };
  struct D {
    constexpr D(const C& c) : w{c.v} { }  // Previously aborted
    float w;
  };
  void f() {
    D d(C(11));
  }


5/8/15   [EDGcpfe/2314,EDGcpfe/8060,EDGcpfe/11761]
Better diagnostic for missing "typename" keyword

A change has been made to issue a more informative diagnostic in cases where a
qualified member of a nonreal, non-prototype-instantiation template class is
used without specifying the "typename" keyword.  For example (with --dep_name):

  template <class T> struct A {
    typedef int I;
  };
  template <class T> void f(T) {
    A<T>::I i;        // missing "typename" keyword
  }


5/7/15   [EDGcpfe/16201]
GNU compatibility: handling of [[gnu:...]] attributes

A change has been made to handle attributes that have the C++11 standard
syntax and use the "gnu" namespace as though they are af_gnu attributes
(i.e., as if they had used the __attribute((...)) syntax) when using
GNU emulation mode and gnu_version >= 40800.  This change allows some
[[gnu:...]] attributes to be accepted where C++11 standard attributes typically
are not applicable, for example, with --c++11 --gnu_version 40800:

  char a[4] [[gnu::aligned(2)]];
  typedef char b[4] [[gnu::aligned(2)]];


5/1/15   [EDGcpfe/16208]
Unnecessary reallocation of attr_name_map

A hash table for attribute names, attr_name_map, had been allocated and
initialized once at program startup, and then reallocated and re-initialized
for each translation unit.  The latter allocation and initialization has
now been removed.


4/29/15  [EDGcpfe/16130]
C++-generating back end: Casts of the form T{...}

The C++-generating back end sometimes incorrectly rendered a cast of the form
T{...} where T is an aggregate type; it dropped the type T.  For example:

  struct S {};
  void g() {
    auto x = S{};  // Previously incorrectly rendered as "auto x = {};"
  }

This is now fixed.


4/27/15  [EDGcpfe/16195]
Default initialization and constexpr default constructors

The front end often failed to fold constexpr default constructors when
processing default initializers.  That in turn could result in dynamic
initialization where static initialization should be performed instead.
For example:

  struct N {
    int n;
    constexpr N(): n(0) {}
  };
  N n;  // Previously the initialization of n was represented as a dynamic
        // initialization.  Now n is recorded with a static initializer.

This is now fixed.


4/27/15  [EDGcpfe/16194]
Ignoring benign macro redefinitions

A benign redefinition of a macro (i.e., one in which the new definition is
identical to the original) should have no effect.  In configurations with
RECORD_MACROS_IN_IL set to TRUE, however, the front end previously created
an extra a_macro IL entry for such a redefinition.  Moreover, in
configurations with FULLY_RESOLVED_MACRO_POSITIONS set to TRUE, the
original positions resulting from an invocation of the macro (correctly)
reflect the original definition, even though (with
MACRO_INVOCATION_TREE_IN_IL set to TRUE) the invocation record referred to
the IL entry for the redefinition, not the original.  This has now been
fixed, with a benign redefinition having no effect on the resulting IL.
For example:

  #define M 10  // #1
  #define M 10  // #2
  int i = M;    // Original positions in expression reflected #1 but
                // invocation referred to #2


4/26/15  [EDGcpfe/16181]
Spurious error on pack expansion of class template parameter pack

A spurious error could be issued on the expansion of a class template
parameter pack used in the declaration of a member template of a
class template.  Now fixed.

  template <class... Types> class X {};
  template <template<class...> class... Types> class A {};
  template <template<class...> class... Types> class B {
    template <class T> void f(A<Types...> a) {}
  };
  int main() {
    B<X> b;
  }


4/23/15  [EDGcpfe/16180]
Spurious error in function default argument involving pack expansion

A spurious error was sometimes issued when a function default argument
used a pack expansion.  Now fixed.

  template< class... Types> class A { }; 
  template< class... Types> void f(A<Types...> a = A<Types...>()) { }
  int main() {
    f<int,char>();
  }


4/23/15  [EDGcpfe/15604,EDGcpfe/15397,EDGcpfe/15717,EDGcpfe/15851,
          EDGcpfe/16160,EDGcpfe/16206]
Allow run time target configuration

To date, the target configuration of the front end has been specified entirely
when the front end is built, rendering it impossible to support multiple
targets with a single front end executable (without local modifications).  A
change has been made to allow the front end to support multiple target
configurations with the new --target command-line option.  This option takes
the name of a "target configuration" and re-initializes target-specific global
variables with the values appropriate for the specified target configuration.

The existing method for configuring the front end is unchanged; the same
configuration macros are used, and the resulting configuration is referred to
as the "legacy" configuration (and is the default configuration if no other
target configuration has been designated as the default and no --target
command-line option is specified).

A subset of the existing configuration macros have been identified as being
target-specific and creating a new target configuration requires specifying
values for each of these target-specific configuration macros (as well as
a unique name for the target configuration).  To aid in this process, another
new command-line option has been added, --dump_legacy_as_target, which takes
the name of the prospective target configuration and dumps (to stderr) a
list of #defines for target-specific configuration macros with the values
of the legacy configuration.  This list can be inserted into an existing
defines.h (or perhaps #include'ed by it) to create the basis of a new
target configuration (initially identical to the legacy configuration).

Note that not all configuration macros are target-specific, and all target
configurations must use the same front end configuration (e.g., it's not
possible to have an IA-64 ABI and Cfront ABI target configuration selectable
at run time, or one that has GNU_EXTENSIONS_ALLOWED and another that has
MICROSOFT_EXTENSIONS_ALLOWED).

As part of these changes, the USE_X86_64 configuration macro has been
replaced by the TARG_SUPPORTS_X86_64 target-specific configuration macro.
Any use of the USE_X64_64 macro should be replaced by a run-time check of
the new targ_supports_x86_64 global variable.

Note that each target configuration will need a predefined_macros.txt file
whose values match those of the configuration; compilers supporting multiple
configurations will also likely require a different libC.a file for each.  To
aid in managing multiple sets of these files, the front end (and eccp.sh) now
append the target configuration name (and a separating underscore) to the value
of EDG_AUXILIARY_INFO_DIR_NAME.  So, if "--target my_config" is used and
EDG_AUXILIARY_INFO_DIR_NAME is "lib", the front end will look for a
predefined_macros.txt file in $EDG_BASE/lib_my_config (and eccp.sh will also
look there for libC.a).  There is no change when using the unnamed legacy
configuration.

For customers that read the IL from a file, note that a change has been
made to standalone_utility_init to split it into two routines:
standalone_utility_early_init and standalone_utility_late_init.  This is
required because initialization of target-specific global variables is based
on the target configuration that was specified in the front end and that
information is not known until after the il_header has been read (so
standalone_utility_late_init must be called after il_read).

Any local changes that make use of configuration macros that are now
target-specific should use the associated global variables.

For examples of using multiple target configurations, see the changes in
defines.h.linux or defines.h.win32, which provide "linux_i686" and
"linux_x86_64" or "win32" and "win64" target configurations respectively
(when INCLUDE_ADDITIONAL_TARGET_CONFIGURATION is TRUE -- it is FALSE by
default).

Two new header files, target_cfg.h and target_map.h, have been added to
support these changes.  Customers that have additional target-specific
global variables can make changes in target_map.h to add those global variables
to the set of target-specific global variables (providing the variables
meet certain criteria -- see the comments in target_map.h).

Note that as a result of these changes, it is now inadvisable to use
a target-specific global variable as the value for a target-specific
configuration macro.  For example:

  #define TARG_IA64_VTABLE_ENTRY_INT_KIND targ_ptrdiff_t_int_kind

will no longer work, though

  #define TARG_IA64_VTABLE_ENTRY_INT_KIND TARG_PTRDIFF_T_INT_KIND

will work as expected.  This is due to a race condition when setting
global variables (e.g., targ_ptrdiff_t_int_kind hasn't yet been assigned
its value from TARG_PTRDIFF_T_INT_KIND before being assigned to
targ_ia64_vtable_entry_int_kind).  When using non-EDG global variables
as values for target-specific configuration macros, ensure that values for
these have been set before set_target_configuration is called.

From an ongoing maintenance point-of-view, new configuration macros are
typically given default values and are thus somewhat invisible when upgrading
to a new release.  That won't be the case for new target-specific configuration
macros that are added henceforth; although the non-target-specific macro will
continue to have a default value, no default values can be specified for
target-specific versions (as the target-specific suffixes are unknown), so
compilation errors will result.  This can be remedied either by manually adding
values for any new target-specific configuration macros or by removing
target-specific configuration, re-compiling, and re-generating the various
target-specific configurations with --dump_legacy_as_target (as described
above).  Any new target-specific configuration macros will be explicitly
mentioned in the release documentation.

Microsoft Visual Studio pre-defines a number of macros (see
https://msdn.microsoft.com/en-us/library/b0084kay(v=vs.140).aspx for a list),
some of which are considered target-specific (e.g., _M_IX86, _M_AMD64, etc.).  
Support for defining such macros should be handled via the
predefined_macros.txt mechanism and a new tool, make_win_predef_macro_table.c,
has been written to help identify these macros and automatically create a
predefined_macros.txt file (similar to the way the make_predef_macro_table
tool creates GNU-specific predefined macros).  In some cases, _M_IX86 had
been defined by the front end, but that definition has been removed.  See
make_win_predef_macro_table.c for more information.  The configuration macro
DEFAULT_USE_PREDEFINED_MACRO_FILE is now set by default when using
defines.h.win32 to reflect this change.


4/21/15  [EDGcpfe/16133]
C++-generating back end: default value of
KEEP_TEMPLATE_ARG_EXPR_THAT_CAUSES_INSTANTIATION

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE and
KEEP_TEMPLATE_ARG_EXPR_THAT_CAUSES_INSTANTIATION set to FALSE, in some
cases the C++-generating back end could generate incorrect code when a
non-type template argument expression is folded.  To avoid this problem,
the default setting of KEEP_TEMPLATE_ARG_EXPR_THAT_CAUSES_INSTANTIATION has
been changed to TRUE when PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, allowing
the original form of the argument to be preserved.  For example, with
--gnu_version=40802 --c++11:

  template <typename T, unsigned N> struct A {
    T m[N];
    constexpr const T &operator[](unsigned i) const {
      return m[i];
    }
  };

  template <typename T, class U, class M>
  struct B;

  template <typename T, T... Vs,
            template <T...> class U,
            unsigned... Is,
            template <unsigned...> class M>
  struct B<T, U<Vs...>, M<Is...>> {
    static constexpr A<T, sizeof...(Vs)> mVs = {Vs...};
    using type = U<mVs[Is]...>;
    // Generated as U<{Vs}[Is]...> with
    // KEEP_TEMPLATE_ARG_EXPR_THAT_CAUSES_INSTANTIATION set to FALSE
  };


4/18/15  [EDGcpfe/16179]
Microsoft compatibility: handling of comma in variadic macro arguments

In the Microsoft preprocessor, a comma appearing in the text passed to an
ellipsis macro parameter generally does not delimit macro arguments when
__VA_ARGS__ is passed as the argument to another macro in the expansion of
the variadic macro.  However, this special treatment of commas does not
apply when the name of that secondary macro is itself the result of a
deeply-nested macro expansion.  The front end previously failed to make
this distinction but has now been changed to emulate the Microsoft
preprocessor more closely.  For example, with --microsoft -E,

  #define A(x,y) B(x,y)
  #define B(x,y) concat(x,2)
  #define concat(x,y) x##y
  #define C2(x,y) y,x
  #define C(...) A(C, abc) (__VA_ARGS__)
  C(x, y)

now produces the output "y,x", as does the Microsoft preprocessor, because
the comma in the __VA_ARGS__ string separates "x" and "y" into distinct
arguments.  Replacing the definition of B, however, with

  #define B(x,y) C2

results in a warning about too few arguments for C2 and the output ",x, y";
__VA_ARGS__ is treated as a single argument because the macro name C2 is
not the result of a nested macro expansion.


4/18/15  [EDGcpfe/16101]
C++-generating back end, Microsoft compatibility: typedefs used as qualifiers
in class templates

The Microsoft compiler has a bug that causes it in some cases to report
spurious errors when a dependent type is used as a qualifier appearing
inside a class template definition.  This problem does not normally occur
in user-written code because member typedefs are typically used to shorten
the template arguments.  However, the IL produced by the front end
generally refers to the underlying type, not the typedef, in such template
arguments.  This occasionally caused problems when compiling the output of
the C++-generating back end when PROTOTYPE_INSTANTIATIONS_IN_IL is set to
TRUE.  To work around this bug in the Microsoft compiler, when
msvc_is_generated_code_target is TRUE, the C++-generating back end in such
configurations has now been changed to use a member typedef when one is
available instead of a dependent type when it occurs in such contexts.
(The typedef will also be used in the definition of a member outside the
class.)  The following example did not trigger the Microsoft compiler bug
but illustrates the effect of this change when compiled with --microsoft:

  template<typename T> struct A { };
  template<typename T> struct B {
    typedef typename A<T>::type X;
    typedef A<typename X::type> Y;  // Previously generated as
                                    // "A<typename A<T>::type::type>"
  };


4/17/15  [EDGcpfe/16150]
Clang compatibility: _Static_assert and __has_feature(cxx_static_assert)

Changes have been made to be more compatible with clang in this area;
_Static_assert is now accepted in all C++ modes, and
__has_feature(cxx_static_assert) is now FALSE in C modes (it is only
TRUE in --c++11 mode).  This is now accepted with --clang:

  void f() {
    _Static_assert(1, "test");
  }


4/17/15  [EDGcpfe/16176]
Indeterminate exception specifications and the never_throws flag

For defaulted special members, the front end sometimes records an
"indeterminate" exception specification (see the entry for EDGcpfe/13735).
Such an entry may later be "resolved", but in cases where that resolution
reveals that the special member throws no exception, the front end previously
failed to set the associated routine's never_throws flag to TRUE.  For example:

  struct S {
    virtual void v() { return; }
  };
  int main() {
    S s;
    s.v();
    return (int)noexcept(S());
  }

In nonstrict modes, the default constructor of S is first generated with an
"indeterminate" exception specification.  The noexcept operator, however,
causes that indeterminacy to be resolved and the resulting exception
specification is "noexcept" (i.e., the constructor is known to never throw
an exception).  Previously, the default constructor's never_throws flag did
not reflect this; now it does.


4/16/15  [EDGcpfe/16175]
GNU compatibility: segfault in lower_gnu_statement_expression

In certain cases involving destructions of local entities in a GNU statement
expression, a segfault in lower_gnu_statement_expression could occur.  Now
fixed.  For example (with --g++):

  struct A { ~A(); };
  A f() {
    return ({ A a; a; });
  }


4/14/15  [EDGcpfe/15918]
C++14: Direct braced initializers and placeholder types

In C++11 mode, a variable declared with a placeholder type ("auto" or
"decltype(auto)") and with a "direct" braced initializer is deduced to have a
std::initializer_list<...> type.  In C++14 mode and in Microsoft C++ mode with
microsoft_version >= 1900, such cases are now only permitted if the braces
enclose a single element and in such situations the outer braces are ignored.
For example:

  auto x{ 1, 2 };  // std::initializer_list<int> in C++11 mode; now an error
                   // in C++14 mode.
  auto y{1};       // std::initializer_list<int> in C++11 mode; now int in
                   // C++14 mode.

This rule is a result of a language change introduced by the C++ standards
committee's paper N3922.  It does not currently apply in GNU and Clang C++14
modes.


4/14/15  [EDGcpfe/16173]
Over-eager generation of virtual defaulted destructor definitions

The front end sometimes generated definitions for virtual defaulted destructors
when that was not actually needed.  This could result in spurious errors.
For example:

  template <typename T> struct U {
    ~U() {
      if (sizeof(T)>8) {}
    }	
  };
  struct X;
  struct Y {
    virtual ~Y() = default;
    U<X> x;
  };

In this example the front end previously generated a body for Y::~Y(), which
in turn triggered the instantiation of U<X>::~U() and that resulted in an
error since the sizeof operator cannot be applied to the incomplete type X.
This is now fixed (the definition of Y::~Y() is no longer forced).


4/14/15  [EDGcpfe/16104]
C++-generating back end, Microsoft compatibility: delegating constructor of
class template

In a configuration in which PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the
C++-generating back end put out the name of the class in the
mem-initializer of a delegating constructor of a class template using a
qualified name and a template argument list.  Although this is correct
code, the Microsoft compiler reports spurious errors when the argument list
passed to the target constructor is enclosed in braces instead of
parentheses.  To work around this issue, the C++-generating back end now
puts out the name of the class in this context as a bare name, referring to
the injected-class-name.  For example:

  template<typename T> struct S {
    S(int);
    S() : S{0} { }  // Previously generated as ::S<T>{(0)}, an error in MSVC
  };


4/9/15   [EDGcpfe/16070]
GNU C++ compatibility: internal error on "!" operator in SFINAE context with
ABI_COMPATIBILITY_VERSION < 402

In g++ mode with ABI_COMPATIBILITY_VERSION < 402, an internal error could
occur in copy_template_param_expr if a template substitution context used
a "!" operator on a dependent expression.  Now fixed.

  template <bool> struct A ;
  template <typename> struct B { enum { value }; };
  template <typename U> struct C {
    template <typename T> void f(typename A <(1 || ! B <T>::value)>::type) {}
    template <typename V> void f(C<V>&) {}
  };
  int main() {
    C<int> ci;
    typedef B<int> X;
    C<X> cx;
    ci.f<X>(cx);
  }


4/7/15   [EDGcpfe/16158]
Assertion failure in mangled_encoding_for_sizeof_pack

In configurations where PROTOTYPE_INSTANTIATIONS_IN_IL and MANGLE_ALL_NAMES
are both TRUE, an assertion failure (in mangled_encoding_for_sizeof_pack)
could occur when mangling a type with a C++11 sizeof... expression.  Now fixed.
For example, with --c++11:

  template <int N> struct X {};
  template <class... T> void f(T... t) {
    X<sizeof...(t)> x;
  }


4/6/15   [EDGcpfe/2667,EDGcpfe/6204,EDGcpfe/7379,EDGcpfe/16149]
Microsoft compatibility: Use of undeclared template in default argument

The Microsoft compiler allows the use of an undeclared class template in
a template default argument.  We now emulate this in Microsoft mode.

  template <typename T1, typename T2 = B<T1> > class A { }; 


4/1/15   [EDGcpfe/16125]
GNU compatibility: Disable checking of register use for multiple alternative
                   constraints with earlyclobbers in asm statements

The checking for conflicts in register usage when "earlyclobbers" (i.e., the
"&" modifier) is used in constraint strings that contain multiple alternatives
has been disabled because such checking resulted in errors that are not
reported by GNU compilers.  It is unclear what criteria GNU uses for generating
such errors, as evidenced by the example below (with --gcc):

  int f(int x, int y) {
    asm("foo %1,%0;" : "=&a" (x) : "b" (y));        // GNU:OK    EDG:OK
    asm("foo %1,%0;" : "=&b" (x) : "b" (y));        // GNU:Error EDG:Error
    asm("foo %1,%0;" : "=&a" (x) : "a" (y));        // GNU:Error EDG:Error
    asm("foo %1,%0;" : "=&a,&b" (x) : "b,b" (y));   // GNU:OK    EDG:Now OK
    asm("foo %1,%0;" : "=&a,&b" (x) : "a,a" (y));   // GNU:Error EDG:Now OK
    asm("foo %1,%0;" : "=&b,&a" (x) : "b,b" (y));   // GNU:OK    EDG:Now OK
    asm("foo %1,%0;" : "=&b,&a" (x) : "a,a" (y));   // GNU:OK    EDG:Now OK
    return x;
  }

In Clang emulation mode, earlyclobbers register conflicts have been disabled
in both single and multiple alternative constraints to match clang's behavior
(i.e., the example above compiles with no errors with --clang).


3/31/15  [EDGcpfe/16124]
GNU compatibility: Choice of underlying integer kind for vector types

It appears that, at least in some (e.g., 16-bit) configurations, GNU
prefers "int" over "short" when selecting an integer type as the underlying
type for a vector.  A change has been made to first check the "int" (or
"unsigned int") integer kind to see if it is the correct size for the
underlying type for a vector before searching for integers of different sizes.
For example, on a configuration where sizeof(int) == sizeof(short), with --gcc:

  typedef int int16_t __attribute__ ((__mode__ (__HI__)));
  typedef int int16_t;   // no longer an invalid redeclaration error


3/31/15  [EDGcpfe/16131]
C++-generating back end: Variable definitions and GENERATE_LINKAGE_SPEC_BLOCKS

In configurations with GENERATE_LINKAGE_SPEC_BLOCKS set to TRUE, the
C++-generating back end sometimes accidentally rendered a variable definition
as a non-defining declaration.  For example:

  extern "C" { extern double d; }  // Declaration.
  double d;                        // Definition.

was previously rendered as:

  extern "C" {extern double d; }
  extern "C" double d;

which doesn't have a definition for variable d.  This is now fixed.


3/31/15  [EDGcpfe/16117]
Microsoft compatibility: Enable additional C++11/C++14 features

The C++11 style of attributes, e.g., "[[noreturn]]" is now enabled
when microsoft_version >= 1900, as is the C++14 global sized deallocation
feature (see EDGcpfe/14687).


3/31/15  [EDGcpfe/12128,EDGcpfe/12504,EDGcpfe/16082]
Clang and Microsoft C++ compatibility: Qualifiers on constructor declarations

In Clang and Microsoft C++ modes, the front end now accepts constructor
declarations with type qualifiers preceding the constructor name (with a
warning).  For example:

  struct S {
    const S();  // Now accepted as a constructor declaration (with a warning)
  };            // in Clang and Microsoft modes.


3/31/15  [EDGcpfe/16116]
GNU compatibility: Spurious error after unrecognized attribute

In configurations where RECORD_UNRECOGNIZED_ATTRIBUTES is TRUE, an
unrecognized attribute before an "auto" type specifier with a trailing
return had resulted in a spurious error.  Now fixed.  For example, with
--g++ --c++11:

  inline __attribute__((X)) auto f() -> int;  // previously a spurious error


3/30/15  [EDGcpfe/16091]
"Referenced but not defined" functions

When, e.g., a function with internal linkage is declared and referenced but
not defined, the front end usually issues an error (ec_never_defined; in some
specific situations a milder diagnostic is issued).  Now, such errors are
discretionary when they apply to functions or function templates (not
variables or labels).  For example:

	template<class T> static void f();
	void g() { f<int>(); }
	  // Previously a hard error, now a discretionary error.


3/25/15  [EDGcpfe/15245]
C++-generating back end, GNU compatibility: parenthesized non-type template
parameters as attribute arguments

Versions of g++ prior to 4.6 require that a non-type template parameter
used as an argument to an attribute be enclosed in an extra set of
parentheses.  The C++-generating back end has now been changed to
accommodate this requirement.  For example, in a configuration with
CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT set to TRUE and
--gnu_version=40500:

  template<int I> struct S {
    // The following was previously generated as "__aligned(I)":
    struct __attribute__((__aligned__((I)))) { } a;
  };
  int i = sizeof(S<4>);  // Previously caused a "not a constant" error in
                         // g++ versions 4.5 and earlier


3/25/15  [EDGcpfe/16111]
Assertion failure when lowering initialization of multi-dimensional array

Using a character string to initialize a multi-dimensional character array
using repeated designated initializers had resulted in an assertion failure (in
handle_multidimensional_ck_init_repeat).  This regression was introduced in
4.10, but the example below had resulted in an infinite loop in C-generating
configurations prior to 4.10.  Both issues are now fixed.  For example,
with --gcc:

  const char x[2][4] = {
    [0 ... 1] = ""
  };


3/24/15  [EDGcpfe/16110]
Over-eager instantiation of noexcept-specifier arguments

Consider the following example in GNU C++ mode:

  template<typename T> struct S {
    S();
    S(const S&) noexcept(S<T>::value);
  };
  S<int> t;

The front end previously issued an error on S<int>::value even though the
associated constructor is not used in this code.  The error was triggered by
an attempt of the front end to pre-compute the results of the type trait
helper operators __has_nothrow_copy and __has_nothrow_assign.  The front end
no longer does this precomputation and the example is now accepted in GNU C++
mode (in strict mode, the code elicits an error because that constructor has
no valid instantiation for any T).


3/24/15  [EDGcpfe/16103]
Abort on use of a static data member of a managed class in constant context

In modes combining C++/CLI and C++11 (e.g., with "--cppcli --c++11") the front
end sometimes aborted (with a null pointer dereference in
define_template_static_data_member) when a const static data member with an
in-class initializer was used in a constant-expression context.  For example:

  template<typename> value struct V {
    static const bool value = false;
  };
  template<bool> class B {};
  struct S {
    B<V<int>::value> x;  // This use of V<int>::value previously triggered an
  };                     // abort in some modes.

This is now fixed.


3/23/15  [EDGcpfe/15997]
Microsoft and GNU C++ compatibility: expressions in non-type template arguments

The C++11 Standard requires that a template argument for a pointer or
pointer-to-member non-type template parameter be an id-expression,
optionally preceded by an "&".  The Microsoft and g++ (in C++11 mode)
compilers do not strictly enforce this requirement, accepting cast
expressions as template arguments in these cases.  The Microsoft compiler
also accepts the address of a __uuidof operator as an argument.  The front
end has now been changed to do the same in the corresponding emulation
modes.  For example, with --g++ --c++11:

  typedef void (*PF)();
  template<PF P> struct S { };
  void f();
  S<(PF)f> sf0;   // Now accepted


3/23/15  [EDGcpfe/16105]
Abort on indirect capture from a generic lambda

When a generic lambda captures a variable that is first captured by an
enclosing nongeneric lambda, the front end often aborted with an internal
error in scope_depth_for_capture (expr.c).  For example:

  void g() {
    auto lambda = [](int x) {
                    return [x]() {
                             return [x](auto y) { sizeof(x); };
                           };
                  };
    lambda(1)()(2);
  }

In this example, the front end aborted while processing the reference to x
in "sizeof(x)".  This is now fixed.


3/23/15  [EDGcpfe/16108]
Incorrect accessibility given to class template member defined out-of-class

Members of a class defined using the "struct" keyword are public by default.
If a member class of a class template was initially declared with "class"
and later defined out-of-class with "struct", instantiations of the class
were incorrectly treated as if they were defined with "class", making their
members private by default (and vice-versa if declared with "struct" and
later defined with "class").  This would result in spurious access errors
or failure to issue access errors.  Now fixed.

  template<typename T> struct A {
    template<typename T2> class B;
  };
  template<typename T> template<typename T2> struct A<T>::B { void f(); };
  int main() {
    A<int>::B<int> d;
    d.f();
  }


3/21/15  [EDGcpfe/16033]
C++-generating back end: incorrectly-braced initializer lists

The C++-generating back end sometimes incorrectly enclosed a braced
initializer list in an extra set of braces.  One such case is the
direct-list-initialization of a variable whose type has an
initializer-list constructor.  For example, with --c++11:

  #include <initializer_list>
  struct S {
    S(std::initializer_list<int>);
  };
  S s{0};   // Previously generated as s{{0}}

Another case is the aggregate initialization of a non-static data member
using the form without an "=":

  struct A {
    int i;
    int j;
  };
  struct B {
    A a{1, 2};   // Previously generated as a{{1, 2}}
  };

These are now fixed.


3/19/15  [EDGcpfe/16106]
Microsoft compatibility: Implicit captures and generic lambdas

Previously, in Microsoft C++ mode with microsoft_version >= 1900, the front end
accepted generic lambdas provided they did not include implicit capture.  That
restriction is now lifted.  For example:

  int f(int x) {
    auto fn = [=](auto p){ return p+x; };  // Now accepted when
    return fn(2);                          // microsoft_version == 1900.
  }


3/19/15  [EDGcpfe/16098]
Microsoft compatibility: __declspec attributes on lambdas

In Microsoft C++ modes that accept lambdas, the front end now accepts
__declspec attributes on such lambdas.  For example:

  auto fn = [](int x) __declspec(dllexport) { return x; };

Such attributes apply to the call operator of the associated closure type.


3/19/15  [EDGcpfe/16092]
C++14: "constexpr" no longer implies "const" for non-static member functions

In the C++11 version of the C++ standard, a non-static member function
declared with the "constexpr" specifier was also implicitly declared "const".
That has changed in the C++14 version of the standard, and the front end
has been modified to reflect that.

Unfortunately, this change may cause valid C++11 programs to become invalid
when compiled in C++14 mode.  The example below is a valid C++11 program
(because the implicit "const" added as a result of declaring the first member
function results in two different function types that can be differentiated
during overload resolution), but is an invalid C++14 program:

  struct A {
    constexpr int f() { return 0; }
    int f() { return 0; }
  };

In order to better manage this transition, a new warning has been added
in C++11 mode in cases where "const" is implicitly added.

Another side-effect of this change is that non-static member functions where
"const" had been implicitly added will have different mangled names when
compiled in C++14 mode (because function cv-qualifiers are included in
mangled names).  A new global variable, mangle_had_been_implicitly_const,
has been introduced that, when TRUE, will maintain the original mangled
name.  Note that setting this variable to TRUE is non-standard and may result
in name collisions.  The default value is FALSE.


3/18/15  [EDGcpfe/16003,EDGcpfe/16093]
__is_convertible_to with private or ambiguous base classes

Previously, the front end's implementation of __is_convertible incorrectly
produced a "true" value when one type is privately or ambiguously derived from
the other.  The same problem occurred for pointers or references to such types.
For example:

  struct B {};
  struct C: private B {};  // Private base class.
  static_assert(!__is_convertible_to(C, B), "Unexpected!");
    // Previously this assertion check failed.  Now okay.

Another example:

  struct B {};
  struct C1: B {};
  struct C2: B {};
  struct D: C1, C2 {};  // Base class B is ambiguous.
  static_assert(!__is_convertible_to(D, B), "Unexpected!");
    // Previously this assertion check failed.  Now okay.

This is now fixed.


3/18/15  [EDGcpfe/15900]
Incorrect lowered IL for repeated aggregate initialization in C++14 mode

As a result of changes in 4.10 for C++14, the front end had, in some cases,
generated a ck_init_repeat on top of a ck_aggregate which contains a
ck_dynamic_init as a means of initializing certain aggregates.  This
particular sequence causes problems during lowering because a ck_init_repeat
requires a general purpose looping construct, but the C language doesn't have
any looping constructs that can appear in an expression context.  The result
had been that lowering generated incorrect or invalid IL for such constructs.

A change has been made in the front end in cases where an aggregate class with
a nontrivial default constructor is initialized with a pair of empty braces.
In such cases, the aggregate is now initialized with a ck_dynamic_init
constant that invokes a default constructor or, if the default constructor
has been deleted, an "internal constructor" that is created for this
particular situation.

For example, in C++14 mode, the lowered IL for the following example did not
correspond to the required behavior (the program would return 1 instead of 0):

  int f() {return 37;}
  struct A {
    int y = f();
  };
  int main() {
    A a[2]{};
    return !(a[0].y == 37 && a[1].y == 37);
  }

The program had returned 0 in C++11 mode.


3/18/15  [EDGcpfe/16094]
Invalid IL on implicit cast in constant-expression appearing in a template

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to FALSE, the front
end sometimes incorrectly recorded a type involving template parameters in the
IL.  This occurred when performing certain implicit conversions in a
constant-expression context, and could, e.g., result in an IL write-read error
in configurations with IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE.  For example,
in C++11 mode:

  template<typename T> struct X {
    typedef short size_type;
    static const size_type N = 5;
    T  m_dim[N];  // N is implicitly cast to size_t.  The original type
                  // X<T>::size_type was previously recorded in the IL even in
  };              // configurations that don't record template-based types.
  template struct X<double>;

This regression (introduced in version 4.9 of the front end) is now fixed.


3/18/15  [EDGcpfe/16095]
Use of il_to_str.c routines after the symbol table has been freed

Usually, using the il_to_str.c routines in back ends is safe even after the
front end's symbol table has been freed.  However, the rendering of signatures
for generic lambdas cannot always be done without the symbol table.  An
alternative output format (not involving the lambda's signature) was already
used for standalone utilities; now, that same format is used when in_front_end
is FALSE.


3/18/15  [EDGcpfe/16099]
Using "auto" as a storage class specifier in C++11 parameter declarations

C++11 removed "auto" as a storage class specifier, making it a type specifier
instead.  The front end provides an option "--auto_storage" to enable the
traditional (C, C++03) meaning of "auto" in C++11 modes, but previously that
did not extend to parameter declarations.  Now it does.  For example:

  void f(auto double x);  // Now accepted with "--c++11 --auto_storage".


3/18/15  [EDGcpfe/14165,EDGcpfe/16097]
Core issue 974: Default arguments and lambda expressions

In C++11 modes and in Microsoft C++ mode with microsoft_version >= 1900, the
front end now accepts lambda expressions with default arguments.  For example:

  auto lambda = [](int p = 0) { return p; };

Such cases were already permitted in GNU C++ modes that accept lambda
expressions.  This implements the standards committee's resolution for Core
issue 974.


3/17/15  [EDGcpfe/15809]
Remove duplicate include directories from the search path

In GNU mode when gnu_version >= 30300 if an include directory is specified
more than once in the search path, the duplicate entries are removed.
Formerly, this was only done if one was a system include and the other
was not.


3/17/15  [EDGcpfe/14503]
Spurious access error on instantiation of out-of-class partial specialization

A spurious access error was sometimes issued on the instantiation of a
member class template partial specialization declared outside of its class.
Now fixed.

  template<class T> class A {
    template<class U> class B {};
  };
  template<class T> template<class U> struct A<T>::B<U*> {};
  int main() {
    A<int> a;
  }


3/16/15  [EDGcpfe/16081]
C++-generating back end and exception specifications on instantiations

In configurations with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to
TRUE, the C++-generating back end renders instantiations as explicit
specializations.  Previously, if an unused member function of an instantiated
class template included an exception specification, this triggered an internal
error because the operand of an exception specification is never parsed if the
member member function is never used (so no IL is available to render the
exception specification).  For example:

  template<class T> struct S {
    void f() noexcept(T()) {}
  };
  S<int> s;  // Previously, the C++-generating back end's attempt at rendering
             // a definition for S<int> triggered an internal error because
             // no IL is available to render "T()" with T == int.

Now, the C++-generating back end simply doesn't render an exception
specification in such cases.  I.e., for the case above, the specialization of
S<int> looks as follows:

  template<> struct S< int>  { 
  void f(); 
  }; 


3/16/15  [EDGcpfe/15750]
C++-generating back end: incorrect destructor name emitted

When producing code based on IL, the C++-generating back end incorrectly
emitted a dependent destructor reference where the name after the "~" was
a typedef to a dependent qualified name.  Now fixed.

  template <typename T> struct A {
    using N = typename T::value_type;
    // Formerly emitted as "n->~value_type()"
    void f(N* n) { n->~N();}
  };
  struct B { struct C { }; typedef C value_type; };
  int main() {
    A<B> a;
    B::C* c = new B::C();
    a.f(c);
  }


3/13/15  [EDGcpfe/16079]
Invalid handling of using-declaration referring to a base class member template

The front end sometimes incorrectly dealt with a using-declaration referring to
a member template of a base class when it was followed by a member template
declaration in the derived class that displaces the base-class import.  The
problem, which usually manifested itself as a spurious ambiguity error, only
occurred when the base and derived classes had different template
parameterization levels.  For example:

  template<typename> struct P {};
  struct B { template<typename T> void f(P<T>); };
  template<int> struct D: B {
    using B::f;
    template<typename T> void f(P<T>);  // Should displace B::f.
  };
  int main() {
    D<0> d;
    P<int> x;
    d.f(x);  // Previously triggered an ambiguity error.  Now okay.
  }

This is now fixed.


3/13/15  [EDGcpfe/16087]
GNU compatibility: generic __atomic_... functions

The front end adds an initial size_t argument (that represents the size of the
pointed-to operand) to four GNU generic __atomic_... functions (namely
__atomic_load, __atomic_store, __atomic_exchange, and
__atomic_compare_exchange).  A change has been made in C- and C++-generating
back end configurations (where GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED is TRUE) to
strip the compiler-generated argument as well as any compiler-generated
casts (so the resulting generated C or C++ source will be compilable by an
appropriate GNU compiler).  For example (with --gnu_version 40700):

  void f(char x) {
    __atomic_load(&x, &x, 0);
    __atomic_store(&x, &x, 0);
    __atomic_exchange(&x, &x, &x, 0);
    __atomic_compare_exchange(&x, &x, &x, 0, 0, 0);
  } 


3/11/15  [EDGcpfe/16083]
Microsoft mode abort on binding of nontype template reference argument

The changes for EDGcpfe/15084 etc. (see entry of 6/10/14) introduced a
regression in Microsoft mode that could trigger an internal error in exprutil.c
(function take_reference_to_operand) when a nontype template reference
argument is bound to a nontype template reference parameter.  For example:

  struct V {};
  template<const V &Val> struct A {};
  template<const V &Val> struct B: A<Val> {};
  template<const V &Val> struct C: B<Val> {};
    // Previously triggered an abort in Microsoft mode during the prototype
    // instantiation of B<Val>.

This is now fixed.


3/11/15  [EDGcpfe/16084]
Changes to diagnostic processing

The diagnostic processing routines have been reworked to provide a mechanism
that can be used to provide additional information about the cause of
an error (for example, the reason for a constexpr evaluation failure).
The new structure builds all of the information about a diagnostic and
then uses that to generate the output.  The new structure is easier
to customize if the diagnostic information is to be displayed in a
format different from what we provide by default.  The new mechanism
uses a different method of wrapping long lines.  Specifically, it now
breaks lines on spaces that occur within fill-in entries.  It also
fixes a bug that caused lines to often wrap before they should have.

Formerly, the diagnostic routines produced their output immediately
when called, so it was possible to pass in the address of a local
buffer as a string fill-in.  Now, the pointer is saved and used later,
so a local buffer or a buffer that might be overwritten must be
copied before being passed to the diagnostic routines.

Command-line errors that are passed to str_command_line error must now
have explicit %s fill-ins.  This also means that the fill-in can be
located anywhere (formerly, the string was just appended to the end
of the message).  There is also a new %d fill-in for numeric values.


3/10/15  [EDGcpfe/16077]
C++14 compatibility: "deprecated" attribute

The "deprecated" attribute is accepted by the front end in GNU and Microsoft
emulation modes as well as C++14 mode, but when configured with both
GNU_EXTENSIONS_ALLOWED and MICROSOFT_EXTENSIONS_ALLOWED set to FALSE,
the attribute was inadvertently unrecognized in C++14 mode.  Now fixed.
This example had not elicited a warning with --c++14 when
GNU_EXTENSIONS_ALLOWED and MICROSOFT_EXTENSIONS_ALLOWED were both FALSE (and
now does):

  int f([[deprecated]] int x) {
    return x;
  }
  int main() {
    return f(0);
  }


3/10/15  [EDGcpfe/16025]
Volatile class fields and bitwise copyability (ABI Change)

A field of a volatile class type T cannot be copied with a generated copy
constructor since that constructor would have a "T const&" or "T&" parameter.
The enclosing class is therefore not trivially copyable.  Previously, the
front end therefore marked the class as not bitwise copyable.  Unfortunately,
that has ABI implications in the sense that a function taking such a class by
value will really pass the class via a pointer.  For example (C++11 mode):

  struct T {};
  struct S { volatile T v; };  // S is not trivially copyable.  Now, however,
                               // it is still treated as "bitwise copyable".
  static_assert(!__is_trivially_copyable(S), "Unexpected!");
  void g(S) {}  // Previously, the lowered g passed its parameter via a
                // pointer because S was considered not to be bitwise
                // copyable.  Now, S is considered bitwise copyable and the
                // lowered function type passes the parameter by value.

With version 4.10 of the front end, g(S) cannot be called because the copy
constructor of S is deleted (in C++11 mode) or the call triggers the
generation of the copy constructor's definition which triggers an error
(since S::v cannot be copied). However, some earlier versions of the front
end did permit g(S) to be called.  In particular, versions 4.7 through 4.9
allowed such calls and pass the class type argument via a pointer, which
means those versions were affected by this ABI bug/incompatibility.


3/9/15  [EDGcpfe/16030,EDGcpfe/16074]
Microsoft/Clang/GNU compatibility: __func__

In Microsoft C and C++ modes with microsoft_version >= 1900, the front end now
accepts the __func__ construct to obtain the name of the enclosing function
(see the entry of 10/7/00).  In addition, a change was made to the string
produced for __func__ in GNU and Clang C++ modes: It no longer includes the
parent class name in the case of a member function (and that is also true in
Microsoft mode).  For example:

  struct S {
    char const* f() { return __func__; }
  } s;  // s.f() produces a pointer to "f" in Microsoft, GNU, and Clang C++
        // modes.  It produces "S::f" in default and strict modes.


3/9/15  [EDGcpfe/16056]
Copies of a_constant not allocated in IL memory

Various places in the front end previously used local copies of a_constant
for various reasons.  If such an object was passed as the source constant
in copy_constant_full, it was necessary to pass the options value
CE_SRC_CONSTANT_IS_NOT_ALLOC_IN_IL to prevent attempting to copy a flag
from the (nonexistent) IL entry prefix that precedes all entries allocated
in IL memory.  Failure to do so could result in segfaults and other
unpredictable results.

Because this mechanism was fragile and error-prone, particularly in light
of constexpr processing where it was difficult or impossible to track
whether a given a_constant entry was allocated in IL memory or was a local
variable, local a_constant variables are no longer used in the front end.
Instead, scratch a_constant entries are requested using the new function
local_constant and recycled via the release_local_constant function.  As an
optimization, in cases when a local constant would have been passed to
alloc_unshared_constant, a new function move_local_constant_to_il can be
called to use the local constant directly in the IL if possible or to make
a copy if necessary.  In CHECKING configurations, an end-of-processing
check is made that calls to local_constant and release_local_constant or
move_local_constant_to_il are balanced.  In addition, in configurations
with EXPENSIVE_CHECKING set to TRUE, a check is made when accessing an IL
entry prefix that the entry actually is allocated in IL memory.  For
example, code that was previously structured as

  { a_constant c;
    /* Use c as an object. */
  }

should now be written as

  { a_constant_ptr c = local_constant();
    /* use c as a pointer. */
    release_local_constant(&c);
  }

and code that was previously

  { a_constant c;
    /* ... */
    IL_ptr = alloc_unshared_constant(&c);
  }

should now be

  { a_constant_ptr c = local_constant();
    /* ... */
    IL_ptr = move_local_constant_to_il(&c);
  }


3/9/15  [EDGcpfe/16067]
Invalid IL generated when lowering zeroed _Complex member

In configurations where LOWER_COMPLEX is TRUE and a dik_zero initialization
is used to initialize a _Complex object, invalid IL had been generated.
This is now fixed.  The example below (with --g++) had generated invalid C
code in C-generating back end configurations:

  struct C {
    _Complex float c;
    C() : c() {}
  };
  C a;


3/6/15  [EDGcpfe/16066]
Clang compatibility: aggregate initialization of _Complex in C mode

The clang compiler allows aggregate initialization of a _Complex variable
in C mode (though GNU does not).  Previously this had caused an assertion
failure (in lower_c99_constant).  For example (with --c --clang):

  _Complex float x = { 1.0f, 1.0f };  // Now accepted in Clang C mode.


3/6/15  [EDGcpfe/16069]
Build problem when ABI_COMPATIBILITY_VERSION < 402

As a result of the changes for EDGcpfe/14701, attempting to build the
front end in certain configurations where ABI_COMPATIBILITY_VERSION < 402
could cause a compilation error in lower_name.c.  Now fixed.


3/6/15  [EDGcpfe/14687]
C++14: Sized global deallocation

The front end now implements the C++14 sized global deallocation feature as
described in N3778.  Two new global operator delete functions are pre-defined:
operator delete(void*, size_t) and operator delete[](void*, size_t).  In
the following case, the sized deallocation function is now chosen (with
--c++14), resulting in "global sized" being printed:

  extern "C" int printf(const char *,...);
  void operator delete(void *) {                    // Previously selected
    printf("global\n");
  }
  void operator delete(void *, __EDG_SIZE_TYPE__) { // Selected with --c++14
    printf("global sized\n");
  }
  int main() {
    int *p = new int;
    delete p;
    return 0;
  }

Note that the __cpp_sized_deallocation feature test macro is used in the
runtime library and in new.stdh to conditionally compile support for this
feature and as a result, the feature-test macros must be enabled when building
the runtime library.  Additionally, the --c++14 command-line option must
be specified when building the runtime library (when
RUNTIME_SUPPORTS_SIZED_DEALLOCATION is TRUE).


3/5/15   [EDGcpfe/15227]
Clang/GNU compatibility: Virtual generated destructors and virtual bases

In Clang C++ mode and in GNU C++ modes with gnu_version < 40900, the front end
now forces the definition of a virtual implicitly-generated destructor for a
class X if that class has a virtual base class and is itself a direct or
indirect nonvirtual base class of a derived class whose virtual function table
will be emitted if lowering is enabled.  (This only applies to the IA-64 ABI.)
For example:

  struct A { virtual ~A(); };
  struct B1 : virtual A {};
  struct B2 : virtual A {};
  struct C1 : B1 { virtual ~C1() ;  };
  struct C2 : B2 { virtual ~C2() ;  };
  struct D : C1, C2 { virtual ~D(); };
  D::~D() {}

Here, the definition of the "decider" function D::~D() of class D would trigger
the emission of D's virtual function table if lowering were enabled.  The base
classes B1 and B2 each have a virtual base class and a generated virtual
destructor: Those generated destructors are now defined in this translation
unit in Clang mode and in some GNU C++ modes.


3/4/15   [EDGcpfe/16065]
GNU compatibility: builtin function signatures

Tracking the function signatures of the GNU builtins has always been a
difficult process as the functions sometimes have different signatures than
what is documented, and the signatures occasionally change from one version of
GNU to another.  To help in this process, an automated script has been
written to extract the definitions from sys_predef.c and generate test cases
for each builtin definition.  With the help of this automated testing process,
we've made a number of changes to function signatures as well as ensuring that
builtins are only available in the appropriate GNU emulation modes (there were
a number of builtins that had been available in the EDG front end but were not
actually available in the corresponding GNU compiler).  This should align the
front end much better with the actual behavior of recent GNU compilers.


3/4/15   [EDGcpfe/16057]
Clang compatibility: Explicit declaration of type_info

Using the typeid operator without including the standard header <typeinfo> is
ordinarily an error.  The front end assumes that the <typeinfo> header has
been included if the standard type_info type is defined.  Clang, however,
only requires that the type is declared; not defined.  For example (assuming
DEFAULT_TYPE_INFO_IN_NAMESPACE_STD is configured to FALSE):

  struct type_info;  // Declared but not defined.
  namespace std { using ::type_info; }
  struct S { virtual ~S(); } s;
  std::type_info const &ti = typeid(s);  // Now accepted in Clang mode.

This case is now accepted in Clang mode (but still an error in other C++
modes).


3/2/15   [EDGcpfe/16046]
Prototype instantiations of exception specifications of member templates

The front end previously erroneously performed a prototype instantiation of
the exception specification of a member function template when doing a real
instantiation of the enclosing class template.  This could result in premature
errors (i.e., errors that only should be issued if the member template is
really used).  For example:

  template<class T> struct X {
    X();
    template<class U> X(U) noexcept(noexcept(T().x())) {}
  };
  X<int> d;  // Previously triggered a spurious error about T() not having
             // a class type.  Now okay.

This is now fixed.


3/2/15   [EDGcpfe/16045]
Floating-point bound in array new-expression

The first array bound in a new-expression (the one that can be non-constant)
can now have a floating-point type in Microsoft C++ mode and in C++14 modes.
For example:

  int *p = new int[1.0]; // Now accepted in C++14 and Microsoft modes.

The C++14 change is a result of a language change introduced by the C++
standards committee's paper N3323.


2/27/15  [EDGcpfe/16056]
Accessing the IL prefix of IL entities that were not allocated

When an IL entity is allocated, a small portion of memory that precedes the IL
entity itself (the entity prefix) is used for various housekeeping tasks.
In some cases the front end uses structures that are typically used for
IL entities, like a_constant, on the stack rather than as part of the IL
itself.  In such cases, the front end must not attempt to access the prefix
of these entities (as they will likely point to unrelated items on the stack).
A number of these cases were identified and have now been fixed.

To prevent future instances, a check is now made when requesting the address of
a prefix for an IL entity to ensure that the entity has indeed been allocated
(only when EXPENSIVE_CHECKING is TRUE).

In some instances, the following example had resulted in an unlowered
ck_complex constant, which had caused an assertion failure (in dump_constant)
in configurations where LOWER_COMPLEX is TRUE (with --g++):

  struct C {
    union {
      int a;
      int b;
    };
    _Complex float c;
    C() : c(){}
  };
  C x;


2/26/15  [EDGcpfe/16037]
GNU compatibility: accept the abi_tag attribute on inline namespaces

g++ 5.0.0 accepts the abi_tag attribute on inline namespaces, and now
so does the front end.  At the current time, no action (other than recording
the attribute) is taken.  See also the Changes entry for EDGcpfe/15897.
For example (with --gnu_version 50000):

  inline namespace __cxx11 __attribute__((abi_tag)) { }


2/26/15  [EDGcpfe/16014]
GNU compatibility: corrected function signatures for __atomic builtins

A number of errors were found in the function signatures for the following GNU
builtin functions: __atomic_load, __atomic_store, __atomic_exchange,
__atomic_compare_exchange, __atomic_store_1, __atomic_exchange_1,
__atomic_compare_exchange_1, __atomic_store_2, __atomic_exchange_2,
__atomic_compare_exchange_2, __atomic_store_4, __atomic_exchange_4,
__atomic_compare_exchange_4, __atomic_store_8, __atomic_exchange_8,
__atomic_compare_exchange_8, __atomic_store_16, __atomic_exchange_16, and
__atomic_compare_exchange_16.  Now fixed.


2/25/15  [EDGcpfe/16013]
C++-generating back end: qualified names of members of named inline namespaces

The change for EDGcpfe/15043, included in version 4.10, erroneously
suppressed qualification when forming the names of members of named inline
namespaces, which could result in incorrect generated code.  This is now
fixed.  For example, with --c++11:

  namespace N {
    inline namespace M {
      template<typename T> struct S;
    }
    template <typename T> struct M::S {  // Previously omitted "M::", thus
      void f();                          // defining N::S, not N::M::S...
    };
    template<> void S<int>::f();         // ...and making S ambiguous here
  }


2/25/15  [EDGcpfe/16018]
C++-generating back end: typedef members of template instances first
referenced with inaccessible arguments

The C++-generating back end previously considered a typedef member of a
template instance to be inaccessible if the first reference to that
instance used an inaccessible type name as a template argument, even if
that argument could be specified using an accessible type name.  As a
result, the generated output sometimes inappropriately used the underlying
type of the member typedef, even if the name of that type was inaccessible.
This is now fixed.  For example:

  struct A {
  protected:
    static int f();
  };
  template<typename T> struct B : A {
    typedef decltype(f()) fT;  // fT is public
  };
  class C {
    typedef int CT;
    typedef B<CT> BCT;  // B<int> first instantiated using private argument
  };
  B<int>::fT b;  // Previously generated as "decltype((f())) b"


2/24/15  [EDGcpfe/16044]
C++-generating back end: defaulted function template declarations

A defaulted function template declaration was not represented properly
in the string representation of templates, resulting in incorrect
C++-generating back end output.  In addition, the trailing ";" was
omitted.  Now fixed.

  template < typename T> struct A {
    A(){}
  };
  // Formerly emitted as "... = default = default"
  template <typename T> A<T>::A(const A&) = default;


2/23/15  [EDGcpfe/16043]
Runtime control of feature-test macro definitions

Whether or not the standard feature test macros (see EDGcpfe/14634) are
defined was previously determined by a configuration macro,
DEFINE_PORTABLE_FEATURE_TEST_MACROS.  This has now been changed to depend
instead on the value of the global variable
define_portable_feature_test_macros so that it can be controlled at the
time the front end is run instead of only when it is built.


2/23/15  [EDGcpfe/15753]
C++-generating back end: qualification of members of nonreal classes

In C++-generating back end configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, a qualified reference to a
nonstatic data member of a nonreal class was generated using an unqualified
name.  This is now fixed.  For example:

  struct A { int i; };
  template<typename T> struct B : T {
    void g() {
      this->A::i = 3;  // Previously generated as this->i
    }
  };


2/20/15  [EDGcpfe/15591]
Variadic deduction failure with non-variadic template template argument

A deduction failure could occur if a template with a non-variadic
template parameter was passed to a template template parameter with
a template parameter list that was variadic.  For example, the case below
resulted in spurious "no instance ... matches" errors, but was accepted
if the commented-out ellipses were present.  Now fixed.

  template <template <class /*...*/> class T> class A  {};
  template <template <class /*...*/> class... T> class B {};
  template <template <template <class...> class...> class T> void f(){}
  int main() {
    f<A>();
    f<B>();
  }


2/20/15  [EDGcpfe/15544]
Variadic deduction failure with explicitly specified template template argument

A deduction failure could occur when a non-variadic template was used as
an explicit template argument for a template template parameter with a
variadic parameter list.  Now fixed.

  template< class T > T&& f( T& t );
  template <class T1, class T2> struct A {
    A(T1,T2);
  };
  template <template <typename...> class TTP, typename... Args>
  TTP<Args...> g(Args &&... args) {
    return TTP<Args...>(f<Args>(args)...);
  }
  int main() {
    g<A>(1, 2);
  }


2/20/15  [EDGcpfe/15849]
C++-generating back end: Missing function template default argument when
using CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE,
and when prototype instantiations are used to generate template definitions
in the C++-generating back end, the code generated for an instantiation
of a class template omitted default arguments of function templates.

So, for a class such as:

  template<typename T> struct A {
    template<typename U> A(U, const T& = T());
  };
  A<int> a('x');

The class generated for the instantiation of A<int> must look like:

  template<> struct A< int>  {
    template< class U> A(U, const int & = ((int)0));
  };

The default argument had been missing from the declaration of A<int>::A.
Now fixed.


2/19/15  [EDGcpfe/16036]
clang compatibility: empty argument to __has_feature/__has_extension

The clang compiler treats an empty argument to the __has_feature and
__has_extension built-in macros as an error.  The front end previously
failed to diagnose this error and inadvertently treated such an argument as
a test for support of Unicode literals, for which clang has no feature
name.  This is now fixed.  For example, with --clang:

  #if __has_feature()  // Now diagnosed as an error
  #endif


2/19/15  [EDGcpfe/16029]
Incorrect checking code in equiv_template_arg_lists

A bug in some checking code added to equiv_template_arg_lists in version 4.10
could, in theory, result in a spurious internal error, although no actual
cases have been encountered at this time.  Now fixed.


2/18/15  [EDGcpfe/16001]
Microsoft C++ compatibility: Access checking in decltype(...) constructs

In Microsoft mode, the front end does not by default treat access errors
during template argument deduction as mere deduction failures (i.e., so-called
SFINAE behavior); instead, they are ordinary errors.  However, it does now
treat access errors occurring within decltype constructs in return types of
member functions in that way.  For example:

  class P { P& operator=(int); };  // P::operator= is private.
  struct S {
    template<typename T> static auto f(T)->decltype((T() = 0), 1);  // (1)
    static auto f(...)->int;                                        // (2)
    using type = decltype(f(P()));
  };

Previously, this example triggered an access error while considering the
candidate (1) for the call f(P()).  Now, the candidate is simply discarded in
favor of candidate (2).

The changes for this also affect the behavior described for EDGcpfe/12708.
E.g., modifying the example in the Changes entry for EDGcpfe/12708 as follows
(to place the access error in a decltype construct), now produces an error
again:

  struct A {
    template <class T> static decltype(typename T::X()) f(T);
  };    
  class B {
    typedef int X; 
  };  
  int main() {
    B b;
    A::f(b); 
  } 

(i.e., the disabling of access errors described in EDGcpfe/12708 no longer
applies in the decltype context).


2/18/15  [EDGcpfe/7107, EDGcpfe/16198]
Core issue 429: Diagnose non-placement delete used for placement new

Core issue 429 specifies that a diagnostic should be issued when a
two-parameter form of a usual deallocation function is used for a placement
new operation.  That is now implemented (except in GNU emulation mode).
For example (with -x):

  struct S {
    static void* operator new(__EDG_SIZE_TYPE__, __EDG_SIZE_TYPE__);
    static void operator delete(void*, __EDG_SIZE_TYPE__);
  };
  S* p = new (0) S; // Now ill-formed: non-placement deallocation function
                    // matches placement allocation function.


2/16/15  [EDGcpfe/15970]
Abort with constexpr base class pointer cast

The front end previously aborted with a failed assertion (in fold_expr) on
attempting to cast a derived class object pointer to a pointer to one of
its bases in a constexpr context.  This is now fixed.  For example (with
--g++ --c++11):

  class Base { };
  struct Derived : public Base {};
  struct Nested : public Derived {
    static constexpr Base* f() { return &n; }  // Previously aborted
    static Nested n;
  };

  void f() {
    Nested::f();
  }


2/15/15   [EDGcpfe/15612]
Dependent expressions in constant contexts

The front end previously issued a spurious "must have a constant value"
error for some expressions involving dependent values in template
definitions.  This is now fixed.  For example, with --g++ --c++11:

  enum Test {
    E = 0
  };

  constexpr Test operator&(const Test lhs, const Test rhs) {
    return static_cast<Test>(static_cast<int>(lhs) & static_cast<int>(rhs));
  }

  template<Test TEST> struct C {
    static const Test value = TEST & Test::E;  // Previously an error
  };


2/14/15   [EDGcpfe/15647]
Abort with constexpr base class cast on explicit temporary

The front end previously aborted with a failed assertion (in fold_expr)
when processing a base-class cast applied in a constexpr context to an
explicit temporary.  This is now fixed.  For example, with --g++ --c++11:

  struct A {
    constexpr operator int() {
      return 0;
    }
  };

  struct B : A { };

  template <class T> void f() {
    constexpr int i = B();   // Previously aborted on cast from B to A
  }

  void g() {
    f<int>();
  }


2/13/15   [EDGcpfe/14028,EDGcpfe/15990]
Incorrect cast to variably-sized type in lowered IL

In cases where the result of a variably-sized "new" operator is partially
initialized with values whose type includes a function with a parameter
passed by a copy constructor, lowering had added an incorrect cast which had
caused an assertion (in dump_expr).  The incorrect cast had resulted in an
eok_bassign operation whose source size is zero, possibly causing a back end
to omit the assignment altogether.  For example (with --c++11):

  struct A {
    A(const A&);
  };
  template <class T> using B = void (*)(T);
  void f(int i) {
    new B<A>[i] { {} };
  }


2/13/15   [EDGcpfe/15656]
Spurious error on "::template" in GNU and Microsoft modes

The changes for EDGcpfe/9422 (GNU mode) and EDGcpfe/12785 (Microsoft mode)
introduced a regression in cases where "::template" is followed not by a
simple identifier, but by "operator" and some additional tokens forming the
generalized identifier.  For example:

  struct X { template<typename> void operator()() {} };
  template <typename T> void f() {
    void (T::*pmf)() = &T::template operator()<int>;  // (*)
  }
  template void f<X>();

Previously, the line marked (*) was incorrectly parsed, leading to syntax
errors.  This is now fixed.


2/13/15   [EDGcpfe/16019]
Lowered type_kind for tk_nullptr

During the lowering process, tk_nullptr is lowered to "void *", but the
type_kind field of an expression had not been lowered.  The field is now
lowered (to tk_pointer).  For example (with --c++11)

  void f() {
    auto&& x = nullptr;
  }


2/12/15   [EDGcpfe/15707]
Clang/GCC compatibility: Default constructors of unions with NSDMIs

Ordinarily, in C++11 mode the generated default constructor of a union (or a
class with an anonymous union) is "deleted" if it has a nonstatic data member
whose type has a nontrivial default constructor.  For example:

  struct N { N(); };  // Type with nontrivial default constructor.
  union U {
    N n{};  // Nonstatic data member initializer.
  } u;

This is normally an error since the initialization of the variable u
implicitly uses the deleted default constructor of U.  In GNU and Clang C++
modes, however, the front end does not mark U's constructor as deleted because
the field requiring nontrivial initialization includes a nonstatic data member
initializer (NSDMI).


2/12/15   [EDGcpfe/16002]
Conversion function template to "reference to abstract class"

Previously, when considering user-defined implicit conversions, the front end
accidentally discarded conversion function templates whose destination type is
a reference to a complete abstract class.  For example:

  template<typename T> struct A { virtual ~A() = 0; };
  template struct A<int>;  // Ensure A<int> is complete.
  struct W {
    template<typename T> operator A<T>&();
  } w;
  int g(A<int>&);
  int r = g(w);  // Previously an error because the conversion template was
                 // incorrectly discarded.  Now okay.

This is now fixed.


2/11/15   [EDGcpfe/16010]
Dependent expressions in constant contexts

The front end previously incorrectly rejected some expressions appearing in
constant contexts in template definitions as not having a constant value if
they involve dependent values.  This is now fixed.  For example, with
--c++11:

  template <int I> struct Int { };

  template <int I, int J>
  constexpr int operator+(Int<I> lhs, Int<J> rhs) { return I + J; }

  template <int I, int J>
  struct Sum : Int<Int<I>() + Int<J>()> { };  // Previously a spurious error


2/11/15   [EDGcpfe/9000]
"bit field" vs. "bit-field" in diagnostics

The diagnostics file that comes with the front end (error_msg.txt) almost
consistently uses the term "bit field", but one instance was written
"bit-field" instead (ec_unsigned_enum_bit_field_with_signed_enumerator).  That
one instance has now been changed to "bit field" also.


2/9/15   [EDGcpfe/15988]
Use of an unevaluated "this" in a non-capturing lambda

The front end previously required "this" to be captured for uses of "this" in
an unevaluated context within a lambda.  For example, in C++11 mode:

  struct S {
    unsigned f() {
      return []{ return sizeof(i); }();  // Previously an error because
    }                                    // i requires access to "this", but
    int i;                               // "this" is not captured.
  };

This is now fixed.

Prior to the changes for EDGcpfe/15384,EDGcpfe/15386 (see entry of 9/4/14) the
front end did (accidentally) accept cases like the above when the lambda
appears in a nonstatic data member initializer.  In that sense this fixes a
regression.  For example:

  struct F {
    int i = []{ return decltype(i)(); }();  // Accepted in version 4.9, but
  };                                        // not 4.10.  Now accepted again.


2/6/15   [EDGcpfe/15987]
Abort with template-dependent using-declaration of member operator new

In configurations with NEW_CAN_BE_FOLDED_INTO_CTOR set to TRUE, a class that
contains a using-declaration for an operator new from a template-dependent base
class could abort while processing the definition of one of its constructors
(the abort was an internal error in set_overload_set_traversal_symbol).  For
example:

  template<typename> struct M {
    static void* operator new(__EDG_SIZE_TYPE__);
  };
  template<typename T> struct I: M<T> {
    using M<T>::operator new;
    I() {}  // Previously triggered an internal error.
  };

This is now fixed.


2/6/15   [EDGcpfe/15895]
Cross-reference output and generated member templates

As was already the case with generated member functions the front end now no
longer outputs cross-reference declaration/instantiation information for
generated member templates that have no direct source representation
(specifically, member templates declared in the closure types of C++14
generic lambdas that implement an implicit conversion to a pointer-to-function
type).  Uses of such generated members are still output, however.


2/6/15   [EDGcpfe/15985]
Current line number within the file being read

The value of curr_ise->actual_line should always reflect the current line
number within the physical file being processed, i.e., ignoring the effect
of #line directives.  However, the changes in version 4.10 for
EDGcpfe/15187 resulted in that value not being updated correctly when #line
directives are present.  This is now fixed.


2/5/15   [EDGcpfe/15978]
Mangling of "auto" and "decltype(auto)" return types in function names

The previous change to provide mangling for "auto" and "decltype(auto)" (see
EDGcpfe/15930 and EDGcpfe/15939) was somewhat overzealous and also mangled a
deduced return type in a function name.  That caused problems in examples like
the one below where the two instances of f1 had been given the same mangled
name (i.e., one with the mangling for "auto" rather than "int" and "double").
With --c++14:

  template <class T> auto f1(T x) { return x; }
  template <class T> auto f2(T x) { return x; }
  int main() {
    f1(f2(0));
    f1(f2(0.0));
    return 0;
  }


2/5/15   [EDGcpfe/15980]
Internal error in generic lambda with attribute on parameter

An internal error could occur (in process_generic_lambda_param_type) if
a complex attribute followed a generic lambda parameter.  Now fixed.

  void f() {
    [ ] ( auto & a [[some_attr([[f([[]])]])]] , auto (*fp) ( float ) ) { } ; 
  }


2/5/15   [EDGcpfe/15920]
Allow "typename" to declare a template template parameter

Because alias templates can be used as template template arguments, the
syntax for declaring template template parameters now allows the use
of the "typename" keyword.  This is a result of the proposal from the
committee paper N4051.  We now allow the "typename" keyword to be used
in C++14 mode, and also in non-strict mode for older dialects.

  template <template <typename> typename X> struct A;


2/5/15   [EDGcpfe/15964,EDGcpfe/15965]
Assertion failures in lowering during initialization of aggregate array

Various assertion failures ("lower_dynamic_init_aggregate_constant: repeat on
non-array", "lower_dynamic_init_aggregate_constant: bad aggr kind",
"lower_dynamic_init_aggregate_constant: have constant, no field") had occurred
when lowering repeated dynamic initialization of certain aggregates in C++14
mode.  Now fixed.  For example (with --c++14):

  struct A {
    struct B {
      int y = f();
      int f() {return 10;}
    };
    B b{};
  };
  A a[2]{};


2/5/15   [EDGcpfe/15952]
Generic lambdas and source sequence entries for instantiations

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured to
TRUE, the front end previously attempted to generate source sequence entries
for the instantiations of the member function templates implied by generic
lambdas.  This often triggered an abort in find_innermost_namespace_scope_depth
and when it didn't, the resulting code generated by the C++-generating back
end was invalid.

The front end now no longer attempts to generate source sequence entries for
such generated templates.


2/4/15   [EDGcpfe/15967]
Invalid IL for routine with deduced return type declared inside itself

In C++14 mode, a routine definition like the following is possible:

  auto g() {
    auto g();
    return 42;
  }

The front accidentally discarded the deduced return type of the function in
such cases.  The result invalid IL could then lead to aborts later on (e.g.,
during the IL lowering process, which does not expect to see undeduced return
types).


2/4/15   [EDGcpfe/15973]
Spurious error on in-class initializer for static array member in template

In C++11 mode, a static array data member can have an in-class initializer,
but the front end issued a spurious error in such cases if the underlying
array element type is a template parameter.  For example:

  template<typename T> struct S {
    static constexpr T x[2] = { 1, 2 };  // Previously a spurious error in
  };                                     // C++11 mode -- now okay.

This is now fixed.


2/4/15   [EDGcpfe/15923]
Microsoft compatibility: invalid pasting in arguments to nested macros

The C and C++ Standards require that when a macro parameter is used as the
operand of a ## (paste), the unexpanded version of the macro argument is
used.  The Microsoft preprocessor, however, generally uses the expanded
version of the argument in such contexts.  One exception to this pattern
occurs when the parameter is pasted to a preceding identifier; in that
case, the Microsoft preprocessor uses the unexpanded version of the argument
(see EDGcpfe/13024).

Another exception occurs when the parameter is pasted to a preceding "(" or
"," (which is invalid according to the Standards, since the result cannot
form a single preprocessing token) and that character precedes the start of
a macro argument in the replacement text.  In this case, the decision
regarding whether to use the expanded or unexpanded version of the original
argument is determined by whether the nested macro uses its parameter in a
paste operation or not.  If it does, the unexpanded version of the original
argument is used; otherwise, the expanded version is used as usual.  The
front end has now been changed to emulate this behavior in Microsoft
compatibility modes.  For example, with --microsoft:

  #define M2(M,X)      M(##X)
  #define with_concat(X)   yy_ ## X
  #define without_concat(X) yy X
  #define M4  xxx
  M2(with_concat, M4);      // Expands to: yy_M4 (argument M4 not expanded)
  M2(without_concat, M4);   // Expands to: yy xxx (argument M4 is expanded)


2/4/15   [EDGcpfe/15976]
Invalid handling of function differing only in auto/decltype(auto) return type

When function declarations differ only in that one return type is "auto" and
the other "decltype(auto)", the front end previously erroneously treated those
as declaring the same function.  For example:

  auto f();
  decltype(auto) f();  // Previously accepted as a redeclaration in C++14 mode,
                       // now an error because only the return type differs.

This is now fixed.


2/4/15   [EDGcpfe/15974]
Invalid decltype(auto) use not diagnosed in deduced return types

The C++14 decltype(auto) type specifier cannot be combined with a pointer,
reference, or pointer-to-member declarator operator.  The front diagnosed this
for variable declarations, but not for deduced return types.  For example:

  decltype(auto)& f();  // Previously went undiagnosed in C++14 mode.

This is now fixed: An error is issued in such cases.


2/3/15   [EDGcpfe/15963]
Assertion failure during lowering of multidimensional arrays

An assertion failure ("lower_aggregate_designated_initializers: type mismatch")
had occurred in certain cases when lowering multidimensional arrays that
have at least three dimensions and the last two dimensions both have a
single element.  For example (with --c++14):

  struct A {
    struct B {
      int y = 37;
    } a[2][1][1] {};
  };
  struct C : A {
    union {
      char a;
      int x = 37;
    };
  };
  int main() {
    return C().x != 37;
  }


1/30/15  [EDGcpfe/15951]
Diagnostics for lambdas

The readability of diagnostics for lambdas (generic lambdas in particular) has
been improved.  For example, a diagnostic that previously read

  "t1.c", line 7: warning: variable "y" was declared but never referenced
            int y = a;
                ^
            detected during instantiation of "lambda
                      [](auto)->auto::operator()(auto)->auto [with
                      <unnamed>=int]" at line 11

is now rendered as

  "t1.c", line 7: warning: variable "y" was declared but never referenced
            int y = a;
                ^
            detected during instantiation of function
                      "lambda [](auto)->auto [with <auto-1>=int]" at line 11


1/29/15  [EDGcpfe/15942]
Lowering of multidimensional arrays with qualified element types

A regression (introduced in 4.10) caused an assertion failure (in
handle_multidimensional_ck_init_repeat) when lowering a repeated aggregate
constant with an underlying qualified element type.  Now fixed.  For example
(with --gcc):

  const char x[16][2] = {
     [0 ... 15] = "xy"
  };


1/28/15  [EDGcpfe/15940]
Variadic arguments to alignas

The front end now permits variadic template parameter expansion in alignas
constructs.  The C++11 standard describes syntax for this, but failed to
provide semantics (that is Core issue 1706).  Recent committee discussions
indicate that the semantics should be equivalent to repeating the construct
with individual arguments and that appears to be existing practice.
For example, in C++11 mode:

  template<typename...T> struct S {
    alignas(T...) char buffer[100];  // Now accepted.
  };
  S<int, long, float> s;


1/28/15  [EDGcpfe/15939]
Mangling support for decltype(auto)

Mangling support has been added for "decltype(auto)".  In IA-64 ABI
configurations the string "Dc" is now used; the EDG-specific string "q" is used
in Cfront ABI configurations.  Previously, the mangling for "auto" had
been used (and continues to be used when ABI_COMPATIBILITY_VERSION < 411).
For example (with --c++14):

  template <class T> auto f(T t) -> decltype(auto) { return t; }
  int main() {
    return f(0);
  }


1/28/15  [EDGcpfe/15930]
Mangled encoding for "operator auto()"

Previously, the mangled encoding used for an "operator auto" conversion
function was that of the deduced type, now the mangled encoding for deduced
"auto" types is used (i.e., "Da" in the IA-64 ABI and "u" in the Cfront ABI).
The change is conditional on ABI_COMPATIBILITY_VERSION >= 411.  Prior to this
change, an "operator auto()" conversion function that had returned a local
type would generate an infinite recursion.  For example (with --c++14):

  struct A {
    operator auto() {
      struct B {};
      return B();
    }
  };


1/27/15  [EDGcpfe/15897]
GNU compatibility: support for abi_tag attribute

Support has been added for the "abi_tag" attribute in g++ compatibility modes
when gnu_version >= 40800.  The abi_tag attribute is described here:
https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/C_002b_002b-Attributes.html.
In the IA-64 ABI, the front end uses the GNU-specific mangling to encode
the names of the abi_tag attributes (namely as a suffix following "B").  The
"__ab" prefix is used for the same purpose in the Cfront ABI.  Note that only
narrow string literals are accepted as arguments to the abi_tag attribute.
For example (with --gnu_version 40800):

  template <class T> __attribute((abi_tag("foo"))) void f1();
  template <class T> struct __attribute((abi_tag("foo"))) A {
    void f1();
    void __attribute((abi_tag("bar"))) f2();
  };
  int main() {
    A<int> a;
    f1<int>();  // Cfront: __ab3foof1__tm__2_i__Fv_v
                // IA-64:  _Z2f1B3fooIiEvv
    a.f1();     // Cfront: f1__18__ab3fooA__tm__2_iFv_v
                // IA-64:  _ZN1AB3fooIiE2f1Ev
    a.f2();     // Cfront: __ab3barf2__18__ab3fooA__tm__2_iFv_v
                // IA-64:  _ZN1AB3fooIiE2f2B3barEv
  }


1/27/15  [EDGcpfe/15659]
Null-pointer values in non-type template arguments

In C++11 mode and in Microsoft C++ modes with microsoft_version >= 1800, the
front end now permits more cases of null pointer values in non-type template
arguments.  For example, in C++11 mode:

  template<class> struct Trait { using type = void; };

  template<typename T, typename Trait<T>::type* = nullptr>
  void ft(T*);
 
  void g(double *p) {
    ft(p);  // Previously failed to match because the conversion of the
  }         // default nullptr argument was not permitted.


1/26/15  [EDGcpfe/15782]
Generalized constant-expressions in non-type template arguments

The front end previously didn't always accept constant-expressions resulting
from calls to constexpr functions in template arguments, even in cases where
C++11 permits them.  For example, in C++11 mode:

  struct S {};
  constexpr int one(S const&) { return 1; }
  template<int I> void g() {};
  int main() {
    g<one(S())>();  // Previously triggered a spurious error.  Now okay.
  }

This is now fixed.


1/23/15  [EDGcpfe/15931]
Abort on foldable C++11-mode logical operator with destructible operand

The changes for EDGcpfe/14139 introduced a regression in C++11 mode that
manifested itself in some cases involving a logical operator (&& or ||) that
is foldable because its first operand is a constant allowing the short-
circuiting of the second operand's evaluation, and that second operand would
otherwise have required a destruction.  The IL in some of those cases was
invalid (still recording the potential destruction), causing the IL lowering
process to abort later on.  For example:

  struct A {
    ~A();
    bool m;
  };
  struct B {
    B(bool);
    ~B();
  };
  template<class T> int operator&&(bool, T);
  void f(B) {
    f(false && A().m);  // Previously produced wrong IL and an abort
  }                     // during IL lowering.

This is now fixed.


1/23/15  [EDGcpfe/15917,EDGcpfe/15945]
Internal error on instantiation of nested generic lambda

An internal error could occur (in scope_depth_for_capture) during the
instantiation of a nested generic lambda.  In configurations without IL
lowering, the internal error could occur in finish_function_body_processing.
Now fixed.

  int main() {
    auto L = [](auto i) {
      return [=](auto j) {
        return [=]() {
          return i;  // internal error here
        };
      };
    };
    return L(3)(3)();
  }


1/23/15  [EDGcpfe/10791,EDGcpfe/15927]
GNU C compatibility: constant-valued variables in array dimensions

When gcc_const_variables_allowed is TRUE (see the Changes entry of 6/25/13 for
EDGcpfe/14216), constant-valued variables used in rvalue contexts are now
treated as constant-expressions in GNU C mode (previously, this was the case
only in some contexts).  For example:

  void g() {
    int const N = 10;
    int const M = N+1;  // N treated as a constant expression here.
    double x[M]; // Now equivalent to "double x[11];" in GNU C mode.
  }              // Previously, x was treated as a variable-length array.

This is a little more aggressive than GCC's actual behavior but it allows the
front end to accept more cases than GCC accepts (it also causes the front end
to accept the odd case that GCC does not accept).


1/21/15  [EDGcpfe/15925]
Line numbers in file tree structure reconstructed from #line directives

The changes in version 4.10 for EDGcpfe/15187 resulted in a tree of
a_source_file entries that corresponds to the pattern of inclusions
implicit in the #line directives produced by preprocessing the original
source and header files.  However, that tree structure was not suitable for
associating sequence numbers with the line numbers implied by the #line
directives.  This was reflected, for example, in the fact that the line
numbers calculated by find_seq_in_source_files (with the physical_line
parameter == FALSE) were different from the (correct) ones calculated by
find_seq_in_lookup_tables.  This has now been addressed by creating a new
sibling a_source_file entry for each new #line directive that names a given
file in order to represent the new mapping between sequence numbers and
line numbers for the subsequent range of lines.


1/20/15  [EDGcpfe/14602]
Accessibility of constructors and conversion functions

The front end sometimes failed to take into account the accessibility of
constructors and conversion functions when determining implicit convertibility.
For example:

  class X {
    X(int) throw () {}
    X& operator=(int) throw () { return *this; }
    X(X const&) = default;
    X& operator=(X const&) = default;
  };
  static_assert(!__is_convertible_to(int, X), "Unexpected!");
    // Previously, this assertion failed.  Now accepted.

Fixing this issue also required reworking the fix for EDGcpfe/9680, which
deals with accessibility checks in default arguments (see the entry of 4/2/09).


1/19/15  [EDGcpfe/15706]
Do not emit vtable as a result of explicitly-instantiated decider function

The front end emitted a vtable when a decider function was explicitly
instantiated.  Other compilers (g++, clang, Microsoft) don't do this,
so now we no longer do when the IA-64 ABI is used (it must be emitted in the
cfront ABI because the vtable won't be emitted elsewhere).  In the example
below, A<long long>::f is not instantiated (interestingly, Microsoft
instantiates that function even though they do not emit a vtable or code
for the function).

  template<typename T> struct A {
    virtual ~A() {}
    virtual void f();
    virtual void g();
  };
  template<typename T> inline void A<T>::f() {
     T t;
     some_undefined_function(t);  // cause error if instantiated
  }
  template <typename T> void A<T>::g() { }
  template void A<long long>::g();


1/16/15  [EDGcpfe/15894]
C++-generating back end and generic lambdas

When prototype instantiations are not recorded in the IL, the C++-generating
back end aborted when attempting to render a generic lambda.  This is now
fixed.  The fix involves recording a text form of the generic lambda (minus
the capture list) as is done with templates.


1/13/15  [EDGcpfe/15903]
Spurious error on use of certain type traits helpers

In modes that may involve generated deleted special member functions, the front
end sometimes emitted spurious errors when handling certain type traits helpers
like __is_assignable or __is_constructible.  For example:

  extern "C" int printf(const char*,...);
  template<typename> struct C { C(C&&); };
  static_assert(!__is_trivially_assignable(C<int>, C<int>), "Unexpected");
    // Previously triggered an error in C++11 mode.

This is now fixed.


1/13/15  [EDGcpfe/15899]
Bit-field layout when container size is smaller than container alignment

The front end sometimes incorrectly laid out a bit field whose container type
is an integer type with a size smaller than its alignment (this is unusual,
but can happen in some modes with alignment attributes).  Specifically, under
such circumstances a bit field could sometimes be placed in the "alignment
padding" of the prior container.  This is now fixed.


1/13/15  [EDGcpfe/15845]
Assertion failure in lower_param_ref

An assertion failure (in lower_param_ref) had occurred when lowering certain
aggregates in C++14 mode.  This is now fixed.  For example (with --c++14):

  struct B {
    int x = 37;
    int y = f();
    int f() { return x;}
  };
  struct A {
    B b {};
  } a;


1/13/15  [EDGcpfe/15871]
C++-generating back end: braces in arguments to initializer-list constructors

In C++11, an initializer-list constructor is one whose first parameter is a
specialization of std::initializer_list and having either no additional
parameters or default arguments for all additional parameters.  Such a
constructor can be invoked with a brace-enclosed list of values as a single
argument.  The C++-generating back end previously incorrectly added an
additional set of braces to the argument to such a constructor.  This is
now fixed.  For example, with --c++11:

  #include <initializer_list>
  struct S {
    S(std::initializer_list<int>);
  };
  int f(S);
  int i = f({1,2});  // Previously generated as f({{1,2}})


1/12/15  [EDGcpfe/14021]
IA-64 ABI: Missing exception epilogue on destructors with function try blocks

Destructors with function try blocks had not been lowered properly when using
the IA-64 ABI; the epilogue for exception handling had inadvertently been
omitted, resulting in undefined behavior at runtime.  The following code
had caused an assertion failure in the runtime library (throw.c) when using the
C-generating back end (with -x):

  struct A {
    ~A() try {} catch (...) {}
  };
  int main() {
    try {
      A a;
      throw -59;
    }
    catch (...) {
      return 0;
    }
    return 1;
  }


1/12/15  [EDGcpfe/15854]
Block-extern function redeclarations and deducible return types

When a block-extern declaration is a declaration of a function previously
defined with a deducible return type, the front end previously failed to imbue
the deduced return type on the local declaration.  This resulted in invalid IL
for expressions referring to the local declaration.  That invalid IL resulted,
e.g., in invalid output in the C-generating back end.  For example, assuming
C++14 mode:

  auto f() { return 42; }
  void g() {
    auto f();
    f();  // Previously this call was represented incorrectly in the IL.
  }

This is now fixed.


1/9/15   [EDGcpfe/15864]
GNU compatibility: virtual destructors in construction virtual tables

The g++ compiler made a change in the 4.9.0 release to suppress references to
virtual destructors from construction virtual tables.  The change was made to
increase the likelihood that speculative devirtualization would be applicable
(it is undefined behavior to invoke a virtual destructor from an object under
construction).  In certain cases, linking objects compiled with the g++ (4.9.0)
and EDG compiler had produced unresolved references to these virtual
destructors.  A change has been made to emulate this behavior (when gnu_version
>= 40900).  The Cfront ABI is unchanged.  In this example (with
--gnu_version 40900), the virtual function pointers for ~B in the B-in-C
construction vtable are now NULL:

  struct A {};
  struct B : virtual A {
    virtual ~B();
  };
  struct C : B {
    ~C();
  };
  C::~C() {}


1/9/15   [EDGcpfe/15857]
Spurious error on use of local variable in lambda header in strict C++14 mode

In modes that accept generic lambdas (particularly, C++14 mode), the front
end issued a spurious diagnostic (an error in strict mode, a warning otherwise)
when a local variable is used in a non-evaluated context in a lambda parameter
declaration.  For example:

  int g() {
    int x;
    return [](decltype(x) p){ return p; }(2);  // Previously a spurious error
  }                                            // in strict C++14 mode.

This is now fixed.


1/9/15   [EDGcpfe/15868]
Incorrect value for macro_context in source positions (IL CHANGE)

In configurations with RECORD_MACRO_INVOCATIONS and NULL_POINTER_IS_ZERO
set to TRUE, the changes for EDGcpfe/15561 (in version 4.10) could result
in some source positions having a macro_context value designating the first
(i.e., index 0) macro invocation when, in fact, the position is not related
to a macro expansion.  This has now been addressed by changing the value of
NO_PARENT_MACRO_INVOCATION from -1 to 0.  As a result, in configurations
with MACRO_INVOCATION_TREE_IN_IL set to TRUE, the zeroth macro invocation
record is now unused and does not correspond to a macro invocation,
although a translation unit with no macro invocations is still marked with
the value 0 for il_header.num_macro_invocation_records.  These represent a
small IL CHANGE.


1/8/15   [EDGcpfe/15862]
Constexpr constructor template and virtual base classes

The front end previously failed to diagnose a constexpr constructor template
in a class with a virtual base class.  In configurations performing IL
lowering, this was likely to trigger an internal error in
initialize_vptr_in_aggregate_constant.  For example:

  struct A {};
  struct B : virtual A {
    template <int ...J> constexpr B() {}  // This is now an error.
  };
  int main() { B(); }
    // Previously, lowering aborted with an internal error because the
    // error above was not diagnosed.

This is now fixed (the example now triggers an error).


1/8/15   [EDGcpfe/15893]
Internal error in wrap_up_constant_full_expression

The changes for EDGcpfe/14647 (see entry of 11/6/13) introduced a regression
in some configurations that set PROTOTYPE_INSTANTIATIONS_IN_IL to TRUE: In GNU
C++ mode, certain functional notation casts to a type with a destructor
appearing in a template could result in an internal error in
wrap_up_constant_full_expression (exprutil.c).  For example:

  struct S { S(); ~S(); };
  template<typename> void g() {
    S as[] = { S() };  // Previously triggered an abort in GNU C++ mode in
  }                    // some configurations.

This is now fixed.


1/8/15   [EDGcpfe/15874]
Spurious command-line error when DEFAULT_GNU_COMPATIBILITY is TRUE

In configurations with DEFAULT_GNU_COMPATIBILITY set to TRUE, the front end
issued a spurious command-line error when specifying certain non-GNU mode
options (e.g., Microsoft mode through "--microsoft_mode").  This is now fixed.


1/8/15   [EDGcpfe/15870,EDGcpfe/15873]
Compilation error on definition of uintptr_t

In some configurations, the front end attempts to declare its own definition
of uintptr_t (a standard C99 integer type that can hold pointer values).
However, when the host environment is a Microsoft or Microsoft-like compiler
the definition was in terms of a type __uint64, which is not actually
defined by the Microsoft compiler and hence resulted in a compilation error.
Now the front end relies on the Microsoft vadefs.h header instead to get the
uintptr_t type in the affected configurations.


1/7/15   [EDGcpfe/15592]
Direct reference binding and explicit conversion operators

The front end previously failed to consider C++11 explicit conversion operators
when binding -- using direct-initialization notation -- a reference to an
expression requiring a conversion into a temporary (the temporary is
initialized using copy-initialization, a context that often excludes explicit
conversion operators).  For example:

  struct X {};
  struct S {
    explicit operator X();
  } s;
  X const &r(s);  // Previously an error; now accepted.
  X const &b = s;  // Still an error (not "direct").

This is now fixed.


1/7/15   [EDGcpfe/11678,EDGcpfe/14185,EDGcpfe/15590]
Local constant-valued variables accessed from local classes

The front end now permits more situations where a local class uses the value
of a constant-valued variable local to the enclosing function.  For example,
in C++11 mode:

  void g() {
    int const N = 10;
    struct S {
      int n = N;  // Previously an error; now okay.
    };
  }

(This implements the standards committee's resolution for Core issue 696.)


1/7/15   [EDGcpfe/15872]
clang compatibility: segfault on __has_feature for C++14 features

Using the __has_feature built-in macro with some C++14 feature names
(cxx_generic_lambda, cxx_relaxed_constexpr, cxx_return_type_deduction,
cxx_variable_templates) or with cxx_runtime_array caused the front end to
abort with a segfault in macro_invocation.  This is now fixed.  For example,
with --clang:

  #if __has_feature(cxx_generic_lambda)  // Previously aborted
  #endif


1/7/15   [EDGcpfe/15593]
Trailing return types in handler parameter declarations

Previously, the front end failed to accept C++11 trailing return types in
handler parameters.  For example:

  int main() {
    try {
    } catch (auto (*pf)()->int) {  // Previously a spurious error in C++11.
    }                              // Now okay.
  }

This is now fixed.


1/7/15   [EDGcpfe/15589]
Effect of multiple alignas specifiers on a class or enum declaration

When multiple C++11 alignas specifiers are used for a class or enum
declaration, the front end now retains the strictest (i.e., largest)
alignment value as required by the C++ standard (except in GNU C++11 mode,
where the previous behavior of keeping the value of the last specifier
remains for compatibility purposes).  For example:

  struct alignas(4) alignas(16) alignas(8) X {};
  static_assert(alignof(X) == 16, "Unexpected");  // Now accepted, except in
                                                  // GNU C++11 mode.

(For variables and nonstatic data members, the strictest alignment specifier
was already correctly recorded.)


1/7/15   [EDGcpfe/15867]
C-generating back end, Microsoft compatibility: segfault in offset_after_field
with bit-field union member

In C-generating back end configurations with MSVC_IS_GENERATED_CODE_TARGET
set to TRUE, the front end previously aborted with a segfault in
offset_after_field when the largest member of a union is the "container"
within which a bit-field is allocated.  This is now fixed.  For example:

  union U {
    char c;
    unsigned i : 6;  // Previously aborted: sizeof(unsigned) > sizeof(char)
  } u;


1/5/15   [EDGcpfe/15856]
Space savings for a_scope and a_template entries

Some small changes were made to a_scope and a_template entries to reduce their
size (particularly, on 64-bit platforms).  The changes involve turning
a_byte_boolean flags into single-bit bit fields and ensuring that checksums
for template definitions are limited to 32 bits.  This is a subtle IL CHANGE.


1/2/15   [EDGcpfe/15355]
Microsoft compatibility: "override" modifier on destructors

In Microsoft C++ mode with microsoft_version >= 1700 the front end now accepts
the "override" modifier on destructors.  For example:

  struct B { virtual ~B(); };
  struct D: B {
    ~D() override;  // Now accepted in Microsoft mode with
  };                // microsoft_version >= 1700.

(Such cases are also allowed in C++11 mode.)


1/2/15   [EDGcpfe/15859]
Warnings when building the front end with gcc

Building some configurations of the front end using gcc with certain
compilation options (notably "-O2 -funroll-loops -Wall") resulted in
compiler warnings.  These warnings have now been eliminated.  This change
is similar to that of EDGcpfe/15100 but affects code added since then and
conditionally-compiled code in different configurations.


12/30/14 [EDGcpfe/15858]
Abort on invalid default template argument in invalid instantiation

In version 4.10, an abort could occur (in reactivate_instantiation_context)
in g++ mode after a default template argument in a friend template declaration
resulted in a "redefinition of default argument" error.  Now fixed.

  template <class T> struct A {
    template <class U = T> friend class A;
     void f(int);
  };
  int main() {
    A<> a;
    a.f(1);
  }


12/28/14 [EDGcpfe/15313]
Spurious "does not have the same number of elements" in variadic instantiation

A spurious pack length mismatch error could be issued when a function
parameter pack whose type is a template parameter pack from an enclosing
class template is followed by a function parameter pack whose type is a
template parameter pack of a function template.  Now fixed.

  void h(...);
  template <class T> int g(T);
  template <class ... T> struct A {
    template <class ... U> void f(T... ts, U... us) {
      // spurious "ts" does not have the same number of elements as "T"
      h(g<T>(ts)...);
    }
  };
  int main() {
    A<int> a;
    a.f(1, 2);
  }


12/28/14 [EDGcpfe/15453]
GNU C++ compatibility: classes instantiated when needed for ADL

Newer versions of the g++ compiler no longer fail to instantiate
classes to determine their associated classes and namespaces for
argument-dependent lookup purposes (see 3/6/06 entry).  We now disable
our emulation of this bug when gnu_version is >= 40500.

  template<class T> class A {
    friend void f(const A& a) { }
  };
  void g(const A<int>& a) {
    f(a);  // error: '"f" undefined' when gnu_version is < 40500
  } 


12/28/14 [EDGcpfe/15727]
GNU C++ compatibility: visibility of using-directives in instantiations

In g++ mode, the front end emulates the non-standard behavior of the
visibility of names in the presence of using-directives (see 11/27/07
entry).  The front end did not properly emulates cases where the
name found as a result of the using-directive was not a template.
Now fixed.  In addition, the special behavior is now used only when
gnu_version <= 40700.

  struct A {};
  struct B {
    // The call of f(t) formerly found ::f instead of N::f
    template< typename T > B(const T &t) : m(f(t)) {}
    int m;
  };
  template <typename T> inline int f(const T& t) {
    return t.g();
  }
  namespace N {
    int f(const A &);
  }
  using namespace N;
  int main() {
    A a;
    B b(a);
  }


12/24/14 [EDGcpfe/15643,EDGcpfe/15844]
clang compatibility: __has_include appearing in a macro expansion

The front end previously aborted with a failed assertion in conv_single_char
if the __has_include macro appears within the expanded text of a macro
invocation and the header file name uses the angle-bracket (<...>) form.
This is now fixed.  For example, with --clang:

  #define M(s) __has_include(s)
  #if M(<foo.h>)    // Previously aborted
  #endif

------------------------------------------------------------------------------
Version 4.10, December 23, 2014

12/22/14 [EDGcpfe/14152]
C++14: Generic Lambdas

In C++14 mode, the front end now supports generic lambdas.  For example:

  auto dbl = [](auto p) { return 2*p; };
  int x = dbl(2);
  double y = dbl(2.0);

Generic lambdas were added to the working paper through the C++ standards
committee's paper N3649.  The implicit capture rule adopted in that paper,
however, is thought to be impractical: The front end therefore uses an
approach that sometimes results in a different set of captures (though in the
common cases, they are the same; other compilers implementing generic lambdas
have similarly eschewed the standard rule).  It is therefore likely that the
details of implicit captures in generic lambdas will be revised in the future.


12/18/14 [EDGcpfe/15554]
Incorrect handling of numeric literal suffixes with user-defined literals

The front end previously incorrectly treated suffixes such as U or L
appearing in a numeric user-defined literal as belonging to the numeric
portion rather than as part of the literal suffix.  A similar problem
occurred in a floating-point user-defined literal where the literal suffix
begins with "e" or "E", which could be mistaken as the start of the
exponent.  These are now fixed.  For example, with --c++11:

  void operator""LL(long double);
  void operator""exa(long double);
  void f() {
    1.2LL;  // Previously an error, "user-defined literal operator not found"
    1.2exa; // Previously an error, "invalid floating constant"
  }


12/18/14 [EDGcpfe/14978]
C++-generating back end: incorrect suffix in numeric user-defined literals

The C++-generating back end previously incorrectly added numeric suffixes
to the integer or floating point portion of a numeric user-defined literal.
This is now fixed.  For example, with --c++11:

  struct S { };
  S operator""_x(unsigned long long);
  S s = 123_x;   // Previously generated as 123ULL_x


12/16/14 [EDGcpfe/15834]
Assertion failure processing aggregate initializer

The front end aborted with an assertion failure in do_fadd for certain
aggregate initializers in which the initializer for one field depends on
the value of a preceding field.  This is now fixed.  For example, with
--c++14:

  struct A {
    double x = x++;
    int z = x + 37;
  };
  static const A a = { };   // Previously aborted


12/16/14 [EDGcpfe/14365]
IA-64 mangling of certain operator functions

The IA-64 ABI specifies that in cases where both binary and unary manglings
are available that the binary mangling should be used.  The front end had
neglected to follow that guideline in the case of a pack expansion.  This has
been fixed when ABI_COMPATIBILITY_VERSION >= 410 (and now matches GNU's
behavior).  The Cfront mangling is unchanged.  For example, with --c++11:

  struct X{};
  void operator+(X);
  template<typename ...T> auto f(T... x) -> decltype(operator+(x...));
  int main() {
    f(X{});
  }


12/16/14 [EDGcpfe/15660]
Microsoft compatibility: location of alink.h header file

The alink.h header file is required to build ms_metadata.cpp, which is
needed when enabling C++/CLI support.  Formerly, this was available
on the Microsoft web site at a location that was specified in the
ms_metadata.cpp file.  It is now included with installations of Visual
Studio (beginning with Visual Studio 2012) as part of the Windows 8 (and
newer) SDKs.  The file can be found in:

  \Program Files(x86)\Windows Kits\8.x\Include\um\alink.h

where 8.x is currently either 8.0 or 8.1.


12/15/14 [EDGcpfe/14537]
Assertion failure during IA-64 mangling of constructor in unnamed class

An assertion failure (in get_mangled_function_name_full) had resulted in
configurations that use the IA-64 ABI on a case that inherits a constructor
in an unnamed class.  Now fixed.  For example (with --c++11):

  struct A {
    template <class T> A(const T&) {}
  };
  struct : A {
    using A::A;
  } a(37);


12/15/14 [EDGcpfe/15828]
Deduced return types and prototype instantiations

The front end previously expected an "auto" return type to be deducible for a
prototype instantiation of a template when that prototype instantiation was
used, e.g., in a call.  That could result in an internal error in function
force_instantiation_to_deduce_return_type (templates.c).  For example:

  template<typename T> struct S {
    auto f();
    int g() { return f(); }  // Use of prototype instantiation of S<T>::f.
  };                         // Previously triggered an internal error.

This is now fixed.


12/15/14 [EDGcpfe/15831]
Lowering of "auto" type

The front end ordinarily replaces the C++14 "auto" placeholder function return
type by the deduced return type.  However, for "auto" functions that are not
defined or are defined as deleted (such functions cannot be referenced and thus
are marked as unneeded), the return type is left as "auto".  Since the "auto"
type is a C++-only construct, IL lowering should have replaced it with a C type
but failed to do so.  This is now fixed, with the "auto" type being replaced by
a typeref to void.  For example, with --c++14:

  auto f();  // Return type was previously "auto" in lowered IL, now void


12/15/14 [EDGcpfe/15827]
Explicit instantiation of deleted function

The front end should have ignored explicit instantiations of deleted member
functions, but did not.  This could result in the routine entry for
such a routine being marked as "needed", which in turn could result in bad
code being generated by the C-generating back end (because the routine
still had a return type of "auto", now fixed by EDGcpfe/15831).  Explicit
instantiations of deleted functions now have no effect.

  template <class T> struct A {
    auto f() = delete;
  };
  template struct A<int>;


12/15/14 [EDGcpfe/15829]
Missing error on use of "void" and "auto"

An error should be issued when both "void" and "auto" are used in a
declaration; the front end had issued an error in all modes except --c++14
and now issues an error in that case as well:

  void auto f() {}    // now gets an error with --c++14


12/13/14 [EDGcpfe/15819]
Abort on invalid decltype-qualified destructor call

An abort could occur (in class_qualified_id_lookup) on a decltype-qualified
destructor call in which the expression before the "->" was a class
type, and the decltype produced a non-dependent nonclass type.  Now fixed.

  template <class T> void f(T* p) {
    class Z {} z;
    int x; 
    z->decltype(x)::~T() ; 
  }


12/12/14 [EDGcpfe/14600]
Lowering of thread_local variables

Previously, only thread_local variables with dynamic initialization that are
defined in the translation unit were candidates for replacement with a
thread wrapper routine during lowering, but that resulted in a violation of
the standard that requires the initialization of all thread_local variables
in the translation unit before the first odr-use of any thread_local
variable (even statically-initialized thread_local variables).  The previous
behavior matches that of the GNU compiler and is more efficient in that
wrapper routines are not created for statically-initialized thread_local
variables.  A new global variable, all_thread_locals_have_wrappers, has been
introduced and is set by default to TRUE to enable the standard-compliant
behavior by emitting wrappers for all thread_locals with extern linkage.
all_thread_locals_have_wrappers is set to FALSE in GNU emulation modes (but to
TRUE in clang emulation mode).  This change only affects configurations where
USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES is TRUE.  For example
(with --c++11):

  int ret = 1;
  int f() {
    ret = 0;
    return 0;
  }
  thread_local int n = f();   // Previously f() was never called because
                              // "n" was not odr-used, but "m" is odr-used
                              // which should trigger initialization of all
                              // thread_locals in the translation unit.
  thread_local int m = 5;
  int k = m;
  int main() {
    return ret;               // Returns 0 except with --g++.
  }


12/11/14 [EDGcpfe/14701]
Mangling of user-defined literal operator

A user-defined literal operator reference in a context that requires mangling
had resulted in invalid mangled names in IA-64 ABI configurations and an
assertion failure ("end_mangling_full: wrong number of leftover spaces") in
Cfront ABI configurations.  That is now fixed.  For example (with --c++11):

  constexpr int operator "" zzz(unsigned long long x);
  constexpr int operator "" zzz(long double x);
  template <class... T> void f(decltype(T(operator "" zzz))...) {}
  void g() {
    f();
  }


12/10/14 [EDGcpfe/15609]
constexpr signed/unsigned char array initialized from string literal

The front end previously failed to treat a constexpr array of signed or
unsigned char initialized from a string literal as a constant expression,
because the element type of the array is different from the plain char type
of the characters in the string literal.  This is now fixed.  For example,
with --c++11:

  constexpr unsigned char r[] = "abc";
  static_assert(r[0] == 'a', "");   // Previously treated as non-constant


12/10/14 [EDGcpfe/15685]
Abort on invalid decltype-qualified destructor call

An abort could occur (in class_qualified_id_lookup) on a decltype-qualified
destructor call in which the expression before the "->" was not a pointer
and was a non-class type.  Now fixed.

  template <class T> inline void f(T* p) {
    T t;
    t->decltype(t)::~T();
  }
  int main() {
    int *p = 0;
    f(p);
  }


12/9/14  [EDGcpfe/15608]
Member access in constexpr mem-initializers

The front end previously failed to treat a constexpr constructor invocation
as a constant expression if the constructor has a mem-initializer in which
the expression refers to a previously-initialized member of the class.
This is now fixed.  For example, with --c++11:

  struct S {
    constexpr S() : m(42), n(m) { }
    int m, n;
  };
  static_assert(S().n == 42, "");  // Previously treated as non-constant


12/9/14  [EDGcpfe/15762]
Pointer-to-member functions and deduced return types

Previously, the front end sometimes produced invalid IL when dealing with
pointer-to-member function constants referring to a member function with a
C++14 deduced return type.  That in turn usually resulted in an abort later
on (e.g., during lowering).  For example:

  struct S { auto f(); };
  bool b = &S::f == nullptr;  // Previously triggered an abort in
                              // lower_constant.

This is now fixed.


12/9/14  [EDGcpfe/15777]
C-generating back end: incorrect generated code for member access expression

The C-generating back end previously produced incorrect code for a member
access expression involving a qualification conversion on a non-lvalue in
the lowered code.  In such cases, the generated code attempted to take the
address of a comma expression in which the first operand computed the
struct value and the second operand was a member access within the result
of the first operand.  This has now been fixed by moving the address
operation from the comma expression to its second operand.  For example:

  const struct S { S() { } } s;
  struct A {
    const S x;
    A() : x(s) {}
  };
  void f() {
    static const S z = A().x;  // Previously generated incorrect code
  }


12/8/14  [EDGcpfe/15770]
Abort on invalid qualification of decltype(auto) return type

The front end aborted in get_template_arg_by_list_pos with a null pointer
dereference when dealing with the invalid qualification of decltype(auto)
used as a (deduced) return type.  For example:

  decltype(auto) const g() { return 1; }  // Previously aborted.

This is now fixed.


12/8/14  [EDGcpfe/15775]
Abort on bad iterator declaration in range-based "for" statement

The front end previously aborted in scan_range_based_for_expression (with a
null pointer indirection) when recovering from certain errors in the
declaration of the iterator variable of a C++11 range-based "for" statement.
For example:

  void g() {
    for ([]{} : {}) {}  // Previously triggered an abort.
  }

This is now fixed.
 

12/8/14  [EDGcpfe/15607]
Binding a non-const constexpr reference to a numeric literal

The front end previously issued a spurious diagnostic on an attempt to bind
a constexpr reference to a non-const type to a numeric literal.  This is
now fixed.  For example, with --c++11:

  constexpr int &&r = 3;  // Previously an error, now accepted


12/5/14  [EDGcpfe/15744]
Explicit specializations and deduced return types

The front end produced invalid IL and often aborted when an explicit
specialization involved a deduced return type.  For example:

  template<typename T> T f() {return T();}
  template<> auto&& f() { return 1; }  // Previously triggered an internal
                                       // error in generic_cast_operand.

This is now fixed.


12/4/14  [EDGcpfe/15741]
Invalid IL for aggregate mem-initializer with destructible elements

C++11 added the ability to have constructors initialize members through
aggregate initialization.  However, the front end produced an invalid list of
IL entries representing the destructions in some such cases.  That in turn
could lead to an abort (in adjust_cleanup_state_for_aggregate_init) during IL
lowering.  For example:

  struct A { ~A(); };
  struct B { A a1, a2; };  // Aggregate class with destructible elements.
  struct C {
    C() : b{A(),A()} {}  // The front end previously produced invalid IL for
    A a;                 // the representation of destructions in this
    B b;                 // constructor.
  };

This is now fixed.


12/4/14  [EDGcpfe/15754]
GNU/Clang compatibility: Call through an incomplete class

GCC and Clang accept the following case:

  struct I;
  template<class> void f(I const &i) {
    i();  // Should be an error because i has an incomplete class type.
  }

We now emulate that behavior (but issue a warning) in Clang, GNU, and
Microsoft C++ modes, by treating a call through an incomplete class type in a
prototype instantiation context as a dependent call.  (This is often not an
issue in Microsoft modes because prototype instantiations are usually not
performed for function templates in that case, but this behavior adds a little
bit of compatibility when forcing prototype instantiations in Microsoft mode.)


12/3/14  [EDGcpfe/15638]
Literal class types with no constexpr constructor

Consider the following example:

  struct A { int a; };
  struct B : public A {};
  constexpr B b{ B() };  // Invalid C++11/C++14.

Here B is not a literal type according to the C++11 and C++14 standards
because it isn't an aggregate class type and it has no constexpr constructor
that is not a copy/move constructor.  The declaration of b is therefore
invalid since the type of a constexpr variable must be a literal type.

However, existing practice is to treat B as a literal type anyway because its
value-initialization produces a valid constant value.  The front end now
implements the same rule in nonstrict modes (causing the example above to be
accepted in nonstrict C++11 or C++14 modes).


12/3/14  [EDGcpfe/15403]
Abort on default initialization with a variadic constructor template

The front end previously aborted with an internal error in
push_template_instantiation_scope (scope_stk.c) when handling the default
initializer in a prototype instantiation context for a class type with a
variadic constructor template.  For example:

  template<typename> struct S {
    template<typename...> S();
    void f();
  };
  template<typename T> void S<T>::f() {
    S a;  // Previously triggered an internal error.
  };

This is now fixed.


12/2/14  [EDGcpfe/15655]
Incorrect handling of reference-returning constexpr functions

The front end previously incorrectly handled some constexpr function
invocations when the function returns a reference.  In some cases, the
front end simply did not fold the call to a constant; in others, the front
end aborted with a failed assertion ("get_pointer_offset: bad kind").  This
is now fixed.  For example, with --c++11:

  struct S {
    constexpr S(int i): t(i) { }
    int t;
  };
  constexpr S&& fwd(S& __t) { return static_cast<S&&>(__t); }
  constexpr static int&& val (S&& arg) {
    return fwd(arg).t;
  }
  constexpr int xxx(S&& arg) {
    return val(fwd(arg));
  }
  static_assert(xxx(S(1)) == 1, "");   // Previously reported "function
                                       // call must have constant value"
  static_assert(val(S(1)) == 1, "");   // Previously aborted


12/2/14  [EDGcpfe/15747]
Assertion failure when mangling lambda call operator (IA-64 ABI configs)

An assertion failure (in mangled_ia64_parent_qualifier) had occurred when
mangling a lambda call operator.  Now fixed.  For example (with --c++11
-tused):

  template <class T, void (T::*m)() const> void g();
  template <class T> void h(const T &f) {
    g<T, &T::operator()>();
  }
  void f() {
    h([]() { });
  }


12/2/14  [EDGcpfe/14700]
Incorrect IL for lowered thread_local rvalue references

In cases where thread_local variables are lowered (i.e., when
USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES is TRUE), the return value
for a wrapper routine for an rvalue reference thread local variable didn't
match the type of the wrapper routine, resulting in invalid IL.  In
C-generating configurations that use inlining, an internal error ("wrong result
type for *") had occurred.  For example (with --c++11):

  thread_local static int&& x(0);
  int z = x;


12/2/14  [EDGcpfe/14566]
Spurious error on default argument following a function parameter pack

A spurious error had been given on the use of a default argument following
a function parameter pack.  Now fixed.  For example (with --c++11):

  struct A {
    template <class ...T> A(T..., int=0);
  };


12/1/14  [EDGcpfe/15702,EDGcpfe/15732]
Use of "this" in Microsoft-mode noexcept specification

In Microsoft C++ mode with microsoft_version >= 1900, the front end previously
issued a spurious error on the use of "this" in the noexcept specification of
a member function.  For example:

  struct S {
    bool e();
    void f() noexcept(noexcept(this->e()));
  };  // Previously an error when microsoft_mode == 1900; now okay.

This is now fixed.


11/30/14 [EDGcpfe/15735]
Unique file identifier processing disabled by default on Windows

The changes for unique file identifiers (see EDGcpfe/14054 on 5/20/14)
are now disabled by default on Windows because the Microsoft compiler does
not use such a facility and because the mechanism can produce incorrect
results for network mounted file systems.


11/30/14 [EDGcpfe/15328]
Build problem if UNIQUE_FILE_IDENTIFIER_AVAILABLE is defined

Build errors would occur if UNIQUE_FILE_IDENTIFIER_AVAILABLE was defined
in defines.h or on the compilation command-line.  Now fixed.


11/30/14 [EDGcpfe/15738]
Incorrect error test for CreateFile result on Windows

The changes for unique file identifiers (see EDGcpfe/14054 on 5/20/14)
test incorrectly for an error when calling the CreateFile function.
Although the test was incorrect, the code following the call should
handle the error cases acceptably.  The test has now been fixed.


11/26/14 [EDGcpfe/14181,EDGcpfe/15367]
C++14: Value category of member selections (IL CHANGE)

The C++14 standard made a significant change to the value category of an
expression of the form prvalue.m or prvalue.*pm: The result is now an xvalue
(this change came about by the resolution of the C++ standardization
committee's Core issue 616; in C++11 it is a prvalue).  The front end now
implements that rule (except that in GNU or Clang C++14 modes, the C++11 rule
is retained for compatibility with the GCC and Clang compilers).  For example:

  template<typename T, typename U> struct is_same {
    static bool const value = false;
  };
  template <typename T> struct is_same<T, T> {
    static bool const value = true;
  };
  struct X {};
  struct S { X m; } s;
  static_assert(is_same<decltype((S().m)), X&&>::value, "Not C++14");
    // Now accepted in C++14 mode.

Note that this is a subtle IL CHANGE.


11/25/14 [EDGcpfe/15723]
GNU compatibility: accept multiple alternative constraints in asm statements

The GNU compiler allows "multiple alternative constraints" to occur in asm
statements (see https://gcc.gnu.org/onlinedocs/gcc/Multi-Alternative.html),
and now so does the front end.  Multiple sets of constraints are separated
by commas within the constraint string.  For example (with --gcc):

  void f(int x) {
    __asm__ __volatile__
    (
      "lock ; cmpxchgl %3, %1\n\t"
      "sete %2"
      : "+a,a" (x), "+m,m" (x), "=q,m" (x)
      : "r,r" (x)
      : "cc"
    );
  }

Note that this change involves a slight IL CHANGE; certain GNU constraint
modifiers, namely, "&", "%", "#", "*", "?", and "!", are now treated
as constraints (because they can appear multiple times in a single constraint
string).  That's a change for "&" which had been a modifier
(aom_earlyclobber).  Also, back ends will now see an aoc_end_of_constraint
"constraint" which represents the "," in a constraint string (i.e., it's
a separator for constraint sets).


11/25/14 [EDGcpfe/15619]
Incomplete return types in prototype instantiations

When during the prototype instantiation of a template a call resolves to the
prototype instantiation of another template and the return type of the called
function is incomplete, the front end now issues just a warning in nonstrict
modes (previously an error was issued).  For example:

  struct I;
  template<typename> struct S {
    I f();
    template<typename T> void g(T) {
      f();  // Previously an error during prototype instantiation, now just
    }       // a warning (except in strict mode).
  };


11/24/14 [EDGcpfe/15603]
Backing expressions for implicitly converted constants

The changes for EDGcpfe/14588 caused the front end not to record a backing
expression for certain initializer constants that are the result of an
implicit conversion.  For example:

  char a[] = { 0x31, 0x32, 0x00 };

Here the original initializer constants are of type int, but these are
implicitly conversion to type char.

Two changes were made to this.  First, the backing expression is now only
dropped in the case of large aggregate initializers (currently, more than a
thousand element values), because the only reason for the change was saving
IL memory for such initializers.  Second, if the new configuration macro
REDUCE_BACKING_EXPRESSION_USE is set to FALSE (it is TRUE by default), then
backing expressions are recorded even for those large initializers.


11/24/14 [EDGcpfe/15611]
Abort on GNU mem-initializer for array with destructors

In GNU C++ mode, a mem-initializer for an array is not required to be "()" or
a braced initializer (see the entry of 10/15/09 for EDGcpfe/10115).   When
handling that extension, however, the front end could abort with an internal
error in add_as_child_of_curr_object_lifetime if the array being copied
requires destructions.  For example:

  struct M {
    M() {}
    M(const M&) {}
    ~M() {}
  };
  struct S {
    S();
    M m[1];
  };
  S::S(): m((M[1]){ M() }) {}  // Previously triggered an abort.

This is now fixed.

 
11/24/14 [EDGcpfe/15610]
Unbounded loop on invalid initializer for a flexible array member

In GNU C++ mode, certain invalid initializers for a flexible array member
could result in an non-terminating loop in the front end.  For example:

  struct S { int f[]; };
  int x[] = { 1, 2, 3 };
  S sx[] = { { f: x, }, 0 };  // The processing of the aggregate initializer
                              // previously failed to terminate.

This is now fixed.


11/24/14 [EDGcpfe/15722]
Issue with lowering of certain multi-dimensional arrays

An assertion failure ("lower_aggregate_designated_initializers: type mismatch")
had occurred in certain circumstances (involving designated initializers or
anonymous unions with initialized fields and multi-dimensional arrays).  The IL
allows for a multi-dimensional aggregate array to be initialized with a single
ck_init_repeat construct, but lowering had expected such a construct to
initialize the entire multi-dimensional aggregate, and not just a piece of it.
Lowering has been changed to handle this case.  For example (with --c++14):

  struct A {
    struct B {
      int x = 37;
    } a[2][3];
    union {
      char y;
      int x = 38;
    };
  } a = { 19 };


11/23/14 [EDGcpfe/15716]
Avoid errors when looking for a template-based copy constructor

A partial instantiation of a constructor template is sometimes needed
to determine if a class has a copy constructor.  Such instantiations
could sometimes result in errors from types that are instantiated
as part of the determination.  In order to avoid such errors, the front
end now detects certain constructor templates that could not produce a
copy constructor and discards them earlier in the processing than it
previously did.  Constructs similar to the example below are found in
the g++ header files starting with g++ 4.9.


  template <typename T> struct A {};
  template <typename T> struct B {
    typedef typename T::X X;
  };
  struct C {
    C(C&&) {}
    template <class T, class = A<typename B<T>::X>> C(T) {}
  };
  struct D {
    C e;
  };


11/23/14 [EDGcpfe/15470]
Microsoft compatibility: template parameters in in-class specializations

In a Microsoft in-class specialization (D<true> in the example below),
template parameters of enclosing class templates were not visible, but
should have been.  Now fixed.

  struct A {
    template <typename T1> struct B {
      static T1 f() {}
    };
    template <typename T1> struct C {
      template <bool> struct D;
      template <> struct D<true> {
        static T1 f() {
          return B<T1>::f();  // formerly "T1" is undefined
        }
      };
    };
    void g() { C<void>::D<true> cd; cd.f(); }
  };
  A a;


11/21/14 [EDGcpfe/15721]
Abort on deduced trailing return type with invalid decltype(auto) specifier

Trailing return types require that the associated function declarator be
preceded with an "auto" specifier, not "decltype(auto)".  A bug in error
recovery for cases that used "decltype(auto)" instead caused the front end
to abort in deduce_auto_type (overload.c) if the trailing return type itself
indicates a deduced return type.  For example:

  decltype(auto) f()->decltype(auto) { return 42; }
    // Previously triggered an internal error after issuing a (justified)
    // error.


11/19/14 [EDGcpfe/15712]
Initialization of arrays of unspecified bounds with pack expansions

When an array with unspecified bound is initialized with a brace-enclosed
initializer containing a pack expansion, the front end previously counted that
pack expansion as a single element during prototype instantiations and used
that to set the adjusted type of the array.  The adjusted type for the array
was thus misleading, and in the case of GNU C++-mode compound literals it
resulted in incorrect output in the C++-generating back end.  For example:

  template <int... N> void f() {
    (int []){N...};  // This compound literal was previously rendered as
  };                 // "(int [1]{(N)...}".
  int main() {
    f<>();
    f<1, 2>();
  }

(The problem was less noticeable in other initialization contexts because they
use a recorded "declared type" instead of the adjusted type for rendering
purposes.)  This is now fixed.


11/19/14 [EDGcpfe/11175,EDGcpfe/15715]
Delete expressions with pointers to void

The front end now diagnoses delete expressions with operands of a pointer-to-
void type; an error is issued in strict C++11 mode (including strict C++14
mode), a warning in other modes.  For example:

  void g(void *p) {
    delete p;  // Now elicits a warning or error.
  }


11/19/14 [EDGcpfe/15711]
GNU C compatibility: Default C11 mode when gnu_version >= 50000

The front end now enables C11 mode extensions by default in GNU C modes with
gnu_version >= 50000.


11/19/14 [EDGcpfe/15673]
Missing diagnostic and abort on nonconstant initializer for constexpr variable

In C++14 mode, a constexpr aggregate variable whose initializer requires the
implicit use of a nonconstant field initializer went undiagnosed, resulting in
an internal error later on.  For example:

  constexpr int f(int x) { return x; }
  int main() {
    constexpr struct S {
      int x = f(x = 37);
    } s = {};  // The initializer for s is not constant.  Previously, this
  }            // triggered an internal error in C++14 mode; now a normal
               // error.

This is now fixed.


11/19/14 [EDGcpfe/15710]
Microsoft compatibility: Additional C++11 and C++14 features

In Microsoft C++ mode with microsoft_version >= 1900, the front end now accepts
the following features: thread local storage (C++11) and binary literals
(C++14).  See also the Changes entry for EDGcpfe/15489.


11/18/14 [EDGcpfe/14331]
Typeinfo structures and key/decider functions

In classes with a key (or "decider") function, the front end now avoids
emitting the associated typeinfo structures if that key/decider function is
not defined.  Previously, those structures were forced in any translation
units where exception handling or RTTI features required the existence of the
structures.  That in turn could result in unneeded instantiations of virtual
member functions, which in turn could trigger errors.  For example:

  struct I;
  struct B {
    virtual void k();  // Key/decider function.
  };
  template<typename T> struct C: B {
    virtual void f() { T i; };  // Would trigger an error if instantiated
  };                            // with T == I.
  struct D: C<I> {
    virtual void k();
  };
  D& g(B &b) {
    return dynamic_cast<D&>(b);  // Previously caused the instantiation of
  }                              // C<I>::f(), and thus an error.  Now okay.


11/17/14 [EDGcpfe/15633]
IL representation for #ident and #pragma ident (IL CHANGE)

Previously (in configurations where IDENT_DIRECTIVE_AND_PRAGMA is TRUE),
the #ident and #pragma ident preprocessing directives were both handled by
the same pragma processing code and were both mapped to pk_ident pragmas.
Unfortunately, it appears that the processing for these (and the IL that
needs to be generated) are different; #ident takes a single string argument
(and gives a warning if anything follows that), and #pragma ident can have
arguments of unspecified number and type.  Accordingly, two separate
pragma kinds are now used: #ident maps to pk_ident_directive and #pragma ident
maps to pk_ident_pragma.  For backward compatibility, pk_ident is defined
to pk_ident_directive, which will allow back ends to process #ident directives
as before, but #pragma ident directives will generate new pk_ident_pragma
IL entries.  This is an IL CHANGE.  For example:

  #pragma ident "string" extra
    // Generates pk_ident_pragma with "ident \"string\" extra" in pragma_text.
  #ident "string" extra
    // Generates pk_ident_directive with "string" constant in ident_string and
    // issues a warning on "extra".

Also, the configuration macro USE_PRAGMA_IDENT_IN_GENERATED_CODE has been
removed; as a result, #ident is always represented as #ident and #pragma ident
as #pragma ident in generated C and C++ code.


11/17/14 [EDGcpfe/13789]
Microsoft compatibility: accept invalid default template argument

The Microsoft compiler allows an a template to be referenced with too few
template arguments when it is used in a default template argument (provided
the default argument is never used).  We now allow this in Microsoft mode.

  template <typename T1, typename T2> class A {};
  template <typename T1, typename T2 = A<T1> > class B {};
  int main() {
    B<int, int> b;
  }


11/17/14 [EDGcpfe/15561]
Performance enhancements

A number of relatively minor changes were made to improve the overall speed of
the front end.  This includes some tuning of the lexing process (including
skipping whitespace), the mangling process (especially, the handling of IA-64
substitutions), the rendering of integers in the C- and C++-generating back
ends, and a few other optimizations that made a measurable difference on some
"real-world" source code.


11/17/14 [EDGcpfe/15605]
Failure to match variadic template template parameter

A class template should sometimes match a template template parameter with
a variadic template parameter list.  The front end failed to do this in
some cases.  Now fixed.

  template<typename T, typename... U> struct A { };
  template<template<typename...> class T, typename... U> void f(void);
  int main() {
    f<A, int>();  // Formerly "no instance ... matches"
  }


11/14/15 [EDGcpfe/15700]
Deduction/substitution problem with nested dependent qualified type

If a dependent qualified name (LHS::E in the example below) appeared as a
nested construct within another dependent qualified name (T::template C2<...)
the lookup of E in LHS incorrectly ignored members that were not types.
Now fixed.

  template<typename T, typename S, int N> struct A {};
  template<typename T> struct B { enum { E = 17 }; };
  struct C {
    typedef int type;
    template<int LHS = 17, int RHS = 17> struct C2 { typedef C type; };
  };
  template<typename S, int N> struct D : A<C, S, N> {};
  template<typename T, typename LHS, int N>
    A<typename T::template C2<LHS::E, 30>::type, B<C>, N>
     operator<( A<T, LHS, N> &lhs, typename T::type rhs);
  struct E : D< B<C>, 4> {
    template<typename RHS> E(const A<C, RHS, 4> &rhs) {}
  };
  E f(E &x) {
    return (x < 0) ;
  }


11/13/15 [EDGcpfe/14271]
Microsoft compatibility: accept incorrectly formed template template argument

The Microsoft compiler allows syntactically invalid template template
arguments.  Specifically, in a template template argument that refers to
a nonreal template (a member of an unknown dependent type) the name can
be prefixed by "typename" (which is not allowed for a template template
argument), and can also be followed by an empty template argument list
(i.e., "<>").  We now accept this usage in Microsoft mode.

  template <template <class> class T> struct B {};
  template <class T> struct A {
    B<typename T::X<> > bi;
  };


11/13/14 [EDGcpfe/13646,EDGcpfe/13648,EDGcpfe/13628]
Microsoft compatibility: redeclarations in __if_exists blocks

The front issued an error if a class declared in a template context
contained more than one declaration of a given entity inside dependent
__if_exists or __if_not_exists blocks.  Now the redeclaration error is
suppressed (except for member functions, which are still treated as
invalid overloads) during the prototype instantiation of the class and
when the name in the __if_exists is dependent.

  template <class T> struct A {
    __if_exists(T::A) { static const bool i = true; }
    __if_not_exists(T::A) { static const bool i = false; }
  };


11/10/14 [EDGcpfe/15654]
Spurious instantiation of elided constructor in unevaluated context

The front end previously instantiated elided constructors even when they were
only called in unevaluated contexts.  This could lead to spurious errors.
For example:

  struct X {
    X(X const&) = delete;
    X(X&&);
  };
  template<typename T> struct Y {
    T x;
    template<typename U> Y(Y<U>&& y): x(y.x) {}
  };
  Y<X>&& yval();
  void g(Y<X const>);
  typedef decltype(g(yval())) V;

Here, the result of yval() is conceptually converted to Y<X const> with one
instance of the Y constructor template, and that converted value is then
copied with another instance.  However, the second invocation is elided.
Both invocations are in an unevaluated context (because they are part of the
decltype operand), but the elided call still triggered an instantiation,
which then triggered an error because the constructor template of Y<X const>
ends up referring to the deleted copy constructor of X.

This is now fixed: The elided constructor is no longer instantiated, and no
diagnostic is issued.


11/7/14  [EDGcpfe/14935]
Allow redeclaration of alias template (core issue 1896)

Some compilers (g++, clang) allow redeclaration of alias templates.
The proposed resolution of core issue 1896 is that such redeclarations
should be permitted.  We now allow the redeclaration of an alias template.

  template <class T> struct A{};
  template <class T> using B = A<T>;
  template <class U> using B = A<U>;


11/4/14  [EDGcpfe/14286,EDGcpfe/14868,EDGcpfe/15621]
Spurious diagnostics on qualifiers in alias declarations

The front end had issued spurious errors on trailing cv- and ref-qualifiers
when used in an alias declaration of a function.  Now fixed.  For example
(with --c++11):

  using f1 = void() const;
  using f2 = void() &&;
  using f3 = void() const &;


10/23/14 [EDGcpfe/15582]
Microsoft compatibility: Ref-qualifiers

Consider:

  struct S { void f() &; };
  void g() {
    S().f();
  }

The "&" ref-qualifier (see entry of 4/23/13 for EDGcpfe/13936) indicates that
the member function S::f can only be called on lvalues.  However, in Microsoft
mode, this was previously not enforced because Microsoft compilers -- which
until recently did not support C++11-style ref-qualifiers at all -- do permit
rvalues to be bound to lvalue references to non-const types.  Now, however,
Microsoft compilers have added support for ref-qualifiers and in that context
they do adhere to the standard constraints.  The front end now matches that
behavior (ref-qualifiers are enabled by default in Microsoft mode when
microsoft_version >= 1900).

As part of this change, diagnostics for such mismatches have been improved in
general (not just in Microsoft mode).


10/23/14 [EDGcpfe/15586]
__has_trivial_copy, __has_trivial_assign, and generated special members

Previously, the front end produced a true value for __has_trivial_copy(T) only
if both the copy and the move constructors of a class type T were trivial.
Now, a true value is produced also for classes whose copy constructors are all
trivial but whose move constructors (if any) are nontrivial.  Similarly,
__has_trivial_assign no longer depends on the triviality of the move assignment
operator.  For example:

  struct S {
    S& operator=(S const&) = default;  // Trivial copy assignment.
    S& operator=(S&&);                 // Nontrivial move assignment.
  };
  static_assert(__has_trivial_assign(S), "Old behavior");
      // This assertion now succeeds.

As part of this change, some corrections were also made in the criteria
deciding whether to generate certain special members.  For example:

  struct A {
    A();
    A(A const&);
  };
  struct B { A a; };
  B& (B::*pmf)(B&&) = &B::operator=; // Previously an error; now okay.

Previously, no move operations were generated for B because A has no move
constructor.  Now, move operations are generated, and they call the
corresponding copy operations of A.


10/23/14 [EDGcpfe/15517]
Abort in is_literal_type with Microsoft-mode base class of a class template

The front end sometimes aborted in is_literal_type (types.c) when it performed
a "nonreal instantiation" of a class with an incomplete, nondependent base
class (which is accepted during nonreal instantiations).  For example:

  struct S1;
  template<typename> struct S2;
  template <typename, typename U> struct S3: S2<U> {};
  template <typename T> struct S4: S3<T, S1> {};

This triggered an abort during the nonreal instantiation of S3<T, S1> (nonreal
because T is a template parameter) because its base S2<S1> is incomplete.
This problem is now fixed.


10/22/14 [EDGcpfe/15562]
Generated copy/move constructors and const fields

The front end previously ignored const qualifiers on fields when determining
whether to generate a viable (i.e., non-deleted) copy or move constructor.
This sometimes triggered spurious errors.  Consider the following example:

  struct X {
    X(X const&) = delete;
    X(X&&);
 };
 struct Y {
   const X x;
   template<class T> Y(T&&);
 };
 Y&& yval();
 void g() {
   Y y = yval();  // Previously triggered an error.
 }

Previously, the front end generated a move constructor for Y even though its
field x is not copyable due to its const type (X's move constructor doesn't
accept a const argument, and its copy constructor is deleted).  The
initialization of y in function g() then caused the generation of the body of
Y's move constructor, which led to an error attempting to select the deleted
copy constructor of X.

This is now fixed: The move constructor is no longer generated since field x
cannot be moved (or copied).  The initialization of y then simply picks the
constructor template of Y and the case is accepted. 


10/22/14 [EDGcpfe/15548]
Microsoft compatibility: __is_convertible_to and array types

When evaluating the type traits helper __is_convertible_to(T1, T2) in Microsoft
mode, the front end replaced an array type T1 or T2 by the reference type T1&
or T2&, respectively.  This caused the following example to be accepted:

  typedef int A[3];
  static_assert(__is_convertible_to(A, A), "Standard");

Now, when microsoft_version >= 1900, the extra "reference type layer" is no
longer added to the specified type and the case above produces an error as
expected from the standard "is_convertible_to" trait (if microsoft_version
equals 1900, the standard behavior is in effect when microsoft_build_number >
22129).


10/22/14 [EDGcpfe/15576]
Switch statements controlled by an enum bit field

The front end previously issued a spurious error on certain case labels in
switch statements controlled by a bit field of enumeration type.  For example:

  enum E1 { e1 };
  enum E2 { e2 };
  struct S { E1 f : 16; } s;
  void f() {
    switch (s.f) {
    case e2: ;  // Previously triggered a spurious error indicating that e2
    }           // must be of type E1.
  }

This is now fixed.  Note that this case was already accepted with a warning in
GNU C++ mode; that warning is no longer issued.


10/21/14 [EDGcpfe/15573]
C11 _Static_assert and struct/union definitions

The front end now accepts the C11 _Static_assert construct (see entry of 1/3/14
for EDGcpfe/12649) inside struct or union definitions.


10/20/14 [EDGcpfe/15568]
Predefined macros on MacOS X systems

On MacOS X systems, the front end predefines some macros (see the entry of
3/16/05).  Previously, that unconditionally included defining the macros
__BIG_ENDIAN__ and _BIG_ENDIAN, even those are not true on current versions
of MacOS X.  This is now fixed: Those macros are now only predefined if the
host compiler defined __BIG_ENDIAN__.  (For cross compilation, sys_predef.c
can be customized as needed.)


10/17/14 [EDGcpfe/15565]
Microsoft and GNU compatibility: Partial specialization via a using-declaration

In GNU and Microsoft C++ modes, the front end now accepts partial template
specializations using a qualified name that involve a using-declaration.
For example:

  namespace N { template<typename> struct X {}; }
  namespace M { using N::X; }
  template<typename> struct Y;
  namespace N {
    template<typename T> struct M::X<Y<T>>;  // Previously an error.  Now a
  }                                          // warning in GNU/Microsoft mode.


10/17/14 [EDGcpfe/15563]
Spurious errors on deduced void return types in templates

The front end did not correctly handle "auto" return types in templates that
were deduced to a "void" type.  For example:

  template <typename T> auto f() {}  // Always deduces a "void" return type.
  void g() { f<int>(); }             // Triggered a spurious error; now okay.

This is now fixed.


10/17/14 [EDGcpfe/15549]
Microsoft compatibility: __is_empty and union types

The type traits helper __is_empty usually returns a false value when its
operand is a union type (see the entry of 11/12/13 for EDGcpfe/14651).
However, that was not the case in Microsoft C++ mode.  Now, when
microsoft_version >= 1900 the same is true in Microsoft modes (more precisely,
if microsoft_version == 1900, the new behavior is in effect when
microsoft_build_number > 22129).  For example:

  union U {};
  static_assert(!__is_empty(U), "Nonstandard");
    // Now accepted when microsoft_version >= 1900.


10/17/14 [EDGcpfe/15564]
Warning for macro_preempts_udl_suffix

As described in the entry for EDGcpfe/14857, when the global variable
macro_preempts_udl_suffix is TRUE (as it is by default in g++ mode), an
apparent user-defined string literal will be lexed as an ordinary string
literal followed by an identifier if that identifier has been defined as a
macro name.  The front end will now issue a warning if the first token of
that macro's expansion is an identifier, on the theory that such a case
might be an attempt to specify a user-defined literal suffix via a macro
expansion, to make it easier for the user to understand the syntax error
that follows.  Macros for which the first token is not an identifier do not
elicit the warning, as other kinds of tokens might result in correct
syntax.  For example, with --gnu_version=40800 --c++11:

  int operator "" _A(const char *);
  #define _B _A
  int i = "abc"_B;  // Now warns that _B is a macro, not a literal suffix


10/16/14 [EDGcpfe/15477]
Microsoft compatibility: User-defined literals when wchar_t is not built-in

In Microsoft C++ modes that accept user-defined literals but don't have a
built-in type wchar_t, the front end now accepts user-defined literal operators
for wide string literals: Such an operator must have as its first parameter
type "X const*" where X is a typedef named wchar_t for the wide character
integer type, or a typedef thereof.  For example:

  typedef unsigned short wchar_t;  // Assume unsigned short is the wide
                                   // character type.
  int operator""_x(wchar const *str, size_t len) {  // Now valid in some
    return 42;                                      // Microsoft modes.
  }

(Note that a similar extension does not currently exist for user-defined
wide-character literals.)


10/15/14 [EDGcpfe/15503]
Microsoft compatibility: Exported generated members and default arguments

In Microsoft mode, the front end forces the definition of generated special
member functions for "dllexported" classes (see the entry of 3/21/12 for
EDGcpfe/12772).  However, previously this generation occurred before some
default arguments had been processed, which in turn triggered spurious errors.
For example:

  struct __declspec(dllexport) S {
    struct __declspec(dllexport) N {
      int p, q;
      N(int x = 0, int y = 0): p(x), q(y) {}
    } p1;
  };
 
Previously, generating the definition of S::S() produced an error indicating
that N has no default constructor because the default arguments of N's
constructor were not recognized.  This is now fixed.


10/15/14 [EDGcpfe/15559]
GNU vector subscripting and value categories

The changes enabling subscripting a GNU vector (see entry of 11/13/13 for
EDGcpfe/14580) failed to convert the subscript to an rvalue (or prvalue, in
C++11 terms).  This could manifest itself as an abort in the C++-generating
back end (in check_operation_node_consistency).  This is now fixed.


10/14/14 [EDGcpfe/15491,EDGcpfe/15494,EDGcpfe/15495,EDGcpfe/15496]
GNU C compatibility: C11 features accepted in non-C11 C modes

In GNU C mode with gnu_version >= 40700, the front end now accepts the
following C11 features even when C11 mode is not enabled: _Noreturn, _Alignof,
and _Alignas.  Similarly, when gnu_version >= 40900, the _Generic construct is
also allowed in non-C11 GNU C modes.


10/14/14 [EDGcpfe/15556]
C++-generating back end aborts on C11 _Generic constructs

The C++-generating back end previously aborted when attempting to render the
"default:" case of a C11 _Generic construct.  This is now fixed.


10/14/14 [EDGcpfe/15489]
Microsoft compatibility: Additional C11, C++11, and C++14 features

In Microsoft C++ mode with microsoft_version >= 1900, the front end now accepts
the following C++11 and C++14 features: generalized lambda capture, generic
lambdas, the implicit noexcept rules, inheriting constructors, ref-qualifiers
on member functions, alignof/alignas, inline namespaces, user-defined literals,
deduced return types, and decltype(auto).  In Microsoft C mode with
microsoft_version >= 1900, the _Alignof construct is also accepted.


10/14/14 [EDGcpfe/14261,EDGcpfe/14851,EDGcpfe/15277,EDGcpfe/15392,
          EDGcpfe/15429,EDGcpfe/15476]
Incorrect behavior when pack used as argument to non-variadic template

The front end failed to properly handle cases where a parameter pack was
used as a template argument to a non-variadic template.  Now fixed.

  template <class T1, class T2> class A {};
  template <typename... Args> void f(A<Args...>& args);
  int main() {
    A<int,int> t;
    f(t);
  }


10/14/14 [EDGcpfe/15552]
GNU compatibility: Attribute vector_size constraints

The front end previously required that the argument to the GNU vector_size
attribute be a power of two.  Now, it requires that the numbers of elements
in the vector be a power of two.  For example:

  long double __attribute__((vector_size(2*sizeof(long double)))) vec;
    // Previously an error in configurations where sizeof(long double)
    // is not a power of two.  Now always accepted.


10/13/14 [EDGcpfe/15500]
Spurious error for missing calling convention on explicit instantiation

An explicit instantiation directive that omits a calling convention specified
on the original template declaration previously elicited a spurious error (in
modes that accept calling convention specifiers or attributes; i.e., Microsoft
and GNU modes).  For example, in Microsoft mode:

  template <typename T> void __fastcall g() {};
  template void g<int>();  // Previously an error; now okay.

This is now fixed.  (Contradictory calling conventions are still diagnosed.)


10/13/14 [EDGcpfe/15501]
Spurious "unused" warnings on captured variables

The front end previously failed to mark a variable captured by a lambda as
"used".  This could result in spurious warnings about the captured variable
having been set but not used.  It also meant that no warning was issued for
variables captured before they are initialized.  For example:

  struct S { int x; };
  int f() {
    S s = { 10 };  // Previously triggered a "set but never used" warning.
    return [=]{ return s.x; }();
  }

This is now fixed.


10/13/14 [EDGcpfe/15545]
Spurious error on destructor call in prototype instantiation

Version 4.9 introduced a bug causing the front end to issue a spurious
ambiguity error on an explicit destructor invocation in a member template if
the destructor being named is for a dependent base class.  For example:

  template<class T, class X = T> struct B { ~B(); };
  template<class T> struct D: B<T> {
    void f() {
      B<T>::~B();  // Spurious error in version 4.9 during the prototype
    }              // instantiation of D<T>::f.
  };



This regression -- introduced by the changes for EDGcpfe/14127 (see the entry
of 11/19/13) -- is now fixed.


10/11/14 [EDGcpfe/15547]
Incorrect prototype instantiation routine entry in template entry

The a_template entry for a member template of an instantiation of a class
template contained an incorrect routine pointer.  It pointed to the
routine entry from the prototype instantiation of the class instead of
the routine entry from the real instantiation (i.e., in the example below,
the a_template entry for A<int>::f pointed to the routine entry for A<T>::f
instead of A<int>::f).  Now fixed.

  template <class T> class A {
    template<class X> X f() {return 0;}
  };
  A<int> a;


10/9/14  [EDGcpfe/15541]
Abort on typeref during cross-referencing output

When outputting cross-reference entries, the front end sometimes aborted with
an internal error in record_symbol_reference_full when dealing with a deduced
return type used as a template argument type.  For example:

  auto f() { return 42; }
  template<class T> void g(T) {}
  int main() {
    g(f());  // Previously triggered an internal error in some cases.
  }          // Now okay.

This is now fixed.


10/8/14  [EDGcpfe/15353,EDGcpfe/15508]
Error on specialization of inline namespace member

A spurious error was issued if an instance of a template from an inline
namespace was specialized in the scope containing the inline namespace.
Now fixed.

  namespace std {
    inline namespace M {
      template < class T> void swap (T, T);
    }
    template <class T> void swap ();
    template <> void swap (int, int);
  }


10/7/14  [EDGcpfe/14178,EDGcpfe/14813,EDGcpfe/15078,EDGcpfe/15134,
          EDGcpfe/15144,EDGcpfe/15301]
GNU statement expressions with class type results (IL CHANGE)

Version 4.9 of the front end enabled the ability to have destructible entities
in GNU statement expressions (GSEs), but with the restriction that the result
expression of a GSE cannot be of a class type requiring nontrivial copy
construction or nontrivial destruction.  (See the entry of 1/20/14 for
EDGcpfe/7317 et al.)

The latter restriction is now lifted.  For example:

  struct D { D(D const&); };
  D g(D d) {
    return ({ d; });  // Now accepted.
  }

These changes required an IL CHANGE.  First, if a GSE ends in an expression
statement (which is the result of the GSE), that statement will have a new
kind "stmk_stmt_expr_result" (which may have an associated dynamic initializer
entry to represent a "result by constructor").  (The now-redundant flag
"is_statement_expression_result" has been eliminated.)  Second, the dynamic
initializer kind "dik_call_returning_class_via_cctor" has been renamed
"dik_class_result_via_ctor" because it now not only applies to calls returning
certain class types, but also to GSEs returning such types (the synonym
"dik_call_returning_class_via_cctor" is maintained for backward compatibility).


10/7/14  [EDGcpfe/15521]
Removal of unneeded destructors with LOWER_VARIABLE_LENGTH_ARRAYS

As a result of the changes dated 11/19/11, in configurations where both
LOWERING_REMOVES_UNNEEDED_CONSTRUCTIONS_AND_DESTRUCTIONS and
LOWER_VARIABLE_LENGTH_ARRAYS are TRUE, lowering had incorrectly removed
destructions for objects with VLA types, resulting in an assertion failure
("add_dyn_init_cleanup: missing destructible entity descr") in some cases.
Such destructions are no longer removed.  For example (with --g++):

  struct S {
    ~S() {}
  };
  void f(int s) {
    S a[s];
  }


10/5/14  [EDGcpfe/15215]
GNU C++ compatibility: partial ordering of lvalue vs. rvalue references

The change introduced by core issue 1164 (see EDGcpfe/11270 on 1/14/11)
is supported beginning with g++ version 4.9.  We now use the rules as
specified by 1164 in g++ mode when gnu_version >= 40900.

  template<typename T> int f(T&);
  template<typename T> int f(T&&);
  int i;
  int j = f(i);  // formerly ambiguous, now calls f(T&)


10/3/14  [EDGcpfe/15515]
Type traits applicable to "object types" and void types

In some cases, the front end erroneously treated "void" as a valid object type
for some type traits helpers.  For example, __has_trivial_copy(void) usually
produced a true value when it really should be a false value.  The affected
type traits helpers are __has_copy, __has_nothrow_copy, __has_trivial_copy,
__has_trivial_destructor, __has_trivial_move_constructor, __has_assign,
__has_trivial_assign, __has_nothrow_assign, __has_trivial_move_assign, and
__has_nothrow_move_assign.  This is now fixed.


10/3/14  [EDGcpfe/13615]
GNU C++11 compatibility: Explicit conversion functions

Consider the following C++11 case:

  struct S {
    operator int();
    explicit operator long();
  } s;
  bool b(s);  // Previously an error in all GNU C++11 mode; now accepted
              // when gnu_version >= 40700.

Explicit conversion operators usually apply for direct-initialization contexts
like the initialization of the variable b in this example.  However, that is
only the case if the type converted to by the explicit conversion operator is
exactly (modulo type qualifiers like "const") the required destination type.
The latter condition is not satisfied in the example above (where the explicit
conversion operator converts to "long", but the required destination type is
"bool"), and so there is no conversion ambiguity in standard C++11: Only
"operator int()" applies.  However, in GNU C++11 modes, the front end did not
that special condition to match a bug in early versions of GCC.  GCC 4.7 fixed
that bug and the front end therefore now restricts its emulation to modes with
gnu_version < 40700.


10/3/14  [EDGcpfe/15075]
Value of __cplusplus in C++14 modes

The newly-approved Standard for C++14 specifies the value of the
__cplusplus predefined macro as 201402L.  The front end has now been
changed to follow suit when --c++14 mode is specified, except that in
Microsoft and GNU modes it adopts the value set by those compilers: MSVC
continues to use 199711L, while g++ beginning with version 4.9 uses 201300L
when -std=c++14 is specified.


9/29/14  [EDGcpfe/15442,EDGcpfe/15475]
Emitting virtual function tables for class templates in IA-64 ABI configs

The decision to emit a virtual function table for an instance of a class
template had previously been based on the existence of a definition for the
class's "key" function (matching the behavior for non-template classes).  The
IA-64 ABI specifies that a virtual function table should be emitted in
objects in which the class template is instantiated; a change has been made
to mark the virtual function tables as being defined in the translation
unit.  Although not specifically mentioned in the IA-64 ABI, in practice, g++
and clang (and EDG) suppress definitions of virtual function tables when the
virtual function tables are not not referenced in the translation unit.
A similar change has been made when deciding when to emit virtual destructors.
This change should more closely align EDG's behavior with that of g++ and clang
(though the change affects all modes, not just GNU and clang emulation modes).
The Cfront behavior is not changed.  The previous behavior can be restored by
setting ABI_COMPATIBILITY_VERSION to a value less than 410.  For example:

  template <class T> struct A {
    virtual void f();
  };
  template <> void A<void*>::f() { }   // Now: no vtable emitted.

  template <class T> struct B {
    virtual void f();
  };
  B<char> b;    // Now: vtable emitted (had been undefined).


9/25/14  [EDGcpfe/15394]
Attributes and explicit specializations

The front end previously failed to record attributes for non-defining explicit
specializations of function templates in the secondary source sequence entry
for that specialization (in configurations with GENERATE_SOURCE_SEQUENCE_LISTS
set to TRUE).  This caused the C++-generating back end to fail to render those
attributes.  For example, in Microsoft mode:

  template<typename T> void f() {}
  template<> __declspec(dllimport) void f<int>();
    // Previously, the C++-generating back end did not render the
    // "__declspec(dllimport)".

(A similar problem existed for static data members and member functions of
class templates.)  This is now fixed.


9/24/14  [EDGcpfe/15485]
Representation of same-type casts

In some modes (Microsoft mode in particular) casting an lvalue to its own type
preserves the lvalue (see the entry of 11/1/13 for EDGcpfe/14628).  The IL
representation of such situations frequently just omitted the cast altogether.
For example:

  void g(int&) {}
  void h(int p) {
    g((int)p);  // Accepted in Microsoft C++ mode, but the IL previously did
  }             // not reflect the presence of the cast.  Now it does.

Now, such casts are represented using an eok_lvalue_cast node.  (This affects,
e.g., the C++-generating back end: It now renders the original cast, whereas
it didn't before.)


9/24/14  [EDGcpfe/15332]
C++-generating back end: assertion failure with explicit specialization of
member of inline namespace in containing namespace

After the change for EDGcpfe/15043, the C++-generating back end could abort
with an assertion failure in adjust_current_namespace when putting out the
declaration of an explicit specialization or explicit instantiation if the
template is a member of an inline namespace nested within the current scope.
This is now fixed.  For example:

  namespace N {
    inline namespace {
      template<typename T> void f(T);
    }
    template<> void f(int);  // Previously aborted
  }


9/24/14  [EDGcpfe/15483]
Abort in copy_routine_type_default_args in complex cases

When recording the declared types of function declarations (i.e., when the
configuration macro GENERATE_SOURCE_SEQUENCE_LISTS is TRUE), the front end
could sometimes abort with an internal error in copy_routine_type_default_args
while updating the IL for the default arguments of a member function.
Currently, this has only been reproduced with large, complex test cases, but
the issue has been fixed.


9/23/14  [EDGcpfe/15467]
Spurious warning on member function template from unnamed namespace

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE the front end
issued a spurious "declared but never referenced" warning on member function
templates of classes defined in an unnamed namespace.  For example:

  namespace {
    struct X { template <typename T> static void f() {} };
  }  // Previously, a spurious warning was emitted for X::f<T>().
  int main() {
    X::f<int>();
  }

This is now fixed.


9/23/14  [EDGcpfe/11269,EDGcpfe/14191,EDGcpfe/15139]
Nontype template arguments and linkage

C++11 relaxed the requirements for nontype template arguments to allow
references and pointers to functions and variables with external linkage.  The
front end now allows this in C++11 mode (or, more precisely, when the global
variable local_types_as_template_args_enabled is TRUE; this includes certain
Microsoft C++ modes).  For example:

  template<int *p> struct S {};
  static int i = 0;
  S<&i> si;  // Now permitted in C++11 mode and in some Microsoft modes.

(This relaxation came about through the C++ standards committee's resolution
for Core issue 1155.)  In Microsoft mode, this relaxation also applies to
static member functions of local classes (which have no linkage at all).  For
example:

  template<void (*)()> struct X {};
  void g() {
    struct L { static void f() {} };
    X<&L::f> x;  // Now accepted in Microsoft C++ mode.
  }


9/22/14  [EDGcpfe/15438]
Performance with complex nested macros

Certain highly complex nested macro invocations, such as might be
encountered using the Boost "repetition" preprocessor library, exceeded the
initial allocation size of some extensible internal buffers, resulting in
very poor performance due to the overhead involved in relocating the data
after reallocation.  The initial allocation size of the buffers involved
has been increased to reduce the likelihood of needing to reallocate the
buffers.


9/19/14  [EDGcpfe/15463]
Microsoft compatibility: Bound functions in unevaluated contexts

A "bound function" is an expression of the form "obj.f" or "ptr->f" where f is
a nonstatic member function.  Ordinarily, such an expression can only be used
to call the indicated member function.  Now, in Microsoft mode, the front end
also allows taking the address of such an expression inside a sizeof operand:
"&(p->f)" is treated as a pointer-to-function in such cases.  For example:

  struct S { int f(); };
  unsigned s = sizeof(&((S*)0)->f);  // Now accepted in Microsoft mode.

The bound function in such cases is represented by an eok_points_to_static or
eok_dot_static node (this is a new use of those operators).


9/18/14  [EDGcpfe/15455]
Internal error converting dependent expression to pointer type

The front end could previously issue an internal error in
conv_pointer_to_whatever when a function template contains a cast of a
dependent expression to a pointer type.  This is now fixed.  For example,
with --g++ --c++11:

  struct S {
    const int& operator[](int) const;
  };

  void f(const int*);

  template <typename T> void g(const T& t) {
    const int& ir = t[0];
    f(reinterpret_cast<const int*>(&ir));  // Previously aborted
  }

  void h() {
    S s;
    g(s);
  }


9/17/14  [EDGcpfe/15450]
Lowering of fixed point in Microsoft C mode

In configurations that accept and lower fixed point operations in Microsoft
C mode, that lowering was inadvertently skipped for dynamic initializations
when the C mode is pre-C99.  Dynamic initializations are not typically allowed
in C mode, but they are in Microsoft C mode.  The following example (with
-m --fixed_point --microsoft) had caused an assertion failure (in
form_constant) and is now fixed:

  void f(_Accum x) {
    _Accum y[] = {1.0k, x};
  }


9/15/14  [EDGcpfe/15436]
GNU C++ compatibility: noexcept specifier on template member of normal class

In g++ mode, nonstandard lookup rules are used when scanning the argument
of a noexcept operator of a function template (only names visible prior
to the declaration in a class are considered).  This processing was applied
to all classes, but should have only been applied to members of class
templates.  A quirk in the way in which this feature was emulated caused
template parameters to not be visible for member function templates of
non-template classes when deferral of function prototype instantiations
was enabled.  Now fixed.

  template <bool b> struct A {};
  template <typename T> T&& f();
  template <class T> struct C : public A<noexcept(f<T>() = f<T&>()) > {};
  template<typename T> struct B {
    static const bool value = true;
  };
  struct D {
    template<typename T> bool operator=(T& t) noexcept(B<T>::value) {}
  };
  C<D> c;
 

9/14/14  [EDGcpfe/15311]
Default gnu_version in clang mode

As noted in the description of the change for EDGcpfe/14634 (1/2/14), clang
mode is treated in the front end as a variant of gnu mode.  Consequently,
the feature set available in clang mode defaults to the features enabled by
the value of gnu_version.  This dependency could inadvertently exclude some
features (e.g., user-defined literals) that should be enabled in clang mode
but are not supported with the default setting of gnu_version.  The front
end has now been changed to set gnu_version to 40800 when clang mode is in
effect and --gnu_version is not specified on the command line.  For example,
with --clang --c++11:

  int operator "" _a(const char *);  // Previously rejected (assuming default
                                     // gnu_version < 40700), now accepted


9/11/14  [EDGcpfe/15416]
Abort after error in name qualifier

In some cases when a name qualifier produced an error, the front end could
abort in class_qualified_id_lookup later on.  For example:

  template <class T> struct A { ~A(); };
  int main() {
    A<short> a, p = &a;
    p->decltype([](A<short> x){return x;}(a))::~A();
  }  // Previously triggered an abort after an error was issued for the
     // invalid use of a lambda inside a decltype construct.

This is now fixed.


9/10/14  [EDGcpfe/15405]
allocated_in_region count with COMPILE_MULTIPLE_SOURCE_FILES

In configurations with DEBUG set to TRUE, the front end maintains a tally
of the amount of storage allocated in each region.  With
COMPILE_MULTIPLE_SOURCE_FILES set to TRUE, regions can be freed and reused
for subsequent source files, but the usage count for such regions was not
reset.  This is now fixed.


9/9/14   [EDGcpfe/15398]
Assignment to const-qualified types in prototype instantiations

In GNU, Clang, and Microsoft modes, the front end no longer issues an error
when attempting to assign to an lvalue with a known "const" type during a
prototype instantiation.  (However, any real instantiation of the associated
template will result in an error.)  For example:

  template<class T> struct S {
    int *const p;
    void f() { p = 0; }  // No longer an error in some C++ modes.
  };

(In the case of Clang mode, this is a little more lenient than the Clang
compiler itself: Clang accepts the code above, but does not accept it if the
assignment is to a variable not declared in a dependent scope.  Also, this
change is less likely significant in Microsoft mode since by default no
prototype instantiation of function definitions is performed in that mode.)


9/8/14   [EDGcpfe/15385]
Microsoft C++ compatibility: Unrestricted unions

In Microsoft C++ modes with microsoft_version >= 1900, the front end now
implements the C++11 rules for union members (i.e., "unrestricted unions").
See also the entry of 1/17/13 for EDGcpfe/9165.


9/8/14   [EDGcpfe/15378]
Spurious "not constant" error with dependent constructor call

In a template definition, a dependent constructor call initializing a
variable that later appears in a context requiring a constant expression
previously resulted in an error.  This is now fixed.  For example (with
--c++11):

  template<class T, T N> struct S {
    static constexpr T x = N;
  };

  template<typename T> int func() {
    const T v(16);  // Initialization by dependent constructor call
    S<T, v + 1> s;  // Use of "v" was previously incorrectly diagnosed as
                    // not a constant, now accepted
    return s.x;
  }


9/5/14   [EDGcpfe/15388]
GNU compatibility: Compatibility of extern __inline definition replacement

GNU C and C++ allow a function definition to be provided "for inlining only"
and also a later declaration or definition for non-inline use.  Previously,
the front end did not check the compatibility of the declarations involved,
and as a result did not apply type composition rules.  Now it does unless both
declarations are unprototyped.  For example:

  extern __inline__ int f(double n) { return n; }
  int f();  // Unprototyped declaration; now the composite type "int (double)"
            // is retained.
  int g(int n) { return f(n); }

The second declaration of f introduces a separate routine entry.  Previously,
the type for that second entry was unprototyped (since the second declaration
is unprototyped).  Now, the ordinary type composition rules are applied: The
second routine entry the also has a prototyped type with a parameter of type
"double".  That in turn ensures that n is converted to "double" in the call
"f(n)".


9/4/14   [EDGcpfe/13497,EDGcpfe/15400]
Mangled name collision for lambdas in default arguments of local class members

The front end previously incorrectly handled the mangling of lambdas appearing
in default arguments of a member function of a local class.  This error could
result in duplicate mangled names.  For example:

  int main() {
    struct A {
      int x;
      A(int i = []{return 1;}(),
        int j = []{return 1;}()) : x(i-j) {}
    };  // The two closure types were previously mangled the same way.
    return A().x;
  }

This is now fixed.  (Since it only affects local types, this changes does not
raise an ABI incompatibility.)


9/4/14   [EDGcpfe/15402]
Microsoft compatibility: Explicit enum with bool "base" type

In Microsoft mode, the front end previously did not permit bool as an explicit
underlying type for an enum type (see the entry of 9/27/10 for EDGcpfe/10112).
That restriction is now lifted when microsoft_version >= 1800.


9/4/14   [EDGcpfe/15384,EDGcpfe/15386]
Capturing "this" in nonstatic data member initializers

Previously, the front end did not permit the capturing of the "this" pointer
by lambda expressions appearing in nonstatic data member initializers.  That
limitation is now lifted.  For example, in C++14 mode:

  struct S {
    int a;
    struct N { int b; } n = { [=]{ return a; }() };
      // The initializer for n implicitly captures this.  Now accepted.
  } s = { 42 };  // s is initialized to { 42, { 42 } }.


9/2/14   [EDGcpfe/12793,EDGcpfe/14368,EDGcpfe/15248]
Abort on lambda in default argument

In some cases involving default arguments containing a lambda enclosing a
local class type, the front end aborted during IL lowering in the function
type_is_lambda_in_default_argument.  For example:

  void g(int x = []{ struct A { A() {} void f() {} }; return 1; }()) {}
    // Previously aborted during lowering.

This is now fixed.


9/2/14   [EDGcpfe/15395]
Lowering of scoped enumeration types

In configurations that support lowering but have the configuration macro
PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE set to FALSE, the use of a typedef to
refer to a scoped enumeration type had caused the premature lowering of the
scoped enumeration type, potentially causing undesired behavior.  In the case
below, with --c++11, the static assertion had triggered:

  enum class E : char {};
  void foo() {
    typedef E X;
  }
  E e;
  char f(bool);
  int f(...);
  static_assert(sizeof(f(e)) == sizeof(int), "should not be convertible");


9/2/14   [EDGcpfe/15389]
Spurious diagnostic on override modifiers

In modes supporting the "override" and/or "new" member function modifiers, the
front end sometimes issued diagnostics when such a modifier appears in a class
template.  For example, in C++11 mode:

  struct B {
    virtual void f(int);
    virtual void f(char);
  };
  template<typename T> struct D: B {
    void f(T) override;  // Previously triggered an error and a warning.
  };                     // Now accepted.

This is now fixed.


9/2/14   [EDGcpfe/15396]
Restored optimization for lvalue related class cast

As a result of the expression changes that were made in version 4.0, the
optimization of suppressing the NULL-preservation check for some lvalue
related class casts during lowering had inadvertently been removed.  A change
has been made that will restore the previous behavior on cases like this
(where an eok_question had been introduced during the cast):

  struct A {
    virtual void v();
  };
  struct B {
    int x;
    void g();
  };
  struct D : A, B {};
  D& f();
  void h() {
    f().g();    // No longer has an eok_question operation.
  }


8/29/14  [EDGcpfe/15237]
Microsoft compatibility: constexpr

In Microsoft mode with microsoft_version >= 1900 the front end now accepts
the C++11 constexpr feature.  However, a keyword "constexpr" specified on a
nonstatic member function is ignored with a warning in such modes.  That
limitation is lifted if C++11 mode is enabled (e.g., with the command-line
option --c++11), except on "dllimport" constructors (where constant-folding
can lead to implementation difficulties with the initialization of virtual
function tables).


8/25/14  [EDGcpfe/14686]
C++14: apostrophe as digit separator

The front end now accepts in --c++14 mode the apostrophe character as a
digit separator in numeric literals, as described in C++ Committee document
N3781.  The feature is also controlled by the --[no_]digit_separators
command-line option.  For example,

  long l = 2'147'483'647;  // Equivalent to 2147483647


8/22/14  [EDGcpfe/15379]
Downgrade diagnostic on virtual function declared but not defined in a
local class

According to the C++ standard, a non-pure virtual function is "odr-used", and
as such, an error had been issued when a virtual function in a local class
had been declared but not defined (because a reference to the function
will be in the vtable, causing an error at link time).  In cases where
the local class is unused, the error might be considered spurious, so it
has been downgraded to a warning (except in strict mode).  For example:

  void g() {
    struct A {
      virtual void f();   // Now a warning except in strict mode.
    };
  }


8/21/14  [EDGcpfe/15372]
Microsoft compatibility: allow non-final template default argument

The Microsoft compiler allows a template to have a default template
argument followed by a template template parameter without a default argument.
An error is issued on an attempt to make use of the default argument.
We now emulate that behavior in Microsoft mode.

  template <class T = int, template <class X> class T2> struct A {};


8/21/14  [EDGcpfe/15374]
GNU and clang compatibility: push_macro and pop_macro

The push_macro and pop_macro pragmas, previously only enabled in Microsoft
mode, are now enabled in GNU mode (when gnu_version >= 40403) and clang
mode.


8/19/14  [EDGcpfe/15368]
Incorrect lowering for certain lambda captures

In configurations where DO_RETURN_VALUE_OPTIMIZATION_IN_LOWERING is TRUE
and the front end has determined that a routine is a candidate for the
optimization, incorrect code had been generated in the case where the
returned value was used as the source for a lambda capture (when the
variable is captured by value).  Now fixed.  In the following example the
value captured for "a" in the lambda was not properly initialized (--c++11):

  int x = 0;
  struct A {
    int m;
    A(int _m) : m(_m) {}
    A(const A &x) : m(x.m) {}
  };
  A f() {
    A a(99);
    [a]() -> void { x = a.m; }();
    return a;
  }
  int main() {
    f();
    return x != 99;   // Had returned non-zero.
  }


8/18/14  [EDGcpfe/15308]
Promoted type for operations on bit fields

By default the front end now treats certain operations applied to bit fields
as bit fields for the purpose of determining the promoted type of that
operation.  For example, consider

  struct S { unsigned bf: 7; } *p;

p->bf promotes to type int (except in PCC and Microsoft modes) because all its
values can be represented by (signed) int.  Previously, however, expressions
like (0, p->bf), ++p->bf, and p->bf = 3, promoted to unsigned int (the type
used to declare the bit field).  Now these expressions promote to int also.

The C and C++ standards are not very clear in describing the required behavior
in cases like these, but we now believe this change matches the intent of the
standards.  If needed, the prior behavior can be restored by setting the global
variable bit_field_promotion_applies_to_some_operations to FALSE (as is done in
GNU modes with gnu_version < 40000).


8/15/14  [EDGcpfe/14107]
C++14: binary literals

The front end now accepts binary literals, as described in C++ Committee
paper N3472, in C++14 mode.  For example, with --c++14:

  int i = 0b1110;  // Equivalent to 0xe or 016


8/14/14  [EDGcpfe/15358]
Return statement of generated assignment operators

The return type of a compiler-generated assignment operator for a class type
X is "reference to X" (i.e., X&), but the IL representing the returned
expression for the assignment operator simply returned an enk_variable node
for "this" with type "pointer to X" (i.e., X*).  This situation was an
accidental leftover from versions of the front end prior to 4.0, when lvalues
were represented by pointers to the underlying object.  This is now fixed.


8/14/14  [EDGcpfe/15359]
Microsoft compatibility: noexcept

The C++11 feature "noexcept" is now enabled in Microsoft modes with
microsoft_version >= 1900.


8/14/14  [EDGcpfe/15357]
Microsoft compatibility: Implicit noexcept specifiers

In Microsoft modes that enable the C++11 "noexcept" feature, the front end now
follows the standard rules for the default exception specification of
destructors and deallocation functions (see the entries for EDGcpfe/10617 and
EDGcpfe/13566).  Previously, the default behavior in Microsoft mode was as if
the command-line option --no_implicit_noexcept was specified.  For example:

  struct S { S() noexcept {} } *p;
  static_assert(noexcept(delete p), "Unexpected");
    // Now passes in Microsoft modes that enable the noexcept feature.


8/14/14  [EDGcpfe/15346]
Case label constants in GNU mode

In GNU modes that don't enable the C++11 constexpr feature (including GNU C
mode), the front end accidentally accepted certain non-integer constants for
case label constants.  This regression was introduced by the changes for the
constexpr feature.  For example:

  int g(int p) {
    switch (p) {
      case (double)0: return 1;  // Previously accepted in some GNU modes.
      case 1.0: return 2;        // Ditto.
      default: return 3;
    }
  }

This is now fixed (an error is issued for such labels).


8/13/14  [EDGcpfe/15356]
Abort on re-declaration of inline function with the GNU noinline attribute

In some cases, redeclaring an inline function with the GNU noinline attribute
resulted in an internal error (in set_inline_flag, in il.c).  For example, in
GNU C99 mode:

  inline void f() __attribute__((noinline));
  inline void f() {}  // Previously triggered an internal error in some modes.

This is now fixed.


8/13/14  [EDGcpfe/15349]
Representation of pointer difference (IL CHANGE)

Previously, in a pointer difference involving pointer types with different
type qualifiers, one of the operands was implicitly cast to the type of the
other operand.  This is no longer done.  For example:

  long pdiff(char *p, char const *q) {
    return p-q;  // Previously, the second operand was implicitly converted
  }              // to char*.  This is no longer done.

This is a slight IL CHANGE.


8/11/14  [EDGcpfe/15352]
Microsoft compatibility: Suppressed special members

In Microsoft C++ modes, the front end sometimes suppresses the implicit
declaration of a special member if the associated definition would trigger an
error (see the entry of 5/11/07).  However, the changes for EDGcpfe/13365
limited this behavior to Microsoft C++ modes with microsoft_version < 1400,
because the implicit special members are visible in some contexts (e.g., with
using-declarations).  Now, when microsoft_version is in the 1400-1899 range,
implicit special members that would trigger an error if they were to be defined
are still declared but they are ignored for overload resolution purposes.  For
example:

  struct S {
    S();
    template <typename T> S& operator=(const T&) {
      return *this;
    }
    int &ir;    // A reference member would cause an error when defining
                // implicit operator=.
  };
  S s;
  void f() {
    s = S();    // Previously an error with --microsoft_version=1400.
  }             // Now okay because the generated operator= is ignored
                // (unless microsoft_version >= 1900).

An additional change was made to elide copy construction early if a copy
constructor is generated (again, when microsoft_version < 1900).  That ensures
that cases like the following are accepted even though the copy constructor is
not considered.

  class B { B(B const&) {} };  // Private copy constructor.
  struct D : B {  // Copy constructor suppressed in Microsoft C++ mode
    D();          // because its definition would lead to an error.
  };
  int main() {
    D x = D();  // Accepted despite the suppressed copy constructor because
  }             // copy elision is applied early.


8/11/14  [EDGcpfe/15261]
C++-generating back end: dependent friend declarations

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the code
produced by the C++-generating back end for a friend declaration naming a
dependent nested type incorrectly used the "class" keyword instead of the
"typename" keyword.  This is now fixed.  For example:

  template<typename T> struct S {
    friend typename T::C;  // Previously generated as "class T::C"
  };

In addition, the front end rejected uses of this and other forms of extended
friend syntax (see the entry of 5/10/06) in non-C++11 g++ and clang modes,
even though g++ has accepted these forms by default since version 4.7, as
does clang.  The front end now also accepts them (with a warning on first
use) in the corresponding non-C++11 modes.


8/8/14   [EDGcpfe/15351]
Lowering of switch and case statements

When a switch statement contains an initialization, lowering may change
the switch statement into a block statement (to contain the initialization)
and put the new switch statement in the block.  Since all case/default
statements have a pointer to the switch statement that contains them,
this re-writing had caused the case/default statements to erroneously
point to a block statement.  Similarly, lowering some case statements
had also led to incorrect IL.  Now fixed.  For example:

  int f() {
    switch (int i=20) {
      case 0:  return 0;
      default: return 1;
    }
  }


8/8/14   [EDGcpfe/15350]
GNU compatibility: "packed" attribute on enum

It appears that a "packed" attribute on an enum definition is ignored
by GNU versions earlier than 4.0.0.  The front end now emulates that
behavior.  The following example has an exit code of 1 when --gnu_version 30400
is used and an exit code of 4 (on most machines) when --gnu_version 40000
is specified:

  enum e { } __attribute__((packed));
  int main() {
    return sizeof(e);
  }


8/6/14   [EDGcpfe/15338]
Microsoft C++ compatibility: Generated special member functions

In Microsoft C++ mode with microsoft_version >= 1900 move constructors and move
assignment operators may now be implicitly declared or defined with "= default"
(as per the rules for standard C++11).  Furthermore, in such modes the prior
Microsoft-mode-specific behavior of not at all declaring an implicit special
member function if generating its definition would result in an error (see the
entry of 5/11/07) is now replaced by standard C++11 behavior as well (usually,
the generated special member is a deleted member in those cases).  Finally, the
the generation of move assignment operators and move constructors in C++/CLI
and C++/CX managed types is now disabled.


8/5/14   [EDGcpfe/15293]
GNU compatibility: Allow a constant as the second operand of __builtin_va_start

In GNU modes, the second operand of __builtin_va_start is now permitted to be
a constant (a warning is issued) instead of the usual variable.  For example:

  void g(int p, ...) {
    __builtin_va_list  ap;
    __builtin_va_start(ap, 42);  // Now accepted with a warning in GNU C++
  }                              // mode.

(GCC appears to generally ignore the second operand of __builtin_va_start.)


8/5/14   [EDGcpfe/15285]
Missing diagnostic on use of an opaque enum declaration in a type name

A declaration like
  using T = enum class E: int;
is not valid in C++11.  This is now diagnosed (with an error in strict mode,
and a warning otherwise).


8/5/14   [EDGcpfe/15336]
GNU ABI compatibility: Returning classes with trivial copy constructor and
nontrivial move constructor

Ordinarily, returning a class type with a nontrivial move constructor is
implemented by passing a hidden pointer parameter to the result's storage
(the same is true for a class type with a nontrivial copy constructor).
However, when emulate_gnu_abi_bugs is TRUE and gnu_abi_version < 40600, the
front end now no longer applies this rule if the class type has a trivial
copy constructor.  For example:

  struct S {
    S();
    S(S&&);  // Nontrivial move constructor (but a trivial generated copy
  };         // constructor).
  S f() { return S(); }  // Now implemented without a hidden pointer
                         // parameter in some configurations.

This appears to match the behavior of corresponding versions of GCC.


8/4/14   [EDGcpfe/15187]
Reconstructing file tree structure from #line directives

When the front end preprocesses a source file, the tree structure of the
header files named in #include directives is reflected in the
first_child_file, last_child_file, and next fields of the resulting
a_source_file IL entries.  This nesting information can also be inferred
from the #line directives in output produced by the GNU preprocessor, which
have additional fields following the file name that reflect entry into and
exit from header files.  The front end previously ignored these fields when
compiling a file that had already been preprocessed, producing a flat list
of a_source_file IL entries for the files named in #line directives.  It
has been changed, however, to use the additional fields when they are
present, and for such files the tree structure of the source file entries
in the IL is now the same as if the front end had processed the original
#include directives.


8/4/14   [EDGcpfe/15339]
Spurious SFINAE failure on access of member of a deduced reference parameter

Consider the following C++11 case:

  struct S { void f(); };
  template<typename> struct X {};
  template<typename T> auto g(T &&p)->X<decltype(p.f())>;  // (1)
  void h(S s) {
    g(s);  // Previously triggered a spurious error.
  }

When matching the call "g(s)" to template (1), the front end deduces T to be
S& (because an lvalue is passed to the "T&&" parameter), and with the C++11
rules for collapsing references, this results in the type of p also being S&.
The front end then mistakenly looked up "f" in "p.f()" as if it were denoted
by "T::f", which fails because T is a reference type and not a class type.
That failure disqualified g<S&> as a candidate (i.e., SFINAE behavior), and
triggered a spurious error about no instance of g matching the call "g(s)".
This is now fixed: "f" in "p.f()" is looked up in the type of "p" (which is
just "S" during the deduction process).


8/4/14   [EDGcpfe/15337]
Aggregate initializers and designators into C anonymous unions

Some C modes (e.g., GNU C mode) permit both initializer designators and
nonstandard anonymous unions.  The front end previously handled designators
into nested anonymous unions incorrectly, which could result in spurious
warnings and incorrect results.  For example:

  struct S {
    union {
      int a;
      float b;
    };
    int c;
  } s = { .a = 1, 2 };

In C modes that accept this (e.g., GNU C mode with gnu_version >= 40600), the
front end previously issued a spurious warning about "2" being an excess
initializer, and produced IL that failed to initialize s.c (which should be
initialized to 2 in this example).  That is now fixed.


7/31/14  [EDGcpfe/15334]
Abort on opaque enum declaration that is part of another declaration

In Microsoft and Clang modes, an opaque enum declaration can be part of
another declaration (see the entry for EDGcpfe/14944).  However, when
GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, the front end aborted with an internal
error in attach_tag_attributes (decl_spec.c) if such a "non-autonomous"
opaque enum declaration followed a definition.  For example:

  enum X : int {x};
  typedef enum X : int X;  // Previously aborted in some Clang and
                           // Microsoft modes.

This is now fixed.


7/31/14  [EDGcpfe/15309]
Incorrect handling of SFINAE case with partial template argument list

Consider the following C++11 case:

  template<typename X, typename Y> X f(Y);
  template<typename T> auto g(T t) -> decltype(f<double>(t));  // (1)
  int main() {
    g(4);  // Previously triggered a spurious error.
  }

When matching the call "g(4)" to template (1), the front end deduces T to be
int (the type of "4") and then verifies for SFINAE purposes that substituting
that T in the return type is valid.  Previously, that substitution failed for
names like f<double> where the template argument list doesn't cover all the
template parameters (because the additional parameters can be deduced).  In
the example above, that results in a spurious error claiming there is no match
for the call "g(4)".  That problem is now fixed.


7/30/14  [EDGcpfe/15304]
Missing diagnostics on alignas(...) and _Alignas(...) in invalid contexts

The front end previously failed to diagnose attempts to use the alignas
specifier in certain contexts not permitted by the C++11 and C11 standards.
For example, in C++11 mode:

  char alignas(4) buf[100];  // Now an error.  (alignas(4) should precede
                             // "char" or immediately follow "buf".)

C11 has different constraints; for example:

  char c _Alignas(4);  // Now an error.  (_Alignas(4) should precede "c" or
                       // "char".)

That is now fixed: A diagnostic is now emitted for such cases.


7/29/14  [EDGcpfe/15242]
Parenthesized expressions

Expression nodes now include a new flag is_parenthesized that is set to TRUE
if the node results from a nonconstant expression that is parenthesized in the
source.  For a constant expression, the flag is recorded in the backing
expression if one is available.  This flag is recorded even when performing IL
lowering (unlike the eok_parens representation; see the entry for
EDGcpfe/9108).


7/29/14  [EDGcpfe/15327]
Microsoft compatibility: Enum types used as qualifiers

The changes to add support for C++11-style scoped enumeration types (see the
entry of 10/31/08 for EDGcpfe/8528 and EDGcpfe/8747) accidentally broke the
ability to use an enumeration type in certain vacuous destructor invocations
in Microsoft C++ modes for which microsoft_version < 1400.  For example:

  enum E { e };
  template<typename T> void g(T p) {
    p.T::~T();
  }
  int main() {
    g(e);  // Triggered a parsing error in the instantiation of g<E>.
  }

This is now fixed.


7/29/14  [EDGcpfe/15258]
Clang compatibility: C++11 features accepted in non-C++11 mode

Some C++11 features are enabled in non-C++11 GNU C++ mode (see the entry of
9/9/13 for EDGcpfe/14245 et al.).  Since the front end treats Clang mode as a
special GNU C++ mode, it potentially also accepted the same set of features in
non-C++11 Clang mode, but since Clang mode is usually enabled with a fairly
small value default value for gnu_version, the extensions were often not
observable in Clang mode.

Now the front end more closely follows the actual Clang compilers in this
regard (in Clang mode).  Specifically, the following C++11 features are
enabled in non-C++11 Clang mode: deleted and defaulted functions, nonstatic
data member initializers, and rvalue references.  For all these, the first
use is warned about and clang_version must be at least 30000.


7/29/14  [EDGcpfe/15114]
Missing diagnostic on invalid default argument in friend template declaration

The C++11 standard requires that a friend function template declaration
that specifies a default template argument be a definition and be the only
declaration of the template in the program.  We now diagnose violations
of these rules.

  template <class U> int g();
  template<class T>
  class A {
    template<class U=int> friend T f();  // not definition
    template<class U=int> friend T g(){}  // not only declaration
  };
  A<int> a;


7/28/14  [EDGcpfe/15331]
Invalid IL generated when using a default argument in GNU C++ 3.4.x mode

The changes for EDGcpfe/10809 and EDGcpfe/13359 (see entry of 11/14/12) had a
bug that caused invalid IL to be generated in GNU C++ 3.4.x mode if a default
argument of a member or friend function declaration requires a destructor call
but no conversion to the parameter type.  For example:

  struct X { ~X(); };
  struct S {
    S(X p = X());
  };
  S x;  // Previously triggered the creation of invalid IL.  Now okay.

This is now fixed.


7/25/14  [EDGcpfe/15315]
Spurious error on sizeof... in a local class or lambda expression

The front end previously issued an error when sizeof... appeared in a local
class or lambda expression and was applied to a function parameter pack from
a function enclosing that local class or lambda expression.  For example:

  template<typename... T> void f(T ...p) {
    struct A {
      int x[sizeof...(p)];  // Previously triggered an error.
    };
  }

The error was due to an incorrect interpretation of the standard; it is no
longer issued for cases like these.


7/24/14  [EDGcpfe/15310]
Position information for aggregate initializer constants

The front end now records the positions of aggregate initializer constants in
more cases.  For example:

  double z[] = { 2 };

In this case, the a_constant entry representing "2" now records the position
of that literal.  Note that prior to the changes for EDGcpfe/14588, that
position information could be retrieved from the backing expression.


7/24/14  [EDGcpfe/15133]
Internal error in C++-generating back end on some local declarations

When a local declaration starts with a template-id that includes an argument
that is also the first declaration of a class type, the front end previously
produced an invalid sequence of source sequence entries.  This in turn resulted
in an internal error in the C++-generating back end (in function
check_for_and_take_source_seq_entry).  For example:

  template<typename> struct X {}; 
  int main() {
    X<struct S> x;  // Previously triggered an internal error in the
  }                 // C++-generating back end.

This is now fixed.


7/23/14  [EDGcpfe/15288]
Incorrect preprocessor output for raw string literals

Preprocessor output (e.g., the output of the -E command-line option)
incorrectly failed to revert changes made when translating the physical
form of a source line into its internal representation (for embedded
newlines, line splices, and trigraphs) when they occur inside a raw string
literal.  (The IL, however, did have the correct value of such raw string
literals.) This is now fixed.  For example:

  // The following initializer was previously displayed in preprocessor
  // output as R"<>(a\nb\ncd#)<>":
  const char * g = R"<>(a
  b
  c\
  d??=)<>";


7/22/14  [EDGcpfe/15081]
Abort in C++-generating back end on redefinition of typedef with attributes

In GNU C++ mode the C++-generating back end sometimes aborted in il_to_str.c
(function output_type_attributes) when attempting to render a typedef
redefinition that includes type attributes.  For example:

  typedef float AF __attribute__ ((__may_alias__));
  typedef float AF __attribute__ ((__may_alias__));
    // The front end previously aborted while rendering the second typedef.

This problem (which was caused by incorrect IL for the declared type recorded
in a secondary source sequence entry) is now fixed.


7/22/14  [EDGcpfe/15317,EDGcpfe/15341]
Mismatched types used in lowered run-time test for array new

In cases where lowering inserts a run-time check to verify the size of
an array new operation (see the Changes entry for EDGcpfe/13489), the
inserted checks may have had mismatched types as operands to some
operations, which might cause problems for some back ends.  For example
(with --c++11):

  long p = 1;
  void f(void) {
    new int[p];
    new int[p] = {1};
  }


7/21/14  [EDGcpfe/15295]
Incorrect preprocessing output with macro_preempts_udl_suffix

As described in the entry for EDGcpfe/14857, when the global variable
macro_preempts_udl_suffix is TRUE (as it is by default in g++ mode), an
apparent user-defined string literal will be lexed as an ordinary string
literal followed by an identifier if that identifier has been defined as a
macro name.  The preprocessing output produced by the front end (with the
-E command-line option, for example) failed to show that macro's expansion,
however.  This has now been fixed.  For example, with --gnu_version=40802
--user_defined_literals -E:

  #define A "xyz"
  #define B "abc"A
  char *s = B;  // Previously displayed as: char *s = "abc"A;
                // Now displayed as:        char *s = "abc" "xyz";


7/21/14  [EDGcpfe/15305]
Remove unnecessary zeroing when lowering partially initialized aggregates

The initialization of an entity to a partially initialized aggregate constant
is often lowered to an assignment (typically to the value of a static
temporary).  Previously, the original stmk_init had been lowered to an
initk_zero to ensure that all fields in the aggregate were properly
initialized, but that superfluous step has been removed (since the added
assignment applies to all fields of the aggregate).  For example (with --gcc):

  typedef union {
    struct {
      char a;
      char b;
    };
    short s;
  } u;
  short f() {
    return ((u) { { a:1 } }).s;  // Had generated a memset call.
  }


7/16/14  [EDGcpfe/15299]
Function modifiers accepted in invalid syntactic locations

The front end previously accepted the context-sensitive function modifiers
"final" and "override" after function declarators that aren't for member
function declarations.  For example:

  struct A {};
  typedef void (A::*pmf)() final;  // Previously accepted in C++11 mode.
                                   // Now an error.

This is now fixed (i.e., an error is issued on such cases).


7/15/14  [EDGcpfe/15269]
Unbounded loop in merge_name_reference_lists

When simultaneously compiling multiple translation units in GNU C++ mode, the
front end sometimes ended up in a unbounded loop in merge_name_reference_lists
(in trans_copy.c).  This behavior was caused by two routine entries (one of
which is "extern __inline__"; see the Changes entry of 6/18/02) sharing the
same list of a_name_reference entries; this is an invalid IL situation.  This
problem is now fixed.


7/15/14  [EDGcpfe/15186]
Abort in C++-generating back end on function declarator in trailing return type

The C++-generating back end sometimes aborted (in get_param_for_param_ref,
il_to_str.c) with an internal error when attempting to render a reference to a
parameter of a function declaration from within a function declarator appearing
in the trailing return type of that declaration.  For example:

  template<class T> struct S {};
  auto f(int p) -> S<void (decltype(p))>;  // Previously aborted in some
                                           // configurations.  Now okay.

This is now fixed.


7/15/14  [EDGcpfe/15263]
Spurious error on generation of inheriting constructor using protected member

In C++11 mode, the front end incorrectly handled the generation of an
inheriting constructor whose generation requires a call to a protected base
class constructor.  This resulted in spurious access errors.  For example:

  struct B {
  protected:
    B(int);
  };
  struct D: B {
    using B::B;
    friend void g();
  };
  void g() {
    D d(2);  // Triggers the generation of D::D(int).  Previously resulted in
  }          // an error about B::B(int) not being accessible.  Now okay.

This is now fixed.


7/15/14  [EDGcpfe/15291]
GNU C++ compatibility: internal error on VLA in default template argument

An internal error could occur (in mangled_encoding_for_type_full) if a
VLA type was used as a template argument in a default template argument.
Now fixed.

  template <typename T> struct A {
    typedef bool type;
  };
  template <typename T, typename A<T>::type U = false> void g(const T &t) { }
  void g(...) { }
  void f(int x) {
    char arr[x];
    g(arr);
  }


7/15/14  [EDGcpfe/15296]
__cpp_aggregate_nsdmi and cxx_aggregate_nsdmi

When support was added for the C++14 feature permitting aggregate class types
to have nonstatic data member initializers (see the entry for EDGcpfe/14146),
the setting of the corresponding feature-test macro (__cpp_aggregate_nsdmi)
was not updated to reflect that support.

This is now fixed.  The result of __has_feature(cxx_aggregate_nsdmi) in Clang
mode has also been updated.


7/14/14  [EDGcpfe/13100]
Missing diagnostic for invalid pack expansion

The front end previously permitted a mem-initializer for a data member to be a
pack expansion even though the C++ standard does not permit this.  For example:

  template<typename ...T> struct S {
    S(T ...p): m(p)... {}  // Previously accepted; now a discretionary error.
    int m;
  };

This is now fixed: A discretionary error is emitted.


7/14/14  [EDGcpfe/6235,EDGcpfe/9112,EDGcpfe/14852,EDGcpfe/15284]
Microsoft compatibility: Truncation of enum constant values

In Microsoft modes, the front end now allows the specified constant value of an
enumerator to be outside the representable range of the enumerator's underlying
type.  For example:

  enum { e = static_cast<unsigned long long>(-1) };
                                           // Now accepted in Microsoft mode.  
A warning is issued in such cases (and the value is truncated).


7/14/14  [EDGcpfe/15260]
Clang compatibility: __is_literal

In Clang mode, __is_literal is now equivalent to __is_literal_type.


7/14/14  [EDGcpfe/14945]
Microsoft compatibility: Implicit enum base type

When declaring an enum type twice with just one of the declarations having an
explicit "base" type, Microsoft compilers appear to assume that the declaration
without an explicit base type has an implicit "int" base (even for non-scoped
enum types).  This front end now emulates this behavior.  For example:

  enum E: int;
  enum E {};  // Usually an error because of the missing explicit base type,
              // but now accepted in Microsoft C++ mode.


7/11/14  [EDGcpfe/15257]
Clang compatibility: __char16_t/__char32_t keywords

The clang compiler defines __char16_t and __char32_t keywords in all C++
modes, and now so does the front end (in clang emulation mode).  The
__char16_t and __char32_t keywords have the same meaning as the
char16_t and char32_t keywords respectively.  For example (with --clang):

  typedef __char16_t char16_t;
  typedef __char32_t char32_t;

Also introduced during this change is the ability to specifically target
a clang back-end (C or C++) compiler by using the new
CLANG_IS_GENERATED_CODE_TARGET and CLANG_TARGET_VERSION_NUMBER configuration
macros.  For the most part, these are similar to the existing
GCC_IS_GENERATED_CODE_TARGET and GCC_IS_GENERATED_CODE_TARGET macros.


7/10/14  [EDGcpfe/15290]
GNU C++ compatibility: lookup in dependent base class

A change made in version 4.5 (see EDGcpfe/12738 on 3/9/12) could cause a
name from a dependent base class not to be found in cases where g++ does
find the name.  Now fixed.

  struct B { int i; };
  template <typename T> struct A : T {
    template <typename U> int f(U) { return 1; }
  };
  // Identifier "i" not found during the prototype instantiation of A<B>::f
  template <> template <typename T> inline int A<B>::f(T) { return i; }
  int main() {
     A<B> a;
     a.f(1);
  }


7/10/14  [EDGcpfe/15119]
Internal error on type declared in sizeof expression

When GENERATE_SOURCE_SEQUENCE_LISTS and IL_SHOULD_BE_WRITTEN_TO_FILE are both
TRUE, the front end sometimes aborted with an internal error in
read_memory_region ("IL entry write-read difference") if a type was declared
in a sizeof expression.  For example:

  enum class E { e = sizeof((struct S*)0) };
    // Sometimes triggered an abort in some configurations.

This is now fixed.


7/9/14   [EDGcpfe/15281]
Microsoft and Clang compatibility: Ambiguous user-defined conversions

Consider the following case:

  struct X {};
  struct Y {
    operator X const&() ;
    operator X&() ;
  };
  void g(Y y) {
    (X const&)y;
  }

Somewhat surprisingly, the standard considers the conversion of y to X const&
via a user-defined conversion ambiguous.  This means that an expression like
"static_cast<X const&>(y)" must produce an ambiguity error.  However, for a
C-style cast (as in the example) or a functional-style conversion, a strict
reading of the standard requires the conversion to be treated as a
reinterpret_cast instead (without invoking any of the conversion functions).
The Microsoft and Clang compilers adhere to that reading and we now implement
that also in the corresponding front end modes.  However, in other modes we
continue to issue an ambiguity error since the strict interpretation is
arguably dangerous.  (The issue has been brought to the attention of the
standardization committee, and we will adjust the front end's behavior after
the rules for this type of situation have been clarified.)


7/9/14   [EDGcpfe/14985]
Microsoft compatibility: String literals in array of character initializers

In Microsoft modes, the front end now treats a string literal appearing in the
braced initializer for an array of characters matching the string literal type
as if the literal were a comma-separated list of characters instead.
For example:

  char str[] = { 48, "123" };

is now treated as

  char str[] = { 48, 49, 50, 51, 0 };

in Microsoft mode (assuming an ASCII-like character encoding).  A string
literal in such a case cannot be followed by another initializer:

  char str[] = { 48, "123", 52 };  // Error, too many initializer values.


7/9/14   [EDGcpfe/15278]
Aggregate initialization involving a constexpr element constructor call

In some cases, an aggregate initializer containing an element initializer that
is a call of a constexpr constructor producing a constant result was mistakenly
treated as not being a constant initializer, which in turn could lead to the
initialization not being treated as a static initialization when it should have
been.  For example:

  struct Int {
    int i;
    constexpr Int(int i): i(i) {}
  };
  struct Aggr { Int i; } v = { -1 };  // Previously treated as a dynamic
                                      // initialization.

This is now fixed.


7/8/14   [EDGcpfe/15273]
GNU compatibility: suppress conversion on asm memory operands

Generally speaking, the constraint string for a GNU asm operand is left for the
back end to process, but an exception has been made in the case of the "m",
"o", "v", "<", and ">" constraints, which indicate that the operand is a memory
operand (see https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html).
Previously, when the operand referred to an object with class type, a
conversion operation was applied, but that is now suppressed on memory
operands.  The following example had given an ambiguity error due to
the conversion operation, but the conversion operation is now suppressed
(with --g++):

  struct A {
    operator int();
    operator unsigned int();
  };
  void f(A const& op, int x) {
    asm("cmpl %[left],%[right]\n" :: [left] "o" (op), [right] "a" (x));
  }


7/7/14   [EDGcpfe/15276]
GNU C++ compatibility: destructor call using non-dependent base class name

A change in version 4.9 resulted in a spurious error in g++ mode on a
destructor call where the object had a dependent type, but the destructor
name was a non-dependent name that referred to a base class of the object
type in an actual instantiation.  Now fixed.

  namespace N {
    template <class T> struct A { ~A(); };
  }
  template <class T> struct B : N::A<int> {
    void f(B* p) {
      p->N::A<int>::~A();
    }
  };
  int main() {
    B<int> b;
    b.f(&b);
  }


7/7/14   [EDGcpfe/15272]
Assertion failure in equiv_template_arg_lists with secondary translation units

When simultaneously compiling multiple translation units, the front end
sometimes aborted with an assertion failure in equiv_template_arg_lists
("equiv_template_arg_lists: unequal arg list lengths") when dealing with
complex cases involving variadic template argument lists.  This is now fixed.


6/30/14  [EDGcpfe/15265]
Inadvertent pre-lowering of aggregate constants in C mode

The changes for EDGcpfe/8523 introduced the notion of pre-lowering an aggregate
constant, but that processing is not required in C mode and, in some cases,
had generated a lowered structure with zero size (despite having a non-NULL
field list).  For example (with --gcc):

  typedef struct {
    int m;
  } A;
  int f(int i) {
    return ((A) { i }).m;
  }


6/30/14  [EDGcpfe/15250,EDGcpfe/13864]
Abort on failure to fold conversion in initializer for constexpr variable

In C++11 mode, the front end sometimes failed to fold the conversion of a
constant derived class object to a base class in a constexpr initialization
context.  This could lead to an abort in decl_inits.c (in "initializer").
For example:

  struct B { int x = 42; };
  struct D: B {};
  constexpr B b = B(D());  // Previously aborted in C++11 mode.

This is now fixed.


6/30/14  [EDGcpfe/15241]
Pack expansion missing in some generic braced initializers

The front end sometimes failed to record the presence of a pack expansion if it
appeared in a braced initializer for a template-dependent type.  For example:

  template<typename T> struct S {
    template<typename ... U>
      S(U ... args): S{(T)args ...} {}  // The second "..." was not previously
  };                                    // not reflected in the IL.

This could, e.g., lead to incorrect rendering in the C++-generating back end
(in the example above, one of the ellipses went missing).  This is now fixed.


6/27/14  [EDGcpfe/15088]
Microsoft compatibility: internal error during partial ordering

An internal error could occur (in convert_constant_for_deduction) in
Microsoft C++11 mode during partial ordering or partial specialization
processing involving nontype template parameters.  Now fixed.

  template <class T1, class T2, int N> void f(T1, T2 (&a)[N]); // #1
  template <class T1, class T2, int N> void f(T1*, T2 (&a)[N]); // #2
  int main() {
    int i;
    int arr[5];
    f(&i, arr); // calls #2
  }


6/27/14  [EDGcpfe/15246]
Spurious error with default constructor with default arguments in GNU mode

The changes for EDGcpfe/14637 (see entry of 11/13/13) caused the front end
to sometimes not recognize a default constructor as such when it is a member
of a class template and it has parameters with default arguments.  This
problem, which only occurred in some GNU C++ modes with gnu_version >= 40700
and the --no_parse_templates option, could lead to spurious errors.  For
example:

  template<class T> struct S {
    S(T x = 0) {
      S<T> s;  // Previously triggered a spurious error.  Now okay.
    }
  };
  S<int> s;

This is now fixed.

Note that the error occurs during the prototype instantiation of S<T>::S even
though --no_parse_templates is an explicit request not to perform prototype
instantiations for nonclass templates.  That is because the affected GNU modes
must perform prototype instantiation to correctly handle a potential __bases
or __direct_bases operator that might occur during such an instantiation.  To
avoid this surprising effect, the front end now disables support for __bases
and __direct_bases if the --no_parse_templates is specified on the command
line.


6/27/14  [EDGcpfe/15218]
Abort on __is_literal_type in Microsoft C++ mode

The front end frequently aborted with an internal error in class_decl.c
(check_if_constexpr_generated_default_constructor) when processing the
__is_literal_type predicate for a non-aggregate class type (unless constexpr
was enabled).  For example:

  struct S { S(int); };
  bool const b = __is_literal_type(S);  // Previously aborted in some
                                        // Microsoft C++ modes.  Now okay.

This is now fixed.


6/26/14  [EDGcpfe/15224]
Abort on initializer for constexpr variable in prototype instantiation

The front end sometimes aborted with an internal error in "initializer" during
a prototype instantiation containing a template-dependent initializer for a
constexpr variable.  For example:

  struct S {
    int i;
    constexpr S(int v) : i(v) {}
  };
  template<typename T> void g() {
    constexpr S s(T::f());
  }

This is now fixed.


6/26/14  [EDGcpfe/15223]
Reference to freed template argument list

A template argument list that is pointed to by a pack rescan entry could,
in some (rare) circumstances, be freed, resulting in a dangling pointer.
This could conceivably result in a variety of incorrect behavior, but
has been observed in some cases to result in an internal error in
update_template_param_symbol.  Now fixed.


6/26/14  [EDGcpfe/15236]
Abort in scan_ctor_arguments for decltype

The changes for EDGcpfe/14756 introduced a bug causing the front end to abort
with an internal error in scan_ctor_arguments for certain complex cases.  This
regression is now fixed.


6/26/14  [EDGcpfe/15256]
Spurious error on dependent constructor initializer

The front end sometimes issued a spurious error on a dependent constructor
initializer during the prototype instantiation of a constructor template.
For example:

  template<typename> struct B {};
  struct D: B<void> {
    template<typename T> D(T): B<T>() {}  // Previously triggered a spurious
  };                                      // error.  Now okay.

This is now fixed.


6/26/14  [EDGcpfe/15259]
Clang compatibility: inline namespaces enabled in C++03 mode

Inline namespaces are now enabled in clang C++03 mode when clang_version
is >= 30000.

  inline namespace N {}


6/25/14  [EDGcpfe/14941]
Spurious error on instantiation of noexcept of member function template

A spurious "does not make use of any argument packs" could be issued
on a pack expansion that uses a template parameter pack of the enclosing
class in a noexcept specifier of a member function template.  Now fixed.

  template <bool B1, bool ... Bargs> struct A {
    static const bool value = B1;
  };
  template <class ... T> struct B {
    static const bool value = true;
  };
  template <typename ... T> struct C {
    template <class S> void f() noexcept(A<B<T&>::value ...>::value) {}
  };
  C<int> c;


6/24/14  [EDGcpfe/15208]
GNU C++ compatibility: __GNUC_STDC_INLINE__ and __GNUC_GNU_INLINE__

In GNU C mode, one of the macros __GNUC_STDC_INLINE__ and __GNUC_GNU_INLINE__
is defined depending on whether standard C99 "inline" behavior is in effect or
not (see the entry of 9/29/09 for EDGcpfe/8555).  Now, one of these macros is
also defined in GNU C++ mode (when gnu_version >= 40103): __GNUC_STDC_INLINE__
is defined in GNU C++11 mode, and __GNUC_GNU_INLINE__ is defined in other
C++ modes.

6/23/14  [EDGcpfe/15230]
Division by zero on explicit type alignment in some configurations

In configurations for which both macros GNU_EXTENSIONS_ALLOWED and
MICROSOFT_EXTENSIONS_ALLOWED are set to FALSE, the front end sometimes
aborted with a division by zero on a class type with an explicit alignment
specifier.  For example:

  struct alignas(16) S {};  // Previously aborted in C++11 mode in some
                            // configurations.

This is now fixed.


6/13/14  [EDGcpfe/15228]
GNU compatibility: Segfault in apply_warn_unused_result_attr

In a case like the one given below where the GNU __warn_unused_result__ is
applied to the function type by the use of parentheses, a segfault had
occurred in apply_warn_unused_result_attr and is now fixed.  For example
(with --g++):

  int (__attribute__((__warn_unused_result__)) f)();


6/12/14  [EDGcpfe/15112]
Significant parentheses around function call target dropped in C++-generating
back end

When a function name in a function call is parenthesized, the function name is
not subject to argument-dependent lookup (ADL).  The IL for function calls
includes a flag arg_dependent_lookup_suppressed_on_call to reflect such
situations, but it was not always set correctly, causing the C++-generating
back end to erroneously drop parentheses.  For example:

  int f(void*) { return 1; }
  namespace N {
    struct S {} s;
    int f(S*) { return 2; }
  }
  int main() {
    return (f)(&N::s) != 1;  // Selects the first f above.
  }

Without the parentheses in the call to f, argument-dependent lookup would kick
in and the better match N::f would be selected.  With the parentheses, only the
first f is found.

This is now fixed: The C++-generating back end now preserves the parentheses.


6/12/14  [EDGcpfe/15043]
C++-generating back end: unnecessary name qualification with inline namespace

The C++-generating back end previously used a qualified name when putting
out the name of a member of an inline namespace when the name appears in
the context of the inline namespace's parent namespace.  This is now fixed,
and an unqualified name is used.  For example:

  namespace N {
    inline namespace {
      template<typename T> int f(T) {
        return 0;
      }
    }
    template int f(int);  // previously generated as N::f
  }


6/10/14  [EDGcpfe/15084,EDGcpfe/15145,EDGcpfe/15220]
Spurious constant expression errors in non-type template arguments

The front end previously incorrectly rejected some expressions used as
non-type template arguments, either because they use the unary *
indirection operator or because a dependent expression was claimed to be
non-constant.  This has now been fixed.  In particular, the unary *
operator is now accepted in C++11 and Microsoft modes when applied to an
address constant designating a variable that can be used in a constant
expression, and dependent expressions in a template definition are treated
as constant.  For example:

  template <int I> class A { };
  template <typename T> void f() {
    const int c = T::x;
    const int d = T::y - c;
    A<d> a;   // Previously an error
  }

  template <const int *P> struct B : A<*P> {};   // Previously an error
  extern const int N = 0;
  B<&N> foo;


6/9/14   [EDGcpfe/15213]
Spurious error on use of GNU transparent union with const field

The changes for EDGcpfe/12450 introduced a regression causing the front end to
emit a spurious error when calling a function with a transparent union
parameter whose matching field is const-qualified.  For example:

  typedef union U { int const i; } TU __attribute((transparent_union));
  void g(TU u) {}
  int main() {
    g(1);  // Previously triggered a spurious error.
  }

This is now fixed.


6/8/14   [EDGcpfe/15117]
Missing error on trailing comma in template argument list

A change made in version 4.5 caused an error to no longer be issued for
a trailing comma in a template argument list.  Now fixed.

  template <class T> class A { };
  A<int,> a;


6/5/14   [EDGcpfe/15212]
Internal error when using guiding declarations

A feature added in version 4.9 introduced an internal error that could
occur (in remove_unneeded_instantiations) when using guiding declarations
(--guiding_decls).  The underlying defect could also cause function
instantiations done only to determine a routine's return type to not
be removed from the IL.  Now fixed.

  // Internal error when compiled with --guiding_decls
  inline int f(int a) {
    return a;
  }
  template <class T> int f(T arg) { return 0; }
  int main() {
    f(0.0);
  }


6/3/14   [EDGcpfe/15207]
Internal error when projection symbols are created in prototype instantiations

An internal error could occur (in make_projection_symbol) when attempting
to create a projection symbol in a prototype instantiation.  Projection
symbols are now created in fewer cases in prototype instantiations.

  template <class T> void g(T x = []()->int {
    struct A {
      using T::f;
    };
    struct C : A {
      void g(T t) {
        f(t);
      }
    };
  }
  );


6/3/14   [EDGcpfe/15210]
Remove configuration macro GNU_COMPLEX_EXTENSIONS_ALLOWED

The configuration macro GNU_COMPLEX_EXTENSIONS_ALLOWED has been replaced
by C99_IL_EXTENSIONS_SUPPORTED.  As a result, some back ends may now see the
eok_xconj, eok_real_part, and eok_imag_part operations.  This is a slight IL
CHANGE (in configurations where GNU_COMPLEX_EXTENSIONS_ALLOWED is FALSE but
C99_IL_EXTENSIONS_SUPPORTED is TRUE).


6/3/14   [EDGcpfe/15202]
Lowering of __builtin_complex

The changes for EDGcpfe/12780,EDGcpfe/14747 introduced __builtin_complex,
but any attempt to use it in configurations that use lowering had resulted in
an assertion failure in lower_builtin_operation.  That is now fixed.
For example (with --gcc):

  _Complex double f(double a, double b) {
    return __builtin_complex(a, b);
  }


6/3/14   [EDGcpfe/15203]
GNU: Aggregate initialization of complex types with LOWER_COMPLEX set to FALSE

In configurations that support lowering, but not lowering of complex types
(i.e., LOWER_COMPLEX is FALSE), the use of aggregate initialization for
objects with complex types had caused assertion failures at various locations
in lowering (and also in the C-generating back end in some configurations).
This example, with --gnu_version 40700 --c++11, had resulted in an assertion
failure (lower_dynamic_init_aggregate_constant: bad aggr kind) and is now
fixed:

  double x = 1.0;
  __complex double y = { x, 0.0 };

Note that in a case where a complex number is initialized with an aggregate
(like above), the back end should be prepared to handle a ck_aggregate with two
floating-point elements even in cases where LOWER_COMPLEX is FALSE.  This is a
slight IL CHANGE.


5/30/14  [EDGcpfe/15190]
__func__ in templates

The type of __func__ in a template is potentially dependent on the arguments
for which the template is instantiated (i.e., the length of the string
represented by __func__ can differ from one instantiation to the next), but
previously the front end did not treat the expression __func__ as a template-
dependent expression.  That in turn could result in spurious errors due to
incorrect lookup results for certain function and operator calls that have
__func__ as an argument (in C++11 mode).  For example:

  struct Log {
    template<typename T> Log& operator<<(T const&);
  };
  template<class T> struct B {
    void f() {
      Log() << __func__; // Previously did not find instantiations of
    }                    // Log::operator<< during most real instantiations.
  };
  template struct B<int>;  // Triggered a spurious error.

This is now fixed.  (The dependent nature of __func__ appearing in templates
was clarified by the standards committee's resolution for Core issue 1779.)


5/28/14  [EDGcpfe/14850]
Constexpr functions not instantiated in secondary translation units

Functions that are constexpr must be instantiated when they are referenced
in order to produce a constant expression.  Such instantiations were not
being done in secondary translation units, resulting in spurious errors
when an example like the one below is compiled as a secondary translation
unit.  Now fixed.

  template<typename T> struct A {
    template<typename T2> static constexpr bool f(T2*) { return true; }
    template<typename> static constexpr bool f(...) { return false; }
  };
  struct B {
    static const bool b = A<int>::f<int>(nullptr);
  };


5/27/14  [EDGcpfe/15183]
Spurious Microsoft-mode warning on lambda capturing a parameter pack

In Microsoft modes that enable both lambdas and variadic templates (e.g., when
microsoft_version >= 1800), the front end issued a spurious warning about an
anonymous union member being hidden by a lambda member when a lambda captures
a parameter pack.  For example:

  template<typename ... T> inline int g(T ... p) {
    return [p ... ]{ return 42; }();  // Previously triggered a spurious
  }                                   // warning.
  int main() {
    return g(1, 2) != 42;
  }

This is now fixed.


5/27/14  [EDGcpfe/14004,EDGcpfe/14869]
C++11: implicit initialization in aggregate initializers

C++11 changed the initialization of aggregate members without a corresponding
initializer in an aggregate initializer from "value initialization" (the C++03
behavior) to being initialized from an empty initializer list.  This is
notably different from the C++03 behavior in that an initializer-list
constructor is considered for such initialization.  For example:

  #include <initializer_list>
  struct S {
    S(std::initializer_list<int>);
  };
  S x[1] = {};  // Now accepted in C++11 modes.

The front end now implements this new rule (introduced in the language through
Core issue 1070) in its C++11 modes (except in some clang and GNU modes).

Note that this required some changes in lowering that back ends doing their
own lowering may have to emulate: Specifically, previously any arguments for
a constructor selected for the initialization of an array were default
arguments; now, they may be arguments representing a generated empty
initializer-list.

Also, in Cfront ABI configuration (i.e., IA64_ABI set to FALSE) the mangling
of an aggregate initializer appearing in template signatures (an unusual case)
may change if the aggregate initializer leaves out some element initializers.
For example:

  struct A { union {int m = 37;} u; };
  template <class T> auto f() -> decltype(T(* new A{}));
  int main() { f<A>(); }

The encoding of A{} in the mangled name of f<A>() is now different in the
Cfront ABI.


5/23/14  [EDGcpfe/14728]
Lookup failure with using-directives and hidden name processing

Name lookup could produce an incorrect result when using-directives
are being used and RECORD_HIDDEN_NAMES_IN_IL is TRUE.  Now fixed.
Although this example looks quite routine, the circumstances that
give rise to this problem appear to be uncommon as the problem was
introduced in version 3.7 and has only recently been encountered.

  namespace N {
    namespace {
      struct A { };
    }
    void f() {
      struct B: A { };
    }
    void g() {
      struct C: A { };  // "A" not found
    }
  }


5/23/14  [EDGcpfe/15180]
Microsoft compatibility: using-declaration, struct, and typedef with same name

An internal error could occur (in inactive_scope_lookup) in Microsoft mode
if a scope contains a tag name (i.e., struct, class, or enum), a typedef,
and a using-declaration to a tag name.  Now fixed.  The example below
illustrates the issue in some, but not all, configurations.

  struct A { int x; };
  typedef struct A A;
  namespace N1 { using ::A; }
  using N1::A;
  int main() {
    A a;
  }


5/22/14  [EDGcpfe/14026,EDGcpfe/14145,EDGcpfe/14384]
C++14, GNU C++ compatibility: Generalized lambda capture (IL CHANGE)

In C++14 mode, the front end now allows a lambda to capture any initializer
(in addition to the C++11 feature of simply capturing local variables).  For
example:

  extern "C" int printf(char const*, ...);
  int main() {
    auto x = [x = 42]{ return x+1; };
    printf("%d\n", x());  // Prints "43\n".
  }

This kind of capture is known as an "init-capture", and causes the addition of
a corresponding nonstatic data member in the closure type associated with the
lambda.

In GNU modes that allow lambda expressions, init-captures are enabled even in
non-C++14 modes.

The efficient representation of init-captures required moving some existing
fields of a_lambda_capture to variant sections; this is an IL CHANGE.


5/20/14  [EDGcpfe/15142]
GNU and clang C++ compatibility: invalid use of template keyword

g++ and clang allow the template keyword in contexts in which it is not
permitted, such as the example below where x is not followed by a template
argument list.  This is now accepted in g++ and clang modes.

  template <class T> void f(T t) {
    t.template x();
  }


5/20/14  [EDGcpfe/14054]
Inode-like information now used in include suppression

The front end now uses unique file identifiers (e.g., inode numbers
on Unix-like systems) to determine if two differently named files
actually refer to the same underlying file.  This information is used
to suppress the redundant processing of include files.  The example
below now prints the #warning message only once.  The new configuration
macro UNIQUE_FILE_IDENTIFIER_AVAILABLE must be TRUE for this feature to
be enabled.  The new macro defaults to TRUE on Windows and on systems
that support the stat() library routine.

  file: t1.c:
  #include "h1.h"
  #include "h2.h"

  file: h1.h:
  #pragma once
  #warning "in h1.h"

  file: h2.h:
  <link to h1.h>


5/20/14  [EDGcpfe/14297]
GNU C++ compatibility: linked directories considered the same

GNU compilers treat two include directories as being the same directory if
one is a link (symbolic or hard) to the other.  This can affect the
processing of #include_next directives.  The front end now uses inode
information (if available) to determine if two directories with different
names are actually the same directory.  This feature requires that
UNIQUE_FILE_IDENTIFIER_AVAILABLE be TRUE (see entry above for more
information), but is not supported on Windows because the unique file
identifier mechanism on Windows does not work for directories.


5/19/14  [EDGcpfe/15167]
Declaring operator new/delete "inline"

The C++ standard does not permit a replaceable non-member operator new or
operator delete to be declared "inline".  The front end now diagnoses such
cases (the standard doesn't actually require a diagnostic): an error in strict
mode, a warning otherwise.  For example:

  inline void operator delete(void*) {}  // Now elicits a warning or error.

The diagnostic is also emitted if such a replaceable operator is inline because
of a GNU attribute "always_inline".


5/19/14  [EDGcpfe/15157,EDGcpfe/15173]
GNU C11 compatibility: Selector decay for _Generic constructs

The C11 standard does not specify that array-to-pointer or function-to-pointer
type decay transformations are applied to the selector expression of a _Generic
construct.  However, GCC does appear to perform those transformations, and the
front end now does the same in GNU C11 mode.  For example:

  int main() {
    double x[2];
    return _Generic(x, double*: 0, double[2]: 1);
  }

This example now returns 0 in GNU C11 mode, and 1 in other C11 modes.


5/19/14  [EDGcpfe/15172]
Possible memory corruption converting non-type template arguments

In some configurations, a memory scribble within the stack could occur in
conv_nontype_arg_to_required_type (templates.c), with unpredictable results.
This is now fixed.


5/16/14  [EDGcpfe/15080,EDGcpfe/15143]
GNU compatibility: "#pragma GCC target"

Support has been added for the "target", "push_options", "pop_options", and
"reset_options" strings for "#pragma GCC".  See
http://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html for
more details.  An internal ak_target attribute is attached to each function
declaration that is affected by the "#pragma GCC target".  These new options
are accepted when gnu_version >= 40400; when gnu_version >= 40800, the "target"
attribute is used to implement the multiversioning feature (see the Changes
entry for EDGcpfe/14759).  For example (with --gnu_version 40800):

  extern "C" int puts(const char *);
  #pragma GCC push_options
  #pragma GCC target("default")
  void f() { puts("default"); }
  #pragma GCC pop_options

  #pragma GCC push_options
  #pragma GCC target("mmx")
  void f() { puts("mmx"); }
  #pragma GCC pop_options

  #pragma GCC push_options
  #pragma GCC target("arch=corei7")
  void f() { puts("arch=corei7"); }
  #pragma GCC pop_options

  int main() {
    f();    // Chooses one of the f()s above based on the CPU at load time.
    return 0;
  }


5/16/14  [EDGcpfe/15166]
GNU C++ compatibility: multiversion special functions

The changes for GNU function multiversioning neglected to include special
functions.  That has now been fixed.  The following example (with --gnu_version
40800) had failed an assertion (in scan_function_body) and now compiles without
issue:

  extern "C" int printf(const char *,...);
  struct A {
    __attribute__((target("sse3")))     A() { printf("A() sse3\n");     }
    __attribute__((target("sse3")))    ~A() { printf("~A() sse3\n");    }
    __attribute__((target("default")))  A() { printf("A() default\n");  }
    __attribute__((target("default"))) ~A() { printf("~A() default\n"); }
  };
  A a;
  int main() {}


5/13/14  [EDGcpfe/15160]
GNU C++ compatibility: internal error instantiating default argument during
prototype instantiation

In g++ mode, a default argument can be specified on an out-of-class definition
of a member function of a class template.  If such a default argument was
instantiated as part of overload resolution in a prototype instantiation,
an internal error could occur (in push_template_instantiation_scope).  Now
fixed.

  template<class T> struct A {
    static void f() { A<T> x; x.g(); }
    void g(int x);
  };

  template<class T> void A<T>::g(int x = 0) { }

  int main() {
    A<int>::f();
  }


5/13/14  [EDGcpfe/15151]
GNU C++ compatibility: using-directives vs. names from dependent base classes

g++ sometimes finds names in dependent base classes in cases where they
should not be visible.  A change made in version 4.4 (see entry for
EDGcpfe/12040) changed our behavior to find such names in fewer cases.
That change caused the front end to fail to find certain names from
dependent base classes in cases where g++ still did.  g++ prefers a name
from a dependent base class to a name found via a using-directive.  We now
emulate the g++ behavior for such cases.

  namespace N {
    template <class T> void f(T);  // #1
  }
  template <class T, class T2> struct A : T {
    int g(T2 t2) {
      return f(t2);  // Now calls #2 when T is B
    }
  };
  struct B {
    int f(int) { return 0; }  // #2
  };
  using namespace N;
  int main() {
    A<B, int> ab;
    ab.g(1);
  }


5/13/14  [EDGcpfe/15150]
Segfault when lowering typeid

In cases where a variable is defined with the same mangled name as a type_info
variable and that variable does not have the proper type, a segfault had
occurred (in f_identical_types) when trying to lower a typeid operation.
For example in an IA-64 ABI configuration with --rtti:

  #include <typeinfo>
  extern "C" {
    int _ZTIi;    // _ZTIi is the typeinfo for "int" (in the IA-64 ABI)
  }
  void f(int x) {
    typeid(x).name();
  }

This example now results in a multiple-definition error in the linker.


5/9/14   [EDGcpfe/15137]
Binding an rvalue reference to a converted lvalue during overload resolution

The ability to bind an rvalue reference to a converted lvalue in overload
resolution contexts (see the entry for EDGcpfe/13672,EDGcpfe/14769) is now
disabled in all Microsoft modes.  Previously, it was only disabled in Microsoft
modes with microsoft_version < 1700.  For example:

  extern "C" int printf(char const*, ...);
  void f(double const&) { printf("lvalue\n"); }
  void f(double&&) { printf("rvalue\n"); }
  int main() {
    int i = 42;
    f(i);  // Now prints "lvalue" in all Microsoft modes; previously printed
  }        // "rvalue" when microsoft_version == 1800.


5/9/14   [EDGcpfe/15141]
Spurious error on initializer for unspecified-bound array in template

The front end previously issued a spurious error ("an empty initializer is
invalid for an array with unspecified bound") when a multi-dimensional array
variable defined with an aggregate initializer in a function template has both
an unspecified bound and a template-dependent bound.  (The error only occurred
if the function template underwent prototype instantiation.)  For example:

  template<int N> void g() {
    double x[][N] = { 1, 2, 3 };  // Previously triggered an error during
  }                               // prototype instantiation.

This is now fixed.


5/8/14   [EDGcpfe/15135]
C++-generating back end: Duplicate rendering of Microsoft attribute targets

Version 4.9 of the front end added various improvements to the processing of
Microsoft bracketed attributes.  One of those improvements was to recognize
"target specifiers" in such attributes (originally, the target specifiers were
mostly ignored; see the entry of 1/19/10 for EDGcpfe/8363 et al.).  However,
the C++-generating back end incorrectly rendered the attribute targets twice:
once from the structured IL representation, and once from the string recorded
in an_ms_attribute entries.  For example:

  [returnvalue:SA_Post(MustCheck=SA_Yes)] int f([SA_Pre(Null=SA_No)] int *x);
    // Previously rendered as "[returnvalue: returnvalue:SA_Post...".

This is now fixed.  The fix includes a small IL CHANGE: The string
representation of attributes no longer includes the target specifier.


5/8/14   [EDGcpfe/15049]
Erroneous handling of some base-to-derived conversions

The front end previously erroneously interpreted the explicit conversion of an
lvalue of a base class type to a reference to a derived class type if the base
class also contained a conversion function to a reference to the derived class.
In some cases, this resulted in spurious errors.  For example:

  struct B { operator D() const = delete; };
  struct D: B {};
  void g(B const &b) {
    static_cast<D const&>(b);  // Previously used the conversion function,
  }                            // thereby triggering a spurious error.

This is now fixed: The user-defined conversion conversions are not considered
if a base-to-derived conversion is available.


5/8/14   [EDGcpfe/15147]
GNU compatibility: "target" declaration followed by definition

In the case where the "target" attribute is used on a function declaration
but the function is subsequently defined without the "target" attribute, a
spurious error had been issued (only in C++ mode when gnu_version >= 40800).
Now fixed.  For example (with --gnu_version 40800):

  void f() __attribute__((__target__("sse4.2")));
  void f() {}


5/6/14   [EDGcpfe/14991]
C++-generating back end: Linkage specification (IL CHANGE)

When the new configuration macro GENERATE_LINKAGE_SPEC_BLOCKS is TRUE, the
front end now records entries in the source sequence entries list to represent
braced linkage specifications.  The C++-generating back end uses these entries
to improve the code it generates.  For example, given:

  extern "C" {
  #pragma MyPragma
    void f() {};
  }

the C++-generating back end now produces essentially the same code if the macro
GENERATE_LINKAGE_SPEC_BLOCKS is TRUE, whereas without that setting it produces

  #pragma MyPragma
  extern "C" { void f() {} }

Setting the new macro to TRUE requires that GENERATE_SOURCE_SEQUENCE_LISTS be
TRUE also, and that CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS both be FALSE.  (If
those conditions are met, the macro is TRUE by default.  That is an IL CHANGE
that can be undone by setting the macro to FALSE explicitly.)


5/6/14   [EDGcpfe/14542]
Spurious error on use of "final", "sealed", or "abstract" specifier

A spurious error had been issued in cases where a virtual function declaration
has a "final" specifier and the class has a dependent base class that could
declare the overridden function.  A similar situation arose when the C++/CLI
"sealed" and "abstract" modifiers were used.  Now fixed.  For example (with
--c++11):

  template <class T> struct D : T {
    void f() final;   // Overrides T::f()
  };


5/5/14   [EDGcpfe/15125]
Matching attributes to built-in declarations in other translation units

When simultaneously compiling multiple translation units, the front end by
default issues an error when a declaration in one translation unit has an
attribute that is not present on the matching declaration of another
translation unit.  Now that diagnostic is inhibited if the entity with the
missing attribute is a compiler-declared entity (e.g., "operator delete").


5/5/14   [EDGcpfe/15129]
Abort in remap_secondary_pointer_for_rewrite with GNU alias attribute

When simultaneously compiling multiple translation units, the front end
sometimes aborted in remap_secondary_pointer_for_rewrite (in trans_copy.c,
with message "missing primary IL correspondence") when dealing with a routine
entry for a function whose GNU alias attribute (or, similarly, a weakref or
ifunc attribute) is resolved late in the compilation process.  This is a
regression introduced by the changes for EDGcpfe/14931.  It is now fixed.


5/2/14   [EDGcpfe/15126]
Abort in check_correspondences with deferred prototype instantiations

When simultaneously compiling multiple translation units, the front end
sometimes aborted in check_correspondences when verifying corresponding
prototype instantiations of function templates.  This occurred in some
complex cases when the full instantiation of prototype instantiations is
deferred (as it commonly is in GNU C++ modes).  This is now fixed.


5/1/14   [EDGcpfe/14925]
Offsets of bit fields in their containers

When targ_microsoft_bit_field_allocation (set to the value of the configuration
macro TARG_MICROSOFT_BIT_FIELD_ALLOCATION) is TRUE, bit fields are allocated
strictly within "container fields" (see the entry of 3/31/95).  When that is
the case, the byte offset of a field within its container is now recorded if
the configuration macro RECORD_BIT_FIELD_CONTAINER_OFFSETS_IN_IL is TRUE.
For example:

  struct S {
    long x: 4;  /* offset_in_container == 0 */
    long y: 8;  /* offset_in_container == 0 */
    long z: 8;  /* offset_in_container == 1 */
  };

This offset is recorded in the field "offset_in_container" of a_field entries.


5/1/14   [EDGcpfe/15107]
Miscellaneous issues with GNU function multiversioning

A couple of issues with the implementation of GNU function multiversioning
(see the Changes entry for EDGcpfe/14759) have been identified and fixed.
In some cases, the "referenced" flag for target-specific routines had been
incorrectly set to FALSE.  An array-to-pointer decay operation was missing on
the first operand in calls to __builtin_cpu_supports/__builtin_cpu_is which
could cause problems for back ends.  Additionally, the types of the strings
passed to __builtin_cpu_supports/__builtin_cpu_is had not been properly
lowered in some configurations.


5/1/14   [EDGcpfe/15124]
Memory corruption during compilation of multiple source files

The dummy_undefined_symbol static variable was not being properly initialized
between the compilation of source files which could lead to the use of an
invalid pointer, causing undefined behavior during compilation.  This
could occur in configurations where COMPILE_MULTIPLE_SOURCE_FILES is true
and at least two of the source files contained range-based "for" loops
that required calls to begin/end functions.  Now fixed.


4/30/14  [EDGcpfe/15122]
Microsoft compatibility: C++/CX public scoped enum in global scope

The front end previously failed to diagnose a public scoped enum type
defined in global scope.  For example:

  public enum class E { e };  // Previously accepted, but this is not
                              // valid C++/CX.

This is now fixed: An error is issued.


4/29/14  [EDGcpfe/12740,EDGcpfe/14294]
GNU compatibility: typedef redeclaration in system header files

Versions of GNU earlier than 4.6.0 appear to allow a typedef redeclaration
when both typedefs refer to pointer to function types and there is a
discrepancy in the parameter types of the underlying function types.
Such discrepancies are only ignored in system header files.  A change
has been made to downgrade the error to a warning (which is typically
suppressed because warnings are typically suppressed when parsing system
headers).  For example, the following no longer results in an error with
--gnu_version=40500:

  # 2 "/usr/include/bits/types.h" 1 3 4
  typedef void (*my_sig_t)();
  typedef void (*__sighandler_t) (int);
  typedef __sighandler_t my_sig_t;


4/29/14  [EDGcpfe/15118]
Microsoft compatibility: __is_win_class and __is_win_interface

In Microsoft modes, the front end now supports two additional type traits
helpers: __is_win_class and __is_win_interface.  __is_win_class(X) is TRUE
only if X is a ref class type in C++/CX mode.  __is_win_interface(X) is TRUE
only if X is an interface class type in C++/CX mode.


4/29/14  [EDGcpfe/14949]
Assertion failure in mangled_encoding_for_function_type

In configurations that use lowering and have the configuration macro
RECORD_BACKING_EXPRS_WITH_IL_LOWERING set to FALSE, it was possible for a
typeid expression that referred to a pointer to a function type to cause
an assertion failure in mangled_encoding_for_function_type.  This is now
fixed.  For example:

  #include <typeinfo>
  typedef void (F)();
  void f(const std::type_info *x) {
    f(&typeid(F*));
  }


4/28/14  [EDGcpfe/14865,EDGcpfe/15079,EDGcpfe/15095]
Spurious error on pack expansion in member alias template

A spurious error could be issued if a member alias template was instantiated
by another member of the class during the prototype instantiation of
the class.  Now fixed.  This problem caused an error to be issued when
compiling the gcc 4.9 bits/alloc_traits.h header.

  template<typename T> struct A {
    template<typename... S> struct B {
      typedef int type;
    };
    template<typename... S> using C = typename B<S... >::type;
    // Instantiation of C<S...> resulted in error
    template<typename... S> C<S...> f(S...) { }
  };


4/28/14  [EDGcpfe/14739]
Duplicate definition of default_cpp_cli_import_flags

When compiling the front end using a C++ compiler, some configurations resulted
in the global variable default_cpp_cli_import_flags having two definitions (one
in ms_metadata.cpp and one in fe_init.c).  That, in turn, resulted in a linker
error while building the front end.  That problem is now fixed.


4/28/14  [EDGcpfe/15096,EDGcpfe/15116]
Spurious error on reference to parameter pack in noexcept of function template

A spurious "pack ... does not have the same number of elements" diagnostic
could be issued on a noexcept specification of a function template when
the noexcept uses a function parameter pack expansion.  Now fixed.

  struct A {
    template <class... U> A(U...) {}
  };
  template <class T> T f(T t) { return t; }
  struct B {
    template <class ...U> A g(U... u) noexcept(noexcept(A(f<U>(u)...))) {
      return A(f<U>(u)...);
    }
  };
  int main() {
    B b;
    auto a = b.g("abc");
  }


4/28/14  [EDGcpfe/15106]
Spurious "**BAD ENTRY KIND**" in IL display program

As a result of the changes introduced by EDGcpfe/14931, a spurious
"**BAD ENTRY KIND**" message had been emitted by the IL display program for
gnu-routine-supplements.  This is now fixed.


4/25/14  [EDGcpfe/15091]
C++/CX attributes on base class specifiers

Previously the front end recorded C++/CX attributes applied to base class
specifiers on the Microsoft attributes list of the parent scope entry.  This
is no longer done since the attributes are directly accessible from the
corresponding base class entries themselves.


4/25/14  [EDGcpfe/15115]
Declarations with decltype-qualified names

The C++11 standard prohibits the use of decltype-qualified names for many
(but not all) declarative contexts.  The front end previously did not diagnose
such uses; now it issues an error in strict mode and in clang modes, and a
warning otherwise.  For example:

  struct S { void f(); struct N; } s;
  void decltype(s)::f() {}   // Now an error in strict C++11 mode.
  struct decltype(s)::N {};  // Now an error in strict C++11 mode.


4/25/14  [EDGcpfe/15101]
Spurious error on template parameter used as a mem-initializer-id

In many C++ modes, including strict and C++11 modes, the front end previously
issued a spurious error on a template parameter used as a mem-initializer-id
if the parameter did not also appear in the base class specifiers list.
For example:

  struct B {};
  template<typename T> struct D: B {
    D(): T() {}  // Previously triggered a spurious error in strict mode.
  };

This is now fixed.


4/25/14  [EDGcpfe/15011]
Abort on instantiation of friend function of class template

In configurations with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to
TRUE, the front end sometimes aborted with an internal error in
scope_depth_for_class_ss_list (src_seq.c) when managing the source sequence
entries for a friend function of a class template.  For the problem to
manifest itself, the class template and the friend function had to be
instantiated in two different namespace "extents" for a namespace not
enclosing the class template.  For example:

  template <class T> struct A {
    friend void f(A) {int i; }
  };
  namespace N { A<int> a; }  // Namespace N doesn't enclose struct A.
  namespace N {
    void g() { f(a); }       // Previously triggered an abort.
  }

This problem is now fixed.


4/23/14  [EDGcpfe/15100]
Warnings when building the front end with gcc

Building the front end using gcc with certain compilation options (notably
"-O2 -funroll-loops -Wall") resulted in compiler warnings.  These warnings
have now been eliminated.  This change is similar to that of EDGcpfe/14794
but affects code added since then and conditionally-compiled code in
additional configurations.


4/23/14  [EDGcpfe/15048]
Microsoft compatibility: Duplicate definition of variables

In Microsoft modes, the front end now accepts two definitions for a non-local
variable if the first definition does not include an initializer and the
second definition includes an initializer and the "extern" storage class
specifier.  For example:

  int x;
  extern int x = 3;  // Now accepted in Microsoft modes.

In such cases, the first definition is retroactively treated as a declaration.
Variables that require nontrivial destruction are not considered for this
treatment.


4/23/14  [EDGcpfe/11251]
Microsoft compatibility: allow ambiguous base class in member access

The Microsoft compiler allows a member access expression that refers
to a member of an ambiguous base class.  The first base class found is
used, unless one of them is direct, in which case the direct base is used.
We now emulate this behavior (with a warning) in Microsoft bugs mode.

  #include <stdio.h>
  struct A {
    int i;
    A(int x) { i = x; }
    inline int g() { return i; }
  };
  struct B1 :  A {
    B1() : A(2) { }
  };
  struct B2 :  A {
    B2() : A(1) { }
  };
  struct C :  B1,  B2 {
    void f() {
      printf("%s\n", A::g() == 2 ? "pass" : "fail");
    }
  };
  int main() {
    C x;
    x.f();
  }
 

4/23/14  [EDGcpfe/14950]
C++-generating back end: assertion failure with enum redeclaration

In configurations using the C++-generating back end, an abort could occur
(an assertion failure in gen_declaration_statement) if an enumeration is
redeclared in the same scope.  This is now fixed.  For example:

  void f() {
    enum E : char { e0 };
    enum E : char;   // Previously caused an abort
  }


4/23/14  [EDGcpfe/14889]
Using constant-valued variables in lambda expressions

Previously, the front end issued an error when a lambda expression used the
value of a constant-valued variable declared in a function outside that
lambda expression if the variable is not captured.  For example:

  int g() {
    int const N = 3;
    return []{ return N; }();  // Previously an error; now okay.
  }

Such cases are now accepted (in modes that accept lambda expressions).


4/22/14  [EDGcpfe/15015]
Deduction failure when expanding a pack into a template argument list with
default template arguments

Deduction could fail when a pack is expanded into the template argument
list of a template with default template arguments.  Now fixed.

  template <class T0 = int, class T1 = int> struct C {
    C() {}
  };
  template <typename R> struct A {
    template <typename ... Args> void f(C<Args...> args) { }
  };
  template <typename T, typename ... Args> struct B {
    void f() {
      A<T> a;
      a.f(args);  // Spurious "no instance ... matches the argument list"
    }
    C<Args ...> args;
  };
  int main() {
    B<char> b;
    b.f();
  }


4/22/14  [EDGcpfe/14958]
Source range for enk_condition nodes

In configurations with EXTRA_SOURCE_POSITIONS_IN_IL, the expr_range field
of an_expr_node was left as null_source_range for enk_condition nodes.
This has now been fixed.  For example:

  bool f();
  void g() {
    if (bool b = f())  // enk_condition_node now has source range information
      ;
  }

------------------------------------------------------------------------------
Version 4.9, April 17, 2014

4/15/14  [EDGcpfe/14790]
Preliminary support for C++/CX

The front end now includes support for C++/CX, a set of extensions designed
by Microsoft to support the "Windows Runtime" (or WinRT) platform.  When the
new configuration macro CPPCX_ENABLING_POSSIBLE is TRUE, the extensions can be
enabled through the --cppcx command-line option or by setting the configuration
macro DEFAULT_CPPCX_ENABLED to TRUE.

As with C++/CLI, IL lowering is not available in C++/CX mode, and hence the
C-generating back end cannot be used when those features are enabled.

The changes required to implement this additional dialect are significant.
They're considered "preliminary" in that a number of refinements are planned
in the near future, but the resulting changes are not expected to dramatically
affect the IL representation.

Support for C++/CX relies on the same ms_metadata.cpp file as support for
C++/CLI (to import .winmd files, in the case of C++/CX).  Compiling this file
now requires Visual C++ 2012 (aka. Visual C++ 11.0) which reports a version
number 17.00; previously, Visual C++ 2010 was sufficient for compiling that
file (version number 16.00).  Note that the free "Express" version of Visual
C++ is not sufficient for this purpose because it does not include the
required ATLMFC library.


4/15/14  [EDGcpfe/14790]
C++/CLI: Custom Attributes

C++/CLI allows Microsoft-style bracketed attributes to be introduced through
classes deriving from System::Attribute.  This is now supported by the front
end.  For example:

  using namespace System;
  [System::AttributeUsage(AttributeTargets::Class, AllowMultiple=true)]
  public ref struct MyAttr : public Attribute {
    // A new, custom attribute.
    MyAttr(String^) {}
  };
  [MyAttr("Message")] ref struct RS {};

Various other improvements to the emulation of Microsoft-style bracketed
attributes have been made as well.


4/14/14  [EDGcpfe/15036]
Microsoft, GNU C++, and Clang compatibility: using-declaration and typedef
in the same scope

The Microsoft, g++, and clang compilers all allow a typedef to be followed
by a using-declaration of the same name in a given scope.  When the name
is used, g++ and clang find the typedef, while Microsoft finds the
using-declaration.  We now emulate the appropriate behavior in g++,
clang, and Microsoft modes.

  typedef int A;
  namespace N {
    struct A { };
  }
  using N::A;  // must come after the typedef
  A t = 0.0;   // GNU finds the typedef, Microsoft finds
               // the using-declaration (resulting in an error)


4/13/14  [EDGcpfe/14822]
clang compatibility: macro expansion of feature-test macro arguments

Beginning with version 3.3, clang does not macro-expand the arguments of
the feature-test macros (__has_feature, etc.).  The front end previously
performed that macro expansion unconditionally; now it only does so with
clang_version < 30300.  For example:

  #define IS_POD is_pod
  int i = __has_extension(IS_POD);  // 1 for clang_version < 30300,
                                    // 0 for clang_version >= 30300


4/13/14  [EDGcpfe/14847]
clang compatibility: version and mode dependencies in __has_attribute

The front end previously gave the clang __has_attribute macro the value 1
if the named attribute is supported by either gcc or g++ mode, ignoring
which mode is in effect and the current value of gnu_version.  This has now
been changed so that the result of __has_attribute is 1 only if the
attribute is supported with the current mode and gnu_version.  For example:

  int i = __has_attribute(flatten);  // Previous unconditionally 1, now
                                     // 0 for gnu_version < 40000.


4/13/14  [EDGcpfe/14871]
clang compatibility: __has_feature(cxx_decltype) in non-C++11 mode

The front end previously incorrectly gave the value 1 for the clang
feature-test macro __has_feature(cxx_decltype) in modes in which the
__decltype construct is supported (see the entry for EDGcpfe/11338) but the
"decltype" keyword is not recognized (i.e., when gnu_version is at least
40300 but C++11 mode is not enabled).  This is now fixed.  For example,
with --clang --gnu_version=40800 --no_c++11:

  int i;
  #if __has_feature(cxx_decltype)
  typedef decltype(i) I;  // Previously selected, causing an error
  #else
  typedef int I;
  #endif


4/13/14  [EDGcpfe/14846,EDGcpfe/14872]
clang compatibility: changes to __has_feature, __has_extension, and GNU
version macros

Several changes have been made to the implementation of the clang
__has_feature and __has_extension feature-test macros.  First, contrary to
published documentation but conforming to current clang implementations,
the type trait helper names can now be tested with __has_feature;
previously they could only be used with __has_extension.  Second, feature
and type trait helper names can now have an optional "__" prefix and
suffix.  Finally, the "attribute_deprecated_with_message" feature name is
now supported, with the value 1 if the current emulation allows a string
argument for the "deprecated" attribute (currently, if gnu_version is at
least 40500 -- see the change for EDGcpfe/12407).  For example, with
--clang:

  int i = __has_feature(__is_pod__);  // Now has value 1
  // Now has value 1 if gnu_version >= 40500:
  int j = __has_feature(attribute_deprecated_with_message);
                                                            
In addition, the clang compiler unconditionally defines the GNU version
macros __GNUC__, __GNUG__, __GNUC_MINOR__, and __GNUC_PATCHLEVEL__ to
reflect version 4.2.1, and the front end has been changed to do the same in
clang mode.  (This change does not affect the value of gnu_version, which
should normally be set to a later version for maximum compatibility with
the clang implementation.)


4/11/14  [EDGcpfe/10197]
Abort on invalid friend declaration written as specialization

In modes in which in-class specializations are allowed (Microsoft and Sun),
an abort could occur (in full_specialization) if a friend class declaration
was written as an (invalid) explicit specialization.  Now fixed.

  template <typename T> class C {
    template <> friend class C;
  };


4/11/14  [EDGcpfe/14893]
Handling of new-expressions in SFINAE contexts

Consider the following example:

  template<class T> void f(decltype(new T(1, 2)) *);  // (1)
  template<class T> void f(...) {}                    // (2)
  int main() {
    f<int>(0);  // Should select (2).
  }

The call of f<int> matches candidate (2), but it shouldn't match candidate (1)
because "new int(1, 2)" is not a valid expression.  The C++ SFINAE rules,
therefore make the example valid.  Previously, however, the front end ignored
the second operand of the initializer in the new-operand while evaluating the
viability of candidate (1).  It then proceeded with instantiating that
candidate, and that triggered an error because of the presence of the extra
operand.  This is now fixed.


4/11/14  [EDGcpfe/15042]
Microsoft C++/CLI and C++/CX compatibility: DEFAULT_CPPCLI_CPPCX_VERSION

The DEFAULT_CPPCLI_CPPCX_VERSION configuration macro has been added to
specify the default value for microsoft_version when C++/CLI or
C++/CX mode is being used and no version number was explicitly specified
with the --microsoft_version command-line option.


4/11/14  [EDGcpfe/15040]
Abort with multibyte character following universal-character-name in string
literal

The front end could previously abort with a failed assertion in
conv_string_literal when a multibyte character follows a
universal-character-name in a string literal or, in a raw string literal,
follows a reverted construct such as a trigraph.  This is now fixed.  For
example, with --unicode_source_kind=UTF-8:

  char c1[] = "\U00010000𐀀";  // Previously aborted


4/10/14  [EDGcpfe/15037]
Microsoft C++/CLI compatibility: override without explicit "virtual" keyword

Early builds of Microsoft Visual Studio 11.0 in C++/CLI mode (i.e., with
/clr) did not allow a member function to override a base member function unless
the member function was explicitly declared "virtual".  Later builds relaxed
this restriction and now so has the front end.  This is now accepted with
--microsoft_version 1700 --cppcli:

  struct B {
    virtual void f(int);
  };
  struct D : B {
    void f(int) override;
  };


4/9/14   [EDGcpfe/15035]
GNU compatibility: missing error on __thread dynamic initialization

In configurations where THREAD_LOCAL_STORAGE_SPECIFIER_ALLOWED is TRUE,
the changes to support the C++11 thread_local keyword (see the Changes
entry for EDGcpfe/9167,EDGcpfe/12359) had mistakenly allowed dynamic
initialization of a variable with the __thread storage specifier without
an error in GNU emulation modes where gnu_version >= 40800.  Those errors
are now re-enabled.  For example (with --gnu_version 40800):

  extern __thread int i;
  __thread int *p = &i;   // now gets an error (again)


4/9/14   [EDGcpfe/15026]
GNU C++ compatibility: missing diagnostic on invalid template template argument

A change made in version 4.6 could cause a class template instance to
incorrectly be allowed as the argument for a template template parameter
(the underlying class template was used as the argument).  Now fixed.

  template <class T1, class T2> class A {};
  template <class T1, class T2, template<class, class> class TT> class B { };
  template <class T1, class T2> class B<T1, T2, A<int, int> > { };


4/9/14   [EDGcpfe/10978]
Recorded position of using directives

Version 4.2 of the front end introduced an unintentional change that caused the
recorded position of a using directive to be the position of the "namespace"
keyword instead of the "using" keyword.  For example:

  namespace N {}
  using namespace N;  // Since version 4.2, the position recorded in an
                      // a_using_decl entry for this directive was the
                      // position of the keyword "namespace".  Now it's
                      // the position of the keyword "using".

This is now fixed: The position of the keyword "using" is again the recorded
position in such cases.


4/7/14   [EDGcpfe/15020]
Memory use when reading an alternate-format IL file

When configured with ALTERNATE_IL_FILE_FORMAT set to TRUE, the front end
had a bug that caused it to allocate too much memory for character-string
IL entries read from an IL file.  This is now fixed.


4/7/14   [EDGcpfe/13888]
Internal error reading IL file with local namespace aliases

An internal error could occur (in ptr_remap_function) while reading an
IL file that is not in the alternate IL file format if the program uses
multiple namespace aliases within a given function.  Now fixed.

  namespace N { }
  int main() {
    namespace l1 = N;
    namespace l2 = N;  
  }


4/6/14   [EDGcpfe/14875]
clang compatibility: missing type traits helpers in __has_extension

The __has_extension macro (see the entry for EDGcpfe//14634) previously
returned 0 for the type traits helper names is_standard_layout, is_trivial,
and is_trivially_copyable, in accordance with published clang
documentation.  However, clang does, in fact, support these type traits
helpers and the front end has been changed accordingly.  For example (in
clang C++ mode):

  #if !__has_extension(is_trivial)
  #error __is_trivial not supported  // No longer issued
  #endif


4/6/14   [EDGcpfe/14877]
clang compatibility: __has_extension with type traits helper names

The __has_extension macro (see the entry for EDGcpfe/14634) previously
unconditionally returned the value 1 for type traits helper names that are
supported by clang's C++ mode, even if the --no_type_traits_helpers
command-line argument had been specified.  It has now been changed to
return 0 in this case.  For example (in clang C++ mode):

  #if __has_extension(is_pod)
  int i = __is_pod(int); // No longer an error with --no_type_traits_helpers
  #endif 


4/3/14   [EDGcpfe/14759]
GNU compatibility: Function multiversioning

Support has been added for the GNU function multiversioning feature as
documented here: http://gcc.gnu.org/wiki/FunctionMultiVersioning.  This
feature uses the "target" attribute to determine, at load time, which
version of a function should be called, thereby allowing the user to take
advantage of features that may be available on a particular CPU.

The new configuration macro GNU_FUNCTION_MULTIVERSIONING controls this feature
(and defaults to FALSE).  Function multiversioning is only available in
C++ mode, though the "target" attribute is also accepted in C mode (to match
gcc's behavior).

The current GNU implementation of function multiversioning is specific to
the Intel/AMD line of processors, and when the new macro
USE_X86_FUNCTION_MULTIVERSIONING is TRUE, we emulate the GNU behavior.
Customers that use other processors can set USE_X86_FUNCTION_MULTIVERSIONING
to FALSE (though they'll need to add lowering and/or back end support
in that case).

In configurations that have lowering, a "resolver" function is generated
to determine the most appropriate function of the group of target-specific
functions to invoke at run time (based on the characteristics of the CPU
where the executable is being executed).  The ifunc dispatch mechanism is then
used to invoke the resolver function at load time (see the Changes entry for
EDGcpfe/13424).

For example (with --gnu_version 40800):

  extern "C" int puts(const char *);
  void __attribute__((target("default")))     f() { puts("default"); }
  void __attribute__((target("mmx")))         f() { puts("mmx"); }
  void __attribute__((target("arch=corei7"))) f() { puts("arch=corei7"); }
  int main() {
    f();    // Chooses one of the f()s above based on the CPU at load time.
    return 0;
  }


4/2/14   [EDGcpfe/14992]
C++-generating back end: braced constructor arguments in field initializers

In a non-static data member initializer (field initializer) where the
initializer is a brace-enclosed list of arguments for the member's
constructor, the C++-generating back end incorrectly added an extra layer
of braces in the generated output.  This is now fixed.  For example:

  struct A {
    A(int, int);
  };
  struct B {
    A a{1,1};    // Previously generated as "a{{1, 1}}"
  };


4/1/14   [EDGcpfe/14886]
Microsoft compatibility: spurious error on template template default argument

A spurious error could be issued in Microsoft mode on the use of a
template template argument for a template template parameter that has
a default argument specified.  Now fixed.

  template <class T> class A {};
  template <template <class = int> class D = A> struct C {
    void f();
  };
  template <template <class> class D> void C<D>::f() { }


4/1/14   [EDGcpfe/14980]
Microsoft compatibility: explicit override of a cv-qualified member function

A spurious error had been reported when using the Microsoft explicit override
mechanism to override a cv-qualified member function.  Now fixed.  For example
(with --microsoft):

  struct A {
    virtual void f(void) const = 0;
  };
  struct B: A {
    virtual void A::f(void) const override {}
  };


3/31/14  [EDGcpfe/14989]
Off-by-one error when writing C++/CLI portable assemblies

In configurations that use portable assemblies to emulate C++/CLI DLLs,
there was an off-by-one error when generating a portable assembly which had
caused the last entry not to be written to the portable assembly, potentially
causing an assertion failure in import_class_definition if that last entry
was ever referenced.  Now fixed.  Any portable assemblies should be
re-generated.


3/27/14  [EDGcpfe/14981]
Microsoft compatibility: define _MANAGED macro in C++/CLI mode

The Microsoft compiler defines the macro _MANAGED when the /clr
command-line option is given.  The front end now defines that macro when
cppcli_enabled is TRUE.  For example:

  #if !defined(_MANAGED)
  #error Requires --cppcli  // No longer an error with --cppcli
  #endif


3/27/14  [EDGcpfe/14979]
Default template arguments on member class template of non-template class

The front end issued a spurious error if an out-of-class definition of
a class template member of a non-template class specified a default
template argument.  Such usage is prohibited for members of class templates,
but not for members of non-template classes.  Now fixed.

  struct A {
    template <typename T> class B;
  };
  template <typename T = int> class A::B { };


3/26/14  [EDGcpfe/14937]
Dependent static member constant matched to pointer parameter in GNU mode

A constant whose value is template-dependent and whose type is a non-dependent
integral type is normally not considered a potential null pointer constant
when matching the constant to a pointer type parameter.  However, in GNU mode
that rule was disabled because calls with such constants were expected to be
treated as "template-dependent" and resolved at template instantiation time
when the value of the constant is known.  (See the entry for EDGcpfe/9380 on
12/15/08.)  However, not all calls with such constants as arguments are
"template-dependent" in GNU C++ mode; when they aren't, the normal rule of not
matching the constant with a pointer parameter now applies.  For example:

  void g(char*);
  void g(char);
  template<typename T> struct S {
    void f() {
      g(N);  // Previously triggered an ambiguity error in GNU C++ mode.
    }        // Now okay.
    static char unsigned const N = T::k;
  };
  struct X { static unsigned const k = 3; };
  template struct S<X>;  // To force a prototype instantiation of S<T>::f.

During the prototype instantiation of f, the call g(N) is nondependent even
in GNU C++ mode.  Previously, however, N was considered a potential match for
the char* parameter of g(char*), which resulted in an ambiguity.  Now, only
g(char) is a viable candidate (and hence there is no ambiguity).


3/26/14  [EDGcpfe/14951]
C++-generating back end: incorrect typeid expression with unnamed type

The C++-generating back end previously generated a reference to an
undeclared temporary type name when the operand of a typeid operator is
an expression whose type is an unnamed class or enumeration.  This is now
fixed.  For example:

  #include <typeinfo>
  struct { } x;
  void f() {
    typeid(x);  // Previously generated as "typeid(__T12345678)"
  }


3/26/14  [EDGcpfe/14966]
Spurious "never referenced" diagnostic on variadic function parameter

A spurious "never referenced" diagnostic (a remark, by default) could be
issued for non-initial elements of a pack expansion of a variadic template.
Now fixed.

  template <typename... Args> inline int f(Args... args) {
    return sizeof...(args);
  }
  int main(void) {
    f(1,2,3,4);
  }


3/26/14  [EDGcpfe/14963]
C++-generating back end: omitted braces in parenthesized direct value
initialization

The strict interpretation of a C++11 example like

  struct S {
    S();
  };
  void f() {
    S s({});
  }

is that a temporary S object is constructed using S::S() and the result is
moved into s by S's generated move constructor.  However, the Standard
permits eliding the move operation, so the IL for the initializer of s in
this example reflects calling the default constructor directly for s.  The
C++-generating back end consequently incorrectly generated the declaration
of s as

  S s();

which declares a function, not a variable.  This has now been fixed; the
C++-generating back end detects this special case and generates the
declaration as

  S s(S{});


3/21/14  [EDGcpfe/14926]
Comparing different enumeration types

The front end now issues a remark for comparisons between two different enum
types.  For example:

  enum E { e };
  enum F { f };
  int v = e<f;  /* Now triggers a remark. */


3/21/14  [EDGcpfe/14947]
Microsoft C compatibility: static_assert

In Microsoft C mode with microsoft_version >= 1600, the front end now enables
static_assert with the C++ spelling of the keyword (i.e., "static_assert"
instead of "_Static_assert").


3/21/14  [EDGcpfe/14921]
Attribute nonnull matching across translation units

When simultaneously compiling multiple translation units, the front end now
allows a difference in the GNU attribute "nonnull" for declarations of the
same entity in differing translation units.  For example:

  // File1.cpp
  void f(char*) __attribute((nonnull(1)));

  // File2.cpp
  void f(char*);

Previously, simultaneously compiling both files above resulted in an error
(attribute "nonnull" is missing in another translation unit).  Now no error
is issued.


3/21/14  [EDGcpfe/14876,EDGcpfe/14934]
clang compatibility: __is_... keywords

In clang mode, the front end now approximates the unusual behavior of clang
compilers when dealing with keywords that start with "__is_".  Ordinarily,
these are indeed just keywords, but if they appear immediately after the
keyword "struct", a warning is issued and from there on they are treated as
keywords only in expression contexts when they are immediately followed by a
left parenthesis.  For example:

  // int __is_pod;     // Would be an error at this point.
  struct __is_pod {};  // Now accepted with a warning in clang mode.
  int __is_pod;        // Also accepted.
  static_assert(__is_pod(int), "!");  // __is_pod is a keyword here.

This is known not to be a perfect emulation of the current clang behavior,
but it is expected to be sufficient for normal code (and clang is expected
to switch to this exact model in the future).


3/21/14  [EDGcpfe/14936]
C++11: Narrowing conversion and nontype template arguments

In C++11, narrowing conversions are not permitted for nontype template
arguments of integral or enum type.  However, the front end was previously
only considering the type of a template argument consisting of the name of
a constant-valued variable (and not its value) when deciding whether a
narrowing conversion is involved.  This could trigger spurious errors.
For example:

  template<int T> void g() {}
  void f() {
    unsigned const N = 1;
    g<N>();  // A conversion from unsigned to int is not a narrowing
  }          // conversion if the unsigned value is a known constant that
             // fits in type int.  Previously the front triggered an error
             // here; now okay.

This is now fixed.
  

3/21/14  [EDGcpfe/14938]
Abort on type traits helper that checks access in template argument

Certain type traits helpers (like __is_destructible) check the accessibility
of special member functions.  When such a construct was used in a context that
ordinarily requires the deferral of accessibility checks (in particular,
template arguments), the front end aborted in record_access_error (with
message "access check result needed immediately but access check deferral in
effect", in symbol_tbl.c).  For example:

  class C { ~C(); };          // Private destructor.
  template<bool> struct X {};
  X<__is_destructible(C)> x;  // Previously aborted; now okay.

This is now fixed.


3/21/14  [EDGcpfe/14940]
GNU/clang compatibility: Pointer/reference to array of unknown bound parameter

In GNU and clang C++ modes, the front end now accepts a parameter type that
is a pointer or reference to an array of unknown bound.  For example:

  void f(int (*)[]);  // Now accepted in GNU and clang C++ modes.

Note that GCC only accepts such constructs in some template instantiation
contexts, whereas the front end accepts them unconditionally (as does the
clang compiler).

See also the Changes entry of 6/24/97 for the similar feature in Microsoft
mode.


3/21/14  [EDGcpfe/14952]
Spurious error on use of "final" on member class template

A spurious error was issued during the instantiation of a class template
that contained a nested class template that made use of the "final"
keyword.  Now fixed.

  template <class T> class A {
    template <class U> class B final {};
  };
  A<int> a;


3/21/14  [EDGcpfe/14946]
Microsoft and GNU compatibility: Elaborated specifiers for scoped enum types

In C++11 mode, a scoped enum type can be referred to using a so-called
"elaborated type specifier" of the form "enum <name>".  The standard does not
permit the forms "enum class <name>" or "enum struct <name>" for such type
specifiers.  Microsoft and GNU compilers, however, do accept those forms, and
the front end now emulates that in Microsoft and GNU modes (with a warning in
GNU mode, to match GCC's behavior).  For example:

  enum class E { e };
  enum class E x = E::e;  // Now accepted in GNU and Microsoft modes.

In other modes, the error has been made discretionary.


3/21/14  [EDGcpfe/14944]
Microsoft and clang compatibility: Opaque enum declarations

C++11 allows an enum type to be declared with an explicit underlying type but
without actually providing a definition.  This is known as an "opaque enum
declaration" (see the entry of 6/20/12 for EDGcpfe/9250 et al.).  For example:

  enum E: int;

The standard requires such declarations to stand on their own (i.e., to be
followed by a semicolon), but clang and Microsoft compilers permit them to
be part of other declarations.  For example:

  enum E: int x;  // Now accepted in some clang and Microsoft modes.

The front end now emulates that behavior in Microsoft and clang modes that
accept opaque enum declarations.


3/21/14  [EDGcpfe/14948]
Microsoft compatibility: error on use of member function in instantiated base

A change was made in version 4.6 that could result in spurious errors
in Microsoft mode when a member function was used without arguments
in a decltype context.  Now fixed.

  template <class T> class A {
    static int Foo_t(void);
    typedef decltype(Foo_t)* Foo;
  };
  template <class C> class B: public A<C> { };


3/20/14  [EDGcpfe/14943]
Override of a virtual destructor in a class with a template base class

A spurious error had been issued when the virtual destructor declared in a
class with a template base class specified the "override" function modifier.
Now fixed.  For example (with --c++11):

  template <class T> struct A : T {
    virtual ~A() override;
  };


3/20/14  [EDGcpfe/14226]
Microsoft compatibility: Errors using certain C++/CLI assemblies

Certain assemblies (such as System.Windows.Forms.dll) were not handled
properly in C++/CLI, resulting in spurious errors when importing the
assembly.  Now fixed.

  #using <System.dll>
  #using <System.Drawing.dll>
  #using <System.Windows.Forms.dll>
  using namespace System;
  using namespace System::Runtime::CompilerServices;
  using namespace System::Drawing;
  using namespace System::Windows::Forms;
  namespace N {
    public ref class Button : Control {
      EventHandler^ action;
    public:
      event EventHandler^ Click {
        void add(EventHandler^ d) { }
        void remove(EventHandler^ d) {}
        void raise(Object^ sender, EventArgs^ e) {}
      }
    };
  }



3/19/14  [EDGcpfe/14824]
Spurious remark for unevaluated use of undefined symbol in #if

In C++11 mode when the && or || operator is overloaded, the front end
issued a spurious remark about an "undefined preprocessing identifier"
appearing in an unevaluated right-hand operand of that operator in the
expression of a #if directive.  This is now fixed.  For example:

  struct S { };
  bool operator&&(const S&, const S&);
  // "X" is not defined here
  #if defined(X) && X  // Previously caused a remark for use of X after &&
  #endif


3/19/14  [EDGcpfe/14900]
Invalid UTF-8 characters in character string literals

The front end previously incorrectly recovered from the occurrence of
invalid UTF-8 characters in character string literals, resulting in
incorrect data and potential aborts.  This is now fixed.  For example,
assuming the --unicode_source_kind=UTF-8 command-line option, the following
invalid UTF-8 character sequence resulted in an abort in
conv_string_literal:

  char str[] = "«8080808080808080»";

Note: The above example must be decoded using the edg-changes-example tool.


3/19/14  [EDGcpfe/14933]
Microsoft compatibility: incomplete type error on nonreal instantiation

A change made in version 4.5 (see EDGcpfe/12786 on 5/14/12) could result
in an incomplete type error in Microsoft mode when a real class is used as
a base class of an instantiated nonreal class.  Now fixed.

  template <class T> class A : T { };
  template <size_t sz>  class B;
  typedef A<B<sizeof(long)> > AB;
  template<class T, class U> class C : U { };
  // The following caused the instantiation of C<T*, AB>, which resulted in
  // the incomplete type referred to by AB being used as a base class of C.
  template <typename T> class D : public C<T*, AB> {
    typedef C<T*,  AB> base;
  };


3/19/14  [EDGcpfe/14899]
Extended characters and surrogate pairs in char16_t string literals

An extended character appearing directly (i.e., not as a
universal-character-name) in a char16_t string literal was incorrectly
handled by the front end when the character requires a surrogate pair in
its UTF-16 encoding.  Rather than producing the corresponding surrogate
pair, the front end previously truncated the character's code point to its
low-order 16 bits.  This is now fixed.  For example, assuming the
--unicode_source_kind=UTF-8 command-line option, the following two strings
should be (and now are) equivalent, containing the two char16_t code units
of the character's surrogate pair and the terminating null character.  The
front end previously created a four-byte value for the second string, with
both char16_t characters being the null character:

  char16_t c1[] = u"\U00010000";
  char16_t c2[] = u"𐀀";


3/18/14  [EDGcpfe/14898]
char16_t literals and out-of-range numeric escape sequences

The front end incorrectly treated an out-of-range numeric escape sequence
appearing in a char16_t literal as an extended character requiring a
surrogate pair, resulting in incorrect data and potential aborts.  This is
now fixed: a warning is issued and the value is truncated to a single
char16_t character.  For example:

  char16_t str[] = u"\x10000\x10000";  // Previously aborted in
                                       // conv_string_literal


3/16/14  [EDGcpfe/14919]
Error on explicit instantiation of function template from inline namespace

A spurious error was issued if a function template declared in an inline
namespace was explicitly instantiated using an unqualified name.  Now fixed.

  inline namespace {
    template <class T> void f(T) { }
  }
  template void f(int);


3/15/14  [EDGcpfe/14931]
Move infrequently-used GNU-specific fields out of a_routine (IL CHANGE)

A number of infrequently-used GNU-specific fields have been moved from
a_routine into a new IL entry, a_gnu_routine_supplement, and a pointer to
that IL entry is now dynamically allocated when any one of those fields
has a non-default value.  The fields that were moved are: section,
aliased_routine, resolver_var, inline_partner, ctor_priority, dtor_priority,
and asm_name.  The new field in a_routine is "gnu_extra_info" (so, e.g.,
rp->section now becomes rp->gnu_extra_info->section).  Three new macros,
gnu_routine_supp, ensure_gnu_routine_supp, and has_gnu_routine_supp have been
added to assist in accessing these fields.  This is an IL CHANGE.


3/15/14  [EDGcpfe/14838]
NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE and --no_multibyte_chars

In a configuration with NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE set
to TRUE, the --no_multibyte_chars command-line option had no effect:
byte sequences that are valid multibyte characters in the current locale
were still accepted as such although --no_multibyte_chars should have
disabled that processing.  This is now fixed.  For example:

  // The following is a valid identifier in EUC-JP locale with multibyte
  // characters but is now diagnosed as "unrecognized token" with
  // --no_multibyte_chars:
  int «a4a2» = 1;

Note: The above example must be decoded using the edg-changes-example tool.


3/12/14  [EDGcpfe/14904]
Folding of initializers with references to previously-initialized fields

The front end incorrectly treated as non-constant an initialization in
which the initializer for a non-static data member referred to a
previously-initialized member's value.  This is now fixed.  For example:

  struct F {
    constexpr F(): x(3) {}
    int x;
    int y = x;
  };
  double d[F().y];  // Previously an error, now accepted.


3/8/14   [EDGcpfe/14920]
Qualified names for scoped and member enumerators

In some configurations, the name of a scoped or member enumerator
incorrectly appeared in the output of il_to_str (e.g., in diagnostic
messages) as an unqualified name.  This has now been fixed.  For example:

  enum class E { e0 };

  template<E T> struct X {
  };

  int f(int);
  int f(double);

  int g() {
    return f(X<E::e0>());  // Error message previously referred to "X<e0>"
  }


3/7/14   [EDGcpfe/14819]
Internal error in f_set_no_trans_unit_corresp

When simultaneously compiling multiple translation units, the front end tracks
for each entity declared in multiple translation units a "canonical entry"
(the entry that will eventually be kept in the merged IL tree).  Among other
criteria, an IL entry for a class type is preferred as a choice for a
"canonical entry" if the entry corresponds to a definition, but the front end
previously failed to distinguish a complete definition from one that is still
being completed.  In some complex multi-translation unit cases, this could
result in an internal error in f_set_no_trans_unit_corresp (in trans_corresp.c;
with message "correspondence busy").  That problem is now fixed.


3/6/14   [EDGcpfe/14916]
C++-generating back end: typedef for dependent decltype as qualifier

In C++-generating back end configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the changes to support decltype
as a qualifier in version 4.8 (see the entry for EDGcpfe/10610) caused an
assertion failure in gen_class_qualifier when a typedef whose underlying
type is a dependent decltype is used as the nested-name-specifier in a
qualified name.  This is now fixed.  For example:

  template<typename T> struct S {
    typedef decltype(T::x) TX;
    typedef typename TX::z TXZ;  // Previously caused an assertion failure
  };


3/6/14   [EDGcpfe/14913]
Microsoft-mode alignment on intermediate typedefs

In Microsoft mode (as in GNU modes) the front end allows a typedef to have an
alignment different from its underlying type.  However, when such a typedef was
itself underlying another type, the front end frequently failed to take the
explicit alignment into account.  For example:

  #define OFFSET(s, m) \
     (unsigned long)(&reinterpret_cast<char&>((((s *)0)->m)) )
  typedef __declspec(align(16)) float AlignedFloat;
  typedef AlignedFloat AF;
  struct S {
    float t;
    AF v;
  };
  static_assert(OFFSET(S, v) == 16, "Unexpected");  // Previously failed in
                                                    // some cases; now okay.

When compiled with "--microsoft_version --pack_alignment=8" the front end
should discard the request to align the struct on an 8-byte boundary because
the type AF is explicitly aligned on a 16-byte boundary.  Previously, the
front end failed to see this due to the multiple typedef levels.  That is now
fixed.


3/6/14   [EDGcpfe/14910]
Const-qualification on temporary for lowered pointer-to-member constant

The temporary created during lowering to point to the lowered pointer-to-member
constant had been const-qualified and, as an unintended consequence of the
changes for the C++11 constexpr feature (see the Changes entry for
EDGcpfe/8523), had that const-qualification stripped.  The const-qualification
has now been restored.  For example:

 struct A;
 struct B {
   typedef void (A::*pmf)(B*);
   B(pmf);
 };
 struct A {
   void f(B*) {}
 };
 B obj = B(&A::f);


3/6/14   [EDGcpfe/14885]
Assertion failure in lower_array_new

The example below had failed an assertion check in lower_array_new in
configurations where
NEW_AND_DELETE_FOR_ARRAY_CAN_BE_FOLDED_INTO_RUNTIME_ROUTINE is FALSE because
lowering of the member function B::f (which had been delayed because of the
presence of a static variable and the lack of a module id) was mistakenly
lowered after the file scope had been popped.  Now fixed.
For example (with --c++11 --no_exceptions):

  struct A {
    A();
  };
  struct B {
    void f() {
      static int i;
      new A[1];
    }
  };
  int x = 0;


3/6/14   [EDGcpfe/14911]
Deducing auto&& from an initializer list

The front end previously incorrectly handled deduction of a variable declared
with "auto&&" and initialized with a braced initializer containing lvalues.
This resulted in spurious errors.  For example:

  #include <initializer_list>
  int main() {
    int i = 42;
    auto &&r = { i, i };  // Previously triggered spurious errors; now okay.
  }

This is now fixed.


3/6/14   [EDGcpfe/14914]
Spurious error on indirect field with volatile member in union

The changes for EDGcpfe/13954 did not completely address the problem they
intended to solve.  Specifically, in C++03 mode, the front end still issued
a spurious error on a union containing a class type that indirectly includes
a volatile class-type field (the original problem had been identified for
direct fields).  For example:

  struct T {};
  struct V { volatile T t; };
  struct S { V v; };
  union U {
    S s;  // Previously triggered a spurious error in C++03 mode; now okay.
  };

This is now fixed.



3/5/14   [EDGcpfe/14903]
Microsoft compatibility: Qualified class types and pointer-to-member types

In Microsoft C++ modes, when rescanning a template, a dependent pointer-to-
member-function type may have a "const/volatile" member function type if
the substituted parent class type is const/volatile (see the Changes entry of
1/18/12 for EDGcpfe/12214).  However, it appears that this is not done by the
Microsoft compiler if the pointer-to-member type appears in a non-template
member of a class template.  The front end now more closely emulates that
Microsoft behavior.  For example:

  struct S { void f() const; };
  template<class C> struct D {
    typedef void (C::*pmf)();
  };
  template<class C> void b(C*, typename D<C>::pmf);
  void g() {
    S const *cp = 0;
    b(cp, &S::f);  // Previously accepted in Microsoft mode; now an error
  }                // because the "const" in the deduced type for parameter
                   // C no longer transfers to the member function type.


3/5/14   [EDGcpfe/14146]
C++14: Aggregate class types with nonstatic data member initializers

In C++14 mode, aggregate class types are permitted to have nonstatic data
member initializers.  For example:

  struct S { int x, y = x; } s = { 11 };  // Initializes s.y to 11 also.

This relaxation of the class aggregate rules was introduced by the C++
standards committee's paper N3653.


2/28/14  [EDGcpfe/14874]
Relaxed lambda forms with deduced return types

In the original C++11 standard, lambdas with deduced return types had to
consist of a single return statement.  The committee relaxed this constraint,
and the front end now accepts the more general case in all modes that support
lambda expressions.  Technically, the relaxation came via the committee's
paper N3638 (see the entry for EDGcpfe/14144,EDGcpfe/14633) which introduces
C++14 features, but the development of that aspect of it was in response to
Core Issue 975 and had originally been approved by the Core Working Group as
a C++11 defect resolution.  Treating it as a C++11 defect resolution also
matches the resolution of other major implementations.


2/27/14  [EDGcpfe/14890]
GNU C++11-mode IL corruption with array rvalue in constexpr context

In GNU C++11 mode, the front end could end up creating corrupted IL entries
when performing an array-to-pointer conversion on an array rvalue in a
constexpr context.  This corruption usually manifested itself as an abort
somewhere downstream from the conversion process (e.g., when writing the IL
to a file).  For example:

  struct S {
    int const *ap[2];
  };
  void g() {
    constexpr int i = 42;
    constexpr int k = *S{{&i}}.ap[0];  // Previously triggered an abort in
  }                                    // some configurations.

In this example, the sub-expression "S{{&i}}.ap" is an array lvalue, and
applying the subscripting operator to it implies an array-to-pointer
conversion, which triggered an abort in GNU C++11 mode.

This is now fixed.


2/27/14  [EDGcpfe/14839]
C++-generating back end: incorrect construction of alias instantiation

An alias template instantiated with dependent template arguments was sometimes
not constructed properly in the C++-generating back end output when the
output was generated from IL (i.e., with PROTOTYPE_INSTANTIATIONS_IN_IL).
Specifically, pack expansion information in the alias instantiation (e.g.,
the definition of the alias C in the example below) could be missing.
Now fixed.

  template<typename T> T f();
  template<typename T> struct Z { };
  template<typename R, typename... A> struct S {
    template<typename F> using I = decltype(F()(f<A>()...));
    template<typename F> using C = Z<I<F>>;
    // Formerly emitted as:
    //   template< class F> using C = Z< decltype((F()(f<A>())))> ;
  };


2/26/14  [EDGcpfe/14879]
Abort on __is_convertible_to testing convertibility from reference type

In modes that support the __is_convertible_to type trait helper, the front
end aborted when evaluating the helper for a source type that is a reference
to an incomplete type.  For example:

  static_assert(!__is_convertible_to(char(&)[], char*), "Unexpected");
    // Previously aborted in C++11 (and other) modes.

This is now fixed.


2/26/14  [EDGcpfe/14888]
Braced initializers for static data members of class templates

The front end previously accidentally treated "direct" list initialization
of static data members of class templates as "copy" list initialization (the
"direct" syntax omits the "=" sign of the "copy" syntax).  This could result
in spurious errors (e.g., because copy-list-initialization doesn't consider
explicit constructors).  For example:

  template<typename T> struct X {
    static T x;
  };
  template<typename T> T X<T>::x{0};
  struct S { explicit S(int); };
  template S X<S>::x;  // Previously triggered a spurious error about the
                       // explicit constructor not being available for
                       // copy-list-initialization.

This problem is now fixed.


2/26/14  [EDGcpfe/14849]
Spurious access error for protected trivial (defaulted) copy constructor

When checking access to a protected defaulted copy constructor that is also a
trivial copy constructor, the front end did not correctly consider the origin
of the access.  This could result in spurious access errors.  For example:

  struct N { N(N const&); };
  class P {
  protected:
    P(P const&) = default; // Trivial copy constructor.
  };
  struct D : public P {
    D();
    N n;
  } d;
  D copy(d);  // Requires the generation of the copy constructor of D, which
              // in turn requires access to the trivial copy constructor of P.
              // Previously, that triggered a protected member access error.

This problem is now fixed.


2/24/14  [EDGcpfe/14858]
Segfault displaying IL for array type with dependent bound expression

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, an array
type with a dependent bound expression involving a local variable could
result in a segfault (in form_expression, il_to_str.c) in the IL display
program applied to the resulting IL file.  This is now fixed.  For example:

  template <typename T> void f(T out) {
    typedef int y[sizeof(out) + 1];  // could segfault in edgcpdisp
  }


2/24/14  [EDGcpfe/13815,EDGcpfe/13847,EDGcpfe/14553,EDGcpfe/14764,
          EDGcpfe/14805]
Pack expansions in alias templates used in template declaration contexts

If a pack expansion was used in an alias template definition and that
alias template was instantiated with a pack expansion in a template
declaration context, the pack was not expanded properly when the template
declaration was instantiated or used in a deduction or partial ordering
context.  This caused compilation errors when using the GNU 4.8 <future>
header.  Now fixed.

  template <typename T, T... I> struct A { };
  template <int... K> using B = A<int, K...>;
  template <int... I> void f(B<I...> i) {}
  int main() {
    B<1,2,3> i3;
    f(i3);
  }


2/23/14  [EDGcpfe/14857]
GNU compatibility: macro names vs C++11 user-defined literal suffixes

C99 defines macros such as PRId64 whose definitions are string literals
containing printf formatting controls.  They are intended to be
concatenated with other string literals to provide portable formatting for
implementation-defined numeric types.  One programming style places these
formatting controls adjacent to the surrounding string literals with no
intervening white space, for example:

  void f() {
    int64_t i = 0;
    printf("%"PRId64"\n", i);
  }

This usage is not permitted in C++11 because the macro name is parsed as
a user-defined literal suffix and not as an identifier token, making it
unavailable for macro expansion and attempting to invoke a nonexistent
literal operator.  Beginning with version 4.8, however, g++ accepts such
code, and the front end has now been changed to do so as well in g++ mode
with gnu_version >= 40800, although the mechanism is different: the C99
macro names are not valid user-defined literal suffixes because they do not
begin with an underscore, and g++ puts out a warning for such cases and
makes the failing suffix a separate token.  This technique is not upwardly
compatible with potential future standard suffixes that do not begin with
an underscore, so the front end keys on the presence of a macro definition,
not on the form of the name, in determining whether to treat the identifier
as a literal suffix or not.

This behavior is controlled by the global variable macro_preempts_udl_suffix
to allow it to be enabled, if desired, for modes other than the default.


2/22/14  [EDGcpfe/11636,EDGcpfe/14412,EDGcpfe/14705,EDGcpfe/14856]
<: digraph in C++11 mode

The C++11 Standard changed the treatment of the <: digraph (equivalent to
the "[" token) so that it is not recognized when the ":" is likely meant as
the first character of the :: global scope operator.  The front end now
implements this rule in C++11 mode.  With --c++11 --g++, the new rule is
applied only for gnu_version >= 40800, since earlier versions of g++ always
treat <: as a digraph, even with -std=c++11.  For example:

  int i;
  int f() {
    return 0<::i;  // Previously interpreted as "0[:i", now as "0 < ::i"
  }


2/22/14  [EDGcpfe/14842]
Incorrect source positions in dependent constant expressions

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL and PARENS_IN_IL set
to TRUE, the IL contained missing or incorrect source position information
in constant expressions that depend on nontype template parameters.  For
example, given

  template<int N> void f() {
    int i = (N-1);
  }

the eok_parens node in the initializer for "i" had no source position
information, while the expr_range and operator_position of the eok_subtract
node reflected the positions of the parentheses.  This is now fixed.


2/22/14  [EDGcpfe/14625]
Microsoft compatibility: floating-point literals in constant expressions

The changes for constexpr support in version 4.6 inadvertently caused a
regression preventing the use of floating-point literals in constant
expressions in Microsoft mode.  This is now fixed.  For example:

  void f() {
    static_assert(1.0 < 2.0, "err");  // Previously an error in Microsoft mode
  }


2/21/14  [EDGcpfe/14144,EDGcpfe/14633]
C++14: Deduced return types

In C++14 mode the front end now accepts functions with deduced return types.
For example:

  auto forty_two() { return 42; }  // Return type deduced to "int".
  auto pointer_42()->auto* {       // The first "auto" announces the trailing
    return forty_two;              // return type.  The second auto is the
  }                                // placeholder type to be deduced.

This change to the C++ language was introduced by the committee's paper N3638.


2/20/14  [EDGcpfe/14873]
C11: value of __STDC_VERSION__ macro

In C11 mode, the value of the __STDC_VERSION__ predefined macro is now
201112L, as required by the C11 Standard.


2/20/14  [EDGcpfe/12777]
C11: UTF-8, char16_t, and char32_t literals

In C11 mode the front end now accepts character constants prefixed with u
or U and string literals prefixed with u8, u, or U to indicate UTF-8,
UTF-16, or UTF-32 encoding of the value.  This is essentially identical to
the C++11 implementation of this feature, except for three points: first,
in C++11, char16_t and char32_t are reserved words denoting unique types
for UTF-16 and UTF-32 characters, while in C11 they are not predeclared and
not unique.  Second, a char16_t or char32_t character literal containing
more than one character is an error in C++11 but is permitted, with
implementation-defined results, in C11.  (The front end issues a warning
and discards all but the last character of the literal in C11 mode.)
Finally, the macros __STDC_UTF_16__ and __STDC_UTF_32__ are predefined in
C11 mode with the value 1 to indicate that the encoding of char16_t and
char32_t characters is UTF-16 and UTF-32, respectively; those macros are
not defined in C++11 mode.  These literal forms can be enabled or disabled
by the command-line option --[no_]uliterals.


2/13/14  [EDGcpfe/13985,EDGcpfe/14725]
Deduction in pack contexts that contain explicit template arguments

If a pack expansion made use of both a template parameter pack for which
the template arguments were explicitly specified, and a template parameter
pack that was deduced, deduction could fail resulting in spurious errors
or the incorrect function being called.  Now fixed.

  template <typename T1, typename T2> struct A {};
  template <typename... T> struct B {};
  template <typename... P1, typename... P2>
  B<A<P1, P2>...>* f(P2...) {return nullptr; }
  int main() {
    f<int,char>(1, 'x');
  }


2/11/14  [EDGcpfe/10093]
GNU: Allow zero as a valid "constructor" or "destructor" attribute value

GNU accepts (with a warning) a value of "0" for a "constructor" or "destructor"
attribute, and now so does the front end.  Previously, the value of zero for
the a_routine::ctor_priority and a_routine::dtor_priority fields was used as
a "flag" to indicate that a priority value had not been specified, now two
new fields, a_routine::has_ctor_priority and a_routine::has_dtor_priority
have been added to fill this role.  As such, this is a slight IL CHANGE.
For example (with --gcc):

  void f(void) __attribute__((constructor(0)));
  void g(void) __attribute__((destructor(0)));


2/10/14  [EDGcpfe/14816]
Issue with virtual function call dispatch in the IA-64 ABI

In cases where a class shares a virtual function pointer with a virtual base
class, it had been possible for the shared virtual function pointer to have
been set (to a construction vtable entry) during virtual base initialization
and then used before it was re-set to point to the derived class, causing
unpredictable results.  In the example below, the implicit dynamic cast of
"this" to "IB *" had been performed with an incorrect virtual function pointer,
leading to an incorrect computation for the result, which, in some cases, had
resulted in calling "foo" rather than "bar".  A change has been made (in IA-64
ABI configurations) to re-set the virtual function pointer in cases where a
virtual base initialization shares a virtual function pointer with a derived
class.

  extern "C" int printf(const char*,...);
  struct IA {
    virtual void foo() = 0;
  };
  struct IB {
    virtual void bar() = 0;
  };
  struct A : virtual IA {
    A(IB* bp) : m_bp(bp) {}
    void foo() { printf("foo\n"); }
    IB* m_bp;
  };
  struct B : virtual IB, A {
    B() : A(this) {}
    void bar() { printf("bar\n"); }
  };
  int main() {
    B b;
    b.m_bp->bar();
  }


2/10/14  [EDGcpfe/14744]
C11: _Thread_local

The front end now supports the _Thread_local storage class specifier in C11
mode.  Support for _Thread_local is nearly identical to the C++11 thread_local
storage class specifier (see the 8/28/13 Changes entry), except that there
is no dynamic initialization (or destruction).

In configurations where IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS is FALSE,
the __STDC_NO_THREADS__ macro is defined to 1 (in C mode).


2/6/14   [EDGcpfe/14843]
Instantiations during copy/move assignment operator generation

When the front end determines which special members to generate for a class
type (like copy constructors and copy assignment operators), it may have to
instantiate class types, which may lead to errors (which instantiations occur
is not precisely defined by the language).  The front end now avoid some such
instantiations while generating copy/move assignment operators.  For example:

  template<typename> struct P {};
  template <typename T> struct P<T const&> {
    typedef T value_type;
  };
  template < typename T> struct X {
    typedef typename P<T&>::value_type value_type;
    value_type v;
  };
  struct S {
    void operator=(S&);
    template<typename T> typename X<T>::value_type operator=(T&);
  };
  X<S const> e;

Previously, while considering the generation of a move assignment operator
for X<S const> in this example, the front end attempted to instantiate
X<S>::value_type (which doesn't exist, and therefor triggers an error) as
part of testing the member assignment template of S for copying the member
X<S const>::v.  Now the member assignment template is discarded without
requiring the instantiation of X<T>::value_type.


2/5/14   [EDGcpfe/14383]
C++14: decltype(auto)

In C++14 mode, the front end now accepts the decltype(auto) construct for
variable declarations.  For example:

  decltype(auto) i1 = 1;     // deduces i1 to be int (i.e., decltype(1)).
  decltype(auto) i2 = (i1);  // deduces i2 to be int& (i.e., decltype((i1))).
  decltype(auto) i3 = i1;    // deduces i3 to be int (i.e., decltype(i1)).


2/5/14   [EDGcpfe/14836]
Spurious ambiguity in partial ordering involving nondeduced nontype parameter

A spurious ambiguity diagnostic could be issued when a more-specialized
function template makes use of a nontype template argument in a non-deduced
context.  Now fixed.

  template <int I> struct A {};
  template <typename T> struct B;
  template <class T> struct C {};
  template <> struct B<C<int> > {
    static const int n = 10;
  };
  template <class T> void f(A<B<C<T > >::n>, C<T>);
  template <class T, int I> void f(A<I>, T);
  int main() {
    A<10> a10;
    C<int> ci;
    f(a10, ci);
  }


2/3/14   [EDGcpfe/14835]
Spurious error on inheriting constructor using typedef in class template

When an inheriting constructor in a template is expressed using a typedef
name, the front end previously issued a spurious error.  For example:

  template<typename T> struct B {};
  template<typename T> struct D : B<T> {
    typedef B<T> Base;
    using Base::Base;  // Previously triggered an error about "Base" already
  };                   // being declared in this scope.  Now okay.

This is now fixed.


2/3/14   [EDGcpfe/14834]
Spurious error on aggregate initialization in prototype instantiation

When performing prototype instantiations of function templates in non-C++11
modes (e.g., strict C++03 mode), the front end sometimes issued a spurious
error on a braced initializer.  For example:

  template<typename T> struct S { int i; };
  template<typename T> void g() {
    static S<T> sa[] = { { 1 }, { 2 } };  // Previously a spurious error in
  }                                       // some modes; now okay.

This is now fixed.


1/31/14  [EDGcpfe/14827]
Spurious "no default constructor" error with a trivial default constructor

In some cases involving user-defaulted special members, the front end failed
to represent a trivial default constructor, which in turn triggered spurious
errors about missing default constructors.  For example:

  struct D {
    D& operator=(D&&) = default;
  } d;  // Previously a spurious error "no default constructor"; now okay.

This is now fixed.


1/31/14  [EDGcpfe/14826]
Trivially copyable class types

A trivially copyable class type is a class type that has a trivial destructor
and whose copy/move functions (constructors, assignment operators) are all
trivial.  Previously, the front end considered the presence of a deleted
copy/move function to make a class type not trivially copyable, which was
erroneous.  This resulted in wrong outcomes for the type traits helpers
__is_trivially_copyable and __is_trivial.  For example:

  struct TC {
    TC(TC&&) = default;  // The explicit declaration of this trivial move
  };                     // makes the implicitly-declared copy constructor
                         // "deleted", but it remains "trivial".
  static_assert(__is_trivially_copyable(TC), "Error");

This is now fixed.


1/31/14  [EDGcpfe/14831]
Microsoft C compatibility: C99-style for-statements

In Microsoft C mode with microsoft_version >= 1800, the front end now supports
C99-style for-statements.  For example:

  int g(int n) {
    for (int k = 1; k<=n; ++k);  // Now accepted in Microsoft C mode with
    int k = 3;                   // microsoft_version >= 1800.
    return n+k;
  }


1/31/14  [EDGcpfe/14817]
Abort in GNU mode on template argument referring to a local variable

In GNU C++ mode a template argument referring to a local variable could
sometimes lead to an internal error in expr_to_record_for_variable with
configurations that record backing expressions for constants.  For example:

  template<int I> struct X {};
  void g() {
    unsigned const N = 0;
    X<(N<2) ? 1 : (N<4) ? 2 : 0> x;  // Previously triggered an assertion
  }                                  // failure in some modes/configurations.

This is now fixed.


1/30/14  [EDGcpfe/14755]
Microsoft compatibility: Preferring move constructors in overload resolution

In Microsoft mode, the front end prefers copy constructors over other member
functions during overload resolution (see the Changes entry of 8/14/03).  This
rule is now extended to include move constructors.  For example:

  struct D {
    D(D&&);
    D(int);
  };
  struct S {
    operator D();
    operator int();
  };
  S g();
  D d(g());  // Now accepted in all Microsoft modes.  The D(D&&) constructor
             // is selected.  (An ambiguity error is issued in default and
             // strict modes.)


1/30/14  [EDGcpfe/14825]
Spurious error on scoped enum declaration then definition in class template

A spurious "declaration does not declare anything" error was issued if
a class template contained an opaque enumeration declaration followed
by a definition that was also within the class.  Now fixed.

  template <class T> struct X {
    enum class ID:T;
    enum class ID:T { i1, i2 };
  };
  int i = (int)X<int>::ID::i2;


1/30/14  [EDGcpfe/14616]
GNU C++ compatibility: Partial ordering of nonstatic members vs non-members

g++ does not seem to implement the partial ordering of members and non-members
as described in core issue 532 (see entry for EDGcpfe/10974 on 5/9/13). We
now disable this ordering in C++11 g++ mode (causing the example below
to be accepted).

  template <typename T> struct A {
    template <typename U> void operator*=(U); // #1
  };
  template <typename T> void operator*=(A<T> &, const int &) { } // #2
  int main() {
    A<int> a;
    a *= 2;  // should call #2 in g++ mode
  }


1/29/14  [EDGcpfe/14820]
GNU compatibility: Predeclared _IO_FILE type

When emulating GCC 4.0 or later (C or C++ modes), the front end now predeclares
a struct type _IO_FILE (in global scope), which corresponds to the C standard
library's FILE type.  Furthermore, when that type is predeclared, the following
predeclared functions include a parameter of type _IO_FILE* instead of void*:
__builtin_fprintf, __builtin_fprintf_unlocked, __builtin_fputc,
__builtin_fputc_unlocked, __builtin_fputs, __builtin_fputs_unlocked,
__builtin_fscanf, __builtin_fwrite, __builtin_fwrite_unlocked,
__builtin_vfprintf, and __builtin_vfscanf.  (Note that none of this affects
clang mode.)


1/29/14  [EDGcpfe/14818]
Unbounded recursion in verify_template_correspondence with friend template

When simultaneously compiling multiple translation units the front end
sometimes entered an unbounded recursion sequence when attempting to verify
the correspondence of a friend class template across translation units.
(Since known examples of this behavior are quite intricate, none are included
here.)  That problem is now fixed.


1/29/14  [EDGcpfe/14811]
Microsoft bugs mode abort on invalid typename specifier

In Microsoft bugs mode, the front end previously aborted on certain invalid
"typename" specifiers (typically due to a null pointer being passed to
is_incomplete_type).  For example:

  auto x = typename(); // Previously aborted in is_incomplete_type.

This is now fixed.


1/29/14  [EDGcpfe/14814]
Internal error in GNU C++ mode on invalid compound literal

In some GNU C++ mode cases involving an attempt to initialize an empty class
type with an incompatible expression as part of a compound literal construct,
the front end aborted with an internal error in aggr_init_class (decl_inits.c).
For example:

  struct Empty {};
  struct S { Empty e; };
  S b[1] = (S[]) { 0 };  // Previously aborted in GNU C++ mode.
                         // Now a normal error.

This is now fixed (a normal type incompatibility error is issued).


1/27/14  [EDGcpfe/14809]
Constant folding with string constant values

The front end previously miscalculated the ending point of a string
initializer for a constexpr character array, so that accessing the array
element immediately following the string's terminating '\0' retrieved a
garbage value instead of the '\0' to which the array element is implicitly
initialized.  This is now fixed.  For example:

  constexpr char c[2] = "";
  constexpr char x = c[1];
  static_assert(x == 0, "Bug");   // Previously might fail


1/27/14  [EDGcpfe/14812]
Assertion failure in copy_type_full

When using a function with default arguments as the argument to decltype or
__typeof, an assertion failure in copy_type_full had resulted in some cases
and is now fixed.  For example (with --c++11):

  int f(int i = 1);
  void g() {
    decltype(f) x;
  }


1/25/14  [EDGcpfe/14794]
Warnings when building the front end with gcc

Building the front end using gcc with certain compilation options (notably
"-O2 -funroll-loops -Wall") resulted in compiler warnings.  These warnings
have now been eliminated.


1/25/14  [EDGcpfe/14808]
GNU: Add support for __builtin_cpu_init, __builtin_cpu_is,
     __builtin_cpu_supports

When gnu_version >= 40800, support has been added for the __builtin_cpu_init,
__builtin_cpu_is, and __builtin_cpu_supports GNU builtins.


1/24/14  [EDGcpfe/13424]
GNU "ifunc" attribute

Support has been added for the GNU "ifunc" attribute.  The ifunc attribute
specifies the name of a user-provided "resolver" function which is called once
at load time to determine dynamically the address to be used for the function
with the ifunc attribute.

As not all back ends support the STT_GNU_IFUNC ELF feature on which this
is based, a new configuration macro, LOWER_IFUNC, is introduced which,
when TRUE, will turn the ifunc routine into a wrapper function that
invokes the resolver (just once), caches the result and then dispatches
to the function returned by the resolver.  In certain cases, the call through
the wrapper function can be replaced by an indirect function call (see
the definition of LOWER_IFUNC for more information).  In most configurations
with lowering, LOWER_IFUNC defaults to TRUE (and FALSE when lowering isn't
used).

One caveat: as is the case with the GNU "alias" attribute, the name specified
by the "ifunc" attribute must be an unmangled name (g++ requires a mangled
name).  There is no such restriction when using C mode (as there are no
mangled names).  We hope to ease this restriction in the future.

For example (with --gcc --gnu_version 40600):

  int printf(const char *,...);
  void target(void) {
    printf("Here\n");
  }
  static void (*resolver(void))(void) {
    return &target;
  }
  void source() __attribute__ ((ifunc ("resolver")));
  int main() {
    source();   // Prints "Here"
  }


1/24/14  [EDGcpfe/14746]
C11: __STDC_NO_ATOMICS__ and __STDC_NO_VLA__

The front end currently does not implement the optional C11 feature known as
"atomic types" and accordingly predefines the macro __STDC_NO_ATOMICS__ to 1,
as required by the C11 standard.  Furthermore, in modes that disable support
for variable-length arrays, the front end similarly predefines the macro
__STDC_NO_VLA__.  Although these are requirements of the C11 standard, this
behavior has also been extended to plain C99 modes.


1/24/14  [EDGcpfe/14743]
C11: _Generic

The front end now supports the C11 _Generic construct.  For example:

  int f();
  int x = _Generic(f(), signed: -1, unsigned: 1);
    // Now accepted in C11 mode and equivalent to "int x = -1;".

A new configuration macro REPRESENT_C11_GENERIC_CONSTRUCT_IN_IL determines
whether the construct as a whole is represented in the IL (if the macro is
TRUE) or if only the selected expression is represented (if the macro is
FALSE).  The macro is TRUE by default if IL lowering is disabled and FALSE
otherwise (if it is set to TRUE when lowering is enabled, lowering will
eliminate the construct).


1/22/14  [EDGcpfe/12780,EDGcpfe/14747]
__builtin_complex

In modes that support built-in complex floating-point types (e.g., C99 mode
or GNU modes), the front end now supports the __builtin_complex construct to
create a complex value from its real and imaginary parts.  Given two constants
it produces a constant.  For example:

  _Complex double z = __builtin_complex(1.0, 2.0);  // Now accepted in C99
                                                    // mode.

This is useful to implement the CMPLX, CMPLXF, and CMPLXL macros mandated by
the C11 standard.

Furthermore, in clang modes, complex types can be initialized using aggregate
initialization syntax.  For example:

  _Complex float z = { 1.0, 2.0 };  // Now accepted in clang C99 mode.

The clang implementation uses this feature to implement the C11 macros listed
above.  (See also the entry of 11/28/12 for EDGcpfe/13347 for the identical
feature supported in some GNU C++ modes.)


1/22/14  [EDGcpfe/12779]
C11: _Alignof and _Alignas

In C11 mode, the front end now accepts the _Alignas(...) construct as well as
_Alignof as a synonym for __alignof (although in strict mode, only a type
operand is permitted for _Alignof).  For example:

  _Alignas(int) char buf[100];
  int buf_alignment = _Alignof(int);

Note that this is entirely similar to the C++11 "alignas" and "alignof"
features, and this is true also for the underlying implementation.  In
particular, the "_Alignas" construct is represented internally as a kind of
attribute (even in C11 modes that do not support a general attribute
mechanism).


1/22/14  [EDGcpfe/14789]
Abort when rescanning a type operand

The front end could previously abort when "rescanning" a call-like built-in
operation like __is_convertible_to (during the execution of clear_operand).
The problem only occurred in configuration that set CHECKING to FALSE.
For example:

  template<bool> struct R {};
  template<typename T> R<__is_convertible_to(T, int)> g();
  int main() { g<int>(); }  // Previously triggered an abort while
                            // rescanning the __is_convertible_to expression.

This is now fixed.


1/21/14  [EDGcpfe/12778]
C11: _Noreturn

In C11 mode, the front end now accepts the _Noreturn specifier (which is
similar to the C++11 [[noreturn]] attribute).


1/21/14  [EDGcpfe/14745]
C11: Anonymous unions and anonymous structs

In C11 mode, the front end now accepts anonymous unions and anonymous structs
as specified in the C11 standard.  For example:

  struct S {
    union {
      struct { int i, j; };
      struct { float x, y; };
    };
  } s;
  int printf(char const*, ...);
  int main() {
    printf("%d\n", (char*)&s.j - (char*)&s.y);  // Prints "0" on common
    return 0;                                   // platforms.
  }

Also, the configuration macro ALLOW_NONSTANDARD_ANONYMOUS_UNIONS has been
removed.  The effect is as if the macro had been defined to be TRUE;
configurations that set it to FALSE now elicit a compilation error (to avoid
a silent change).


1/20/14  [EDGcpfe/7317,EDGcpfe/9032,EDGcpfe/9156,EDGcpfe/9684,EDGcpfe/10566,
          EDGcpfe/13920,EDGcpfe/13930]
Destructible entities in GNU statement expressions

In GNU C++ modes, the front end now accepts destructible entities in GNU
statement expressions.  For example:

  struct D { ~D(); };
  int g() {
    return ({ D d; 42; });  // Now accepted in GNU C++ modes.
  }

A remaining limitation is that the result of a GNU statement expression cannot
be of a class type requiring nontrivial copy construction or nontrivial
destruction.  Such cases are now more consistently diagnosed; previously, they
sometimes resulted in an internal error in assign_expr_to_temp during IL
lowering (in lower_il.c).  For example:

  struct D { D(D const&); };
  D g(D d) {
    return ({ d; });  // Previously triggered an internal error when lowered;
  }                   // now an ordinary error because d has a nontrivial copy
                      // constructor.

As a result of these changes, it is now possible for an olk_expr_temporary
lifetime to have an olk_block child lifetime.


1/17/14  [EDGcpfe/14788]
Lambdas and calling conventions

Closure types for lambda expressions that do not capture anything have a static
member function implementing an alternative entry point to the body of the
lambda.  In modes permitting multiple calling conventions (Microsoft mode in
particular) such alternative entry points are generated for every relevant
calling convention, and each entry point is given a different name.
Previously, those names could accidentally include a "new-line" character: This
is now fixed.


1/17/14  [EDGcpfe/14787]
Accessing of members of objects of the class type being defined

The changes for EDGcpfe/11746,EDGcpfe/11557 (entry of 9/14/11) enable accessing
members of *this in member declarations of a class C being defined (i.e., even
though the class is still incomplete).  Other implementations have interpreted
the standard as also allowing member access on other expressions of a class
type that is being defined.  The front end now uses this broader interpretation
in its nonstrict C++11 modes.  For example:

  template<class T> struct S {
    auto f()->int;
    auto g(S &b)->decltype(b.f());  // Previously an error (b has incomplete
  };                                // type); now accepted in nonstrict C++11
                                    // modes.


1/14/14  [EDGcpfe/14784]
Abort on C++11-style GNU attribute applied to invalid entity

In some unusual cases, the front end could abort (in form_type_first_part,
il_to_str.c) while attempting to issue a diagnostic for a C++11-style (i.e.,
doubly bracketed) GNU attribute applied to an invalid entity.  For example:

  struct S {};
  typedef void (S::* [[gnu::const]] PMF)(int, int);
    // Previously triggered an abort in GNU C++11 mode.

This is now fixed.


1/14/14  [EDGcpfe/14783]
Inheriting constructors and exception handling

In modes disabling exception handling, the front end previously aborted with an
internal error in form_exception_specification_for_generated_function when
processing inheriting constructors.  For example:

  struct B { B(int); };
  struct D: B { using B::B; };  // Previously triggered an internal error
                                // if exception handling is disabled.

This is now fixed.


1/13/14  [EDGcpfe/14768]
Overload resolution with narrowing conversions in braced initializers

The front end previously treated a narrowing conversion in a braced initializer
as a reason to discard a candidate during overload resolution.  Now, such
narrowing conversions are only checked (and diagnosed) after overload
resolution has resolved the call.  For example:

  struct S {
    S(int);
    S(...);
  };
  S g() {
    return { 1.2 };
  }                 

Previously the ellipsis constructor was selected because the S(int) candidate
was discarded due to the narrowing conversion.  Now, the S(int) candidate is
selected for the call, and a diagnostic is issued because the call requires a
narrowing conversion.


1/9/14   [EDGcpfe/14635,EDGcpfe/14771]
alignas in local declaration contexts

The front end failed to recognize the keyword "alignas" (see EDGcpfe/8527) as
a possible start of a local declaration, leading to spurious errors.
For example:

  int main() {
    alignas(int) char x[3];  // Previously a spurious error; now accepted.
  }

This is now fixed.


1/9/14   [EDGcpfe/13672,EDGcpfe/14769]
Binding an rvalue reference to a converted lvalue during overload resolution

The changes for EDGcpfe/12427 in response to Core Issue 1138 failed to extend
the ability to bind an rvalue reference to a converted lvalue to overload
resolution contexts.  For example:

  extern "C" int printf(char const*, ...);
  void f(double const&) { printf("lvalue\n"); }
  void f(double&&) { printf("rvalue\n"); }
  int main() {
    int i = 42;
    f(i);  // Previously printed "lvalue"; now prints "rvalue".  (Note the
  }        // type mismatch, which requires an lvalue-to-rvalue conversion.)

This is now fixed.


1/9/14   [EDGcpfe/14765]
Spurious error on designated initializer when lambdas are enabled

In modes in which both designated initializers and lambdas are enabled,
certain designators were incorrectly being parsed as lambdas, resulting in
spurious errors.  Now fixed.

  int x[10] = { [2] = 1 };


1/8/14   [EDGcpfe/14766]
clang compatibility: __has_include_next macro

The front end now supports the __has_include_next macro in clang mode (see
the entry for EDGcpfe/14634).  Its value is 1 if #include_next with the
named header file would succeed and 0 otherwise.  For example:

  // file f.h:
  #if __has_include_next(<f.h>)
  #include_next <f.h>  // will not result in a catastrophic error
  #endif


1/8/14   [EDGcpfe/14763]
Microsoft compatibility: __is_convertible_to and rvalue references

The front end implements nonstandard behavior in Microsoft mode when evaluating
__is_convertible to with one or two operands being rvalue reference types (see
also the entry for EDGcpfe/13642,EDGcpfe/13681 of 5/3/13).  This nonstandard
behavior is now limited to Microsoft modes with microsoft_version < 1800.
For example:

  static_assert(__is_convertible_to(int&&, int&&), "Nonstandard");
    // Succeeds with microsoft_version >= 1800, but fails when
    // microsoft_version < 1800.

In addition, when microsoft_version < 1800, a small change was made to change
the outcome for cases where the first type is an lvalue reference and the
second type is an rvalue reference.  For example:

  static_assert(!__is_convertible_to(int&, int&&), "Nonstandard");
    // Now succeeds in all Microsoft modes.


1/7/14   [EDGcpfe/14756]
C++11: Destructors for return values and decltype

When a function call is the immediate operand of a decltype construct, the
call does not produce a temporary, and therefore an inaccessible or deleted
destructor associated with the return type does not make the call invalid.
This rule is now implemented.  For example:

  struct R { ~R() = delete; };
  R g();
  typedef decltype(g()) TR;  // Previously an error because the destructor
                             // is deleted.  Now accepted in C++11 modes.

This change to the C++ language was introduced by the committee's paper N3276.
(See also the entry for EDGcpfe/11740 and EDGcpfe/14277 of 7/19/13.)


1/6/14   [EDGcpfe/14753]
Microsoft compatibility: Conditional operator with xvalues

In C++11, a conditional operator whose second and third operands are xvalues
of identical types produces an xvalue.  Microsoft compilers do not appear to
implement that standard behavior yet, and the front end now matches those
compilers in Microsoft mode (an rvalue is produced instead).  (GNU mode
already made a similar exception.)  For example:

  struct Z {} v;
  Z&& z() { return static_cast<Z&&>(v); }
  int main() {
    (1 ? z(): z());  // This expression is an xvalue in C++11 mode, but an
  }                  // rvalue in Microsoft and GNU C++ modes.


1/6/14   [EDGcpfe/14731]
C++-generating back end, GNU compatibility: __sync_... and __atomic_... names
and arguments

In configurations in which GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED is TRUE, the
front end transforms a call using a generic builtin function name to the
appropriate concrete version (see the entries of 7/31/07 and 6/26/12), and
the C++-generating back end put out these calls using the transformed name.
This caused problems compiling the generated code because the parameter
types of the generic and concrete versions are different, and the cast
nodes for mapping the arguments to the concrete parameter types are marked
as compiler-generated, suppressing them from the C++-generating back end
output.  The C++-generating back end has now been changed to restore the
original generic name in such function calls, avoiding the
argument/parameter mismatches in the generated code.  For example:

  void *f(void *volatile *x, void *y, void *z) {
    return __sync_val_compare_and_swap(x, y, z);
    // Previously generated as __sync_val_compare_and_swap_4(x, y, z)
  }


1/6/14   [EDGcpfe/14685]
C++14: [[deprecated]]

In C++14 mode, the front end now recognizes the standard-notation attribute
"deprecated", optionally followed by a parenthesized string literal.  Uses of
an entity marked with this attribute are diagnosed with a warning by default.
For example:

  int x [[deprecated("Old!")]];  // This attribute is now recognized in C++14
                                 // mode.
  int y = x+1;                   // A warning is issued for the use of x here.

(Similar attributes with Microsoft- and GNU-like syntax were already supported
by the front end.)


1/3/14   [EDGcpfe/12649,EDGcpfe/12864]
C11: _Static_assert

In C11 mode and in GNU C modes with gnu_version >= 40600, the front end now
supports the _Static_assert feature (equivalent to the C++11 static_assert
feature).  For example:

  _Static_assert(sizeof(char) == 1, "Nonstandard char size");
    // Now accepted in C11 mode.


1/3/14   [EDGcpfe/14762]
C++14 and C11 modes

Command-line options "--c++14" and "--c11" have been added to the front end.
When features of the C++14 or C11 standards are implemented in the front end,
they will be enabled by these options.  Internally, a new global variable
std_version now reflects which C or C++ standard is in effect, and global
variables like cpp11_mode and c99_mode are now macros whose values depend on
the value of std_version.


1/3/14   [EDGcpfe/14482]
Unintended reuse of nonreal instantiations yielding incorrect behavior
with variadic template parameters

The way in which dependent nontype argument expressions were compared
could result in the failure to properly substitute a variadic template
argument.  This could potentially result in a variety of incorrect behavior.
In the example below, this resulted in a failure to use the correct
operator= function.  The problem would arise when a given template was
instantiated on similar dependent nontype expressions that should be
considered distinct because they used different template parameters, but
incorrectly reused a previously created instance (A<sizeof...(U) ==
sizeof...(T)> in the example below).

  template <bool, typename T = void> struct A {};
  template <typename T> struct A<true, T> { typedef T type; };
  template <typename... T> struct B {
    template <typename... U,
              typename = typename A<sizeof...(U) == sizeof...(T)>::type >
    explicit B(U&&...);

    template <typename... U,
              typename = typename A<sizeof...(U) == sizeof...(T)>::type>
    B& operator=(const B<U...>&);
  };
  template <typename... T> B<T&...> g(T&...);
  B<int> f();
  int main() {
    int a;
    g(a) = f();
  }


1/3/14   [EDGcpfe/7498,EDGcpfe/7967,EDGcpfe/13752,EDGcpfe/14758]
Microsoft compatibility: default nontype template arguments not evaluated
unless used

The Microsoft compiler does not evaluate nontype template default
arguments unless they are used.  As a result, the Microsoft compiler
accepts default arguments that are invalid and default arguments that
reference an entity that was declared after the point where the
default argument was specified.  We now emulate this behavior in
Microsoft mode when nonclass prototype instantiations have not been
requested.

  template <int X = Y> class C { };
  C<1> c1;
  const int Y = 2;
  C<>  c2;  // The default argument Y is evaluated at this point


1/2/14   [EDGcpfe/14508]
GNU C++ compatibility: Passing a packed array member to reference to const
(IL CHANGE)

In g++ modes, when passing a field of a packed type to a parameter of
reference to const type, the front end normally copies the field to a
suitably aligned temporary, unless the field is of a non-POD class type (see
the Changes entry for EDGcpfe/8366).  Previously, however, this failed when
the field was an array: A spurious conversion error was issued.  For example:

  void g(const int (&p)[1]);
  struct  __attribute__ ((packed)) Packed {
    char c;
    int i[1];
  };
  Packed p = {0, 1};
  int main () {
    g(p.i);  // Previously an error.  Now accepted.
  }

This is now fixed.  The fix involves slight IL CHANGE: Dynamic init entries
of kind dik_bitwise_copy now sometimes include a pointer to a source
expression (previously, all such entries had an implicit source).

In addition to the fix above, the copy to an aligned temporary is now
inhibited if the destination type is single-byte aligned (the copy is
unneeded in such cases since the member itself is not unaligned).


1/2/14   [EDGcpfe/14634]
Feature-test macros

The feature-test macros from document WG21 SG10 SD-6 have been implemented:
__cpp_aggregate_nsdmi, __cpp_attributes, __cpp_binary_literals,
__cpp_constexpr, __cpp_decltype, __cpp_decltype_auto,
__cpp_generic_lambdas, __cpp_init_captures, __cpp_lambdas,
__cpp_raw_strings, __cpp_return_type_deduction, __cpp_runtime_arrays,
__cpp_rvalue_references, __cpp_static_assert, __cpp_unicode_characters,
__cpp_unicode_literals, __cpp_user_defined_literals,
__cpp_variable_templates, and __cpp_variadic_templates.  These macros have
a non-zero value (indicating the year and month in which the feature was
adopted by the C++ Standard Committee) if the corresponding feature is
enabled in the current execution of the front end.  The __has_include macro
described in that document has also been implemented, having the value 1 if
the named header file is found and 0 otherwise.  These macros are defined
if DEFINE_PORTABLE_FEATURE_TEST_MACROS is set to TRUE (the default value).

As part of this change, a rudimentary clang mode has been added, with
--clang and --clang_version command-line options and corresponding
DEFAULT_CLANG_COMPATIBILITY and DEFAULT_CLANG_VERSION configuration macros.
clang mode is viewed as a dialect of GNU mode, so that --clang, --no_clang,
and --clang_version implicitly set gcc_mode or gpp_mode to TRUE.  Currently
the only effect of setting clang_mode to TRUE is to enable the clang
feature-test macros __has_feature, __has_extension, __has_attribute, and
__has_builtin, as well as the __has_include macro described above.  The
value specified for --clang_version currently has no effect and is ignored.

For example, assuming --clang and a configuration in which
DEFINE_PORTABLE_FEATURE_TEST_MACROS is TRUE:

  // a has value 200410 if static_assert is enabled, 0 otherwise:
  int a
  #ifdef __cpp_static_assert
    = __cpp_static_assert;
  #endif
  ;
  // b has value 1 if rvalue references are enabled, 0 otherwise:
  int b = __has_feature(cxx_rvalue_references);
  // c has value 1 if #include <x.h> will succeed, 0 otherwise:
  int c = __has_include(<x.h>);


1/2/14   [EDGcpfe/14599]
Spurious partial specialization ambiguity when deferring function prototype
instantiations

When the prototype instantiation of functions is deferred until their
first use (i.e., in g++ mode in many configurations) a spurious ambiguity
could result when determining which partial specialization of a class
template is to be used, because partial specializations declared after
the point at which the function template was defined were incorrectly
being considered.  Now fixed.

  template <class T1, class T2> struct A;
  template <class T1, class T2> struct A<T1*,T2> { static int i; };
  template <class T> int f(T) {
    A<int*,int*> a;  // Formerly spurious ambiguity
    return a.i;
  }
  template <class T1, class T2> struct A<T1,T2*> { };
  int main() {
    f(1);
  }


12/23/13 [EDGcpfe/14695]
Assertion failure: make_handle_for_entity: non-simple indirection

In configurations where DO_IL_LOWERING is TRUE but DO_FULL_PORTABLE_EH_LOWERING
is FALSE, the example that follows had resulted in an assertion failure
(make_handle_for_entity: non-simple indirection).  A change has been made in
cases where the RDF_INDIRECT flag is specified in a region description entry;
previously when the RDF_INDIRECT flag was set, the accompanying ck_stack_offset
constant had an offset of zero.  Now it's possible for the offset to be
non-zero.  Strictly speaking, this isn't an IL CHANGE, but back ends should be
prepared for a non-zero offset in this case.  For example (with --c++11):

  template<typename _Tp> struct A {
    A(const A& __a) { }
    ~A() { while(0); }
  };
  struct B {
    A<char> m;
    B(const char* __s);
  };
  struct C {
    B b;
    int x;
  };
  C f() {
    return {"foo", 42};
  }


12/20/13 [EDGcpfe/14751]
Remove unused is_for_init_decl field

The is_for_init_decl field in a_decl_parse_state is unused and has been
removed (the changes for EDGcpfe/12748,EDGcpfe/12805 removed the last use).


12/18/13 [EDGcpfe/13751,EDGcpfe/14719]
Microsoft compatibility: Bitwise copying and __unaligned

The changes for EDGcpfe/9157 included permitting conversions that drop the
__unaligned specifier.  However, the case where the conversion amounts to a
bitwise class copy was accidentally omitted, and still caused spurious errors.
For example:

  struct S { int x; };
  void g(S __unaligned *p) {
    S x = *p;  // Previously an error; now okay.
  }

This is now fixed.


12/18/13 [EDGcpfe/14544]
GNU compatibility: Argument-dependent lookup for block-extern declarations

The C++ standard specifies that argument-dependent lookup is suppressed if
a block-extern declaration is found during normal lookup.  Previously, this
rule was entirely ignored in GNU C++ modes.  Now, rules are more subtle.
Specifically, the standard rule applies for non-operator functions when
gnu_version >= 40500, or in template contexts when gnu_version >= 30400.
For example:

  struct S {} s;
  void g(S const&);
  template<class T> void f1() {
    extern void g(S);
    g(s);  // Ambiguity error when instantiated with gnu_version < 30400.
  }
  void f2() {
    extern void g(S);
    g(s);  // Ambiguity error with gnu_version < 40500.
  }
  int main() {
    f1<void>();
    f2();
  }


12/18/13 [EDGcpfe/14735]
Microsoft compatibility: abort on invalid decltype type in destructor call

An abort could occur (in normal_id_lookup) in Microsoft mode if a destructor
type was specified using decltype, and the type was invalid for the object
being destroyed.  Now fixed.

  struct A {};
  int main() {
    A *p;
    p->~decltype(p)();
  }


12/17/13 [EDGcpfe/14736]
Build failure with ms_metadata.cpp

Some changes to the file ms_metadata.cpp needed for const-correctness
of C++11 string literals (see the entry of 7/19/13 for EDGcpfe/10662) were
inadvertently omitted, resulting in errors when that file was compiled on
Windows platforms.  These changes have now been made.


12/16/13 [EDGcpfe/14733]
GNU and Microsoft compatibility: Empty pack expansions in new-initializers

A case like the following is now accepted in GNU and Microsoft C++11 modes:

  template<int ... I> int* g() {
    return new int(1, I...);  // An empty expansion of I... is now accepted
  }                           // in GNU and Microsoft C++11 modes.
  int main() {
    int *r = g<>();
  }

(In other modes this is an error because the variadic template's only valid
expansion is for an empty argument list.)

Furthermore, in a prototype instantiation performed in Microsoft mode, a
new-initializer like "new int(x, y, z)" is now treated as dependent and
therefore does not elicit an error per se (this was already the case in GNU
C++ modes).


12/13/13 [EDGcpfe/14561]
C++11 range-based "for" statements and variable-length arrays

In GNU C++11 mode the front end supports both range-based "for" statements and
variable-length arrays (VLAs), but a range-based "for" loop applied to a VLA
effectively treated the VLA as a zero-length array.  For example:

  double f(int n) {
    double x[n];
    for (double &d: x) d = 1.0;  // Previously this loop had no effect.
    return x[n-1];
  }

This is now fixed.


12/12/13 [EDGcpfe/14618]
Microsoft compatibility: Declarations after statements in C mode

In Microsoft C mode with microsoft_version >= 1800, declarations can now appear
after statements in the same block.  For example:

  void f(int p) {
    if (p == 0) return;
    int q = p+2;  // Previously an error in Microsoft C modes; now okay if
  }               // microsoft_version >= 1800.


12/12/13 [EDGcpfe/14727]
Microsoft compatibility: Partial ordering of lvalue vs. rvalue references

In Microsoft mode with microsoft_version >= 1800 the standard C++11 rule that
treats an lvalue reference parameter as more specialized than a corresponding
rvalue reference parameter is now applicable.  For example:

  template<typename T> int f(T&);
  template<typename T> int f(T&&);
  int x, y = f(x);  // Previously ambiguous in all Microsoft C++ modes; now
                    // okay (and calls f(T&)) when microsoft_version >= 1800.

See also the entry for EDGcpfe/11270 of 1/14/11.


12/12/13 [EDGcpfe/14413,EDGcpfe/14730]
Spurious error on function template instance passed to T&& parameter

The front end previously failed to deduce a call to a function template with a
parameter of the form T&& (where T is a template parameter) when the
corresponding argument is an instance of a function template.  For example:

  template<typename T> void f(T&&);
  template<typename T> void g();
  void h() {
    f(g<int>);  // Previously triggered a spurious error about there not
  }             // being a matching "f".

This is now fixed.


12/11/13 [EDGcpfe/14721,EDGcpfe/14726]
Memory requirements for very large aggregate initializers

The changes to support initializer lists in version 4.5 of the front end (see
the entry of 8/26/12 for EDGcpfe/9170) caused the front end to record extensive
information for every element in an initializer list at once.  This is needed
when dealing with certain C++11 features (e.g., passing an initializer list as
a function call argument).  However, compared to the prior treatment of
(traditional) initializer lists, it consumes much more front end memory, which
could be problematic for very large initializer lists (e.g., with millions of
elements).  The management of large initializer lists in the front end has
therefore been reworked to reduce memory requirements for large traditional
aggregate initializers to something close to those of version 4.4 of the front
end.

See also the entry for EDGcpfe/14588, which reduces IL memory usage (as opposed
to front end memory consumption) for large initializers in some configurations.


12/10/13 [EDGcpfe/14454]
Overly-aggressive folding of ?: expressions with constant first operand

The front end attempts to fold conditional expressions in which the first
operand is a compile-time constant.  Under some circumstances, the front
end folded such expressions even when the selected operand is not a
constant, making it impossible to recover the original form of the
expression from the IL.  The front end will now fold conditional
expressions only when the selected operand is also a constant, allowing the
original form of the expression to be recorded as the constant's backing
expression.  For example:

  int f() {
    int i = 1;
    int j = 2;
    return true ? i : j;  // Previously folded to an enk_variable node
                          // referencing "i", now not folded
  }


12/10/13 [EDGcpfe/14629]
Spurious error on decltype of parameter in function template declaration

Version 4.8 introduced a regression that resulted in a spurious undefined
identifier error when a function template used a parameter name in
a decltype expression.  Now fixed.

  template <class T> void f(void (*p)(T x, decltype(x()) y)) {}


12/5/13  [EDGcpfe/14724]
GNU C++ compatibility: spurious ambiguity when using variadic functions

A spurious ambiguity could occur in g++ mode with gnu_version >= 40700
when an overload set contained a variadic and a non-variadic function
template.  Now fixed.

  struct A {
    template <typename T> A(T&& seq , void* = 0 ); // #1
    template <typename First, typename ...T> A(First&& first, T&&... t); // #2
  };
  int main() {
    int i;
    A a(i);  // Should call #1
  }


12/5/13  [EDGcpfe/14716]
Microsoft compatibility: Instantiating templates to find candidates

In C++, template classes must sometimes be completed so that candidates for a
function call can be made available (friend declarations and member operator
declarations in particular).  Microsoft compilers, however, do not always do
this.  For example:

  struct I;
  template<class> struct P { I i; };
  template<class T> T& make();
  template<class T> bool g(T const&);
  template<typename T> struct C {
    template<class U> static decltype(g(make<T>())) f();
    static const bool value = sizeof(f<T>());
  };
  template struct C<P<void>>;

Here, resolving the call to g in the decltype expression should normally
trigger the instantiation of P<void> (the type of make<T>()) to allow
argument-dependent lookup (ADL) to find a possible better candidate declared
as a friend in P<void>.  That instantiation would trigger an error because
P<void>::i is declared with an incomplete type I.  Previously, in Microsoft
modes with microsoft_version >= 1600, that error was also issued, but now this
case is accepted in such modes.  (The Microsoft conditions for avoiding the
instantiation are unclear.  The front end avoids it only in decltype arguments
during partial function template instantiations, which matches all the cases
we have encountered thus far.)


12/5/13  [EDGcpfe/14675]
C++-generating back end, GNU C++ compatibility: dependent destructor name

g++ has a bug that causes it to issue a spurious error when the name of a
dependent destructor that is not a member of the current instantiation is
referenced without a template argument list.  (The template argument list
is implicit in the type of the object for which the destructor is being
invoked.)  A change in version 4.8 resulted in the C++-generating back end
omitting this unnecessary template argument list, triggering the g++ bug
when compiling the generated code.  The C++-generating back end has now
been changed to put out the template argument list in such cases when
gcc_is_generated_code_target is TRUE.  For example:

  template<typename T1, typename T2 = int> struct S {
    S<T2> *m;
    ~S() {
      m->~S<T2>();  // Previously generated as "m->~S()"
    }
  };
  S<float, double> v;


12/3/13  [EDGcpfe/14665]
C++-generating back end: parenthesized non-constant array bound in
new-expression

The type in a new-expression can be written in one of two forms, either
parenthesized or unparenthesized.  The form without parentheses allows the
major bound in an array type to be non-constant; however, the type in
parentheses is a type-id, in which all array bounds must be constant.  The
C++-generating back end previously put out some array types with
non-constant array bounds using the parenthesized form.  This is now fixed.
For example:

  extern unsigned i;
  const int *p = new const int[i]();  // Previously put out as
                                      // "new (const int [i])()"


12/3/13  [EDGcpfe/14707]
Cached noexcept specifiers

A noexcept specifier of a member of a class template instance isn't parsed
until the member is used in some way.  While it isn't parsed, a flag named
"arg_cached" is TRUE in the IL entry representing the noexcept specifier.
Previously, il_def.h erroneously indicated that this flag could only
temporarily be TRUE, when in fact it may remain TRUE for a member that is
never used.  That is now fixed.  Furthermore, the front end did not always
"instantiate" a cached noexcept specifier when the associated member was
used.  For example:

  template<class T> struct S {
    void f() noexcept(true);
  };
  void g() {
    S<int> x;
    x.f();  // Previously this did not trigger the parsing of the noexcept
  }         // argument of S<int>::f; now it does.

That is now fixed too.


12/2/13  [EDGcpfe/14717]
Microsoft compatibility: __is_pod

Previously, the front end always produced a false value for __is_pod applied
to non-class types in Microsoft modes.  Now, this behavior is restricted to
Microsoft modes with microsoft_version < 1800.  For example:

  static_assert(__is_pod(int), "Surprising");
    // This assertion now succeeds in Microsoft mode with
    // microsoft_version == 1800.


11/27/13 [EDGcpfe/14664,EDGcpfe/14712]
GNU compatibility: spurious error with asm registers with leading %l

As a result of the changes for asm goto (EDGcpfe/12441, et al.), a register
whose name begins with the string "%l" had caused spurious errors when used
in the first argument to an asm declaration.  That has now been fixed.  For
example (with --gcc --gnu_version 40500):

  void f(int x) {
    asm volatile("op %0, %%lreg;" : "=r"(x));
  }


11/27/13 [EDGcpfe/14710]
Spurious "circular dependency" error on some class templates

In some cases, the front end issued a spurious "circular dependency" error
on class templates with a defaulted default constructor and a nonstatic data
member initializer.  For example:

  template<typename T>
  struct S {
    S() = default;
    int i = 0;
  };
  S<int> bar;  // Default constructor generation previously triggered 
               // spurious error.

This is now fixed.


11/26/13 [EDGcpfe/14711]
Deleted member function causes error rather than deduction failure (SFINAE)

A call of a non-overloaded deleted member function in a SFINAE context often
erroneously triggered an immediate error rather than just disqualifying the
candidate template associated with the SFINAE context.  For example:

  template <class U> struct DT{ U u; };
  template <class> char dt(...);                                       // (1)
  template <class T, class = decltype(DT<T>().~DT<T>())> int dt(int);  // (2)
  struct DD { ~DD() = delete; };
  static_assert(sizeof(dt<DD>(0)) == 1, "Unexpected");

Here, in the call of dt<DD>, candidate (2) should be disqualified because the
call to the destructor in the default template argument is invalid (since that
destructor is deleted), and candidate (1) should be selected instead.
However, the front end erroneously reported an error for the attempted use of
the deleted destructor.  This is now fixed.


11/26/13 [EDGcpfe/14645]
Invalid character in raw string delimiter in unselected #if branch

According to the C++11 Standard, the unselected branch of a #if consists of
preprocessing tokens, and a character sequence beginning with the two
characters 'R"' "shall be" a valid raw string literal preprocessing token;
this "shall be" formulation requires a diagnostic for a violation of the
rule.  Nevertheless, it is a common expectation that any text whatsoever
can appear in the unselected branch of a #if without eliciting error
messages.  The front end has now been changed to put out a remark instead
of a discretionary error for an invalid character in the delimiter portion
of a putative raw string literal that appears in the unselected branch of a
#if.  For example:

  #if 0
  const char *p = R"@(xyz)@";  // Previously a discretionary error, now a
                               // remark
  #endif


11/26/13 [EDGcpfe/14709]
Microsoft-mode abort in is_special_rvalue_ref_generic_parameter_at_pos

The changes for EDGcpfe/14129 introduced a regression that caused the front
end to abort in is_special_rvalue_ref_generic_parameter_at_pos with certain
non-top-level function declarators in Microsoft-mode templates (requires
support for rvalue references; e.g., with microsoft_version >= 1600).
For example:

  template<typename T> void (*f()) (int);  // Return type uses a function
                                           // declarator.
  void (*pf)(int) =  f<void>();            // Previously triggered an
                                           // internal error.

This is now fixed.


11/26/13 [EDGcpfe/14708]
Microsoft compatibility: Binding an rvalue reference to a converted lvalue

The changes for EDGcpfe/14284 enabled some standard C++11 behavior with
respect to binding a rvalue reference to a converted lvalue in Microsoft C++
modes with microsoft_version >= 1800.  This is now instead done when
microsoft_version >= 1700.  For example:

  struct S { S(int const&); };
  void f(S&&) {}
  void g(int x) {
    f(x);  // Now accepted in Microsoft C++ mode with
  }        // microsoft_version >= 1700 (previously required
           // microsoft_version >= 1800).


11/25/13 [EDGcpfe/14559]
C++-generating back end, Microsoft compatibility: parenthesized function
declarator with explicit calling convention

A change in version 4.6 corrected the erroneous omission of parentheses
needed to separate a globally-qualified function declarator from its return
type in the output of the C++-generating back end (see the entry for
EDGcpfe/13478).  However, these parentheses are not needed when the
declarator is separated from the return type by a specifier for the
function's calling convention, and, in fact, the Microsoft compiler issues
an error for a parenthesized declarator following a calling convention
specifier.  The C++-generating back end has now been changed to suppress
the unneeded parentheses in this case.  For example:

  int __stdcall f();
  struct S {
    friend int __stdcall ::f();  // Previously generated as
                                 // "friend int __stdcall (::f)()"
  };


11/25/13 [EDGcpfe/14611,EDGcpfe/14692]
Missing information about the original form of case label constants

When the type of the constant given in a case label is different from the
promoted type of the expression in the switch statement, the a_constant IL
entry designated by the case_value field of the corresponding
a_switch_case_entry struct should have a backing expression: an eok_cast
node converting the case label constant to the required type, allowing the
original constant to be identified.  Because of a change in version 4.6,
this backing expression was missing in Microsoft mode.  This is now fixed.
For example:

  enum E { e0 };
  void foo(unsigned char c) {
    switch (c) {
      case e0:   // Now has a backing expression in Microsoft mode
        break;
      case 5u:   // Now has a backing expression in Microsoft mode
        break;
    }
  }


11/22/13 [EDGcpfe/8542,EDGcpfe/14697]
Static initialization with address constants

The front end now diagnoses as an error an attempt to statically initialize
with an address constant a variable of field whose size is different from the
address type.  In the case of bit fields, the field's width is taken into
account.  For example:

  typedef __EDG_PTRDIFF_TYPE__ Int;
  int x;
  struct S { Int bits: 10; } s = { (Int)&x };
    // Now an error in C modes.


11/20/13 [EDGcpfe/14684]
Nonstandard anonymous unions and command-line options

In configurations with ALLOW_NONSTANDARD_ANONYMOUS_UNIONS set to TRUE, the
front end may accept certain extensions to standard anonymous unions (see the
entry of 9/1/94).  Previously, this extension was accepted in GNU and Microsoft
modes, but if the macro DEFAULT_ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE,
they were also accepted in all other modes, including strict C and C++ modes.

Now, nonstandard anonymous unions are disabled in strict modes by default even
when the macro DEFAULT_ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE.
Furthermore, a new command-line option --[no_]nonstd_anonymous_unions can now
override the default behavior of any mode.


11/20/13 [EDGcpfe/14186]
Internal error on use of explicitly specialized scoped enumeration

An internal error could occur (in instantiate_template_enum) on the use
of an explicitly specialized scoped enumeration.  Now fixed.

  template <class T> struct A {
    enum class B : T;
  };
  template <> enum class A<int>::B : int { e0, e1 };
  int main() {
    return (int)A<int>::B::e1;
  }


11/20/13 [EDGcpfe/14589]
Copy/move behavior in GNU C++11 4.6.x mode

When emulating GNU C++11 4.6.x (gnu_version >= 40600 but < 40700) the front end
does not generate a deleted copy constructor or copy assignment operator in
the presence of a user-declared move constructor or move assignment operator
(as the C++11 standard required).  Instead, no copy constructor or copy
assignment operator is generated at all in such cases.  However, if the user-
declared move constructor or move assignment operator was defaulted, the front
end sometimes erroneously recorded the class as bitwise copyable, which could
lead to odd errors later on.  For example:

  struct M { M(); M(M&&); };  // Move-only type.
  struct B {
  protected:
    B(B&&) = default;  // In GNU C++11 4.6.x mode, no copy constructor is
  };                   // generated at all.
  struct D : B {
    M m;
  };
  D f(), d(f());  // Requires the definition of the implicit move constructor
                  // of D.  Previously this implicit definition triggered a
                  // spurious error for the protected move constructor of B.

This is now fixed.


11/20/13 [EDGcpfe/14643,EDGcpfe/14646,EDGcpfe/14688]
GNU compatibility: __builtin_ia32_pshufw and __builtin_ia32_vec_ext_v8hi

The recently added builtins __builtin_ia32_pshufw and
__builtin_ia32_vec_ext_v8hi (see EDGcpfe/14528,EDGcpfe/14557) had incorrect
function signatures which have now been corrected.


11/20/13 [EDGcpfe/14682]
Definition of "standard layout"

The __is_standard_layout type trait helper produces "true" for types that are
scalar types or "standard layout class types".  The latter is a term from the
C++11 standard that turns out to be open to interpretation for some classes
that have a direct base class that is itself derived from a nonempty base.
The front end's behavior has now been changed to match that of the GCC compiler
(which is expected to be the interpretation that will be selected when the C++
standards committee resolves this open issue).  For example:

  struct B { int i; };
  struct C: B {};
  struct D: C {};
  static_assert(__is_standard_layout(D), "?");
    // Previously, this static assertion failed.  Now it succeeds.


11/20/13 [EDGcpfe/14693]
Abort during call to reference_to_implicitly_invoked_function in complex
template code

In complex template code, version 4.8 of the front end sometimes aborted with
an internal error in reference_to_implicitly_invoked_function (symbol_ref.c)
called from select_destructor_full (symbol_tbl.c).  This regression (introduced
by the changes for EDGcpfe/10610) is now fixed.


11/20/13 [EDGcpfe/13676]
Microsoft compatibility: resolution of ambiguous qualifier in a class member
access

The C++98/C++03 standards specify that a name followed by :: in a class
member access is looked up in both the class of the member access and in
in the current context, and if it is found in both places the program
is ill-formed.  The Microsoft compiler silently uses the entity found
in the class of the member access.  We now emulate this behavior in
Microsoft mode.  Formerly, we resolved the ambiguity by issuing a
warning and using the entity found in the current context, resulting
in an error on the example below.

  struct A {
    friend struct B;
    void f();
    typedef A some_type;
  };
  struct C {};
  struct B {
    A *ap;
    typedef C some_type;
    void f() {
      ap->some_type::f();  // Now accepted
    }
  };


11/19/13 [EDGcpfe/14127]
Spurious error on calls to implicitly-declared trivial destructor

The front end previously issued a spurious error on a call with an implied 
"this->" to an implicitly-declared trivial destructor.  For example:

  struct S { void d(); };
  void S::d() {
    this->S::~S();  // Always okay.
    S::~S();        // Previously a spurious error; now accepted.
  }

This is now fixed.


11/19/13 [EDGcpfe/14678]
C++-generating back end: regression generating explicit invocation of
dependent destructor

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, a change
in version 4.8 inadvertently caused the C++-generating back end to generate
incorrect code for an explicit call of a dependent destructor named using a
typedef.  This is now fixed.  For example:

  template<typename T> struct A {
    typedef T type;
  };
  template<typename T> struct B {
    typedef typename A<T>::type type;
    void f(type *p) {
      p->~type();   // Previously generated as "p->~typename A<T>::type()"
    }
  };


11/19/13 [EDGcpfe/14689]
Remove use of "thread_local" as an identifier

The "thread_local" field in a_variable has been renamed to avoid conflicting
with the C++11 "thread_local" keyword.


11/18/13 [EDGcpfe/14670]
Lowering of expressions with tk_imaginary type (IL CHANGE)

When LOWER_COMPLEX is TRUE, the types of imaginary expressions are lowered
to a typedef for the appropriate floating-point type, but the type_kind field
associated with the lowered expressions had remained tk_imaginary (see
EDGcpfe/9097).  A change has been made to lower the type_kind to tk_float.
For example (with --c99):

  _Complex float f(float r, float i) {
    return r + (i * __I__);
  }


11/18/13 [EDGcpfe/14681]
C++-generating back end: private typedefs in template arguments

In cases in which a publicly-accessible typedef refers to an inaccessible
typedef and the public typedef is used as a template argument, the
C++-generating back end sometimes generated the template argument using
inaccessible names.  This is now fixed.  For example:

  template<typename T> struct A { };
  template<typename T> class B {
    static T* f(T*);
    typedef decltype(f((T*)0)) P0;
    typedef P0 P1;
  public:
    typedef P1 P2;
  };
  struct C {
    struct D { };
    typedef B<D>::P2 P3;
    typedef A<P3> AP3;    // Previously generated as
                          // A<decltype(B<D>::f(D*)0)>, now as A<B<D>::P2>
  };


11/18/13 [EDGcpfe/14674]
Spurious error on uninitialized subobject in GNU SFINAE context

In GNU C++11 mode the front end sometimes issued an error in SFINAE contexts
(where errors are normally not emitted) for expressions requiring the default-
initialization of a class with a const member or a reference member.
For example:

  struct S { int const N; };
  template<typename T> struct Test {
    template<unsigned long> struct Val2Type {};
    typedef char YesType;
    typedef char (&NoType)[2];
    template<typename U> static YesType test(Val2Type<sizeof(new U)>*); // (1)
    template<typename U> static NoType test(...);                       // (2)
    static bool const value = (sizeof(test<T>(0)) == sizeof(YesType));
  };
  int r = Test<S>::value;

Previously, the tentative deduction of (1) for the call to Test<S>::test
triggered an error in GNU C++11 mode, when instead that candidate should just
silently be ignored and (2) be selected instead.  This is now fixed.


11/18/13 [EDGcpfe/13075,EDGcpfe/14641]
GNU C++ compatibility: treat "<" as start of template argument list in
typename contexts

Some of the g++ 4.8 headers contain code similar to the example below
in which a "template" keyword is missing before B<U> in the alias
template declaration.  We now accept this in g++ mode.

  template<typename T> struct A {
    template<typename U> class B {};
  };
  template<typename T> struct A<T*> {
    template<typename U> using my_B = typename A<T>::B<U>;
  };


11/17/13 [EDGcpfe/14683]
Microsoft compatibility: regression on template friend function declarations

Version 4.7 fixed a problem with template friend declarations in nonreal
classes used as base classes in Microsoft mode.  That change introduced
a regression when there were multiple friend function template declarations
with the same name.

  template <typename T> class A {
    template <typename U> friend void f(U);
    template <typename U> friend void f(U*);
  };
  template <typename T> class B : public A<T> {};


11/17/13 [EDGcpfe/14683]
Microsoft compatibility: regression on using-declaration in Microsoft nonreal
class

Version 4.5 introduced a change that caused certain nonreal classes
used as base classes to have actual instantiations done on them
in Microsoft mode.  This could result in spurious "has already been
declared" errors in Microsoft mode when a class instantiated in that
way contained a using-declaration of an implicitly declared operator=.
Now fixed.

  template <typename T> class A;
  template <typename T> class B : public A<T> {
    typedef A<T> Base;
    using Base::operator =;
  };
  template <typename T> class C : public B<T> { };


11/15/13 [EDGcpfe/14569]
GNU mode implicit routine aliasing

In GNU C mode, the front end sometimes implicitly aliases functions that match
standard C library functions to their __builtin_... counterparts (see the
entries for EDGcpfe/10179, EDGcpfe/10328, and EDGcpfe/14348).  This implicit
aliasing is now also recorded in GNU C++ modes.  For example:

  extern "C" int abs(int);  // Now an implicit alias for __builtin_abs

Previously, calls to such aliases were folded by the front end and could
appear in constant-expression contexts.  This is not the case in GNU C++ mode,
and is also no longer the case in GNU C mode with gnu_version >= 40500.
For example, with the declaration above:

  double z[abs(-3)];  // Now only accepted in GNU C mode with
                      // gnu_version < 40500.


11/15/13 [EDGcpfe/7624,EDGcpfe/13759,EDGcpfe/14520,EDGcpfe/14497]
Lookup should include dependent base classes in specializations of templates

As clarified by core issue 544, in an explicit specialization, lookup
should include dependent base classes.  This is now implemented for
full specializations.  It is not yet implemented for specializations
of member templates.

  template <class C> struct A : public C {
    int f();
  };
  struct D {
    int i;
  };
  template <> int A<D>::f() {
    return i;
  }


11/15/13 [EDGcpfe/14580]
GNU compatibility: __builtin_shuffle

In GNU modes with gnu_version >= 40800 (>= 40700 in GNU C mode) the front end
now supports the __builtin_shuffle vector operator.  Although this operator
looks like a call to a predeclared function when used, it is implemented with
a keyword "__builtin_shuffle" (and is therefore potentially available even
when GNU_BUILTIN_IA32_VECTOR_FUNCTIONS_ALLOWED is FALSE).  For example:

  typedef __attribute((vector_size(16))) int V4;
  V4 do_shuffle(V4 x, V4 permutation) {
    return __builtin_shuffle(x, permutation);
  }


11/13/13 [EDGcpfe/14580]
GNU compatibility: Subscripting vectors

In GNU modes with gnu_version >= 40600, the front end now accepts expressions
using the subscript notation on GNU vectors.  For example:

  typedef __attribute((vector_size(16))) int V4I;
  int g() {
    V4I v = { 1, 2, 3, 4 };
    return v[2];  // Now accepted in some GNU modes.
  }

This new subscripting operation is represented using a distinct (and new)
operation code eok_vector_subscript.


11/13/13 [EDGcpfe/14637]
Too-strict checking of default argument of function templates in some modes

The changes for EDGcpfe/13741 (see entry of 3/13/13) caused the front end to
perform a "prototype instantiation" of default function call arguments for
some cases where that was previously not done.  This generic instantiation
could then lead to errors that might otherwise not have been reported.
For example, consider:

  struct S {
    template<typename T1, typename T2>
      static void g(T1 &x, T2 & = x.f());
  };

This example was accepted in all Microsoft modes prior to the changes for
EDGcpfe/13741, but after those changes (i.e., in version 4.8) an error was
issued when C++11 mode is also enabled or when microsoft_version >= 1800.
This is now accepted again because the prototype instantiation of the default
argument is no longer done in those modes.  The cases of EDGcpfe/13741 are
also still accepted, albeit using a different mechanism.


11/12/13 [EDGcpfe/14610]
Abort with opaque enum template with --microsoft_version=1300

An abort could occur (in enum_template_declaration) on the declaration of a
specialization of an opaque enumeration of a class template when C++11 mode
is combined with Microsoft mode and microsoft_version < 1400.  Now fixed.

  template <class T> struct A {
    enum class S : T;
  };
  template <> enum class A<int>::S : int { sint };


11/12/13 [EDGcpfe/14651]
__is_empty and union types

In non-Microsoft modes, the type traits helper __is_empty now returns a false
value when its operand is a union type.  This matches the description of the
C++11 std::is_empty template.


11/12/13 [EDGcpfe/14650]
__is_pod and void types

The type traits helper __is_pod now returns a false value when its operand is
a (possibly qualified) void type.


11/11/13 [EDGcpfe/14632]
User-defined conversions to enum types in conditional operators

Consider:

  enum class E { e };
  struct S1 { operator E(); };
  struct S2 { operator E(); };
  E g(bool b, S1 s1, S2 s2) {
    return b ? s1 : s2;  // Now okay.  (Previously a spurious error.)
  }

Previously, the front end issued a spurious error about s1 and s2 being
incompatible as operands for the conditional operator.  The C++11 standard,
however, indicates that in a conditional operator the second and third
operand could potentially be converted to a common scoped enumeration type,
and since that conversion is not ambiguous in this example, the case is valid.
The front end now correctly accepts such cases.

If the scoped enum type is replaced by an unscoped enum type, the outcome is
very different:

  enum E { e };
  struct S1 { operator E(); };
  struct S2 { operator E(); };
  E g(bool b, S1 s1, S2 s2) {
    return b ? s1 : s2;  // Now an error.  (Previously erroneously accepted.)
  }

Previously, the front accepted this case.  However, the standard indicates
that the common type for the second and third operand of the conditional
operator should be derived from the promoted type of the unscoped enum type
(which is int, in this case).  The expression b ? s1 : s2 therefore has type
int, and that is not implicitly convertible to the return type E.  The front
end now correctly diagnoses such cases.


11/11/13 [EDGcpfe/13138]
Additional change to GNU-compatible overload resolution tie-breaker

In GNU C++ mode, when overload resolution would normally conclude with an
ambiguity, the front end often considers the additional tie-breaking rule that
the candidate with the best "worst conversion on an argument" is preferred (if
indeed one viable candidate stands out in this way): See the Changes entry of
7/20/04.  Previously, however, that rule was always limited to cases where the
resulting candidate was a built-in operator (see the entry of 4/5/05).  Now,
the latter condition only applies when gnu_version < 40000.  Since the
tie-breaker in general does not apply when emulating GCC versions 4.0.x
through 4.3.x (see the entry of 9/13/13), this effectively means that for
gnu_version >= 40400, the tie-breaker rule now applies even when the resulting
selected candidate is not a built-in operator.  For example:

  struct S {
    S();
    operator char*() const;
    int operator!=(char const*);
  };
  int r = S() != (char*)0;  // Now accepted in GNU C++ mode with
                            // gnu_version >= 40400.


11/9/13  [EDGcpfe/14532,EDGcpfe/14578]
GNU and Microsoft compatibility: reinterpret_cast in constant expressions

The reinterpret_cast operator (including C-style and function-style casts
with reinterpret_cast semantics) is not allowed in a constant expression by
the C++11 Standard.  MSVC and, beginning with version 4.6, g++ do not
enforce this restriction, however, so the front end's Microsoft and g++
modes have been changed accordingly.  For example:

  struct S {
    int m;
  };
  // The following is now accepted with --g++ --gnu_version=40600 --c++11:
  static_assert(&reinterpret_cast<char&>(((S *)0)->m) == 0, "error");


11/8/13  [EDGcpfe/14636]
Spurious error on duplicate using-declarations for class or enum name

The front previously rejected duplicate using-declarations in local scopes for
equivalent types (specifically, when it was for a class or enum type).  For
example:

  namespace N { struct S {}; }
  void g() {
    using N::S;
    using N::S;  // Previously triggered an error; now accepted.
  }

Such cases are now accepted, and so are similar cases involving using-
declarations for class templates.  (It is not actually entirely clear that
such duplicate local using-declarations are valid C++, but existing practice
is to accept them and the front end now does also.  This is also the C++
standards committee's Core issue 36.)


11/8/13  [EDGcpfe/14661]
Abort or incorrect result with invalid decltype in template argument

In some unusual cases, processing a decltype construct in a template deduction
context was erroneously handled if the decltype operand was invalid due to the
use of a deleted special member function.  For example:

  template<typename T, typename = decltype(T{})> char f(int);
  template<typename T>                           long f(...);
  struct S { S() = delete; };
  static_assert(sizeof(f<S[1]>(0)) != 1, "Unexpected!");

Assuming sizeof(long)>1, the static_assert should succeed because deduction
for the first template should fail for T == S since T{} is invalid due to the
deleted default constructor.  Prior to the changes for EDGcpfe/14222, the
front end would instead select that first template, and the static_assert
construct would fail.  After the changes for EDGcpfe/14222 (i.e., in version
4.8), the front end instead aborted with an internal error.  This is now
fixed.


11/8/13  [EDGcpfe/13873,EDGcpfe/13958,EDGcpfe/14067,EDGcpfe/14272,
          EDGcpfe/14446,EDGcpfe/14496]
GNU C++ compatibility: regression on use of injected class name

A change made in 4.7 caused regressions in g++ mode when gnu_version < 40500
for certain uses of the injected class name of class templates (see entry
for EDGcpfe/13446 on 12/3/12).  This change has been backed out until
a solution can be found that does not have adverse consequences.

  template <typename T> struct X {
    X();
  };
  int main() {
    // Incorrectly rejected as a result of EDGcpfe/13446
    X<int> x = X<int>::X();
  }


11/8/13  [EDGcpfe/14336,EDGcpfe/14414,EDGcpfe/14631,EDGcpfe/14649]
Overload resolution when binding a function lvalue to an rvalue reference

Previously, the front end preferred binding an rvalue reference to a function
lvalue over binding an lvalue reference to that function lvalue.  Now it is
the other way around (as required by the C++11 standard).  For example:

  int g(void (&&)());  // (1)
  int g(void (&)());   // (2)
  void x() {}
  int z = g(x);  // Previously select (1); now selects (2).

(This matches the C++ standards committee's Core issue 1238.)


11/8/13  [EDGcpfe/14565]
constexpr applied to array of dependent type

The front end had emitted a spurious error when the constexpr keyword is
applied to a variable whose type is an array of template-dependent elements.
For example (with --c++11):

  template <class T> struct A {
    static void f() {
      constexpr T x[] = { 0 };
    }
  };
  void f() {
    A<int>::f();
  }


11/7/13  [EDGcpfe/14652]
Assertion failure on raw string literal with null character in delimiter

A null character (zero byte) appearing in the delimiter portion of a raw
string literal is an error.  The front end previously did not recover
gracefully from this error, however; it issued two diagnostics for the null
character and then aborted with an assertion failure in
conv_string_literal.  This is now fixed.  For example, with "^@"
representing a null character:

  const char *p=R"^@(x)^@";  // Previously aborted, now issues a single
                             // diagnostic


11/6/13  [EDGcpfe/14648]
upc_block_size moved from a_type to a_typeref_type_supplement (IL CHANGE)

The upc_block_size field of the typeref variant in a_type entries (defined
when UPC_EXTENSIONS_ALLOWED is TRUE) has been moved to the
a_typeref_type_supplement structure.  This potentially reduces the size of
a_type entries.


11/6/13  [EDGcpfe/14647]
GNU compatibility: Less checking of functional notation casts in templates

In GNU C++ mode, the front end now relaxes checking of functional notation
casts appearing in template contexts.  For example:

  struct S { S(); };
  template<class T> S g() {
    return S(3);  // Normally an error when the template is parsed, but
  }               // now only an error in GNU C++ mode if the template is
                  // instantiated.


11/6/13  [EDGcpfe/14638]
GNU compatibility: Less checking of default arguments in templates

In GNU C++ mode, the front end no longer attempts to bind default function
call arguments to their corresponding parameter in templates.  This inhibits
certain (justified) errors that are otherwise emitted.  For example:

  template<class T> void g(int & = 1);
    // Previously an error in GNU modes that parse default arguments of
    // templates; now accepted in those modes.

(Note that such cases were already accepted in modes that don't parse default
arguments of templates in their generic form.)


11/5/13  [EDGcpfe/14639]
Abort on binding a compound literal to a reference in some C++ modes

In C++ modes that accept compound literals but not constexpr functions (e.g.,
GNU C++03 mode) the front end sometimes aborted with an internal error in
take_reference_to_operand (in exprutil.c) when attempting to bind a compound
literal to a reference.  For example:

  struct S {};
  struct R { R(S const&); };
  R sa[] = { (S){} };  // Previously triggered an internal error while
                       // binding "(S){}" to the reference parameter of
                       // R::R(S const&).

This is now fixed.


11/5/13  [EDGcpfe/14640]
Warnings when building the front end on 64-bit Windows

Several of the changes for version 4.8 resulted in warnings when building
the front end on a 64-bit Windows platform.  These warnings have now been
eliminated.


11/5/13  [EDGcpfe/13735]
Instantiation errors during the generation of special members

When generating the declarations of special member functions of a class (e.g.,
copy constructors or copy assignment operators) the front end may trigger
instantiation errors even if the special member isn't used.  In particular,
the corresponding special members of subobjects are examined to
  - determine the exception specification of the newly generated member, and
  - determine if the newly generated member should be "deleted" (or, in some
    Microsoft modes, inhibited altogether).
This examination may trigger the instantiation of member templates, which in
turn can lead to instantiation errors.  For example:

  template<typename T> struct E { typedef typename T::error type; };
  struct A {
    A& operator=(const A&);
    template <class U> typename E<U>::type operator=(U&);
  };
  struct B : A { };

Previously, in GNU C++ mode, the front end instantiated E<A> while doing
overload resolution on A::operator= to determine the exception specification
for the generated copy assignment operator of B.  That in turn triggered an
error because A::error does not exist.  In other modes, overload resolution
on A::operator= was needed to determine if the generate copy assignment
operator of B is implicitly "deleted".  However, these errors are not always
triggered by GNU and Microsoft compilers.  To more closely match these
compilers' behavior, two changes have been made.

First, in nonstrict C++ modes, the front end now delays the generation of
exception specifications for generated special member functions until the
exception specification is needed (if at all).  A special member function
with an indeterminate exception specification has an exception specification
with the flag "indeterminate" set to TRUE (this mechanism was already used for
certain generated default constructors in the presence of field initializers).
Delaying the generation of exception specifications in this way avoids
triggering instantiation errors in some cases.

Second, when selecting an overloaded copy/move assignment operator, member
operator templates are sometimes discarded early (i.e., without instantiating
them) if it can be determined that a nontemplate candidate is an obviously
better match.


11/5/13  [EDGcpfe/14603]
Ignored carriage returns in raw string literals

According to the C++ Standard, environment-specific line terminations are
mapped to single newline characters in translation phase 1.  On a system
like Windows, where the line termination is typically a carriage return
followed by a linefeed (CRLF), the front end implements this transformation
by dropping CRs when configured with IGNORE_CARRIAGE_RETURN_IN_SOURCE set
to TRUE.  In general, the source transformations applied in translation
phases 1 and 2, including line splices and translation of trigraphs, are
reverted inside raw string literals.  However, the 2011 C++ Standard is not
clear whether that reversion also applies to line terminations.

The initial implementation of raw string literals in the front end in
version 4.7 reverted the transformation of line terminations inside raw
string literals, preserving CRLFs, on the assumption that one use of raw
string literals could be to wrap arbitrary binary data; in that usage
scenario, replacing CRLFs with newlines would corrupt the data.  However,
we also opened core language issue 1655 to clarify the intent of the
Standard on this point, and the Committee has now determined that line
terminations are to be represented as newlines within raw string literals.
The front end has now been changed accordingly.  For example:

  const char *p = R"(
  )";   // Previously equivalent to "\r\n" on Windows, now "\n"


11/4/13  [EDGcpfe/14620]
GNU asm input operand transformations

Previously, the IL for GNU asm input-only operands did not reflect implicit
array-to-pointer and function-to-pointer conversions.  Now it does.
For example:

  struct S { int x[5]; };
  void g(struct S *p) {
    asm("" : : "r"(p->x));  // Previously, p->x had type "array of 5 int"
  }                         // in this context; now it is "pointer to int".


11/4/13  [EDGcpfe/14619]
Spurious "invalid token" diagnostic concatenating prefix with string

The front end sometimes issued an incorrect diagnostic stating that a
concatenation in a macro expansion does not create a valid token when a
string prefix is concatenated with a string literal.  This is now fixed.
For example:

  #define M(pfx, str) pfx ## str
  wchar_t *p = M(L, "x");  // Sometimes caused a spurious diagnostic


11/2/13  [EDGcpfe/14474]
GNU C++ compatibility: qualified friend class template regression

A change made in version 4.8 (see EDGcpfe/13855 on 8/1/13) could result
in spurious errors on a qualified friend class template declaration in
g++ mode.  Now fixed.

  template <class T> struct A {
    template <class U> class B;
    template <class V> template <class U> friend class A<V>::B; 
  };
  template <class V> template <class U> class A<V>::B {}; 
  int main() {
    A<int>::B<short>  ab;
  }


11/1/13  [EDGcpfe/14628]
Preserving lvalue-ness on same-type casts

When casting an lvalue to the type of that lvalue, the result is normally an
rvalue of that type.  In Microsoft modes, however, the lvalue-ness is
preserved.  In Sun C++ mode, the lvalue-ness was previously preserved only if
the "static_cast" form was used, but now it is preserved with C-style casts
and functional notation casts as well.  For example:

  int* void g(int *p) {
    return &(int)(*p);  // Accepted in Microsoft and Sun modes.
  }

Furthermore, this feature is now controlled by a separate global variable
(preserve_lvalues_with_same_type_casts) that can be controlled by the new
command line option "--[no_]preserve_lvalues_with_same_type_casts".
So with "--microsoft --no_preserve_lvalues_with_same_type_casts" the front
end now rejects the example above (a similar effect to the command-line
option "/Zc:rvalueCast" provided by very recent Microsoft compilers, but the
Microsoft option only applies to its C++ mode).


11/1/13  [EDGcpfe/14607]
Microsoft mode unbounded recursion on elided copy constructor

The changes for EDGcpfe/14150 introduced a regression in Microsoft bugs mode
that caused the front to abort due to unbounded recursion in some cases
involving an elided copy constructor and classes that convert to each other.
For example:

  struct A;
  struct B {
    B(A const&);
    B(B&);
  };
  struct A {
    A(B);
  };
  B f();
  B g() {
    return f();  // Triggered unbounded recursion (and eventual abort) in
  }              // Microsoft bugs mode.

This is now fixed.  (See also EDGcpfe/10058, which addressed this same issue
in all C++ modes.)


10/31/13 [EDGcpfe/14624]
C++-generating back end: omitted qualification of names in type template
arguments

In some cases, the front end failed to use a qualified name in a type
template argument, even though the reference appears in a context in which
the name is not visible and thus requires qualification.  This is now
fixed.  For example:

  template<typename T> struct X { };
  template<typename T> struct A {
    static T* f(T*);
    typedef X<decltype(f((T*)0))> xcp;
  };
  struct S {
    struct I { };
    typedef X<decltype(A<I>::f((I*)0))> xcp; // Previously generated as
                                             // "f((I*)0)", omitting "A<I>::"
  };


10/29/13 [EDGcpfe/14621]
Microsoft compatibility: token concatenation with signed integers

According to the C and C++ Standards, a signed numeric literal is two
tokens, the sign and the numeric literal, and not a single token.  This
distinction comes into play when a signed numeric literal is the right
operand of the ## concatenation operator: only the sign character is
concatenated with the last token of the left operand, and the numeric
literal remains a separate token.  The Microsoft preprocessor does not obey
this rule, however, allowing a valid floating-point literal to be formed by
concatenating a signed integer literal as the exponent portion.  The front
end now emulates this nonstandard behavior in microsoft_bugs mode.  For
example:

  #define M(n) 1e##n
  double d = M(-1);   // Now accepted in microsoft_bugs mode


10/29/13 [EDGcpfe/14612]
Spurious error on union member when near/far qualifiers are enabled

Version 4.8 of the front end introduced a regression causing the front end
to issue a spurious error about invalid union members when near/far qualifiers
are enabled (e.g., in "--microsoft_16" mode).  For example:

  struct C { char c; };
  union U { C x; } u;  // Triggered a spurious error in version 4.8 when
                       // near/far qualifiers were enabled.

This is now fixed.


10/27/13 [EDGcpfe/14590]
Spurious error on "<" following variable in for-init expression

Starting with version 4.5, a spurious "not a template" error could be issued
in C++11 mode if a variable in a for-init expression was followed by a "<".
Now fixed.

  int main() {
    for (i < 10; ;);
  }


10/24/13 [EDGcpfe/14531]
Multiple diagnostics for invalid token concatenation

When instructed to do so via the DEFAULT_CHECK_CONCATENATIONS configuration
option or the --check_concatenations command-line argument, the front end
issues a diagnostic when the result of the ## preprocessing operator does
not combine two preprocessor tokens into a single valid token.  In cases
where the token preceding an invalid concatenation is the result of one or
more valid concatenations, a change in version 4.5 (see the entry for
EDGcpfe/12839) incorrectly resulted in spurious diagnostics for those valid
concatenations in addition to the intended diagnostic.  This is now fixed.
For example:

  #define CAT(a, b) a ## _ ## b
  extern void CAT(x, ());  // Previously caused two diagnostics


10/24/13 [EDGcpfe/14588]
Backing expressions for implicitly converted constants

When a constant value is implicitly converted to a constant of another type,
the front end previously always attempted to represent that implicit conversion
in the backing expression.  For example:

  char a[] = { 0x31, 0x32, 0x00 };

Here, the initializer constants are of type int, but they are implicitly
converted to type char.  In cases like this, each a_constant entry representing
an element of the initializer additionally pointed to an expression tree
consisting of two expression nodes and the unconverted a_constant entry.  That
overhead turns out to be excessive for some very large aggregate initializers
that occasionally show up (e.g., hundreds of thousands of elements).  The front
end therefore now records an "original type" (new field a_constant::orig_type)
for constants that are converted in this way in certain initialization
contexts, and does not record the backing expression in those cases.


10/23/13 [EDGcpfe/14585]
GNU C++11 compatibility: Conversion from lambda to function pointer

In standard C++11, a closure type includes a conversion function to a pointer
to function if the associated lambda is introduced with "[]" (see the entry of
1/17/12).  GNU compilers, however, also add that member if the lambda
includes a "capture default" (i.e., "[=]" or "[&]") but no actual capture
occurs.  For example:

  int i;
  struct S { S(void (*pf)()); };
  S s([&]{ i = 0; });  // Lambda captures nothing: Implicit conversion to
                       // function type is possible in GNU C++11 mode.

This behavior is now emulated in GNU C++11 mode.


10/22/13 [EDGcpfe/14584]
Objectless reference to member of nonstandard anonymous struct

In configurations in which ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE, an
objectless reference to a member of a nonstandard anonymous struct
subobject resulted in an abort (a failed assertion in scan_identifier).
This is now fixed.  For example:

  struct A {
    union {
      struct {
        int m;
      };
    };
  };
  int i = sizeof(A::m);  // Previously aborted


10/22/13 [EDGcpfe/14591]
GNU-mode abort on call with brace-enclosed argument to overloaded function

In GNU C++11 mode, a call with a brace-enclosed argument to an overloaded
function sometimes resulted in an internal error (in aggr_init_generic_element
in decl_inits.c).  For example:

  struct S { union { int i; }; };
  void f(S const&);
  void f(S &&);
  template<class T> void g(int i) {
    f({{i}});  // Previously triggered an abort during instantiation of
  }            // g<int>(int).
  int main() {
    g<int>(0);
  }

This is now fixed.


10/22/13 [EDGcpfe/14564,EDGcpfe/14601]
Spurious error on "explicit" keyword used in conversion function template

The front end had issued a spurious error when the "explicit" keyword was
applied to a conversion function template.  Now fixed.  For example
(with --c++11):

  template<typename T> struct A { };
  struct B {
    template<typename T> explicit operator A<T>();
  };
  A<char> a = static_cast<A<char>>(B());


10/22/13 [EDGcpfe/14555]
C++-generating back end: operator< template-id with empty argument list

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end sometimes failed to put a space between the name
of an operator< template and an empty template argument list, resulting in
incorrect code.  This is now fixed.  For example:

  template<typename T> bool operator<(T& t1, int);
  template<typename T> struct S {
    friend bool operator< <>(T& t1, int);  // Previously generated as
                                           // operator<<>(T& t1, int)
  };


10/21/13 [EDGcpfe/14507]
C++-generating back end: incorrect qualification of dependent operator names

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end unnecessarily (and, depending on the type of the
qualifier, possibly incorrectly) qualified the name of a dependent operator
function, sometimes resulting in code that could not be compiled.  This is
now fixed.  For example:

  template<typename T> struct S { typedef T& type; };
  template <typename T> struct X {
    static typename S<T>::type s;
    static const int i = sizeof(s.operator-()); // Previously generated as
                                                // s.S<T>::type::operator-
  };
  struct Y { int operator-(); };
  X<Y> xy;

------------------------------------------------------------------------------
Version 4.8, October 18, 2013

10/15/13 [EDGcpfe/14577]
Freeing memory regions

When IL_SHOULD_BE_WRITTEN_TO_FILE is TRUE, the front end previously freed the
memory for function scope memory regions upon completion of the function
definition if the IL for that definition was no longer needed (it could, e.g.,
still be needed for inlining or to be written to a precompiled header file).
Now, this behavior is inhibited by default: All memory regions are freed (and
written out) when the compilation is completed.  This is a preliminary step in
anticipation of phasing out memory regions altogether in future versions of
the front end.  For now, the previous behavior can be restored by setting the
configuration macro FREE_MEMORY_REGIONS_EARLY to TRUE.


10/15/13 [EDGcpfe/12929]
C++11: template support for opaque enum templates

Support for opaque enumerations was added to the front end in version 4.5
(see the 6/20/12 entry for EDGcpfe/9250, et al.).  This did not include
support for the definition of enumerations of class templates outside of
their class, or explicit specialization of such enumerations.  These
features are now supported.

  template <class T> struct A {
    enum E : T;
    enum class S : T;
  };
  template <> enum A<int>::E : int { eint };
  template <> enum class A<int>::S : int { sint };
  template <class T> enum class A<T>::S : T { sT };


10/15/13 [EDGcpfe/10611,EDGcpfe/13463,EDGcpfe/14117]
C++11: decltype allowed as a base class or mem-initializer-id

The resolution of core issue 950, described in n3049, allowing decltype(expr)
to be used as a base class or mem-initializer-id is now implemented.

  struct A {} a;
  struct B : decltype(a) {      // base class
    B() : decltype(a)() {}      // base class initializer
    B(int) : decltype(B())() {} // delegating constructor
  };


10/15/13 [EDGcpfe/10610,EDGcpfe/13616]
C++11: decltype allowed in nested-name-specifiers and destructor calls

The resolution of core issue 743, described in n3049, allowing decltype(expr)
to be used in a nested-name-specifier or following "~" in a destructor name is
now implemented.

  template <class T> struct A {
    struct B {};
  };
  template <class T> inline void f(T t) {
    typename decltype(t)::B b;
    T *p = new T();
    p->~decltype(t)();
  }
  int main() {
    A<int> a;
    f(a);
  }


10/14/13 [EDGcpfe/14567]
Abort on lowering of conditional expression with constant condition

When support for constexpr is enabled (i.e., in C++11 mode), the front end
previously aborted with an internal error in make_init_entity_node (in
lower_init.c) when lowering a conditional expression with a constant
condition and a result that is an rvalue of a class type with a nontrivial
destructor.  For example:

  struct S {
    ~S();
    S(char const*);
  };
  void f(S s) {
    f(1 ? s : "");  // Previously triggered an internal error.
  }

This is now fixed.


10/11/13 [EDGcpfe/14535]
Distinguishing C-style casts from functional notation casts

The front end now distinguishes expression nodes representing C-style casts
and functional notation casts by setting the flag is_functional_notation_cast
to TRUE for the latter.  An additional flag is_brace_notation_cast further
distinguishes casts like "double(x)" from the C++11 alternative "double{x}".


10/10/13 [EDGcpfe/14528,EDGcpfe/14557]
GNU compatibility: Better __builtin support

The front end has been modified to include updated function signatures (mostly
changes in the return type) for various GNU __builtin functions.  The following
routines now have different signatures when gnu_version >= 40400:
__builtin_ia32_psadbw, __builtin_ia32_cmp*ps, __builtin_ia32_cmp*ss,
__builtin_ia32_cmp*pd, __builtin_ia32_cmp*sd, __builtin_ia32_packsswb128,
__builtin_ia32_packssdw128, __builtin_ia32_packuswb128,
__builtin_ia32_packusdw128, __builtin_ia32_pmuludq, __builtin_ia32_pmuludq128,
__builtin_ia32_palignr, __builtin_ia32_pmaddubsw, and
__builtin_ia32_pmaddubsw128.

Additionally, these builtin functions now have updated signatures when
gnu_version >= 40500: __builtin_ia32_vec_ext_v16qi and
__builtin_ia32_vec_set_v16qi.

Undocumented builtin functions __builtin_ia32_pshufw,
__builtin_ia32_vec_set_v4hi, __builtin_ia32_vec_ext_v8hi,
__builtin_ia32_vec_set_v8hi, and __builtin_ia32_pfrsqit1 have also been
implemented.


10/9/13  [EDGcpfe/14552]
Lambda closure types given same mangled name

In cases where a lambda is used as an initializer for an object that is defined
outside its namespace, a non-unique discriminator may have been assigned to
the lambda closure type, possibly resulting in a mangled name collision.
A change was made (when ABI_COMPATIBILITY_VERSION >= 408) to ensure the
discriminators are unique.  For example (with --c++11):

  namespace N {
    extern int i;
    extern int j;
  }
  int N::i([]() -> int { return 123; }());
  int N::j([]() -> int { return 123; }());


10/9/13  [EDGcpfe/14554]
Spurious exception specification mismatch error on operator delete members

In C++11, deallocation operators ("operator delete" and "operator delete[]")
are implicitly noexcept if they are not declared with an explicit exception
specification (see also the entry of 1/8/13 for EDGcpfe/13566).  Previously,
the front end sometimes failed to apply this rule to in-class declarations of
member deallocation functions.  This resulted in spurious errors.  For
example:

  template<typename> struct S {
    static void operator delete(void*, __EDG_SIZE_TYPE__);
  };
  template<typename T> void S<T>::operator delete(void*, __EDG_SIZE_TYPE__) {}
    // Previously triggered a spurious error regarding incompatible
    // exception specification in C++11 modes.

This is now fixed.


10/8/13  [EDGcpfe/14545]
Abort on braced initializer for complex variable in GNU C++11 mode

In GNU C++11 mode, a braced initializer for a _Complex variable could result
in an abort (during the execution of conv_float_to_integer when called from
is_narrowing_conversion).  For example:

  int main() { 
    _Complex double x = {0};  // Previously triggered an abort
  }                           // in GNU C++11 mode.

This is now fixed.


10/3/13  [EDGcpfe/14530]
Extra source position information and explicit specializations

Entries of type a_decl_position_supplement (provided when the configuration
macro EXTRA_SOURCE_POSITIONS_IN_IL is TRUE) now include a pointer to a list of
entries of type an_element_position that describe the position of various
elements of the associated construct.  Currently, this is only used to
describe the position of the "template" keyword in explicit specializations.
For example:

  template<class T> struct S {};
  template<> struct S<void>;
  template<> struct S<int> {};

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, the secondary source sequence
entry for the specialization of S<void> points to a decl-position supplement
that now itself points to an entry describing the position of the "template"
keyword.  In the case of a specialization that is a definition (like S<int>),
the same information is available via the decl-position supplement of the
source correspondence entry.


10/1/13  [EDGcpfe/14538]
constexpr static data member initializers

The front end now accepts more kinds of initializers for constexpr static
data members, including string literal initializers for character arrays.
For example:

  struct X {
    static constexpr const char x[] = "x";  // Previously an error.
  };                                        // Now okay.


10/1/13  [EDGcpfe/14539]
Add ITF_LAST, TCF_LAST macros

The names ITF_LAST and TCF_LAST have been introduced to identify the last bit
defined for the bit vectors that pass boolean information into and out of
identical_types and types_are_compatible.  They can be used as the basis for
defining additional bits if you want to customize the interfaces to those
routines.


9/30/13  [EDGcpfe/14514]
Microsoft compatibility: dllimport variables as nontype template arguments

In Microsoft C++ mode variables declared as "dllimport" are usually treated as
having a nonconstant address (see entry of 7/5/06).  As a consequence, their
address cannot be used as a nontype template argument.  Now, however, the front
end has lifted that restriction for variables of array type.  For example:

  template<char* c> struct S {};
  extern char __declspec(dllimport) x[];
  typedef S<x> SX;  // Previously an error; now accepted.


9/30/13  [EDGcpfe/10608]
Type adjustments in exception specifications

The resolution of Core issue 973 clarified that the types specified in an
exception specification should be adjusted as follows:
  - a function type becomes a pointer type to that function type,
  - a type array of T becomes a pointer to T, and
  - top-level const/volatile qualifiers are dropped.

This is now implemented.  For example:

  typedef void f();
  void g() throw(f);
  void g() throw(f*);         // Previously a redeclaration error; now okay.
  void h() throw(int);
  void h() throw(const int);  // Previously a redeclaration error; now okay.


9/26/13  [EDGcpfe/14527]
Inconsistent lowered IL in arithmetic operations

The types of operands in arithmetic operations in the IL should be
consistent, and in a couple of cases (involving the computation of the
number of bytes to allocate for a multi-dimensional array new operation, or
when lowering a compound assignment operation with an imaginary type) the types
were not consistent.  Those two cases have been fixed and a consistency check
has been added.  For example:

  // with --c99:
  int main() {
    _Bool b;
    b *= (_Imaginary long double)0.0;
  }

  // or with --c++:
  short s = 5;
  int (*p)[10] = new int[s][10];


9/19/13  [EDGcpfe/14511]
GNU compatibility: Aliasing of "abs" and "strlen"

GNU recognizes certain declarations as matching standard library functions
and optimizes calls to those routines in some cases (see Changes entries for
EDGcpfe/10328 and EDGcpfe/10179).  This implicit aliasing doesn't work
when these routines have been given explicit aliases (i.e., when compiling
glibc itself) and has now been disabled when an "alias" or "weakref"
attribute, or an "asm name" is present.  In this example (with --gcc), "abs"
had been considered an implicit alias for __builtin_abs but isn't any longer:

  int __abs (int x) { return x; }
  extern __typeof (__abs) abs __attribute__ ((weak, alias ("__abs")));


9/18/13  [EDGcpfe/14504]
Missing "set but never used" warning

A change during the rework of initializer processing in version 4.5 of the
front end (see the entry for EDGcpfe/9170 of 7/11/12) caused it to no longer
issue a warning when a variable was "set" by taking its address and assigning
to the dereferenced result in the same expression, but then not using the
result of that assignment later on.  For example:

  int main() {
    double d;
    *(&d) = 3.0;  // Triggered a "set but never used" warning in version 4.4,
  }               // but not in more recent versions.  That is now restored.

This is now fixed: The warning is restored.


9/17/13  [EDGcpfe/14500]
GCC compatibility: extern __inline function definition replacement

GNU C and C++ allow a function definition to be provided "for inlining only"
and also a later declaration or definition for non-inline use.  (Note that
this differs from the C99 specification, where only one definition can appear
in any single translation unit.)  See the entry for EDGcpfe/13606 on 2/4/13
for additional details.  For example:

  extern __inline void f() {}  // For inlining only.
  extern void f() __asm("g");  // For other contexts.
  int main() {
    f();
  }

Previously, in GNU C mode, the second declaration displaced the "for inlining
only" definition, and if the latter was not otherwise needed in the IL, it was
subject to the "removal of unneeded entities" process.  This was undesirable
since it could prevent an inliner in a back end from inlining the call, and
in some cases that could in turn lead to linker errors (if the program did
not include a definition for the second declaration).  Now, the front end
explicitly pairs the two associated routine entries (through a new field
"inline_partner" in a_routine) and will keep both in the IL tree if either
one is needed.


9/16/13  [EDGcpfe/14154]
String representation of __is_nothrow_assignable and __is_trivially_assignable

The string representations -- as recorded in builtin_operation_names -- of
_is_nothrow_assignable and __is_trivially_assignable were accidentally
interchanged (causing, e.g., output by the IL display utility of the
corresponding operations to be erroneous).  This is now fixed.


9/13/13  [EDGcpfe/14494]
C++11 and C99 features in Microsoft mode with microsoft_version >= 1800

In Microsoft C++ mode with microsoft_version >= 1800 the following C++11
features are now enabled by default: raw string literals, list initializers,
delegating constructors, variadic templates, deleted and default functions,
nonstatic data member initializers (aka. NSDMIs or "field initializers"), and
alias declarations (including alias template declarations).  Similarly, in
Microsoft C mode with microsoft_version >= 1800, the following C99 features
are now enabled by default: designated initializers, compound literals, and
the _Bool type.


9/13/13  [EDGcpfe/14490]
GNU C++ compatibility: "best worst conversion" in overload resolution

In GNU C++ mode with gnu_version < 40000 the front end sometimes prefers a
builtin operator candidate over a user-declared candidate even though the
former is not an unambiguously better match than the latter.  Specifically,
the builtin candidate is selected if its worst argument conversion is better
than the worst argument conversion needed for the user-declared candidate
(see the entries of 4/5/05 and 7/20/04).  Now this behavior is also enabled
when gnu_version >= 40400.  This causes the front end to accept the following
case:

  struct S { S(char); };
  bool operator==(char, S const&);
  enum E { e };
  bool g(char c) {
    return c == e;  // Previously ambiguous in GNU 4.4 mode.  Now the
  }                 // builtin operator is preferred because the worst
                    // conversion involved is a promotion, whereas the
                    // user-declared operator requires a user-declared
                    // conversion.

Note that this is the same example as the following entry (below, also for
EDGcpfe/14490), but the mechanism that makes it acceptable in some GNU modes
is different.


9/13/13  [EDGcpfe/14490]
User-declared operators and enum operands

The standard specifies that nonmember user-declared operators without a
parameter of enumeration type (or a reference thereto) are not considered for
a use of the corresponding operator in which none of the operands has a class
type.  For example:

  struct S { S(char); };
  bool operator==(char, S const&);
  enum E { e };
  bool g(char c) {
    return c == e;  // Previously ambiguous; now okay.
  }

Previously, the front end issued an ambiguity error because it considered the
user-declared operator==, which is a better match for the first operand since
the built-in operand requires promotion of the char value.  Now, however, the
user-declared operator== is dropped from consideration because it has no
parameter of enum (or reference to enum) type and none of the operands has
class type.

This change does not apply in Microsoft C++ mode, nor in GNU C++ mode when
gnu_version < 40800 (although the corresponding compilers accept the case
above, it is for different reasons, as they appear not to apply the standard
rule in general).


9/12/13  [EDGcpfe/14411]
Explicit conversion function allowed on first argument of constructor in
direct-initialization

Core issue 899 (see the entry for EDGcpfe/11904 on 3/22/12) allowed use of an
explicit conversion function for the argument of a copy constructor when the
context is direct-initialization.  Core issue 1087 extends that resolution to
apply to any constructor whose first parameter is a reference to the
initialized class type (in contexts with just one explicit argument for that
constructor), not just a "copy constructor" per se.  This is now implemented.

  struct C {
    template <class T = int> C(C&, T = 0);
  };
  struct A {
    explicit operator C&() const;
  };
  int main() {
    A a;
    C c(a); // Now calls the constructor template.  (Previously called the
  }         // implicitly declared copy constructor, which is a worse match
            // since it takes a "C const&" rather than a "C&".)


9/11/13  [EDGcpfe/14407]
Spurious exception specification mismatch error on class template destructor

In C++11 mode, the front previously attempted to check the exception
specification of a destructor of a class template thought to override a
base class's virtual destructor.  However, that check sometimes triggered
spurious errors because of unknown properties of template parameters (i.e.,
the check cannot be done in general for class templates).  For example:

  struct B { virtual ~B() {} };
  template<class T> struct D: B {
    T x;
    virtual ~D() {}  // Previously triggered a spurious error in C++11 mode.
  };

This is now fixed (the check is no longer performed in templates).


9/10/13  [EDGcpfe/14442]
Microsoft mode handling of "?" operator with interconvertible 2nd/3rd operands

Usually, if the second and third operands of a "?" operator have different
types and are each convertible to the other, the operator is ambiguous.
Microsoft compilers, however, disambiguate some of these cases when one of
the operands has a class type (see, e.g., the Changes entry of 10/7/10 for
EDGcpfe/11052).  In particular, it appears Microsoft compilers (a) prefer
converting the third operand to the type of the second operand rather than
vice versa, and (b) prefer a constructor call over a user-defined conversion
call.  The exact boundaries of these two preferences is unfortunately not
clear, but the front end now balances the two in a way that matches all the
cases we are currently aware of.  For example:

  struct S {
    S() {}
    S(char const*) {}
    S(S const&) {}
    operator char const*() const { throw "xxx"; }
  };
  int main() {
    bool b = true;
    S s;
    char const *p = (b ? (char const*)0 : s);  // No longer throws an
  }                                            // exception.

Previously, in the example above an exception was thrown because criterion
(b) took precedence over criterion (a).  Now criterion (a) takes precedence
for this case (but not for other similar but slightly different cases).


9/10/13  [EDGcpfe/14470]
Spurious suppression of default nested class constructor

In C++11 and Microsoft C++ modes, the front end sometimes incorrectly
suppressed the default constructor of a nested class that requires a call
to another nested class default constructor involving a default argument.
For example:

  struct S {
    struct D { D(int = 0); };
    struct N { D d; };  // Default constructor was accidentally suppressed
  };                    // in some modes.
  S::N n;  // Previously a spurious error.

This is now fixed.


9/9/13   [EDGcpfe/14245,EDGcpfe/14399,EDGcpfe/14422,EDGcpfe/14423,
          EDGcpfe/14428,EDGcpfe/14429,EDGcpfe/14430]
C++11 features accepted in non-C++11 GNU C++ mode

The front end now accepts a number of C++11 features in some non-C++11 GNU
C++ modes.  This includes: rvalue references (gnu_version >= 40800), lambdas
(gnu_version >= 40500), standard attribute syntax (gnu_version >= 40800),
delegating constructors (gnu_version >= 40700), inheriting constructors
(gnu_version >= 40800), nonstatic data member initializers (aka. NSDMIs,
gnu_version >= 40700), and deleted/defaulted functions (gnu_version >= 40400).
(Scoped enumeration types and variadic templates were already handled by
previous changes.  See the entries of 8/28/12 and 9/26/12.)

GCC doesn't actually enable rvalue references in this way, but since
inheriting constructors require rvalue references, we have paired the
enabling of those two features.

A warning is issued whenever one of these features is used for the first time
outside a system header in a non-C++11 GNU C++ mode.


9/9/13   [EDGcpfe/14410]
GNU C++ compatibility: Abort on declaration of variadic member template

A change made in version 4.7 (see EDGcpfe/13643 on 5/17/13) could result in
an abort (in update_parameter_pack_symbol_values) on the declaration of a
variadic member template in g++ mode when gnu_version >= 40700.  Now fixed.

  template <typename...> class A;
  template <class T1> struct B {
    B(const T1&);
    template<typename... Args> B(A<Args...>);
  };
  template <typename T> struct C {
    void f() {
      B<int> b(0);
    }
  };
  int main() {
    C<int> c;
    c.f();
  }


9/6/13   [EDGcpfe/12468]
Calls to "warn_unused_result" functions in GNU statement expressions

The front end previously issued a spurious warning when the last expression
statement of a GNU statement expression is a call to a function declared with
the attribute "warn_unused_result" (that call produces the result of the
statement expression and is therefore not unused).  For example (assuming
GNU mode):

  __attribute((warn_unused_result)) int f();
  int g() {
    return ({ f(); });  // Previously triggered a warning; now silently
  }                     // accepted.

This is now fixed.


9/6/13   [EDGcpfe/14475]
GNU compatibility: Floating-point literals in integral constant expressions

In GNU modes, the front end now accepts floating-point literals in more
contexts expecting integral constant expressions.  For example:

  enum E { e = 2.1 ? 1 : 2 };  // Previously an error in many GNU modes;
                               // now accepted in all such modes.


9/6/13   [EDGcpfe/14435]
Missing error on invalid braced initializer for character array

The changes to support initializer lists in version 4.5 of the front end (see
the entry of 8/26/12 for EDGcpfe/9170) caused the front end to erroneously
accept a braced initializer for a character array where the first element in
the braces is a string literal matching the array type but additional
initializers follow.  The extraneous initializers were silently ignored.
For example:

  char const s[6] = { "a", 1 };  // Previously silent accepted; now an error.

This problem is now fixed: One or more errors are now issued for such cases.


8/28/13 [EDGcpfe/14443]
Missing initialization of global and static variables

The front end can be repeatedly invoked in a single process and must
re-initialize itself each time.  The variables gnu_bases_operators_enabled
and avail_override_exception_check_entries were not properly initialized
and could retain their values from a previous invocation, resulting
in undefined behavior.  Now fixed.


8/28/13 [EDGcpfe/9167,EDGcpfe/12359]
C++11: Support for thread_local

Changes have been made to support the C++11 thread_local keyword (see N2659).
Objects declared with thread_local storage duration are unique to each
thread of execution, can be dynamically initialized, and are destroyed
at thread termination.

Initialization and destruction of objects with thread_local storage
duration presents some challenges for a stand-alone compiler with no
inherent knowledge of the underlying system's threading model; as a result,
several configuration options are available to allow back ends to choose
the model that works best for their application.

When a back end generates code that is unaware of thread creation,
"lazy initialization" can be used to ensure that each object with
thread_local storage duration is initialized at its first use in each thread
by setting USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES to TRUE.
In such configurations, each use of a potentially dynamically-initialized
thread_local variable is re-written to call an initialization wrapper routine
that does the one-time (per-thread) initialization.  All file-scope dynamic
initializations for objects with thread_local storage are lowered and placed
in a single __tls_init routine (regardless of the setting of
SEPARATE_ROUTINES_FOR_FILE_SCOPE_DYNAMIC_INITS).  When using
one-instantiation-per-object mode, the thread_local initializations
for each "slice" are placed in separate __tls_init__N routines (where
N represents the "slice").

If a back end has the means to execute startup code at thread creation,
the overhead associated with lazy initialization can be avoided.  In that
case, USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES should be set to
FALSE and the back end should arrange to invoke the __tls_init routine from
each translation unit (or, when SEPARATE_ROUTINES_FOR_FILE_SCOPE_DYNAMIC_INITS
is TRUE, each of the routines pointed to by
il_header.thread_local_dynamic_init_routines) at thread creation.

Additionally, the configuration macro LAZY_INITIALIZATION_USES_WEAK_REFERENCES
has been added to allow for back ends that do not support "weak" references.
The default value for this macro is TRUE (as a value of FALSE creates
empty initialization routines for thread_local variables with external
linkage even when they don't have any dynamic initialization).

Note that conformance with the IA-64 ABI requires that
USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES and
LAZY_INITIALIZATION_USES_WEAK_REFERENCES be set to TRUE.
C-generating back end configurations also require
USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES to be set to TRUE.

If the new configuration macro IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS
is set to FALSE, the thread_local keyword is parsed and ignored.  The
predefined macro __STDCPP_THREADS__ is defined as 1 when
IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS is TRUE.

In all cases, the destructions needed at thread termination time are
registered with the runtime library by calling __cxa_thread_atexit in the
IA-64 ABI or __record_needed_thread_destruction in the Cfront ABI.
See the Changes entry in lib_src/Changes for information about related
changes to the runtime library to support this.


8/27/13  [EDGcpfe/14409]
Obsolete macro definitions when building with a Microsoft compiler

The basics.h file contained some macro definitions for integer limits
such as SCHAR_MIN that were used when the front end was being built with
a Microsoft compiler.  Those macros were present because they were defined
incorrectly by very old versions of the Microsoft header files.  These
macros are no longer needed and some of the values were incorrect for
modern Microsoft compilers, so those macro definitions have been removed.


8/27/13  [EDGcpfe/14376]
Destructor invoked when conditional constructor is bypassed

In certain cases, it had been possible for a destructor to be called
when the constructor had not been invoked (because the expression involving
the constructor is conditionally executed).  For example (with --c++11):

  int ctor, dtor;
  struct A {
    bool b;
    A() : b(true) { ctor++; }
    ~A() { dtor++; }
  };
  int main() {
    {
      A a = A();
      bool x = false;
      if (x && ([=]{ return a.b; })()) { }
    }
    return (ctor != dtor);  // now returns 0
  }


8/26/13  [EDGcpfe/14434]
Incorrect processing of cast using decltype without GNU_EXTENSIONS_ALLOWED

If the front end was built with GNU_EXTENSIONS_ALLOWED set to FALSE, a
decltype operator used as the type in a functional-notation cast was not
processed correctly.  If MICROSOFT_EXTENSIONS_ALLOWED was TRUE, an abort
could occur (in is_incomplete_type).  If MICROSOFT_EXTENSIONS_ALLOWED was
FALSE, spurious errors were issued.  Now fixed.

  struct A { };
  int main() {
    A a;
    decltype(&a)(0);
  }


8/21/13  [EDGcpfe/14402]
Allow mangling routines to be used during back_end processing

Previously, the mangling routines (i.e., routines in lower_name.c) had used a
mixture of front end memory and general memory to create mangled names.  A
change has been made to use general memory whenever possible in order to allow
customers to make calls to mangling routines in most situations (front end
memory is still needed in certain cases, but those are unlikely to occur at
this point in the compilation).


8/18/13  [EDGcpfe/14387]
Microsoft compatibility: prototype instantiations of in-class specializations
done in C++11 mode

A change made in version 4.5 caused prototype instantiations of Microsoft
mode in-class specializations to be done in C++11 mode, resulting in
errors in cases such as the one below, which is accepted by the
Microsoft compiler.  Now fixed.

  template<class T> struct A {
    template<class T2> void f(T2);
    template<> void f(wchar_t) { xxx; } 
  }; 


8/16/13  [EDGcpfe/14327]
GNU compatibility: Don't emit "GCC system_header" pragmas when preprocessing

The GNU compiler doesn't emit a "GCC system_header" pragma when producing
preprocessed output and now neither does the front end in GNU emulation mode.
For example, invoking the front end with "--gcc -P ex.c" will result in no
output (with the two files as given below):

  $ cat ex.h
  #pragma GCC system_header
  $ cat ex.c
  #include "ex.h"
  $

8/13/13  [EDGcpfe/14375]
End position of sizeof...(x) construct

The front end previously did not correctly record the position of the closing
parenthesis of a C++11 sizeof...(x) construct for an empty pack expansion (in
configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE).  This could
result in invalid position information in the IL.  For example:

  template<typename... T> struct S {
    static const auto N = sizeof...(T);
  };
  int g() {
   return (int)(S<>::N);
  }

In this example, the recorded end position for the initializer of S<>::N
(i.e., the field initializer_range.end in the corresponding a_variable entry)
was previously an arbitrary (uninitialized) value.  This is now fixed.


8/13/13  [EDGcpfe/9252]
C++11: user-defined literals

In C++11 mode, or when --user_defined_literals is specified on the command
line, the front end now accepts user-defined literals as described in
C++ Standard Committee document N2765.  For example:

  long double operator "" _hr(long double h) { return h * 3600; }
  long double seconds_in_2_hours = 2.0_hr;


8/12/13  [EDGcpfe/9164]
C++11: Inheriting constructors

In C++11 mode, the front end now accepts using declarations in derived
classes that denote the implicit generation of "inheriting constructors", as
described in the C++ standards committee's paper N2540.  For example:

  struct B {
    B(int);
    B(double);
  };
  struct D: B {
    using B::B;  // Generates D::D(double), but not D::D(int).
    D(int);
  };

The acceptance of this feature is controlled by the global variable
inheriting_constructors_enabled.


8/9/13   [EDGcpfe/14360]
Triviality of defaulted copy constructor or copy assignment operator

The C++11 standard specifies that a defaulted copy constructor or copy
assignment operator is nontrivial if its parameter does not have the same
type as the type that its implicit counterpart would have had.  The front
end previously failed to adhere to this rule.  For example:

  struct S {
    S& operator=(S&) = default;  // The implicit operator would have a
  };                             // parameter of type S const&.
  static_assert(!__has_trivial_assign(S), "XXX");
     // The front end previously failed this assertion because the defaulted
     // copy assignment operator was considered trivial.

This is now fixed.


8/9/13   [EDGcpfe/14359]
C++-generating back end: assertion failure with member types of
dependent base classes

The changes for EDGcpfe/10680 (included in version 4.2) introduced a bug in
C++-generating back end configurations in which
PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE.  When a type member of a dependent
base class is named in the derived class using an unqualified name
(permitted in Microsoft and default modes), the front end could abort with
an assertion failure in gen_name.  This is now fixed.  For example:

  template<typename T> struct B { };
  template<typename T> struct D : B<T> {
    int arr[X::N];   // "X" assumed to be a member of B<T>, causing an abort
  };


8/8/13   [EDGcpfe/10584]
C++11: reinterpret_cast and identical integer/enum types

In C++11 mode, the front end now accepts a reinterpret_cast that casts a
source expression of integer or enumeration type to that same type.
For example:

  int p = 1, q = reinterpret_cast<int>(p);  // Now accepted in C++11 mode.

This implements the C++ standards committee's Core issue 799 resolution.


8/8/13   [EDGcpfe/9616]
C++11: Throwing an array with unspecified bound

The resolution of the C++ standards committee's Core issue 499, which is
part of the C++11 standard, clarified that throwing an array of unspecified
bound can be valid.  Previously, this was an error in strict mode (and it
is still an error in GNU C++ mode, since GCC has not implemented the new
rule yet), but now it is accepted in strict C++11 mode.  For example:

  extern int x[];
  void f() {
    throw x;  // Now accepted in strict C++11 mode.
  }


8/8/13   [EDGcpfe/14358]
Microsoft compatibility: defined() operator in macro expansion

As noted below in the change for EDGcpfe/13211, the Microsoft compiler has
a bug in the handling of the "defined" operator when it appears in the
expansion of a macro instead of directly in the source.  As noted below in
the change for EDGcpfe/13703, the bug only occurs with the parenthesized
form of the "defined" operator.  Further experience now reveals that the
bug only occurs when the operand of "defined" immediately follows the left
parenthesis with no intervening white space, and the front end has been
revised accordingly.  For example:

  #define A 1
  #define NOSPACE defined(A)
  #if NOSPACE
  #error "Non-space not handled correctly: result is always false"
  #endif
  #define SPACE defined( A)
  #if !SPACE
  #error "Space not handled correctly: result has the correct value"
  #endif


8/1/13   [EDGcpfe/14353]
GNU C++ compatibility: Instantiating a reference to array of unknown bound

In GNU C++ mode, the front end now accepts a reference to an array of unknown
bound when it occurs in a template instantiation context.  For example:

  struct S { template<typename T> S(T&); };
  extern char const x[];
  S s(x);  // Now accepted in GNU C++ mode.

(See also the entry of 6/14/13 for EDGcpfe/14129, which covers a variation of
this behavior for Microsoft mode.)


8/1/13   [EDGcpfe/14111]
Spurious error on function declarator in variadic class template instance

The front end previously could produce a spurious error when attempting to
parse a function declarator during the instantiation of a variadic class
template if a parameter pack in the function declarator "collapses" due to an
empty pack expansion, and that pack is both preceded and succeeded by another
parameter (that is not itself a collapsing parameter pack).  For example:

  template<typename ... T> struct S {
    int f(int, T *...p, int) { return 42; }
  };
  template struct S<>;  // Previously triggered a spurious error.

The spurious error suggested that the parameter list should end with the
function parameter pack (expected a ")").  This is now fixed.


8/1/13   [EDGcpfe/13855]
Microsoft and GNU C++ compatibility: C++-generating back end issue with
friend templates

When a qualified friend template is used in either Microsoft mode with
--parse_templates, or in g++ mode, the C++-generating back end omitted
the qualifier on the name in the friend declaration.  Now fixed.

  namespace N {
    namespace M {
      template<typename T1> struct A;
    }
    template <int I> struct A;
    template <typename T> class reference {
      template <typename T1> friend struct N::M::A;
    };
  }


7/31/13  [EDGcpfe/14341]
Names of enumerator constants

The front end previously did not record the name of an enumerator in the IL
entry representing the use of an enumerator constant.  The C++-generating
back end attempted to re-create the name by comparing the constant's value
to the corresponding enumerator constants, but that failed if more than one
enumerator constant had the same value.  For example:

  enum E { e1 = 42, e2 = 42 };
  void test() {
    enum E x = e1, y = e2;
  }

Previously, the initializer for y was rendered as "e1" by the C++-generating
back end.  Now "e2" is rendered instead (i.e., the form that appeared in the
source) because that name is recorded in the a_constant entry representing
the use of e2 in the initializer for y.


7/31/13  [EDGcpfe/14334]
Sun C++ compatibility: __typeof__ and __alignof__

In Sun C++ mode the front end now accepts the GNU "__typeof__" feature.  The
variant "__typeof" is also accepted, but, unlike in GNU modes, "typeof"
(without underscores) is not.  For example:

  __typeof(42) x;  // Declares x of type int

Also, the keyword "__alignof__" is now accepted as a synonym for "__alignof"
in Sun C++ mode.


7/31/13  [EDGcpfe/14348]
GNU compatibility: non-prototyped routines not eligible for aliasing

In some cases, __builtin_strlen and __builtin_abs are used as aliases for
routines respectively named "strlen" and "abs" in order to allow calls to these
routines to be folded in the front end (see Changes entries for EDGcpfe/10328
and EDGcpfe/10179).  Such aliasing had been allowed on non-prototyped routines,
but a change has been made to disallow this.  For example (with --gcc):

  int abs();
  int main() {
    return abs(0, 0);  // no longer an alias for __builtin_abs
  }


7/30/13  [EDGcpfe/14335]
Spurious naming issues when using pragma redefine_extname

In configurations that support pragma redefine_extname, the use of this
pragma had corrupted the strings used in the IL entries, causing undefined
behavior.  Additionally, pragma redefine_extname now finds routines
and variables that are implicitly declared.  For example (with --gcc):

  #pragma redefine_extname old new
  int new() { return 0; }
  int main() {
    return old();     // Now returns zero; had caused linker errors in
                      // some configurations.
  }


7/29/13  [EDGcpfe/14347]
C++-generating back end failed to render some type operators

A type operator like C++11's "decltype" was not always rendered correctly
when it appears as the type of a cast (an odd-looking identifier of the form
__Txxx was rendered instead, with xxx a long string of digits).  For example:

  struct {} x;
  decltype(decltype(x)()) y;

The inner decltype (which specifies the type in a function-style cast) was
previously incorrectly rendered.  This is now fixed.


7/29/13  [EDGcpfe/14329]
C++-generating back end, GNU compatibility: Spurious "volatile" keyword added
to asm statement reconstruction

A GNU asm statement without output operands is treated as "volatile"
(i.e., the GNU compiler won't delete it).  Such statements had resulted in
the generation of "asm volatile" statements in C++-generating back end
configurations.  A change has been made to generate the "volatile" keyword
in the output only in cases where the input contained the "volatile" keyword.
For example (with --gcc):

  void f() {
    asm("ret" : :);   // had generated 'asm volatile ("ret" : :);'
  }


7/27/13  [EDGcpfe/14330]
Additional source positions for constants

Constants representing literals (numbers, strings, and characters) now
indicate the source position of the corresponding token via the
source_corresp.decl_position field of a_constant.  (It should be noted that
constants with a non-null source position cannot be shared.)  In addition,
in configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE, a new
field, end_position, has been added to a_constant to record the ending
position of the corresponding literal token.  This field is also set for
initializer list elements, which already indicated the starting position in
source_corresp.decl_position, except that for reasons of memory space usage
no ending position is maintained for ck_designator constants.


7/27/13  [EDGcpfe/14333]
GNU compatibility: command-line macro definitions with embedded spaces

The GNU preprocessor separates the name and replacement text of a
command-line macro definition with an optional "=", preceded by zero or
more spaces; that is, "-DA=B", "-DA B", and "-DA =B" are all accepted by
the GNU preprocessor (the second form defines macro A with the value
"B 1").  The front end correctly handled the first two forms but
incorrectly interpreted the third as including the "=" in the replacement
text.  This is now fixed.  For example, assuming a command-line option
"-DX =y" with --gcc or --g++:

  int X;  // Previously equivalent to "int =y;", now to "int y;"


7/27/13  [EDGcpfe/14332]
Error recovery with invalid character in raw string delimiter

The severity of the diagnostic issued when an invalid character is found in
a raw string delimiter has been reduced to a discretionary error, allowing
it to be further weakened or suppressed altogether.  Also, such an error
previously caused the front end to consider the raw string literal defective
and consequently to scan it as a non-raw string; now, if the raw string
delimiter is otherwise well-formed, the front end will continue to treat the
literal as a raw string.  For example:

  const char *p = R"@(abc
  def)@";   // Previously elicited a non-discretionary error for the '@'
            // and a cascade of errors from an unterminated string literal;
            // now results in a single discretionary error.


7/26/13  [EDGcpfe/14337]
Alignment of GNU vector types

The front end failed to record an alignment for GNU vector types (leaving the
alignment of such types to be one in all cases).  For example:

  __attribute((vector_size(16))) int v16;
  static_assert(__alignof(v16) == 16, "Invalid alignment");

This is now fixed: The alignment of a vector type equals its size.  (Note that
while current versions of GCC appear to accept almost arbitrarily large
vector sizes, the front end must limit the vector size to what can be
represented with the a_targ_alignment type.  See also the Changes entry of
10/5/01 describing how this type can be configured to be larger than the
default a_byte type.)

7/24/13  [EDGcpfe/10301,EDGcpfe/13921,EDGcpfe/13997,EDGcpfe/14161]
Completeness of enum types with explicit underlying types

The front end now implements support for the resolution to the C++ standards
committee's Core issues 803 and 977, which makes an enum type with an explicit
underlying type complete as soon as that underlying type has been seen.
For example:

  enum E: char { e = sizeof(E) };

In addition, for such enumeration types, the first enumerator constant was
previously given type int until the end of the enum type's definition; it
should have been given the specified underlying type instead.  For example:

  enum F: char { f0, f1 = sizeof(f0) };
    // Previously sizeof(f0) was equivalent to sizeof(int); now it is 1.

This is now fixed.


7/23/13  [EDGcpfe/14288]
Microsoft compatibility: internal error on Microsoft asm in for statement

In Microsoft mode, in modes in which range-based for loops are enabled
(C++/CLI and Microsoft version >= 1700), an internal error could occur on
a Microsoft asm in an invalid location in a for statement.  Now fixed.

  int main() {
    for _asm{ }
  }


7/23/13  [EDGcpfe/14184]
alignof/__alignof and arrays of unspecified bound

Previously, applying the "alignof" (or "__alignof") operator to an array of
unspecified bound elicited a warning or an error depending on the mode
(because such an array type is technically incomplete).  Now it is silently
accepted in all modes.  For example:

  unsigned n = (unsigned)__alignof(int[]);  // Now silently accepted in
                                            // all modes that accept the
                                            // __alignof operator.

In addition, the evaluation of "alignof" in template substitution contexts
now more closely matches that of ordinary contexts (previously, for example,
in substitution contexts alignment attributes applied to variables or fields
were never considered).


7/23/13  [EDGcpfe/14328]
Remove do-nothing lowered dynamic initialization

In certain cases, lowering is able to remove a dynamic initialization
from the IL completely.  The changes for
LOWERING_REMOVES_UNNEEDED_CONSTRUCTIONS_AND_DESTRUCTIONS
(see the Changes entry for 11/19/11) suppressed this removal in some cases
where a dynamic initialization had a call to an unneeded destructor.
Now fixed.  For example:

  struct A { ~A() { } };
  void f() {
    A a;
  }


7/22/13  [EDGcpfe/11271]
C++11: [[final]], [[override]], [[base_check]], and [[hiding]] attributes

During the C++11 standardization process the [[final]], [[override]],
[[base_check]], and [[hiding]] attributes were added to the C++ working paper
and implemented by the EDG front end (see the Changes entries of 12/3/09 and
3/26/10).  Subsequently, those attributes were removed from the final C++11
standard (in favor of context-sensitive keywords -- see the Changes entry of
3/8/12 and N3206).  A change has been made to issue a warning for use of these
attributes in strict mode.  This example (with --c++11 --strict) now elicits
a warning:

  struct B {
    virtual void f();
  };
  struct D: B {
    [[final]] virtual void f();
  };


7/22/13  [EDGcpfe/14276]
Spurious implicit conversions of scoped enums used with built-in operators

The front end erroneously considered conversions of scoped enumeration types
when comparing certain built-in operators taking integer-like operands with
user-declared overloaded operators.  For example:

  enum class E: int { e };
  int operator|(void*, E);
  int x = 0 | E::e;  // Only the user-declared operator should match, but
                     // the front end previously reported an ambiguity with
                     // the built-in operator.

This is now fixed.


7/22/13  [EDGcpfe/14090,EDGcpfe/14200,EDGcpfe/9817,EDGcpfe/10253,
          EDGcpfe/10846,EDGcpfe/12881]
Abort on malformed friend declaration of main()

The front end previously aborted (in corresponding_param_type; class_decl.c)
when processing a malformed friend declaration of main() that attempts to add
default arguments.  For example:

  template <class T> class S {
    friend int main (T x = 2) ;
  };
  int main() {
    S<bool> s;  // Previously triggered an abort.
  }

This is now fixed.


7/22/13  [EDGcpfe/14305]
Space usage of a_source_position

The type a_source_position included two or more fields of type unsigned long
(depending on the configuration macros FULLY_RESOLVED_MACRO_POSITIONS and
RECORD_MACRO_INVOCATIONS).  The type unsigned long was chosen long ago to
ensure at least 32 significant bits, but it now commonly is a 64-bit type.
Now these fields have type uint32_t, which can result in significant space
savings on some platforms.  In addition, for configurations that set
FULLY_RESOLVED_MACRO_POSITIONS to TRUE, the declaration order of some fields
has been rearranged to increase the likelihood of a more efficient layout.


7/19/13  [EDGcpfe/10662]
C++11 const-correctness in the front end

C++11 removed the previously-deprecated implicit conversion from a narrow
string literal to char* (see the entry for EDGcpfe/10299 below for a
discussion of the implementation of this change in the front end).  In
order to permit compilation of the front end as C++11 code while still
allowing clients of the front end and IL structures to use the former
interfaces, the front end now defines a new typedef, a_const_char, that is
used in declaring pointers to read-only string data and pointers to such
pointers.  Depending on the value of the new configuration macro
USE_POINTER_TO_CONST_CHAR, a_const_char is typedef'ed either to const char
(for C++11 compatibility) or to char (to preserve the existing interfaces).
The default value for the macro is TRUE when __cplusplus is defined and has
a value of at least 201103L when the front end is built and FALSE
otherwise.  Customers who set USE_POINTER_TO_CONST_CHAR to TRUE will need
to make possibly-extensive changes to their code, as the types of many
variables, function parameters, function return values, and fields of IL
data structures will be different.


7/19/13  [EDGcpfe/11740,EDGcpfe/14277]
C++11: Incomplete return types and decltype

Toward the end of the C++11 standardization process, the committee adopted a
rule that the return type in a function call need not be complete if the
function call appears as the immediate operand of a decltype construct (see
the committee's paper N3276).  This behavior is now implemented.  For example:

  struct S;
  S f();
  decltype(f()) *p;  // Previously an error, now okay.


7/19/13  [EDGcpfe/14299]
C++/CLI: "= default" in C++11 mode

When using C++/CLI and C++11 modes, the front end erroneously rejected
an explicitly-defaulted member function declaration.  This is now fixed.
For example (with --cppcli --c++11):

  class A {
    A() = default;
  };


7/19/13  [EDGcpfe/14274]
Microsoft compatibility: __declspec(restrict) in C99 mode

In configurations where SUPPRESS_RESTRICT_IN_GENERATED_CODE is TRUE and
"restrict" is a keyword, using __declspec(restrict) had caused a spurious
diagnostic which is now fixed.  For example (with --microsoft --c99):

  __declspec(restrict) void *f() {
    return 0;
  }


7/19/13  [EDGcpfe/14300]
GNU compatibility: __builtin_constant_p and const variables

In GNU C mode (all versions) and in GNU C++ mode with gnu_version >= 40300
or gnu_version >= 40000 but < 40100, and when gcc_const_variables_allowed is
TRUE (see the Changes entry of 6/25/13 for EDGcpfe/14216), a call of the form
__builtin_constant_p(x), where x is the name of a nonlocal const variable
initialized with a constant expression, now produces the value 1 (i.e.,
"true") if the call appears in function scope.  For example:

  int const N = 20;
  int is_N_constant = __builtin_constant_p(N); // Produces 0 (false) value.
  void g() {
    if (__builtin_constant_p(N)) {  // Condition is now true in some
    }                               // GNU modes.
  }


7/19/13  [EDGcpfe/14303]
Setting of this_param_variable (in a_scope) for IA-64 alternate entry points

Member functions created during lowering by define_default_version_of_routine
(which are typically IA-64 alternate entry points) had been created with
a_scope::this_param_variable set to NULL.  A change has been made to set
a_scope::this_param_variable to point to the "this" parameter for the
member function.


7/18/13  [EDGcpfe/12441,EDGcpfe/12528,EDGcpfe/13092,EDGcpfe/14104]
GNU: Support for "asm goto"

Support has been added for GNU's "asm goto" in GNU C and C++ emulation
modes when gnu_version >= 40500.  "asm goto" is described by
http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.htm.  For example
(with --gnu_version 40500):

  void f() {
  label:
    asm goto ("jmp %l[label]"::::label);
    asm goto ("jmp %l0"::::label);
  }


7/16/13  [EDGcpfe/14295]
IA-64 ABI: Calling sequence for function returning class type with trivial
copy constructor and trivial, but explicitly-defaulted, destructor

According to the IA-64 ABI, a function that returns a class type that
has a non-trivial copy constructor or destructor should expect that the
caller has allocated a temporary for the return value and passed a pointer to
the temporary as an implicit first parameter.  In cases where the class has a
trivial copy constructor and a trivial, but explicitly-defaulted, destructor,
the front end erroneously used this calling sequence for such functions.
When the EDG front end is used to compile both caller and callee, the issue is
largely hidden, but if one side of the call is compiled with a different
compiler (or now, with a different version of the EDG front end), this mismatch
could result in undefined behavior at run-time.  The previous (incorrect)
behavior is preserved when ABI_COMPATIBILITY_VERSION < 408.  For example
(with --c++11):

  struct A {
    ~A() = default;
  };
  A f() {
    return A();
  }
  int main() {
    f();  // had generated call to _Z1fv(&temp), now _Z1fv()
  }


7/12/13  [EDGcpfe/14279]
Microsoft compatibility: "boolean-converted" in C++/CLI mode

In C++11, conversion functions can be declared "explicit" to indicate that
they should be considered for explicit conversions (e.g., casts) but not for
implicit conversions.  One exception, however, are "boolean-converted"
expressions (i.e., expressions appearing in contexts that expect a boolean
control value, such as the controlling expression of a "while" statement):
In those contexts, C++11 mode also considers explicit conversion functions.
C++/CLI mode also enables explicit conversion functions, but previously the
exception for "boolean-converted" expressions did not apply in that mode.
Now, it does apply if microsoft_version >= 1800.  For example:

  struct S { explicit operator bool() const; };
  void g(S s) {
    while (s) {}  // Previously not accepted in any C++/CLI mode; now
  }               // accepted if microsoft_version >= 1800.

See also the Changes entry of 4/19/11 for EDGcpfe/8624, etc. 


7/12/13  [EDGcpfe/12812,EDGcpfe/14282]
Criterion for user-provided member functions

The C++11 standard defines a function to be user-provided if it is explicitly
declared and neither defaulted nor deleted on its first declaration.  However,
that definition was different earlier in the standardization process, and that
is what we previously implemented: deleted member functions were always
considered to be user-provided (and the front end erroneously made implicitly-
declared deleted functions user-provided as well).  The front end has now been
updated to implement the newer definition, which changes the validity of
certain cases.  For example:

  struct S {
    int i;
    S() = default;
    S(S const&) = delete;  // No longer a user-provided constructor.
  };
  S s = { 1 };  // Now valid (in C++11 mode).

Previously, S was not considered an aggregate type because it included a
user-provided constructor (the deleted copy constructor), and so the
initialization of s was invalid because no matching constructor is present
in S.  However, with the new rules, the deleted constructor is no longer
considered to be user-provided, and S is therefore an aggregate type, which
in turn makes the initialization of s valid.

As part of this change, a fix was made also to more reliably mark classes
with implicitly deleted copy functions (constructors and/or copy assignment
operators) as being not bitwise copyable.  For example:

  struct S {
    S&& operator=(S&&);
  };
  S f();
  void g(S x) {
    true ? f() : x;  // Now an error because it makes use of the
  }                  // deleted copy constructor.

In this example, S has a deleted copy constructor because of the user-declared
move assignment operator.  Struct S should therefore not be considered
bitwise copyable, but previously the front end failed to mark the class as
such.  That in turn caused it to fail to diagnose the use of the deleted copy
copy constructor in some contexts (such as the conversion needed for the
conditional expression in this example).  This is now fixed.


7/12/13  [EDGcpfe/14284]
Microsoft compatibility: Binding an rvalue reference to a converted lvalue

The changes for EDGcpfe/12427 that permit binding an lvalue converted to an
rvalue to an rvalue reference in C++11 mode (part of implementing support for
the C++ standards committee's resolution for Core issue 1138) are now also
enabled in Microsoft C++ mode with microsoft_version >= 1800.  For example:

  struct S { S(int const&); };
  void f(S&&) {}
  void g(int x) {
    f(x);  // Now accepted in newer Microsoft C++ modes.  Previously an error
  }        // about attempting to bind an lvalue to an rvalue reference.

A related behavior implemented for C++11 mode through the changes for
EDGcpfe/11002 (see Changes entry of 9/10/10) has also been enabled in
Microsoft C++ mode (all versions).


7/11/13  [EDGcpfe/14287]
C++-generating back end: format of "non-arithmetic" integer constants

When the front end scans a hexadecimal or octal integer literal, it marks
the resulting constant as "non-arithmetic," reflecting the assumption that
such literals are likely to be used as bit masks and the like rather than
as numeric values.  This allows the front end to suppress warnings for sign
changes and such that may not be appropriate.  The C++-generating back end,
however, ignored this flag and put out all integer constants as decimal,
rendering the generated code susceptible to the warnings that were
suppressed in the original source.  Such constants are now put out as
hexadecimal literals, avoiding this problem.  For example:

  int i = 0xffffe52e;  // Previously generated as 4294960430U, resulting
                       // in a "sign change" warning when the generated
                       // code was compiled.


7/10/13  [EDGcpfe/14209]
Abort on function-style cast with template-dependent pointer-to-member

In some unusual cases involving a function-style cast of a template-dependent
pointer-to-member function bound to an object, but not immediately used for
a call (which should be an error), the front produced a corrupt data structure,
which in turn caused internal errors or other aborts in later processing.
For example:

  struct A { int f(); };
  template <int (A::*p)()> struct B {
    void g(A &x) {
      typedef int (B::*PMF)();
      PMF( x.*p )();  // Function-style cast of invalid expression "x.*p"
    }                 // (invalid because it is not immediately called):
  };                  // This previously triggered an abort in most
                      // configurations.

This is now fixed.


7/10/13  [EDGcpfe/14219]
pragma before "while" keyword in "do" statement (IL CHANGE)

In C++-generating back end configurations, when a pragma occurs
between the dependent statement of a "do" statement and the closing "while"
keyword, that pragma had been emitted in the generated C++ after the "do"
statement, thereby causing it to pertain to the following statement.
In order to handle cases such as this, a new end-of-construct source sequence
entry has been added for "do" statements to indicate the placement of the
"while" clause (which is an IL CHANGE).  For example (with --microsoft):

  void f() {
    do {} __pragma(warning(suppress:4127)) while(false);
      // had generated this C++:
      // do {} while(false); __pragma(warning(suppress:4127))
  }


7/9/13   [EDGcpfe/14202]
Instantiation of class template of non-literal type with a constexpr member
function

A constexpr member function is only permitted in a literal class type.  This
rule is relaxed when the class type is an instantiation of a class template,
but the front end previously issued an error for such cases.  This error is now
suppressed and the member function is not considered constexpr.  For example
(with --c++11):

  struct A {
    A() { }
  };
  template <class T> struct B {
    T m;    // Makes B<A> a non-literal class.
    constexpr int f() { return 0; }
  };
  B<A> a;


7/3/13   [EDGcpfe/14128]
Microsoft compatibility: accept "final" function modifier

The "final" context sensitive keyword is now accepted as a member
function modifier when microsoft_version >= 1700.  For example (with
--microsoft_version=1700):

  struct B {
    virtual void f() {}
  };
  struct D : B {
    virtual void f() final {}
  };


7/3/13   [EDGcpfe/14267]
C++-generating back end: qualified names for members of the unnamed namespace

When a member of the unnamed namespace is hidden, requiring a qualified
name to refer to it, the C++-generating back end incorrectly used an
unqualified name.  This is now fixed.  For example:

  struct A { enum { B }; };
  namespace {
    struct B { };
  }
  struct C: A {      // A::B hides struct B inside C
    void f(::B *);   // Previously generated as f(B *)
  };


7/3/13   [EDGcpfe/14103]
GNU compatibility: use of "always_inline" attribute on non-inline functions

Recent versions of GNU (i.e., 4.7.0 and later) give a warning and don't inline
a function when the "always_inline" attribute is used on the definition of a
function that is not otherwise inline.  The front end now produces a similar
warning and does not implicitly mark the routine as inline (when
gnu_version >= 40700).  The previous behavior (i.e., to implicitly mark the
routine as inline) is maintained when gnu_version < 40700.  For example:

  __attribute__((always_inline)) void f() {}
                  // gnu_version >= 40700: warning and f is not marked inline
                  // gnu_version <  40700: f is implicitly marked inline


7/2/13   [EDGcpfe/14264]
IL write-read error with Microsoft attributes in parameter types

In cases where a routine definition and a previous declaration of the routine
differ (e.g., because of default arguments), the process of reconciling the
declarations had inadvertently lost any Microsoft attributes that were applied
to parameter types, resulting in an IL write-read assertion failure in some
configurations.  For example (with --microsoft):

  void f([SA_Pre(Null=SA_No)] int x = 0);
  void f([SA_Pre(Null=SA_No)] int x) {}


7/2/13   [EDGcpfe/14265]
C++-generating back end: enumerators as array bounds

A change in version 4.7 caused the C++-generating back end to put out the
value instead of the name of an enumerator when the enumerator is used in
the source code as an array bound in a cast.  This is now fixed.  For
example:

  struct S {
    enum { e = 4 * 256 };
  };
  extern void* p;
  void f() {
    (int(*)[S::e])p;  // Cast previously generated as (int(*)[1024])
  }


7/1/13   [EDGcpfe/14263]
GNU compatibility: Sentinel values

When checking argument values for the GNU "sentinel" attribute (see the entry
of 3/24/06), the front end now also accepts the GNU __null constant and any
expression of the C++11 type std::nullptr_t.  For example (GNU mode):

  void f(int, ...) __attribute__((sentinel));
  void g() {
    f(42, __null);  // No longer elicits a warning.
  }


7/1/13   [EDGcpfe/14259]
Extended position information for nonstatic data member initializers

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the front end now records the
start and end positions of nonstatic data member initializers in the
corresponding a_field entry.  (A new initializer_range field has been added
to a_field entries in such configurations; it mimics the field of the same
name in a_variable.)


7/1/13   [EDGcpfe/14257]
Failure to set correspondence on function template prototype instantiation

When simultaneously compiling multiple translation units but not performing
prototype instantiations of function templates, the front end sometimes
failed to record a cross-translation unit correspondence for the a_routine
entry representing a prototype instantiation of a function template defined
in a secondary translation unit.  This, in turn could result in an internal
error ("entity with external linkage does not have corresp info") in
trans_copy.c.  This is now fixed.


6/29/13  [EDGcpfe/14258]
C++-generating back end: deleted definition not included in template strings

When the string representation is used to reconstruct template definitions
in the C++-generating back end, the "= delete" was omitted from the
string representation.  Now fixed.

  template <typename T> struct A {
    template <typename U> void operator()(U *) const = delete;
  };


6/28/13  [EDGcpfe/14190]
GNU compatibility: __builtin_bswap16

In GNU modes, the front end now predeclares the byte swapping function
__builtin_bswap16.  For example (with --g++):

  typedef unsigned short uint16_t;
  int main() {
    return __builtin_bswap16((uint16_t)0xaabb) != (uint16_t)0xbbaa;
  }


6/28/13  [EDGcpfe/14255]
String literal discriminators and folding in the IA-64 ABI

The IA-64 ABI requires that string literals appearing in certain local contexts
be numbered with a "discriminator" value used for mangling purposes.  This is
important, for example, to ensure that all the string literals emitted in
inline functions share the same address.  Consider the following example:

  inline char const* f() {
    char const *p1 = "Y";
    char const *p2 = true ? "Y" : "N";
    return p2;
  }
  int main() { return f() != 0; }

The string literals "Y" can be shared; i.e., there is only one a_constant
entry for them.  However, the conditional operator can be folded in this case
and previously the folded result pointed to a backing expression, which in
turn prevented sharing of the a_constant entries representing the initializers
of p1 and p2, despite the two having the same discriminator value.
A consequence of the resulting invalid IL was that lowering could generate
duplicate definitions of variables storing the string literal (in
configurations with RECORD_BACKING_EXPRS_WITH_IL_LOWERING set to TRUE).
This is now fixed: No backing expression is recorded for string constants
with a discriminator value even when the constant results from folding.


6/27/13  [EDGcpfe/14179]
Missing diagnostic on member enum defined using derived class name qualifier

In C++11 an enum type can be declared using an opaque declaration in a class
and then defined outside that class.  However, the front end failed to
diagnose attempts to do this using a derived class name qualifier.
For example:

  struct B {
    enum class E;
  };
  struct D: B {};
  enum class D::E { e };  // Invalid, but previously accepted.

This is now fixed (i.e., an error is now issued on a case like this).


6/27/13  [EDGcpfe/14254]
Capture by reference of a variable captured by value in an enclosing lambda

When a nested lambda captures a variable by reference that is captured by
value in a non-mutable enclosing lambda, the reference capture should behave
as a reference-to-const.  For example:

  void g1(int x) {
    auto lambda = [x] {
                    [&x] {  // Implies "reference to const int".
                    };
                  };
  }

The front end, however, failed to propagate this principle to more deeply
nested reference captures, which resulted in spurious errors about attempting
to bind a reference to a non-const type to a const initializer value.
For example:

  void g2(int x) {
    auto lambda = [x] {
                    [&x] {
                      [&x] {};  // Triggered a spurious error because the
                    };          // capture was handled as a "reference to
                  };            // (non-const) int".
  }

This is now fixed.


6/26/13  [EDGcpfe/8527]
C++11: alignas and alignof

In C++11, the front end now accepts alignas(...) as an alignment specifier
(equivalent to the early draft-standard [[align(...)]] attribute; see the
entry of 12/3/09 for EDGcpfe/8293) and alignof(...) to query the alignment
of a type (similar to the existing __alignof__ extension).  For example:

  struct alignas(16) S {};
  static_assert(alignof(S) == 16, "Error");

The C++11 standard doesn't allow an expression argument for "alignof", but
since it is a common extension, the front end does accept expression
arguments with a warning in non-strict C++11 modes:

  int i = alignof(1);  // Accepted with a warning in non-strict C++11 mode.


6/26/13  [EDGcpfe/13502]
Prefix attributes on exception handler parameters

The front end now accepts prefix attributes on exception handler parameters.
For example:

  void f() try {
  } catch ([[]] int) {  // Now accepted in C++11 mode.
  }


6/26/13  [EDGcpfe/14216]
Macro/variable to control gcc mode const variable feature

gcc with -O1 allows the use of const variables in constant expressions
in C mode (see EDGcpfe/10651).  We've allowed this unconditionally in
gcc mode (because we do not have an equivalent of the -O option), with
the rationale that it's harmless to accept more cases than gcc does.
However, folding more cases can produce different results on uses
of the __builtin_constant_p operator.  For example, the following
compiled by gcc with -O1 will print that both cases are constant, but
with -O0 will print that both are non-constant:

  extern int printf(const char *, ...);
  #define check_const(a) \
  if (__builtin_constant_p(a)) printf(#a " is constant\n"); else \
  printf(#a " is not constant\n");
  const int ci=2;
  int main() {
    check_const(ci);
    check_const(ci == 2);
  }

We've now added a macro DEFAULT_GCC_CONST_VARIABLES_ALLOWED and an
associated variable gcc_const_variables_allowed, which default to
TRUE, giving the same behavior as before (the -O1 behavior).
Customers who do not want that behavior can change the setting of the
macro to FALSE.


6/25/13  [EDGcpfe/14246]
C++-generating back end: range-based for generated incorrectly

In configurations with MICROSOFT_EXTENSIONS_ALLOWED set to FALSE, the
C++-generating back end put out a range-based for statement with an
extraneous undeclared initializer for the index variable.  This is now
fixed.  For example:

  void f() {
    int a[5] = { 1, 2, 3, 4, 5 };
    for (int &x : a) {  // Previously generated as
                        // "for (int &x = *__T12345678 : a)"
      x *= 2;
    }
  }


6/25/13  [EDGcpfe/13545]
Rvalue references in exception specifications

In strict mode, the front end now issues a discretionary error on rvalue
reference types used as exception specification types.  For example:

  void f() throw(int&&); // Now an error in strict C++11 mode.

This corresponds to the resolution of the C++ standards committee's Core 
issue 1267.


6/25/13  [EDGcpfe/14239]
Improved diagnostic on explicit declaration of predeclared function

Some compatibility diagnostics on explicit declarations of predeclared
functions referred to the explicit declaration itself as if it were the
"prior" declaration.  For example, in Microsoft mode:

  extern "C++" void __cdecl __debugbreak(void);  // (1)
    // Previously triggered an error about the linkage specification being
    // incompatible with the "previous" declaration, but the diagnostic
    // pointed to line (1) for that "previous" declaration.

This is now fixed: The diagnostic now clarifies that the incompatibility is
with an implicit declaration.


6/25/13  [EDGcpfe/14166]
Spurious correspondence error when using complicated nonreal types

When simultaneously compiling multiple translation units containing
declarations involving relatively complicated "nonreal types" (i.e., types
expressed using template parameters, such as "typename X<1, T>::Y" where T is
a template parameter), the front end sometimes issued spurious correspondence
errors.  This was triggered by the failure of the front end to establish a
correspondence relationship between templates involved in the expression of
those nonreal types.  This problem -- which is believed to be rare in
practice -- is now fixed.


6/24/13  [EDGcpfe/14215]
GNU compatibility: placement of transparent_union attribute

The old attributes framework had allowed the transparent_union attribute to be
specified as a specifier in a declaration.  That behavior is now restored.
For example (with --gcc):

  typedef __attribute__((transparent_union)) union {
    int i;
  } U;


6/24/13  [EDGcpfe/14214]
GNU compatibility: deprecated attribute on a parameter

As a result of the changes for the underlying attribute processing mechanism
(see the 12/3/09 Changes entry), specifying the "deprecated" attribute on
a parameter in GNU emulation mode had resulted in a spurious error and is now
fixed.  For example (with --gcc):

  int f(int p __attribute((deprecated))) {
    return p;
  }


6/24/13  [EDGcpfe/14222]
Deleted special member functions and C++11 SFINAE rules

The front end previously did not always fail template deduction on a reference
to a deleted special member function, as would be required by the C++11 SFINAE
rules (see Changes entry of 4/26/10 for EDGcpfe/9169).  For example:

  struct S {
    S();
    S(S const&) = delete;
  } s;
  template<class T> int f(decltype(T(s)) *p);  // (1)
  template<class T> char f(decltype(T()) *p);  // (2)
  int main() {
    f<S>(new S);  // Should pick (2).  Previously reported as ambiguous.
  }

In this example, selecting candidate (1) for the call in main() would require
the use of the deleted copy constructor of S.  So the C++11 SFINAE rules
remove that candidate from the set, and that is now correctly done: Candidate
(2) is then selected for the call.  Previously, both candidates competed in
overload resolution, and that resulted in an ambiguity (since the parameter
types are otherwise identical).


6/24/13  [EDGcpfe/14234]
End position of parenthesized initializer

In configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE, the end
position of a parenthesized initializer was often not recorded.  For example:

  int main() {
    int x(2);  // The position of the right parenthesis was not recorded
  }            // in the a_variable entry.

This is now fixed.


6/21/13  [EDGcpfe/14230]
C++-generating back end: lvalue-to-rvalue conversion with folded
conditional expression

In cases where a conditional expression has a constant first operand and is
consequently folded to just the second or third operand and that operand
has a reference type but the other operand is a prvalue or has a different
type, the implicit type and lvalue-to-rvalue conversion of the selected
operand could be lost in the code put out by the C++-generating back end.
This has now been addressed by explicitly reflecting the lvalue-to-rvalue
conversion as a cast of the selected operand to the prvalue type.  For
example:

  struct A {
    operator int&();
  };
  int&& ir = true ? A() : 0;  // Previously generated as A(), now (int)A()


6/21/13  [EDGcpfe/14228]
C++-generating back end: Abort on initializer in template

In GNU C++ mode, the front end does not attempt to match the structure of an
initializer to that of a class type variable it initializes.  For example:

  struct S { int i[2]; };
  template<class T> void f() {
    S s = { 1, 2 };  // Previously aborted in GNU C++ mode for certain
  }                  // configurations.  Now okay.

In GNU C++ mode, the initializer "{ 1, 2 }" in this example is not matched to
type S, and therefore only has a single ck_aggregate constant (in other modes
a ck_aggregate constant is constructed for S and another one for the embedded
array).  In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE,
such situations could cause the C++-generating back end to abort with an
internal error ("gen_initializer_constant: ran out of fields").  This is now
fixed.


6/21/13  [EDGcpfe/14227]
C++-generating back end, GNU C++ compatibility: static member function of
class template as template argument

g++ has a bug requiring that a qualified name be used when passing the
address of a static member function of a class template as a template
argument inside the definition of the class template.  The C++-generating
back end has now been changed to work around this g++ bug by
unconditionally putting out a qualified name in such contexts.  For
example:

  template <void(*)()> struct A;
  template <typename T> struct B {
    static void f();
    typedef A<&B::f> Af;  // Previous generated as A<&f>, now A<&::B<T>::f>
  };


6/21/13  [EDGcpfe/14220]
C++-generating back end: incorrect name references in partial specializations

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, under
some circumstances a template argument appearing in one partial
specialization could refer to a template parameter of a different partial
specialization in the output of the C++-generating back end.  This is now
fixed.  For example:

  template<int> struct A;
  template<char> struct B;

  template<typename T, bool, bool> struct C { };

  template<typename T, bool b> struct C<T, true, b> {
    static constexpr char x = A<T::i>::v;
    static constexpr char y = 100 / x;
    typedef B<y> By;
  };

  template<typename T> struct C<T, false, false> {
    static constexpr char x = A<T::i>::v;
    static constexpr char y = 100 / x;
    typedef B<y> By;  // template argument previously generated as
                      // "100 / ::C< T, true, b> ::x", using the template
                      // parameter "b" from the previous partial
                      // specialization.
  };


6/21/13  [EDGcpfe/14229]
std::bad_array_new_length mistakenly thrown in non-C++11 modes

Throwing std::bad_array_new_length is a C++11 feature (see the Changes
entry for EDGcpfe/13489) and code in lowering had mistakenly enabled
throwing that exception in non-C++11 modes.  That is now fixed.
For example, with -x, the following example had returned 0 and now returns 1:

  #include <new>
  void f(int i) {
    new int[i];
  }
  int main() {
    try {
      f(-1);
    } catch(std::bad_array_new_length) {
      return 0;
    } catch(...) {
      return 1;
    }
    return 2;
  }


6/20/13  [EDGcpfe/14224]
Assertion failure casting derived-class reference to base-class reference

In configurations in which RECORD_BACKING_EXPRS_WITH_IL_LOWERING is set to
TRUE, an attempt to cast a derived-class reference to a base-class reference
could result in an assertion failure in add_base_class_casts.  This is now
fixed.  For example:

  struct B { };
  struct D: B { };
  D d;
  D &dr = d;
  void f() {
    B &br = dr;  // Previously aborted
  }


6/20/13  [EDGcpfe/14168]
C++11: User-defined conversions to std::nullptr_t and comparison operators

In C++11 modes, the front end now considers user-defined conversions to
std::nullptr_t when resolving relational and equality operators.  For example:

  namespace std { using nullptr_t = decltype(nullptr); }
  struct X { operator std::nullptr_t() { return nullptr; } } x;
  bool b = x<x;  // Previously an error; now accepted.

Note that for relational operators (e.g., "<="; but not for "==" or "!=")
the next standard will likely make comparisons of nullptr_t expressions
invalid altogether.
  

6/20/13  [EDGcpfe/14223]
C++/CLI: Interface list processing from DLL

When reading a DLL and parsing a list of interfaces for a managed type,
in some cases a comma would be missing from the list, causing the resulting
portable assembly to have spurious errors.  The Control and BindingSource
types in the System.Windows.Forms.dll file had instances of this issue and
are now fixed.


6/20/13  [EDGcpfe/10300]
Constant static data members

C++11 changed the rule deciding when a const static data member can be used
as a valid constant expression.  In C++03, the data member had to be
initialized within the class, but in C++11 that is no longer needed (this
change was the resolution to Core issue 721).  The front end already
implemented this relaxation in nonstrict modes for non-template classes, but
now it implements the change completely.  For example:

  template<typename T> struct S {
    static int const N;
  };
  template<typename T> int const S<T>::N = 5;
  int z[S<int>::N];  // Now accepted in all C++11 modes.


6/20/13  [EDGcpfe/14221]
Error recovery attempting to cast to a base class type

The front end failed to recover from errors when casting to a pointer or
reference to a base class type, leading to an assertion failure in
get_pointer_offset.  This is now fixed.  For example:

  template <class T, class U> void f(T x, U y) {
    struct B : T, virtual U {
      B(const T& x, const U& y) : T(x), U(y) {}
    };
    B b (x, static_cast<B&&>(y));  // Previously aborted casting x to T&
  }
  int main() {
    f([]{}, []{});
  }


6/20/13  [EDGcpfe/13734]
Microsoft C++ compatibility: __is_convertible_to(void, void)

In Microsoft C++ mode with microsoft_version >= 1800, the result of the
builtin-in type trait helper __is_convertible_to now produces "true" for two
void types (including when such types are const/volatile qualified).  Other
conversions to void types still produce "false" (contrary to the value implied
by the standard).


6/19/13  [EDGcpfe/14198]
C++/CLI: Type of BeginInvoke/EndInvoke

In C++/CLI mode, the front end predeclares BeginInvoke and EndInvoke methods
for delegate types.  However, previously it failed to record the type of the
"this" parameter for those generated members (which resulted in those members
being static).  This is now fixed.


6/19/13  [EDGcpfe/14199]
Unbounded loop on Microsoft mode typedef

In Microsoft mode, the size_t type is predeclared.  A typedef for size_t can
be created that uses the former declaration; for example:

  typedef size_t size_t;

However, that previously resulted in a circular type graph, which in turn
resulted in an unbounded loop.  This is now fixed.


6/19/13  [EDGcpfe/14203]
Abort mode on aggregate initialization with missing braces

In nonstrict C modes, the front allows the omission of braces on array
initializers.  For example:

  void g() {
    double z = 1.0;
    double az[2] = z;  // Allowed in nonstrict C modes.
  }

However, when such code contained a dynamic component (as in the example
above), the generated IL was invalid, which was likely to result in an abort
if the initializer was lowered (e.g., in C99 mode).  This is now fixed.

Furthermore, cases like these are now diagnosed as errors by default in
GNU C and Microsoft C modes (to match the GNU and Microsoft compilers).


6/18/13  [EDGcpfe/13977]
Severity of invalid attributes in GNU mode

Some invalid uses of attributes in GNU mode are now diagnosed with a warning
instead of an error.  Some of those cases are specific to the C++11 form of
attributes.  For example:

  struct S {};
  S* g() {
    return (S [[gnu::unused]]*)0;  // Previously an error; now accepted with
  }                                // a warning in GNU C++11 mode.


6/17/13  [EDGcpfe/14112]
Spurious correspondence error when namespace member used as template argument

When simultaneously compiling multiple translation units in configurations
the front end occasionally reported a spurious correspondence error on entities
(usually fields or variables) involving a template argument that is a type
from a namespace not enclosing the entity for which the error occurred.
This rare problem is now fixed.


6/17/13  [EDGcpfe/14196]
Failure to issue error on call of function with parameter pack based on alias

The front end failed to issue an error (or to fail overload resolution)
for an invalid call of a function having a parameter pack that is based on
an alias template that does not use its parameter.  The failure to detect
an error could cause incorrect code generation (the argument type in the
call did not match the parameter type).  Now fixed.

  enum E {};
  template <class Z> using AE = E;
  template <class T> struct A {};
  template < class ... T > int f (A<T...>, AE<T> ... );
  int main() {
    f(A<int>(), 1);
  }


6/17/13  [EDGcpfe/13885]
Needed flag setting on lowered pointer-to-member constant

In certain cases, the needed flag was incorrectly set to FALSE on lowered
pointer-to-member constants.  Now fixed.  For example (with --c++11):

  struct A {
    int x = 37;
    int A::*const& pd = &A::x;
  };
  struct B {
    A a = A(A{A()});
  };
  int main() {
    B b;
  }


6/17/13  [EDGcpfe/13811]
GNU C++ compatibility: override and final

In GNU C++ mode with gnu_version >= 40700 the front end now accepts the
"override" and "final" modifiers on virtual function declarations even when
C++11 mode is not enabled (a warning is issued in those cases).  See also the
entry of 3/8/12 for EDGcpfe/12742 and EDGcpfe/12360.


6/17/13  [EDGcpfe/14194]
GNU C++ compatibility: prototype instantiation of noexcept no longer deferred

In g++ mode, the prototype instantiation of noexcept specifiers was
deferred if function prototype instantiations were deferred.  This could
cause an internal error in C++-generating back end versions (in
gen_exception_specification) if the function was never used in a way
that would cause its noexcept specification to be needed.  In addition,
this did actually not match the behavior of g++.  Prototype instantiations
of noexcept specifiers are now done in all cases.  This change could
also affect non-g++ mode if the --defer_parse_function_templates option
was explicitly specified.

  template<class X, class Y> struct A {
    X x;
    Y y;
    void f(int a, int b) {}
    void g(A& p) noexcept(noexcept(f(x, p.x)) && noexcept(f(y, p.y))) { }
  };


6/17/13  [EDGcpfe/14195]
Definition of copy assignment operator

The front end previously never considered an assignment operator with a
const/volatile qualified this parameter to be a copy assignment operator,
unless Microsoft, GNU, or Sun mode was enabled.  The committee has since
clarified (via its resolution of Core issue 574) that such assignment
operators can be valid copy assignment operators, and the front end now
reflects that decision.  For example:

  struct S {
    S& operator=(S const&) const;
  };

Previously the user-declared assignment operator of S was not considered a
copy assignment operator, and the front end therefore generated another
such operator.  Now, the front end no longer generated the extra operator.


6/16/13  [EDGcpfe/11571]
Internal error on pack reference in rescan of template default argument

An internal error could occur (in get_curr_template_params_and_args) on
the rescan of a dependent template default argument that contained a
pack expansion.  Now fixed.

  template <class ...T> struct A {
    template <class U = int[sizeof...(T)]> struct B {};
  };
  A<int>::B<> ab;


6/16/13  [EDGcpfe/14110]
Spurious error on pack expansion in template nontype default argument

A template nontype template argument containing a top-level (e.g.,
non-parenthesized) pack expansion was not accepted.  Now fixed.

  template<typename ... T> struct S {
     template<int a = sizeof...(T)> void f() { }
  };


6/14/13  [EDGcpfe/14180]
Missing diagnostic on invalid member overloading with ref-qualifiers

In C++11, member functions can include ref-qualifiers (see entry of 4/23/13
for EDGcpfe/8627).  The standard does not permit overloading two member
functions with the same name and parameter types but with one having a
ref-qualifier and the other not.  Previously, the front end incorrectly
treated const and volatile qualifiers on the member function as part of the
"parameter types", thereby failing to diagnose certain invalid cases.
For example:

  struct S {
    int f() const;
    void f() &;      // Previously silently accepted in C++11 mode.
  };                 // Now an error.

This is now fixed.


6/14/13  [EDGcpfe/14139]
Spurious error in C++11 constant expression with possibly-overloaded || or &&

The front end gave a spurious error on an expression of the form
"1 || nonconstant" or "0 && nonconstant" in a constant expression in
C++11 mode if there was some previous declaration of an operator|| or
operator&& (which made the operation seem potentially overloaded).
Now fixed.

  struct S {
    S operator||(S const&);
  };
  int f();
  int main() {
    int a[1 || f()];  // Now accepted
  }


6/14/13  [EDGcpfe/14138]
User-defined conversion allowed on integer nontype template argument

The check for allowed conversions on a C++11 nontype template argument
passed for an integer template parameter failed to allow a user-defined
conversion at the end.  Now fixed.

  struct A {
    constexpr A(int i) : n(i) { }
    constexpr operator int() { return n; }
    int n;
  };
  template<int> struct B { };
  constexpr A a = 0;
  B<a> ba;  // Formerly got a spurious error


6/14/13  [EDGcpfe/14129]
Microsoft compatibility: Reference deduction with array of unknown bound

The Microsoft C++ compiler accepts the following case:

  template<class T> void f(T&&);       // (1)
  template<class T> void f(const T&);  // (2)
  extern const char x[];
  void g() {
    f(x);  // (3)
  }

Previously, the front end selected template (2) for call (3), and that
resulted in an error because deduction produces a reference to a array of
unknown bound.  Now, the front end modifies that behavior in Microsoft mode
in the following two ways:
  a) substitution of the lvalue reference of template (2) turns the array of
     unknown bound into an array of length one (this appears to match the
     Microsoft behavior for other cases), which removes template (2) from the
     list of callable candidates.
  b) when substituting T&& with an array of unknown bound, no error is
     issued.
With these changes, the example above is now accepted (in Microsoft mode
only).


6/14/13  [EDGcpfe/13794]
Microsoft compatibility: Parameter with array type in for-each loop

Microsoft allows a parameter with an array type as the collection variable
in a for-each loop, and now so do we.  For example (with --microsoft):

  void f(int x[10]) {
    for each(int i in x) {}
  }


6/14/13  [EDGcpfe/14174]
VTT param missing in some subobject region table entries (IA-64 ABI only)

In cases where a function returning an object is used to initialize
a base class and that class has virtual bases, the exception handling
region table entry generated to invoke the subobject destructor was
missing the VTT pointer, causing undefined behavior at run-time in releases
prior to 4.7 and a compile-time assertion failure (in make_region_table_entry)
in release 4.7.  This is now fixed.  In the following example, the exception
handling routines had invoked _ZN1AD2Ev with a single argument but now invoke
it with the VTT argument as well (with -x):

  struct X {};
  struct A : virtual X {
    ~A() { while (0); }
  };
  A f() { return A(); }
  struct B : A {
    B() : A(f()) { throw 1; }
  };
  int main() {
    try {
      B b;
    } catch (...) {}
  }


6/14/13  [EDGcpfe/10299]
Deprecated conversion from string literal to "char *"

The deprecated conversion from a string literal to "char *",
deprecated in C++98 and C++03 and removed altogether in C++11, is now
treated as a distinct feature with its own control variable and macro.
The variable deprecated_string_literal_conv_allowed controls the
feature.  It is enabled in pre-C++11 C++ mode, and in Microsoft, GNU,
and Sun modes.  It is disabled in strict C++11 mode.  In default C++11
mode, the macro DEFAULT_DEPRECATED_STRING_LITERAL_CONV_ALLOWED gives
the setting.  The command-line option --[no_]deprecated_string_conv
can be used to override or confirm the default.  Also, a warning is
now issued for the conversion in C++11 mode (when the conversion is
enabled) and in g++ mode with gnu_version >= 40200.

  char *p = "abc";  // Now gets an error or warning in some modes


6/14/13  [EDGcpfe/14173]
Preserve static_cast to identical type in more cases in Microsoft/Sun modes

The processing for static_cast in Microsoft and Sun modes now
preserves a do-nothing cast in the IL in more cases, in particular
cases where the operand is an rvalue.

int main() {
  int i = 5;
  i = static_cast<int>(i / 5);  // Cast now preserved
}

The front end discards casts in some modes because the compilers being
emulated seem to discard those casts, and it's hard to get the same
semantics without also discarding the cast.  This conflicts, however,
with the desire of applications that do source analysis to get the entire
original program.  While we aren't able to eliminate the problem entirely,
this change preserves more of the casts that appear.


6/14/13  [EDGcpfe/13377]
Microsoft compatibility: Instantiated pointer-to-member functions

A change made in version 4.5 (see EDGcpfe/12214 on 1/18/12) introduced
a regression on certain uses of pointer-to-member function types in
function template instantiations in Microsoft mode.  This could result in
an "unexpected function type" diagnostic on the instantiation of function
template #1 in the example below.  Now fixed.

  template <typename T> struct A {
    template <class U> static char f(void(U::*)(void));  // #1
    template <class U> static char f(...);  // #2
    static const bool value = sizeof(f<T>(0)) == sizeof(char);
  };
  class C {};
  int main(){
    bool b = A<const C>::value;
  }


6/13/13  [EDGcpfe/13783]
GNU C++ compatibility: Throw expressions in templates with exceptions disabled

In GNU C++ mode with exceptions disabled, the front end now accepts throw
expressions in prototype instantiations.  For example:

  template<class T> void f() {
    throw 1;  // Accepted during prototype instantiations even if
  }           // exceptions are disabled in GNU C++ mode.
  template void f<int>();  // At this point the throw expression triggers
                           // an error in GNU mode with disabled exceptions.


6/13/13  [EDGcpfe/14177]
Needed flag processing of lowered delegating constructors/destructors

As part of the changes made for delegating constructors (see the Changes
entry for [EDGcpfe/7689,EDGcpfe/12842]), in IA-64 ABI configurations,
lowered delegating constructors/destructors alternate entry points
(which are routines that invoke either the complete or the subobject
constructor/destructor at run-time) are created whenever exceptions are enabled
for classes that have virtual bases.  Previously these routines had been marked
as "needed" when they were in fact unused.  For example (with --c++11):

  struct A {
    ~A();
  };
  struct B : virtual A {
    B(int i) : A() {}
  };
  int main() {
    B b(0);
  }


6/13/13  [EDGcpfe/12021]
Value categories

We have implemented the C++11 concept of "value categories" (see N3055).
This adds the concept of "xvalues" (formerly called "rvalue reference
objects" in the front end), which are eXpiring values created by
certain rvalue reference operations (e.g., a call of a function
returning an rvalue reference type).  To the end-user of the front end,
the visible differences are:

1)  Operations that return rvalue references to function type now return
function lvalues, not rvalue pointers-to-functions.  Rvalue references
to function types can now bind (only) to function lvalues.
2)  The "?" operator produces an xvalue result if its second and third
operands are xvalues of the same type.
3)  The "," operator produces an xvalue result if its second operand
is an xvalue.
4)  Member selection (x.y) and pointer-to-member selection (x.*y) now
produce an xvalue result if the class object is an xvalue.
5)  Casts to rvalue reference types now accept the proper kinds of
operands, whether lvalues, xvalues, or prvalues.
6)  Non-class xvalues can now have cv-qualified types.
7)  Xvalues need not have complete types.
8)  Xvalues have dynamic type, and typeid applied to an xvalue of
polymorphic class type is now evaluated at runtime.

Implementation of this feature required some fairly significant changes
in the expression-processing files (expr.c, exprutil.c, overload.c, and
to some extent folding.c).  In particular, we chose to update the names
of many routines and fields to match the new terminology (for example,
conv_lvalue_to_rvalue became conv_glvalue_to_prvalue).  This may cause
extra work for those porting customer-written extensions to the new version.
However, we felt that in the long term it was better to use the more
modern and precise terminology in the front end.  Most of the changes
in customer code should be simply mechanical renaming of routine names,
though one does also have to think about what to do with xvalues (and
the new names are reminders of that).

The IL is largely unchanged.  The is_xvalue flag added in version 4.7
is now more widely used, and now the expression nodes so marked are
essentially funny lvalues rather than funny rvalues.  That is, xvalue
nodes are considered descriptions of objects in memory, which have
addresses like lvalues, rather than descriptions of values as they
formerly were.


6/12/13  [EDGcpfe/14172]
Assertion failure in constant_value_at_address with reinterpret_cast

The folding routines failed to exclude consideration of a reinterpret_cast
in --c++11 mode when attempting to fold an address expression, resulting in
an assertion failure in constant_value_at_address while evaluating such an
expression.  This is now fixed.  For example:

  struct A {};
  struct B {};
  // The following initializer expression previously aborted in --c++11 mode:
  B b = reinterpret_cast<const B&>(static_cast<const A&>(A()));


6/12/13  [EDGcpfe/14073]
End position of GNU address-of-label expression

In GNU modes, the recorded end position of an address-of-label expression of
the form "&& label" was incorrectly set to the end position of the token
following the label.  This is now fixed.


6/12/13  [EDGcpfe/13581]
GNU C++ compatibility: friend class declarations and using-directives

The g++ compiler finds friend classes made visible by using-directives,
but starting with gnu_version 40000 such classes are only found if the
class name was not found in an enclosing scope.  The example below
was formerly ambiguous in g++ mode, but is now accepted in g++ mode when
gnu_version >= 40000.

  namespace N {
    struct A {
      friend struct D;
    };
  }
  using namespace N;
  struct D;
  struct B {
    friend struct D;  // Now okay when gnu_version >= 40000
  };


6/11/13  [EDGcpfe/14105]
Performance improvement for instantiation-dependence tests

In some cases involving variadic templates instantiated with very long and
complex lists of template arguments, the front end spent most of its time
determining whether those arguments were "instantiation dependent".  This
test has now been improved (by caching results and by short-circuiting the
computation in non-template contexts).  For some test cases this improves
compilation time over a hundredfold.


6/11/13  [EDGcpfe/14150]
Microsoft compatibility: elided constructor not needed

MSVC accepts the example below, apparently because the template copy
constructor that would be needed (to copy a scoped_ptr<B> rvalue)
is elided and its existence is never checked for.  (If it were,
overload resolution would fail because a template constructor can't
be instantiated to produce a constructor that copies its own type
by value; such a constructor would be unusable, because passing its
argument would require a copy, which would require a call of the same
constructor, etc.)  We now accept this case in Microsoft mode.

  template<class T> struct scoped_ptr {
    scoped_ptr(scoped_ptr &);
    static scoped_ptr f();
    template<typename U> scoped_ptr(scoped_ptr<U> other);
  };
  class B {};
  class D : public B {};
  struct X {
    X(scoped_ptr<B>);
  };
  int main() {
    X x(scoped_ptr<D>::f());
  }


6/11/13  [EDGcpfe/14075]
Preservation of typedefs in result type of "?" on pointer types

The front end now preserves typedefs where possible in the result type
of a "?" operation whose second and third operands are pointer types.
For example (in C mode):

  typedef struct {
    int s;
  } my_struct;
  int main() {
    my_struct *ps1,*ps2;
    ps2 = 1 ? ps1 : (void *)0;  // my_struct typedef preserved in result type
  }


6/10/13  [EDGcpfe/2155,EDGcpfe/6663,EDGcpfe/12701]
Warning for potential data loss in numeric conversions

The front end now optionally issues a warning when an arithmetic value is
converted to a type with fewer significant bits or when a floating-point
value is converted to a non-floating-point type.  This behavior is
controlled by the configuration option DEFAULT_WARNING_ON_LOSSY_CONVERSION
(the default value for the global variable warning_on_lossy_conversion) and
by the command-line option --[no_]lossy_conversion_warning.  For example:

  int i;
  char c;
  void f() {
    c = i;   // Now optionally issues a warning for the conversion
  }


6/10/13  [EDGcpfe/13975]
Allow enumeration type in range-based for statement

A spurious error had been reported when a range-based for statement
had an enumeration type and there was no overloaded "operator !=" defined
for the enumeration type.  Now fixed.  For example (with --c++11):

  extern "C" int printf (const char *, ...);
  enum E { e1, e2, e3, X };
  E operator*(E e) { return e; }
  E begin(E e) { return e; }
  E end(E e) { return X; };
  E operator++(E& e) { return e = E(e+1); }
  int main() {
    for (auto e: e1) {
      printf ("%d ", e);
    }
  }


6/10/13  [EDGcpfe/14141]
Incorrect memory region used for allocation of module id in name mangling

As a result of the changes made for EDGcpfe/9428, memory allocated for
the module id of an individuated namespace incorrectly pointed to the
general memory region which could cause the pointers to be invalid after
a pre-compiled header file is restored.  A change has been made to allocate
the storage in the front end memory region.


6/7/13   [EDGcpfe/14143]
Excess elements in lowered array initializers with pointer-to-member type

During the lowering of initializers of arrays whose elements are
pointer-to-member types, in the IA-64 ABI, any non-specified elements are
filled with the proper lowered constant (i.e., -1).  The computation of the
number of existing elements may have been incorrect in some cases, leading to
an initializer with more elements than the array.  For example, with --g++:

  struct A {
    int m;
  };
  typedef int A::*PDM;
  PDM x[] = {[3] = &A::m};


6/7/13   [EDGcpfe/14114]
Un-lowered "zero" constants can escape to back end with designators

In cases where designated initializers are used to initialize arrays
whose element types require lowering (e.g., complex types, pointer-to-members),
the repeated "zero" constant under the generated ck_init_repeat had not been
lowered.  For example, with --g++:

  struct A {
    int m;
  };
  typedef int A::*PDM;
  PDM x[] = {[3] = &A::m};
  _Complex double y[] = {[3] = 0.0i};


6/5/13   [EDGcpfe/14126]
Performance regression in complex macro expansion

The change for EDGcpfe/11932 below (part of version 4.4) introduced a
significant performance degradation in certain very complex macro
expansions, such as might be encountered using the Boost preprocessing
library.  This is now fixed.


6/5/13   [EDGcpfe/14137]
Missing implicit-step flag on base class cast under rvalue reference cast

The implicit_step_of_explicit_cast flag was not set on the top base class
cast under an eok_ref_cast node for an rvalue reference cast.  That
caused incorrect C++-generating back end output for cases like this one.
Now fixed.

  struct A {};
  struct B : A {};
  struct C : B {};
  int main() {
    C c;
    A &&r = static_cast<A&&>(c); // Was output as static_cast< A &&>((A)c)
  }


6/4/13   [EDGcpfe/14119]
Incorrect lowered code on conversion function call result bound to rvalue ref

In cases where lowering modifies a call to store the returned value in
an additional parameter, certain cases had resulted in the cv-qualifiers
for the added argument to be incorrect.  Now fixed.  For example, with --c++11:

  struct A {
    A(const volatile A&);
  };
  struct B {
    operator A();
  };
  const volatile A &&r = B();


6/4/13   [EDGcpfe/5457]
Use hexadecimal floating-point constants in generated code

A new configuration macro, USE_HEX_FP_CONSTANTS_IN_GENERATED_CODE, has been
introduced to control whether floating-point values should be emitted as
hexadecimal floating-point constants (when the macro is TRUE), or as they had
been, as decimal floating-point constants (when the macro is FALSE) in
generated code.  Using hexadecimal floating-point constants has the advantage
of requiring one less floating-point to decimal conversion in the front end
and one less decimal to floating-point conversion by the back end (thereby
increasing the likelihood that the floating-point value internally
represented in the front end is the value that is used at run-time).
Of course, this can only be used if the back end compiler supports
hexadecimal floating-point constants (a C99 feature).  The default value for
USE_HEX_FP_CONSTANTS_IN_GENERATED_CODE is FALSE.

In this example, with --c99, with a gcc back end, had produced the output
string "0xf.fffffffffffffffp+16380" and now produces the output
string "0xf.ffffffffffffffep+16380" (when
USE_HEX_FP_CONSTANTS_IN_GENERATED_CODE is TRUE):

  extern int printf(const char *,...);
  int main() {
    long double ld = 0x0.fffffffffffffffep+16384L;
    printf("%La\n", ld);
  }


6/3/13   [EDGcpfe/13617]
Spurious error on incomplete base class in class template in Microsoft mode

The front end approximates the behavior of Microsoft compilers with respect to
dependent base classes by performing a "nonreal instantiation" of such base
classes (i.e., an instantiation where the template parameters are treated as
generic types).  However, that process could lead to incomplete base classes of
non-dependent types, which previously triggered a spurious error.  For example:

  struct I;  // Incomplete class
  template<typename T, typename U> struct S: U {};
  template<typename T> struct X: S<T, I> {};
    // S<T, I> is a dependent class for which the front end performs a
    // nonreal instantiation.  However, S<T, I> has a base class of type I,
    // which is nondependent and previously triggered an error.

This is now fixed: In Microsoft mode incomplete bases classes are now permitted
in nonreal instantiations of class templates.


5/31/13  [EDGcpfe/10692]
typeid of polymorphic xvalue is determined at runtime

The value of a typeid operator applied to an xvalue of polymorphic type
is now determined at runtime.


5/30/13  [EDGcpfe/14088,EDGcpfe/14113]
Microsoft compatibility: Initializer lists

In Microsoft mode with microsoft_version >= 1800 initializer lists are now
enabled by default (i.e., even when C++11 mode is not enabled).  In addition,
the front end can now also use the <initializer_list> header supplied with
the Microsoft compiler (which required recognizing an alternative signature
for the initializer_list constructor).
The <initializer_list> header supplied with the front end has also been updated
to more closely match that of the Microsoft compiler when compiling in
Microsoft mode (it is not an exact match, however).  Enabling this required the
introduction of a new macro __EDG_CONSTEXPR_ENABLED__ that is predefined by
the front end in modes that enable the C++11 constexpr feature.
(The entry of 8/26/12 for EDGcpfe/9170 describes the introduction of
initializer lists in C++11 mode.)


5/28/13  [EDGcpfe/14089]
Abort on mem-initializer with destructor when exceptions are disabled

The initializer changes of version 4.5 (see entries for EDGcpfe/9170)
introduced a bug in C++ modes that disable exception handling (including
default C++ mode), causing IL lowering to abort (in lower_dynamic_init) when
processing a mem-initializer for a member whose type has a nontrivial
destructor.  For example:

  struct D { ~D(); };
  struct S {
    D d;
    S(D x): d(x) {}  // This previously triggered an abort in lowering when
  };                 // exception handling is disabled.

This is now fixed.


5/28/13  [EDGcpfe/13399]
C++-generating back end fails to render "static" on in-class specialization

In Microsoft C++ mode, the front accepts in-class specializations of static
member functions, but the C++-generating back end did not render any "static"
specifier appearing on the specialization.  For example:

  struct S {
    template<class T> static void f(T x);
    template<> static void f<int>(int x);
                // Previously, "static" on the specialization was not
  };            // rendered by the C++-generating back end.

This is now fixed (by correctly recording the declared storage class in the
IL).


5/24/13  [EDGcpfe/14040]
Generated default constructor with const members

Previously, in C++11 mode, the front end generated an ordinary default
constructor definition for classes with uninitialized const members.  Now,
the default constructor is defined as deleted (except in GNU C++11 mode,
since GCC does not appear to implement that C++11 requirement).  For example:

  struct A {
    constexpr int f() const { return x+1; }
    int const x;   // Uninitialized const field means the generated default
  };               // constructor should be "= delete" in C++11 mode.
  int x[A().f()];  // Previously accepted in C++11 mode; now an error.


5/23/13  [EDGcpfe/14084]
Environment variable for system default locale name

The normal mechanism for constructing the system default locale name (in
configurations with NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE and
EDG_WIN32 set to TRUE) does not work for Unicode-only locales like Hindi,
which do not have a native multibyte character set, resulting in an
assertion failure in host_envir_early_init.  In order to provide a
workaround that is available in the field, the front end now checks for
an environment variable named EDG_DEFAULT_SYSTEM_LOCALE and, if set, uses
that value for the system default locale name instead of constructing one
from Windows system calls.


5/23/13  [EDGcpfe/14082]
Microsoft compatibility: Static data members in unions

In Microsoft mode, the front end now accepts static data member declarations
in unions.  For example:

  union U {
    static int count;  // Previously an error in Microsoft mode; now okay.
  };

This is standard in C++11, but not in C++03 (it is now, however, accepted in
all Microsoft C++ modes; not just Microsoft C++11 mode).


5/23/13  [EDGcpfe/14020]
Generated default constructor incorrectly treated as noexcept

The front end sometimes incorrectly treated a generated default constructor as
being known not to throw any exceptions ("noexcept").  For this to occur, the
class required a subobject type containing a nonstatic data member initializer
and a generated default constructor that does in fact throw an exception.
For example:

  struct X { X() { throw 1; } };
  struct F {
    X x;
    int i = 2;
  };
  struct S { F f; };
  int main() {
    try {
      S s;
    } catch (...) {}
  }

In this example, F has a nonstatic data member initializer and a generated
default constructor that might throw an exception.  However, the generated
default constructor of S was incorrectly recorded as throwing no exception,
which in turn triggered a call to terminate() at run-time (before the
exception could be caught in main()).  This is now fixed.


5/23/13  [EDGcpfe/14087]
Some local temporaries not marked with is_local_to_function

Some local temporaries generated by the front end proper (as opposed
to IL lowering), e.g., for compound literals, were not marked with the
is_local_to_function flag even though they are entered in a function-local
scope.  Now fixed.


5/21/13  [EDGcpfe/14080]
Spurious warnings about unreferenced deleted functions

Functions defined with "= delete" cannot validly be referenced, but in some
cases the front end issued a warning about them not being referenced.
For example:

  namespace {
    void f() = delete;
  }
  // Previously the front end issued an unhelpful warning about f being
  // declared without being referenced.

This is now fixed.


5/21/13  [EDGcpfe/14000]
Visibility of member enumerator constants declared outside their parent class

In some modes (including C++11 mode), an enumeration can be partially declared
in a class (in C++11, using opaque enum declarations), with the associated
enumerator constants declared after the class definition.  In the case of
unscoped enumerations, the front end treats the enumerator constants as
members of the class, but it previously failed to look up the constants in
some contexts where class members ought to be visible.  For example:

  struct S {
    enum E: int;
    E f();
  };
  enum S::E: int { e };
  S::E S::f() {
    return e;  // Previously an error because e was not found.
  }

This is now fixed.  Note that the C++11 standard is currently unclear about
how such enumerator constants should be treated (this is Core issue 1485): It
is likely that the C++ standards committee will in the future decide on
something different from what the front end currently implements.  (See also
the entry for EDGcpfe/12237 on 2/15/12.)


5/21/13  [EDGcpfe/14077]
C++/CLI: static conversion function allowed for functional-notation cast

C++/CLI has a rule that a functional-notation cast finds only constructors
and not conversion functions.  However, it turns out MSVC also finds
static conversion functions.  Now fixed.

  public value struct B {
    int x;
  };
  public ref struct A {
    static operator B(A^ );
  };
  int main() {
    A^ z;
    B b = B(z);  // Accepted now
  }


5/21/13  [EDGcpfe/14065]
Virtual base classes and generated move constructors

Previously, no move assignment operator was generated for a class with a
virtual base class.  This constraint has now been removed.  For example:

  struct A { A(); };
  struct B : virtual A {};
  typedef B& (B::*PMF)(B&&);
  PMF p = &B::operator=;  // Now accepted.  Previously an error since no
                          // matching operator= was generated.

(In GNU C++ mode with gnu_version < 40800 the prior behavior is maintained
since that matches corresponding versions of GCC.)


5/21/13  [EDGcpfe/14065]
Failure to make generated assignment operator "= delete"

In C++11 mode, the front end sometimes failed to mark a generated copy
assignment operator as being a "deleted" member (i.e., as if it has been
declared "= delete", and therefore not invokable).  Specifically, the C++11
standard specifies that a generated copy assignment operator should be
"deleted" if the user declared a move constructor for the class, but the
front end failed to enforce that if the class also declared a copy
constructor.  For example:

  struct S {
    S(S const&);
    S(S&&);  // The generated copy assignment operator should be "deleted";
  };         // previously, that was not enforced.
  void f(S x, S y) {
    x = y;   // Previously, this was erroneously accepted.
  }

This is now fixed.  (In GNU C++ mode with gnu_version < 40700 the prior
behavior is maintained since that appears to match corresponding versions of
GCC.)


5/21/13  [EDGcpfe/14081]
Assertion failure when lowering typeid operation

Previously, a typeid operation on a lowered nullptr_t type had resulted
in an assertion failure (in get_typeinfo_var).  This is now fixed.  The
likelihood of this abort increased in the 4.6 release when typeid
operations were folded (thereby increasing the likelihood of orphaned
abk_typeid constants that are lowered after types have been lowered).
For example (with --g++ --c++11):

  namespace std {
    typedef decltype(nullptr)     nullptr_t;
    struct type_info {
      bool operator==(const type_info&) const;
    };
  }
  void f() {
    const decltype(nullptr) mynull = 0;
    char c[bool(typeid(nullptr) == typeid(mynull))];
  }


5/21/13  [EDGcpfe/14023]
Microsoft compatibility: Alignment reduction ignored

In Microsoft mode, an attempt to reduce the alignment of a class type using
the __declspec(align(...)) attribute is now ignored (except for C++/CLI
managed class types).  For example, assuming a 4-byte aligned int type:

  struct I3 { int x, y, z; };
  struct __declspec(align(2)) CIC {
    char c1;
    I3 i;  // Type requires 4-byte alignment: attribute "align(2)" ignored.
    char c2;
  };

Previously, CIC was given an alignment requirement of 2; now it is 4.
Note that the behavior of "#pragma align(...)" has not changed.


------------------------------------------------------------------------------
Version 4.7, May 21, 2013

5/20/13  [EDGcpfe/14074]
Ending position of macro replacement range (IL CHANGE)

In configurations with RECORD_MACROS_IN_IL and EXTRA_SOURCE_POSITIONS_IN_IL
set to TRUE, the ending position in the a_macro replacement_text_range
reflected the position of the terminating newline of the definition.  This
has now been changed to reflect the end position of the last token in the
definition.  For example, with the following definition,
replacement_text_range.end.column was previously 18 and is now 11.

  #define M 1 /* */


5/17/13
IL version number changed to 4.7

5/17/13  [EDGcpfe/13643]
Variadic template issue with member function templates and enclosing packs

The front end did not properly handle variadic member function templates
of variadic classes that made use of pack expansions that reference
packs of both the member template and the enclosing class.  The resulting
pack expansion did not contain the proper types from the enclosing
class.  That resulted in a spurious error on the assignment in the
example below.  Now fixed.

  template <class ... T> struct A {};
  template <class T, class T2> struct B {};
  template <typename... T> struct C {
    template <typename... U> static A<B<T, U>...> f(U&& ... args);
  };
  class D {};
  int main() {
    D d;
    C<short , int, D> t;
    A<B<short,short>, B<int,int>, B<D,D&>> ab;
    ab = t.f((short)0,0,d);
  }


5/16/13  [EDGcpfe/14039]
Abort on aliases templates when debug output enabled

When fine-grained debug output was enabled (e.g., "-d4"), the front end was
likely to abort in f_skip_typerefs ("NULL referenced type") while producing
the tracing output for the instantiation of an alias template.  This is now
fixed.


5/16/13  [EDGcpfe/13992]
GNU C++: Nonstandard anonymous structs and constexpr constructors

The folding process for constexpr constructor references did not correctly
handle the nonstandard anonymous structs allowed by GNU C++ mode.
Now fixed.  This example formerly got an assertion failure in folding.c
(in i_fold_constexpr_ctor):

  struct B {
    struct /* unnamed_1 */ {
      int h;
      struct /* unnamed_2 */ {
        union /* unnamed_3 */ {
          unsigned char i;
          int j;
        };
        int k;
      };
    };
    int l;
    constexpr B(): h(1), i(2), k(3), l(4) {}
  };
  constexpr B b;


5/15/13  [EDGcpfe/14038]
Spurious error on use of type traits helper in Microsoft mode

Version 4.5 introduced a change that caused certain nonreal classes used as
base classes to be have actual instantiations done on them in Microsoft mode
(see entry of 5/15/12 for EDGcpfe/12786).  This could result in spurious
errors in certain uses of type traits helpers that require a complete type.
For example:

  template<bool V> struct S {};
  template<typename, typename T>
    struct X : public S<!__is_abstract(T)> {};
  struct I;
  template<typename T>
    struct R : X<T, I> {};  // Previously triggered an error because
                            // __is_abstract is applied to the incomplete
                            // type I.  Now accepted.

This is now fixed.


5/15/13  [EDGcpfe/13650]
Abort on static_assert in some configurations

In configurations that generate source sequence entries (e.g., when using the
C++-generating back end) and eliminate unneeded IL entries, the front end
could abort (for example with a "IL entry write-read difference" internal
error) if a static_assert construct referred to an entity that was not
otherwise used.  For example:

  const bool b = true;
  static_assert(b, "fail");  // Previously triggered an internal error in
                             // some configurations.

This is now fixed.


5/15/13  [EDGcpfe/14037]
Invalid IL/abort with pragma in lambda expression

The front end sometimes incorrectly processed pragmas appearing in lambdas
with implicit captures.  In particular, in configurations that generate
source sequence entries (e.g., when using the C++-generating back end), the
source sequence entry associated with the pragma could end up pointing to
the wrong IL entry, which in turn was likely to produce an abort later on.
For example:

  struct S {
    int f();
    int g() {
      return [=]{
  #pragma test_immediate
       return f();  // Implicit capture of "this".
      }();
    }
  };

The C++-generating back end previously aborted (in different places
depending on details of the configuration) when processing this example.
This is now fixed.


5/15/13  [EDGcpfe/13981]
Constant member access in class object initialized to empty aggregate

A logic error caused the front end to treat a member access within a const
class object that is initialized to an empty aggregate as a non-constant
expression.  This is now fixed.  For example:

  constexpr struct A { int i; } a = { };
  constexpr int j = a.i;  // Previously incorrectly diagnosed as an error


5/14/13  [EDGcpfe/14036]
C-generating back end: incorrect naming of promoted base class member

In configurations in which tail-padding reuse is enabled (see the entry for
EDGcpfe/11008 below), the C-generating back end put out incorrect code when
referring to a member of a promoted base class subobject when the reference
is taking the address of a member of a namespace-scope object.  This is now
fixed.  For example:

  struct ZZZ {
    int x;
    virtual void f() {}
  };
  struct A : ZZZ {
    int* ip = &x;
  };
  A a;
  int main() {
    if (a.ip != &a.x)  // Incorrect code generated for &a.x
      return 1;
  }


5/14/13  [EDGcpfe/14025]
GNU C++ mode abort on assignment to lvalue cast to void

The front end aborted in exprutil.c (in conv_rvalue_expr_to_lvalue) on
processing an assignment to a variable cast to void (which is
invalid and should get an error) in g++ mode with gnu_version
less than 40000.  Now fixed (an error is issued).

  int main() {
    int i;
    (void)i = 0;
  }


5/14/13  [EDGcpfe/14033]
constexpr function calls not folded in prototype instantiations

It appears that common practice (g++, clang) for constexpr is not to
fold constexpr function calls in prototype instantiations of templates.
At the least, it appears that no template instantiations are kicked
off to instantiate the bodies of constexpr templates.  Such an
instantiation was, in our front end, the cause of a spurious error
when the g++ 4.7 <tuple> header is compiled with no deferral of
prototype instantiations, e.g., in C++-generating back end versions.
Now, we suppress constexpr call folding in prototype instantiations
except in constant expressions.  The following example gets no
error now because f is not instantiated:

  template <class T> struct X {
    T arr[1];
    constexpr operator int() { return 1; };
  };
  template <class T> constexpr int f() {
    return X<T>{};
  }
  template <class T> struct A {
    int i = f<void>();
  };


5/14/13  [EDGcpfe/14032]
Abort after error on defaulted default constructor

In some unusual cases, the front end could abort during an IL walk (e.g., in
walk_tree_and_set_needed) after issuing an error about being unable to
determine the exception specification for a defaulted default constructor.
For example:

  template <class T> struct A {
    constexpr A(int i) {}
    A() = default;
    A<B> pmf = &B::f;
    void g() { A<short> a(37); }
  };

After issuing various errors, the front aborted on this example (in some
configurations) while determining needed flags.


5/13/13  [EDGcpfe/13426]
Missing diagnostic on default template argument added outside of class

The front end failed to issue a diagnostic on an attempt to provide
a default template argument on the definition of a member function
template outside of its class (default template arguments for function
templates is a C++11 feature).

  template <class T> struct A {
    template <class U> void f();
  };
  template <class T> template <class U = int> void A<T>::f() {}


5/11/13  [EDGcpfe/13965]
C++11 constexpr: lvalue "?" can be folded if first operand value is constant

In C++11 constexpr folding, a "?" operation that returns an lvalue can now
be folded if its first operand folds to a constant and the selected
operand (second or third) has a constant address.

  struct A {
    int i;
    constexpr A(int p) : i(p) {}
    constexpr const int &f(int b) { return b ? i : i; }
  };
  constexpr A a{2};
  constexpr int j = a.f(1);  // Now folded to 2


5/11/13  [EDGcpfe/14018]
Folding of comparison of variable address to 0/nullptr

A comparison of the address of a variable to a null pointer, e.g.,
"&x != nullptr", is now folded to a constant if the variable is not
extern.

  int a;
  int x[&a != 0];  // Now accepted as a constant expression in C++11 mode


5/11/13  [EDGcpfe/13984]
Microsoft C++11 mode: null or conversion to void * in nontype template argument

The changes for C++11 constexpr tightened up the allowed conversions for
nontype template arguments.  However, it turns out MSVC allows some
additional conversions.  The front end now allows conversion from
a null pointer constant to a pointer, and conversion from a different
pointer type to void *, in a nontype template argument.

  template<void *n> class A {};
  void f() {}
  typedef A<&f> T;  // Okay now
  typedef A<0> T2;  // Okay now


5/10/13  [EDGcpfe/14016]
Binding lvalue reference to rvalue allowed in GNU C++ prototype instantiation

The front end now allows an lvalue reference (to non-const) to bind to
an rvalue in a template prototype instantiation in GNU C++ mode,
because g++ appears not to do that check until a real instantiation.

  template<class T> void f(bool &rb = false) {}  // Now accepted;
                                                 // error on actual
                                                 // instantiation


5/10/13  [EDGcpfe/14015]
Template initializer-list constructor

The front end formerly did not allow a template to be an initializer-list
constructor, which gets special special treatment in list-initialization.
Now, it can be.

  #include <initializer_list>
  template <class T> struct A {
    template <class U> A(std::initializer_list<U>);
  };
  A<int> v = { 1, 2, 3 };  // Now accepted


5/10/13  [EDGcpfe/13968]
Abort on use of member function name as a GNU asm operand

In GNU C++ modes, the front end triggered an internal error in exprutil.c
("extract_node_from_operand: converting unexpected operand kind") when the
name of a nonstatic member function appeared as a GNU-style asm operand.
For example:

  struct C { void f(); };
  void C::f() { 
    asm ("" : : "m" (C::f));  // Previously triggered an internal error;
  }                           // now an ordinary error is issued.

This is now fixed (an ordinary error is issued).


5/9/13   [EDGcpfe/10974]
Partial ordering of nonstatic members. vs non-members (core issue 532)

Core issue 532 specifies that nonstatic members can be ordered relative
to non-members.  We now implement this feature in C++11 mode.

  struct A { };
  template<class T> struct B {
    template<typename R> int operator*(R&); // #1
  };
  template<typename T, typename R> int operator*(T&, R&); // #2

  // The declaration of B::operator* is transformed into the equivalent of
  // template<typename R> int operator*(B<A>&, R&);

  int main() {
    A a;
    B<A> b;
    b * a; // calls #1
  }


5/9/13   [EDGcpfe/14012]
SFINAE rescan handling of variably-sized array new

In general, the SFINAE rescan of a dependent variable-sized array new
did not work correctly, with the consequence that deduction always
failed.  Now fixed.

  struct A {
    int f();
  };
  template <class T> auto f() -> decltype(new int[T().f()]) { return 0; }
  int main() {
    f<A>();
  }

In addition, a change has been made in mangling to mangle the expression
that results from a variable-sized array type (previously an assertion
check prevented mangling of variable-sized array types).


5/8/13   [EDGcpfe/13991]
Spurious error on constexpr constructor of class template

The C++11 standard makes a general exception for constexpr constraints in the
context of template instantiations: If a constraint is not satisfied, an
instantiation can still be valid, but it is not treated as "constexpr".
The front end previously ignored that exception for a constexpr constructor
that does not initialize each of its subobjects, which resulted in spurious
errors.  For example:

  template<typename T> struct S {
    T x;
    constexpr S() {}  // Missing initializer for member x.
  };                  // Previously an error for e.g. S<int>; now okay.

  S<int> si;
  constexpr S<int> csi;  // Still an error since the S<int>::S() constructor
                         // is not constexpr.

This is now fixed.


5/8/13   [EDGcpfe/14006]
Microsoft compatibility: spurious error in partial specialization

Version 4.5 introduced a change that caused certain nonreal classes used
as base classes to be have actual instantiations done on them in Microsoft
mode.  This could result in spurious errors on partial specializations
declared in such base classes when the partial specialization declaration
used a nontype template parameter of the enclosing class.  Now fixed.

  template <int I> struct A {
    enum { J = I };
    template <int K, int L> struct B;
    template <int K> struct B<K, J> {};
  };
  template <int I> struct C : A<I> { };
  int main() {
    C<1> c;
  }


5/8/13   [EDGcpfe/14001]
Elided braces in C++11-style aggregate initializers (Core issue 1270)

When C++11 generalized brace-enclosed initializers the allowance to elide
braces in aggregate initializers was not extended to the new contexts
allowing braced initializers.  For example:

  int x[2][2] = { 1, 2, 3, 4 };  // This has always been okay.
  int y[2][2]{ 1, 2, 3, 4 };     // This was originally disallowed in C++11,
                                 // but now it is permitted.

The C++ committee recently revisited its original decision, however, to deal
with Core issue 1270, and decided to permit brace elision in all aggregate
initialization contexts after all.  The front end now implements this in all
C++11 modes, except in GNU C++11 modes where gnu_version < 40800 (since the
corresponding GCC compilers do not accept elision in all contexts).


5/8/13   [EDGcpfe/13930]
GNU C++: statement expressions allowed in ctor-initializers

GNU statement expressions are now allowed in the ctor-initializers of
a constructor.

  struct A {
    int i;
    A() : i( ({ int j = 1; j; }) ) {}
  };


5/8/13   [EDGcpfe/13969]
Incorrect end position recorded for aggregate variable initialization

Versions 4.5 and 4.6 of the front end did not always correctly record the end
position of an initializer for an aggregate variable (in configurations with
EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE).  For example:

  char const str[] = "Message";  // The end position of the initializer was
                                 // previously incorrectly set to that of the
                                 // "]" token.

This is now fixed.  (See also EDGcpfe/13406 for a similar issue with scalar
variables.)


5/8/13   [EDGcpfe/14005]
Abort following SFINAE rejection of "new" of invalid type

The front end could abort with an assertion failure in expr.c, in
scan_new_operator, on a use of an invalid type with a "new" operator
in a SFINAE context.  That set up an expectation that an error
would be generated somewhere in the compilation, but of course
no error was issued because the invalid type appeared during
template deduction, and just caused deduction to fail.  Now fixed.

  struct A {
    typedef int ARR[];
  };
  template <class T> auto f(T p) -> decltype(new typename T::ARR) { return 0; }
  void f(...);
  int main() {
    f(A());
  }


5/8/13   [EDGcpfe/12944,EDGcpfe/13972]
Core issue 1402: Defaulted move constructors

The front end no longer "deletes" a defaulted move constructor just because
a subobject has no associated move constructor.  This is in accordance with
the C++ committee's Core issue 1402.  For example:

  struct S { S(S const&); };  // S has no generated move constructor since
                              // it has a user-declared copy constructor.
  struct G {
    S s;
    G();
    G(G&&) = default;
  };
  G g((G()));  // Previously an error in strict C++11 mode; now okay.

In this example, G's implicitly declared copy constructor is an "= delete"
member because a move constructor is explicitly declared.  Previously,
however, that move constructor was disabled because G has a field of type S
that doesn't have an associated move constructor.  The copy/move required to
construct the variable g therefore resulted in an error in strict C++11 mode
(in nonstrict mode, the copy/move construction was elided).  Now, the copy
constructor of S is deemed acceptable to implement the defaulted "move"
operation of G.

(See also the entry of 4/24/13 for EDGcpfe/13934, which documents the changes
for the other part of Core issue 1402: Ignoring move constructors and move
assignment operators that are both defaulted and deleted.)


5/8/13   [EDGcpfe/14007]
reinterpret_cast on pointer-to-member rules out constexpr call folding

A reinterpret_cast of a pointer-to-member-function constant followed by
a call of that function via a ".*" or "->*" operator is no longer
considered for constexpr call folding (it involves undefined behavior).
Formerly, a case like the following aborted in il.c, in
binary_operation_type_kind, when the front end attempted to fold the
call with the "wrong" argument type.

  struct A {
    constexpr int f(double d) { return d+1; }
  };
  int main() {
    A a;
    if ((a .* (int (A::*)(int))&A::f) (10) != 11) return 1;
  }


5/7/13   [EDGcpfe/13995]
Microsoft template/nontemplate copy constructor trick no longer needed

A mechanism that fiddled with the comparison of template and nontemplate
copy constructors in Microsoft mode has proved to no longer be needed
in recent versions, and is now turned off for microsoft_version 1600
and above.

  extern "C" int printf(const char *, ...);
  struct A {
    A() {}
    A(const A&) { printf("C1\n"); }
    template <class T> A(T&) { printf("C2\n"); }
  } a;
  int main() {
    (void)A(a);  // Prints "C1" for < 1600, "C2" for >= 1600
  }


5/7/13   [EDGcpfe/14002]
GNU C++ compatibility: Implicit noexcept

In GNU mode with gnu_version > 40800 destructors and deallocation functions
now have an implicit "noexcept" specifier if none is explicitly provided.
For example:

  struct D { ~D(); };
  static_assert(noexcept(((D*)nullptr)->~D()),
                "D::~D should be noexcept");  // Now accepted in some
                                              // GNU C++ modes.

See also the Changes entries for EDGcpfe/10617 and EDGcpfe/13566.


5/7/13   [EDGcpfe/13982]
Abort on folding of GNU __builtin_constant_p in constexpr function call

The GNU built-in function __builtin_constant_p was not properly handled
during evaluation of a constexpr function call, with the consequence that
the front end failed an assertion check in folding.c, in the function
fold_gnu_builtin_function_call_if_possible.  Now fixed.

  constexpr int f(int x) {
    return __builtin_constant_p(x) ? 1 : 2;
  }
  constexpr int i = f(3);


5/6/13   [EDGcpfe/13990]
GNU C++11 compatibility: Vector types and literal types

In GNU C++11 mode with gnu_version >= 40800, the front end now treats a
vector type as a literal type.  For example:

  typedef float __attribute((vector_size(4*sizeof(float)))) V4;
  constexpr V4 quad3D(float x, float y, float z) {  // Now accepted in some
    return (V4){ x, y, z, 0 };                      // GNU C++11 modes.
  }
  

5/6/13   [EDGcpfe/12021]
decltype applied to an xvalue returns an rvalue reference

In accordance with [dcl.type.simple]p4 of the C++11 standard, the decltype
operator applied to an xvalue now returns an rvalue reference type.

  struct A { A(); A(int); };
  int main() {
    A a;
    decltype((A&&)1) rr = a;  // Error now; can't bind rvalue ref to lvalue
  }


5/6/13   [EDGcpfe/13979]
Obscure error recovery problem with dependent "&" in constexpr template

An abort inside binary_operation in folding.c resulted from a declaration
of a dependent variable in a constexpr template (which is not allowed
and drew an error) followed by a use of "&" applied to that variable.
Now fixed.

  template <class T> constexpr int* f(T p) {
    constexpr T y = {1};
    return new int [ & y ];
  }


5/6/13   [EDGcpfe/13666]
Possible use of unset memory in copy_tokens_from_cache

alloc_cached_token did not clear some of the fields in the cached token entry.
This could lead to incorrect behavior, including copy_tokens_from_cache
not copying all of the expected tokens.  If the example below is compiled
with a version with INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL set to TRUE and
with source sequence lists, unset memory could be referenced from
copy_tokens_from_cache (whether this causes incorrect behavior for this
example depends on the contents of the unset memory).  Now fixed.

  #define Y(value) \
  _Pragma("some_pragma") \
            (value)
  int main() {
    int (*x)[256] = Y(0);
  }


5/3/13   [EDGcpfe/13642,EDGcpfe/13681]
__is_convertible_to

The implementation of the type traits helper function __is_convertible_to
has been reworked to more closely match the definition of std::is_convertible
in the C++11 standard library (the prior implementation was based on
ISO/IEC TR 19768, a pre-C++11 "Technical Report on C++ Library Extensions";
see the Changes entry of 3/21/06).  For example:

  struct F {};
  struct B { B(F&&) {} };
  static_assert(__is_convertible_to(F, B), "F should be convertible to B");

Previously, the static_assert in this example failed; now it is accepted.
The emulation of Microsoft's implementation of __is_convertible_to has also
been improved as part of this change.  For example:

  static_assert(__is_convertible_to(int&&, int&&),
                "Error in Microsoft mode");

This static_assert succeeds in C++11 mode, but now fails in Microsoft mode
(requires microsoft_version >= 1600 for the rvalue reference type): This
corresponds to the current behavior of the Microsoft compiler.


5/3/13   [EDGcpfe/13970]
User-defined conversion not considered on nested list initialization

Overload resolution failed to consider user-defined conversions on
nested list initializations in some cases.  Now fixed.

  struct A { A(int, int); };
  struct B { B(A); };
  struct C { C(B); };
  C c{{{1, 2}}};  // Now accepted


5/3/13   [EDGcpfe/12021]
First steps on value categories

As first steps on the way to implementing C++11 value categories, an
"is_xvalue" field has been added to expression nodes, and a number of
routines that used the term "rvalue reference object" in their names
now use "xvalue" instead (e.g., conv_rvalue_reference_object_to_lvalue
is now conv_xvalue_to_lvalue).


5/2/13   [EDGcpfe/13397]
Incorrect processing of nested variadic pack expansions

The front end could sometimes fail to properly handle a pack expansion
containing another pack expansion, resulting in spurious errors.  Now fixed.

  template <class ... Ts> struct A {};
  template <template <class ...> class... U, class... T> void f(U<T...>...){}
  int main() {
    A<int, int, int, int, int> a;
    f(a, a, a);
  }


5/2/13   [EDGcpfe/13967]
GNU attributes with C++11 syntax

In GNU C++11 mode with gnu_version >= 40800, the front end now maps C++11
attributes of the form "gnu::xyz..." to GNU-style attributes of the form
"xyz...".  For example:

  struct S { int i; } s [[gnu::aligned(16)]];

is now equivalent to

  struct S { int i; } s __attribute((aligned(16)));

in such GNU modes.


5/2/13   [EDGcpfe/13925]
Empty anonymous unions in strict mode

The front end now issues a discretionary error for empty anonymous unions in
strict C++ mode.  For example:

  struct S {
    union {};  // Now an error by default in strict C++ mode.
  };


5/2/13   [EDGcpfe/13961]
Problems with implicitly-initialized elements of constexpr arrays

The front end incorrectly handled implicitly-initialized elements of
constexpr arrays in two cases.  In the first case, accessing array elements
of a class type that were implicitly value-initialized during aggregate
initialization could result in a segfault or be incorrectly diagnosed as
non-constant.  For example:

  struct A {
    constexpr A (): a(6) {}
    int a;
  };
  void f() {
    constexpr A g[3] = { A () };
    constexpr A p = g[2]; // Incorrectly diagnosed as non-constant
    constexpr A q = g[1]; // Front end terminated with a segfault
  }

In the other case, accessing an element of a string past the end of the
initializer was incorrectly diagnosed as non-constant.  For example:

  void f() {
    constexpr char s[2] = "";
    constexpr char c = s[1];  // Incorrectly diagnosed as non-constant
  }

These are both now fixed.


5/1/13   [EDGcpfe/13960]
Microsoft C++: __is_convertible_to with reference type as second argument

The implementation of __is_convertible_to in Microsoft mode (which has
nonstandard behavior) has been modified so that it produces false if the
destination type is a reference to a class or array type that is less
qualified than the source type.  For example:

  struct S {};
  static_assert(!__is_convertible_to(S const, S&),
                "Cannot drop type-qualifiers");

See also the entry for EDGcpfe/13625 (dated 2/12/13).


5/1/13   [EDGcpfe/13954]
Spurious error on field with volatile member in union

Version 4.6 introduced a bug that caused a spurious error ("disallowed
member function") to be issued on certain union type definitions containing
a field of a class type that itself contains a volatile field.  For example:

  struct T {};
  struct S { volatile T t; };
  union U {
    S s;  // Previously triggered a spurious error indicating that S
  };      // has a disallowed member function.

This is now fixed.


5/1/13   [EDGcpfe/13963]
GNU C++: arguments to builtin functions with ellipsis converted to rvalue

The front end has special processing that prevents default argument
promotions on GNU built-in functions that take their argument via
an ellipsis (e.g., __builtin_isinf).  However, that also prevented
lvalue-to-rvalue conversions, which foiled constexpr folding on
some cases.  Now fixed.

  inline constexpr bool isinf(long double p) {
    return __builtin_isinf(p);
  }
  constexpr double x = isinf(1.0);


5/1/13   [EDGcpfe/13933]
Stringization of Unicode and raw string literals

The front end previously failed to escape the quotation marks of a Unicode
or raw string literal when it was the operand of the # (stringize) operator.
This is now fixed.  For example:

  #define M(x) #x
  const char *s = M(U"abc");  // Previously expanded to "U"abc"" instead
                              // of the correct form "U\"abc\""


5/1/13   [EDGcpfe/13778]
Spurious error on certain pack expansions in constructor declarations

If a constructor declaration began with a pack expansion where the pack
that was named was not at the top level in the function declarator (e.g.,
in the example below the pack T is not the immediate parameter type but rather
is used inside a template argument list), spurious errors could be issued
about the pack not being expanded and later that the pack expansion did
not make use of any packs.  The errors resulted from the failure to handle
packs in the disambiguation of a constructor declaration, so the error
only occurred when the pack was the first parameter of the constructor.
Now fixed.

  template <typename T> struct A {};
  template <typename... T> struct B {
    B(A<T>... ts);
 };


5/1/13   [EDGcpfe/13918]
Abort on nested class derived from dependent parent class (GNU mode)

In GNU C++ mode, a nested class defined in a class template can derive from a
dependent instance of the class template.  Version 4.6 of the front end,
however, introduced a bug causing such cases to abort with an internal error
(in is_literal_type) in GNU C++11 mode.  For example:

  template<typename T> struct S {
    struct N: S<T> {};  // Previously triggered an internal error in
  };                    // GNU C++11 mode.

This is now fixed.


5/1/13   [EDGcpfe/13644]
Microsoft compatibility: concatenation with inert macro name

The Microsoft preprocessor allows concatenation of an identifier at the end
of a macro expansion with another identifier that immediately follows the
closing parenthesis of the macro invocation.  (Standard preprocessing
maintains them as separate tokens.)  The front end failed to emulate this
processing in Microsoft mode when the identifier following the macro
invocation is an inert macro name, i.e., the name of a macro appearing in
the expansion of that same macro; such macro names are internally marked to
prevent recursive invocation of the macro, and that marking prevented the
concatenation from occurring.  This is now fixed.  For example:

  #define A(x) x
  #define B A(x)B
  int B;    // Now expands to "int xB;" in Microsoft mode


5/1/13   [EDGcpfe/13398]
Microsoft compatibility: template argument pack expansion containing void

In Microsoft mode, "void" is allowed in some contexts that are not
permitted by the standard (see EDGcpfe/12029 on 9/6/11).  That feature
could result in spurious errors on valid uses of "void" in a pack expansion
in Microsoft mode.  Now fixed.

  template <class ... Ts> struct A {
    static int i;
  };
  template <class ... Ts> struct B {
    static int f() {
      return A<Ts...>::i;
    }
  };
  int main() {
    B<void> b;
    b.f();
  }


4/30/13  [EDGcpfe/13904]
Generation of "= default" definitions

The definitions of special member functions defined with "= default" were
previously always generated when the parent class was completed.  Now, such
definitions are only generated if the special member is actually used, just
as if those special members had been implicitly-declared.  The previous
approach caused some template cases to trigger spurious errors when the
(unneeded) generation of a definition triggered the instantiation of other
member functions.  For example:

  template<typename T> struct S {
    T& m();
    void operator=(S const&) { m() = m(); }
  };
  template<typename T> struct V { T const &r; };
  template<class T> struct F {
    F();
    F& operator=(F&&) = default;
    S<V<T>> sv;
  };
  void g() {
    F<F<int>> x;
  }

In this example, the definition of F<F<int>>'s move assignment operator was
previously generated even though it wasn't used.  That definition triggered
the instantiation of S<V<F<int>>>'s copy assignment operator, which in turn
elicited an error because V<F<int>>'s assignment operator is deleted (since
it has a reference member).


4/30/13  [EDGcpfe/13951]
C++-generating back end: missing qualification in non-type template arguments

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL is set to TRUE
and the front end is run in C++11 mode, the C++-generating back end
sometimes used an unqualified name in a non-type template argument when a
qualified name is required.  This bug was introduced in version 4.6 and is
now fixed.  For example:

  namespace N {
    template<typename> struct C {
      static const bool value = false;
    };
    template<bool> struct B {
      typedef int type;
    };
    template<typename T> struct A {
      typedef typename B<C<T>::value>::type type;
    };
  }
  template<typename T> struct D {
    template<typename>
    typename N::B<N::C<T>::value>::type f(); // Argument to B was generated
                                             // without the required "N::"
  };


4/30/13  [EDGcpfe/13957]
Using conversion function to reference to array for pointer operand to built-in

A conversion function that returns a reference to an array is now
considered when trying to match an operand of a built-in operator that
requires a pointer.  Similarly for a reference to a function type.

  template <typename T> struct X {
    T data;
    operator T&() {
      return data;
    }
  };
  int main() {
    X<int[10]> x;
    int i = x[0];
  }


4/29/13 [EDGcpfe/13913]
Spurious constexpr error on generated default constructor

In some cases involving a class with a generated default constructor and a
subobject whose type is an instance of a class template the front end issued
a spurious error ("constexpr constructor calls non-constexpr function") when
generating the definition of the default constructor.  For example:

  struct S { S(); };
  template<typename T> struct X {
    T t;
    constexpr X() {}
  };
  struct D: X<S> {};
  D d;  // Previously the generation of D::D() at this point triggered a
        // spurious error.

This is now fixed.


4/29/13 [EDGcpfe/13944]
Generated copy constructor in class with mutable field

The changes for EDGcpfe/13788 intended to address an issue with mutable fields
for both copy assignment operators and copy constructors.  However, the copy
constructor case was not addressed correctly, causing generated copy
constructors to be implicitly "deleted" (in C++11 mode) even though their
definition could validly be generated.  For example:

  struct S {
    S(S&);
  private:
    S(S const&);
  };
  struct X {
    mutable S x;
  };
  void g(X& s) {
    X d(s);  // Previously resulted in a spurious error in C++11 mode because
  }          // X's (generated) copy constructor was declared "= delete".

This is now fixed.


4/29/13  [EDGcpfe/8625,EDGcpfe/13915]
UTF-8 string literals

We have now implemented the UTF-8 string literal feature of C++11 (see
paper N2442).  These literals specify that the encoding of the resulting
constant will be UTF-8.  For example:

  const char s[] = u8"\u03a9";  // equivalent to "\xce\xa9"


4/29/13  [EDGcpfe/13949]
Wrong end_position in switch case entry

A change in version 4.6 broke the recording of the end_position field
in the IL a_switch_case_entry.  Now fixed.


4/26/13  [EDGcpfe/11272,EDGcpfe/13707]
Additional type traits helpers

When type traits helpers are enabled (particularly, in C++11 mode) the front
end now recognizes the following additional helpers: __is_nothrow_assignable,
__is_trivially_assignable, __is_trivially_constructible, __is_destructible,
__is_nothrow_destructible, and __is_trivially_destructible.  Each of these
corresponds to the similarly named class templates in the C++11 standard
library (e.g., std::is_destructible<T>).


4/25/13  [EDGcpfe/13942]
Incorrect end position on expression for "new" with braced-init-list

The end position was not set correctly for a "new" operator with a
brace-enclosed initializer.  Now fixed.


4/24/13  [EDGcpfe/13937]
Missing is_partially_initialized flag on initializer_list array constant

When a member of an initializer_list included both a dynamic initialization
and also partial initialization of an aggregate, the is_partially_initialized
flag on the ck_aggregate constant for the array was sometimes not
properly set.  This could cause problems later, e.g., an assertion
failure in the C-generating back end.  Now fixed.

  #include <initializer_list>
  struct A {
    int i;
    int y[2];
    struct B {
      B();
    } b;
  };
  int main() {
    for (A a : {A{}}) ;
  }


4/24/13  [EDGcpfe/13934]
Core issue 1402

We now implement (part of) Core issue 1402, which says that move
constructors and move assignment operators that are both defaulted and
deleted should be ignored by overload resolution.  Implementing that
fixed a compilation problem with the gcc 4.7.2 stl_tree.h header file.

[ Update: See also the entry of 5/8/13 for EDGcpfe/12944 which documents the
changes for the remainder of Core issue 1402 (generating a move constructor
in more cases). ]


4/23/13  [EDGcpfe/13936]
GNU compatibility: Extended asm operand limitation

Previously, the front end imposed a limit of 30 total (i.e., input and output)
operand descriptions in extended GNU asm constructs.  This limit has now been
lifted.


4/23/13  [EDGcpfe/8627]
C++11: ref-qualifiers on member functions

C++11 adds ref-qualifiers on member function declarations, which
allows the declaration of functions that will operate only on
lvalue or rvalue objects.  Now implemented.  See paper N2439.

  extern "C" int printf(const char *, ...);
  struct A {
    void p() & { printf("&\n"); }
    void p() && { printf("&&\n"); }
  };
  int main() {
    A a;
    a.p();    // &
    A().p();  // &&
  }

These changes include a change to include ref-qualifiers in mangled
function types.  The IA-64 ABI mangling scheme is followed for IA-64 ABI
configurations.  For Cfront configurations, an optional "_R" (for an
lvalue ref-qualifier) or "_E" (for an rvalue ref-qualifier) now follows the
"F" encoding for a function type.


4/23/13  [EDGcpfe/7689,EDGcpfe/12842]
C++11: Delegating constructors

In C++11 mode, the front end now accepts "delegating constructors".
See paper N1986.  For example:

  struct S {
    S(int);
    S(): S(0) {}  // Default constructor for S delegates to constructor
  };              // S::S(int).

This feature can also be enabled in non-C++11 modes with the new command-line
option --delegating_constructors.

Note that in the IA-64 ABI configuration, when using lowering, delegating
constructors that have virtual base classes are implemented by invoking
a new cdk_delegation constructor (which is specific to the EDG front end
-- i.e., it's not part of the IA-64 ABI).  This constructor is invoked
by both the complete and subobject constructors and contains special
treatment to ensure that the proper (i.e., complete or subobject) target
constructor is called.  In certain cases where the delegating constructor
body is empty, use of this constructor is optimized away.

A new "delegation" destructor is used in both IA-64 ABI and Cfront
configurations to determine at run-time whether the complete object or
the subobject is being destroyed and invoke the appropriate destructor
(or in the Cfront case, invoke the destructor with the appropriate second
argument).

In the IA-64 ABI, these new cdk_delegation constructor and destructor routines
are mangled with "C9" and "D9" respectively.  The delegation destructor is
unnamed in the Cfront ABI (a temporary name is used).

The use of a delegation destructor relies on a change in the
run-time library, and thus is enabled only when ABI_COMPATIBILITY_VERSION is
407 or greater (in configurations where lowering does exception handling).


4/22/13  [EDGcpfe/13391]
Microsoft compatibility: pack expansion used in default template argument

A spurious error could be issued on the use of a pack expansion in a
default template argument of a type template parameter in Microsoft mode.
Now fixed.

  template < typename ... T > struct B { };
  template<typename ... Args> struct A {
    template<class T = B<Args...>> void f() { }
  };
  int main() {
    A<int,int> a1;
    a1.f();  // caused spurious error on evaluation of B<Args...>
  }


4/22/13  [EDGcpfe/13733]
Sun compatibility: incorrect handling of typename in some cases

In Sun mode, a spurious incomplete type error could result when a class
template, that was declared but not defined, was used as part of a qualified
name in a typename specifier in a template declaration.  Now fixed.

  namespace N {
    template <typename T> struct A;
  }
  template <typename T> typename N::A<T>::type f(T& t);


4/22/13  [EDGcpfe/13436]
Missing error on parameter pack not at end of partial specialization arguments

The front end failed to issue a diagnostic on a template parameter pack that
was not the final template argument in a partial specialization declaration.
Now fixed.

  template <class ... Args> struct A{};
  template <class T, class ... Args> struct A<Args..., T> {};


4/21/13  [EDGcpfe/13737]
Variadic parameter packs in __is_constructible argument list

Variadic template parameter packs are now allowed in the argument lists
of the __is_constructible and __is_nothrow_constructible type trait
operators.

  template <bool B> struct Base {
    static const bool value = B;
  };
  template <typename T, typename... Args> struct is_constructible
    : Base<__is_constructible(T, Args...)> { };
  template <typename T, typename... Args> struct is_nothrow_constructible
    : Base<__is_nothrow_constructible(T, Args...)> { };
  static_assert(is_constructible<int, int>::value, "fail");
  static_assert(is_nothrow_constructible<int, int>::value, "fail");


4/19/13  [EDGcpfe/13924]
Dependent pointer-to-member in C++11 SFINAE context

Dependent pointer-to-member constants were not handled completely
correctly in C++11 SFINAE contexts.  In particular, the front end
erroneously rejected some cases due to failing to remember information
needed to check that the constant has the standard required form
(i.e., "&" applied to a qualified name).  Now fixed.

  template <bool B> struct A { typedef int type; };
  template <> struct A<false> {};
  struct C {
    template<class T> void f(T&) { }
  };
  template<class T> struct D {
    template<void (C::*)(int&)> struct tester;
    template<class U> static char test(tester<&U::template f<int> >*);
    template<class> static long test(...);
    enum { value = sizeof(test<T>(0)) == 1 };
  };
  template<class T>
  typename A<D<T>::value>::type g(const T&) { }
  void foo() {
    C it;
    g(it);
  }


4/19/13  [EDGcpfe/13914]
Abort in Microsoft mode on use of nonstatic function from dependent base

An assertion failure occurred in select_and_prepare_to_call_overloaded_function
in overload.c, in Microsoft mode with --parse_templates, on a call of a
nonstatic member function from a dependent base class, with an implied
object pointer ("this->").  This problem was introduced in version 4.6.
Now fixed.

  template <class T> struct B {
    virtual int f();
  };
  template <class T> struct A : B<T> {
    int g() {
      return f();  // Aborted previously
    }
  };
  int main() {
    A<int> a;
    a.g();
  }


4/19/13  [EDGcpfe/13919]
Microsoft compatibility: internal error on static data member when parsing
nonclass templates

An internal error could occur (in generic_cast_operand) in Microsoft mode
when microsoft_version <= 1300 on a template static data member of
a class template declared in a namespace when the --parse_templates option
is used.  Now fixed.

  namespace N {
    template <class T> struct A {
      typedef T::x x;
      static const x i;
    };
    template <class U> const A<U>::x A<U>::i = -1;
  }


4/19/13  [EDGcpfe/13704]
Microsoft C++: Specializing a file-scope class template in a namespace

In Microsoft C++ mode, a specialization for a file-scope class template is now
accepted in a namespace.  For example:

  template<class T> struct S {};
  namespace N {
    template<> struct S<int> {};  // Now accepted in Microsoft C++ modes.
  }


4/18/13  [EDGcpfe/13704]
GNU and Microsoft C++: access ignored on unevaluated copy constructor after
  conversion function

g++ and MSVC++ do not appear to check the access on a copy constructor
needed to copy an argument after it has been converted via a conversion
function that returns a reference, in an unevaluated expression (in
g++, an unevaluated expression in a template).  That is now emulated in
those modes.

  class A {
    A(const A&);  // private
  };
  struct B {
    operator A&();
  };
  char f(A);
  template <class T> struct C {
    static B b;
    static const int i =  sizeof(f(b)); // Accepted even though copy ctor
                                        // is private
  };
  C<int> c;


4/17/13  [EDGcpfe/13898]
Incorrect handling of pointer to member as default template argument with C++11

A change made for C++11 in version 4.6 caused pointers-to-members to not
be accepted as default template argument values in some cases.  Now fixed.

  struct A {
    int f(int i) const { return i;}
  };
  template<typename R, typename S> struct B {
    template<typename U = A,
             typename T = A ,
             typename X = R (U::*)(S) const,
             X PMF = &A::f >
    int g() {
      A a;
      return (a.*PMF)(0);
    }
  };
  int main() {
    B<int, int> b;
    b.g();
  }


4/16/13  [EDGcpfe/13846]
Revert to clearer error in C++11 mode for enum value out of range

In C++11 mode, the expression that gives the value for an enumerator
is scanned as a converted constant expression of the type of the enum.
That meant that if the value was out of range a generic message
about narrowing was issued, instead of the more specific message
for enums issued in non-C++11 mode.  We have now reverted to the old
error message for enum-out-of-range cases.  Also, because g++ mode
treats narrowing errors as warnings, only a warning was issued for an
enum out of range in g++ mode.  That's also restored to an error with
the change back to the old message.


4/16/13  [EDGcpfe/13891]
C++/CLI C++11 mode: nullptr accepted as nontype template argument for handle

In C++/CLI plus C++11 mode, a nullptr constant is now accepted as the
value for a nontype template parameter of handle type.

  ref class A {};
  template<A^ g> ref class B {};
  int main() {
    B<nullptr> k;
  }


4/16/13  [EDGcpfe/13905]
C++/CLI: safe_cast misinterpreted as identifier in template with dependent base

The C++/CLI pseudo-keyword "safe_cast" was not properly recognized when
it appears in a template with a dependent base class.  For example
(with --cppcli --parse_templates -tall):

  template<class T>
  ref class A : T
  {
    T^ f() {
      return safe_cast<T>(0);  // Now accepted
    }
  };


4/16/13  [EDGcpfe/13906]
Spurious error on range-based-for with const-qualified begin/end

A spurious error had been issued on range-based-for (and for-each) statements
when the begin/end member functions (or functions) had a const-qualified
return type.  Now fixed.  For example (with --c++11):

  struct Iterator {
    bool operator!=(const Iterator&) const;
    Iterator& operator++();
    const int& operator*() const;
  };
  struct Range {
    const Iterator begin();
    const Iterator end();
  };
  int main() {
    for (auto x : Range()) {}
  }


4/15/13  [EDGcpfe/13907]
Microsoft compatibility: disable trigraphs by default

Microsoft Visual Studio 2010 and later disable trigraph support by default
so the front end now does the same (i.e., trigraphs are enabled by default when
microsoft_version < 1600 and disabled otherwise).


4/15/13  [EDGcpfe/13899]
Access error on reference to protected trivial default constructor

A spurious access error could occur on the use of a protected trivial default
constructor.  Now fixed.

  struct A { };
  template <class T> class B : public A {
  protected:
    B() = default;
  };
  struct C : public B<C> {
    C() {}
  };


4/14/13  [EDGcpfe/13599]
GNU C++ mode: access checking in SFINAE contexts

As of g++ 4.8, GNU C++ seems to consider access in SFINAE contexts, so
we now emulate that.  However, we also discovered that access checking on
base class casts seemed to be considered even on earlier versions, so
we do that as well now.

  struct A {};
  struct B : private A {};
  int g(A);
  int g(...);
  void f(...);
  template <class T> auto f(T p) -> decltype(g(p)) { return 0; }
  int main() {
    f(B());  // Got access error, now selects f(...)
  }

Also, the changes of EDGcpfe/13655 to consider some calls in member
template declarations dependent in a real instantiation of the
outer template are now done in g++ mode as well.


4/13/13  [EDGcpfe/13882]
Microsoft compatibility: partial ordering and references to functions

A change made in version 4.5 added emulation of the Microsoft behavior for
ordering of references to functions vs. pointers to functions (see
EDGcpfe/13194 on 2/12/13).  The earlier change did not handle some cases
properly.  Specifically, the earlier change only preferred a reference
to function if there was only one parameter involved in partial ordering.
A reference to function should also be preferred when there are multiple
parameters if a reference/pointer to function parameter involves dependent
types.  We now accept examples such as the one below in Microsoft mode.

  template <class Result, class Arg> void f(Result(*)(), Arg); // #1
  template <class Result, class Arg> void f(Result(&)(), Arg); // #2
  void g() {
   f(g, 0); // now calls #2 in Microsoft mode
  }


4/12/13  [EDGcpfe/13853,EDGcpfe/13894]
GNU C++ compatibility: Multiple returns in lambdas with implicit return type

In GNU C++11 mode with gnu_version >= 40500, lambdas with an implicit return
type are now allowed to contain multiple statements and multiple returns as
long as the returns all imply the same return type.  (This extensions was
already accepted in Microsoft mode; see entry of 5/9/12 for EDGcpfe/12913).
For example:

  auto lambda = [](bool b) { if (b) return 42; else return 43; };
       // Now accepted in some GNU C++11 modes.


4/12/13  [EDGcpfe/13893]
Initialization of std::initializer_list<T> from {} in overload resolution

According to Core Issue 1543, initializing a parameter of type
std::initializer_list<T> from an empty initializer list {} is an exact
match, not a user-defined conversion.  We mostly got that right, but
in overload resolution we rejected such a match in contexts where a
user-defined conversion is not permitted.  Now fixed.

  #include <initializer_list>
  struct A {
    A(std::initializer_list<A>);
  };
  A a = {};  // Formerly got spurious error


4/11/13  [EDGcpfe/13890]
Spurious error on defaulted move assignment operator

In C++11 mode, the front end sometimes issued a spurious error on a defaulted
move assignment operator whose definition could not be generated (e.g.,
because of the presence of a data member of reference type) if the parent
class has a user-declared copy constructor and copy assignment operator.
The standard requires such assignment operators to be simply "dropped", but
the front end attempted to generate definition anyway, resulting in the
error.  For example:

  struct S {
    S(S const&) = delete;
    void operator=(S const&) {}
    S& operator=(S&&) = default;  // Defaulted member should be "dropped";
    int &r;                       // previously it triggered a spurious error.
  };

This is now fixed.


4/11/13  [EDGcpfe/11205]
GNU C mode: allow constant-valued variable in __builtin_constant_p operand

GNU C allows the use of constant-valued variables in constant
expressions when -O1 is specified (normally, they are allowed only in
C++ mode, but gcc allows them in C mode in that case).  The front end
already allowed those in most contexts, but it didn't in the operand
expression of a __builtin_constant_p in a constant expression.  Now,
it does.

  const int constvar = 1;
  int notconstvar = 2;
  int i = __builtin_constant_p(constvar) ? constvar : notconstvar;

(Note, however, that accepting that example depends on the setting of
DEFAULT_ALWAYS_FOLD_CALLS_TO_BUILTIN_CONSTANT_P.)


4/11/13  [EDGcpfe/13678]
Partial specialization in inline namespace

A partial specialization of a class template declared in an inline namespace
was not allowed to be partially specialized in the enclosing namespace
using an unqualified name.  Now fixed.

  namespace N {
    inline namespace N_inline {
      template <typename T> struct A { T t; };
    }
  }
  template <typename T> struct B { T t; };
  namespace N {
    template <typename T> struct A< B<T> > { B<T> t; };
  }


4/10/13  [EDGcpfe/13883]
GNU C++ compatibility: Default arguments in lambda expressions

In GNU C++11 mode, the front end now accepts default arguments in lambda
expressions.  Note that since the lambda's "function declarator" really is the
declarator for an operator() of the corresponding closure type, constraints
associated with that operator remain in force.  For example, in a local scope
a lambda's default arguments cannot refer to local variables.  For example:

  int main() {
    int x = 1;
    int y = [](int p = 2){ return p; }(); // Now accepted in GNU C++11 mode.
    int z = [](int p = x){ return p; }(); // Error even in GNU C++11 mode:
    return y+z;                           // The local variable x cannot be
  }                                       // referred to.


4/9/13   [EDGcpfe/13877]
Microsoft compatibility: _MSC_FULL_VER

In Microsoft modes, the front end now predefines a macro MSC_FULL_VER whose
value is obtained by concatenating the decimal representation of
microsoft_version and a "build number" stored in the new global variable
microsoft_build_number.  By default the build number is set to 99999, but it
can be modified with the new command-line option --microsoft_build_number.
The build number is currently not used by the front end for anything other
than setting the _MSC_FULL_VER macro value.


4/9/13   [EDGcpfe/13874]
Abort on out-of-class initialization of (invalid) local static data member

Declaring a static data member of a local class is invalid (and elicits an
error), but attempting to initialize such a static data member could trigger
an internal error in Microsoft C++ mode and in some GNU C++ modes
("push_or_repush_object_lifetime: parent is in file scope memory, new olp is
not").  For example:

  int main() {
    struct L { static int x; };  // Invalid static data member declaration.
    int L::x = 0;                // This could trigger an internal error.
  }

This problem (introduced in version 4.6) is now fixed.


4/9/13   [EDGcpfe/13710]
Microsoft compatibility: __is_convertible_to

Previously, in Microsoft modes, uses of __is_convertible_to with two identical
"void" types or two identical function types produced a "true" value.  Now it
produces a "false" value to match the behavior of Microsoft's compilers.
For example:

  typedef int F();
  static_assert(!__is_convertible_to(F, F), "Should not trigger");


4/9/13   [EDGcpfe/8626]
C++11 raw string literals

We have now implemented the "raw string literal" feature of C++11 (see
papers N2442 and N3077).  These literals can span multiple lines and
escape sequences and trigraphs are not translated.  For example:

  const char *p = R"+++(a\
  ??=\0xa
  z)+++";  // Equivalent to "a\\\n\?\?=\\0xa\nz"


4/8/13   [EDGcpfe/13876]
Missing conversion to boolean controlling expression in enhanced for loops

In range-based-for and Microsoft for-each statements, the ne_call_expr
expression (that embodies the "not-equal" test for the loop) had not
been converted to a boolean expression, resulting in invalid IL (and
generated C code that wouldn't compile in C-generating back end
configurations) in certain cases.  For example (with --c++11):

  struct H { operator bool(); };
  struct E {
    int operator*();
    E operator++();
    H operator!=(E &o);
  };
  struct D { D(); };
  E begin(D);
  E end(D);
  void f() {
    for (int i : D()) {}
  }


4/8/13   [EDGcpfe/13782]
Microsoft compatibility: "override" and "virtual"

In Microsoft C++/CLI mode with microsoft_version >= 1800 or with C++11 mode
also enabled, the front end now no longer requires the keyword "virtual" when
the context-sensitive keyword "override" is present.  For example:

  struct B {
    virtual void f();
  };
  struct D: B {
    void f() override;  // Previously an error in C++/CLI mode because
  };                    // "virtual" was not present.  Now accepted if
                        // microsoft_version >= 1800 or if combined with
                        // C++11 mode.


4/8/13   [EDGcpfe/13755,EDGcpfe/13872]
Empty clobbers list in GNU C mode

The front end now accepts empty clobbers lists in extended asm constructs
when gnu_version >= 40500 (it already accepted empty clobbers lists in GNU
C++ mode).  For example:

  void f() {
    void **p = 0;
    __asm__("mov %0, %%esp" "jmp *%1"
            : : "r"(p), "r" (p)
            : /* Previously this elicited an error in all GNU C modes. */);
  }


4/8/13   [EDGcpfe/13865]
Partial initialization flag not correctly set in some cases

In some cases involving C++11-style braced initialization, the flag
is_partially_initialized of the a_dynamic_init entry representing the
initialization was not correctly set.  This also resulted in an internal
error in the C-generating back end ("can't generate code for partial
aggregate" in dump_initializer_part).  For example:

  struct S {
    int x;
    int y[2];
    struct N { ~N() {} } z;
  };
  void f(S p) {}
  int main() {
    f({});  // Previously triggered an abort in c_gen_be.c.
  }

This is now fixed.


4/7/13   [EDGcpfe/13870]
No conversion from scoped enum returned from conversion function to integral

The front end mistakenly allowed a conversion function that returns a
scoped enum type to be used to convert an operand of a built-in operator
(like "+") that requires an integral or arithmetic type, in spite of the
fact that there is no implicit conversion of a scoped enum to integral.
Now fixed.

  enum class SE : int {};
  struct A {};
  void operator+(A, int) ;
  struct B {
    operator A() const ;
    operator SE() const ;
    void operator[](int p) const {
      *this + p;  // Got spurious ambiguity error; now uses operator+(A, int)
    }
  };


4/6/13   [EDGcpfe/13868]
Overload resolution change on "this" parameter cv-qualification difference

Overload resolution has been changed to account for a cv-qualifier difference
when comparing a reference binding against an implied reference binding
for a "this" parameter.

  class A;
  struct B {
    B(A&&);
  };
  struct A {
    operator B() const;
  };
  A f();
  void g(const B& str);
  int main() {
    g(f());  // Was ambiguous; now chooses B(A&&)
  }


4/5/13   [EDGcpfe/13857]
Abort on out-of-class-template member function with noexcept-specifier

In C++11 modes that defer prototype instantiations of function templates
(e.g., GNU C++-mode in many configurations), the front end aborted with an
internal error in is_template_dependent_noexcept_specification (decls.c)
when processing an out-of-class definition of a member function of a class
template.  For example:

  template<class T>
  class S { 
    S() noexcept(true); 
  }; 
  template<class T> S<T>::S() noexcept(true) {} 
    // Triggered an abort in GNU C++11 mode in version 4.6.

This regression introduced by version 4.6 of the front end is now fixed.


4/5/13   [EDGcpfe/13831]
Aggregate initializers that fail to initialize a reference

The front end previously accepted aggregate initializers that didn't properly
initialize a reference member if that member was embedded in an implicitly
initialized aggregate type.  For example:

  struct R { int &r; };
  struct S { int i; R x; } s = { 1 };  // Previously accepted; now an error
                                       // because s.x.r is a uninitialized
                                       // reference.

Now such cases trigger an error.


4/5/13   [EDGcpfe/13850]
Microsoft mode: objectless nonstatic data member references in non-C++11 mode

Microsoft mode now allows objectless nonstatic data member references
(see EDGcpfe/8402 below) for microsoft_version >= 1600 even if C++11
mode is not specified.


4/3/13   [EDGcpfe/13785]
C++-generating back end: missing definition of inline member function of
class template with function prototype instantiation deferral

In configurations with both PROTOTYPE_INSTANTIATIONS_IN_IL and
FUNCTION_PROTOTYPE_INSTANTIATION_DEFERRAL_ALLOWED set to TRUE, the front
end (in certain very obscure cases) does not instantiate an inline member
function of a class template in --g++ mode when g++ does instantiate the
function (see the entry for EDGcpfe/12919 below for some background on this
issue).  The result of this difference could be seen in the fact that the
member function was only declared, not defined, in the code generated by
the C++-generating back end for the class template definition.  This has
now been addressed by putting out the definition of such member functions
from the string form (tokens) of the definition.  In the following example,
for instance, the C++-generating back end previously put out only a
declaration, not a definition, for H<T>::~H():

  struct A { };
  struct B : virtual public A {
    virtual ~B();
  };
  struct C : virtual public A { };
  struct D : virtual A { };
  struct E : virtual D { };
  struct F : virtual D, B { };
  struct G : virtual E, F { };

  template<typename T> struct H {
    ~H() { }
  };
  template<typename T> struct I : public H<T> { };

  struct J : virtual C {
    virtual void f() = 0;
  };

  struct K : virtual C, G {
    I<int> Ii;
  };
  struct L : K {
    ~L();
  };

  struct M : virtual J, L {
    void f();
  };
  void M::f() { }


4/3/13   [EDGcpfe/13844]
dynamic_cast downcast of pointer to virtual base allowed on null pointer value

The front end now allows dynamic_cast to do a downcast from a polymorphic
virtual base class to a derived class if the pointer is a constant null
pointer value.  Previously, the cast got an error.

  struct A {
    virtual void f();
  };
  class D : public virtual A {};
  int main() {
    dynamic_cast<D*>(static_cast<A*>(0));
  }


4/3/13   [EDGcpfe/13838]
Assertion/invalid IL for certain aggregate constant initializations

Lowering of designated initializers (now used when initializing union members)
in aggregate constants had assumed that a single ck_init_repeat generated by
the front end did not span multiple array dimensions.  A change has been made
to allow such constants to be processed correctly.  The following example had
resulted in an assertion failure ("lower_aggregate_designated_initializers:
type mismatch") in configurations with EXPENSIVE_CHECKING, otherwise invalid IL
(with --c++11):

  struct B {
    struct A {
      int x = 47;
    } a[2][3];
    union {
      int y;
      int z = 37;
    };
  } b{};


4/2/13   [EDGcpfe/13843]
GNU C++ compatibility: specialization of member vs. member template

Version 4.6 introduced a regression in g++ mode that resulted in a
spurious "not an entity that can be explicitly specialized" error
if an explicit specialization matched the type of both a normal member
function and a function template of a non-template class.  Now fixed.

  struct A {
    A(int);
    template<typename T> A(T);
  };
  template<> A::A(int i){}


4/2/13   [EDGcpfe/13832]
Missing backing expression on constexpr base-class cast

In certain cases where the result of a constexpr constructor invocation
was bitwise copied with slicing to a base class type, the backing
expression was not recorded on the base-class constant, with the
consequence that the C++-generating back end output for the case
was incorrect.  For example (now fixed):

  struct A {
    union { int x = 37 ; } ;
  };
  struct B : A {};
  constexpr A x = B();  // Was output as "= {{37}}"


4/2/13   [EDGcpfe/13507]
Enclosing-context constant-valued variable treated as constant in VLA
  expression in lambda

An enclosing-context constant-valued variable is now considered constant
when referenced in an array bound expression inside a lambda when the
current dialect allows variable-length arrays (e.g., g++ mode).
For example, this example from the C++11 standard got a spurious
error in --g++ --c++11 mode, and is now accepted:

  void f1 (int i) {
    int const N = 20;
    auto m1 = [=] {
      int const M = 30;
      auto m2 = [i]{
        int x[N][M];  // Spurious errors on N, M
        x[0][0] = i;
      }; // m2
    }; // m1
  } 


4/2/13   [EDGcpfe/13840]
Un-lowered constant can get to back end

An abk_temporary constant that is generated by the front end is re-written
in lowering to point to a temporary variable, but in configurations where
RECORD_BACKING_EXPRS_WITH_IL_LOWERING is FALSE, an unlowered abk_temporary
could escape to the back end as in this example, causing invalid C code
to be generated in configurations that use the C-generating back end:

  constexpr const int& x = 37;
  int main() {
    return ([]()->decltype(x){return {x};}() != 37);
  }


4/1/13   [EDGcpfe/13809]
Setting of needed flag in namespaces

The changes that introduced the parent_scope for IL entities (see the
Changes entry of 3/5/08), had a side-effect of neglecting to properly set
the needed flag on a_namespace entries in certain cases.  A change has been
made to set the needed flag on parent scope namespaces and class types
during the needed and keep-in-IL tree walks.  In this case, the needed
flag for namespace N hadn't been set and now is:

  namespace N {
    int x;
  }


3/31/13  [EDGcpfe/13713]
C++-generating back end: omitted extern "C++" on non-defining variable decl

The C++-generating back end generated incorrect code for a non-defining
declaration of a variable that was explicitly declared with extern "C++".
Such a declaration is equivalent to declaring the variable with the
"extern" keyword, but the C++-generating back end omitted both the linkage
specification and the keyword.  Such declarations are now emitted with
the "extern" keyword.  For example:

  extern "C++" int x;  // Previously generated as "int x;", which is a
                       // definition.


3/31/13  [EDGcpfe/13683]
C++-generating back end: qualifier missing in template friend declaration

The C++-generating back end sometimes failed to use a qualified name when
it is needed in a template friend declaration.  This is now fixed.  For
example:

  template<int I> struct S;
  namespace N {
    template<typename T> struct S {
      template<int I> friend struct ::S;  // Previously generated as
                                          // "struct S"
    };
  }


------------------------------------------------------------------------------
Version 4.6, March 30, 2013

3/29/13
Version number changed to 4.6


3/28/13 [EDGcpfe/13788]
Generated special member in class with mutable field incorrectly "deleted"

The changes for EDGcpfe/9807 (see entry of 3/21/12) caused some generated
copy constructors and copy assignment operators for classes with mutable
members to be implicitly "deleted" (in C++11 mode) even though their
definition could validly be generated.  For example:

  struct S {
    S& operator=(S&);
  private:
    S& operator=(S const&);
  };
  struct X {
    X(S &s) : x(s) {}
    mutable S x;
  };
  void g(X &d, X const &s) {
    d = s;  // Previously this triggered a spurious error in C++ mode
  }         //  because X::operator=(X const&) was declared "= delete".

This is now fixed.


3/28/13 [EDGcpfe/13824]
Incorrect type on pointer-to-member cast that changes class and cv-qualifiers

An eok_pm_derived_class_cast or eok_pm_base_class_cast cast sequence that
is also supposed to change the cv-qualifiers of the member type failed
to do so (it changed the class but kept the cv-qualifiers of the original
node).  That caused a failure of a consistency check on variable
initializers added recently.  Now fixed.

  struct B {};
  struct D: B {
    int i;
  };
  void f(int B::* pmb) {
    int const D::*pmd = pmb;  // Type of initializer was missing const
  }


3/28/13
IL version number updated to 4.6


3/28/13  [EDGcpfe/13727]
Explicit conversion functions in Microsoft and C++/CLI modes

In Microsoft C++ mode with microsoft_version >= 1800, C++11-style explicit
conversion operators are now accepted.  Furthermore, in C++/CLI modes with
microsoft_version >= 1800, explicit conversion operators are no longer
restricted to ref and value class types: They are also permitted in standard
class types and in interface class types.


3/28/13  [EDGcpfe/13417]
Internal error on noexcept specifier following syntax error

A syntax error in the declarator of a member function template could result
in an internal error (in alloc_template_cache_segment) if the declaration
also included a noexcept specification.  Now fixed.

  template <class T> struct A {
    template <class U> int f(T::template U {}) noexcept (true);
  };
  int main() {
    A<void> a;
    a.f(a);
  }


3/27/13  [EDGcpfe/13818]
Enum types defined in templates

Enumeration types defined in templates were previously never considered
template-dependent.  However, when such a type was created during the
prototype instantiation of a template in configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to FALSE, it could not be given a valid
parent scope (since the parent scope is not part of the IL).  This in turn
could lead to aborts (in particular in lowering and name mangling).
For example (in C++11 mode):

  template <class T> void f(T *) {}
  template<class T> struct S {
    void g() {
      enum { x = sizeof(T) } e;  // Previously a non-dependent type.
      f(&e);                     // Previously triggered an abort in
    }                            // IL lowering (in some configurations).
  };

This is now fixed: Enumeration types defined in prototype instantiation are
now treated as dependent types.


3/27/13  [EDGcpfe/13797]
GNU compatibility: New __builtin_ia32_... functions

When GNU_BUILTIN_IA32_VECTOR_FUNCTIONS_ALLOWED is TRUE, the front end now
predeclares the following functions in GNU mode: __builtin_ia32_pause,
__builtin_ia32_movnti64, __builtin_ia32_addcarryx_u32, and
__builtin_ia32_addcarryx_u64.


3/26/13  [EDGcpfe/13435]
Regression on pack expansion in template default argument

A change in version 4.5 could result in spurious errors evaluating a
pack expansion in a default template argument.  Now fixed.

  template <int i> struct x {};
  template <class T> struct A;
  template <class T, class... Args> struct A<T(Args...)> {
    template <class = x< sizeof...(Args)> > A();
  };
  template <class T, class... Args> struct B {
    typedef A<T(Args...)> type;
  };
  template <class T, class... Args> typename B<T, Args...>::type f(T, Args...);
  int main() {
    f(0, 0, 0);
  }


3/26/13  [EDGcpfe/13806]
Abort on local anonymous union introducing a new type name

In some unusual cases, the front end aborted with an internal error in
cancel_name_collision_discriminator when encountering a local anonymous union
declaring a member that itself introduces a new type name.  For example:

  void f() {
    union {
      struct B *x;
    };  // Previously triggered an internal error.
  }

(the name "B" matters here, because the failure mechanism involves a hash
table collision).  This is now fixed.


3/26/13  [EDGcpfe/13805]
C++11 "final" class modifier not recognized in some configurations

Version 4.5 added support for the C++11 "final" class modifiers (see the entry
of 3/12/12 for EDGcpfe/12619 and EDGcpfe/12741).  However, an oversight caused
that support to be disabled when the value of the configuration macro
MICROSOFT_EXTENSIONS_ALLOWED was FALSE.  This is now fixed.


3/26/13  [EDGcpfe/13786]
Abort on variadic argument list split across two template parameters

An abort could occur (in update_template_param_symbols) when an explicitly
specified variadic function template argument list was used in the function
type of the function template as the argument list for a class template in
which part of the argument list was associated with a non-pack and the
latter part was associated with a parameter pack.  Now fixed.

  template <typename T, typename... Args> struct A {
    typedef T type;
  };
  template <typename... T> typename A<T...>::type f();
  int main() {
    f<int, int>();
  }


3/25/13  [EDGcpfe/13799]
Microsoft compatibility: regression on template friend function declarations

Version 4.5 introduced a change that caused certain nonreal classes
used as base classes to be have actual instantiations done on them
in Microsoft mode.  This could result in spurious "has already been
defined" errors in Microsoft mode when a class instantiated in that
way contained a friend function template declaration.  Now fixed.

  template<class T, int I> struct A {
    template<class T> friend void operator<<(int os, A& s) {}
    typedef int type;
  };
  template<class T, int I> struct B: public A<T, I> {
    typedef A<T, I> A_type;
    typedef typename A_type::type type;
  };
  int main() {
    B<int, 1> b;
  }


3/25/13  [EDGcpfe/13657]
Internal error in definition of default special member function

An internal error could occur in the generation of an implicitly defined
special member function when the generation was caused by a reference
in default argument of another member of the class.  Now fixed.

  struct X { X(); };
  struct A {
    X x;
    A() = default;
    template <class T> A(const A&&, A&& = A(), char* = 0) {}
  };
  A a;


3/23/13  [EDGcpfe/13776]
C++/CLI mode: Consider dependent handle-to-function value as callable

The front end did not accept a dependent handle-to-function as a functor
value in C++/CLI mode.  Now fixed.

  template < typename __TLambda, typename... __TArgs >
  void f(__TArgs... __args) {
    auto x = [__args...](__TLambda^ __lambda) -> void { __lambda(__args...);
  };


3/23/13  [EDGcpfe/13795]
Failure to find default constructor for base when generating derived class
constructor

The front end failed to find a default constructor for a base class
while generating a constructor for a derived class.  The base class
has to have a template constructor that can serve as a default
constructor and no non-template constructors that can so serve.
Now fixed.

  struct A {
    template <class ...T> A(T...);
  };
  struct B {
    A a;
  };
  B b;


3/21/13  [EDGcpfe/13784]
Un-lowered constants are marked as lowered

Allocated IL entities have their il_lowering_flag flag set to the value of
initial_value_for_il_lowering_flag, which is TRUE during the lowering phase.
In cases where lowering is copying various IL entities, it is desirable to
maintain the value of the il_lowering_flag rather than having it always set to
TRUE; that's largely the case already, but in some cases performing a copy of
a constant had the undesired effect of setting the il_lowering_flag to TRUE in
the copy, thereby exposing the back end to potentially unlowered constants.
A change has been made to fix this issue.  Prior to this change, the "foo"
constant in the following example hadn't been lowered and, in IA-64 ABI
configurations where HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS is TRUE,
no associated variable for the string was created.  After the change, the
associated variable is created, but that led to an issue with mangling of the
promoted static variable in the newly created constructor; that issue has also
been fixed:

  struct A {
    A(const char *);
  };
  struct B : virtual A {
    B() : A("foo") { while(0); }
  };


3/21/13  [EDGcpfe/13764]
IA64-ABI: substitutions involving template parameters in dependent types

During the IA-64 ABI mangling process, a check is performed for each type
to see if the type has already been mangled and if so, a substitution is
used for that instance of the type.  That check had neglected to verify that
any template parameters were also identical, resulting in an assertion failure
("alloc_substitution: missed mangling substitution") in configurations with
EXPENSIVE_CHECKING and/or mangled names whose substitutions may have been
incorrect.  The previous behavior can be restored by setting
ABI_COMPATIBILITY_VERSION to 405 or lower.  For example:

  template <class T> struct B {};
  template <class T> using A = B<decltype(T())>;
  template <class T> decltype(A<A<T>>(), A<A<T>>()) f(T x);
  int main() {
    f(37);  // was: _Z1fIiEDTcmcv1BIDTcvS0_IDTcvT__EEE_EEE_EcvS3__EES1_
            // now: _Z1fIiEDTcmcv1BIDTcvS0_IDTcvT__EEE_EEE_EcvS5__EES1_
  }


3/21/13  [EDGcpfe/13777]
Microsoft compatibility: disambiguation of lambdas vs. attributes

In Microsoft mode when lambdas are enabled, it is necessary to determine
whether a "[" begins a lambda or a Microsoft attribute.  This processing
did not handle pack expansions in a lambda capture list properly, resulting
in some lambdas incorrectly being treated as attributes.  Now fixed.

  template < typename T, typename... Args > void f(Args... __args) {
    [__args...](T* t) -> void { t(__args...); }(nullptr);
  }


3/20/13  [EDGcpfe/12502]
GNU C++ compatibility: Signedness of __underlying_type

An enumeration type has two associated integer types: The type used to
determine integral promotion rules, and an "underlying type" (used for the
internal representation of enum values).  Ordinarily, these two types are
identical and the variant field int_kind in a_type entries for enumeration
types therefore represents them both.  GNU C++, however, sometimes makes the
underlying type "unsigned" (when no enumerator constant is negative) when the
type used to determine promotion rules is signed.  In such GNU C++ mode cases,
the front end records the type for promotion purposes in the int_kind field
(as it has always done), but the __underlying_type operator (see the entry of
7/5/11 for EDGcpfe/11495 etc.) now produces the unsigned underlying type
instead of the (signed) type used for promotion purposes.  For example:

  enum E { e, f };
  __underlying_type(E) x;  // x now has an unsigned type in GNU C++ mode
                           // (in other C++ modes it is still a signed type).
                           // The "integer kind" of E remains signed in all
                           // modes.


3/20/13  [EDGcpfe/13775]
GNU C++ compatibility: typedefs not found by friend class declarations

Starting with g++ version 4.5, friend class declarations do not consider
typedefs.  We now emulate this in g++ mode when gnu_version >= 40500.

  template< class T > class A { };
  class B : public A<B> {
    typedef A<int> A;
    friend class A; // finds injected class name of A
  };


3/20/13  [EDGcpfe/13774]
GNU C++ compatibility: friend template that refers to typedef

g++ allows a friend template declaration that names a typedef that refers
to the prototype instantiation of a class template.  This is treated as
if it were a friend template declaration that referred to the template
itself.  We now accept this in g++ mode when gnu_version >= 30400.

  template <class T> struct A {
    typedef A<T> my_type;
  };
  class B : public A< B > {
    template <class T> friend class A<T>::my_type;
  };


3/19/13  [EDGcpfe/13588]
Assertion failure during mangling of unnamed namespace

In some configurations (MANGLE_ALL_NAMES, PROTOTYPE_INSTANTIATIONS_IN_IL, and
IA64_ABI all TRUE), the mangling of an entity in an unnamed namespace had
resulted in an assertion failure (in mangled_simple_id).  This is now fixed.
For example:

  template <bool B> struct A {
    typedef int type;
  };
  namespace {
    template <class T> struct B {
      static const bool value = false;
    };
  }
  template <class T> typename A<B<T>::value>::type f();
  void g() {
    f<int>();
  }


3/18/13  [EDGcpfe/13769]
GNU C++ compatibility: unnamed class types as template arguments

g++ allows unnamed types that are class members to be used as template
arguments starting with version 4.5.  We now emulate this in g++ mode
when gnu_version >= 40500.

  template<class T> void f(const T &);
  struct A {
    enum { e };
    static struct {} b;
  };
  int main() {
    f(A::e);
    f(A::b);
  }


3/18/13  [EDGcpfe/11469,EDGcpfe/13728,EDGcpfe/13039]
Mangling of cv-qualifiers on function types

Previously, cv-qualifiers had only been mangled on non-static member
function types; a change has been made to also mangle cv-qualifiers
on non-member function types as well.  The previous behavior can be restored
by setting ABI_COMPATIBILITY_VERSION to 405 or less.  In this example,
identical mangled names had been generated for the two overloads of
function "f" which had resulted in linker errors:

  template <class T> struct A { };
  typedef void cfn(int) const;
  typedef void fn(int);
  int f(A<fn>) { return 3; }
  int f(A<cfn>) { return -3; }
  int main() {
    int i;
    A<fn> a1;
    A<cfn> a2;
    i = f(a1) + f(a2);
    return i;
  }


3/18/13  [EDGcpfe/13765]
Wrong ABI_COMPATIBILITY_VERSION

The changes for EDGcpfe/12296 (which attempted to restore the previous
mangling for implicit "this") inadvertently used 440 when comparing against
ABI_COMPATIBILITY_VERSION -- the real value should be 404 (to represent
version 4.4).  This is now fixed.


3/15/13  [EDGcpfe/13760]
Redundant source sequence entries for Microsoft in-class specializations

Version 4.5 introduced a change that caused certain nonreal classes
used as base classes to be have actual instantiations done on them
in Microsoft mode.  If such a class contained a Microsoft in-class
specialization that contained a class template, source sequence entries
were generated for the prototype instantiation of the class template
inside the in-class specialization, but should have been suppressed.
Now fixed.


  template <class T, class U> struct A {
    template <int V> struct B;
    template <> struct B<1> {
      template <class V> struct C {
        void f(V){}
      };
    };
  };
  template <class T, class U> class D : public A<T, U> { };


3/15/13  [EDGcpfe/13758]
Folding of address of dependent field selection to a constant

The front end now folds a "->" field selection whose first operand is
a dependent constant address to a tpck_expression constant.  That allows
cases like the following (implementing offsetof) to work in
templates, in modes that do prototype instantiations (e.g., g++ mode
with recent gnu_version numbers):

  template <int N> struct A { 
    int m; 
    A() { 
      int j = __INTADDR__( &(((A*)0)->m) ); 
    } 
  }; 
  A<1> a;


3/14/13  [EDGcpfe/13754]
Lambda in operand of non-polymorphic typeid should get an error

The operand of a typeid is unevaluated if the expression type is not
polymorphic, so a lambda should not be allowed in such an operand.
Now fixed.

  #include <typeinfo>
  struct A {
    const std :: type_info & x = typeid ( [this]{} ) ;
  };


3/13/13  [EDGcpfe/13741]
GNU C++ compatibility: default arguments not considered in certain
prototype instantiations

A change made in version 4.5 could cause spurious errors in the prototype
instantiation of a member function of a class template when a call required
the use of a default argument of another member function of the class
template.  This required g++ mode, a gnu_version >= 40700, a mode or
configuration in which deferral of prototype instantiations is not done
(e.g., a C++-generating back end version), and the --no_parse_templates
option.  Now fixed.

  template <typename T> class A {
    void f(const T& t) {
      return g(t);  // spurious "too few arguments"
    }
    void g(const T&, int = 0);
  };


3/13/13  [EDGcpfe/13714]
Enumerator type in lowered multiplication operation

An operand of a multiplication operation had an enumeration type 
when lowering an array new operation where one of a multi-dimensional
array index was an enumeration type.  A cast has been added to the
underlying type.  For example:

  struct A {}; 
  enum E {} e;
  void f() {
    new A [e][2];
  } 


3/13/13  [EDGcpfe/13748]
GNU C++ compatibility: prototype instantiations not deferred in some cases

In g++ mode in certain configurations, function prototype instantiations
are deferred until the function is first called to allow unused invalid
templates to be accepted as they often are by g++.  Variadic templates
have prototype instantiations done in all modes, but their prototype
instantiations were not being deferred (but should have been) if the
--no_parse_templates option was used.  Now fixed.  This example should
get an error when prototype instantiations are not deferred but not when
they are deferred.

  struct A { };
  template <class ... T> struct B : A {
    const B<T...>& operator=(const B<T...>& rhs) const {
      A::operator=(rhs);
      return *this;
    }
  };


3/13/13  [EDGcpfe/13746]
Incorrect alignment of certain types in defines.h.solaris on Intel Solaris

The sample configuration provided by the defines.h.solaris file specified
incorrect alignment values for long long, double, and long double.  This
could result in incorrect behavior when using structures containing
those data types.  Now fixed.


3/12/13  [EDGcpfe/13740]
Abort on "new" inside "noexcept" inside template argument in function body

The front end got confused on object lifetime memory region issues on
a "new" operator (or other construct that requires object lifetime cleanup)
inside a "noexcept" inside a nontype template argument inside a function
body.  Now fixed.

  int main() {
    int x = 1;
    [](int a[sizeof x]){};  // Formerly aborted with --c++11; now gets error
  }


3/11/13  [EDGcpfe/9249]
Nonstatic data member initializers

We have implemented the "nonstatic data member initializers" (NSDMIs)
feature of C++11, which allows initializers on nonstatic data member
declarations within the class.  See N2756.  For example:

  struct A {
    int i = 1;
    constexpr A() {}  // i gets initial value of 1
    constexpr A(int p) : i(p) {} // Default initial value for i is overridden
  };


3/11/13  [EDGcpfe/8523]
constexpr

We have implemented the "constexpr" feature of C++11, which allows
functions and constructors that return constant values for constant
arguments.  See N2235, and the additions in N3078, N3268, and N3277.
For example, in the following all the constructors, conversion
functions, and operator functions are folded at compile time to
produce a constant value for a3.

  struct A {
    int i;
    constexpr A(int p) : i(p) {}
    constexpr operator int() { return i; }
  };
  constexpr A operator+(A a1, A a2) {
    return A{(int)a1 + (int)a2};
  }
  int main() {
    constexpr A a1{1};
    constexpr A a2{2};
    constexpr A a3 = a1 + a2;
    if (a3.i != 3) return 1;
  }


3/11/13 [EDGcpfe/13715]
Spurious ambiguity in partial ordering and nondeduced contexts

The front end failed to properly order function templates when a template
parameter was only used in nondeduced contexts in the parameter types
of a function template.  Now fixed.

  template<class T> struct A { typedef T type; };
  template<class T> void f(typename A<T>::type&){} // #1
  template <class T, class U> void f(U& t);        // #2
  int main() {
    int i = 1;
    f<int>(i);  // should call #1
  }


3/8/13  [EDGcpfe/11680, EDGcpfe/13645]
Conversion of lvalue to rvalue on volatile discarded-value expression in C++

In C, an lvalue expression at the top level is converted to an rvalue.
In C++03, that was not true.  That surprised some people who counted
on that conversion to force loads from volatile-typed variables, e.g.,

  volatile int x;
  void f() {
    x;    // Fetches x in C, not in C++03
  }

With core issue 1054, the C++11 standard added lvalue-to-rvalue conversions
for volatile lvalues having certain forms in "discarded-value expressions".
This covers only a small fraction of the cases where the conversion is
done in C, but it does cover the cases people were complaining about
and makes C and C++ essentially the same in practical terms.
The front end now does this conversion in C++11 mode, and also in g++
mode (since g++ seems to have done something like this all along,
possibly just following the C rule).


3/7/13  [EDGcpfe/13722]
No instantiation of elided copy constructor for reference in default argument

The change for EDGcpfe/12490 caused elided copy constructors to be
instantiated in certain modes.  In a refinement of that change, the
front end now does not instantiate such copy constructors on an
elided reference in a default argument expression except in strict mode.

  template <class T> struct A {
    A(T *);
    A(A &);  // Suppress A(const A&) copy constructor
    template <class U> A(const A<U>&) {
      int x[-(int)sizeof(U)];  // Cause error, but only in instantiation
    }
  };
  void f(int, A<int> p = 0);  // Formerly provoked error, e.g., in g++ mode

[EDGcpfe/13745, 3/13/13] The same is now done for elided destructors.


3/7/13   [EDGcpfe/13721]
Result of "?" is accidentally considered an xvalue because of folding

The folding of "?" operators with the first operand constant, which
uses the second or third operand value as the folded result, accidentally
made the result an xvalue when the preserved operand is an xvalue.
Now fixed (the folding is not done in such cases).

  int &&f();
  int i;
  decltype(true ? f() : f()) x = i;  // Got spurious error previously


3/5/13   [EDGcpfe/13711]
Wrong type on implicit initializer for array field in braced initialization

In some cases, the front end creates implicit entries representing the
initialization of fields in braced initialization.  For example:

  struct D { D() {} };
  struct A {
    char x[2];
    D d;
  } a = {};

Here the constant representing the "{}" initializer is a ck_aggregate constant
with two sub-constants: One for A::x and one for A::d.  Previously, such
constants for array fields (like for A::x in this example) were given the
wrong type; specifically, they were given the element type instead of the
array type.  This is now fixed.


3/4/13   [EDGcpfe/13703]
Microsoft compatibility: defined() operator in macro expansion

As noted below in the change for EDGcpfe/13211, the Microsoft compiler has
a bug in the handling of the "defined" operator when it appears in the
expansion of a macro instead of directly in the source.  The bug only
occurs, however, when the operand is parenthesized -- "defined(X)" but not
"defined X" -- but the change for EDGcpfe/13211 applied to both forms.
This has now been corrected.  For example:

  #define A 1
  #define PARENS defined(A)
  #define NO_PARENS defined A
  #if PARENS
  #error The Microsoft bug is not emulated
  #endif
  #if !NO_PARENS
  #error The Microsoft bug does not occur without parentheses
  #endif

The front end previously triggered the second #error when microsoft_bugs is
TRUE.  It now, like the Microsoft compiler, processes this example without
error.


3/1/13   [EDGcpfe/13689]
Representation of unresolved alias and weakref attributes (IL CHANGE)

Previously, when the front end could not resolve the name specified in an
"alias" or "weakref" attribute to a declaration in the same translation unit,
it instead recorded the attribute name as an "asm name".  This behavior was
only an approximation of the GCC behavior, but allowed some significant cases
to be handled correctly by the C-generating back end.  Now that attributes
are recorded in detailed form in the IL (see entry for EDGcpfe/8293 etc.)
this is no longer needed: The back end can consult the attribute to determine
the aliased name if needed.  Instead, the front end now sets a new flag
"is_gnu_alias" in variable and routine entries declared with the GNU "alias"
attribute, and similarly with the pre-existing "is_weakref" flag.
The new behavior also avoids problems with the C++-generating back end
transforming a declaration like

  static int xyz_alias() __attribute((weakref("xyz")));

into

  static int xyz_alias() __attribute((weakref("xyz"))) __asm("xyz");

(the latter is not accepted by GCC).

 
3/1/13   [EDGcpfe/13217]
Microsoft compatibility: unterminated macro invocations inside macro arguments

As noted below in the change for EDGcpfe/8933, the Microsoft preprocessor
allows an invocation of a function-style macro to begin inside a macro
argument and terminate in text following that invocation.  The change for
EDGcpfe/8933 only permitted the closing parenthesis for such invocations to
appear in the main program text following the top-level macro invocation.
In fact, the Microsoft preprocessor accepts a closing parenthesis in the
expanded text of a containing macro invocation as well, a feature used in
some complex Microsoft-mode Boost preprocessing code.  The front end now
accepts such cases in Microsoft bugs mode as well.  For example, the
following now produces an empty expansion, as it does with the Microsoft
preprocessor:

  #define BOOST_PP_CAT(a,b) BOOST_PP_CAT_I(a, b)
  #define BOOST_PP_CAT_I(a,b) BOOST_PP_CAT_II(a##b)
  #define BOOST_PP_CAT_II(res) res
  #define BOOST_MPL_PP_IS_SEQ(seq) BOOST_MPL_PP_IS_SEQ_(seq)
  #define BOOST_MPL_PP_IS_SEQ_(seq) \
     BOOST_PP_CAT(BOOST_MPL_PP_IS_SEQ_, BOOST_MPL_PP_IS_SEQ_0 seq ) )
  #define BOOST_MPL_PP_IS_SEQ_0(x) BOOST_MPL_PP_IS_SEQ_1(x
  #define BOOST_MPL_PP_IS_SEQ_ALWAYS_0(unused) 0
  #define BOOST_MPL_PP_IS_SEQ_BOOST_MPL_PP_IS_SEQ_0 \
     BOOST_MPL_PP_IS_SEQ_ALWAYS_0(
  #define BOOST_MPL_PP_IS_SEQ_BOOST_MPL_PP_IS_SEQ_1(unused) 1
  #define BOOST_PP_BOOL(x) BOOST_PP_BOOL_I(x)
  #define BOOST_PP_BOOL_I(x) BOOST_PP_BOOL_##x
  #define BOOST_PP_BOOL_0 0
  #define BOOST_PP_BOOL_1 1
  #define BOOST_PP_COMPL(x) BOOST_PP_COMPL_I(x)
  #define BOOST_PP_COMPL_I(x) BOOST_PP_COMPL_ID(BOOST_PP_COMPL_##x)
  #define BOOST_PP_COMPL_ID(id) id
  #define BOOST_PP_COMPL_0 1
  #define BOOST_PP_COMPL_1 0
  #define BOOST_PP_NOT(x) BOOST_PP_COMPL(BOOST_PP_BOOL(x))
  #define BOOST_PP_IIF(bit,t,f) BOOST_PP_IIF_I(bit, t, f)
  #define BOOST_PP_IIF_I(bit,t,f) BOOST_PP_IIF_II(BOOST_PP_IIF_##bit(t, f))
  #define BOOST_PP_IIF_II(id) id
  #define BOOST_PP_IIF_0(t,f) f
  #define BOOST_PP_IIF_1(t,f) t
  #define BOOST_PP_TUPLE_EAT_1(e0)
  #define BOOST_PP_ASSERT_D(cond) \
     BOOST_PP_IIF(BOOST_PP_NOT(cond), \
     BOOST_PP_ASSERT_ERROR, BOOST_PP_TUPLE_EAT_1)(...)
  #define BOOST_PP_ASSERT_ERROR(x,y,z)

  BOOST_PP_ASSERT_D( BOOST_PP_NOT( BOOST_MPL_PP_IS_SEQ(a) ) )


2/27/13  [EDGcpfe/13691]
Undefined behavior when mangling dependent dynamic_cast in IA-64 ABI

The mangling of a dependent dynamic_cast in IA-64 ABI configurations had
resulted in a stack pointer erroneously being used in the IA-64 ABI
substitution mechanism, potentially causing undefined behavior.  Now fixed.
Here's an example that had caused this issue in some configurations
(with --c++11):

  struct B {} b;
  struct D : B {} d;
  template <class T> auto f(T p1) -> decltype(dynamic_cast<B&>(p1),p1);
  void g() {
    f(d);
  }


2/26/13  [EDGcpfe/13690]
Warning on unused variable whose initializer creates a temporary

When an unused variable appears in the source program, the front end
gives a warning unless the initializer for the variable has a side
effect (if it does, the warning is reduced to a remark).  In the past,
creation of a temporary was considered a side effect, so a declaration
like the reference initialization in

  int main() {
    const int &i = 1;
  }

formerly got no warning.  Now, for this purpose, the act of creating
the temporary itself is not considered a side effect, so an example
like the above now gets a warning about an unused variable.


2/25/13  [EDGcpfe/13560]
Explicit declaration of operator delete wrongly treated as never throwing

The implicit declaration of ::operator delete (and ::operator delete[]) is
marked as never throwing (a_routine::never_throws flag is TRUE).  However, an
explicit declaration of that function can override that behavior.  Previously,
the front end failed to reset the never_throws flag in such cases, which e.g.
resulted in a wrong result with the "noexcept" operator.  For example:

  void operator delete(void*) noexcept(false) {}
  static_assert(!noexcept(delete (char*)nullptr), "Error!");
    // Previously this assertion failed; now accepted.

This is now fixed.


2/25/13  [EDGcpfe/13685]
Assertion failure during generation of error message with anonymous union

An error message (ec_name_at_decl_position) triggered with an anonymous
union had generated an assertion failure ("diag_message: missing symbol
substitution"); this is now fixed.  For example (with --c++11):

  struct A {
    A() {}
  };
  void f(int n) {
    switch (n) {
      union {A a;};
      case 1:
        break;
    }
  }


2/21/13  [EDGcpfe/13674]
Microsoft compatibility: checking of type in static data member instantiation

The Microsoft compiler does not check that the type in a static data
member explicit instantiation matches the declared type of the static
data member.  We now emulate this in Microsoft mode (with a warning).

  template <class T> struct A {
    static int I;
  };
  template <class T> int A<T>::I = 1;
  template void* A<int>::I;


2/21/13  [EDGcpfe/12973]
Scoped enumeration value as switch expression

The front end (in C++11 mode) now accepts a scoped enumerator value
as a case expression.

  enum class scoped_enum {se0};
  void foo(scoped_enum p) {
    switch(p) {
      case scoped_enum::se0: break;
    }
  }


2/20/13  [EDGcpfe/13664]
Bug in handling of nested initializer lists

The front end incorrectly handled some cases involving nested initializer
lists and initializer-list constructors.  Now fixed.

  #include <initializer_list>
  struct A {
    A(std::initializer_list<int> p) {}
  };
  struct B {
    B(std::initializer_list<A> p) {}
  };
  int main() {
    B b {{4,5,6}, {7,8,9}};
  }


2/20/13  [EDGcpfe/13655]
Microsoft C++: suppressing errors on decltype in nested template declaration

The MSVC compiler does limited parsing of decltype expressions when a
template declaration is scanned, and as a consequence in a case like
the one below it gives no error on the declaration where the nested
template uses a template parameter from the enclosing template that is
known when the template declaration is processed in the instantiation
of A<B> (that is, Fun().func() is not dependent then and should get an
error).  We now avoid that error as well, leaving it to be caught
(silently) during SFINAE processing.

  template<typename Fun> struct A {
    template<class U>
    static decltype(Fun().func(), char()) Test(Fun* f); // Does not use U
    template<class U> static int Test(...);
    static const bool value = sizeof(Test<Fun>((Fun*)0)) == sizeof(char);
  };
  struct B {
    void func(int);
  };
  int main() {
    int a[!A<B>::value ? 1 : -1];
  }


2/18/13  [EDGcpfe/13652]
Missing start position for direct braced initializer

In modes accepting direct braced initialization of variables (such as C++11
mode), the front end failed to record the position of the start of the
initializer (in configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE).
For example:

  int v{1};  // Previously, vp->initializer_range.start (where vp points to
             // the a_variable entry) did not represent the position of the
             // left brace.

This is now fixed.


2/18/13  [EDGcpfe/13663]
GNU compatibility: __builtin_nans in constant-expressions

The front end now evaluates calls to __builtin_nans (and __builtin_nansf and
__builtin_nansl) to constant floating-point values if the argument to the
call is an empty string literal.  See also the Changes entry of 11/19/03.


2/18/13  [EDGcpfe/13662]
GNU C++ compatibility: Folding of dependent built-in function calls

Previously the front end treated calls to GNU __builtin_... functions that
involve template-dependent arguments as not constant.  This could result in
spurious errors.  For example:

  template <int N> struct X {
   static const int S = __builtin_clzll(N);  // Previously an error; now
  };                                         // accepted.

Now calls to foldable GNU __builtin_... functions for which all arguments
are constants are treated as potentially constant during generic template
processing if at least one of the arguments is template-dependent in any way.
(Such calls may still be considered nonconstant when they are instantiated.)


2/17/13  [EDGcpfe/13669]
Out-of-class inline declaration of key function suppresses destructor

In configurations where the key function for a class is determined at the
end of the compilation (i.e., Cfront ABI and when IA64_ABI_VARIANT_KEY_FUNCTION
is TRUE), a key function candidate that isn't declared inline, but whose
out-of-class definition is inline (and therefore isn't eligible to be a
key function) can result in a virtual destructor being suppressed.
In this example, D::~D had not been emitted (even though it is referenced
from the vtable):

  struct B {
    virtual void f();
    virtual ~B() {}
  };
  struct D : B {
    D() {}
    virtual void f();
  };
  inline void D::f() {}
  int main() {
    D *d = new D();
    d->f();
    return 0;
  }


2/15/13  [EDGcpfe/13613]
Spurious warning when building front end with Microsoft compilers

Building the front end with Microsoft compilers could potentially produce a
spurious warning about an uninitialized local variable "saved_is" in function
process_simple_init_component (decl_inits.c).  Some code in that function has
been rearranged to avoid that warning.


2/15/13  [EDGcpfe/13639]
GNU C++ compatibility: Effect of "packed" pragma on non-POD fields

The changes for EDGcpfe/12297 (see entry of 9/28/11) cause the front end to
ignore a packing directive applied to a class when aligning its field of
non-packed, non-POD class type.  However, it appears GCC only ignores the
packing directive imposed by attributes in this way: Packing directives from
"#pragma pack(n)" directives remain in effect.  For example:

  struct NonPOD { NonPOD(); int x; };
  #pragma pack(2)
  struct __attribute((packed)) P {
    NonPOD np;
    char c;
  };
  #pragma pack()

Assuming type int is 4-byte aligned and GNU mode with gnu_version >= 30400,
field np would previously have been aligned to a 4-byte boundary, and type P
would have had size 8.  Now field np is aligned to a 2-byte boundary (as
constrained by the pragma) and type P has size 6.


2/15/13  [EDGcpfe/8523]
New ck_address/abk_temporary constant (IL CHANGE)

As part of the changes for constexpr, we have added a new subkind under
the ck_address constant kind.  The new subkind, abk_temporary, produces the
address of a static temporary initialized with a given constant.  It's
similar to abk_constant, but applicable to constants that don't have
an inherent memory object, e.g., integer constants.


2/12/13  [EDGcpfe/13578]
C++-generating back end: #pragma pack for union defined in typedef

In configurations with USER_CONTROL_OF_STRUCT_PACKING set to TRUE, the
C++-generating back end sometimes put out a #pragma pack directive
following the typedef keyword in a typedef declaration that defines a
union.  This is now fixed.  For example, with

  template<typename T> const int &f();
  #pragma pack(push,8)
  template<typename T> const int &f();
  typedef union U {
    int i;
  } U;

compiled with --no_parse_templates, the typedef declaration was previously
generated as

  typedef
  #pragma pack(8)
  union U {
    int i;
  };


2/12/13  [EDGcpfe/13558]
Abort on invalid attempt to use default argument of template

The front end aborted ("copy_default_arg_expr: rout NULL, no error")
on an attempt to use a default argument of a function type that
came from a template but now refers to no specific function.
Now fixed (the case below gets an error).

  template <class T> struct A {
    void f(int dummy = 0)  { }
  };
  int main() {
    (A<short>().*(&A<short>::f))();
  }


2/12/13  [EDGcpfe/13194]
Microsoft compatibility: partial ordering and references to functions

The Microsoft compiler considers a reference to function to be more
specialized than a pointer to function for partial ordering purposes.
This is only the case when the reference/pointer parameter is the only
parameter considered by partial ordering.  We now emulate this in
Microsoft mode.

  template <class T> void f(T (&)()){}  // #1
  template <class T> void f(T (*)()){}  // #2
  template <typename T> void f(T** p, void (*)()) {}  // #3
  template <typename T> void f(T* p, void (&)()) {}  // #4
  void g() {}
  int main() {
    int **p = 0;
    f(g);  // calls #1
    f(p, g); // calls #3
  }


2/12/13  [EDGcpfe/13640]
Invalid code from inlining

Inlining produced invalid code for the following test case.  The
actual problem was that the type of an lvalue intermediate result
was not adjusted, which might also have caused some other problems,
also presumably now fixed.  The cases which had the problem all
involve a conversion function that returns a (non-const) reference
to a non-class object.

  struct A {
    int m;
    operator int&() { return m; }
  };
  struct B {
    A a;
    int const& f() { return a; }  // Was missing type adjustment on result of
                                  // conversion function call (int->const int);
                                  // inlined code aborted at runtime
  };
  int main() {
    B b;
    b.a.m = 99;
    return b.f() != 99;
  }


2/12/13  [EDGcpfe/13562]
noexcept operator applied to call of via pointer-to-member-function

The determination of the value of a noexcept operator failed to
handle a pointer-to-member call properly, always concluding that the
call might throw an exception.  Now fixed; the exception specification
of the called function type is considered.

  struct A {
    void g() noexcept(true) {}
  };
  static_assert(noexcept((A().*(&A::g))()), "pm call can't throw");


2/12/13  [EDGcpfe/13577]
C++-generating back end: GNU vector typedefs as template arguments

When a typedef for a GNU vector type is used as a template argument, the
C++-generating back end previously replaced the typedef with the vector
base type, resulting in incorrect code.  This is now fixed.  For example:

  template <typename T> struct S { };
  typedef float v4f __attribute__((vector_size(16)));
  S<v4f> s;    // Previous generated as S<float>


2/12/13  [EDGcpfe/13582]
C++-generating back end: incorrect parentheses for explicit temporary with
operator() in Sun mode

In Sun mode, the C++-generating back end incorrectly parenthesized an
explicit temporary that was used as the object expression in a call to an
overloaded function call operator (operator()), transforming the object
expression into a cast to a function type.  This is now fixed.  For
example:

  struct S {
    int operator()(int);
  };
  int i = S()(3);    // Previously generated as (S())(3)


2/12/13  [EDGcpfe/13574]
C++-generating back end: unnecessary parentheses with explicit temporaries in
initializer constants

In addition to the cases described below for EDGcpfe/13355, EDGcpfe/13375,
EDGcpfe/13423, and EDGcpfe/13523, early versions of g++ are also confused
by redundant parentheses around an explicit temporary appearing in an
initializer.  When such initializers are represented in the IL as
constants, the C++-generating back end previously unnecessarily enclosed
them in parentheses.  These parentheses are now suppressed.  For example:

  struct A {};
  typedef int A::* P;
  P a = P();    // Previously generated as (P())


2/12/13  [EDGcpfe/13625]
Microsoft C++: __is_convertible_to with reference type as second argument

The implementation of __is_convertible_to in Microsoft mode has been
corrected so that rvalue reference cases like __is_convertible_to(int, int&&)
and lvalue reference to const cases like __is_convertible_to(int, const int &)
now correctly return true.

  const bool b = __is_convertible_to(int, int&&);
  static_assert(b, "int should be convertible to int&&");
  const bool b2 = __is_convertible_to(int, const int &);
  static_assert(b2, "int should be convertible to const int &");


2/11/13  [EDGcpfe/13575]
GNU C++ compatibility: error on injected class as template template argument

A change in version 4.5 caused an injected class name of a class template
to be rejected as a template template argument when gnu_version >= 40500
(note that such usage is a g++ extension).  Now fixed.

  template <class T> struct A {
    int f();
  };
  template <template <class> class TT, class T> struct B : TT<T> {
    int f();
  };
  struct C : B<A,int> {  // okay -- refers to ::A
    int f() {
      return B<A,int>::f();  // error on this use of A<int>::A
    }
  };
  int main() {
    C c;
    c.f();
  }


2/9/13   [EDGcpfe/13123]
Reference to deleted function causes SFINAE failure

Selection of a deleted function (i.e., marked "= delete") in overload
resolution now causes a deduction failure in a SFINAE context.
This is similar to what happens when an inaccessible function is
referenced in a SFINAE context.

  struct A {
    operator int();
  };
  A operator+ (A, A) = delete;
  template <class T> auto f(T p) -> decltype(T() + T());
  int f(int);
  int main() {
    A a;
    int i = f(a);  // Now accepted, template "f" fails SFINAE with no error
  }


2/8/13   [EDGcpfe/13638]
Abort on noexcept applied to ambiguous delete

The front end aborted (in il.c, alloc_or_dealloc_routine_from_new_delete)
on a noexcept operator applied to a delete operation where the delete
routine to be called was ambiguous.  Now fixed.

  void operator delete (error);
  int main() {
    noexcept(delete (char*)0);
  }


2/8/13   [EDGcpfe/13635]
Abort on noexcept applied to overloaded function

The front end aborted ("extract_node_from_operand: converting unexpected
operand kind") on a noexcept operator applied to the name of an overloaded
function.  Now fixed (an error is issued).

  void f();
  void f(int);
  int main() {
    noexcept(f);
  }


2/7/13   [EDGcpfe/13631
C-generating back end: line break in name of promoted base class member

In configurations in which tail-padding reuse is enabled (see the entry for
EDGcpfe/11008 below), the name of a very deeply-nested promoted base class
member could be split over two lines.  This is now fixed.  For example:

  struct A1 { virtual A1* f(); };
  struct A2 : A1 { virtual A2* f(); };
  struct A3 : A2 { virtual A3* f(); };
  struct A4 : A3 { union {}; virtual A4* f(); };
  struct A5 : A4 { virtual A5* f(); };
  // ...
  struct A37 : A36 { virtual A37* f(); };

In the generated code, the temporary (__T12345678) name given to the
unnamed union in class A4, promoted into the declaration of class A37,
was previously broken over two lines.


2/6/13   [EDGcpfe/13573]
Spurious errors on some array designators in some GNU C modes

Version 4.5 introduced a regression in GNU C modes with gnu_version < 40000
causing the front end not to accept an array designator chained after a
C99-style field designator.  For example:

  struct S { int b[2]; } s = { .b[1] = 2 };
    // Previously the "[1]" designator was not recognized in some
    // GNU C modes.

This is now fixed.


2/6/13   [EDGcpfe/13627]
C-generating back end: tail padding-reuse and initialization as assignment

In configurations in which tail-padding reuse is enabled (see the entry for
EDGcpfe/11008 below), when IL lowering rewrites initialization as
assignments the C-generating back end could generate incorrect code: the
base class members were correctly promoted into the derived class, but the
initialization code referred to the base class members as if they appeared
in a nested struct member representing the base class.  This is now fixed.
For example:

  struct A {
    virtual void f();
    int y = 37;
  };
  struct B : A {
    int x = 47;
  };
  int main() {
    B{};   // Initialization of B::A members used incorrect names
  }


2/6/13   [EDGcpfe/13623]
Type "auto" replaced by an error type during lowering

Under some circumstances, the representation of the "auto" type specifier
(which is a special tk_template_param entry) in a declared_type field could
previously be erroneously replaced by an error type during IL lowering.
For example:

  int main() {
    auto *p = new int(4);  // Previously "auto" in the declared_type of the
  }                        // variable entry representing p was replaced by
                           // an error type during IL lowering.

This is now fixed.


2/5/13   [EDGcpfe/13611]
Addition of tpck_noexcept template parameter constant kind (IL CHANGE)

When the noexcept operator was first introduced (see the Changes entry
of 9/3/12), dependent noexcept operators were represented by
tpck_expressions on top of eok_noexcept operations.  This represented
a departure from the typical representation for operators like this
(i.e., sizeof, alignof, typeid, uuid), but we felt the IL was cleaner.
However, due to memory region issues in cases where a noexcept operation
is used as an array bound, we've reversed our decision and have now
added a tpck_noexcept template parameter constant kind (similar to
tpck_sizeof, et al.).  For example (with --c++11):

  struct A { };
  void f(int) noexcept;
  void f(float) throw (A);
  template <class T> void g(T p) {
    int arr[noexcept( f(p) )];
  }
  int main() {
    g(1);
  }


2/4/13   [EDGcpfe/13606]
GCC compatibility: extern __inline function definition replacement

GNU C and C++ mode allow a function definition to be provided "for inlining
purposes only" (using "__attribute((gnu_inline))" in GNU C++ mode or
"extern __inline" in GNU C mode).  Previously, such declarations were
displaced (with a warning) only when another matching definition appeared
(see Changes entries of 7/13/11 and 6/18/02).  Now, they are displaced by
any matching declaration that doesn't imply "for inlining only" semantics,
and a warning is no longer issued.  For example:

  extern __inline void f() {}  // For inlining only.
  extern void f();             // Now displaces the prior definition.
  int main() {
    f();                       // Not inlined.
  }

If this example is compiled and linked by itself, a linker error ensues
because no ordinary definition is provided (the original "for inlining only"
definition has been discarded by the subsequent declaration).

This new behavior interacts with "asm name" specifiers.  For example:

  extern __inline void g() {}  // For inlining only.
  extern void g() __asm("gg");
  int main() {
    g();
  }

Previously, the second declaration of g in this example was treated as an
ordinary redeclaration of the for-inlining-only definition, and the asm name
was discarded with a warning (because the "asm name" cannot be changed after
the definition has been seen).  Now, since the second declaration displaces
the prior definition, the asm name is recorded normally and the call to g in
main requires a definition of the symbol "gg" rather than a function "g".


2/1/13   [EDGcpfe/13610]
Internal error on use of Microsoft __w64-annotated type

In Microsoft-compatible configurations, the front end could abort with an
internal error in ilp64_will_narrow (types.c) when converting a 64-bit type
with a __w64 annotation to a 32-bit integral type.  For example:

  typedef int Int;
  typedef __w64 long Long;

  void g(Long x) {
    Int i = (Int)x;  // Previously triggered an internal error in some
  }                  // 64-bit configurations.

This is now fixed.


1/31/13  [EDGcpfe/13609]
Microsoft compatibility: ambiguity on class template with virtual base classes

A change made in version 4.5 (see EDGcpfe/12786 on 5/14/12) could result
in a spurious ambiguity in Microsoft mode on a reference to a member of
a virtual base class, when the same virtual base class was instantiated
based on different template parameters (in the example below A is instantiated
based on both T and T2 from D).  Now fixed.

  template <typename T> struct A {
   struct AA {};
  };
  template <typename T> struct B : virtual public A<T> {};
  template <typename T> struct C : virtual public A<T> {};
  template <typename T, typename T2> struct D : public C<T> , public B<T2> {
    AA x;
  };


1/29/13  [EDGcpfe/13201,EDGcpfe/13202]
Proxy class for template parameters used in pointer-to-members

In cases like "int (T::*)()", where T is a template parameter, the template
parameter T should be replaced with a proxy class, but hadn't been, leading to
mangled names that had "?" characters.  Additionally, a change was made to the
substitutions mechanism in the IA-64 ABI to prevent proxy classes from being
mangled twice (leading, in some configurations to an "alloc_substitution:
missed mangling substitution" assertion failure).  The mangling change
is contingent on ABI_COMPATIBILITY_VERSION >= 406.  For example (with --c++11):

  template <class Z> using B = int Z::X::*;
  template <class... T> void f(B<decltype(T())>... args);
  int main() {
    f();
  }


1/28/13  [EDGcpfe/9569, EDGcpfe/9603, EDGcpfe/12396, EDGcpfe/12911,
          EDGcpfe/13595]
GNU compatibility: binary literals

Binary literals are now supported in GNU mode when gnu_version >= 40300.

  int i = 0b01;


1/28/13  [EDGcpfe/13603]
Lowering of array variable in nested lambdas

In cases where an array variable is captured by reference in a lambda, then
subsequently captured by a nested lambda, lowering had failed an assertion
check (in implied_copy_of_source).  For example (with --c++11):

  void f(const int*) {}
  int main() {
    int A[2] = {0, 1};
    [&](){
       [=]() { f(A); }();
    }();
  }


1/28/13  [EDGcpfe/13008]
Internal error on noexcept or partial specialization in invalid scope

In general, the front end recovered successfully from a template declaration
in an invalid scope (such as a function or block scope).  However, certain
template constructs (noexcept specifications and partial specializations)
could result in an internal error (in get_parent_information_for_template).
Now fixed.

  void f() {
    template <class T> void g(T) noexcept(true);
  }


1/27/13  [EDGcpfe/13605]
Incorrect backing expression on static selection of named constant

A static selection in which the right operand is a named constant yielded
a constant result with a backing expression for the static selection, but
with is_named_constant_definition still (incorrectly) set. 
If there is a subsequent type change, the backing expression was changed
to an incorrect one, which caused incorrect cp_gen_be output.  Now fixed.

  struct {
    enum E { e0, e1 };
  } a;
  struct B {
    int bitfield : a.e1; // a.e1 allowed in Microsoft mode
                         // cp_gen_be output was like __T3328184::e1
  } b;


1/25/13  [EDGcpfe/13602]
Abort during determination of "this" in lambda return type

The front end aborted in lambda_body_for_closure after incorrectly
determining the meaning of "this" in the return type of a lambda.
"this" in that case should refer to the "this" of the enclosing
context.  Fixed.

  struct A {
    int j;
    int i = []()->decltype(this->j) { return 0; }();
  };


1/25/13  [EDGcpfe/13601]
Wrong cv-qualifiers on type of non-class temporary for reference binding

In some cases, the temporary created as part of binding a reference to
const to a non-class expression did not have the cv-qualifiers
specified by the C++ standard.  For example, in

  const int &r = 5;

the temporary had type "int" instead of "const int".  This made no
significant difference, but may have precluded some optimizations
(e.g., knowing that the above temporary's value could never change).
The cv-qualifiers are now correct.


1/24/13  [EDGcpfe/13600]
Incomplete aggregate initializer produces bad IL/bad generated C code

Initializing an aggregate class containing a field of array-of-scalar type
followed by a field requiring a nontrivial constructor call could lead to
invalid IL if the initializer was a braced list that did not specify an
actual value for the array field (and the subsequent fields).  This invalid
IL in turn resulted in invalid C code when processed through the C-generating
back end.  For example (using C++11 mode):

  struct X { X() {} };
  struct A {
    char a[3];  // Array-of-scalar-type field.
    X x;        // Field requiring a call to a nontrivial constructor.
  };
  int main() {
    return A{}.a[0];  // The initialization represented by "A{}" previously
  }                   // resulted in invalid IL and erroneous generated C
                      // code.

This is now fixed.


1/23/13  [EDGcpfe/13598]
Spurious error on opaque enum declaration following its definition

The front end previously incorrectly issued an error when an enumeration was
first defined and then declared using an opaque enum declaration.
For example:

  enum E: int { e, g };
  enum E: int;  // Previously triggered a spurious error; now okay.

This is now fixed.


1/22/13  [EDGcpfe/13590]
Spurious error on inaccessible destructor in SFINAE initializer_list creation

A creation of a std::initializer_list object within a SFINAE context
issued a spurious error if the destructor for the member type is
inaccessible.  In a SFINAE context, an error like that is supposed to
merely cause the deduction to fail.  Now, it does.

  #include <initializer_list>
  struct A {
    A(int);
  private:
    ~A();
  };
  template <class T> auto f(T p) -> decltype(std::initializer_list<A>{p});
  void f(...);
  int main() {
    f(1);
  }


1/18/13  [EDGcpfe/13580]
Ambiguity on partial ordering of variadic templates

The front end considered two variadic function templates as unordered
even if the variadic template parameter was not actually used in the
signature of the function template.  The precise rules for such cases
are incorrect in the standard and are in the process of being worked
out by WG21.  The likely outcome is that #2 should be preferred over
#1 because the variadic parameter is not used by the call.  We have
now implemented this behavior (which matches g++) pending clarification
of the standard.

  template<typename T, typename... Args> void f(const T&, Args...);  // #1
  template<typename T, typename ... Args> void f(const T&){}  // #2
  int main() {
   f(1);
  }


1/17/13  [EDGcpfe/9165,EDGcpfe12833]
C++11: Unrestricted unions

In traditional C++, unions cannot contain fields with nontrivial construction,
assignment, or destruction semantics.  C++11, however, does permit such fields
but if a corresponding constructor, destructor, or copy assignment operator is
generated, it is implicitly "deleted".  The front end now implements the new
rules in C++11 mode or when the option --unrestricted_unions is specified on
the command line.  For example:

  struct S { S(); };
  union U {
    S s;  // Previously an error; now accepted in C++11 mode.
    int i;
  };
  U u;  // Error: The generated default constructor of U is deleted.

Furthermore, when unrestricted unions are enabled, unions can also contain
static data members.

Currently, unrestricted unions cannot be enabled in Microsoft C++ modes
because it is unclear how the feature should interact with the nonstandard
treatment of implicitly deleted special members in those modes.


1/17/13  [EDGcpfe/13585]
Microsoft mode: initialization of local static variable

Due to a typo in the original fix (see Changes entry for 5/8/08), the
initialization for a local static variable in an inline function with a
DLL interface in Microsoft mode in configurations that use lowering had been
initk_none, but is now initk_zero.  For example:

  struct __declspec(dllexport) X {
    X();
  };
  __declspec(dllexport) inline void f() {
    static X x;  // initializer kind had been initk_none and is now initk_zero
  }


1/16/13  [EDGcpfe/13584]
Internal error on nested C-style ellipsis in variadic function template

An internal error could occur (in end_potential_pack_expansion_context)
if a variadic function template contained a nested declarator with a
C-style ellipsis parameter.  Now fixed.

  template < typename ... T> void f(void (*)(int,...));


1/15/13  [EDGcpfe/12444]
GNU C++ compatibility: specializations of class members in invalid namespaces

g++ allows a member of a class template to be specialized in an invalid
namespace.  This is allowed for static data members in all g++ versions.
It is allowed for other class members for g++ versions prior to 4.1.  We
now emulate this behavior in g++ mode as appropriate for a given gnu_version
value.

  template <typename T> class A {
   static int I;
   void f();
  };
  namespace N {
   template <> int A<int>::I;  // okay in g++ mode for any gnu_version
   template <> void A<int>::f(){} // okay in g++ mode for gnu_version < 40100
  }


1/15/13  [EDGcpfe/13579]
Abort after error on use of C++/CLI event

The front end used an uninitialized variable after issuing an error
on a use of a C++/CLI event.  The use of the uninitialized variable
caused garbage on an available list, which could manifest itself
later in various kinds of aborts.  Now fixed.

  delegate void D();
  ref struct S {
    event D^ e {
      void add(D^);
    }
  };
  void f(S ^s, D ^d) {
   s->e -= d;
  }


1/14/13  [EDGcpfe/13334]
Merging of default template arguments across declarations

Default template arguments for function templates were added to C++11
(see EDGcpfe/7122 on 6/23/10), but the front end failed to merge the
set of default arguments provided across multiple declarations.
Now fixed.

  template <int, int> int f();
  template <int i = 1, int j = 2> int f() { return i+j; }
  int  k = f();  // now accepted


1/14/13  [EDGcpfe/13169]
GNU compatibility: Lowering of assigned goto expressions

The expression in a GNU assigned goto statement was never lowered causing
unlowered IL to be emitted by the front end.  The case below had caused
an assertion failure (in dump_expr) in C-generating configurations (with
--g++):

  int f(int x) {
    goto *(x ? &&A : &&B);
  A: return 0;
  B: return 1;
  }


1/13/13  [EDGcpfe/13567]
Dangling pointers to some inlined call expressions

In some cases during inlining, the call expression to be inlined is
replaced by a block statement rather than by re-writing the expression.
In those cases, the original expression has been detached from the IL
tree (and portions of the original expression may have been used to
create the inlined code, thereby rendering the original expression
invalid).  In some cases, lowering had continued to process the original
expression which, after the changes for EDGcpfe/13231 and in configurations
where EXPENSIVE_CHECKING is TRUE, had led to an abort (in
node_operands_have_correct_lvalueness) on this case:

  struct A {
    void g() {}
  } a;
  A f() { return a; }
  main () {
    f().g();
  }

Changes have been made to ensure that dangling pointers to the original
expression are not used.


1/10/13  [EDGcpfe/12749]
GNU C++ compatibility: __bases and __direct_bases operators

The g++ __bases and __direct_bases operators are now supported in g++
mode when gnu_version >= 40700.  These are needed to support the GNU
tr2/type_traits header.  The argument of the operators must be a type
template parameter and in an instantiation the actual type argument
must be a class type.  Use of the operators in deduction and substitution
contexts is not supported, as is the case with g++.

  struct A {};
  struct B {};
  struct C : public A, B {};
  struct D : public C {};
  template <typename... Elements> struct typelist { };
  template <typename T> struct bases {
    typedef typelist<__bases(T)...> type;
    type t;
  };
  template <typename T> struct direct_bases {
    typedef typelist<__direct_bases(T)...> type;
    type t;
  };
  bases<D> b;  // instantiates typelist<A,B,C>
  direct_bases<C> d;  // instantiates typelist<A,B>


1/10/13  [EDGcpfe/13572]
is_partially_initialized flag set incorrectly on std::initializer_list objects

The is_partially_initialized flag had been set incorrectly on some
dynamic initializations involving std::initializer_list objects raising
the possibility that back ends might not properly initialize the
std::initializer_list object.  This is now fixed.  For example (with --c++11):

  #include <initializer_list>
  int main() {
    std::initializer_list<int[3]> x = {
      {},
      {1,2,3}
    };
    return (x.begin()[0][0] | x.begin()[0][1] | x.begin()[0][2]);
  }


1/10/13  [EDGcpfe/13571]
Designated initializers in unions with partial aggregate initialization

In C-generating back end configurations, the re-computation of the
is_partially_initialized flag during lowering for a dynamic init had been
incorrect in some cases involving designated initializers in unions,
resulting in generated C code that failed to completely initialize
the target.  This has now been fixed.  Additionally, the partial_aggr_value
flag of a_constant is now also set during the re-computation of the
is_partially_initialized flag (previously the value originally determined
by the front end had been passed through lowering, irrespective of
changes made to the constant when lowering designated initializers).
This example (with --c99) had left the last two elements of the array
uninitialized:

  extern int printf(const char *,...);
  union A {
    int b[2][2];
  };
  int main() {
    int x;
    x = 99;
    union A u = { { [0][1] = x } };
    printf("%d %d %d %d\n", u.b[0][0], u.b[0][1], u.b[1][0], u.b[1][1]);
    return (u.b[0][0] + u.b[0][1] + u.b[1][0] + u.b[1][1]) != 99;
  }


1/9/13   [EDGcpfe/13231]
Original lvalue type now captured on lvalue-to-rvalue conversion

A new field, orig_lvalue_type, has been added to an_expr_node to capture
the original type of the lvalue when an expression is converted from an
lvalue to an rvalue simply by clearing the is_lvalue flag.
cv-qualifiers are dropped during the lvalue-to-rvalue conversion, and prior
to this change the original lvalue type (with any cv-qualifiers) had not been
available in the IL.  orig_lvalue_type is also set for casts to reference
types (i.e., when is_reference_cast is TRUE), to the underlying type
of the cast (whether the cast produces an lvalue or rvalue).  See
destination_type_for_reference_cast.  The orig_lvalue_type field is
NULL otherwise, and (for now at least) it's NULL if the expression
was created during the lowering process.


1/8/13   [EDGcpfe/13270]
Microsoft mode: function found in dependent base considered dependent

In Microsoft mode with --parse_templates, name lookup in the prototype
instantiation can find member functions in a dependent base class.
The implementation for that was changed in version 4.5 (see EDGcpfe/12786
on 5/14/12), and that caused a regression in some cases like the
following, because we assumed we had full information on the base
class member function in the prototype instantiation even though we
don't have it until the real instantiation.  Now working again.

  template<class T> struct A {       
    void f(char *p1 = 0) {}
  };
  template<class T> struct B : public A<T> {       
    typedef A<T> Dep;
    B() {       
      Dep::f();  // Formerly gave a spurious error "too few arguments" error
    }
  };
  B<char> b;


1/8/13   [EDGcpfe/13354]
Aggregate initialization of GNU vectors

In all GNU C++ modes and in GNU C modes with gnu_version >= 40500 the
aggregate initialization of a vector subobject no longer requires braces
(similarly to standard array and aggregate struct types).  For example:

  void g() {
    __attribute((vector_size(8))) int x[1] = { 37 };
  }       // Now accepted and treated as "... = { { 37 } };".


1/8/13   [EDGcpfe/13566]
Default setting for implicit noexcept specifiers

In strict C++11 mode, the front end generates implicit noexcept specifiers
for certain destructors and deallocation functions (see the entry of 9/3/12).
Now a new configuration macro DEFAULT_IMPLICIT_NOEXCEPT_ENABLED determines
whether this behavior should also apply to default C++11 mode.  The macro is
set to TRUE by default, which changes some cases in default C++11 mode.
For example:

  struct B { virtual ~B() noexcept; };
  struct D: B { virtual ~D(); };

Previously an error was issued on this example in default C++11 mode (but not
in strict C++11 mode) because the exception specification on the derived
class destructor is incompatible with (i.e., more relaxed than) the
overridden destructor.  Now, by default, the derived class destructor is
implicitly "noexcept", and hence the exception specifications are compatible.


1/8/13   [EDGcpfe/13523]
C++-generating back end: unnecessary parentheses with explicit temporaries in
conditional expressions

In addition to the cases described below for EDGcpfe/13355, EDGcpfe/13375,
and EDGcpfe/13423, early versions of g++ are also confused by redundant
parentheses around an explicit temporary appearing as the second or third
operand of a conditional (?:) expression.  The C++-generating back end has
now been changed to suppress the extra parentheses in this context as well.
For example:

  struct A {
    A();
  };
  void f(bool b) {
    A a;
    b ? A() : A();   // Operands previously generated as "(A())"
  }


1/7/13   [EDGcpfe/13549]
Abort on initialization of an enum bit field in Microsoft C++11 mode

Initialization a bit field using a braced initializer in Microsoft C++11
mode could result in an internal error in conv_integer_to_integer
(folding.c) if the initializer was not a constant value.  For example:

  enum E { e };
  struct S { E b: 2; };
  void g(E x) {
    S s = {x};  // Previously, this could produce an internal error in
  }             // Microsoft mode.

This regression was introduced in version 4.5 by the changes for EDGcpfe/9170.


1/7/13   [EDGcpfe/13554]
GNU compatibility: __builtin_unreachable

The front end now predeclares a function "void __builtin_unreachable();" in
GNU modes.  A call to this function is not treated specially by the front end,
but back ends should eliminate the call and can assume that the location of
the call is unreachable.


1/7/13   [EDGcpfe/13553]
Spurious error in GNU C++ mode on initialization of array in template

When processing a braced initializer for a multidimensional array in GNU C++
mode, the front end frequently issued a spurious error (about there being too
many initializer values) if the array appeared in a template but had known
(i.e., not template-dependent) bounds.  For example:

  template<typename T> void f() {
    int x[2][2] = { 1, 2, 3, 4 };  // Previously triggered a spurious error.
  }
  int main() { f<int>(); }

This regression (introduced by the changes for EDGcpfe/9170 in version 4.5)
is now fixed.


1/4/13   [EDGcpfe/13336]
Spurious warnings and/or internal errors on Microsoft-mode enum definitions

The changes for EDGcpfe/12762 (see entry of 3/19/12) caused a regression in
Microsoft C++ mode when declaring an enumeration type in class definition
scope and later defining that type with an explicit underlying type outside
the class.  Uses of the enumeration type potentially resulted in an internal
error (in class_qualified_id_lookup, lookup.c).  Also, if the original enum
declaration was scoped or opaque, a spurious warning about an incompatible
underlying type was sometimes emitted.
For example, with microsoft_version == 1700:

  struct S {
    enum struct E: short;
  };
  enum struct S::E: short { e, f };  // Previously triggered a spurious
                                     // warning in Microsoft C++ mode.
  int main() {
    S::E::f;  // Previously triggered an internal error.
  }

This is now fixed.


1/4/13   [EDGcpfe/13515]
Spurious error on definition of member of nested class of class template via
typedef

A spurious error was issued if a member of a nested class of a class template
was defined outside of the class using a typedef to the nested class.  Now
fixed.

  template <class T> struct A {
    typedef struct B {
      void f(T param1);
    } C;
  };
  template<class T> void A<T>::C::f(T) { }


1/4/13   [EDGcpfe/13506]
GNU C++ compatibility: Qualified local declarations

In GNU C++ mode with gnu_version < 40101 the front end now ignores a
namespace qualifier on a local declaration (with a warning) if the qualifier
denotes the innermost namespace.  For example:

  namespace N {
    void g() {
      int N::x;           // Treated like "int x;" after a warning is issued.
      extern int N::f();  // Treated like "extern int f();" after a warning
    }                     // is issued.
  }


1/4/13   [EDGcpfe/13479]
C++-generating back end, Microsoft compatibility: dependent value in base
class replaced with constant

A change made in version 4.5 (see EDGcpfe/12786 on 5/14/12) could result
in an dependent value in a template argument of a base class being replaced
with a constant in the C++-generating back end output.  This could occur
in Microsoft mode if the class of the dependent value had previously been
used as a base class of a class template and the --parse_templates option
was used.  Now fixed.

  template<typename T> struct A { static const bool B = false; };
  template<> struct A<bool> { static const bool B = true; };
  template<typename T> struct Z : public A<T> { };
  template<bool> struct Y { };
  // The base class on the following line was emitted as Y<false>
  template<typename T> struct X : Y<A<T>::B> { };


1/4/13   [EDGcpfe/13469]
Microsoft compatibility: spurious error on definition of class template member

A change made in version 4.5 (see EDGcpfe/12786 on 5/14/12) could result
in spurious redeclaration errors, in Microsoft mode, on the out-of-class
definition of a member of a class template if the declaration made use of
a nonreal class that had been previously used as a base class of a class
template.  Now fixed.

  template <int I> class A {};
  template <int I> class C {
    typedef typename A<I>::B B;
  };
  struct D {
    template <int I> static void f(typename C<I>::B);
  };
  template <int I> struct E : public C<I> {};
  template <int I> void D::f(typename C<I>::B) {}


1/3/13   [EDGcpfe/13541]
GNU: Lowering of compound literals had generated out-of-order initialization

As a result of the changes for C++11 initializer lists (see the Changes entry
for EDGcpfe/9170), the lowering of certain compound literals had resulted
in a temporary whose initial value referred to a static variable that followed
the temporary (resulting in generated C code that would not compile in
C-generating back end configurations).  Now fixed.  For example (with --g++):

  struct S {
    int *p;
  };
  void f() {
    static int list[1];
    (struct S){ list };
  }


1/3/13   [EDGcpfe/12815]
C++11: void parameter lists

In C++11 mode, the front end now accepts a function declarator of the form
"(VT)" where VT is a typedef for type void as equivalent to "(void)" or "()".
The type must be nondependent.  For example:

  typedef void NOPARAMS;
  void g(NOPARAMS) {}   // Now accepted in all C++11 modes.
  int main() { g(); }

Previously a warning was issued in nonstrict C++ modes and an error in strict
mode.  (This relaxation was added to the language through core issue 577.)


1/3/13   [EDGcpfe/12817]
Use of "auto" with secondary declarators

In strict C++11 mode, the front end now issues an error if an "auto" type
specifier followed by multiple declarators is used both to announce a
trailing return type and to deduce a type from an initializer.  For example:

  auto f()->int, x = 0;  // Now an error in strict C++11 mode.

In nonstrict modes, a warning is issued.  (This constraint was added to the
language through core issue 1265.)


1/3/13   [EDGcpfe/13543]
Abort when lowering designated initializers in GNU compound literal

In configurations that lower designated initializers, the presence of
designated initializers in GNU compound literals had caused an abort
(in fill_out_aggregate_ptr_to_data_member_initialization).  This regression
was introduced in 4.2 (see Changes entry for EDGcpfe/10353,EDGcpfe/10664)
and is now fixed.  For example:

  int x = (struct S { int x; }){ .x = 42 }.x;

Note that the uses_designated_initializers field in a_constant is set by the
front end when an aggregate constant uses designated initializers and is
now reset during lowering once the designated initializers have been lowered
(previously this field had remained set even after lowering).


1/2/13   [EDGcpfe/13352,EDGcpfe/13542]
Representation of compound literals

Prior to version 4.5 the front end set the flag "explicit_cast_applied" for
the aggregate constant representing a compound literal.  Version 4.5 no
longer sets that flag in such cases (for other reasons), but that caused the
C++-generating back end to incorrectly drop the "cast-like" part of compound
literals.  For example, in GNU C++ mode:

  int x = (struct S { int x; }){ .x = 42 }.x;
      // In version 4.5, the C++-generating back end failed to render
      // the "(struct S { int x; })" part of the compound literal.

This is now fixed.  A new flag is_compound_literal now identifies a_constant
entries representing compound literals.


1/2/13   [EDGcpfe/12865, EDGcpfe/13086]
GNU C++ compatibility: dependent qualified typedefs

Older versions of g++ (3.3 and earlier) allowed a typedef to refer to an
elaborated type specifier (and we emulate this behavior).  Versions 3.4 and
newer allow such typedefs, but only when a qualified name is used and the
qualifier is dependent.  We now emulate this behavior in g++ mode when
gnu_version >= 30400.

  struct C {};
  template <class T> struct A {
    typedef T my_type;
  };
  template<class T> struct B {
    friend class A<T>::my_type;
  };
  B<C> bc;


1/1/13   [EDGcpfe/13478]
C++-generating back end: qualified and parenthesized friend function names

The C++-generating back end incorrectly omitted necessary parentheses and
qualification in some friend function declarations.  For example, with the
following input

  struct X { };
  X f(int);
  namespace N {
    class B {
      friend X (::f)(int);   // Previously generated incorrectly
    };
  }

the indicated friend declaration was generated as

  friend X ::f(int);   // Missing parentheses

in configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE and

  friend X f(int);     // Missing qualification

otherwise.  Both of these issues are now fixed.


12/31/12 [EDGcpfe/13480]
GNU attributes in nested declarators

The front end accepts GNU attributes as the first element of a nested
declarator, but previously such attributes applied to the complete
declaration.  For example:

  int (__attribute((stdcall)) **ppf)();

Previously, the attribute was applied to the variable declaration as a whole,
which resulted in the attribute being ignored (with a warning) because the
declaration does not have a function or pointer-to-function type.  Now, the
attribute is applied to the type under the nested declarator (in this case
the function type).
This change also improves the output of such attributes by the C++-generating
back end.


12/31/12 [EDGcpfe/13477]
C++-generating back end: hiding of and by inherited names

When a member name inherited from one base class hides a member name
inherited from a different base class, the C++-generating back end failed
to use a qualified name in the generated code when referring to the hidden
name.  This is now fixed.  For example:

  struct B {
    struct T { };
  };
  struct X {
    int T;
  };
  struct D: B {
    struct I: X {  // X::T hides B::T
      struct T m;  // Previously generated as "T", now as "B::T"
    };
  };


12/28/12 [EDGcpfe/13351]
C++-generating back end, GNU C compatibility: casting scalar to union type

The changes enabling C++11 initializer lists (added in version 4.5; see
EDGcpfe/9170 below) introduced a bug that caused an abort (in
gen_temp_init) in C++-generating back end configurations when the source
contains a cast of a scalar to a union type (a gcc extension).  This is now
fixed.  For example:

  union U { int i; double d; };
  int x;
  void f() {
    union U u;
    u = (union U)x;   // Previously aborted
  }


12/22/12 [EDGcpfe/13539]
Spurious macro redefinition warning

The change to support function-style macros in the predefined macro file
(added in version 4.5; see EDGcpfe/12912 et al. below) introduced a bug
that could result in spurious warnings about macro redefinitions.  The bug
was most likely to manifest itself when a paste (##) operation appeared
near the end of the macro definition.  This is now fixed.  For example, the
front end sometimes warned that the second definition of TRX in the
following was an incompatible redefinition:

  #define TRN(n) TRX(n)
  #define TRX(n) TR##n

  #define TRN(n) TRX(n)
  #define TRX(n) TR##n


12/21/12 [EDGcpfe/13536]
Incorrect gcc mode folding of pointer difference with VLA array

A change made in version 4.5 (see EDGcpfe/12676) broke some cases of
pointer difference folding in gcc mode when the pointers are to
VLAs.  Now fixed again.

  int func(int i) {
    int arr[i][i];
    int res = (arr[1] - arr[0]);  // Incorrectly computed as a constant
    return res;
  }
  int main() {
    if (func(5) != 5) return 1;
  }


12/21/12 [EDGcpfe/13470]
Microsoft: Spurious error on use of nontype template parameter in base class

A change made in version 4.5 broke some obscure uses of a nontype template
parameter in a "?" operator in a class that is used as a dependent base class
of a template in Microsoft mode.  Now fixed.

  template <int I, unsigned int UI, bool B = true> struct A {
    enum {E1 = I};
    enum {E2 = B ? E1 : 0};  // Gave spurious error: B is not constant
  };
  template <int J = 6> struct B : public A<1, J> {};


12/20/12 [EDGcpfe/11548]
Microsoft compatibility: __if_exists and template instances

Our emulation of the Microsoft __if_exists and __if_not_exists keywords
did not handle instances of templates properly.  We returned TRUE if
the instance had been fully instantiated.  The Microsoft compiler returns
TRUE if the instance had been partially or fully instantiated, but the
reference in the __if_exists (or __if_not_exists) does not cause the
instance to be partially instantiated.  We now emulate this behavior in
Microsoft mode.  This is used by the version of the Boost encode_counter
class that targeted for the Microsoft compiler.  The example below
should compile correctly (i.e., only the declarations with the positive
subscripts are evaluated).

  template <int I> struct A { };
  struct B {
    __if_exists(A<1>) { int n[-1]; }
    __if_not_exists(A<1>) { int n[1]; }  // does not exist here
  };
  typedef A<1> a1;
  struct C {
    __if_exists(A<1>) { int n[1]; }  // does exist here
    __if_not_exists(A<1>) { int n[-1]; }
  };


12/19/12 [EDGcpfe/13535]
Runtime abort when "delete []" is used on a null pointer in GNU and MS modes

The changes for EDGcpfe/10873 introduced a virtual function lookup in cases
where the type given to "delete []" has a virtual destructor (only in GNU and
Microsoft emulation modes).  Unfortunately, when a null pointer is used,
the virtual function lookup had caused a runtime abort.  Lowering now adds
the requisite check to avoid the call when the object pointer is null.
For example (with --g++ or --microsoft):

  struct A {
    virtual ~A() {}
  };
  int main() {
    delete [] (A*)0;
  }


12/18/12 [EDGcpfe/13533]
Microsoft compatibility: Explicit dllimport class template instantiation

In Microsoft mode with microsoft_version >= 1310, the front end now no longer
attempts the instantiation of a nested class during the explicit instantiation
of a dllimport enclosing template class.  For example:

  template<typename T> struct S {
    struct N { T x; };
  };
  template struct __declspec(dllimport) S<void>;
    // Previously this resulted in an error because S<void>::N::x cannot have
    // type void.  Now it is accepted because S<void>::N is not instantiated.


12/18/12 [EDGcpfe/13529]
Invalid IL for noexcept on lambda in function template instantiation

The front end sometimes generated invalid IL for the representation of a
noexcept-specification on a lambda appearing in a function template instance.
For example:

  template<class T> void f(T) {
    []() noexcept(false) { throw 42; }();
              // Previously the "noexcept(false)" was not correctly recorded
  }           // in the IL.
  int main() {
    try { f(1); } catch (...) {}  // After code generation, the exception
  }                               // was likely not caught, resulting in a
                                  // call to "terminate()".

This is now fixed.


12/18/12 [EDGcpfe/13526]
C++-generating back end, GNU C++ compatibility: namespaces and classes with
the same name

When a class name is made visible by a using-directive in the same scope as
a namespace with the same name, versions of g++ prior to 4.5 reported
spurious errors if the namespace name is used as a qualifier.  The
C++-generating back end has now been changed to generate and use a unique
namespace alias in such cases when gcc_is_generated_code_target is TRUE,
circumventing the problem.  For example, given:

  namespace N {
    struct A { };
  }
  namespace A {
    struct S {
      static S* m;
    };
  }
  using namespace N;
  using namespace A;
  S* S::m;    // Previously generated as ::A::S *S::m, a g++ error

The C++-generating back end now adds a namespace-alias declaration using a
unique name of the form

  namespace __T12345678 = A;

and generates the static member definition as

  ::__T12345678::S *S::m;


12/14/12 [EDGcpfe/13190]
Microsoft compatibility: Use of "." in qualified names

A change made in version 4.4 (see EDGcpfe/12452 on 11/18/11) restricted
the use of "." in place of "::" (is allowed in Microsoft bugs mode) to
apply only when microsoft_version <= 1400.  The microsoft_version test
has now been updated to <= 1500.

  struct A {
    struct B {};
    static int i;
  };
  int main() {
    A.B ab;
    int i = A.i;  // Only accepted in Microsoft bugs mode when
                  //  microsoft_version <= 1500
  }


12/14/12 [EDGcpfe/13252]
Missing definition of friend function of class instantiated by default argument

A problem with class fixup processing could cause a function defined in
a friend function declaration to not have its definition undergo fixup
processing if the enclosing class was first instantiated by a function
default argument.  This result would be as if the function did not have a
definition.  The function body would not undergo semantic analysis and no
IL would be emitted (e.g., in the example below the operator!= would be
reported as undefined by the linker).  Now fixed


  template <typename T> struct A {
    friend bool operator!=(const A& a, const A& b) {
      return true;
    }
  };
  struct test {
    void f(A<int> a = A<int>());
  };
  int main() {
    A<int> a;
    return (a != a) != true;
  }


12/13/12 [EDGcpfe/11484,EDGcpfe/12983]
New option to set fixed mmap address at run time

A new command-line option, --mmap_address, and corresponding global
variable, fixed_address_for_mmap, have been added to allow the fixed address
used by mmap to be set at run time.  The --mmap_address command-line option
takes a decimal or hexadecimal (as indicated by a leading "0x" prefix)
argument.  Valid values for this argument are dependent on the operating system
and the only validation is to ensure that the given argument is aligned to a
page boundary.  It is expected that this option will only be used in driver
scripts as specifying an invalid value will likely lead to a catastrophic error
or possibly an abort.  The use of a fixed address for mmap is useful in cases
where pre-compiled header files are used (to ensure that the same address
space is available from one invocation of the front end to another).
These changes only affect configurations where USE_FIXED_ADDRESS_FOR_MMAP
is TRUE.


12/13/12 [EDGcpfe/13525]
Internal error with --no_func_prototype_tags and C++-generating back end

Using the --no_func_prototype_tags options (see entry for EDGcpfe/13002) in
non-Microsoft C mode could previously lead to an internal error triggered by
the C++-generating back end (in bypass_prototypes_param_src_seq_entries).
For example:

  void g(struct S *p) {}  // Previously aborted in the C++-generating
                          // back end when compiled with options
                          // "--c --no_func_prototype_tags".

This is now fixed.


12/13/12 [EDGcpfe/13254]
GNU C++ compatibility: namespace made inline by namespace extension

g++ allows a namespace to be made inline through use of the inline
keyword on a namespace extension declaration.  This previously resulted
in a warning, but the namespace was not made inline.  The warning is
still issued, but now the namespace is made inline in g++ mode (making A
visible in the example below).

  namespace N {
    template<typename T> struct A;
  }
  inline namespace N { }
  typedef A<char> a;


12/13/12 [EDGcpfe/13482]
Microsoft compatibility: regression involving template keyword in default
template template argument

A change made in version 4.5 (see EDGcpfe/12785 on 3/23/12) resulted in
spurious errors in Microsoft mode on the use of the template keyword for
syntactic disambiguation in a default template template argument.  Now fixed.
Note that although the earlier change was made to address an issue when
the --parse_templates option was used, this issue affects all uses of
Microsoft mode.

  template <template <typename U> class T> struct A { };
  template <typename T> void f(A<T::template xxx>* = 0);


12/13/12 [EDGcpfe/13170]
Visibility of template parameter in its default argument

A template parameter was incorrectly being found by lookup when scanning
its default argument.  Template parameters are now no longer visible
in their default arguments.  An exception is made for type parameters
in Microsoft mode (see 4/13/06 entry).

  template <typename T> struct A {
    static const bool value = true;
  };
  template <typename T, bool A = A<T>::value> struct B {};


12/12/12 [EDGcpfe/13518]
Spurious exception specification mismatch error on template operator delete

In strict C++11 mode, the front end sometimes issued a spurious exception
specification incompatibility error when specializing an operator delete
template.  For example:

  template<class T> void operator delete(void*, T) {}
  template<> void operator delete(void*, float) {}
      // Previously triggered a spurious error in strict C++11 mode.

This is now fixed.  (Operator delete is special in this context because in
strict C++11 mode it has an implicit "noexcept" specification by default.)


12/12/12 [EDGcpfe/13383]
Regression involving dependent name looked up in both base and derived class

A change made in version 4.5 (see EDGcpfe/12671 on 2/28/12) caused certain
cases to be rejected where a name was looked up using a qualified name first
as member of a class template, then as a member of a dependent base class
of the class template and then once again as a member of the class template.
In the example below, the final lookup was finding B<T>::type instead of
D<T>::type causing a spurious "declaration is incompatible" error.  Now fixed.

  template <typename T1> struct B {
    struct type {};
  };
  template <typename T> struct D : public B<T> {
    typename D<T>::type f(typename B<T>::type);
  };
  template <typename T> typename D<T>::type D<T>::f(typename B<T>::type) {
    return D<T>::type();
  }


12/12/12 [EDGcpfe/13505]
GNU C++ compatibility: use of ambiguous namespace name allowed

When doing a lookup involving using-directives, g++ prefers a namespace
name over a non-namespace name when the name is followed by a "::".  We
now emulate this behavior in g++ mode.

  namespace N {
    struct A {};
  }
  namespace M {
   struct N {};
  }
  template <typename T> struct C {
    static void f(T t);
  };
  using namespace M;
  int main() {
    C<N::A*>::f(0);  // N should be ambiguous, but g++ finds ::N
  }


12/11/12 [EDGcpfe/13490]
Spurious error on elaborated enum name qualified with dependent class name

The changes adding support for opaque enum declarations (see entry of 6/20/12)
caused the front end to emit a spurious error when it encountered an
elaborated enum name qualified with a dependent class name.  For example:

  template<class> struct S { enum E { e }; };
  template<class T> struct R {
    enum S<T>::E ev;  // This previously triggered a spurious error.
  };

This regression is now fixed.


12/11/12 [EDGcpfe/12763,EDGcpfe/13508]
Use of pre-compiled header files on systems with ASLR

Many recent versions of operating systems implement some form of Address
Space Layout Randomization (ASLR) where the addresses of various portions
of a process' address space change between invocations; in such environments,
the use of pre-compiled header (PCH) files could lead to aborts
(say in f_add_orphaned_file_scope_il_entry or module_id_for_source_corresp).
This issue has now been fixed.


12/10/12 [EDGcpfe/13504]
Form of name reference for static data member definitions

In configurations that record the form of name references, the name
reference information (i.e., the set of qualifiers used in the name) was
inadvertently not recorded for the definition of a static data member.  One
consequence of this omission was that the C++-generating back end might use
a fully-qualified name when generating such definitions; depending on the
other declarations in scope, versions of g++ prior to 4.5 could issue
spurious errors for the generated code.  This is now fixed.  For example:

  namespace N {
    class C { };
  }
  namespace C {
    class D {
      static int m;
    };
  }
  using namespace N;
  using namespace C;
  int D::m;   // Previously generated as int (::C::D::m), causing a g++ error
              // Now maintains the qualification from the source


12/7/12  [EDGcpfe/13513]
Use of uninitialized memory

A constant copy incorrectly used in_file_scope on a constant that
is allocated on the stack.  That refers to memory preceding the
stack-based variable, which is mostly random.  Now fixed.


12/7/12 [EDGcpfe/13489,EDGcpfe/9247,EDGcpfe/9975]
C++11: run-time checking of array new size

A change has been made in lowering to add a run-time check to ensure that the
array size is not too small (less than zero or less than the number of
initializers) or too large (causing an overflow during the multiplication
operation).  If the new test fails, the new library routine
__throw_bad_array_new_length (Cfront ABI) or __cxa_throw_bad_array_new_length
(IA-64 ABI) is called to throw std::bad_array_new_length.  This new code is
added when exceptions are enabled and when ABI_COMPATIBILITY_VERSION >= 406.
A new configuration macro, RUNTIME_SUPPORTS_ARRAY_LENGTH_CHECK, has been
added (defaults to TRUE except in Windows configurations) that will suppress
this check when the macro's value is FALSE.  For example:

  #include <new>
  int main() {
    int ret = 1;
    int n = 3;
    try {
      auto a = new int[n] {1,2,3,4};  // array too small for initializer list
    } catch (std::bad_array_new_length) {
      ret = 0;
    }
    return ret;
  }


12/7/12  [EDGcpfe/13512]
Referenced flag and nonstatic member functions

The representation of nonstatic member functions reference their parent class
through their this parameter.  However, nonstatic member function declarations
previously did not force the "referenced" flag in the source correspondence of
the parent type entry to be set to TRUE.  That in turn could e.g. cause the
C-generating back end to generate poor code in configurations with the macro
MAINTAIN_NEEDED_FLAGS set to FALSE (such configurations are fairly uncommon).
For example:

  struct S { S(); };  // If S was not otherwise used in the translation unit,
                      // the C-generating back end rendered a declaration for
                      // the lowered constructor referring to an otherwise
                      // undeclared "struct S;".  Such code is likely to
                      // elicit warnings from a target C compiler.

This is now fixed: The referenced flag of the parent class of a nonstatic
member function is now always set to TRUE.


12/4/12  [EDGcpfe/13356]
GNU compatibility: Spurious error on g++-mode specialization

Version 4.5 introduced a problem that resulted in a spurious error on an
explicit specialization with the wrong number of template parameter clauses,
which formerly was accepted in g++ mode.  Examples such as the one below are
once again accepted in g++ mode with a nesting depth warning.  An error is
still issued in other modes.

  template <class T> struct A {
    template <class U> int f(U u);
  };
  template <> int A<long>::f(int i) { return i; }


12/4/12  [EDGcpfe/13492]
GNU and Microsoft compatibility: spurious nesting depth warning

In Microsoft and g++ modes, the front end allows nonstandard friend
template declarations that have the wrong number of template parameter
clauses.  In cases where the injected class name was named in the
friend template declaration, the nesting depth of the declaration was not
being determined properly, resulting in a spurious nesting depth warning.
Now fixed.

  template <class T> struct A {
    template <int> class B {
      template <int> friend class B;
    };
  };
  A<int>::B<1> a;


12/4/12  [EDGcpfe/13385]
C++-generating back end: explicit specializations of non-member function
templates

The changes for EDGcpfe/12731 (included in version 4.5; see below)
incorrectly applied to non-member function templates.  As a result, in
configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE, an
explicit specialization of a non-member function template that appears
outside its namespace was generated inside its namespace but with a
qualified name, which is an error.  This is now fixed.  For example:

  namespace N {
    template<typename T> void f(void);
    template<> void f<int>(void);
  }
  template<> void N::f<int>() { }  // Previously generated as
                                   // namespace N { template<> void N::f... }


12/3/12  [EDGcpfe/13446]
GNU C++ compatibility: injected class name for class templates

g++ prior to version 4.5 does not create an injected class name for class
templates.  We now emulate this behavior in g++ mode when gnu_version < 40500.
Formerly, we emulated portions of this behavior by ignoring the injected
class names in certain contexts, but it was still found in certain cases,
such as the example below.  In addition to the source compatibility issue,
this could result in the C++-generating back end producing code that
could not be compiled by the g++ version indicated by the gnu_version being
used because the generated code assumed the existence of an injected
class name.

  namespace N {
    template<typename T> struct B { int i; };
  }
  struct D: N::B<int> {
    void f() {
      B b;  // Formerly (and still) rejected with gnu_version < 40500
      B::i = 1;  // Now rejected with gnu_version < 40500
    }
  };

12/3/12  [EDGcpfe/13423]
C++-generating back end: unnecessary parentheses with explicit temporaries in
non-static member access expressions

In addition to the cases described below for EDGcpfe/13355 and
EDGcpfe/13375, early versions of g++ are also confused by redundant
parentheses around an explicit temporary appearing as the object expression
in a member-access expression referring to a non-static class member.  The
C++-generating back end has now been changed to suppress the extra
parentheses in this context as well.  For example:

  struct S {
    int i;
    S();
  };
  void f() {
    int i = S().i;
  }


11/29/12 [EDGcpfe/12052,EDGcpfe/13432]
C-generating back end: duplicate dummy members in generated union

In configurations with USE_EMPTY_STRUCT_IN_GENERATED_C (see the entry for
EDGcpfe/11105 below) set to TRUE, a union with multiple members whose types
were generated as empty structs caused the C-generating back end to insert
multiple padding members, all named __dummy_empty1, into the union in the
generated code.  This is now fixed; if padding is needed, only a single
padding member is inserted at the end of the union.  For example:

  struct A {};
  struct B {
    union {
      A a1;  // Each of a1 and a2 was previously followed by a member named
      A a2;  // __dummy_empty1 in the generated C code; now a single member
             // named __dummy_empty is added at the end.
    } u;
  } b;


11/28/12 [EDGcpfe/13431]
Default type for va_list or __builtin_va_list

In non-GNU modes, when DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE is
TRUE, the front end previously set the va_list type to char* or void*
(depending on the mode) if sys_predef.c did not set the configurable
type_underlying_va_list to a specific type.  In GNU modes, on the other hand,
when type_underlying_va_list is left NULL, the type for __builtin_va_list was
set to char* or, when USE_X86_64 is TRUE, to a special array type (see entry
for EDGcpfe/10180).  This could lead to surprises when, e.g., compiling code
in non-GNU mode with the C-generating back end targeting GCC on an x86-64
platform.  To avoid such surprises, the default type underlying va_list or
__builtin_va_list is now always retrieved by a call to the new function
get_default_va_list_type defined in sys_predef.c.  That function can be
customized if needed, but by default it always produces the special array
type described in the entry for EDGcpfe/10180 when USE_X86_64 is TRUE.


11/28/12 [EDGcpfe/13347]
GNU C++11 compatibility: Aggregate initialization of complex type

In GNU C++11 mode with gnu_version >= 40700, the front end now accepts
braced initializers with two elements to initialize an object of a built-in
complex type.  For example:

  __complex double z = { 1.0, 2.0 };  // Real part 1.0, imaginary part 2.0.


11/28/12 [EDGcpfe/13465]
GNU compatibility: Attribute fastcall

When GNU_X86_ATTRIBUTES_ALLOWED is TRUE (and USE_X86_64 is FALSE), the front
end now accepts the GNU "fastcall" attribute when gnu_version >= 30400.  For
example:

  __attribute((fastcall)) void f();

A tweak was also made to the handling of conflicting GNU calling convention
attributes in GNU C++ modes.  Now, the last-specified attribute that is not
"cdecl" is retained.  For example:

  __attribute((cdecl)) void f();    // Calling convention is now "cdecl".
  __attribute((stdcall)) void f();  // Calling convention is now "stdcall".
  __attribute((cdecl)) void f();    // Calling convention is still "stdcall".
  __attribute((fastcall)) void f(); // Calling convention is now "fastcall".

This better approximates the behavior of g++.


11/28/12 [EDGcpfe/13467]
Mutable lambdas not marked as such in IL

The front end previously failed to set the is_mutable flag in a_lambda
entries for mutable lambdas.  For example:

  auto i = []() mutable { return 2; };
         // The a_lambda entry associated with this lambda now has its
         // is_mutable flag set.


11/27/12 [EDGcpfe/13455]
Missing diagnostics on noexcept redeclarations

The front end previously failed to diagnose many cases of function
redeclarations involving unmatched noexcept-specifiers.  For example:

  void f() noexcept;
  void f() noexcept(false);  // Previously accepted; now an error.

This is now fixed.


11/27/12 [EDGcpfe/13456]
Incorrect syntax disambiguation with some noexcept uses

The front end did not correctly parse certain function declarations that
include a parameter with a noexcept-specifier.  For example:

  void f(int (*p)() noexcept);  // Previously triggered spurious errors
                                // because "(*p)" was parsed as an expression.

This is now fixed.


11/26/12 [EDGcpfe/13364]
Spurious Microsoft-mode error on assignment operator from a dependent base

In Microsoft C++ mode, version 4.5 of the front end introduced a bug causing
it to sometimes issue a spurious redeclaration error when a class template
derived from a dependent base class declaring a user-defined assignment
operator.  For example:

  template<int N> struct B {
    typedef B<N> BN;
    BN& operator=(BN const&);
  };
  template<int N> struct D: B<N> {};
    // The "nonreal" instantiation of base class type B<N> previously
    // triggered a redeclaration error for B<N>::operator=.

This is now fixed.  (This bug was introduced by the changes for EDGcpfe/12786
etc. -- see the entry of 5/14/12.)


11/23/12 [EDGcpfe/13425]
Incorrect complete-object-type determination with pointer-to-member operator

The code that determines the complete object type for an expression
incorrectly assumed that a pointer-to-member reference always yields
a complete object, because a member of a class is always a complete
object.  That logic unfortunately ignored the fact that the member may
have base classes.  Now fixed, by assuming we can never tell the
complete object type for pointer-to-member operations.  Formerly, this
test case got a link-time error because the call was interpreted
as a non-virtual call to the pure virtual function of the base class:

  struct B { virtual void f() = 0; };
  struct D : B { virtual void f() {} };
  struct A { D d; };
  int main() {
    A a;
    B A::*pm = (B A::*)&A::d;
    (a.*pm).f();
  }


11/21/12 [EDGcpfe/13406]
Incorrect end position recorded for simple variable initialization

Version 4.5 of the front end did not always correctly record the end position
of a simple variable initializer (when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE).
For example:

  void g() {
    int i = 1;  // In version 4.5, the end position of the initializer was
  }             // incorrectly set to the end position of the identifier "i".

This is now fixed.


11/21/12 [EDGcpfe/13413,EDGcpfe/13414]
Abort in C++/CLI mode on event definition using a malformed delegate type

In C++/CLI mode, the front end aborted in f_types_are_compatible_full (called
from check_event_accessor_type) when processing an event definition based on
a delegate type that was previously erroneously defined with a non-function
type.  For example:

  delegate void D;  // Error: delegate not based on a function type.
  ref class R {
    event D ^e {
      int raise() { return 0; }  // Previously triggered an abort.
    }
  };

Similarly, an event defined with a handle to an undeclared type resulted in
an abort in delegate_invocation_type (types.c).  For example:

  ref class R {
    event E ^e {                 // Error: Type E undeclared.
      int raise() { return 0; }  // Previously triggered an abort.
    }
  };

Both these issues are now fixed.


11/21/12 [EDGcpfe/13412]
Abort in Microsoft mode on malformed constructor-like member declaration

In Microsoft mode, the front end aborted in function is_constructor_decl
(decl_spec.c) on certain malformed constructor-like member declarations with
a qualified name (qualified constructor names are sometimes accepted in
class-scope member declarations in Microsoft mode).  For example:

  struct S1 { void S2(); };
  struct S2 {
    S1::S2();  // This constructor-like declaration previously triggered an
  };           // abort.  Now it just elicits an error.

This is now fixed (an error is issued for the malformed declaration).


11/20/12 [EDGcpfe/13411]
Infinite loop when redeclaring an extern "C" function as static

In some modes, the front end allows a function to first be declared with
extern "C" linkage, and later defined with internal linkage (i.e., with the
"static" specifier).  When this occurred in a namespace scope, the front end
was likely to end up in an infinite loop attempting to move the routine entry
in function perform_scheduled_routine_moves (il.c).  For example:

  extern "C" namespace N { void f(), g(); }
  namespace N {
    static void f() {}  // This definition previously caused the front end
  }                     // to enter an infinite loop in many modes.

This is now fixed.


11/20/12 [EDGcpfe/13384]
Microsoft compatibility: incorrect overload resolution in a decltype in
a function template declaration

A function call in a decltype operator in a function template declaration
could result in the incorrect function being used (or no function being
found) when evaluating a call of the function template.  Now fixed.

  void g(char);
  namespace N {
    template <class T> auto f(T t) -> decltype(g(t)) { return t; }
    int g(int){}
  }
  int main() {
    N::f(1);
  }


11/19/12 [EDGcpfe/13404]
Abort on noexcept-specification in template when exceptions are disabled

In modes that disable exceptions but allow noexcept-specifications (e.g.,
with the command-line options "--c++11 --no_exceptions") the front end
aborted in scan_noexcept_arg (declarator.c) when handling the argument to
the noexcept-specification of a function template.  For example:

  template<class T> void f() noexcept(true) {}
        // Previously caused the front end to abort.

This is now fixed.


11/16/12 [EDGcpfe/13394]
Explicit conversion functions in C++/CLI mode with C++11 enabled

C++/CLI permits explicit conversion functions only in value class and ref
classes.  C++11 permits them in standard classes.  Previously, combining
C++/CLI and C++11 modes did not enable explicit conversion functions in
standard classes; now it does.  For example:

  struct S {
    explicit operator int();  // Previously an error with "--cppcli --c++11";
  };                          // now accepted (still an error in "plain
                              // C++/CLI" mode).


11/16/12 [EDGcpfe/13381]
GNU C++ compatibility: Typedefs for bool in system headers

In GNU C++ mode, the front end now ignores typedefs for bool that appear
in system headers.  For example:

  // The following preprocessor directive simulates a system header.
  #2 "t.c" 3
  typedef int bool;  // Now silently accepted in GNU C++ mode.

(See the entry for EDGcpfe/12755 on 3/13/12 for the similar case of a
typedef for wchar_t.)


11/16/12 [EDGcpfe/13395]
Default arguments and parameter packs

The front end previously issued a spurious error when a function parameter
with a default argument is followed by a parameter pack.  For example:

  template<typename... T> void g(int = 0, T ... x) {}
    // Previously, the front end issued an error complaining that the
    // default argument isn't at the end of the parameter list.

This is now fixed.


11/16/12 [EDGcpfe/13401]
GNU mode attribute and template parameters

Previously, the front end issued an error when applying the GNU attribute
"mode" to a template parameter type.  Now, this is accepted (an error may
be issued at instantiation time if the type after substitution is invalid).
For example:

  template<typename T> struct S {
    typedef T IntS __attribute((mode(SI)));  // Now accepted in GNU C++ mode.
  };


11/15/12 [EDGcpfe/13379]
Abort on malformed ctor-initializer when list-initialization is disabled

In C++ modes that do not permit list initialization syntax, a malformed
ctor-initializer consisting of an identifier followed by a brace was likely
to cause version 4.5 of the front end to abort with an internal error in
scan_mem_initializer (decl_inits.c).  For example:

  struct A {};
  struct B : A {
    B() : A {}  // Triggered an internal error in version 4.5.
  };

This regression (introduced by the changes for EDGcpfe/9170; see entry of
8/26/12) is now fixed.


11/15/12 [EDGcpfe/13376]
Generated copy functions and volatile fields

Volatile objects of a trivially copyable class type X (e.g., a plain C-style
struct) cannot be copied because the generated trivial copy function has a
parameter of type "X const&".  The front end previously failed to take this
into account when determining whether to "suppress" a generated copy function
of a class with a volatile field of trivially copyable class type (where
"suppress" means "make implicitly = delete" in C++11 mode, but can mean that
the declaration and/or the definition are simply not generated in some
Microsoft modes).  For example, in C++11 mode:

  struct S { int i; };  // A trivially copyable class type.
  struct V {
    S volatile sv;      // The generated constructor V::V(V const&) cannot
  };                    // copy sv, and is therefore now marked as deleted.
                        // The generated copy assignment operator is treated
                        // similarly.

In Microsoft mode, this change also interacts with the change for
EDGcpfe/13365:

  struct S { int i; };
  struct __declspec(dllexport) EV {
    S volatile sv;  // Previously, an error was issued during the generation
  };                // of the definition of EV::EV(EV const&).  Now, the
                    // front end no longer attempts to generate that
                    // definition.


11/15/12 [EDGcpfe/13375]
C++-generating back end: unnecessary parentheses with explicit temporaries in
static member access expressions

In addition to the cases described below for EDGcpfe/13355, early versions
of g++ are also confused by redundant parentheses around an explicit
temporary appearing as the object expression in a member-access expression
referring to a static class member.  The C++-generating back end has now
been changed to suppress the extra parentheses in this context as well.
For example:

  struct S {
    static bool b;
    static bool f();
  };

  void g() {
    S().f();       // Previously generated as (S()).f()
    if (S().b) {   // Previously generated as (S()).b
    }
  }


11/14/12 [EDGcpfe/10809, EDGcpfe/13359]
Defer final conversion on member default argument conversion for g++ 3.4 mode

g++ 3.4 apparently does the final conversion from a default argument
expression of a member or friend function to the parameter type at the
point of use rather than (as required by the standard) at the point
of declaration.  As a result, some cases like the following are
accepted without error as long as the default argument is never
used.  Now, we accept them also in g++ 3.4 mode.

  struct S {
    S(void*);
  };
  struct X {
    void f(S = 1);  // Invalid, but accepted by g++ 3.4
  };


11/14/12 [EDGcpfe/13365]
Microsoft compatibility: dllexport and generated special members

The changes for EDGcpfe/12772 (see the entry of 3/21/12) caused generated
class members of dllexported classes to always be defined (i.e., their
bodies were always generated).  Such definitions could trigger errors if,
for example, a required member function is inaccessible.  Now, such problems
cause the definition of the dllexported generated member not to be generated
until the special member is used.  For example:

  class X { X &operator=(X const&); };  // Private copy assignment.
  class Y: public X {};
  class __declspec(dllexport) Z: public Y {
    // Previously, the front attempted to define Z::operator= at this point,
    // which in turn required the definition of Y::operator=, and that
    // triggered an error because X::operator= is inaccessible in Y.
    // Now, Z::operator= is left declared but not defined instead.
  };
  void g(Z *p, Z z) {
    *p = z;  // This assignment still requires the definition of
  }          // Z::operator=, which then triggers an error because
             // X::operator= is inaccessible.
  

11/13/12 [EDGcpfe/13363]
Abort in C++11 mode on defaulted special member when exceptions are disabled

Version 4.5 of the front end aborted with an internal error in function
form_exception_specification_for_generated_function when defining a special
member function with "= default" inside a class definition while exceptions
are disabled (e.g., because of the --no_exceptions option).  For example:

  struct S {
    S() = default;  // This triggered an abort in version 4.5 when the
  };                // option "--no_exceptions" is used.

This is now fixed.  (This issue was a regression introduced by the changes
for EDGcpfe/12860.)


11/13/12 [EDGcpfe/13361]
GNU C++ compatibility: Elaborated template names in base class specifiers

In GNU C++ mode with gnu_version >= 30300 but < 40100, the front end now
treats the elaborated template name (i.e., the name preceded with "struct" or
"class", but without a template argument list) of a class template being
defined as the name of the current instantiation while scanning a base class
specifier list.  For example:

  template<class> struct B {};
  template<class> struct D: B<struct D> {};  // B<struct D> now treated as
                                             // B<struct D<T>> in some GNU
                                             // modes.

In other modes, such uses remain errors.


11/13/12 [EDGcpfe/13362]
GNU C++ compatibility: Matching of default template template arguments 

In GNU C++ mode, the front end now delays the matching of a template template
parameter's parameter list with a corresponding default template template
argument until that default argument is used.  For example:

  template<typename, typename> struct S { };
  template<typename, template<typename> class TT = S> struct X {};
                            // S doesn't match TT because it has an extra
                            // template parameter.  In GNU C++ mode, this
                            // is now accepted as long as the default
                            // argument is not used.  (In other modes, an
                            // error is issued here.)
  template<typename> struct F {};
  X<int, F> x1;  // Accepted (S is not used, and F matches TT).
  X<int> x2;     // An error is now issued here in GNU C++ mode because
                 // S is used as the substitution for TT, and its parameter
                 // list does not match.

In addition, in GNU C++ modes with gnu_version < 40200, the front end now
ignores template parameters with a default argument when matching a template
against a template template parameter.  For example:

  template<typename, typename = int> struct D {};
  template<template<typename> class TT> struct Y {};
  Y<D> yd;  // Now accepted in some GNU C++ modes.

  
11/12/12 [EDGcpfe/13355]
C++-generating back end: unnecessary parentheses with explicit temporaries

When generating an explicit temporary, a change in version 4.5 (see
EDGcpfe/12719 below) inadvertently resulted in the C++-generating back end
enclosing the expression in unneeded parentheses.  Although redundant
parentheses are generally harmless, bugs in early versions of g++ resulted
in spurious errors when the generated code was compiled.  The problematic
parentheses have now been suppressed.  For example:

  struct A {
    A() { }
  };
  void f() {
    static_cast<void>(A());  // Previously generated as
                             // static_cast<void>((A()))
  }


11/12/12 [EDGcpfe/13360]
C++-generating back end: GNU builtin function __offsetof__

The C++-generating back end previously transformed the GNU builtin function
__offsetof__ into the equivalent EDG-specific builtin function __INTADDR__,
resulting in errors when the generated code was compiled with gcc/g++.
This is now fixed: when gcc_is_generated_code_target is TRUE, the
C++-generating back end uses the GNU spelling for this operation.  For
example:

  struct S { int i; };
  int f() {
    return __offsetof__(&static_cast<S*>(0)->i);  // Previously generated as
                                                  // return __INTADDR__(...
  }


11/12/12 [EDGcpfe/13357]
Abort in i_copy_expr_tree with GNU statement expressions

An attempt to copy a GNU statement expression had resulted in an abort
in i_copy_expr_tree; a change has been made to substitute a dummy expression of
the proper type in cases where the expression is not evaluated, thereby easing
this restriction in certain cases.  The example below had compiled
in versions prior to 4.5 and now compiles again (with --g++):

  void f() {
    int *p = new int[({ 5; })];
  }


11/12/12 [EDGcpfe/13350]
C++-generating back end: abort when file ends with preprocessing directive

In some cases the C++-generating back end could abort dereferencing an
invalid pointer when the source file ends with a preprocessing directive.
This is now fixed.  For example (in Microsoft mode):

  #pragma pack (push, 8)
  template<typename T> struct S { };
  template struct __declspec(dllexport) S<int>;
  #pragma pack (pop)


11/12/12 [EDGcpfe/13311]
Microsoft Compatibility: regression on enum followed by typedef name

A change made in version 4.5 inadvertently broke certain code that
relied on the emulation of a Microsoft mode feature that allowed an enum
specifier to refer to a typedef to an enum.  This is once again accepted 
in Microsoft mode.

  struct A {
    typedef enum { a, b, c } B;
  };
  int main() {
    enum A::B x = A::B::b;
  }


11/9/12  [EDGcpfe/13348]
Abort on Microsoft-style inline assembly comment

The changes for EDGcpfe/11376 (see entry of 2/25/11) caused the front end to
abort in copy_from_source_to_asm_func_buffer (lexical.c) when processing
Microsoft-style inline assembly containing a comment (introduced by a
semicolon) if the assembly code itself was not brace-enclosed.  For example:

  __asm mov eax, 1; This previously caused an abort in Microsoft mode.

This is now fixed.


11/8/12  [EDGcpfe/12988]
GNU compatibility: __builtin_assume_aligned

In GNU modes with gnu_version >= 40700, the front end now predeclares a
function
	void* __builtin_assumed_aligned(void const*, size_t, ...);
The function is not treated in any special way by the front end, except that
it verifies that at most one argument is passed for the ellipsis parameter,
and that if present that argument has integer type.


11/8/12  [EDGcpfe/13326]
GNU C++: use of static data member initialized outside of class as constant

g++ apparently allows the use of a template static data member as a
constant even if its value is provided by an out-of-class definition.
Now, in g++ mode, we do too.

  template <class T>
  struct A {
    static const T x;
    int a[x];  // Use of x as constant okay now
  };
  template <class T> const T A<T>::x = 1;
  int a[A<int>::x];  // Use of x as constant okay now


11/7/12  [EDGcpfe/10525]
Issue remarks for unsequenced operations

The front end now issues remarks for operations on variables that
are unsequenced and could therefore result in undefined behavior.
The algorithm does not detect all instances of unsequenced behavior
(in particular, it limits the processing to expressions involving
variables).  The additional processing to detect unsequenced operations
is only performed when the ec_unsequenced_use_of_variable diagnostic
is enabled (either by enabling all remarks or by explicitly enabling this
remark).  The new processing is only available in configurations where
the new configuration macro SEQUENCING_DIAGNOSTICS_ENABLED is TRUE
(its default value is FALSE because setting SEQUENCING_DIAGNOSTICS_ENABLED
also enables EXTRA_SOURCE_POSITIONS_IN_IL which has a significant cost
in space use).

For example, the expression statements below will each generate new remarks
(with --remark):

  int g(int, int);
  void f() {
    int x = 0;
    int *px = &x;
    int a[5];
    x = x++;
    g(x, x=0);
    a[x] = a[x++];
    *px++ = *px;
  }


11/6/12  [EDGcpfe/13176]
Static member of current instantiation is dependent as template argument

An additional case beyond those covered by EDGcpfe/12993: the name of a
non-overloaded static member function of the current instantiation
is now considered dependent when used as a template argument.
Because of a failure to treat such a reference as dependent, a case
like the following formerly aborted in g++ mode:

  typedef void (*pf)();
  template <pf f> void foo();
  template <typename T> struct C {
    static void g();
    static void sub() {
      foo<C::g>();
    }
  };
  int main() {
    pf f = C<int>::sub;
  }


11/6/12  [EDGcpfe/13229]
Abort on useless partial specialization in GNU C++ mode

In GNU C++ mode, the front end accepts certain partial specializations that
cannot be selected under any circumstances because the template parameters
cannot be deduced from the specialized arguments.  In some cases, this could
trigger an abort in the C++-generating back end (in push_name_context) due to
the definition of the partial specialization being erroneously discarded.
For example:

  template<typename> struct N {};
  template<typename> struct S {};

  template<typename T> struct S<typename N<typename T::X>::Y> {};
    // Accepted in GNU C++ mode, but some C++-generating back end
    // configurations aborted when attempting to render the definition
    // of the partial specialization.

This is now fixed.


11/5/12  [EDGcpfe/13318]
GNU "const" attribute incorrectly set when composing types

In GNU modes, the front end sometimes incorrectly transferred the "const"
attribute specified on one function to another function not declared with
that attribute if both functions participated in an expression producing
the composite type of the two routine types.  For example:

  void fn(void) {}
  void __attribute((const)) fc(void) {}
  void g(int c) {
    (c ? fn : fc) ();  // Previously, this expression had the side-effect
  }                    // of adding the "const" attribute to function fn.

This is now fixed.


10/31/12 [EDGcpfe/13317]
Internal error on "_Pragma("...");" following a template member function

In modes in which the _Pragma("...") form of pragma operator is allowed,
an internal error could occur (in find_member_function_template) if a member
function body in a class template was followed by a _Pragma operator that
was immediately followed by an extraneous semicolon.  Now fixed.

  template<class T> class A {
    void process(int) { }
    _Pragma("diag_warning=10");
  };
  A<int> A;


10/29/12 [EDGcpfe/13237]
Microsoft compatibility: super lookup with virtual base classes

In Microsoft mode, a __super lookup could result in a spurious ambiguity
error if the derived class had a virtual base class and another base class
that also had the virtual base class as one of its base classes.  Now fixed.

  struct A {
    virtual void f();
  };
  struct B : virtual public A {
    virtual void f();
  };
  struct C : virtual public A, public B {
    void g() {
      __super::f();
    }
  };


10/29/12 [EDGcpfe/13275]
GNU and Microsoft compatibility: Default arguments on explicit instantiations

In GNU and Microsoft modes, the front end normally accepts (with a warning)
explicit instantiations with default arguments; see the entry of 1/15/09 for
EDGcpfe/9443.  Previously, however, an error was still issued for such
instantiations if explicit template arguments were specified.  For example:

  template<typename T> int f(T) {}
  template int f(int = 3);  // Previously accepted in GNU and Microsoft modes.
  template double f<double>(double = 3.0);
                            // Previously always an error; now also accepted
                            // in GNU and Microsoft modes.

Now such explicit instantiations are always accepted (with a warning) in GNU
and Microsoft modes.  The default arguments are ignored.


10/25/12 [EDGcpfe/13310]
Traversal of expression with NULL dynamic init in enk_condition

An expression traversal of an enk_condition whose dynamic_init field is
NULL due to an error had resulted a segfault (in traverse_dynamic_init).
Now fixed.  For example (if traverse_expr is run on the resulting
expression tree):

  struct A {};
  void f() {
    if (A);
  }


10/23/12 [EDGcpfe/13271]

In C++11 mode, the front end now accepts an in-class direct braced initializer
for a const static data member of integral type.  For example:

  struct S {
    static int const N{33};  // Now accepted in C++11 mode.
  };


10/22/12 [EDGcpfe/11214, EDGcpfe/12318]
Microsoft compatibility: declaring partial specialization in invalid namespace

A partial specialization can only be defined in the namespace in which
is was initially declared or an enclosing namespace.  The Microsoft
compiler allows partial specializations to be defined in an unrelated
namespace.  We now emulate this behavior in Microsoft mode.

  namespace N {
    template <typename T> struct A { };
  }
  namespace M {
    template<typename T> class B {};
    template<typename T> struct N::A<B<T> > { };
  }


10/22/12 [EDGcpfe/13300]
Remove extraneous check in IA-64 ABI virtual deleting destructors

The IA-64 ABI states that it is not necessary to check for a non-NULL "this"
pointer in deleting destructors when the class has a virtual destructor
(because the check has already been performed at the call site when
determining the address of the virtual destructor).  A change has been made
to eliminate this check.  For example:

  struct A {
    virtual ~A() {}  // deleting destructor no longer checks for NULL "this"
  };
  int main() {
    A a;
  }


10/22/12 [EDGcpfe/13253]
Abort on class template with using-directive for new/delete

Previously, the front end sometimes aborted while processing a class template
containing a using-directive for an operator new or an operator delete (the
abort was in set_overload_set_traversal_symbol).  For example:

  template<class T> struct BT {
    static void operator delete(void*, __EDG_SIZE_TYPE__);
  };
  struct B: BT<B> {};
  template<class T> struct D: B, BT<D<T> > {
    using BT<D<T> >::operator delete;
  };  // Checking this class template previously caused an internal error.

This is now fixed.


10/22/12 [EDGcpfe/13041]
Accept function-style cast for DBL_MAX and FLT_MAX

With some compilers, notably g++ 4.6.0 and later, the value of the DBL_MAX
macro has a function-style cast (e.g., "double(1.79769313486231570815e+308L)");
the front end now accepts a function-style cast to "double" for this value
(as well as a function-style cast to "float" for FLT_MAX).  See also the
changes for EDGcpfe/11604.


10/18/12 [EDGcpfe/13278]
Initial partial specialization allowed outside of namespace

A partial specialization was not allowed to first be declared outside of
its namespace.  Now fixed.

  namespace N {
    template <typename T> struct A { };
  }
  template <typename T> struct N::A<T*> { };


10/18/12 [EDGcpfe/13278]
Microsoft and GNU C++ compatibility: partial specialization declared though
a using-directive

The Microsoft compiler allows a partial specialization in an invalid scope
via a using-directive, as does g++ in permissive mode.  We now issue a
warning in Microsoft mode and a discretionary error in g++ mode.

  namespace N {
    template<class T> struct A {};
  }
  namespace M {
    using namespace N;
    template<class T> class B {};
    // Now allowed with a warning or discretionary error:
    template<class T> struct A<B<T> > {};
  }


10/17/12 [EDGcpfe/13276]
Abort on use of alias template with template template parameter

An abort could occur (in scan_template_argument_list) on a reference
to an alias template with a template template parameter when the
alias template is instantiated with a nonreal template.  Now fixed.

  template<template<typename> class D> using C = D<int>; 
  template<typename T> void f(C<T::template U>); 


10/16/12 [EDGcpfe/12856]
Abort on SFINAE expression with destructible object, kicked off from function

In some complex cases that involve a C++11 SFINAE evaluation of an expression
that involves a destructible type, kicked off from within a function scope,
the front end aborted ("push_or_repush_object_lifetime: parent is in file
scope memory, new olp is not").  Now fixed.

  struct A {
    template <class T> A(T, decltype(T()) = 1) {}
    virtual ~A();
  };
  void f() {
    try {
    }
    catch (A) {
    }
  }


10/12/12 [EDGcpfe/13268]
Access error on use of injected template name

A spurious access error could be issued if more than one injected class name
of the same class template was visible and the first one found was not
accessible but a later one was.  Now fixed.

  template <class T> struct B {
    template <class U> static void x(U u);
    template <class U> static void y(U u);
  };
  struct C : private B<char> { };
  struct A : C, private B<int> {
    // B<char>::B and B<int>::B are both visible, but only B<int>::B is
    // accessible.
    using B<int>::x;
    using B<int>::y;
  };


10/11/12 [EDGcpfe/13261]
Reference cast should not hide temporary from lifetime extension

When a reference is bound to a temporary, the lifetime of the temporary
is extended to match the lifetime of the reference.  Certain operations
on top of the temporary are ignored and do not hide it from the lifetime
extension.  One such operation is a reference cast, but the front end
previously did not "look through" reference casts when looking for
a temporary.  Now, it does, so the temporary is extended in a case
like the following:

  struct A {
    A();
    ~A();
  };
  int main() {
    const A &r = (const A&)A();
  }


10/11/12 [EDGcpfe/13255]
Add a flag for lowered scoped enumeration types

A new flag, originally_a_scoped_enum, has been added to alert back ends
that a lowered enumeration type had originally been a scoped enumeration type.
Previously, scoped and unscoped enumeration types had been indistinguishable
after lowering.


10/10/12 [EDGcpfe/13258]
Abort on multiple levels of copy elision with initializer lists

In some cases involving multiple levels of copy elision on a
destructible object type with brace-form initializers, the front end
aborted in IL lowering (in lower_dynamic_init) because of
malformed IL, to wit a dynamic init entry indicating a destructor
that was not on any lifetime list.  Now fixed.

  struct A {
    ~A() {}
  };
  A x =  A ( { A() } ); 


10/10/12 [EDGcpfe/13257]
Cast to reference type using T{x} form should use IL reference cast

An explicit cast to a reference type using the brace-enclosed form,
e.g., T{x}, should generate the same IL as the T(x) form, but didn't
when the type of x is the same as the underlying type of T; no cast
was added to the IL for x.  A reference cast node is now added.

  typedef int& T;
  int main() {
    int x = 0;
    T(x)++;
    T{x}++;  // Should generate same IL as parenthesized case
  }


10/10/12 [EDGcpfe/10618]
Dynamic exception specifications in C++11 mode

The C++11 standard deprecates dynamic exception specifications (i.e.,
exception specifications of the form "throw ( ... )").  The front end
therefore issues a remark on such constructs in C++11 mode.


10/10/12 [EDGcpfe/13256]
Spurious error on "{}" in cast context

Spurious errors could result if a brace-enclosed initializer was used
in a cast context.  Now fixed.

  const int I = 2;
  void f() {
    int j = (decltype("hello") {})[I];
 }


10/8/12  [EDGcpfe/12994]
enk_alignof node kind for use in backing expressions

In order to preserve __alignof__ operators in C++-generating back end
output, a new expression kind enk_alignof has been added (IL CHANGE).
Like enk_sizeof, it is used only in backing expressions and for
dependent types.


10/6/12  [EDGcpfe/13248]
GNU compatibility: always fold __builtin_constant_p in a constant expression

For a short period around gcc 3.4.0, and g++ 4.0, the GNU compilers did
not fold __builtin_constant_p when inside a function, the operand is
not a constant, and the expression is required to be constant.  As
a consequence an error was issued in such cases.  We dutifully emulated
that back in 2006, but it turns out that was a brief change from the
normal, and probably correct/expected behavior, to always fold
__builtin_constant_p in a constant expression.  So we've changed our
processing to do that as well.


10/5/12  [EDGcpfe/11420]
Internal error on ill-formed template static data member definition

An internal error could occur (in split_token_cache) while processing an
invalid template static data member definition.  This would most commonly
occur when the initializer contained a mismatched right brace.  Now fixed.

  template <class T> struct A {
    static int x;
  };
  template < class T > int A < T > :: x ( } ; 


10/5/12  [EDGcpfe/13232]
C++-generating back end: accessible typedefs to types using inaccessible types

The C++-generating back end correctly preserves an accessible typedef in
the generated code when it is a synonym for an inaccessible named type.
However, when the underlying type is a pointer, reference, array, or
cv-qualified type based on an inaccessible type, in some circumstances the
C++-generating back end put out the underlying type instead of the typedef
name, resulting in incorrect code.  This is now fixed.  For example:

  template<typename> struct A { };
  template<typename> class B {
    struct C;  // private
  public:
    typedef C* Cptr;
  };
  A<B<int>::Cptr> x;  // Previously generated as "A<B<int>::C *>"


10/5/12  [EDGcpfe/13243]
C++-generating back end: infinite recursion with private template arguments

In configurations with CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
and/or NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE,
the change for EDGcpfe/11015 below could result in the C++-generating back
end aborting due to infinite recursion between gen_name and
gen_class_qualifier.  This problem occurred when an instance of a class
template uses an inaccessible template argument and there is a public member
typedef for that type nested inside an instance of a class template that also
uses an inaccessible template argument.  This is now fixed.  For example,
the front end aborted when attempting to put out the return type, H<C::N>::IT,
of the explicit specialization generated for H<C::N>::f() in the following
code:

  template <class T> class H;
  template <class T> struct I {
    typedef H<T> HT;
  };
  template <class T> struct H {
    typedef I<T> IT;
    IT f()   { return IT(); }
  };
  template <class T> struct M {
    typedef H<T> HT;
    typedef typename HT::IT HIT;
    HT m;
    HIT f() { return m.f(); }
  };
  class C {
    ~C();
    struct N { };   // private
    typedef M<N> MN;
    MN mn;
  };
  C::~C() {
    mn.f();
  };


------------------------------------------------------------------------------
Version 4.5, October 5, 2012

10/5/12
IL version number changed to 4.5


10/4/12  [EDGcpfe/13227]
GNU C++: casting from a pointer-to-member to void * or pointer-to-function

g++ 4.4 and after allow casting a pointer-to-member value to "void *"
or a pointer-to-function type.  The front end now emulates that
in GNU C++ modes when gnu_version >= 40400.  This is a variant of
EDGcpfe/11893 (see below), implemented by adding an implied zero-address
object.  As a consequence, it will abort at runtime if the function
is virtual (as will the g++ implementation).  A warning is issued.

  struct A {
    void fun() { }
  };
  void *ptr;
  void (A::*pmf)() = &A::fun;
  int main() {
    ptr = (void*)&A::fun;
    ptr = (void*)pmf;
  }


9/28/12  [EDGcpfe/13221]
C++/CLI: spurious error on assignment from value class initonly field

The front end issued a spurious error on an assignment whose source is
an initonly field having a value class type.  Now fixed.

  value struct S {
    static initonly S s = S();
  };
  int main() {
    S s;
    s = S::s;  // Formerly got an error
  }


9/27/12  [EDGcpfe/13215]
Defaulted member functions in Microsoft C++11 mode

When Microsoft mode with microsoft_version >= 1400 and C++11 mode were
combined, the front end did not accept explicitly defaulted member functions
because "default" is not a keyword in such modes.  This is now fixed.
For example:

  struct S {
    S() = default;  // Previously not accepted with e.g. options
  };                // "--microsoft_version=1600 --c++11".

Note that "default" is still not a keyword in the combined mode.


9/27/12  [EDGcpfe/13211]
Microsoft compatibility: defined() operator in macro expansion

The Microsoft preprocessor has a bug that has the effect of making the
value of the defined() operator unconditionally false when it appears in a
macro expansion, regardless of whether its operand has been defined or not.
Because there are system headers that depend on this behavior, the front
end now emulates it (with a warning) when microsoft_bugs is TRUE.  For
example, the following snippet of code now causes the variable
"not_defined" to be declared when microsoft_bugs is TRUE:

  #define M 1
  #define M_IS_DEFINED defined(M)
  #if M_IS_DEFINED
  int is_defined;
  #else
  int not_defined;
  #endif


9/26/12  [EDGcpfe/11790, EDGcpfe/11791, EDGcpfe/12798]
Variadic templates allowed in g++ mode without --c++11

Variadic templates are now permitted in g++ mode with gnu_version >=
40400 even if --c++11 is not specified.


9/25/12  [EDGcpfe/13208]
Microsoft compatibility: Failing static_assert in nonreal instantiation

In Microsoft mode, the front sometimes "instantiates" templates with template
arguments that are still dependent on template parameters (this is called a
"nonreal instantiation").  During that process, the value of a static_assert
condition may be known, and the front end previously triggered an error if
that value was false.  This was unlike the Microsoft compiler: The front end
therefore no longer checks the value of a static_assert during such nonreal
instantiations.  For example:

  template<bool C, typename T> struct B {
    static_assert(C, "Failed");
  };
  template<typename T> struct D: B<false, T> {};
      // Previously triggered a failed static_assert during the nonreal
      // instantiation of B<false, T> in Microsoft mode.  Now accepted.


9/20/12  [EDGcpfe/13197]
Deduction failure with nondeduced parameter pack

Formerly, the front end assumed that deduction could not succeed when
a nondeduced parameter is also a parameter pack.  However, it turns out
there are cases like the one below where that makes sense.  Therefore,
now fixed.

  template<typename T> struct A {
    typedef T type;
  };
  void foo(int x);
  template <typename ...Args>
  void f(void (*pf)(Args...), typename A<Args>::type... args);
  int main() {
     f(&foo, 99);
  }


9/20/12  [EDGcpfe/13206]
Underlying type of _Bool

Previously, the underlying type of the C99 type _Bool was configured through
the macro TARG_BOOL_INT_KIND, which is also the macro used for the C++ type
bool.  The default configuration for that macro selects "char" for the
underlying type, but the C standard requires an unsigned type and that is not
always the case for type char.  Now, a separate macro TARG_C_BOOL_INT_KIND
selects the underlying integer kind of the boolean type in C mode.
TARG_C_BOOL_INT_KIND is configured for type "unsigned char" by default.


9/20/12  [EDGcpfe/13196]
Deduction failure with cv-qualified multi-dimensional array

Template deduction failed on an attempt to match a parameter that is a
reference to a cv-qualified multi-dimensional array type against an
argument that is an array that is identical except that it is cv-unqualified.
Now fixed.  The one-dimensional case worked okay.

  template<int n> void foo(const int (&x)[n][n]) {}
  int main() {
    int x[1][1] = {{0}};
    foo(x);
  }


9/19/12  [EDGcpfe/13203]
Mangling of dependent decltype types in emulate_gnu_abi_bugs mode

When mangling certain dependent decltype types in IA-64 ABI configurations
when emulate_gnu_abi_bugs is TRUE, a mangling substitution opportunity may
have been missed, resulting in mangled names that hadn't matched those
generated by g++.
For example (with --c++11 --g++ --set_flag emulate_gnu_abi_bugs):

  struct A { int i; };
  template <class T> auto f() -> decltype((A){0});
  int main() {
    f<A>();
  }


9/15/12  [EDGcpfe/13173]
Spurious error on empty pack expansion passed to template template parameter

A spurious "too many arguments" error was issued if any empty pack expansion
was passed as an argument to a template template parameter when the
actual template template argument did not allow a parameter in that
position.  Now fixed.  The example below should be allowed because the
instantiation of B passes only one template argument to A (via the template
template parameter T).

  template <class T> struct A { };
  template  <template <class, class...> class T, class... Args> struct B {
    typedef T<int, Args...> type;
  };
  B<A> N;


9/14/12  [EDGcpfe/13193]
Incorrect mangling in cases where CHECKING is FALSE

A programming error (in literal_representation) had resulted in no mangling for
certain types of constants in configurations where CHECKING is FALSE.  The
error was introduced in 4.2 and is now fixed.


9/7/12   [EDGcpfe/12912,EDGcpfe/10729,EDGcpfe/7902,EDGcpfe/7256,EDGcpfe/6547]
Function-style macros in predefined macros file

Recent versions of gcc, as well as older versions on some platforms,
predefine some function-style macros (macros with parameters) in addition
to many object-style macros.  Although the make_predef_macro_table script
correctly included the function-style macro definitions in its output, the
front end's processing of the predefined macro file quietly failed to
create the corresponding macros at compile time.  This has now been
addressed, and function-style macro definitions in the predefined macro
file are now fully supported.  For example, given a predefined macro file
containing the line

  gnu no __INT64_C(c) c ## LL

the line

  long long x = __INT64_C(10);

is equivalent to

  long long x = 10LL;

in --gcc mode with no other #includes or #defines required.


9/6/12   [EDGcpfe/13165]
Incorrect lowering of compound literals or initializer-list constants

During the lowering of compound literals or initializer-list constants,
the lowered code to perform the requisite initialization may have been
emitted out of order, resulting in undefined behavior at runtime (or in older
versions, an assertion failure: "lower_dynamic_init: keep_dynamic_init
param NULL and want to return TRUE").  For example (with --g++):

  struct B {
    B(int i) : i(i) {}
    ~B() {};
    int i;
  };
  struct A {
    int x;
    B y;
  };
  int f(A p) {
    return p.x + p.y.i;
  }
  int y = f((A){37, B(47)});
  int main() {
    return y != 84;   // Now returns zero.
  }

A change was also made to the handling of stmk_init statements created
during the lowering of NULL pointer-to-data-member constants in IA-64
ABI configurations.  For example:

  struct A {};
  typedef int A::*pd;
  struct B {
    pd a;
  };
  void g() {
    B({}); 
  }


9/5/12   [EDGcpfe/13171]
C-generating back end, GNU compatibility: passing NULL to va_list parameter

The C-generating back end generally adds a cast to the parameter type when
passing NULL (a literal 0) in a function call.  This resulted in incorrect
code in a call that passes NULL to a parameter of type va_list when using
gcc on a platform on which __builtin_va_list is an array type.  The
C-generating back end has now been changed to omit the cast in such calls.
For example:

  #include <stdarg.h>
  void f(int, va_list);
  void g() {
    f(1, 0);  /* Previously generated as f(1, (va_list)0); */
  }


9/4/12   [EDGcpfe/13149]
GNU C++ compatibility: failure to match nondependent vector types

In g++ mode, a declaration that used a nondependent GNU vector type failed
to match a template that used the same vector type.  Now fixed.

  typedef float __m128 __attribute__ ((__vector_size__ (16)));
  template <typename T> T f(float);
  template<> __m128 f<__m128>(float);


9/3/12   [EDGcpfe/9134]
C++-generating back end: macro definition containing ##

In configurations with RECORD_MACROS_IN_IL, the IL representation of a
macro containing a ## concatenation operator preceded by a "#" character
failed to preserve the correct tokenization in the definition.  The
resulting code generated by the C++-generating back end (which emits all
macro definitions at the end of the file) could cause errors when compiled.
The IL representation now contains a space before and after the ##
operator.  For example:

  #define hash_hash # ## #  // Previously recorded as ####


9/3/12   [EDGcpfe/10617,EDGcpfe/11496,EDGcpfe/12018]
noexcept specifier and operator

The front end now implements the C++11 noexcept specifier and operator,
as described in N3050.

  void f(int) noexcept;  // Never throws
  const int version = 5;
  void f(float) noexcept(version >= 5);  // Doesn't throw if expression true
  int main() {
    int arr[noexcept(f(1.0f))];  // noexcept operator is true if expression
                                 // cannot throw, so true in this case
  }

As with the traditional "dynamic" exception specifications, the front end
also accepts noexcept-specifiers on function declarations when exception
handling is disabled.  This simplifies writing header files that are accepted
whether exception handling is enabled or not.

C++11 also specifies that destructors declared without an explicit exception
specification have an implicit exception specification equivalent to the one
of the generated destructor if no destructor had been declared (as described
in N3204), and that deallocation functions (i.e., operator delete and
operator delete[]) have a "noexcept" specification (see N3205).  This
behavior is now implemented in strict C++11 mode or when the new command-line
option --implicit_noexcept is specified.

Our implementation implements the current direction of core issue 1330,
which specifies that noexcept specifications are only instantiated
when needed.  Prototype instantiations of noexcept specifications of
templates are performed in modes in which nonclass prototype instantiations
are done.  In g++ mode, the prototype instantiation of a noexcept
specification is deferred if function prototype instantiations are being
deferred.

A new mangling, "nx" is introduced to mangle the noexcept operator in Cfront
ABI configurations (the standard "nx" mangling is used in the IA-64 ABI).

For configurations where DO_FULL_PORTABLE_EH_LOWERING is TRUE, a new
exception handling stack entry, ehsek_noexcept, has been added to indicate
to the runtime library that a function has a noexcept specification that
doesn't allow an exception to be thrown (resulting in a call to
std::terminate if violated at run-time).  For backward compatibility,
when ABI_COMPATIBILITY_VERSION < 405, the existing ehsek_throw_spec
stack frame is used (i.e., as though throw() were specified -- though this
results in a call to std::unexpected rather than std::terminate).


8/31/12  [EDGcpfe/13167]
Change IL of "new" operations to be more like source form (IL CHANGE)

Previously the a_new_delete_supplement::arg field had specified the entire
argument list to be passed to a "new" or "new[]" operation, including the first
argument which contained the size (in bytes) to be allocated.  Now, that first
argument is omitted and must be provided by a back end (if needed).
Additionally, a new field, a_new_delete_supplement::number_of_elements, is
provided that contains (when non-NULL) an expression that represents the
number of elements in the array.  Previously, back ends that had needed this
information (e.g., to pass to a library routine) needed to extract it from the
expression in the first argument.


8/28/12  [EDGcpfe/12751, EDGcpfe/13158]
GNU compatibility: Scoped enumeration types in non-C++11 mode

In GNU C++ mode with gnu_version >= 40400, the front end now accepts (with a
warning) the declaration of scoped enumeration types and enumeration types
with an explicit base type when C++11 mode is not enabled.  Use of scoped
enumerations as name qualifiers remains an error in such modes, however.
For example:

  enum class E { e };   // Now accepted in some non-C++11 GCC modes.
  long x = (long)E::e;  // Still an error in all non-C++11 GCC modes.
  enum F: short { f };  // Also accepted in some non-C++11 GCC modes.


8/28/12  [EDGcpfe/13117]
Gnu compatibility: access to protected base classes

In a pointer or pointer to member conversion involving a derived class and
a protected base class, g++ versions prior to 4.4 considered casting across
protected inheritance to be permissible if the conversion occurs in a
context in which the base class is an accessible base, even if the
conversion is occurring in the context of a different derived class from
the one in the conversion.  The front end now emulates this behavior in g++
mode with gnu_version < 40400.  For example:

  struct B { };
  struct D1: protected B { };
  void f(B*);
  struct D2: B {
    D1 d;
    D2() {
      f(&d);    // Now accepted with gnu_version < 40400
    }
  };


8/28/12  [EDGcpfe/13155]
Abort on invalid member using-declaration in class template

Certain invalid member using-declarations in class templates aborted with an
internal error in member_using_or_alias_declaration (class_decl.c).
For example:

  template<class T> struct S {
    typedef int I;
    struct N {
      using typename S<T>::I;  // Error.  Previously triggered an
    };                         // internal error.
  };

This is now fixed.  (Note that while such cases are normally invalid they are
usually accepted in GNU and Microsoft modes.)


8/27/12  [EDGcpfe/11674,EDGcpfe/11675]
Defaulted explicit and/or nonpublic members

Previously the front end did not accept "= default" in a class definition for
explicit and/or nonpublic special member functions (that rule was present in
earlier drafts of the working paper for C++11, but it was removed just before
the final standard was agreed on).  For example:

  struct S {
  protected:
    S(S const&) = default;  // Previously an error.  Now accepted.
  };


8/26/12  [EDGcpfe/9170]
C++11 Initializer lists

The front end now implements C++11 initializer lists, as specified in
N2672, including on default arguments as specified in N3217.

  struct A { A(int, int); };
  A a{1, 2};  // Calls constructor with arguments (1, 2)
  int i{3};

Changes have been made to mangle and demangle initializer lists in
both IA-64 and Cfront ABIs.  The EDG-specific Cfront ABI mangling
mirrors that of the IA-64 ABI and uses the same character sequences
(i.e., "il" and "tl") for its encoding.  In the Cfront ABI, the "bi"
sequence is used to indicate a brace-enclosed initializer on a
"new" operation.

The decl_inits.c source file has been substantially rewritten to
handle the new features, but it retains all the old modes and
compatibility options for initializers.


8/24/12  [EDGcpfe/12957]
Remark instead of warning on use of null reference in unevaluated context

The diagnostic issued for a use of a null reference, which was already
reduced to a warning in unevaluated contexts, is now reduced further
to a remark.

  struct dereference {
    template< typename ptr_type >
    auto operator () ( ptr_type &ptr ) const -> decltype( *ptr ) {
      return *ptr;
    }
  };
  template< typename fn_type, typename arg_type >
  auto app( fn_type fn, arg_type arg ) -> decltype(fn(*(arg_type*)nullptr)) {
    return fn( arg );
  }
  int main() {
    int x = 123;
    app( dereference(), &x );
  }


8/24/12  [EDGcpfe/13140]
GNU C++: va_start second argument can be "this"

In a nonstatic member function that has an ellipsis with no parameters,
g++ allows "this" to be used as the second argument of va_start,
acting as the last parameter.  We now allow that as well.

  #include <stdarg.h>
  struct A {
    void f(...) {
      va_list lst;
      va_start(lst,this);
      va_end(lst);
    }
  };

8/24/12  [EDGcpfe/12993]
Address of non-overloaded static member function of current class is dependent

The address of a static member function of the current instantiation is
considered type-dependent.  We usually recognized that, but we did not
when a non-overloaded static function name appeared as an argument.
Now fixed.

  class A {};
  template<typename T> struct D {
    static A g();
    D() { f(g); }  // "g" now considered dependent, so later "f" found
  };
  void f(A(*)()){}
  D<A> di;


8/23/12  [EDGcpfe/13139]
MACRO_INVOCATION_TREE_IN_IL and COMPILE_MULTIPLE_TRANSLATION_UNITS

Setting both MACRO_INVOCATION_TREE_IN_IL and
COMPILE_MULTIPLE_TRANSLATION_UNITS to TRUE could cause the front end to
crash from infinite recursion or to abort with an assertion failure.  The
front end now prevents such configurations.  MACRO_INVOCATION_TREE_IN_IL,
however, controlled both the recording of macro invocations (used by the
front end to display the macro invocation stack in diagnostics when
--macro_positions_in_diagnostics is in effect, either from the command line
or via the DEFAULT_MACRO_POSITIONS_IN_DIAGNOSTICS configuration macro) and
the creation of the macro invocation tree in the IL.  Only the latter was
problematic with COMPILE_MULTIPLE_TRANSLATION_UNITS.  As a result, a new
configuration macro, RECORD_MACRO_INVOCATIONS, has been introduced to
control the former behavior.  Its default value is that of
MACRO_INVOCATION_TREE_IN_IL, so that existing configurations will continue
to have the same effect, but it can be set to TRUE even when
MACRO_INVOCATION_TREE_IN_IL is FALSE.


8/22/12  [EDGcpfe/12860]
Exception specifications and defaulted special members

If an exception specification appears on a defaulted special member
declaration, the front end now issues an error if that exception specification
is incompatible with the exception specification that would be generated
implicitly.  For example:

  struct B { B() throw(int); };
  struct D: B {
    D() throw(unsigned) = default;
         // Now an error, since the generated exception specification is
         // "throw(int)".
  };


8/22/12  [EDGcpfe/13137]
Abort on invalid use of auto-typed static data member

The use of a static data member declared with an "auto" type specifier in the
initializer for that data member previously triggered an internal error in
prep_generic_operand_full (expr_util.c).  For example:

  struct A {
    static auto x = sizeof(x);  // Previously caused the front end to abort.
  };

This is now fixed; an error is now issued in such cases.


8/20/12  [EDGcpfe/13106]
Spurious error on lambda capturing "this" in Microsoft mode

In some expression contexts involving a lambda expression capturing "this",
the front end sometimes mis-parsed certain constructs in Microsoft mode.
For example:

  struct S {
    void f(int x) {
      (void)([x, this]()->void {} );  // Previously triggered spurious
    }                                 // "expected a type specifier" error
  };                                  // in some Microsoft modes.

This is now fixed.


8/18/12  [EDGcpfe/12650]
GNU C++ compatibility: type of large integer literals in C++11

In C++11, as in C99, an integer literal that is larger than can be
represented as a long int has type long long int, assuming it can be
represented in that type.  Beginning with version 4.7, g++ now implements
the C++11 rule with -std=c++11; previously it always followed the c++03
rule that made such literals unsigned long if they could be represented in
that type.  The front end's g++ emulation has now been changed to use the
C++11 rule when --c++11 is specified and gnu_version >= 40700.  For
example, the value of uses_new_rules in the following is now true with
--g++ --gnu_version=40700 --c++11, assuming sizeof(long) is 4 and
sizeof(long long) is 8:

  bool uses_new_rules = (2147483648L > -1);


8/17/12  [EDGcpfe/12851]
Microsoft compatibility: __declspec(<string-literal>)

In Microsoft mode with microsoft_version >= 1700, the front end now accepts
__declspec attributes where the attribute name is a string literal.  Such an
attribute has no effect other than being recorded in the IL with attribute
kind ak_unrecognized (the attribute name includes the delimiting quotation
marks).  No arguments are permitted on this type of attribute.  For example:

  void f(__declspec("xyz") p);  // Now accepted in some Microsoft modes.


8/17/12  [EDGcpfe/13095]
Spurious error on GNU-mode redeclaration of a variable with calling convention

In GNU mode, redeclaring a pointer or reference to a function with a calling
convention attribute previously resulted in a spurious compatibility error.
For example:

  extern void (__attribute((stdcall)) *pf)(int);
  void (__attribute((stdcall)) *pf)(int);  // Previously a spurious error in
                                           // GNU mode.

This is now fixed.  (See also the entry for EDGcpfe/12593, which discusses
the similar problem with function declarations.)


8/16/12  [EDGcpfe/13073]
GNU compatibility: Attribute "nonnull" and nonstatic member functions

The front end now treats the "this" parameter of nonstatic member functions
as parameter number "1" for the GNU attribute "nonnull".  For example:

  struct S {
    void f(int*) __attribute((nonnull(2)));  // Previously, an error.  Now
  };                                         // accepted.


8/16/12  [EDGcpfe/11574]
GNU compatibility: Attribute "nonnull" on function parameters

The front end previously failed to accept the "nonnull" attribute on function
parameter declarations.  This is now fixed.  For example:

  void g(void (*pf)(char const*) __attribute((nonnull(1)))) {
            // The declaration of pf previously elicited an error.
    pf(0);  // Now a warning, because of the effect of the attribute.
  }

(See also the Changes entry for EDGcpfe/11809 on 6/17/11 for a similar change
applied to the "format" attribute.)


8/15/12  [EDGcpfe/13130]
GNU C++ compatibility: namespace for type_info with --ignore_std

Very old versions of g++ made namespace std a synonym for the global
namespace, and the front end provides the --ignore_std command-line option
to support code that relies on that behavior.  However, specifying
--ignore_std resulted in spurious errors processing the <typeinfo> header
when the front end is configured with TYPE_INFO_IN_NAMESPACE_STD set to
TRUE.  This is now fixed.


8/14/12  [EDGcpfe/12822]
GNU C++ compatibility: Meaning of block-extern declarations in namespaces

The resolution of EDGcpfe/10238 (see entry of 11/23/09) caused the front end
to ignore namespace scope reactivations when determining the scope in which a
block extern declaration should be injected.  It turns out that g++ does not
ignore namespace scopes reactivated for the purpose of template instantiation.
For example:

  namespace N {
    int i;
    template<typename> void f() {
      extern int i;  // Previously this was ::i; now it is N::i.
      i = 0;
    }
  }
  int main() { N::f<int>(); }  // Point of instantiation.


8/14/12  [EDGcpfe/12938]
Useless storage class specifiers on member class/enum declarations

In Sun C++ mode, a useless storage class specifier on a member class or enum
declaration is now a warning instead of an error.  For example:

  struct S {
    static enum { e };  // Now accepted with a warning in Sun mode.
  };

Furthermore, in modes where this still elicits an error by default, the error
is now discretionary.


8/14/12  [EDGcpfe/13105]
Microsoft compatibility: friend lookup when not using ADL

In version 4.1 we made a change to emulate the behavior of the Microsoft
compiler involving the lookup of friend functions with definitions
in contexts in which argument-dependent lookup is suppressed (see 3/31/09
entry).  It appears that the special processing done by the Microsoft
compiler does not apply to function templates, but our emulation did.
This could result incorrect overload resolution in such cases.  Now fixed.

  struct C {
    struct B {
      template <typename T> friend int f(B&) { return 0; }
    };
  };
  void f() {
    C::B s;
    ::f<int>(s);  // Formerly: "no instance ... matches the argument list"
  }


8/13/12  [EDGcpfe/13122]
Incorrect scanning of template static data members spanning several lines

The front end could incorrectly scan a template static data member definition,
resulting in spurious errors.  This occurred when the definition spanned
more than two lines, the initializer used the "=" form of initialization,
the initializer was enclosed in parentheses, and the initializer contained
a lambda.  Now fixed.

  template <class T> struct A {
    static int I;
  };
  template <class T> int A<T>::I = ([]()->int{
       return 1+
       1+
       1;});


8/10/12  [EDGcpfe/13113]
Incorrect processing after suppressed preincluded file

If a file containing include guards was included more than once using one
of the preinclude options, subsequent preinclude files were ignored and
the include search directory state was not restored to its proper state.
Now fixed.

8/10/12  [EDGcpfe/13097]
Inlining of function with pointer-to-function argument

The gcc compiler purposely inserts an illegal instruction (with a compiler
warning) when calling a function pointer through a cast that is not identical
to the function type.  Such a construct could be generated during inlining
of calls such as the example given below.  A change has been made to
introduce a temporary in such cases (only when gcc_is_generated_code_target
is TRUE).  For example:

  void f(void *p) {}
  typedef void (*CB)(char *p);
  inline void g (CB cb) {
    char *p = 0;
    cb(p);
  }
  int main() {
    g((CB)f);
  }


8/8/12   [EDGcpfe/13026]
Spurious error during prototype instantiation of default argument

Spurious errors could occur during the prototype instantiation of a
default argument of a function template or member function of a class
template when parsing of non-class templates and implicit typename are both
enabled (e.g., if "--microsoft --parse_templates" is used).  Now fixed.

  template <class T> struct A {
    static T f();
  };
  template <class T> struct B {
    B(T t = (A<T>::f)()) {}
  };


8/8/12   [EDGcpfe/13098]
Internal error on dependent using-declaration of operator new

An internal error could occur (in find_corresponding_operator_delete_sym)
if a class contained a dependent using-declaration of operator new or
operator new[] in modes where exceptions are enabled.  Now fixed.

  struct B {
    void operator delete[](void*, void*) {};
  };
  template <class T> struct A : public B, public T {
    using T::operator new[];
  };


8/8/12   [EDGcpfe/13087]
Internal error if equivalent typedefs are declared directly and by
a using-declaration

If typedefs to the same type were declared in the file scope both directly
and by a using-declaration, an internal error (in file_scope_id_lookup)
could result in a lookup of that name as a qualified name.  This problem was
introduced in version 4.4 (see 1/16/12 entry for EDGcpfe/12433).  Now fixed.

  namespace N {
    typedef int I;
  }
  using N::I;
  typedef int I;
  namespace M {
    using ::I;  // internal error on this lookup
  }


8/7/12   [EDGcpfe/13102]
Abort on SFINAE rescan of parameter reference pack expansion

In some cases, SFINAE processing of a pack expansion reference to a
parameter in a late-specified return type could cause an abort in
rescan_pack_expansion in expr.c.  The abort requires kicking off the
SFINAE processing while inside a(nother) prototype instantiation, as
is arranged in the following (erroneous) example by calling f from
within itself.  Now fixed.

  // Compile with --c++11 -tused:
  int ff(int, int);
  template <class ...T> auto f(T... args) -> decltype(ff(args...)) {
    f(1);
    return 0;
  }
  int main() {
    f(37, 47);
  }


8/2/12   [EDGcpfe/13089]
Abort on use of G++ typeof from different function

In some cases, the front end aborted in form_type_specifier in il_to_str.c
while trying to render a G++ typeof that is based on a local variable from
a scope other than the current one.  This problem was introduced in
version 4.4.  A change has also been made to resolve a mangling abort
stemming from __typeof__(this) or decltype(this) in configurations where
PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE and nonclass templates are parsed.
Both problems are now fixed.

  template <class T>
  struct C {
    void check() {
      typedef __typeof__(this) b ;
      struct C {
        static void foo(b) { __PRETTY_FUNCTION__; } // b from other scope
      };
    }
  };
  int main() {
    C<int>().check();
    return 0;
  }


7/26/12  [EDGcpfe/13085]
C++-generating back end: decltype of local type used as template argument

If a decltype was used to refer to an unnamed local type, the decltype
was stripped when the type was used as a template argument.  This
resulted in the C++-generating back end producing incorrect code.  Now fixed.

  template <class T, class R> class A {};
  int main() {
    auto f = [](char* p){};
    typedef A<char[], decltype(f)> buffer;
    // Emitted as something like:
    // typedef A< char [], class __T1790154560>  buffer;
  }


7/26/12  [EDGcpfe/13084]
Incorrectly allocated symbol header identifiers could leak into the IL

Under certain (rare) circumstances, strings that point to string literal
constants in the front end, or strings that were not necessarily allocated
in the primary file scope memory region could be used as names of IL
entities.  This could cause IL read errors when an IL file is used.
Now fixed.


7/23/12  [EDGcpfe/9170]
eok_bassign length (IL CHANGE)

Previously, the operands of an eok_bassign operation had the same size; a
change has been made to use eok_bassign in cases where a variably-sized
array may be the destination, or for partial-initialization of an array.
As a result, the size of the type of the source operand (the second
operand of the eok_bassign) should be used by the back end to determine how
many bytes should be copied.


7/23/12  [EDGcpfe/10292]
Incorrect constant folding of address of dependent static array variable

In a case like the following, the address of the local static variable
was not properly treated as dependent, which could cause later errors,
for example an assertion failure in binary_operation in folding.c:

  template <class T> void f(T x) {
    static T arr[] = {x};
    arr == 0;
  }


7/23/12  [EDGcpfe/13074]
IA-64 ABI: Suppress reference to __cxa_bad_typeid when possible

The standard requires that an std::bad_typeid exception be thrown
(implemented by calling __cxa_bad_typeid) when a NULL pointer is provided
as an argument to typeid.  A change has been made to suppress the runtime
check for a NULL pointer in cases where the front end can determine that
the expression cannot ever be NULL.  See also changes for EDGcpfe/10628 that
have bearing on whether a reference can be assumed to be non-NULL (to
match GNU's behavior in this area, assume_references_cannot_be_null is
temporarily set to TRUE when deciding whether the typeid expression can
be non-NULL).  For example:

  #include <typeinfo>
  struct A {
    void f(const int& i) {
      const std::type_info &x = typeid(this); // "this" cannot be NULL in a
                                              // non-static member function.
      const std::type_info &y = typeid(i);  // References cannot be NULL if
                                            // assume_references_cannot_be_null
                                            // is TRUE (or in --g++ mode).
    }
  };
  int main() {
    A a;
    a.f(1);
  }


7/22/12  [EDGcpfe/12692]
C++-generating back end: multiple function declarators with extern "C"

When msvc_is_generated_code_target is TRUE, the C++-generating back end
placed the closing "}" incorrectly for a braced extern "C" linkage
specification containing a declaration with multiple function declarators.
This is now fixed.  For example:

  extern "C" { int f(), g(); }  // Previously generated as "f(), } g();"


7/19/12  [EDGcpfe/13069]
GNU compatibility: completely wrong second argument on va_start gets warning

gcc gives only a warning on a completely-wrong second argument to the
va_start builtin, presumably because it knows what the correct value is
(i.e., the final parameter before the ellipsis).  We now do the same in
GNU C or C++ mode.  However, note that this change is only effective
when the built-in processing for <stdarg.h> is turned on (see
DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE) in GNU mode.

  #include <stdarg.h>
  int xx;
  void f(int i, ...) {
    va_list vl;
    va_start(vl, xx);  // Second argument should be "i"
  }

As part of this change, some diagnostics on misuse of va_start have
been made more strict in other modes.  For example, use of va_start
in a function that does not have an ellipsis now gets an error instead
of a warning.


7/15/12  [EDGcpfe/12992]
C++-generating back end, GNU compatibility: destructor name of a different
template instance

g++ has a bug such that if a member function of an instance of a class
template explicitly calls the destructor of a different instance of the
same class template, the destructor must be named using the template
arguments of that other instance.  In configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the C++-generating back end has
now been changed to put out the template argument list in such destructor
calls when gcc_is_generated_code_target is TRUE.  For example:

  template<typename T, typename U> struct S {
    S<U, T>* p;
    ~S() {
      p->~S<U, T>();  // Previously generated as p->~S()
    }
  };
  S<int, char> sic;


7/14/12  [EDGcpfe/12985]
GNU C++ quirk on deduction with overloaded function argument

According to the C++ standard, if an overloaded function name is passed
as the argument in a call that requires deduction, the argument is
treated as a non-deduced context.  g++ seems to add a special case to
that: in the overload set of the argument, any templates that do not
make use of their template parameters in their signatures are discarded.
This can allow deduction if what's left is a single non-template.

  struct A {
    A(); 
  };
  struct B {
    bool bar(const B& b);
    template <typename T> bool bar();  // Note no use of T
    void baz();
  };
  template <typename T, typename S, typename C>
  static void foo(A &a, S (C::*method)(T)) {}
  void B::baz() {
    A a;
    foo(a, &B::bar);
  }


7/11/12  [EDGcpfe/12991]
Spurious "never referenced" warnings on variables used as template arguments

In some cases, variables used as nontype template arguments within a template
were incorrectly flagged as "declared but never referenced".  This occurred
in modes that do prototype instantiations of templates, e.g., --c++11 mode.
Now fixed.

  template<typename T> struct foo {
    static const int value = 1;
  };
  template<int i> void f() {}
  template<typename T> void bar(void) {
    const int i = foo<T>::value;  // Got warning that i is never referenced
    f<i>();  // ... but it is referenced here
  }


7/11/12  [EDGcpfe/9170]
is_partially_initialized field moved (IL CHANGE)

As part of the changes for C++11 initializers, the is_partially_initialized
field has been moved from a_variable to a_dynamic_init where it now
encompasses the entity being initialized by the dynamic initialization
(which may or may not be a whole variable).  The
is_partially_initialized_compound_literal field in a_dynamic_init has also been
removed (its functionality has now been folded into the
is_partially_initialized field).


7/11/12  [EDGcpfe/12388]
GNU C++ compatibility: explicit template arguments on constructor declarations

Starting with version 4.5, g++ allows an explicit template argument list on
a declaration that names an instance of a constructor template (e.g.,
an explicit specialization or friend declaration).  We now allow this
usage in g++ mode when gnu_version >= 40500.

  struct A {
    template <typename T> A(T);
  };
  template <> A::A<int>(int){ }


7/11/12  [EDGcpfe/13058]
C++-generating back end: template argument lists and argument-dependent lookup

Under some circumstances, the C++-generating back end emitted a template
argument list for the name of a function found only by argument-dependent
lookup.  In order to use a template argument list, however, the name would
need to be visibly declared as a template, and that is not true of a name
found only by argument-dependent lookup.  The C++-generating back end has
now been changed to suppress the template argument list in such cases.  For
example:

  namespace N {
    struct S { };
    template<typename T> void f(struct S, T);
  };
  void g() {
    N::f<int>(N::S(), 0);
    f(N::S(), 0);   // Previously generated as f<int>(N::S(), 0)
  }

As part of this change, overload resolution was changed to discard
duplicate functions (e.g., introduced by argument-dependent lookup)
earlier in the process, which improves the setting of the
only_found_through_arg_dependent_lookup flag on calls, and may
improve compilation speed a bit.


7/10/12  [EDGcpfe/13019]
Pragmas not applied to certain instantiations

Pragmas placed on member function templates were not being applied to
instantiations of the template.  Now fixed.  This was being done properly
for namespace scope function templates.  Note that pragmas are applied
both at the point of the partial instantiation of the function template
and at the point of the full instantiation (if one is done).  In
addition, if pragmas were applied to both the declaration and the
definition of a template (of any kind) only the definition pragmas
were applied after the point of definition of the template.  Now the
list of definition pragmas is appended to the list from the declaration.

  template <typename T> struct A {
    template <typename U> void f(U);
  };
  #pragma mypragma
  template <typename T> template <typename U> inline void A<T>::f(U) { }
  int main() {
    A<int> a;
    a.f<double>(10);
  }


7/5/12   [EDGcpfe/13002]
Tags in C-mode function prototypes

In standard C, a tag type first declared in a function prototype scope belongs
to that scope and cannot be redeclared later on (it is therefore of limited
use).  For example (assuming normal C mode):

  void g(struct S *p);  /* This "struct S" belongs to the prototype scope. */
  struct S { int i; };  /* This "struct S" is different from the one above. */
  void g(struct S *p);  /* Error: This "struct S" is the one declared in file
                           scope, and this declaration of g is therefore
                           incompatible with the first declaration. */

In Microsoft mode, the front end treats this example differently (see Changes
entry of 6/30/96): The first "struct S" is not entered in prototype scope, but
in the surrounding (file) scope.  That behavior is now available in other C
modes through the command-line option --no_func_prototype_tags.  The Microsoft
C mode behavior can also be disabled with the option --func_prototype_tags
(that option cannot be combined with C++ mode, however).


7/3/12   [EDGcpfe/12931]
GNU C++ compatibility: Namespace __cxxabiv1

When IA64_ABI is TRUE, the front end now predeclares namespace __cxxabiv1
(which is where IA-64 ABI linkable entities live) in GNU C++ mode.  (In other
modes, the namespace is known to the front end, but not entered in the symbol
table, and therefore not visible to user code until it is explicitly declared.)

7/3/12   [EDGcpfe/13025]
C++-generating back end aborts on certain decltype instantiations

Previously, when TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is set to
TRUE, the C++-generating back end sometimes aborted when attempting to render
a template entity whose argument is expressed using a decltype or GNU typeof
construct.  The abort was triggered in get_param_for_param_ref (il_to_str.c).
For example (assuming C++11 mode):

  struct X { static bool const value = true; };
  template<typename T> auto f(T p)->decltype(p, X());
  template<typename T> struct S { static bool const value = T::value; };
  template<typename T>
  void g(T p) {
    static_assert(S<decltype(f(p))>::value, "Test!");
      // The rendering of this specialization of template S triggered an
      // abort.
  }
  int main() { g(1); }

This is now fixed.


7/3/12   [EDGcpfe/12790]
Abort on multiple GNU type attributes

GNU type attributes are attributes that modify a type.  In some cases, when
multiple type attributes were specified on the same type, the front end could
abort in output_type_attributes (il_to_str.c).  For example:

  #define MA __attribute((may_alias))  // A GNU type attribute.
  int g(void MA MA *p);
  int i = g(0);

In this example, the C++-generating back end aborted when attempting to render
the declaration of g.  This is now fixed.


7/2/12   [EDGcpfe/13003]
Microsoft compatibility: token pasting and inert macro names

In certain cases involving implicit token concatenation (when, according to
the C++ Standard, token splicing via a ## operator evokes undefined
behavior because the result is not a valid preprocessing token, but
rescanning the expanded text in Microsoft mode implicitly forms an
identifier), the front end failed to fully emulate the Microsoft
preprocessor's behavior.  In particular, when the left operand of the ##
operator is the closing parenthesis of a function-style macro that expands
to the name of the current macro (which is marked as "inert," i.e., not to
be expanded in order to prevent infinite recursion) and the result upon
rescanning is the name of a different macro, the front end failed to expand
the resulting macro invocation.  This is now fixed.  For example:

  #define AZ i
  #define B(x) x
  #define A(x) B(A) ## x
  int i = 0;
  int j = A(Z);   // Previously expanded to AZ, now to i


7/2/12   [EDGcpfe/13034]
Case label constants (IL CHANGE)

Prior to the rework of the representation of switch statements (see Changes
entry of 4/15/08), the position of case label constants was recorded in the
a_constant entries themselves.  As a result, the constants could not be
shared.  An unintended consequence of this was that no backing expression was
recorded in those constants.
The reworked representation of case labels records the position of the case
label constant in the corresponding a_switch_case entry, but the position was
still recorded in the constant entry itself (which was therefore still not
shareable).  Now, the constant entry itself is treated as shareable and
therefore no longer records the case label position.  However, the backing
expression is now retained, which is particularly noticeable in output of the
C++-generating back end when a case label constant expression is an enumerator
constant in C mode.  For example:

  enum { zero };
  void f(int i) {
    switch(i) {
      case zero: ;  // Previously, the C++-generating back end rendered this
    }               // as "case 0:" in C mode.  Now it renders "case zero:".
  }


6/29/12  [EDGcpfe/13024]
Microsoft compatibility: macro expansion of arguments in paste operations

According to the C and C++ Standards, if a macro parameter follows a ##
(paste) operator, the tokens of the corresponding macro argument are copied
verbatim into the expansion rather than first being macro-expanded, as
macro arguments usually are.  The Microsoft preprocessor follows this rule
only if the token preceding the ## in the macro definition is an
identifier; otherwise, the argument is macro-expanded before substitution.
The front end has now been changed to do the same in Microsoft mode.  For
example:

  #define A b
  #define M1(z) 0x ## z
  int i = M1(A);   // argument is expanded, giving 0xb
  #define M2(z) q ## z
  int M2(A);       // argument is not expanded, giving qA


6/27/12  [EDGcpfe/13021]
GNU compatibility: objectless references to non-static data members

Beginning with version 4.4, g++ supports the C++11 feature permitting use
of non-static data members without an object expression in unevaluated
contexts (see EDGcpfe/8402 below).  The front end has now been changed to
accept such expressions in g++ mode when gnu_version >= 40400.  For
example:

  struct S { int i; };
  int j = sizeof(S::i);  // Previously an error in g++ mode for all versions,
                         // now accepted with gnu_version >= 40400


6/26/12  [EDGcpfe/12939,EDGcpfe/12978]
GNU compatibility: built-in __atomic_... functions

In GNU modes with gnu_version >= 40700, the front end now predeclares several
__atomic_... functions (these can be used to implement certain parts of the
C++11 and C11 standard libraries).  These functions can be classified in two
groups.  The first group contains __atomic_always_lock_free, 
__atomic_is_lock_free, __atomic_thread_fence, __atomic_signal_fence, 
__atomic_load, __atomic_store, __atomic_exchange, __atomic_compare_exchange, 
__atomic_clear, and __atomic_test_and_set.  The second group contains the
functions __atomic_load_n, __atomic_store_n, __atomic_exchange_n, 
__atomic_compare_exchange_n, __atomic_add_fetch, __atomic_fetch_add, 
__atomic_sub_fetch, __atomic_fetch_sub, __atomic_and_fetch, __atomic_fetch_and,
__atomic_xor_fetch, __atomic_fetch_xor, __atomic_or_fetch, __atomic_fetch_or, 
__atomic_nand_fetch, and __atomic_fetch_nand.  The functions in the first
group are mostly unremarkable from the front end's perspective (although a few
are folded in the front end, and code-generating back ends are likely to map
the others to special instruction sequences).  The functions in the second
group are "generic" in the same sense as the GNU __sync_... functions: See
the Changes entry of 7/31/07 for details.  Like the GNU __sync_... functions,
the __atomic_... functions are only predeclared when the configuration macro
GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED is TRUE.


6/26/12  [EDGcpfe/12707]
C++-generating back end, C++/CLI: dependent properties and events

The C++-generating back end put out references to accessors of dependent
C++/CLI properties and events in function-call form instead of as operators
referring to the property or event name.  It has now been changed to retain
the form used in the source code for such references.  For example:

  template <typename T> ref class Foo {
    typedef T PropertyType;
    property PropertyType ^m_prop;
    Foo(PropertyType^ p) {
      m_prop = p;    // Previously generated as "this->m_prop::set(p)"
    }
  };


6/26/12  [EDGcpfe/12946]
Spurious error on pack expansion in alias template

A spurious error could occur on a pack expansion in an alias template
definition when the alias template was referenced from a dependent
context.  Now fixed.

  template <typename T> void f();
  template<typename T, typename... U> using A = decltype( T (f<U>()...) );
  template<typename T> using _B = A<T>;


6/23/12  [EDGcpfe/12736]
C++-generating back end, GNU compatibility: name of partial specialization of
member class template used as qualifier

The fix for EDGcpfe/11900 (included in version 4.4) caused the
C++-generating back end no longer to add an unnecessary "template" keyword
when the name of a partial specialization of a member class template is
used as a qualifier.  For example, in the code generated for

  template<typename T> struct A {
    template<typename U> struct B;
    template<typename U> struct B<U ()> : T {
      typedef typename B::X type;
    };
  };

the typedef was previously generated as

  typedef typename ::A< T> ::template B< U (void)> ::X type;

After the fix for EDGcpfe/11900, the template keyword no longer appeared in
the generated typedef.  While this form is correct, g++ issues a spurious
error when the template keyword is missing.  The C++-generating back end
has now been changed to put out the template keyword for this case once
again.


6/22/12  [EDGcpfe/13001]
Incorrect type on some lowered expressions

As per the C standard, the type of equality (eok_eq, eok_ne), relational
(eok_ge, eok_gt, eok_le, eok_lt) and logical (eok_land, eok_lor, eok_not)
expressions should always be int.  Some code inserted during the lowering
process had inadvertently used a non-int type.  When generating an eok_eq
comparison expression as part of the test for a static variable, the generated
eok_eq expression had an incorrect type.  Similarly, the eok_not expression in
some loop constructs had incorrect types.  Now fixed.  For example:

  struct A {
    A();
  };
  void f() {
    static A a;              // test for added static guard had incorrect type
    while (float x = 1.5) {} // eok_not test had incorrect type
  }


6/21/12  [EDGcpfe/10667,EDGcpfe/9162,EDGcpfe/11237,EDGcpfe/11318,EDGcpfe/12640]
C++11: Inline namespaces

Inline namespaces are now supported.  Inline namespaces are the standard
version of g++ strong using-directives.  An entity declared in an inline
namespace can be defined or specialized as a member of the enclosing
namespace.  In addition, argument dependent lookup considers inline
namespaces of associated namespaces and the enclosing scope of an inline
namespace that is an associated namespace.

  namespace N {
    template <class T> struct A {};
    template <class T> void g(T){}
    inline namespace M {
      template <class T> void f(T){}
      template <> void f(A<int>);
      struct B;
    }
  }
  template <> void N::f(A<int>){}  // specialized as if member of N
  struct N::B {};  // defined as if member of N
  int main() {
    N::A<int> na;
    f(na);  // argument dependent lookup finds N::M::f
    g(na);  // argument dependent lookup finds N::g
    N::B nb;
    f(nb);  // argument dependent lookup finds N::M::f
    g(nb);  // argument dependent lookup finds N::g
  }


6/20/12  [EDGcpfe/9250,EDGcpfe/11871,EDGcpfe/12413]
C++11 and Microsoft compatibility: Opaque enum declarations

In C++11 mode and in Microsoft mode with microsoft_version >= 1700, the front
end now accepts "opaque enumeration declarations"; i.e., declarations of
enumeration types with a known underlying type (hence, complete), but
without a definition.  For example:

  enum E1: char;  // Now okay in some modes, including strict C++11 mode.
  enum class E2;  // Ditto (underlying type is int).
  enum E3;        // An error in strict modes.  Accepted as an incomplete
                  // enumeration class in most modes (i.e., not an opaque
                  // enum declaration), except in Microsoft mode, where the
                  // underlying type is int.


6/20/12  [EDGcpfe/12995]
GNU compatibility: sync functions now allowed in both 32 and 64 bit versions

GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED is now set to TRUE in both 32 and
64-bit configuration in the defines.h.linux supplied with the release.
Formerly it was only set for 64-bit configurations.

6/17/12  [EDGcpfe/12980]
C++-generating back end: C99 inline function declarations

According to C99 semantics, if all declarations of an inline function have
the "inline" specifier and no "extern" specifier, the definition of the
function is for inline expansion only; i.e., the function must have a
definition in another translation unit.  The C++-generating back end
inadvertently converted external definitions of inline functions in C99
code into inline-only definitions by adding the "inline" specifier to
non-defining declarations of the function.  This is now fixed.  For
example:

  int f();    // Previously generated as "inline int f();"
  inline int f() {
    return 0;
  }


6/15/12  [EDGcpfe/12922]
Incorrect lowered code for certain array types during a lambda capture

In cases where an array variable is captured by a lambda, the front end had
generated IL for a repeated bitwise copy of all elements of the array variable,
but lowering had generated incorrect code for this construct (copying only
the initial element).  Lowering has been changed to copy the entire array
variable in this case and the front end has also been changed to generate
a bitwise copy for the entire array.  This behavior had occurred only when
the underlying type of the array has a destructor.  For example:

  struct A {
    ~A() {}
    int m;
  };
  int main() {
    A a[2];
    a[0].m = 99;
    a[1].m = 99;
    return [=](){
      return a[0].m != a[1].m;  // Now returns zero; had been undefined.
    }();
  }


6/12/12  [EDGcpfe/12862]
Changes to some g++-specific IA-64 mangling

Changes have been made to better emulate g++'s mangling of the "noreturn"
attribute on function types (the IA-64 substitutions had been improperly
handled previously).  Additionally, changes have also been made to
the mangling for __typeof so that a unique IA-64 substitution is used
for a dependent __typeof(<type>) and <type> entities (previously these had used
the same substitution).  Note that g++ doesn't appear to have a mangling
for __typeof, so there is no g++-compatibility issue here.  These changes
were motivated by a new assertion check that verifies that each IA-64
substitution is unique within a mangled name.  The previous behavior can be
restored by setting ABI_COMPATIBILITY_VERSION to a value less than 405.
For example (with --g++ --c++11):

  template <class T, class U> struct A {
    int m;
  };
  void f(void (*)() __attribute__((noreturn)), void (*)());
  template <class T> auto g(T p1) -> decltype(A<typeof(T),typeof(T)>::m,p1);
  int main() {
    f(0, 0);  // had been _Z1fPVFvvES1_
              // now      _Z1fPVFvvEPS_
    g(0);     // had been _Z1gIiEDTcmsr1AIDyT_ES0_EE1mfp_ES0_
              // now      _Z1gIiEDTcmsr1AIDyT_ES1_EE1mfp_ES0_
  }


6/11/12  [EDGcpfe/12758]
GNU compatibility: value of __cplusplus

Beginning with version 4.7, g++ defines the macro __cplusplus to either
199711L or 201103L, depending on whether -std=c++11 is specified or not.
(In previous versions it was defined as the value 1.)  The front end has
now been changed to emulate that behavior when --gnu_version >= 40700,
reflecting the presence or absence of the --c++11 command-line option.  In
addition, --c++11 now also defines __cplusplus to 201103L in default mode;
it was previously defined to 199711L.


6/11/12  [EDGcpfe/12708]
Microsoft compatibility: access checking in function template instantiations

The Microsoft compiler does not do access checking in SFINAE contexts,
and in addition, does not do access checking during the partial instantiation
of a function template.  The front end was doing C++11 SFINAE access
checking in Microsoft mode, but should not have.  This is now fixed.
In addition, access errors that occur during the partial instantiation
of a function template are now ignored in Microsoft mode.

  struct A {
    template <class T> static typename T::X f(T);
  };
  class B {
    typedef int X;
  };
  int main() {
    B b;
    A::f(b);
  }


6/8/12   [EDGcpfe/12961]
Building the front end on Windows in 64-bit mode

The front end and utility programs can now be built on Windows in 64-bit
mode.  This mostly involved adding casts to avoid certain warnings, but
there were a few cases that could cause incorrect execution of the front
end.  If the _WIN64 macro is defined, the defines.h.win32 file sets the
configuration macros appropriately to build a 64-bit version of the front
end.


6/6/12   [EDGcpfe/10181,EDGcpfe/11964,EDGcpfe/12949]
GNU compatibility: ACCEPT_GNU_CARRIAGE_RETURN_LINE_TERMINATOR with
UNICODE_SOURCE_SUPPORTED

The front end previously could not be built with both
ACCEPT_GNU_CARRIAGE_RETURN_LINE_TERMINATOR (see the entry of 11/11/05
below) and UNICODE_SOURCE_SUPPORTED set to TRUE.  This limitation has now
been removed.  In addition, when ACCEPT_GNU_CARRIAGE_RETURN_LINE_TERMINATOR
is set to TRUE, the associated processing is now controlled by a global
variable, carriage_return_is_line_terminator, instead of depending directly
on the value of gnu_mode, permitting the behavior to be enabled in other
modes if desired.


6/5/12   [EDGcpfe/12917]
Abort in IL lowering for destructible entity in default argument in dead code

The changes for EDGcpfe/10778 introduced a bug in version 4.2.  If a
default argument contains a destructible entity, and a call of the
function that uses that default argument is made in a dead branch
of a conditional operator in g++ mode, the front end (in a version
that does IL lowering) aborted with an assertion failure in
lower_dynamic_init.  Now fixed.

  template <class T> struct A {
    ~A() {}
  };
  template <class T> struct B {
    A<T> m;
    B(const T* __s, const A<T>& __a = A<T>());
  };
  void f(void) {
    true ? (void)0 : (void)(B<char>("abc"));  // Note third operand is dead
  }


6/5/12   [EDGcpfe/12954]
Incomplete lowered exception handling in some cases

As a result of the changes for [EDGcpfe/11966,EDGcpfe/12298], lowering of
a "new" operation at file scope for a class with an empty constructor had
resulted in lowered code that contained an object address table, but no
associated exception handling stack.  A change has been made to emit an
exception handling stack entry in this case (which has the side-effect of
completing the object address table type).  (An exception handling stack
entry in this unusual case is not really necessary because the empty
constructor call has been elided.)  For example:

  struct A {
    A() {}
  };
  A *pa = new A;


6/5/12   [EDGcpfe/12950]
Incorrectly generated copy constructor for lambda captures "this"

In modes accepting C++11-style lambda expressions, the copy constructor
generated for closure types failed to copy the field corresponding to a
captured "this" parameter.  This is now fixed.


6/4/12   [EDGcpfe/12947]
Universal-character-names in narrow character literals

In configurations with TARG_SIZEOF_INT < 4, the changes in 4.4 to better
support universal-character-names in narrow string literals (see
EDGcpfe/11914 and EDGcpfe/12066 below) resulted in spurious warnings or
errors for universal-character-names designating single-byte values in
narrow character literals.  This is now fixed.  For example:

  char at_sign = '\u0040';        // Previously warning or error
  char dollar  = '\U00000024';    // Previously warning or error


6/1/12   [EDGcpfe/12955]
Additional name hiding diagnostics

Formerly, the front end issued remarks if a local variable hid another
local variable or function parameter.  Now remarks are also issued if
a local variable or function parameter hides a namespace scope variable
or a class scope field or static data member.

  int j;
  namespace N {
    int i;
  }
  using namespace N;
  void f(int j) // hides ::j
  {
    int i;   // hides N::i
  }
  struct A {
    int k;
    static int l;
    void g(float k, double l) {}  // hides A::k and A::l
  };


5/31/12  [EDGcpfe/12952,EDGcpfe/12953]
GNU compatibility: attribute "packed" on functions, parameters, and typedefs

In GNU modes, the front end now ignores the "packed" attribute on the
declarations of functions, parameters, and typedefs.  (Previously, such usage
resulted in errors.)  For example:

  __attribute((packed)) void f();  // Now accepted with a warning.
                                   // Previously an error.


5/31/12  [EDGcpfe/12935]
Microsoft compatibility: Internal error with enum and typedef with same name

An internal error could occur (in symbols_may_coexist_in_curr_scope) if
an enumeration was declared in an elaborated type specifier in a
class scope, the enumeration had the same name as a typedef from the
enclosing scope, and the underlying type of the typedef was a class or
enumeration with a different name.  Now fixed.

  typedef enum X { e } E;
  typedef struct S {
    enum E f;  // declares enum ::E that hides the typedef ::E
  } S;


5/30/12  [EDGcpfe/12916]
C++-generating back end, Microsoft compatibility: qualified type names in
function template definitions

MSVC does not implement the two-stage lookup for names described in the C++
Standard; in particular, it looks up non-dependent names in the
instantiation context instead of in the definition context.  This can lead
to errors if a name is unqualified in the template definition and name
lookup finds different declarations in the definition and instantiation
contexts.  In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to
TRUE, the C++-generating back end sometimes triggered this problem because
it determined whether the name of a type appearing in the definition of a
function template should be qualified or not based on the definition
context.  (The qualification for non-type names can be preserved via the
name_reference facility enabled by setting
DEFAULT_RECORD_FORM_OF_NAME_REFERENCE to TRUE, but that applies only to
names in expressions, not to the names of types.)  This has now been fixed
by unconditionally qualifying names of non-dependent namespace-scope types
in function template definitions when msvc_is_generated_code_target is
TRUE.  For example:

  typedef long Integer; 

  namespace B { 
    typedef short Integer; 
  }

  namespace C { 
    using namespace B;
    // "Integer" is now ambiguous in namespace C
    template<typename F> void run(F f) {
      f(0);
    }
  }

  struct S {
    template<typename T> void operator()(T) const {
      ::Integer i = (0);    // Previously put out without "::"; MSVC
                            // instantiated the template such that lookup
                            // is done in namespace C, resulting in an
                            // ambiguity error during instantiation.
    }
  };

  int main() {
    C::run(S());
    return 0;
  }


5/30/12  [EDGcpfe/12923]
Add mangling for g++ "restrict" qualifier in Cfront ABIs

A mangling for the g++ "restrict" qualifier ("Dr") has been added in the
Cfront ABI (the IA-64 ABI previously had a mangling for this).  This had
caused problems in cases like the following where the same mangled name
had been used for both routines (with --g++):

  template <class T> void f(T&) { }
  int main() {
    int *__restrict rp;
    int *p;
    f(rp);
    f(p);
  }

The old behavior can be restored by setting ABI_COMPATIBILITY_VERSION to a
value less than 405.


5/30/12  [EDGcpfe/12948]
Internal error during new SFINAE processing with partial specializations

An internal error could occur (in get_expr_rescan_info) when using C++11
SFINAE processing with function templates in which the substitution
required selecting a partial specialization.  In addition, the partial
specialization selection must have involved expressions that had to
be rescanned.  Now fixed.

  template <int I> class A;
  template<typename T, typename U> struct D;
  template<int I, typename T> struct D<A<I>, T> {};
  template<int I> struct D<A<I>, typename A<I>::Atype> {
    typedef int type;
  };
  template<int I> struct E {
    typedef int Etype;
  };
  template<int I> struct F {
    typedef typename E<(I <= 16) + (I <= 32)>::Etype Ftype;
  };
  template <int N> struct A {
    typedef typename F<N>::Ftype Atype;
    template<typename T> typename D<A, T>::type operator=(const T& data);
  };
  int main() {
    A<1> a1;
    a1 = 0;  // internal error in substitution of A<1>::operator=
  }


5/24/12  [EDGcpfe/12941]
Missing name reference information on dependent member name used as lvalue

The front end lost the name reference information on the name of a
dependent member when it is used as an lvalue (e.g., when bound to
a reference).  The name reference information is now preserved.

  template<typename T> struct S {
    int& f(T& r) {
      return r.first;  // Previously put out as r.T::first
    }
  };


5/23/12  [EDGcpfe/12943]
Abort on attempt to deduce a variable-length array type

In C++ modes that accept variable-length arrays (particularly, GNU C++ mode),
the front end sometimes aborted with a failed assertion check in
make_vla_dimension (il.c) when attempting to deduce a qualified variable-
length array type.  For example:

  template<typename T> void f(T const&) {}
  void g(int d) {
    char a[d];
    f(a);  // Previously triggered an internal error in il.c.
  }

This is now fixed (deduction fails).


5/21/12  [EDGcpfe/12928]
GNU compatibility: __builtin_isnan and __builtin_isinf variants

In GNU C and C++ modes, the front end now pre-declares built-in functions
__builtin_isnanf, __builtin_isnanl, __builtin_isinff and __builtin_isinfl.
(This requires a configuration with TARG_HAS_IEEE_FLOATING_POINT.  See also
the entry for EDGcpfe/9876.)


5/21/12  [EDGcpfe/12921]
C++/CLI: Access specifiers in nontrivial property/event definitions

Previously, access specifiers in nontrivial C++/CLI property/event definitions
took effect until the next access specifier or the end of the class definition
(whichever came first).  Now, such access specifiers are limited to the
property/event definition itself.  For example:

  ref struct RS {
    property int p {
      int get() { return 1; }
    private:
      void set(int) {}
    }
    int i;  // Previously i was private; now it is public.
  };


5/19/12  [EDGcpfe/12936]
Elimination of certain temporaries during inlining

In cases where the argument to a function that is being inlined has
certain characteristics (i.e., it is a comma expression where the second
operand of the comma operation is constant valued), inlining can forgo the
need for an additional temporary.  In this example, a temporary
had been created when inlining the call to g, but is now avoided:

  struct A {
    int m;
    A(int _m) : m(_m) {}
    int g() { return m; }
  };
  A a(0);
  A f() { return a; }
  int main() {
    return f().g();
  }


5/18/12  [EDGcpfe/12930]
C++11: Friend injection disabled in C++11 mode

Friend injection is now disabled in default C++11 mode (formerly it was
only disabled in strict C++ modes).  As before, it is enabled or disabled
as appropriate in Microsoft and g++ modes.  The default in other modes
continues to be provided by the DEFAULT_FRIEND_INJECTION macro, which
is TRUE by default.

  class A {
    friend void f(int);
  };
  void f(long){}
  int main() {
    f(1);  // calls f(int) with injection, f(long) without
  }



5/18/12  [EDGcpfe/12925]
GNU C++ compatibility: dependent lookup ignores certain later declarations

In g++ mode when gnu_version >= 30400, the front end emulates the g++
behavior of considering declarations that follow the definition of a
template when resolving dependent calls.  The g++ behavior changed in
g++ version 4.1 to only consider later declarations if there were no
declarations that preceded the template definition.  We now emulate the
new behavior when gnu_version >= 40100.

  template <class T> void f(T, int) { }
  namespace N {
    template <class T> void g(T t) {
        f(t, 0);  // Formerly found N::f, now finds ::f
    }
    template <class T> void f(T) { }
  }
  int main() {
    N::g(1);
  }


5/17/12  [EDGcpfe/12924]
C++-generating back end, GNU compatibility: dependent __typeof__ as template
argument

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the
C++-generating back end used an undeclared temporary type name (i.e., a
name of the form __T12345678) in place of a template argument that is a
type given by a __typeof__ construct (a GNU extension) referring to a
dependent type.  This is now fixed and uses the original __typeof__
construct instead of the temporary name.  For example:

  template <class T> struct A {
    static const int sm = 0;
  };
  template <class T> void g(const T&);
  template <class T> void f(T x) {
    typedef __typeof__(g(x)) type;
    A<type>::sm;    // Previously generated as "A<__T12345678>", now as
                    // "A<__typeof__(g(x))>"
  }


5/17/12  [EDGcpfe/12934]
Incorrect conditional code in strip_local_and_nonreal_typedefs

Some code in strip_local_and_nonreal_typedefs was conditional on
GNU_EXTENSIONS_ALLOWED but should not have been.  This could cause
certain uses of decltype to be handled improperly in front ends built
without GNU_EXTENSIONS_ALLOWED.  Now fixed.

  template <class T> struct A {
    template <int I> struct B { };
  };
  template <int I, class T> void f(T) {
    A<decltype(I)>::B<I> ab;  // spurious error here
  }


5/17/12  [EDGcpfe/12932]
Microsoft compatibility: use "implicit typename" with --parse_templates
in some contexts

Formerly, the --parse_templates option would always disable "implicit
typename" processing, which is used to determine from context which
dependent names are types vs. non-types.  This has been changed so that,
in Microsoft mode, implicit typename is only disabled within function
prototype instantiations.

  template <class T> struct B { typedef int X;};
  template <class T> struct C { static int f();};
  template <class T> struct A {
    // The following declaration is now accepted --parse_templates is
    // used in Microsoft mode.
    auto f(T) -> decltype(C<B<T>::X>::f());
  };


5/14/12  [EDGcpfe/12830]
C++/CLI: internal error on generic declared in class template

An internal error (in push_template_instantiation_scope) could occur
following a normal error if a C++/CLI generic was declared within a class
template.  Now fixed.

  template <typename T> ref struct R {
    generic <typename U> virtual void g(U u) {}
  };


5/14/12  [EDGcpfe/12926]
Missing error on creation of incomplete rvalue result for .* operation

The front end failed to issue an error when the result of a pointer-to-
member ".*" operation is an rvalue with an incomplete type, and as
a consequence it was possible to get various kinds of aborts later.
Now fixed.

  struct A;
  struct B { };
  B f();
  void g(const A&);
  int main() {
    A B::*pdm = 0;
    g(f().*pdm);  // Gets error now because result type A is incomplete
  }


5/14/12  [EDGcpfe/12919]
C++-generating back end versions: knowledge of key function for vtables

Up until now, the C++-generating back end has had little or no knowledge
of the ABI being used.  Now, it has been made aware of "key functions"
in classes, whose definition forces the definition of the virtual
function table of the class, which might force definition of some
template functions or generated destructors.  In cp_gen_be versions
with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, for example, the
following translated in g++ mode with gnu_version=40500 did not output
a definition for A<int>::~A, and now it does (because C::f is the
key function of C, and is defined, so the destructor for C is generated,
and that references the destructor for A<int>).

  template <class T> struct A {
    ~A() {}
  };
  struct B {
    virtual ~B();
    virtual void f();
  };
  struct C : B {
    A<int> m;
    virtual void f();
  };
  void C::f() { }

[6/6/12, EDGcpfe/12951] Additional changes were made to also use this
new approach with typeinfo generation in C++-generating back end versions,
reworking the changes for EDGcpfe/12706.


5/14/12  [EDGcpfe/7165,EDGcpfe/7850,EDGcpfe/9701,EDGcpfe/10836,
          EDGcpfe/11933,EDGcpfe/12786]
Microsoft compatibility: lookup in dependent base classes

The Microsoft compiler, in some cases, instantiates dependent base classes
and does name lookup in them.  In the case below, this allows the Microsoft
compiler to find the class template "A" in the base class instead of finding
the class in the global scope.  We now emulate this behavior in Microsoft mode.

  struct A {};
  template <class T> struct B {
    template <class T> struct A {};
  };
  template <class T> struct C : public B<T> {
    A<int> f();  // now finds B<T>::A instead of ::A
  };
  int main() {
    C<int> c;
    c.f();
  }


5/13/12  [EDGcpfe/12839]
Invalid preprocessor token concatenation

According to the C and C++ Standards, if the concatenation of two
preprocessor tokens using the ## operator does not result in a (single)
valid preprocessor token, the result is undefined behavior.  When
instructed to do so, via the --check_concatenations command-line option or
the DEFAULT_CHECK_CONCATENATIONS configuration option, the front end
previously issued a warning (or error, in strict mode) when the
preprocessor token following the ## operator started a new token,
indicating an invalid concatenation.  However, it did not check for the
case in which the preprocessor token resulting from the concatenation does
not contain the entire original second preprocessor token, i.e., the result
of the concatenation is not a single preprocessor token.  This is now
fixed.  For example:

  #define G(x) x ## 0xE+1
  #define test0xE 1
  int tmp = G(test);  // Result is "test0xE + 1", which splits the "0xE+1"
                      // preprocessor token and now elicits a diagnostic


5/13/12  [EDGcpfe/12838]
Preprocessor numbers, macros, and preprocessing output

The C and C++ Standards use one lexical grammar to process literal numbers
in preprocessing and another during compilation; the former syntax (called
"pp-number" in the Standards) is less detailed and thus accepts as
preprocessing tokens a superset of valid floating-point literals.  In most
cases the difference is immaterial because the result of preprocessing a
pp-number that is not a valid floating-point literal will cause an error
during compilation.  In some cases involving macros, however, the
difference is significant.  For example:

  #define MACRO 1
  int x = 0xE+MACRO;

If the string "0xE+MACRO" is lexed as a single preprocessing token, as
required by the Standards, MACRO will not be replaced by 1 and the result
will not be valid when compiled.  If the string is lexed according to the
full syntax used for compilation, MACRO will be treated as a separate token
and will be replaced by 1, which produces valid output for some emulations.

The front end had two problems in this area.  First, when doing combined
preprocessing and compilation, it used the pp-number grammar for the
preprocessing step only in strict mode; all other modes used the regular
compilation grammar.  However, the GNU preprocessor uses the pp-number
grammar, so the front end now does so in both strict and GNU modes.
Second, the front end always used the pp-number grammar when doing
preprocessing only (-E or -P), regardless of the emulation mode in effect;
now the emulation mode controls whether pp-numbers are recognized, both
when producing preprocessing output and when compiling.


5/11/12  [EDGcpfe/12845]
Microsoft compatibility: Scoped enumeration types

The front end now accepts scoped enumeration types in Microsoft modes with
microsoft_version >= 1700.  The feature follows the similar C++/CLI feature in
that it relies on keywords with embedded whitespace (i.e., "enum struct" is
treated as a single keyword rather than as two keywords as it would be in
C++11 mode).


5/10/12  [EDGcpfe/12861]
Source positions for generated IL

Previously, much of the IL generated for the C++11 range-based-for and
Microsoft for-each statements had statement positions set to the position
of the range expression or collection expression, respectively.  Now,
the generated IL has null source position information for the temporary
variables that are created as well as the expressions used to initialize
these temporary variables (with the exception of the range/collection
expression itself which continues to have non-null source position).
This change also turns off source positions on some property and event
reference expansions, and on an operator= expansion.  In all those cases, the
call was already marked as compiler-generated; the difference is that the
routine node won't have a source position.


5/9/12   [EDGcpfe/12886]
Size of string literal that is the initializer for a flexible array

A change made in version 4.3 destroyed some information in the size of
string constants used to initialize a flexible array (e.g., in gcc mode).
In this example:

  struct A {
    char c;
    char str[];
  };
  struct A a = { 0, "abc" };

The type of the "abc" string constant had been array[4] of char before
version 4.3, and became array[] of char in 4.3.  It's now back to the
complete array type.  [Patch sent out 5/17/12 as part of 4.4.1.]


5/9/12   [EDGcpfe/12580, EDGcpfe/12891]
Unnamed bit fields of enumeration type

In modes that accept enumeration definitions with explicit underlying types
(e.g., C++11 modes), the front end incorrectly parsed unnamed bit fields 
declared with an elaborated enumeration type (it treated the colon of the bit
field declaration as the introduction of the underlying type).  For example:

  enum E { e };
  struct S {
    enum E: 8;  // Previously triggered spurious errors.
  };

This is now fixed.


5/9/12   [EDGcpfe/12913]
Microsoft compatibility: Multiple returns in lambdas with implicit return type

In Microsoft mode, lambdas with an implicit return type are now allowed
to contain multiple statements and multiple returns as long as the
returns all imply the same return type.

  auto f = [](int i)
  {
    if (i > 10) return true; else return false;
  };


5/9/12   [EDGcpfe/12914]
Internal errors following use of invalid template default argument

A number of different kinds of internal errors could result if on the
use of an invalid default template argument of a function template.
Now fixed.  This particular example would get an internal error in
check_for_nonreal_instance in versions built with EXPENSIVE_CHECKING.

  struct A { void f(); void f(int); };
  template <class T = T> void f(T) {} 
  int main() {
    f(&A::f);  // cannot deduce T so default value is used
  }


5/4/12   [EDGcpfe/12898]
C++/CLI: Abort after malformed property definition

The front end could previously abort (usually in enter_cli_property_accessor)
after certain malformed property definitions (particularly, if a closing brace
is missing).  For example:

  ref class R {
    property int p {
      int get() {  // Note missing closing brace.
    }
    R();
    void f();      // Triggered an abort in enter_cli_property_accessor.
  };

This is now fixed.


5/4/12   [EDGcpfe/12906]
C++/CLI: Generic instance flag not set for generic functions

The is_generic_instance flag was not set for the routine entry for
a generic function in the generic definition class and in any instantiations
of the class.  Now fixed.

  generic <class T> ref class A {
    generic <class U> void f(){}
  };


5/2/12   [EDGcpfe/12882]
Abort on attempt to convert pointer-to-member selection x.*y back to lvalue

The front end aborted in assign_expr_to_temp ("temp of class type with cctor")
or conv_class_rvalue_operand_to_lvalue ("couldn't convert to ptr") during
IL lowering on an attempt to convert a pointer-to-member selection
using ".*" whose value is an rvalue (because its left operand is
an rvalue) back to an lvalue so its address can be taken.  Now fixed.
For example (in C++11 mode):

  struct A {
    A() {}
    A(A&&) {}
  };
  struct B {
    A a;
  };
  B f();
  typedef A B::*pd;
  pd p = &B::a;
  A a1 ((f().*p)) ; 


5/2/12   [EDGcpfe/12896]
Microsoft compatibility: use of undefined template names in decltype

We previously made a change to allow the use of undefined namespace
members in decltype expressions in Microsoft mode (see 3/14/12 entry).
Some of the Microsoft headers also require that we infer that the undefined
name is a template in some cases.  The mechanism that allows the use of
undefined names in decltype expressions now assumes that the name is a
template if it is followed by a "<".

  namespace N {}
  template <class T> struct A {
    template <class U> auto f(U) -> decltype(N::X<U>);
  };
  namespace N {
    template <class T> struct X {};
  }


5/2/12   [EDGcpfe/12893]
Internal error after invalid template default argument with EXPENSIVE_CHECKING

An internal error could occur (in check_for_nonreal_instance) if certain
kinds of invalid function template default template arguments were used,
the default argument is needed in a call, and EXPENSIVE_CHECKING is
being used.  Now fixed.

  struct A {
    void f(int);
    void f(char);
  };
  template < class T = T(37) > void f ( T ) { } 
  int main() {
    f(&A::f);
  }


5/1/12   [EDGcpfe/12887]
GNU C++ compatibility: Extraneous size/sign modifiers on typedefs

GNU C++ compilers allow arbitrary size and sign modifiers on typedefs for
integer types that appear in the type-id of new-expressions.  For example:

  typedef unsigned long ULong;
  auto x = new long ULong;   // (1) Now accepted in GNU C++ mode.
  auto y = new short ULong;  // (2) Still not accepted in GNU C++ mode.

The front end now accepts similar modifiers if they're unlikely to cause
confusion.  For example, line (1) is now accepted in GNU C++11 mode, but
line (2) is not.


5/1/12   [EDGcpfe/12850]
operator->* and managed classes

The front end now disallows operator->* members in C++/CLI managed class types.
This matches the behavior of the Microsoft compiler.


5/1/12   [EDGcpfe/10144]
Warning for non-splice trailing backslash inside comment

In non-GNU modes, a backslash followed by whitespace at the end of a line
is not a line splice.  However, visually it is indistinguishable from a
valid line splice, so the front end issues a warning to clarify the reason
for other diagnostics referring to the backslash.  Such a backslash is
harmless inside a comment, however, so the front end has now been changed
to suppress the warning in such cases.  For example (spaces follow the
backslashes):

  /* No warning here: \ 
  */
  // No warning here: \ 


5/1/12   [EDGcpfe/12782]
Microsoft compatibility: processing of members of in-class specializations

Formerly, member functions of Microsoft in-class specializations were
parsed and analyzed at the point where they were encountered in the source
even if they were not referenced.  They are now treated like other member
functions of class templates and are parsed and analyzed when they are
referenced.  They are still parsed and analyzed at the point of definition
when parsing nonclass templates.  This kind of usage is found in the
ppltasks.h header of Visual Studio 11 Beta.

  namespace N {}
  template <class T> struct A {
    template <class T2> struct B {};
    template <> struct B<int> {
      void f() {
        N::X x;  // formerly 'namespace "N" has no member "X"'
      }
    };
  };
  namespace N {
    struct X {};
  }


4/26/12  [EDGcpfe/12863]
C-generating back end: tail padding reuse and bit-field members

In configurations in which tail padding reuse is enabled (see the entry for
EDGcpfe/11008 below), the C-generating back end sometimes failed to insert
necessary padding following base class subobjects before bit-field members
in the derived class or from other base class subobjects, causing the
fields to be incorrectly aligned in the generated code.  This is now fixed.
For example:

  struct B {
    int x : 7;
  };
  struct C {
    int y : 7;    // Had incorrect offset in D objects
  };
  struct D : B, C {
    int z : 7;    // Had incorrect offset in D objects
  };


4/25/12  [EDGcpfe/12854]
C++/CLI: Recursion in constraint checking of generics from metadata

The front end could get into a loop checking constraints of certain
generics imported from metadata.  Although this is not valid C++/CLI
code, the problem would occur processing metadata that is equivalent to:

  generic <typename T> where T : X<T> interface class X {};

Now fixed.


4/24/12  [EDGcpfe/12840]
C-generating back end: tail padding reuse and bit-field members of indirect
base classes

In C-generating back end configurations in which tail padding reuse is
enabled (see the entry for EDGcpfe/11008 below), incorrect C code could be
generated if the first non-static data member of an indirect base class is
a bit-field and the tail padding of that class is reused in the derived
class.  In particular, a call to a base class member function could result
in an attempt to take the address of a bit-field, which is not permitted.
This is now fixed.  For example, given

  struct A {
          A& operator=(A&);
          int zzz : 5;
  };
  struct B : A {
    ~B();
  };
  struct C : A, B { char c; };
  C xC1;

the generated destructor for class C attempted to take the address of zzz
in order to invoke B::~B().


4/23/12  [EDGcpfe/12399]
Microsoft compatibility: Bracketed attributes and specifiers

Previously, Microsoft-style bracketed attributes had to precede all the
declaration specifiers (like inline, static, type names, etc.) of the
affected declaration.  Now, when microsoft_version >= 1700, such attributes
have to precede the type specifiers, but not specifiers like "inline" or
"extern".  For example:

  inline [returnvalue:SA_Post(MustCheck=1)] void f();
      // Now accepted in Microsoft modes with microsoft_version >= 1700.
  inline void [returnvalue:SA_Post(MustCheck=1)] e();
      // Still an error: The attributes cannot appear after "void".


4/23/12  [EDGcpfe/12788]
Incorrect offset for lowered anonymous struct/union pointer-to-data-member

In configurations where non-standard anonymous unions and structs are allowed,
a pointer-to-data-member operation on a member of a nested non-standard
anonymous struct or union had resulted in an incorrect offset when the
pointer-to-data-member constant was lowered (in cases where the non-standard
anonymous struct or union isn't the first member of its parent class).  In this
example, both pointer-to-member offsets were zero:

  struct A {
    int x;
    struct {
      int y;
    };
  } a;
  int main() {
    int A::*px = &A::x;
    int A::*py = &A::y;
    a.x = 1;
    a.y = 2;
    return a.*px == a.*py;  // Had returned 1, now returns 0.
  }


4/20/12  [EDGcpfe/12794]
Abort on invalid pointer-to-member

The diagnosis of certain invalid pointer-to-member types resulted in an abort
in form_type_first_part (il_to_str.c).  For example:

  struct A {};
  void (A::*& (A::*x))();  // Previously triggered an abort.
                           // (This pointer-to-member is invalid because the
                           // member type is a reference type.)

This is now fixed.


4/20/12  [EDGcpfe/12810]
Abort on exception handler with move constructor and trivial copy constructor

The front end previously aborted with internal error in handler_declaration
(decls.c) when processing a catch clause for a class type that has a user-
provided move constructor and a defaulted, trivial copy constructor.
For example:

  struct A {
    A(const A&) = default;
    A(A&&);
  };
  void f() try {
  } catch (A) {  // Previously triggered an internal error.
  }

This is now fixed.


4/20/12  [EDGcpfe/12818]
Abort on defaulted member with severe syntax error

In some cases with unusual syntax errors, the front end aborted in function
assignment_operator_can_be_defaulted (in class_decl.c).  For example:

  struct S {
    ~operator=() = default;  // Previously aborted.
  };

This is now fixed.


4/19/12  [EDGcpfe/12852]
Simplify unused selection expression for static member

When lowering an eok_dot_static operation, the selection expression is
maintained if it has side-effects, but now that expression is simplified if
possible.  In the example below, the resulting lowered code had an
extraneous eok_indirect operation which is now elided:

  struct A {
    static void sf();
  };
  A& f();
  int main() {
    f().sf();
  }


4/18/12  [EDGcpfe/12848]
Static functions found on dependent lookup

Dependent lookup now finds static functions (in accordance with Core
Issue 561) in most modes.  Formerly, that was done only in C++11 mode
and in g++ mode. The C++03 standard specifies that dependent lookup
should not find static functions, but that's changed in C++11, and other
compilers (e.g., g++) have always found them.  Note that because
static functions are found when dependent lookup is not done, our effective
behavior is unchanged in all version levels of g++ and Microsoft modes.

  void f(void *) {}
  static void f(int) {}
  template <class T> void g(T p) {
    f(p);  // No error now in non-strict C++03 mode; static f found
  }
  int main() {
    g(1);
  }


4/18/12  [EDGcpfe/12776]
Uninitialized return value from destructor in some IA-64 ABI cases

In configurations where destructors return "this" (i.e., when
IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS is TRUE), it was possible for
the value returned by a destructor to be uninitialized in cases where the
destructor had multiple "return" statements and the amount of cleanup to
be performed was different between the "return" statements.  For example:
[Patch sent out 5/17/12 as part of 4.4.1.]

  bool b = true;
  struct A { ~A(); };
  struct B {
    ~B() {
      if (b) return;  // Had returned an uninitialized value.
      A a;
      return;         // Had returned the proper "this" value.
    }
  } x; 


4/18/12  [EDGcpfe/12149,EDGcpfe/12791]
Template argument deduction and base/derived mismatch on pointer-to-members

The standard does not permit a pointer to member of a base class to be used
where a pointer to member of a derived class is expected in template
argument deduction, but most compilers allow this.  We now accept such
usage except in strict mode.  Below are two kinds of usage that are now
accepted.

  file: t1.c:
  struct Base {
    template <class U> void f(U);
  };
  struct Derived : Base { };
  int main() {
    void (Derived::*p)(int) = &Base::f;  // now allowed (except in strict mode)
  }

  file: t2.c:
  struct Base {
    void f(int);
  };
  class Derived : public Base { };
  template <typename R, typename A> void f(R (Derived::*p)(A), A) {}
  int main() {
    f(&Base::f, 1);  // now allowed (except in strict mode)
  }



4/16/12  [EDGcpfe/12847]
Deleted function templates and the C++-generating back end

When support for deleted functions was not enabled, the front end sometimes
failed to diagnose the unrecognized syntax, and instead the C++-generating
back end aborted with an internal error in gen_template.  For example:

  template<class T> void f(T&) = delete;
           // Previously caused an abort in the C++-generating back end if
           // support for "= delete" was disabled.

If support for "= delete" was enabled, the C++-generating back end rendered
the "= delete" part twice (i.e., "= delete = delete").

Both of these problems are now fixed.


4/16/12  [EDGcpfe/12835]
Abort on use of variadic non-template member function within itself

The front end aborted ("determine_function_viability: no param, no default
arg", though that message also comes up for other aborts we've seen)
on processing a reference to a non-template member of a variadic
class template, where the member has a parameter pack expansion in
its parameter list, and the reference is within that member function,
and prototype instantiations are being done.  For example (with --c++11):

  template <class ...T> struct A {
    A() {}
    A(const T&...) {
      A a;  // Caused abort on processing looking for default constructor
    }
  };


4/15/12  [EDGcpfe/12570]
C++/CLI: generic and not generic with same name only allowed from metadata

A generic class and non-generic class can have the same name when reading
code from metadata in C++/CLI mode, but this was incorrectly allowed
from source as well.  Now fixed.

  generic <typename T> ref class A {};
  class A {};
  class B {};
  generic <typename T> ref class B {};


4/13/12  [EDGcpfe/12837]
Abort after syntax error in C++/CLI property or event accessor

Certain syntax errors in C++/CLI property or event accessors previously could
trigger an abort (often in enter_cli_property_accessor).  This was more likely
when the enclosing (managed) class was the last declaration in the translation
unit.  For example:

  ref struct R {
    property int p {
      int get() { x
  };
  // End-of-translation-unit: The front end previously aborted here.

This is now fixed.


4/13/12  [EDGcpfe/8100,EDGcpfe/8276]
Aggregate class types with const or reference members

Previously, the front end issued a warning when an aggregate class type
included a reference or a const member.  Now that diagnostic is a remark
instead, because aggregate initialization syntax can still validly initialize
such members.  For example:

  int x;
  struct S { int &r; } s = { x };  // Previously a warning.  Now a remark.


4/11/12  [EDGcpfe/12836]
Microsoft compatibility: class templates with multiple attributes

Spurious errors could result if a class template had multiple Microsoft
attributes.  Now fixed.

  template <class T> [xxx] [yyy] struct A {
    void f(A<T> a){}
  };


4/11/12  [EDGcpfe/12595]
C++-generating back end: friend declarations of template parameters

C++11 allows a template parameter to be declared as a friend by using just
the name of the parameter and omitting the class/struct keyword.  MSVC++
has accepted such declarations, with or without the class/struct keyword,
for a long time; g++, beginning with version 4.7 (with the -std=c++11
command-line option), now accepts these declarations as well, but only if
the keyword is omitted.  The C++-generating back end previously added a
keyword in a friend declaration of a template parameter, even if the
original source had none; it has now been changed to omit the keyword in
such friend declarations.  For example:

  template<typename T> struct S {
    friend T;   // Previously generated as "friend class T;"
  };


4/10/12  [EDGcpfe/12823]
C++-generating back end: qualified enumerator names in constant expressions

In constant expression contexts (case labels, array bounds, and bit-field
sizes), the C++-generating back end always put out a reference to a class
member enumerator using the class in which it is declared as the qualifier.
This caused errors in the generated code when the name is inaccessible in
its own class but accessible via a derived class.  This has now been fixed
by preserving the qualifier used in the original source in such references
(only in configurations that set DEFAULT_RECORD_FORM_OF_NAME_REFERENCE to
TRUE).  For example:

  class B {
  protected:
     enum E { e = 1 };
  };

  struct D : B {
    friend struct S;
  };

  struct S {
    int i : D::e;   // Previously generated as B::e, an access error
  };


4/9/12   [EDGcpfe/12828]
Spurious error on C++/CLI named overrider generic class

The front end previously issued a spurious error on a named overrider for a
generic member function of a generic class if the overridden member was not
itself a member of a generic class.  For example:

  interface struct I {
    generic<typename U> virtual void f(U u);
  };
  generic<typename T> ref struct R: I {
    generic<typename U> virtual void g(U u) = I::f {}
                                   // Previously triggered a spurious error.
  };

This is now fixed.


4/6/12   [EDGcpfe/12826]
Assertion failure with multibyte characters in macro argument

In configurations with FULLY_RESOLVED_MACRO_POSITIONS set to TRUE, a macro
argument containing multibyte characters could result in an assertion
failure in clone_macro_text_map_entries ("offset not found").  This is now
fixed.  For example, the following text containing shift-JIS characters
aborted on some systems:

  #define L(exp) (_frm_.eha.caller.line = __LINE__, (exp))
  #define SET_LOG_BLOCK(args, blk)                                         \
                        (boo(make_log_info args , __FILE__, __LINE__, blk))
  #define SET_LOG(args) SET_LOG_BLOCK(args, (_frm_.call_pos = 'I'))
  #define DB_SQLCHK_FL(tbl, macro, info, mask, print_log) \
        ((5000 & ~mask) ?                                 \
          (print_log((2001,5,macro, info,                 \
                      sqlca.sqlcode, goo())), 600):       \
          600)
  #define DB_SQLCHK(tbl, macro, info) \
      DB_SQLCHK_FL(tbl, macro, info, 100, SET_LOG) 
  void foo() {
    L(DB_SQLCHK("M_SRYSEKY_CATGLNK", "INSERT", "資料純Rード"));
  }


4/5/12   [EDGcpfe/12821]
Microsoft compatibility: Calling conventions and lambda expressions

In Microsoft mode, the closure type for a no-capture lambda now includes
multiple conversion functions to function pointers: One each for the __cdecl,
__stdcall, and __fastcall conventions.  If C++/CLI mode is enabled, the
__clrcall convention is also added to that list.  For example:

  typedef int (__stdcall *FP1)();
  typedef int (__cdecl *FP2)();
  auto x = []{ return 42; };
  FP1 fp1 = x;
  FP2 fp2 = x;  // Now both initializations are accepted.

(See also the Changes entry for [EDGcpfe/10612,EDGcpfe/11770,EDGcpfe/12243] of
1/17/12.)


4/4/12   [EDGcpfe/12732]
Suppress warning on entity that could be referenced by a template

In modes in which non-class templates are parsed, we issued warnings on
unreferenced static entities.  This could result in spurious warnings
in modes in which not all used template instances are instantiated,
because a dependent call could result in a reference to the static
entity.  We now suppress the warning for names used somewhere as the
function name in a dependent call unless all referenced instances
are instantiated (e.g., -tused or -tall modes).  The warning is only
suppressed in translation units that make use of some sort of templates.

  static void f1(int) { }  // no warning because of dependent call of f1
  static void f2(int) { }  // warning because of no dependent call of f2
  template <typename T> void g(T t) { f1(t); }
  int main() {
    g(1);
  }


4/4/12   [EDGcpfe/12748,EDGcpfe/12805]
Assertion failures in C++11 mode with plain-old "for" statements

As a result of adding code to support the C++11 range-based "for" statement
(see [EDGcpfe/9255,EDGcpfe/11021]), some plain-old "for" statements (mostly
those with destructions required in the for-init clause, but others as well)
had resulted in an assertion failure in for_statement.  A change has been made
to disambiguate the range-based "for" and plain-old "for" statements earlier so
that they can be dealt with separately, avoiding the issues that led to the
assertion failure.  This example had resulted in an assertion failure (with
--c++11 in IA-64 ABI configurations):

  struct A {
    ~A();
  };
  void f() {
    for (A();;) ;
  }


4/3/12   [EDGcpfe/12816]
Error recovery on conversion on argument of constructor call

The front end aborted while recovering from an error on the conversion
for an argument of a constructor call, in obscure cases.  Now fixed.
The following aborted (in full_adjust_class_object_type, in overload.c)
in --c++11 mode:

  struct A {
    A(A) ;   // Error
    operator void*();
  };
  struct B {
    operator A();
  };
  template <class T, class U> auto f(U y) -> decltype((T)y) {}
  void g() {
    f<A>(B());
  }


4/2/12   [EDGcpfe/12819]
Abort in access checking in partial specialization SFINAE contexts

The changes for access checking in SFINAE contexts (see 12/15/11 entry)
could result in an abort (in have_particular_member_access_privilege)
when doing SFINAE access checking in the context of determining
whether a partial specialization matches a given class template
specialization.  Now fixed.  [Patch sent out 5/17/12 as part of 4.4.1.]

  class B {
    template <class T> struct C { } ; 
  };
  template <template <class> class T, class U> class A { };
  template <class U> class A<U::template C,U> { };
  A<B::C,B> abi;


3/30/12  [EDGcpfe/12806]
Lowering of value-initialized construction whose constructor is defaulted

Lowering now correctly assumes that a defaulted constructor is not
user-provided, and subsequently uses zero-initialization when
value-initialization specifies a defaulted constructor.  For example (with
--c++11):

  typedef __EDG_SIZE_TYPE__ size_t;
  extern "C" void *memset(void *s, int c, size_t n);
  extern "C" void *malloc(size_t n);
  struct X {
    int i;
    X() { i = 1; };
  };
  struct A {
    X x;
    A() = default;
    int ii;
    void *operator new(size_t sz) {
      void *result = malloc(sz);
      memset(result, 1, sz);
      return result;
    }
  };
  int main() {
    A *p = new A();
    return p->ii != 0;    // had returned 1, now returns 0
  }


3/30/12  [EDGcpfe/12807]
Return or throw of parameter should allow move optimization

The test for the possibility of a move optimization on a return failed to
allow a return of a parameter of the function.  Likewise for a throw
of a parameter.  Core Issue 1148 allows both.  Now, we do too.

  struct A {
    A();
    A(A&&);
  };
  A f(A a) {
    return a;  // Okay; formerly got a spurious error
  }


3/29/12  [EDGcpfe/12804]
C++-generating back end, GNU compatibility: attribute position in parameter
declarations

The C++-generating back end normalizes the position of attributes that
apply to the declarator in a declaration so that they appear in postfix
notation, i.e., following the complete declarator.  Versions of g++ prior
to 3.4, however, issue an error when attributes appear in this position in
a parameter declaration.  The C++-generating back end has now been changed
to place such attributes immediately preceding the identifier in parameter
declarations when gcc_is_generated_code_target is TRUE and
gnu_target_version_number < 30400.  For example:

  int f(int (* __attribute__((__cdecl__)) p)());  // Previously generated as
                         // int f(int (* p)(void) __attribute((__cdecl__)));


3/28/12  [EDGcpfe/12800]
Class modifiers on definition of classes nested in class templates

In Microsoft C++ mode, the front end previously issued spurious errors on a
definition of a class nested in a class template if that nested class included
a modifier "sealed" or "abstract" (the error occurred during the instantiation
of the class template).  For example:

  template<class T> struct S {
    struct N sealed {};  // "sealed" is a class modifier.
  };
  S<int> s;  // This previously triggered an error for S<int>::N.

This is now fixed.
  

3/28/12  [EDGcpfe/12802]
Declarations overloading concrete GNU __sync_... functions

Calls to GNU __sync_... functions are dispatched to concrete implementation of
those functions for certain small data sizes (see Changes entry of 7/31/07).
Previously, the front end could issue an internal error in adjust_gnu_sync_call
(expr.c) if the program overloaded such a concrete __sync_... function (in
GNU C++ mode).  For example (assuming a 4-byte int type):

  int __sync_add_and_fetch_4(int *a) {  // Overloads the built-in function.
    return __sync_add_and_fetch(a, *a); // Previously an internal error.
  }

This is now fixed.


3/27/12  [EDGcpfe/12796]
Incorrect value of cache_tokens count in lexical stack state

The disambiguation routines could increment the cache_tokens value of
the current lexical stack state entry without doing the corresponding
decrement at the end of disambiguation.  This did not result in any
user-visible problems, but could result in extra memory use and slightly
slower compile times.  Now fixed.

  class A {
    void f(int i) {}
  };


3/26/12  [EDGcpfe/12784]
Incorrect setting of "needed" flag with some lowered function pointer types

If a lowered routine has a function pointer as a parameter and that function
type has a parameter that had been modified by lowering to return a
pointer instead, the "needed" flag on the type of the lowered parameter
may have been set incorrectly.  For example, the type "ptr to A"
had been set to FALSE and is now set to TRUE (when lowered) in this case:

  struct A {
    A(const A&);
  };
  void f(void (*PF)(A)) {}


3/26/12  [EDGcpfe/12630]
C++-generating back end: linkage specification on redeclaration after
internal-linkage definition

The change for EDGcpfe/12666 covered only cases in which the variable was
given external linkage with C++ name linkage.  It thus did not address the
similar case in which a variable has internal linkage and is redeclared
with a linkage specifier that is ignored.  This has now been addressed in
the same way, by adding an "extern" specifier to take the place of the
omitted linkage specifier.  For example:

  const int i = 5;
  extern "C" const int i;  // Previously generated as "const int i;", a
                           // redefinition; now as "extern const int i;",
                           // a redeclaration.


3/26/12  [EDGcpfe/12752]
Incorrect setting of "needed" flag in some lowered array types

When copying a type (i.e., using copy_type_full), the "needed" flag value
had also unwittingly been copied to the new type, creating a new type
whose "needed" flag was improperly set to TRUE.  This caused problems
in the cases like the example below where lowering creates a new array
type by copying an existing array type and changing the underlying element
which had resulted in an array type that was marked as "needed" pointing
to an underlying element type whose "needed" flag was FALSE.  To
prevent this, copy_type_full and break_instance_source_corresp have both
been changed to reset the "needed" and keep_in_il flags.  For example:

  struct A {
    int m[2][2];
    virtual void f(void);
  };
  void A::f() {
    m[0][0] = 0;
  }
  void f(A a) {
    A aa = a;
  }


3/26/12  [EDGcpfe/12792]
C++-generating back end, GNU compatibility: abort with extra template
parameter list on partial specialization

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end aborted with a segfault in gen_template_header when
the source contains an extra template header in the declaration of a
partial specialization (a g++ extension; see the entry for EDGcpfe/12118
below).  This is now fixed.  For example:

  template<typename T> struct A { };
  template<typename T> struct B { };
  template<> template<typename T> struct A<B<T> > { }; // Previously aborted


3/24/12  [EDGcpfe/12789]
Microsoft compatibility: Internal error comparing nonreal instances

An internal error could occur (in check_new_class_instantiation) when
comparing dependent template argument lists when microsoft_version <= 1100
and EXPENSIVE_CHECKING is TRUE.  Now fixed.  This problem was introduced
by a change made in version 4.2.

  template <class T> struct A {};
  template <class T> struct B { A<T> a;};
  template <class T> struct C { A<T> a;};


3/23/12  [EDGcpfe/12773]
__is_final

When type traits helpers are enabled (e.g., in C++11 mode) the front end now
recognizes the additional helper __is_final: It takes a type and produces the
value 1 if the type is a "final" class type; otherwise it produces 0 (or an
error if the argument type is an incomplete class type).  For example:

  class C {};
  class F final: C {};
  class [[final]] A: C {};

  static_assert(!__is_final(int), "int is not final");  // Okay.
  static_assert(!__is_final(C), "C is not final");      // Okay.
  static_assert(__is_final(F), "F is final");           // Okay.
  static_assert(__is_final(A), "A is final");           // Okay.

  int i = __is_final(struct S);   // Error: S is incomplete.


3/23/12  [EDGcpfe/12785]
Microsoft compatibility: invalid use of template keyword with --parse_templates

The Microsoft compiler allows invalid uses of the template keyword as used
for syntactic disambiguation.  We allowed these uses in our normal Microsoft
mode, but issued errors on template definitions when nonclass templates are
being parsed.  Note that it is not possible to compile arbitrary code
written for the Microsoft compiler when using --parse_templates, so it is
still the case that not all invalid uses of the template keyword are accepted.

We accept a call of a dependent function template without the use of the
"template" keyword if a normal lookup in the scope of the reference finds a
function template or an overload set containing a function template (even
though that function template will not end up being the one that is
actually called).  This is case #1 in the example below.  We also accept a
qualified name in which the template keyword is followed by an identifier
that does not have a template argument list.  This is case #2 in the
example below.

  template <typename T> struct A {
    template <typename U> void f(U);
  };
  template<typename T> struct B {
    A<T> a;
    template <typename U> void f(U);
    void g(T t) {
      a.f<T>(t);  // #1
      a.A<T>::template f(t);  // #2
    }
  };


3/22/12  [EDGcpfe/11904]
Explicit conversion function allowed on first argument of copy constructor
in direct-initialization

Core Issue 899 adds a special rule that allows use of explicit conversion
functions on the first argument of a copy constructor call that is
effecting a direct-initialization.  The front end now implements that.

  struct A {
    A();
  };
  struct B {
    explicit operator A();
  };
  int main() {
    B b;
    A a(b);  // Now accepted in --c++11 mode
  }


3/22/12  [EDGcpfe/12781]
C++-generating back end, GNU compatibility: g++ abort on generated code with
qualified typedef name in nested class of class template

Versions 4.2 and 4.3 of g++ had a bug that resulted in a segfault when the
source code declares a member of a nested class of a class template, the
declaration of the member uses a typedef defined in the containing class
template, the typedef is named in the declaration using a qualified name,
and the member is defined outside the class template.  In configurations
with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the C++-generating back
end put out the name of such a typedef using a qualified name if the nested
class has a dependent base class, causing the generated code to trigger the
g++ bug.  This has now been addressed by using the underlying type of the
typedef instead of the qualified name of the typedef when
gcc_is_generated_code_target is TRUE and gnu_target_version_number
designates one of the affected g++ versions.  For example:

  template<typename T = int> struct A {
    typedef int *IP;
    struct B { };
    struct C : B {
      C(IP);   // Previously generated as "C(typename ::A< T> ::IP)", now
               // as "C(int *)"
    };
  };
  template <typename T> A<T>::C::C(IP) { }


3/22/12  [EDGcpfe/12783]
Abort on folding of dependent cast to base class

In modes that parse template bodies (e.g., strict mode, g++ mode with
higher version numbers), folding of a cast of a dependent pointer
constant to a pointer to a base class could abort
("get_pointer_offset: bad kind").  This happened only in certain cases
where a base class relationship could be discerned in spite of the
fact that the addresses involved are dependent, as in the following
example:

  template <class T> struct A { 
    int foo(T);
  }; 
  template <class T> class B: public A<T> {}; 
  class C; 
  template <int I> struct E { 
    static B<C*> svar;
    static void bar(C *cp) { 
      int i = (&svar)->foo(cp);   // Base class cast on "->" aborted
    } 
  }; 
  void g(C *c) { 
    E<4>::bar(c); 
  }

Now fixed.


3/21/12  [EDGcpfe/12427]
Binding an rvalue reference to a converted lvalue

The Core Working Group has clarified (Core Issue 1138) that an rvalue
reference can be bound to an rvalue produced by converting an lvalue
to another type.  The front end now allows that.

  int i = 1;
  double &&r = i;


3/21/12  [EDGcpfe/12774]
GNU and Microsoft compatibility: spurious error following nesting depth warning

In cases where a warning was issued for a nesting depth mismatch on a
template declaration, a spurious error could be issued after complaining
that a nontype template parameter was incompatible with the previous
declaration.  Now fixed.

  template <class T> struct A {
    template <int i> class B {
      template <int j> friend class B;
    };
  };
  A<int>::B<1> a;


3/21/12  [EDGcpfe/9807,EDGcpfe/12775]
Generated default constructors in C++11 and Microsoft modes

In C++11 mode, the front end now treats a generated default constructor as a
deleted member (i.e., as if defined with "= delete;") if the ordinary
generation process would result in an error.  In Microsoft mode, no default
constructor is generated at all in such circumstances.  For example:

  struct B { B(B const&); };  // No default constructor.
  struct D: B {};  // D's default constructor cannot be generated since there
                   // is no corresponding B constructor.  In Microsoft mode,
                   // the default constructor is no longer declared at all.
                   // In C++11 mode, the default constructor is "deleted".
                   // In other modes an error is issued when the definition
                   // of the default constructor is generated.
  D d;  // Different errors are issued in Microsoft mode, C++11 mode, and
        // other C++ modes.

In C++ mode, a defaulted default constructor is now also implicitly deleted if
the ordinary generation process would result in an error.


3/21/12  [EDGcpfe/12772]
Microsoft compatibility: Exported generated member functions

In Microsoft mode, the front end generally forces an out-of-line copy of an
inline function that is "dllexported".  Previously, however, it did not do so
for generated members.  Now, it does.  For example:

  struct __declspec(dllexport) B { ~B(); };
  struct __declspec(dllexport) D: B {};
    // The generated destructor of D now gets an out-of-line copy.


3/21/12  [EDGcpfe/12746]
Microsoft compatibility: explicit template arguments in friend template

The Microsoft compiler allows explicit template arguments to be provided
in a friend function declaration in a class template.  We now allow this
usage (with a warning).

  template<typename V> void f() {};
  template <typename U> class A {
    template<typename V> friend void f<V>();
  };


3/21/12  [EDGcpfe/12767]
C++/CLI: internal error on redefined event or property

An internal error could occur (in add_base_classes_to_hide_by_sig_list)
following a normal error if a property or event was redefined in class.
The internal error would occur on an attempt to use one of the accessor
functions.  Now fixed.

  delegate void D();
  ref struct R {
    event D^ E { void add(D^ k ) {} void remove(D^ k ) {} }
    event D^ E { void add(D^ k ) {} void remove(D^ k ) {} }
  };
  void f() {}
  int main() {
    R r;
    r.E += gcnew D(f);
  }


3/21/12  [EDGcpfe/10628]
Diagnostic on comparison of address of local variable to NULL

The front end now checks, on equality and inequality comparisons of
a pointer operand against NULL, whether the pointer operand cannot be
NULL (e.g., if it is the address of a local variable).  It issues
a diagnostic if so.  However, because this diagnostic is "lint-like,"
and produces a lot of false positives in real code, it is disabled
by default.  --diag_warning=known_comparison_with_null can be used
to enable it (or set_default_message_severities can be changed not
to suppress it).  With the right settings, the following will draw
a diagnostic:

  bool f1(int n) { return &n != 0; }

The check also covers references, for example:

  bool f2(int &n) { return &n != 0; }

Standard C++ says that a reference can never contain a null address,
so the comparison above is always true.  However, because many
compilers (e.g., g++) allow null references, there is now a variable
controlling that, assume_references_cannot_be_null, which, by default,
is FALSE except in strict mode.  That means in most modes no
diagnostic will be issued for the f2 case above.


3/21/12  [EDGcpfe/11293]
GNU and Microsoft compatibility: friend declarations that refer to undefined
members

The Microsoft and g++ compilers allow a friend declaration nested in a
class template to refer to an undefined member of the class template.
We now emulate this behavior in Microsoft and g++ modes (with a warning).

  template <class T> struct A {
    struct B {
      friend void A::f();  // now allowed
      friend struct A::C;  // now allowed
    };
  };


3/20/12  [EDGcpfe/12770]
C++/CLI: Abort on derived class when debugging option is active

The front end sometimes aborted in verify_virt_func_override_list (in
class_decl.c) when processing certain derived classes in C++/CLI mode when
a debug option (like "-d-1") is active.
For example:

  ref struct B { virtual int f(); };
  ref struct D: B {
    ~D() {}
    virtual int f() override;
  };  // Triggered an abort if the debug option "-d-1" was specified.

This is now fixed.


3/20/12  [EDGcpfe/12216]
Defaulted move operations

In C++11 modes that permit the generation of move constructors and move
assignment operators (see Changes entry of 3/16/12), the front end now
permits such special members to be explicitly "defaulted".  For example:

  struct MO { MO(MO&&); };
  struct DM {
    DM(DM&&) = default;  // Now allowed in many C++11 modes.
    MO mo;
  };

Such defaulted move operations are also permitted in GNU C++ mode with
gnu_version >= 40500 (even though move operations are not generated by
default when gnu_version < 40600).


3/20/12  [EDGcpfe/12768]
GNU C++ compatibility: Extraneous comma after member declarator

In GNU C++ mode with gnu_version >= 30400, the front end now accepts an
extraneous comma after a class member declarator (with a warning), if that
comma is followed by a semicolon.  For example:

  struct S {
    S(),;    // Now accepted with a warning in GNU C++ mode.
    int i,;  // Ditto.
  };


3/19/12  [EDGcpfe/12695]
C++-generating back end: qualification of names hidden by members of
dependent bases

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end failed to consider members of dependent bases when
determining whether a reference to a name in a containing scope required
qualification or not.  This is now fixed.  For example:

  template<typename T> struct A {
    typedef T X;
  };
  template<typename T> struct X { };
  template<typename T> struct C : A<X<T> > {
    typedef A<::X<T> > ax;  // Previously generated as A< X< T> >
  };


3/19/12  [EDGcpfe/12762]
Enumeration type with explicit underlying type in Microsoft mode

Although the front end accepted the definition of enumeration types with an
explicit underlying type in Microsoft modes (with microsoft_version >= 1400;
see Changes entry of 3/6/06), it did not actually use the specified type for
the underlying type.  For example:

  enum E: char { e };
  static_assert(sizeof(E) == sizeof(char), "Unexpected");
    // Previously, the front end failed this assertion in Microsoft mode.

This is now fixed.  This bug was a consequence of the emulation of a Microsoft
compiler behavior whereby enumeration types can be declared without being
defined, but the declaration is sufficient to consider the enumeration type
"complete" (with underlying type int; see Changes entry of 4/11/95).
For example:

  enum E x;  // Accepted in Microsoft modes

Now, however, if such an incomplete declaration is followed by a definition
that specifies an explicit underlying type other than int, the old enumeration
declaration is rendered invisible and the definition introduces a new,
distinct type.  A warning is issued in such cases.  For example:

  extern enum E *p;    // (1)  Type underlying E is int.
  enum E: char { e };  // Warning: E here is different from line (1).
  enum E *p;           // Error: Incompatible redeclaration of p.

This somewhat surprising behavior matches that of the Microsoft compiler (but
the Microsoft compiler will not issue the warning).


3/19/12  [EDGcpfe/12769]
GNU C++ compatibility: dependent name accessible by non-dependent base class

If a base class is both a dependent base class of a nested class and a
non-dependent base class of an enclosing class, g++ (prior to version 4.6)
finds the name from the enclosing class but then treats that as a reference
to the inherited member of the nested class.  We now emulate this behavior
in g++ mode when gnu_version < 40600.

  struct A {
    int i;
  };
  struct C : A {
    template<typename T> struct D : T {
      void f() {
        i = 1;  // now allowed (should be "this->i = 1")
      }
    };
 };
  int main() {
    C::D<A> cda;
    cda.f();
 }


3/19/12  [EDGcpfe/12299]
printf/scanf checking of argument of type pointer to template parameter

The front end does checking of compatibility between printf/scanf
formatting specifiers and the corresponding arguments.  While it
correctly handled an argument with a template parameter type, it
failed to do so for an argument with a pointer-to-template-parameter
type, with the consequence that a spurious warning could be issued.
Now fixed.

  struct S {
    char name[1];
  };
  struct A {
    static void f(const char*, ...) __attribute__ ((format(printf, 1, 2)));
  };
  template <class T> void test(const T& st) {
    A::f("%s", st.name);  // Spurious warning with --g++ -tused
  }
  int main() {
    S st;
    test(st);
  }


3/16/12  [EDGcpfe/10615,EDGcpfe/12282,EDGcpfe/12565]
C++11: Generated copy and move operations

In C++11 mode, the front end now generates move constructors and move
assignment operators according to the new standard rules.  In addition, the
rules have also changed somewhat for generated copy constructors and generated
copy assignment operators -- in particular, these are sometimes implicitly
"= delete".  For example:

  struct MO { MO(MO&&); };
  struct GM {
    MO mo;
  };  // In C++11 mode, GM has a generated move constructor and a
      // deleted copy constructor.

This behavior is enabled by default in default and strict C++11 modes.  In
Microsoft modes and GNU modes, the default behavior emulates that of the
corresponding version of the Microsoft and GNU compiler, respectively.  The
new command-line options --gen_move_operations and --no_gen_move_operations
can be used to override the default behavior.


3/16/12  [EDGcpfe/12760]
Spurious error on elided copy constructor with const volatile X&& parameter

The front end issued a spurious diagnostic in some modes about an elided
copy constructor not being callable to copy an rvalue, when the copy
constructor has a parameter that is an rvalue reference to const volatile.
The restriction on binding a reference to const volatile to an rvalue
applies only to lvalue references, not rvalue references.  Now fixed.

  struct A {
    A();
    A(const A&) = default;
    A(const volatile A&&);
  };
  int main() {
    A aa;
    A a = (A)(aa);  // Got spurious warning in --c++11 mode
  }


3/14/12  [EDGcpfe/12757]
C++-generating back end, C++/CLI: explicit call of static property accessor
function

In C++/CLI code in which a static property accessor function is explicitly
called using a member access operator (-> or .), the C++-generating back
end put out the expression as a property access rather than as a function
call.  This has now been fixed via a small IL CHANGE: previously the
enk_routine node in a rewritten property access was annotated with the
property description if it was the direct operand of a call node but not
for the operand of eok_dot_static and eok_points_to_static operators.  Now
those enk_routine nodes are also annotated with the property description in
a rewritten property access.  For example:

  ref struct S {
    static property int P {
      int get();
      void set(int);
    }
  };
  void f(S ^s) {
    int i;
    s->P::set(1);     // Previously generated as s->P = 1
    i = s->P::get();  // Previously generated as i = s->P
  }

In addition, in configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to
TRUE, expr_range.start was left as null_source_position in some nodes in
a rewritten property reference; this has also been corrected.


3/14/12  [EDGcpfe/12677]
Microsoft compatibility: use of undefined names in decltype

The Microsoft compiler allows a decltype in the declaration of a function
template or member function of a class template to refer to undefined
members of a namespace.  We now emulate this in Microsoft mode.  The
Microsoft compiler actually does not do any checking of the contents
of such decltype operators.  Our emulation of this is limited to what is
needed to compile the VC 2010 headers that contain these kinds of constructs.

  namespace N {}
  template <class T> struct A {
    auto f() -> decltype(N::g());
  };


3/13/12  [EDGcpfe/12755]
GNU C++ compatibility: Typedefs for wchar_t in system headers

In GNU C++ mode, the front end now ignores typedefs for wchar_t that appear
in system headers.  For example:

  // The following preprocessor directive simulates a system header.
  #2 "t.c" 3
  typedef unsigned long wchar_t;  // Now silently accepted in GNU C++ mode.


3/13/12  [EDGcpfe/12744]
Position information for GNU built-in variadic parameter operations

The changes for EDGcpfe/11160 (see entry of 12/17/10) caused the front end to
fail to record position information in expression nodes for variadic parameter
operations (when GCC_BUILTIN_VARARGS is TRUE).  For example:

  #include <stdarg.h>
  void g(char *one, ...) {
    __builtin_va_list ap;
    __builtin_va_start(ap, one);  // The resulting eok_va_start node operation
  }                               // previously lacked position information.

This is now fixed.


3/13/12  [EDGcpfe/12756]
C++/CLI: Interface classes are abstract

The front end previously did not set the "abstract" flag to TRUE in C++/CLI
interface class types; now it does.


3/13/12  [EDGcpfe/12596]
C++-generating back end, GNU compatibility: parenthesized pointer to data
member declarator

The change made for EDGcpfe/11722 (in version 4.4), which unconditionally
parenthesized the declarator in the declaration of a pointer to a data
member in the output of the C++-generating back end, triggers a bug in g++
versions 4.5.0 through 4.5.2, resulting in spurious errors when the
generated code is compiled.  The change has consequently been disabled when
gcc_is_generated_code_target is TRUE and gnu_target_version_number is one
of the affected versions.  For example:

  struct S { };
  void f() {
    int S::*(*p)[3] = new int S::*[2][3];  // Previously generated as
                                // int (S::*(*p)[3]) = new (int (S::*[2][3]));
  }


3/12/12  [EDGcpfe/12754]
C++-generating back end, GNU compatibility: parentheses in logical expressions

The C++-generating back end consistently enclosed the operands of the
logical "and" and "or" operators (&& and ||) in parentheses, whether they
were required by the precedence of the expression or not.  In some cases,
the result triggered a bug in g++, resulting in spurious errors when the
generated code was compiled.  This is now fixed, and parentheses are added
in such expressions only where necessary.  For example:

  template<typename T> void f(int i) {
    if (T() && u == 1) {  // Previously generated as "if ((T()) && (u == 1))"
    }
  }


3/12/12  [EDGcpfe/12743]
C++/CLI: Assembly visibility

The front end now records the explicitly-specified assembly visibility of
class and enumeration types in the IL (in addition to the effective
visibility, which was already recorded previously).  Furthermore, the front
end previously failed to take the state of member access specifiers into
account when determining the effective assembly visibility of nested classes.
For example:

  public ref struct R {
  private:
    ref struct N {};  // Previously, N had "public" assembly visibility.
  };                  // Now it has "private" assembly visibility because
                      // the member access specifier "private:" is in effect.


3/12/12  [EDGcpfe/12753]
Abort on access specifier before a brace closing a C++/CLI property

In C++/CLI mode, the front end aborted in enter_cli_accessor (symbol_tbl.c)
when it encountered an access specifier just before the brace closing a
property or event definition.  For example:

  value struct V {
    property int p {
      void set(int x) {}
  private:  // Previously triggered an abort.  Now accepted.
    }
  };

This is now fixed (such access specifiers are treated as normal specifiers
appearing in the parent class of the property or event.


3/12/12  [EDGcpfe/12304]
Use of injected class name in friend declaration

In a friend declaration in which the declarator is a qualified name, a
spurious error could be issued if the injected class name of the enclosing
class template was used without a template argument list.  Now fixed.

  namespace N {
    struct B {
      template <class T> static int g(T *a) { return 0; }
    };
    template <class T> inline int h(T *t) { return T::f(t); }
    template <class T> struct A {
      friend int T::g(A *a);  // formerly "argument list ... is missing"
      static int f(A *a) { return T::g(a); }
    };
  }
  int main() {
    N::A<N::B> *a = 0;
    N::h(a);
  }


3/12/12  [EDGcpfe/12619,EDGcpfe/12741]
C++11: "final" class modifier

In C++11 mode, the front end now supports the context-sensitive keyword 
"final" as a modifier for a class definition.  It has the same effect as the
[[final]] attribute.  For example:

  struct B final {};  // Struct B cannot be derived from.
  struct B final;     // Variable "final" of type B.
  struct D: B {};     // Error: B cannot be derived from.


3/10/12  [EDGcpfe/12694]
Assertion failure with complex macro expansions

The front end could abort with an assertion failure in expand_macro_buffer
when processing certain complex macro expansions.  This is now fixed.  For
example:  [Patch sent out 5/17/12 as part of 4.4.1.]

  #define CL_NTOH64(x) (long)( (((long)(x) & 0x00000000000000FFULL) << 56) | \
  (((long)(x) & 0x000000000000FF00ULL) << 40) | (((long)(x) & \
  0x0000000000FF0000ULL) << 24) | (((long)(x) & 0x0000FF0000000000ULL) >> 24)\
  | (((long)(x) & 0x00FF000000000000ULL) >> 40) |  (((long)(x) & \
  0xFF00000000000000ULL) >> 56) )
  #define CL_HTON64 CL_NTOH64
  #define IB_MCR_COMPMASK_PKEY (CL_HTON64(((long)1)<<7))
  #define REQUIRED_MC_CREATE_COMP_MASK (IB_MCR_COMPMASK_PKEY)
 
  CL_NTOH64(REQUIRED_MC_CREATE_COMP_MASK)


3/9/12   [EDGcpfe/12738]
C++-generating back end: incorrect qualifier on dependent function call
in --g++ mode

In versions that use the C++-generating back end in g++ mode, dependent
function calls could be emitted with an incorrect qualifier.  This
would occur in member functions or member function templates of classes
with one or more dependent base classes.  The problem only occurred if
there were multiple dependent function calls, and the calls provided
explicit template arguments.  Now fixed.

  template<typename T, typename U> struct A : U {
    template<typename V> void f(U *p) {
      p->template x<T>();
    }
    template<typename V> void g(T *p) {
      p->template x<T>(); // formerly emitted as "p->U::template x<T>()"
    }
  };


3/9/12   [EDGcpfe/12703]
GNU C++ compatibility: use of inaccessible types as template arguments

The g++ compiler ignores some access errors when they occur in a template
argument list.  The g++ bug only occurs if the argument list is followed
by "::".  Our emulation of this bug issues a diagnostic in all cases, but
reduces the severity of the diagnostic to a warning when the reference
appears in a template argument list and when gnu_version >= 30400.

  template<typename T> struct A {
    typedef int type;
  };
  class B {
    struct C {};
  };
  A<B::C>::type x;  // g++ allows
  A<B::C> y;        // g++ does not allow


3/9/12   [EDGcpfe/12689]
Definition in enclosing namespace of a function first declared as a friend

In modes in which friend injection is not enabled, the front end failed to
find a previous declaration of a friend function when the function was first
declared in a friend declaration and was later defined in a namespace
enclosing the one in which it was declared.  Now fixed.  This usage was
formerly accepted in g++ mode when gnu_version < 40300, but is now accepted
in all modes.

  namespace N {
    struct A {
      friend void f(const A &);
    };
  }
  void N::f(const N::A &) {}


3/8/12   [EDGcpfe/12737]
C++-generating back end: dependent class template reference with empty
argument list

In a reference to a dependent class template that is written with an empty
argument list (i.e., assuming that all the parameters of the class template
referred to by the eventual instantiation will have default arguments), the
C++-generating back end when configured with PROTOTYPE_INSTANTIATIONS_IN_IL
set to TRUE put out the reference with no template argument list and,
consequently, without the template keyword as well.  This is now fixed.
For example:

  template<typename T> struct A {
    typedef typename T::template C<> TC;   // Previously generated as
                                           // "typename T::C"
  };


3/8/12   [EDGcpfe/12090]
Microsoft function modifiers recorded in the IL in more configurations

Previously, the Microsoft function modifiers "abstract", "override", and
"new" were only recorded in the IL entry for a member function when
BACK_END_IS_CP_GEN_BE is TRUE.  Now this is also done when that macro is
FALSE.


3/8/12   [EDGcpfe/12742, EDGcpfe/12360]
C++11: "final" and "override" function modifiers

In C++11 mode, the front end now supports the context-sensitive keywords
"final" and "override" as a modifier for a member function declaration.
Their meaning is the same as, respectively, the [[final]] and [[override]]
attributes (see the Changes entry of 12/3/09 and 3/26/10).  For example:

  struct B { virtual void f() const; };
  struct D: B {
    void f() override;  // Error: f doesn't override because "const" is
  };                    // missing.

(Document N3206 replaced the standard attributes by context-sensitive
keywords.  The attribute is still recognized by the front end, however.)


3/8/12   [EDGcpfe/12675]
Give an error when conflicting command line options are specified

Previously, it was permissible to specify multiple command line
options that (implicitly or explicitly) set the language mode with
the last option prevailing (e.g., specifying "--svr4 --c++ --c" would
result in SVR4 "C" mode).  Now, a catastrophic error is given if two or more
command line options which (implicitly or explicitly) specify the language mode
(i.e., "C" or "C++") are present on the command line.  For example,
specifying "--c89 --c++11" is now a catastrophic error.


3/8/12   [EDGcpfe/12719]
C++-generating back end, GNU compatibility: parenthesized initializers

g++ has a bug that causes it to issue a spurious error when certain forms
of initializer expressions are parenthesized.  The C++-generating back end
generally enclosed initializers in parentheses, causing the generated code
to fail to compile with g++ when one of those forms appears in the source.
This has now been fixed by parenthesizing only those initializer expressions
that contain a comma that would otherwise be interpreted as a declarator
delimiter.  For example:

  struct A {
    short operator()();
  };
  int i = A()();   // Previously generated as (A()())


3/8/12   [EDGcpfe/12745]
Copy of class on conversion to rvalue as operand of "?" operator

The front end now copies a class lvalue to a temporary when it
converts it to an rvalue as part of processing as an operand for
the "?" operator, as required by the C++ standard.  It already did
so in many cases, but now does so uniformly.  This was largely invisible
previously, but became important when the changes for implicitly
generating move constructors were done.


3/6/12   [EDGcpfe/12666]
C++-generating back end: variable redeclaration treated as redefinition

The change for EDGcpfe/12152 (in version 4.4), which added explicit
representation in the IL of the storage class specified in a non-defining
declaration of a variable, resulted in a regression in the code generated
by the C++-generating back end in some cases in Microsoft mode.  When a
variable is defined with C++ name linkage and then later redeclared with a
conflicting name linkage, in Microsoft mode the linkage specification is
ignored and the variable has C++ linkage, i.e., the linkage specification
is treated as if it had been simply the "extern" storage class specifier.
However, in the generated code, because the source had no explicit storage
class specifier and the linkage specification was ignored, the declaration
was effectively put out as a definition.  This has now been fixed by adding
the "extern" storage class specifier in such declarations.  For example:
[Patch sent out 5/17/12 as part of 4.4.1.]

  int i = 5;
  extern "C" int i;   // Previously generated as "int i;", a redefinition;
                      // now generated as "extern int i;" (the conflicting
                      // extern "C" specification having been discarded by
                      // the front end)


3/6/12   [EDGcpfe/12614]
C++-generating back end: parenthesized default argument expressions

The change for EDGcpfe/12319 (in version 4.4), which added parentheses to
default argument expressions to work around a bug in g++ versions earlier
than 4.4, was too extensive.  In particular, MSVC++ 6.0
(microsoft_version=1200) had a bug that caused it to issue errors for
certain parenthesized default argument expressions, and the additional
parentheses can also cause problems for versions of g++ earlier than 3.4.
The fix has now been tweaked to add parentheses only when they are actually
needed, i.e., when gcc_is_generated_code_target is TRUE and
gnu_target_version_number is >= 30400 and < 40400 or when the default
argument expression contains a comma operation that would otherwise be
interpreted as a parameter list delimiter.  For example:

  template<typename T, typename U = int> struct S { };
  class C {
    void f(S<int> x = S<int>());  // Default argument now generated as
                                  // "(S<int,int>())" only when targeting a
                                  // g++ version earlier than 4.4, otherwise
                                  // without enclosing parentheses
  };


3/5/12   [EDGcpfe/12676]
Folding of some nonstandard address constant expressions

To match gcc, the front end now folds a pointer difference operation
whose two operands are based on the address of the same auto variable
to a constant result.  To match gcc and Microsoft, the front end now
folds a pointer difference whose first operand has type "char *" and
whose second operand is a zero cast to "char *" to a constant result
(the stride is one in that case, so the result is the first operand
cast to ptrdiff_t).

  int main() {
    struct { char c; char C; } xx;
    static long xxx = ((long) ((char*) &xx . C - (char*) &xx));
  }
  static int x;
  struct A { long i; };
  struct A a = {
    (char *)&x - (char *)0
  };


3/1/12   [EDGcpfe/12731]
C++-generating back end: explicit specialization placed in wrong namespace

In configurations with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE,
when an explicit specialization of a member function template was written
using a qualified name, the C++-generating back end incorrectly placed that
explicit specialization in the namespace containing the leftmost qualifier
used in the name instead of in the namespace of which the template's class
is a member.  This is now fixed.  For example:

  namespace N {
    struct S {
      template<typename T> void f(T);
    };
    template<> void N::S::f<int>(int) { }  // Previously placed in global
                                           // namespace
  }


2/29/12  [EDGcpfe/8226]
Setting of "needed" flag on parameter type of lowered routine type

In cases where lowering modifies the type of a function to return its
value in a parameter rather than as the return value (typically in cases
where the return value is a class that requires a copy constructor),
the type of the newly added parameter had not been marked as "needed"
and is now marked as such (in configurations that have needed flag processing).
In this example the type "const A *" hadn't been marked as "needed":

  struct A {
    ~A();
  };
  const A f();
  void g() {
    f();
  }


2/29/12  [EDGcpfe/12729]
Reuse of temporaries during inlining

Previously, reuse of an existing temporary during the inlining process was
considered only when inlining a call operation that was not the top-most
expression in an expression statement (instead allocating a new temporary).
This restriction has been lifted, allowing reuse of temporaries in this case
as well.  The example below (EDGcpfe/11527) had used an exponential number
of temporaries and now requires significantly fewer.


2/28/12  [EDGcpfe/12671]
C++-generating back end: abort with function template and use of member of
dependent base class

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL, the C++-generating
back end aborted with a failed assertion when the source involved a
reference to a member of a dependent base class appearing in a function
template.  This is now fixed.  For example:

  template<typename T> struct B { };
  template<typename T> void f() {
    struct D: B<T> { };
    typedef typename D::type Dt;   // Previously caused an assertion failure
  }


2/28/12  [EDGcpfe/11527]
Limit size of an inlined routine

In some cases, recursive inlining could lead to the creation of huge
routines, requiring large amounts of front end CPU processing and
memory, possibly resulting in the exhaustion of resources.
An inline routine must now have fewer lowered statements than the limit
set by the new configuration macro DEFAULT_INLINE_STATEMENT_LIMIT, and
optionally modified by the new command line option --inline_statement_limit.
A setting of zero disables this check (which restores the previous
behavior).  The default value for DEFAULT_INLINE_STATEMENT_LIMIT is (somewhat
arbitrarily) set to 100.  A remark is issued when inlining fails due to the
limit being exceeded.  Here's an example that will result in a single
matrix_mul routine (when there is no limit placed on the size of an inline
routine) and, for larger values of "r" may cause resource exhaustion:

  const int r=5;
  template <int r> struct M { M<r-1> dat[2][2]; };
  template <> struct M<1> { double dat[2][2]; };
  template <int r> void matrix_mul(M<r>& c, M<r>& a, M<r>& b);
  template <> inline void matrix_mul(M<1>& c, M<1>& a, M<1>& b) {
    double b00=b.dat[0][0], b10=b.dat[1][0];
    double b01=b.dat[0][1], b11=b.dat[1][1];
    double a00=a.dat[0][0], a01=a.dat[0][1];
    double a10=a.dat[1][0], a11=a.dat[1][1];
    c.dat[0][0] += a00*b00 + a01*b10;
    c.dat[0][1] += a00*b01 + a01*b11;
    c.dat[1][0] += a10*b00 + a11*b10;
    c.dat[1][1] += a10*b01 + a11*b11;
  }
  template <int r> inline void matrix_mul(M<r>& c, M<r>& a, M<r>& b) {
    matrix_mul(c.dat[0][0],a.dat[0][0],b.dat[0][0]);
    matrix_mul(c.dat[0][1],a.dat[0][0],b.dat[0][1]);
    matrix_mul(c.dat[0][0],a.dat[0][1],b.dat[1][0]);
    matrix_mul(c.dat[0][1],a.dat[0][1],b.dat[1][1]);
    matrix_mul(c.dat[1][0],a.dat[1][0],b.dat[0][0]);
    matrix_mul(c.dat[1][1],a.dat[1][0],b.dat[0][1]);
    matrix_mul(c.dat[1][0],a.dat[1][1],b.dat[1][0]);
    matrix_mul(c.dat[1][1],a.dat[1][1],b.dat[1][1]);
  }
  int main() {
    M<r> A, B, C;
    matrix_mul(C, A, B);
  }


2/27/12  [EDGcpfe/12667]
Representation of out-of-range enumerator values

In nonstrict C++ modes enumerator definitions are accepted with enumerator
constants that don't fit in the range representable by the underlying
integer (a warning is issued in such cases).
Consider:

  enum E {  // Elicits a warning in default C++ mode.
    e = -1,
    f = 0xffffffffffffffffLL
  };

Assuming the largest possible enum size is 64 bits, the type underlying E 
ends up being unsigned and the value of e must be adjusted accordingly: with
2's complement representation it becomes equal to that of f.  However, the
front end previously failed to explicitly truncate the internal value
representation (i.e., the type of the enumerator constant was adjusted, but
the bits of the representation were not).  This could lead e.g. the C- and
C++-generating back ends to render an invalid literal for a case like this
(one whose value doesn't fit in a signed or unsigned 64-bit representation).
This occurred especially when INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is FALSE;
in configurations where INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is TRUE and the
largest host integer is the same size as the largest possible size underlying
an enum type, the problem was not observable.  This is now fixed.


2/27/12  [EDGcpfe/11351]
Microsoft compatibility: va_list using-declaration in std namespace

In Microsoft mode, when <stdarg.h> is treated as a built-in header,
and when va_list is not put in namespace std, the front end now
creates a using-declaration for va_list in namespace std so that
std::va_list can be used.

  #include <cstdarg>
  int main() {
    std::va_list x;
  }


2/27/12  [EDGcpfe/12634]
Access checking in SFINAE contexts

Version 4.4 implemented access checking in SFINAE contexts (see 12/15/11
entry).  Access checking of friend function templates was not handled
properly in SFINAE contexts, resulting in spurious deduction failures.
Now fixed.  [Patch sent out 5/17/12 as part of 4.4.1.]

  template <void (*)(int)> struct C {
    typedef int Y;
  };
  template <class T> void f(typename T::X) { }
  class A {
    typedef int X;
    template <class T> friend void f(typename T::X);
  };
  C<&f<A> >::Y g(int);


2/26/12  [EDGcpfe/12726]
C++-generating back end: cv-qualifiers on reinterpret_cast to reference type

The C++-generating back end sometimes incorrectly rendered a
reinterpret_cast to a reference type when the underlying type is
cv-qualified and the result is used as an rvalue.  Now fixed.

  unsigned int f(volatile float x)
  {
    volatile unsigned int y = reinterpret_cast<volatile unsigned int &>(x);
                                // Formerly, type was rendered as "unsigned &"
    return y;
  }


2/24/12  [EDGcpfe/12438]
C++/CLI: Class from metadata implementing their own nested interface

C++/CLI does not normally provide syntax to indicate that a class X implements
an interface X::I.  However, other CLI languages (Visual Basic in particular)
do allow such constructs.  The front end is now able to correctly import
metadata representing such constructs, and managed classes can derive from (or
otherwise make use of) such classes.


2/24/12  [EDGcpfe/9925,EDGcpfe/10899,EDGcpfe/12331]
GNU compatibility: Arguments for the "mode" attribute

In GNU modes, the front end now accepts new arguments for the "mode" attribute:
unwind_word, libgcc_cmp_return, and libgcc_shift_count.


2/24/12  [EDGcpfe/12724]
Assertion failures during mangling of __typeof__ or decltype

In configurations that record prototype instantiations in the IL and
have MANGLE_ALL_NAMES set to TRUE, the mangling of a __typeof__ or
decltype expression that contains an unknown template parameter
had caused an assertion failure in mangled_encoding_for_type.
This is now fixed.  For example (with --g++ --c++11):
[Patch sent out 5/17/12 as part of 4.4.1.]

  struct A {
    typedef int type;
  };
  template<class T> A g(T&);
  template<class T> struct B {};
  template<class T> void f(T t) {
    typedef __typeof__(g(t)) X;
    typedef decltype(g(t)) Y;
    struct C {
      B<typename X::type> m1;
      B<typename Y::type> m2;
    };
  }
  void h() {
    f(0);
  }


2/23/12  [EDGcpfe/12195,EDGcpfe/12373]
C++/CLI: Default indexed properties from metadata

In C++/CLI mode, the front end previously did not correctly load default
indexed properties from metadata (they were usually loaded as named indexed
properties with the name "Item").  This is now fixed.


2/23/12  [EDGcpfe/12704]
Incorrect matching of qualification conversion in deduction

In template argument deduction, in cases where a qualification conversion
is required, the front end failed in certain cases where the underlying
template parameter should have been deduced as const (e.g., "const int"
in the example below).  Formerly the template parameter was deduced without
the const, causing the function to not match in overload resolution.
Now fixed.  See the 2/9/12 entry for a similar issue concerning array
types.

  template <class T> void f(T *const *const *);
  void g(const int ***a) { f(a); }  // Formerly, failed to match.

  template <class T, int i> void g(T (*const *const *)[i]);
  void g(const int (***a)[1]) { g(a); }  // Formerly, failed to match.


2/22/12  [EDGcpfe/12292]
C++/CLI: Interface names found when used as direct interfaces

In C++/CLI when a lookup begins in a ref class, the lookup does not search
interfaces.  The Microsoft compiler does, however, notice that a name
matches the name of a direct interface and uses that type when the name
is followed by a "::".   We now emulate this in C++/CLI mode.

  public interface struct I {
    interface struct IN {
      void f();
    };
  };
  ref struct R: I::IN {
    virtual void g() = IN::f;
  };


2/22/12  [EDGcpfe/4622,EDGcpfe/4781,EDGcpfe/10127,EDGcpfe/12722]
GNU compatibility: #pragma GCC system_header

The front end now accepts the GNU-specific pragma #pragma GCC system_header
in GNU modes.  It causes the remainder of the header file in which it appears
to be treated as if it occurred in a system header.  A warning is issued if
this directive appears in the primary source file.


2/22/12  [EDGcpfe/11204]
GNU C++: + and - allowed on void * operand after 4.4

g++ mode now allows addition and subtraction of a void * and an integer
when gnu_version >= 40400.  Likewise for a pointer to function.

  int main() {
    void *p = 0;
    p + 1;
    p - 1;
    void (*pf)() = 0;
    pf + 1;
    pf - 1;
  }


2/22/12  [EDGcpfe/12581]
Missing error on conflicting using-declaration

The change for EDGcpfe/12429 (see Changes entry of 11/17/11) introduced a
regression in version 4.4 of the front end: In GNU C++ mode, it caused a
function declaration that conflicts with a using-declaration not to be
diagnosed even if the function was not extern "C".  This bug was also present
in Microsoft mode (but predated version 4.4).  For example:

  namespace N { void f(); }
  using N::f;
  void f();  // Previously failed to trigger an error in GNU and Microsoft
             // C++ modes.

This is now fixed.


2/22/12  [EDGcpfe/12706]
dynamic_cast causes instantiation of virtual functions with C++-generating BE

The front end configured for the C++-generating back end has tended to
instantiate all virtual functions of a class that's used in a dynamic_cast,
in order to ensure that the typeinfo variable for the class is generated.
This was sometimes too much, and provoked errors that other compilers
do not detect.  In contrast, in configurations with IL lowering, the front
end understands the virtual function and vtable generation rules and 
can instantiate exactly what is necessary, and no more.  Now, in
non-IL-lowering configurations, fewer instantiations are forced for a
typeinfo use, i.e., we err on the cautious side instead of instantiating
everything that might be needed.

  template <typename T> struct A {
    T *m_ptr;
    ~A () {
      m_ptr->Unref();  // Got an error when instantiated for A<X>
                       // Now, A<X>::~X is no longer instantiated
    }
  };
  struct B {
    virtual ~B ();
  };
  struct X;
  struct D : B {
    A<X> a;
  };
  void f(B *b) {
    dynamic_cast<D*> (b);
  }

[6/6/12, EDGcpfe/12951] These changes were reworked and integrated with
the changes for EDGcpfe/12919.


2/22/12  [EDGcpfe/12626]
Abort on "explicit" specifier after error

In modes that permit explicit conversion functions (see Changes entry of
4/19/11), the front end sometimes aborted in special_functions_kind_for_symbol
(symbol_tbl.c) after certain severe errors.  For example, in C++11 mode:

  struct N {
    template<class T> struct X;
    inline explicit X();  // Not a valid declaration.  Previously aborted in
  };                      // some modes.

This is now fixed.


2/21/12  [EDGcpfe/12709]
Spurious error on use of template with __underlying_type construct

When a template signature relied on the use of a typedef based on
__underlying_type (e.g., in a return type), the front end sometimes spuriously
failed argument deduction of that template.  For example:

  template<typename T> struct U { typedef __underlying_type(T) R; };
  template<typename T> typename U<T>::R f(T);
  enum E { e };
  auto x = f(e);  // Previously failed deduction, causing no matching f
                  // to be found (i.e., an error).

This is now fixed.  (The entry of 7/5/11 describes the introduction of the
C++11 type traits helper __underlying_type, among other such helpers.)


2/21/12  [EDGcpfe/12662]
Improved diagnostic for missing preinclude file

If multiple preinclude files were specified on the command-line and
one of the files other than the first could not be opened, the position
of the end of the previous preinclude file was used in the "cannot open
source file" diagnostic, which could be confusing.  The diagnostic is
now issued as command-line error with no associated position.


2/21/12  [EDGcpfe/12716]
Microsoft compatibility: __uuidof different types with same UUID value as
template argument

If a template was instantiated using the __uuidof operator on two different
types with that have the same UUID value they were not always treated as
the same instantiation.  This could result in a variety of problems in
programs that expect the instantiations to have the same type.  In
versions with EXPENSIVE_CHECKING enabled, it would also result in an
assertion failure in check_new_class_instantiation.  Now fixed.

  typedef struct _GUID { int i; } IID;
  template <const IID* piid> class I;
  struct __declspec(uuid("{DDB47A6A-0F23-11D5-9109-00E0296B75D3}")) A {};
  struct __declspec(uuid("{DDB47A6A-0F23-11D5-9109-00E0296B75D3}")) B {};
  template <> class I<&__uuidof(A)> {};
  I<&__uuidof(A)> i1;
  I<&__uuidof(B)> i2;  // spurious "incomplete type is not allowed"


2/21/12  [EDGcpfe/12712]
C++/CLI: Diagnose nonstatic data members in interface class types

The front end now issues an error on declarations of nonstatic data members in
interface class types.

  interface struct S {
    int i;  // Now an error (previously erroneously accepted).
  };


2/21/12  [EDGcpfe/12718]
Use of unset variables in hidden name processing

In configurations with RECORD_HIDDEN_NAMES_IN_IL, there could be
references to unset variables in check_hiding_by_inherited_names.
This could result in certain names being considered hidden when they
actually were not.  Now fixed.


2/21/12  [EDGcpfe/12717]
Add label fill-in capability to error message strings

A "label fill-in" facility has been added which allows error message strings
to choose at run-time between two different substitution strings.  These
label fill-ins use the %[label] syntax in the error_msg.txt file and the
string in brackets (the label) is looked up in the label_fill_ins table
to determine which of two error strings should be used to replace the
label fill-in (based upon the value of a label-specific boolean variable).
This is useful to tailor error messages for multiple environments without
having to duplicate error messages.  See label_fill_ins in error.c for more
specifics.


2/21/12  [EDGcpfe/12230]
C++/CLI: handling of operator-> starting from a handle

In C++/CLI, the handling of operator-> functions has a bit of an ambiguity,
because something like h->f(), with "h" a handle, could be a reference to
a member of the class of h directly, or a use of an operator-> function
in that class, which could return a handle to a different class.  MSVC
favors the operator-> interpretation (as we have), but only when there
is an operator-> (or a chain of them) that returns a handle or a pointer
to class.  We now do that part as well.

  ref struct B {
    int foo();
  };
  ref struct R : B {
    B% operator ->();
  };
  R ^f();
  int main() {
    int i = f()->foo();  // Now accepted, because the operator-> is not
                         // used as it does not produce a handle or pointer,
                         // so this is just a reference to a member foo of R
                         // inherited from B.
  }


2/21/12  [EDGcpfe/11404]
C++/CLI: Remark on operator* in managed class type

Declaring a nonstatic unary operator* in a managed class type now triggers a
remark (because such operators can change the meaning of "*h" where h is a
handle).  For example:

  ref struct S {
    int operator*();  // Now triggers a remark.
  };
  int f(S ^h) {
    return *h;  // Calls S::operator*.
  }


2/20/12  [EDGcpfe/12535]
Microsoft compatibility: spurious ambiguity on function called via __super

The front end issued a spurious ambiguity when using the Microsoft mode
__super keyword in cases where a function from a direct base class should
be preferred over one from an indirect base class.  Now fixed.

  struct I {
    int f();
  };
  class B : public I {};
  struct A : public I {
    int f() { return 0; }
  };
  struct C : public A, public B {
    int f() {
      return __super::f(); // formerly ambiguous
    }
  };


2/20/12  [EDGcpfe/12684]
C++-generating back end, C++/CLI: initialization of dependent gcnew array

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL, the C++-generating
back end could abort with an assertion failure when gcnew of a dependent
type has a brace-enclosed initializer.  This is now fixed.  For example:

  template<typename T> void f() {
    gcnew T(4){ 1, 2, 3, 4 };
  }


2/20/12  [EDGcpfe/12712]
C++/CLI: Diagnose all attempts to define an abstract managed member function

The front end previously often accepted definitions of abstract managed member
functions.  For example:

  interface struct S {
    void f() {}  // Previously accepted; now an error.
  };

This is now fixed.  A different message is used for interface members (since
they are always implicitly abstract).


2/20/12  [EDGcpfe/12275]
C++/CLI: Elaborated class specifiers in CLI typeid constructs

In C++/CLI mode, the front end now accepts an elaborated class specifier in
a T::typeid construct.  For example:

  ref struct RS {};
  System::Type^ g() {
    return ref struct RS::typeid;  // Now accepted in C++/CLI mode.
  }

This extension is not part of the ECMA-372 specification, but Microsoft
compilers permit it.


2/20/12  [EDGcpfe/12700]
Spurious error on GNU-C-mode old-style definition after prototyped declaration

In GNU C mode, defining a function with an old-style parameter list after that
function is declared with a prototyped declaration that includes a calling
convention attribute could result in a spurious error in version 4.4 of the
front end.  For example:

  extern void f(_Bool x) __attribute__((stdcall));
  void f(x) _Bool x; {}  // Spurious error in version 4.4 GNU C mode.

This was a regression introduced by the changes for EDGcpfe/11928 (entry of
7/15/11).  It is now fixed.


2/20/12  [EDGcpfe/12489]
Improved diagnostics in C++/CLI when some overload set members are inaccessible

In C++/CLI, inaccessible functions from managed classes are discarded in
overload resolution, rather than (as in standard C++) being considered
as viable functions and an error issued if they are chosen.  This led to
some confusing error messages when no accessible function is viable but
there is an inaccessible function that could have been called were it
not for the C++/CLI access rules.  Now, an additional note is appended
to the diagnostic to identify an inaccessible function that could have
been chosen (only one is identified, and not necessarily the best one,
but it is one that is callable).

  ref struct A {
  public:
    A();
  private:
    int operator+(int);
  };
  int main() {
    A ^h = gcnew A();
    h + 1;
  }

This now produces:

"test.c", line 9: error: no operator "+" matches these operands
            operand types are: A ^ + int
            Note: function "A::operator+" (declared at line 5) could have been
                      called but was not considered because it is inaccessible
    h + 1;
      ^


2/17/12  [EDGcpfe/12197]
C++/CLI: Attributes on generic delegates

Instantiating a generic delegate with square-bracket attributes in C++/CLI
mode previously resulted in an internal error in scan_cli_delegate_definition
(class_decl.c).  For example:

  generic<class T> [Any(2)] delegate void F(T);
  void g(F<int> ^h) {
    h(2);  // Previously triggered an internal error.
  }

This is now fixed.


2/17/12  [EDGcpfe/12699]
IL representation of #pragma GCC visibility ...

In GNU C and C++ modes with gnu_version >= 40200, the front end supports the
"#pragma GCC visibility" constructs when GNU_VISIBILITY_ATTRIBUTE_ALLOWED is
TRUE (see Changes entry of 4/17/08).  However, while the effects of the pragma
were recorded in the IL, the pragma itself was not.  A consequence of this was
that the C++-generating back end did not render these pragmas.  This is now
fixed.  More generally, any "#pragma GCC ..." construct is now recorded in
text form (used by the C++-generating back end), and additional details are
now recorded in a more structured form if the pragma is fully recognized.


2/17/12  [EDGcpfe/12603]
Microsoft-mode abort on invalid local declaration in class template context

When parsing nonclass templates in Microsoft mode, a local declaration of a
qualified name in a member of a class with dependent base classes could result
in an internal error in make_local_static_variable_init (il.c).  For example:

  template<typename T> struct S: T {
    void f(T t) {
      { 
        int U::m(t); // Previously triggered an abort in some Microsoft modes.
      }
    }
  };

The diagnostic in cases like these has also been improved (previously, the
diagnostic suggested a duplicate definition; now it indicates an invalid scope
for a member definition).


2/17/12  [EDGcpfe/12618]
C++/CLI: Internal error when managed template derives from non-managed class

An internal error could occur (in create_nonreal_progenitor_symbol) if a
managed class template (but not generic) derived from both a managed type
that depends on a template parameter and a non-managed dependent base
class (note that this is not allowed, so an error would have already been
issued), and the managed type was the first dependent base.  Now fixed.

  generic <typename T> interface class I { };
  template <class T> struct Base { };
  template<typename T> ref class C : public I<T>, public Base<T> { };


2/17/12  [EDGcpfe/12573]
C++/CLI: Do not inherit certain properties from naked type constraints

When a naked type parameter constraint is used, the ref class and value
class constraints were inherited, but should not have been.  Now fixed.

  generic <typename T> where T: ref class ref class A {};
  generic <typename T, typename U> where T: ref class where U: T ref class B {
    A<T> at;
    A<U> au;  // now gets constraint error
  };


2/16/12  [EDGcpfe/11721]
C++/CLI: Uninitialized initonly static data members and static constructors

Previously, in C++/CLI mode, the front end did not report uninitialized
initonly static data members of a class that also declares a static
constructor (because the static constructor might initialize the member).
Now, an error is issued if the static constructor is defined and it does not
appear to modify an otherwise uninitialized initonly static data member.
For example:

  ref struct S {
    static S() {}
    initonly static int sm;  // Uninitialized initonly static data member
  };                         // is now diagnosed with an error.


2/16/12  [EDGcpfe/12685]
C++-generating back end: omitted qualification in friend declaration

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end sometimes put out the name of a friend class or
friend function without the necessary qualifier.  This occurred in two
specific situations.  The first case involves a friend declaration naming
an instance of a template that is hidden in the scope containing the
friend declaration:

  namespace N {
    template <typename T> class A {};
    class B {
      typedef N::A<B> A;     // Hides N::A
      friend class N::A<B>;  // Previously generated as A<B>
    };
  }

The second case occurs when a friend declaration in a class nested in a
class template names a member function of the class template:

  template<typename T> struct O {
    void f() const;
    struct I {
      friend void O::f() const;  // Previously generated without "O::"
    };
  };

These are now fixed.


2/16/12  [EDGcpfe/12574]
C++/CLI: Using-declarations and access declarations in managed classes

Using-declarations and access declarations appearing in managed class
definitions now result in an error.  For example:

  ref struct B { void f(); };
  ref struct D: B {
    using B::f;  // Now an error.
  };


2/15/12  [EDGcpfe/12237,EDGcpfe/12578]
Microsoft compatibility: Scope of out-of-class member enumerator constants

In Microsoft mode, the front end accepts out-of-class definitions of member
enum types (see Changes entry of 11/30/04).  Previously, however, the
enumerator constants were not visible in the class scope; now, they are.
For example:

  struct S { enum E; };
  enum S::E { e1, e2 };
  S::E x = S::e1;  // Previously an error.  Now accepted.


2/15/12  [EDGcpfe/12681]
C++-generating back end: incorrect qualification on condition name

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end sometimes incorrectly added a global qualifier "::"
when referring to the name of a variable declared in a condition appearing
in a member function of a class with a dependent base class.  This is now
fixed.  For example:

  void g(int);
  template <class T> struct B {};
  template <typename T> struct C : B<T> {
    void f() {
      if (const int x = 0) {
        g(x);   // Previously generated as g(::x)
      }
    }
  };


2/15/12  [EDGcpfe/12403]
Improved error recovery on some malformed C++/CLI declarations

When an identifier that can be a C++/CLI context-sensitive specifier keyword
(like "property" or "event") is not followed by a valid type specifier, the
front end previously always assumed that the identifier should not be treated
as a keyword.  To improve error recovery, the assumption is now made the other
way in some clear error cases.  For example:

  ref class S {
    property bad_id p1 {  // Undeclared "bad_id" previously resulted in a
      bad_id get();       // syntax error that caused the declaration of p2
    }                     // below to be skipped.  Now parsing proceeds with
                          // an ordinary error (no tokens are dropped).
    property int p2 {
      int get();
    }
  };


2/15/12  [EDGcpfe/11474]
GNU C++ compatibility: use of injected class template name in derived class

g++ did not allow the use of an inherited injected class name of a class
template to be used with a template argument list in a derived class.
This has been fixed in g++ 4.5.  Our emulation of this g++ behavior is now
conditional on gnu_version and is only done when gnu_version < 40500.

  namespace N {
    template <class T> class A { };
  }
  class B : N::A<int> {
    A<char> x;  // now accepted in g++ mode when gnu_version > 40400
  };
  

2/15/12  [EDGcpfe/12617]
Rendering of function declarations with trailing embedded type definitions

The C++-generating back end previously could not correctly render a function
declaration that included a trailing array or function declarator (part of the
return type) with an embedded type definition (permitted in GNU C mode).
For example:

  int (*f())[sizeof(struct { int x: 1; })];
     // Previously, the C++-generating incorrectly generated the embedded
     // struct definition.

This is now fixed.  The fix required an IL CHANGE (a new end-of-construct
marker is appended after the source sequence entries describing declarations
embedded after the entry for the function itself).


2/15/12  [EDGcpfe/12343]
Microsoft compatibility: incorrect handling of "." with --parse_templates

In Microsoft bugs mode a "." is sometimes allowed in place of "::" in
qualified names.  If --parse_templates is used with microsoft_version <= 1400
a "." was incorrectly treated as a "::" when scanning a qualified name
in which the qualifier was a dependent type.  This resulted in incorrect
IL for the prototype instantiation of the function and could result
in incorrect output from the C++-generating back end.  Now fixed.

  struct A {
    void f();
  };
  template<class T> struct B {
    A a;
  };
  template<class T> struct C : B<T> {
    C() {
      B<T>::a.f();  // incorrectly emitted as B<T>::a::f
    }
  };
  C<int> c;


2/15/12  [EDGcpfe/12663]
GNU C++ compatibility: access checking in SFINAE contexts

Version 4.4 introduced a change to perform access checking in C++11
SFINAE processing (see 12/15/11 entry).  This processing was not intended
to be done in g++ mode, but certain parts of the access checking were
inadvertently enabled in g++ mode even when new style SFINAE was not
enabled.  This caused the example below to call the f(...) function
instead of issuing an access error when gnu_version < 30400.  Now fixed.
[Patch sent out 5/17/12 as part of 4.4.1.]

  template <typename A> class S {
    class T {};
  };
  template <typename A> typename A::T* f (A) { return 0; }
  void f(...);
  int main() {
    f(S<int>());
  }


2/14/12  [EDGcpfe/12118]
GNU C++ compatibility: extra template parameter list on partial specialization

We previously made a change to issue a discretionary error (instead of
an error) on an extra template parameter list on a partial specialization
in g++ mode (see 2/23/09 entry).  This appears to be used in some common
code bases, so we have further reduced the default severity for this
diagnostic to a warning in g++ mode.

  template <class T> struct A {};
  template <> template <class T> struct A<T*> { };


2/14/12  [EDGcpfe/12641]
C++-generating back end, GNU compatibility: member functions of class
templates used as nontype template arguments

The g++ compiler has a bug that reports spurious errors if the unqualified
name of a member function of a class template is used as a nontype template
argument within the scope of the class template.  In configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the C++-generating back end
triggered this bug by qualifying such member function names only when they
were hidden at the point of reference.  It has now been changed to use a
qualified name in such contexts if gcc_is_generated_code_target is TRUE.
For example:

  template<void (*)()> struct A { };
  template<typename T> struct B {
    static void f();
    A<B::f> af;   // Previously generated as A< f>, now as A< ::B< T> ::f>
  };
  B<int> bi;


2/13/12  [EDGcpfe/12673]
Performance of cases with many friend class templates

Very large translation units containing very large numbers of friend class
template declarations could result in unusually slow compilation performance.
This is now fixed.


2/13/12  [EDGcpfe/12669]
GNU compatibility: Severity of malformed #pragma pack directive

In GNU mode, when a #pragma pack directive starts with "#pragma pack (n" not
followed by a right parenthesis, the front end now only issues a warning
(previously it was an error), and the pack alignment is ignored (previously
it took effect during error recovery).  For example:

  #pragma pack(2, 2)  // Previously an error; now a warning.  No packing
                      // takes effect here.


2/13/12  [EDGcpfe/12674]
C++/CLI: Inconsistent elaborated names for managed classes from metadata

When referring to a managed class type imported from metadata in C++/CLI mode,
the front end now accepts an elaborated name of the form "class X" or
"struct X" (previously, a name like "ref struct X" or "value class X" was
required).  For example:

  void f(class System::ValueType ^h);  // Now Accepted in C++/CLI mode.
                                       // (Previously an error.)


2/13/12  [EDGcpfe/12511]
Microsoft compatibility: abort when using Hong Kong Unicode locale

Windows versions with NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE set to
TRUE would abort (in host_envir_early_init) if the system language for
Unicode conversion was set to "Chinese (Traditional, Hong Kong S.A.R.)".
This resulted from a defect in the Windows runtime where the value
returned by the GetLocaleInfo function was not valid as an input to the
_create_locale function.  We have now modified the code that constructs the
system default locale to avoid this issue.


2/10/12  [EDGcpfe/11655]
Mangling of call operations where ADL is suppressed

An additional mangling encoding has been added to distinguish between
cases where a call operation uses argument-dependent lookup and cases
where argument-dependent lookup is explicitly disabled (by the use of
parentheses).  In both IA-64 and Cfront ABIs, the new "cp" encoding is
used (in place of the typical "cl" encoding for a call operation).
For example:

  namespace N {
    struct A {};
    template <class T> T foo(T t);
  }
  template <class T> T foo(T t);
  template <class T> auto f(T t) -> decltype((foo)(t));
  int main() {
    f(N::A()); // IA-64:  _Z1fIN1N1AEEDTcp3foofp_EET_
               // Cfront: f__tm__8_Q2_1N1A__FZ1Z_YOcp_2_3fooI1IO
  }


2/9/12   [EDGcpfe/12686]
Incorrect matching of qualification conversion in deduction

In template argument deduction, a qualification conversion was incorrectly
allowed from a const array type to a parameter type such as "const T **".
This caused deduction to succeed in some cases where it should fail.  This
rendered the example below ambiguous.  Now fixed.  The Microsoft compiler
also allowed such a conversion, so we continue to do so in Microsoft
mode.  [Patch sent out 5/17/12 as part of 4.4.1.]

  template <class T> void f(T**, T **); // #1
  template <class T> void f(T**, const T **); // #2
  void f(const int (**a)[1]) {
    f(a, a);  // call #1, deduction fails for #2
  }


2/8/12   [EDGcpfe/12661]
C++/CLI: abort on dependent property when templates are parsed

In C++/CLI mode with parsing of templates (e.g., --cppcli --parse_templates),
a reference to a dependent property caused an abort in overload.c
in select_overloaded_function.  Now fixed.

  template <typename T> ref class Foo {
    typedef T PropertyType;
    property PropertyType m_prop;
    Foo(PropertyType^ p) {
      m_prop = p;
    }
  };


2/6/12   [EDGcpfe/12668]
C++/CLI: addition of type qualifiers after boxing as tiebreaker

In C++/CLI mode, addition of cv-qualifiers under a handle after a boxing
conversion now counts as a tiebreaker in overload resolution.

  void f(int^ i) {}
  void f(const int^ i) {}
  int main() {
    f(1);  // Was ambiguous, now selects f(int ^)
  }


2/2/12   [EDGcpfe/11926]
One initialization routine for each file-scope dynamic initialization

A new configuration macro, SEPARATE_ROUTINES_FOR_FILE_SCOPE_DYNAMIC_INITS,
has been added to force lowering to create a separate initialization routine
for each file-scope dynamic initialization (when the macro is TRUE).  When the
macro is FALSE, file-scope dynamic initializations continue to be grouped
together in a single routine for the translation unit, or a single routine for
each "needed" bit in one-instantiation-per-object mode, or a single routine for
each GNU init_priority.  When the new macro is TRUE, a new field,
file_scope_dynamic_init_routines, has been added to the il_header and it
contains a list of the file-scope initialization routines in the order they are
to be executed.  It is the responsibility of the back end to ensure that the
routines on this list are executed in the proper order.  This configuration
option may be useful when a back end has determined that certain file-scope
variables or static data members are unneeded and gives such back ends an easy
way to remove the unneeded initialization.  Most back ends will use the
default value of this macro (FALSE) and will require no changes.


2/1/12   [EDGcpfe/12635]
Template specialization matching and calling conventions

The changes for EDGcpfe/11928 (see Changes entry of 7/15/11) inadvertently
introduced a regression when matching template specialization declarations
with templates if the template specified a Microsoft-style calling convention
(like stdcall or cdecl) in GNU C++ mode.  For example:

  template<typename T> void __attribute((stdcall)) f();
  template<> void __attribute((stdcall)) f();  // Spurious error suggesting
                                               // no matching template exists.

This is now fixed by ignoring the calling convention when matching the
template.  That means that the following variation is now also accepted:

  template<typename T> void __attribute((stdcall)) f();
  template<> void __attribute((cdecl)) f();  // Now accepted.

which matches the behavior of GNU compilers (and that of Microsoft compilers
when the corresponding Microsoft syntax is used).  (See also the changes for
EDGcpfe/12593 of 1/19/12.)


2/1/12   [EDGcpfe/12575]
C++/CLI: discarded dereference of handle not allowed

MSVC in C++/CLI mode does not allow a dereference of a handle to a ref
or interface class to be discarded.  That is, if such an expression
appears at the top level of a statement, or as the first operand in
a comma expression, an error is issued.  The front end now does the
same.  The error can be avoided by adding an explicit cast to void.

  using namespace System;
  int main() {
    *(String^)"abc";  // Error
    (*(String^)"abc", 1);  // Error
    (void)*(String^)"abc"; // Okay
  }


2/1/12   [EDGcpfe/12656]
Abort on this.xxx in C++11 mode

The changes for allowing use of "this" in a late-specified return type
in C++11 mode (see Changes entry for EDGcpfe/11746) introduced a bug
when handling the error case this.xxx (the programmer meant to write
this->xxx instead), which caused an abort in class_qualified_id_lookup.
The abort occurred only in C++11 mode.  Now fixed.
[Patch sent out 5/17/12 as part of 4.4.1.]

  class A {
    A() {
      this.undefined; // Now gets error instead of crash with --c++11
    }
  };


1/31/12  [EDGcpfe/12643]
Tweak in Microsoft overload resolution comparison of user-defined conversions

The emulation of a Microsoft bug (see Changes entry of 9/1/00) related
to comparing two different user-defined conversions in overload resolution
has been tweaked slightly, so that it applies only when both user-defined
conversions are done via conversion functions, and not when one is done
by a conversion function and the other by a converting constructor.

  struct A {
    operator int *();
  };
  struct B {
    B(A);
  };
  void f(B);
  void f(bool);
  int main() {
    A a;
    f(a);  // Ambiguous according to the standard, and now also in Microsoft
           // mode
  }


1/31/12  [EDGcpfe/12647]
C++-generating back end, GNU compatibility: in-class definitions of class
template member functions with deferred prototype instantiation

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL and
FUNCTION_PROTOTYPE_INSTANTIATION_DEFERRAL_ALLOWED set to TRUE, a member
function defined in the source inside the definition of a class template
will not be prototype-instantiated if the function is not used and thus
will have no definition in the code generated by the C++-generating back
end.  This is an inherent limitation of function prototype instantiation
deferral.  The C++-generating back end did mark such member functions as
inline, however, to indicate that there would be no out-of-line definition
elsewhere in the program.  Versions of g++, however, prior to 4.4 issue
spurious errors when performing an explicit instantiation of a class
template containing inline member functions with no definitions.  This
problem is exacerbated if the generated code is compiled with the
-finline-functions g++ command-line option, which causes additional
instantiations that are not known to the front end when processing the
source code.  To address this issue, when gcc_is_generated_code_target is
TRUE and with gnu_target_version_number < 40400, the output of the
C++-generating back end now suppresses the "inline" keyword in the
declaration of such member functions.


1/31/12  [EDGcpfe/12636]
Overload resolution tiebreaker nit with reference to pointer

A change made in version 4.4 exposed a minor problem in overload resolution
in comparing cv-qualifiers added on a pointer under a reference to const.
For example, in this case the front end failed to consider the "const"
added on the pointer conversion under the reference, and therefore
incorrectly saw both functions as being equally good:
[Patch sent out 5/17/12 as part of 4.4.1.]

  int f(char *);
  void f(const char * const &);
  int main() {
    char *p = 0;
    int i = f(p);  // Was incorrectly ambiguous in 4.4, now accepted again
  }

2/21/12:  Some additional changes in this area for EDGcpfe/12714.
An example for this part:

  typedef void* void_ptr;
  typedef const void* const_void_ptr;
  void node_ptr_cast(const void_ptr &p);
  void node_ptr_cast(const const_void_ptr &p);
  int main() {
    void* vp = 0;
    node_ptr_cast(vp);  // Was incorrectly ambiguous in 4.4, accepted again
  }


1/31/12  [EDGcpfe/12633]
GNU __extension__ keyword and typedef declarations

The C++-generating back end erroneously replicated the GNU __extension__
keyword when it appeared on a typedef declaration with multiple declarators.
For example:

  __extension__ typedef struct S {} s, *ps;

was rendered as (ignoring formatting):

  __extension__ typedef struct S {} s, __extension__ *ps;

This is now fixed.


1/31/12  [EDGcpfe/12653]
C++-generating back end: omitted parentheses in nontype template default
argument

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end failed to parenthesize the expression in a nontype
template default argument when it contains an unparenthesized > operator,
resulting in the > operator being interpreted as the end of the template
parameter list.  This is now fixed.  For example:

  template<typename T> struct P;
  template<typename T, bool B = (P<T>::m > 0)>  // Previously omitted parens
  struct S;


1/31/12  [EDGcpfe/12652]
C++-generating back end: missing function parameter pack expansions

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end sometimes failed to add an ellipsis indicating a
function parameter pack expansion in an expression.  This is now fixed.
For example:

  template<typename ...Ts> struct A { };
  template<typename ...Ts> A<Ts&...> f(Ts& ...ts) {
    return A<Ts&...>(ts...);   // Previously missing second "..."
  }


1/30/12  [EDGcpfe/12646]
C++-generating back end, GNU compatibility: unnecessary "template" keywords
in qualified friend function names

The change for EDGcpfe/12600 failed to address the case when the name in
a friend function declaration is a member of a nested class template of a
class template: the generated qualified name could still have an unneeded
"template" keyword, which caused an error when g++ compiled the generated
code.  This is now fixed.  For example:

  template<typename T> struct A {
    template<typename U> struct B {
      void f();
    };
  };
  struct S {
    template<typename T> template<typename U>
    friend void A<T>::B<U>::f();  // Previously generated as
                                  // A<T>::template B<U>::f()
  };


1/30/12  [EDGcpfe/12624]
GNU C compatibility: Incompatible block-extern and implicit declarations

When emulating a GNU C versions other than 3.4.x, the front end allows an
implicit declaration of a function to be followed by an incompatible explicit
declaration of that function.  GCC 3.4 does not permit this in general, but
for certain functions that the compiler knows about, a similar effect occurs.
For example:

  #include <stddef.h>
  void g() {
    int x;
    bzero((char*)&x, sizeof(x));     // Implicit declaration of bzero.
  }
  extern void bzero(void*, size_t);  // Accepted by GCC 3.4 (and other
                                     // versions too).  Previously an error
                                     // with the EDG front end because the
                                     // "void" return type does not match the
                                     // "int" return type of the implicit
                                     // declaration.

The front end now approximates this by accepting the second declaration in
such examples if a corresponding __builtin_... function was predeclared (a
warning is issued).  It is an approximation because (a) certain functions X
for which GCC 3.4 has a __builtin_X do not permit such redeclarations (e.g.,
"prefetch"), and (b) the functions X that GCC 3.4 does accept here appear to
be predeclared by GCC in some way (without the "__builtin_" prefix).


1/29/12  [EDGcpfe/12600]
C++-generating back end, GNU compatibility: unnecessary "template" keywords
in qualified names

The C++ Standard allows use of the "template" keyword in qualified names in
contexts in which it is not actually necessary, and in configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE the output of the C++-generating
back end took advantage of this liberty by putting out the keyword in
qualifiers that name dependent template instances, regardless of whether it
is strictly needed or not.  The g++ compiler, however, issues an error when
the qualifier for an entity being declared contains the "template" keyword.
The C++-generating back end has now been changed not to emit the "template"
keyword in such qualifiers.  For example:

  template<typename T> struct A {
    template<typename U> struct B {
      static int m;
    };
  };
  template<typename T> template<typename U>
  int A<T>::B<U>::m;  // Previously generated as A<T>::template B<U>::m


1/29/12  [EDGcpfe/12074]
Backing expressions for named constants

Constants that are the result of folding constant expressions
have (in some configurations) "backing expressions," which give the
expression that produced the constant.  The backing expressions
for named constants, e.g., enumerators and nonstandard member
constants, were missing when the expression underlying the named
constant was itself simply the value of another named constant.
Now fixed.  For example:

  struct A {
    const int c = 7;
    enum E {
      e0 = 7,  // No backing expression needed
      e1 = c,  // Backing expression was missing, now provided
      e2 = c+1 // Backing expression was already correct (not simple name)
    };
  };

In versions with IL lowering and RECORD_BACKING_EXPRS_WITH_IL_LOWERING
set to TRUE, the backing expressions for expressions tested as boolean
controlling expressions were sometimes incorrect, in that two constants
could be produced that pointed to the same backing expression.  Now fixed.

  struct A {
    const bool b = 1 > 0;
    void f() {
      if (b) {}  // Constant tested pointed to same "1 > 0" expression as above
    }
  } a;


1/27/12  [EDGcpfe/12601]
C++-generating back end: missing "template" keyword in g++ mode

In g++ mode when gnu_version >= 30400, a "template" keyword used for
syntactic disambiguation in a dependent template argument list was sometimes
not emitted in the code produced by the C++-generating back end.  Now fixed.

  struct A { template< class T> class B { }; };
  template <template <class> class TT> void f();
  template <class T> struct C {
    void g() { f<T::template B>(); } // emitted as "f<T::B>()"
  };
  int main() {
    C<A> c;
    c.g();
  }


1/26/12  [EDGcpfe/12602]
C++-generating back end: abort on use of template template parameter parameter

The change for EDGcpfe/12534 introduced a bug that caused an assertion
failure in the C++-generating back end in configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE when a parameter appearing in
a template template parameter's parameter list is used in a subsequent
template parameter of the template template parameter.  This is now fixed.
For example:  [Patch sent out 5/17/12 as part of 4.4.1.]

  template<template<typename U, U* p> class T>  // Previously aborted
  struct X { };                                 // putting out "U*"


1/25/12  [EDGcpfe/12605]
C++-generating back end: omitted template parameter pack expansion

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end sometimes omitted the ellipsis expanding a
template parameter pack in the declaration of a function parameter.
This has now been fixed.  For example:

  template<typename T> struct A;
  template<typename T> struct B {
    typedef typename A<T>::type X;
    template<typename... Args>
    A<X (Args...)> f();  // Previously omitted "..." after Args
  };


1/25/12  [EDGcpfe/12599]
C++-generating back end: incorrect qualification of dependent function names

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end incorrectly put out the function name as a
qualified name in a dependent function call appearing in a member
function of a class template with a dependent base class.  This has
now been fixed.  For example:

  template <class T> struct B { };
  template <class T> int g(T);
  namespace N {
    template <class T> void g(T);
    template <class T> struct D : B<T> {
      void f(T t) {
        g(t);    // Previously generated as ::N::g(t)
      }
    };
  }


1/25/12  [EDGcpfe/12367]
Do not wrap keyword-like identifiers in __identifier(...) inside attributes

In Microsoft mode, identifiers that are spelled like keywords can be
enclosed in __identifier(...) to make them not be treated as keywords.
This is useful in particular for code authored in languages other than
C++, and comes up in metadata imported for C++/CLI.  Such identifiers
are again enclosed in __identifier(...) when they are output, e.g., by the
C++-generating back end.  However, the __identifier construct is not
allowed inside attributes.  Therefore, the wrapping of such identifiers
is now suppressed for output inside an attribute.


1/25/12  [EDGcpfe/12339]
Cross-reference entries for C++/CLI generic constraints

Cross-reference entries are now recorded on references in C++/CLI
generic constraint clauses.  For example:

  interface class I { };
  ref struct RR : public I { };
  generic <typename T>
  where T : I  // Cross-reference entry for reference to "I" now recorded
  void f(T t) { }


1/25/12  [EDGcpfe/12055]
References in backing expressions are keep-in-il, not needed

Constants that are the results of folding constant expressions
have (in some configurations) "backing expressions," which give the
expression that produced the constant.  Now, in the needed-flag
processing, backing expressions are walked only for the keep-in-il flag
walk, and not the "needed" flag walk.  That means that const variables
that are used only as constants will no longer be marked as "needed"
in configurations that maintain backing expressions.  This makes
the "needed" flag more closely match the "odr-used" term of the standard
in such cases.


1/23/12  [EDGcpfe/11185,EDGcpfe/12355,EDGcpfe/12606]
Spurious error on friend class declaration using name of nested template

Previously, the front end issued a spurious redeclaration error on some uses
of a nested class of a class template, when the class template contains a
member class template with the same name as a friend class declaration that
appeared in the nested class.  For example:

  template<typename T> struct S {
    struct N { friend struct F; };
    template<typename> struct F {};
  };
  S<int>::N p;  // Triggered a spurious error about "friend struct F;" being
                // and invalid redeclaration of itself.

This is now fixed.


1/13/12  [EDGcpfe/12283]
Abort on use in prototype instantiation of function inherited via using-decl

The front end aborted (on a pointer deference in add_base_class_casts)
while processing, during a prototype instantiation (i.e., in a mode that
parses templates), a reference to a member function of a base class
inherited via a using-declaration, when another base class is
dependent.  Now fixed.

  struct A {
    int f();
  };
  template <class T> struct AA { };
  template <class T> struct B : AA<T>, A {
    using A::f;
    void f(int);
    void g() {
      f();  // Caused abort with --strict
    }
  };


1/22/12  [EDGcpfe/12622]
Add --c++03 command line option

A --c++03 command line option has been added to enable parsing of C++ code
that adheres to the ISO/IEC 14882:2003 standard.  This command line option
explicitly disables all C++11 features, regardless of their configured
default values (but individual C++11 features can be enabled on the command
line).  Implicitly enables C++ mode.  Note that the related --no_c++11 command
line option (unchanged) turns off C++11 mode, but doesn't explicitly disable
all C++11 features.  Can be combined with other C++ modes, e.g., --strict,
--microsoft_version, --gnu_version (in which case, where applicable, any C++11
features enabled by the emulation mode would be enabled).


1/21/12  [EDGcpfe/12621]
Deduction on conversion function returning reference to array or function

In accordance with Core Issues 913 and 976, a template conversion function
that returns a reference to array or a reference to function now undergoes
deduction on the basis of the decayed version of the underlying type.

  int a_[2];
  template<class T> using A = T(&)[2];
  struct B_ {
    template<class T> operator A<T>() { return a_; }
  };
  int main(int argc, char *argv[]) {
    B_ b;
    int* p = b;  // Deduction now works with T = int
  }


1/19/12  [EDGcpfe/12593]
Spurious error on redeclaration with a GNU calling convention attribute

The changes for EDGcpfe/11928 (see Changes entry of 7/15/11) inadvertently
introduced a regression on function redeclarations with a "cdecl" or "stdcall"
attribute, causing a spurious error to be emitted in such cases.  For example:

  void __attribute__((stdcall)) f();
  void __attribute__((stdcall)) f() {}  // Triggered an incompatibility error
                                        // in release 4.4.

This is now fixed.  [Patch sent out 5/17/12 as part of 4.4.1.]


1/18/12  [EDGcpfe/12214]
GNU and Microsoft compatibility: Instantiated pointer-to-member functions

In GNU and Microsoft mode, instantiating a template containing a dependent
pointer-to-member-function type PMF may cause any const/volatile qualifiers in
the substituted parent class of PMF to be applied to the qualification of the
member function itself.  E.g., a substitution of "int T::f()" with T = const C
results in a type "int C::f() const".  For example:

  template<typename T, void (T::*P)()> struct X {};
  struct S {
    void f() const {}
  };
  typedef X<S const,  &S::f> XST;  // Now accepted in GNU and Microsoft
                                   // C++ modes.

In Microsoft mode, this is only done when instantiating pointer-to-member
types from token caches.  In GNU mode, however, this is also done in type
substitution (but not during deduction).  For example (with the declarations
above):

  template<typename T> void g(void (T::*p)()) {}
  int main() {
    g<S const>(&S::f);  // Accepted in GNU mode, but not in Microsoft mode.
    g(&S::f);           // Not accepted in any mode since "void (T::*p)()"
  }                     // cannot be deduced from "void (S::*)() const".


1/18/12  [EDGcpfe/12244]
Specialization should prefer matching template vs. non-template member

If a class contained both a normal member function and a member function
template that matched the type specified in an explicit specialization,
the front end was incorrectly treating it as an invalid attempt to specialize
the member instead of a valid specialization of the template.  Now fixed.
This change also affects other uses of function types, such as in friend
declarations and explicit instantiation directives.  The Microsoft and
g++ compilers prefer a non-template friend to a matching template
instance (despite the fact that the standard specifies the opposite
behavior), so we preserve the existing behavior in Microsoft and g++
modes.

  struct A {
    A(int);
    template<typename T> A(T);
  };
  template<> A::A(int i){}  // spurious "not an entity that can be specialized"


1/17/12  [EDGcpfe/12609]
GNU C++ compatibility: Undefined-but-used functions with internal linkage

In GNU C++ mode with gnu_version >= 40400, the front end now accepts (with a
warning) a function with internal linkage that is used without being defined.
For example:

    static void foo();  // Now accepted with a warning
    void bar(void) { if (0) foo(); }

Such a situation is likely to result in a linker error later on, unless a
code generator optimizes away the use of the undefined function (as it likely
could in the example above).
  

1/17/12  [EDGcpfe/10612,EDGcpfe/11770,EDGcpfe/12243]
Conversion of a no-capture lambda to a function pointer

When a lambda expression is introduced with "[]" (i.e., it doesn't capture any
local variables), its closure type now includes an implicit conversion operator
to an ordinary function pointer: A call through that pointer is equivalent to
an invocation of the lambda.  For example:

  auto c = []{ return 42; };
  int (*pf)() = c;  // Implicit conversion of closure to function pointer.
  int main() {
    pf();  // Same effect as "c();", but via an indirect call.
  }

The conversion function returns the address of a special static member function
representing an alternative entry point to the call operator of the closure.
Ordinarily, this static member (called "_FUN") is not visible to user code, but
in GNU C++ mode it is visible since that is how GCC behaves.


1/16/12  [EDGcpfe/12433]
Incorrect lookup with base class and nested class with the same name

If a class contained both a nested class of a given name and a projection
symbol to a base class member with the same name that was also a class,
an incorrect lookup result could be returned for lookups that require
that a tag or type symbol be returned.  This apparently does not occur
as often as one might expect as the problem was introduced by version
2.41 in March of 1999 and was only recently discovered.  Now fixed.

  template <class T> struct C { };
  struct B { B(int){} };
  struct A : B {
    void f(C<B>);
    struct B { B(); };
  };
  int main() {
    A::B val;
  }


1/16/12  [EDGcpfe/12105]
GNU C++ compatibility: lookup of template vs. base class member function

g++ sometimes finds a member of a dependent base class when the standard
specifies that either nothing should be found or a namespace scope symbol
should be found.  Our emulation of the g++ behavior produced an incorrect
result when a normal lookup would find a function template in a namespace
scope.  We incorrectly found the base class member.  Now fixed.  A change
made in version 4.4 fixes this (among other things) when gnu_version
is >= 40100 (see 10/11/11 entry).  This change fixes the problem 
when gnu_version < 40100.

  template<typename T> struct A {
    void f();
  };
  template<typename T> void f(T);
  template<typename T> class B: public A<T> {
    friend void f<>(T);  // formerly spurious "f is not a template"
  };
  B<int> a;


1/16/12  [EDGcpfe/12592]
Elided destructor must be accessible and not deleted

The C++ standard (in [class.temporary] paragraph 1) says that, when a
temporary is elided, any destructor that would be used to destroy the
temporary must be accessible and not deleted.  The front end now
does those checks.  In addition, g++ seems to instantiate the destructor,
so the front end now does that as well in g++ mode if the destructor
is inline.

  template<typename T> struct A {
  private:
    ~A() {}
  };
  extern template class A<char>;
  A<char> g();
  A<char> f() { return g(); } // Error now on inaccessible destructor


1/16/12  [EDGcpfe/12604]
GNU C++ mode: Tweak on instantiating statically named function in virtual call

A minor adjustment to the change made for EDGcpfe/12531: an inline
function statically named in a virtual call is instantiated in g++ mode
only if the code is evaluated.


1/15/12  [EDGcpfe/7622,EDGcpfe/11486,EDGcpfe/12215,EDGcpfe/12584]
Using-declarations that reduce access preclude access via base class

Core Issue 360 suggests that, in spite of what the access wording in
the standard says, a using-declaration that reduces the access to
a member of a base class should prevent use of that member by
consumers of the derived class.  (The standard specifies that, if a
pointer to the derived class can be cast to a base class where access
is available, the restriction of the using-declaration should be
ignored.)  This is now implemented in non-strict modes.  (Since
Core Issue 360 is still open, the standard hasn't been changed yet,
so strict modes must remain as they were.  However, MSVC and g++ use
the approach recommended by Core Issue 360, so it seems wise to
follow that in default mode, as well as in Microsoft and GNU C++ modes.)

  struct base {
    int member;
  };
  class deriv : public base {
  private:
    using base::member;
  };
  void f(deriv &d) {
    d.member = 1;  // Now an error except in strict modes
  }

In Microsoft mode, if a using-declaration imports a using-declaration
from a base class, and that imported using-declaration names one or
more functions, no error is now issued if the imported using-declaration
is not accessible.  This change was necessitated by the above change,
in order to keep existing Microsoft-mode code working.

  struct A {
  public:
    int f();
  };
  struct B : public A {
  private:
    using A::f;
  };
  struct C : public B {
  private:
    using B::f;  // Still okay in Microsoft mode even though B::f is
                 // inaccessible
  };


1/13/12  [EDGcpfe/11672]
Cast of floating-point value to scoped enumeration type

Core Issue 1094 clarified that a value of a floating-point type can
be explicitly converted to a scoped enum type.  The front end now accepts
such casts.

  enum class E { e0 };
  E e = static_cast<E>(1.0);


1/13/12  [EDGcpfe/12456]
GNU computed goto: allow const void * expression

The front end now accepts an expression of type "const void *" on a GNU
computed goto, in addition to the usual "void *" mandated by the GNU
documentation.

  int main() {
    const void *p = &&L;
  L:
    goto *p;  // Now accepted in GNU C or C++ mode
  }


1/11/12  [EDGcpfe/12590]
Invalid command line option mistakenly accepted

Command line options that don't take an argument but are given one anyway
hadn't resulted in an error and do now.  For example (had intended
--microsoft_version=1310):

  cpfe --microsoft=1310 test.c      // now results in a command-line error


1/11/12  [EDGcpfe/12115]
Microsoft compatibility: typename before nested class of class template

The Microsoft compiler allows the "typename" keyword to be used before
the declaration of a nested class of a class template (this is invalid
according to the standard because "typename" is required to be followed by
an identifier).  We accepted such usage, but during a real instantiation
of the class the nested class name was not considered to be a member of
the enclosing instantiation (it was treated in a way similar to
"friend struct N").  This resulted in spurious errors in examples
such as the one below.  Now fixed.

  template <class T> class A {
    typename struct N {
      N *x;
    };
    void f(N*);
  };
  void A<int>::f(N* p) {
    N *n = p->x;  // p was formerly considered to point to an incomplete
                  // type ::N, now correctly points to A<int>::N
  }


1/11/12  [EDGcpfe/12576]
C++/CLI: cost of conversion to Object^ after boxing

Overload resolution now considers the cost of a conversion to Object^ after
boxing as making a conversion worse than the similar conversion with
boxing and no conversion.

  void f(System::Object^);
  int f(int^);
  int main() {
    int i = f(123);  // Formerly got a spurious ambiguity error
  }


1/10/12  [EDGcpfe/12558]
Regression in handling of GNU transparent unions

The change of EDGcpfe/12450 (in version 4.4) broke cases where an
expression of a pointer type is converted to a GNU C transparent union
that contains a member having a more-qualified version of that pointer
type.  (The change of EDGcpfe/12450 disallowed dropping qualifiers,
but it also incorrectly disallowed adding qualifiers.)  Now working
again.  [Patch sent out 5/17/12 as part of 4.4.1.]

  typedef union {
    const int *x;
  } TU __attribute__ ((__transparent_union__));
  void f(TU);
  int main() {
    int *p = 0;
    f(p);  // Formerly got spurious error
  }


1/10/12  [EDGcpfe/12577]
C++/CLI for-each loop with collection of type IEnumerable<X>^

A C++/CLI for-each loop with a collection expression of type
System::Collections::Generic::IEnumerable<X>^ for some type X was not
handled correctly.  It was treated as if it had the non-generic
System::Collections::IEnumerable type.  One consequence of that
is that "auto" deduction for a case like the following deduced
a type of System::Object^ for the iterator variable (instead of
the correct "int"):

  ref class R {
  public:
    void f(int i);
    void g() {
      System::Collections::Generic::IEnumerable<int>^ e;
      for each(auto i in e) {
        f(i);  // Formerly got spurious error
      }
    }
  };


1/10/12  [EDGcpfe/12588]
Missing skip_typerefs in local_entities_should_be_promoted

A missing call to skip_typerefs in local_entities_should_be_promoted might
cause undefined behavior in some configurations (the wrong member of a union
had inadvertently been used).  This example (with --microsoft_16) had aborted
in some configurations:

  void __far f() {}


1/9/12   [EDGcpfe/12518]
Meaningless type qualifiers in template instantiations

The front end issues a warning when a const and/or volatile type qualifier has
no effect (e.g., because it is applied to a typedef for a reference type).
Now, such warnings are reduced to a remark when this occurs as part of a
template instantiation (that is not a prototype instantiation).  For example:

  template<typename T> struct A { typedef T& R; };
  template<typename T> struct S {
    typedef typename A<T>::R const R;  // Previously triggered a warning
  };                                   // during the instantiation of S<int>;
  template struct S<int>;              // now only a remark is issued.


1/9/12   [EDGcpfe/12582]
C++11: Access checking of base classes of nested classes of class templates

In C++11 mode the access to a base class name is the same as access to
a name used in the definition of the class (see 9/14/11 entry).  The checking
of nested classes of class templates was not done correctly, resulting in
spurious errors. Now fixed.

  class B { protected: class N {}; };
  template <class T> struct A {
    class D: B::N, B {};
  };
  A<int>::D ai;  // access error in the instantiation of A<int>::D


1/9/12   [EDGcpfe/12525]
GNU C++ compatibility: base class access ignored on class template

g++ (versions 3.4 and newer) allow an inaccessible class to be used as
a base class of a class template.  We now emulate this behavior in g++
mode when gnu_version >= 30400.

  class A {
    class B {};
  };
  template <typename T> class C : A::B {};
  C<int> c;


1/9/12   [EDGcpfe/12506]
C++-generating back end: missing qualifier for typedef to decltype or typeof

When a typedef to a type specified using decltype or __typeof__ was used
as a qualifier in a qualified name, the associated proxy class was not
given a name, causing the qualifier to be omitted in the output of the
C++-generating back end.  This resulted in C++-generating back end
output that would fail to compile.  Now fixed.

   template<typename T> T f(T);
   template<typename T> void g(T t) {
     typedef __typeof__(f(t)) ft;
     typedef typename ft::type x;  // formerly rendered as "typedef type x"
   }


1/8/12   [EDGcpfe/12568]
Assertion failure in complex macro expansion

The change for EDGcpfe/11932 (which was included in version 4.4) caused an
abort when processing some complex macro expansions.  This is now fixed.
For example, the front end aborted with an assertion failure when compiling
the following in Microsoft mode:  [Patch sent out 5/17/12 as part of 4.4.1.]

  #define CAT(a, b) CAT_OO((a, b))
  #define CAT_OO(par) CAT_I ## par
  #define CAT_I(a, b) CAT_II(a ## b)
  #define CAT_II(res) res

  #define X(seq) CAT(X, Y seq)
  #define ZERO(unused) 0
  #define XY ZERO(

  void f() {
    (CAT(X, Y a)));
  }


1/8/12   [EDGcpfe/12521]
Name qualifier entries reused for references to enumerators

In configurations where DEFAULT_RECORD_FORM_OF_NAME_REFERENCE is TRUE,
name qualifier entries for references to enumerators were not reused.
This used extra space and could result in a long list of name reference
entries being attached to the source correspondence entry for the
enumerator constant.  Now fixed.

  // Compile in --c++11 or --cppcli mode
  enum class E { e0 };
  void func(E f) { }
  #define X1 func(E::e0);
  #define X10 X1 X1 X1 X1 X1 X1 X1 X1 X1 X1
  #define X100 X10 X10 X10 X10 X10 X10 X10 X10 X10 X10
  #define X1000 X100 X100 X100 X100 X100 X100 X100 X100 X100 X100
  int main() {
    X1000
  }


1/7/12   [EDGcpfe/12532]
Typedefs no longer dropped from destructor names

The IL for destructor calls dropped typedefs that were used to name the
destructor.  This could result in incorrect name reference entries (e.g.,
in the example below the reference to "~B_T" was recorded as a reference
to "type" without a qualifier.  This caused the C++-generating back end
to produce incorrect output.  Now fixed.

  struct A {};
  template <class T> struct B { typedef T type; };
  template<class T> inline void f(T& t) {
    typedef typename B<T>::type B_T;
    t.~B_T();  // Was formerly rendered as "t.~type()"
  }
  int main() {
    A a;
    f(a);
  }


1/6/12   [EDGcpfe/12542]
C++-generating back end: Missing "friend" keyword for some friend templates

The C++-generating back end dropped the "friend" keyword when rendering a
friend template declaration that is also definition in a mode that defers
prototype instantiation (this requires that PROTOTYPE_INSTANTIATIONS_IN_IL and
FUNCTION_PROTOTYPE_INSTANTIATION_DEFERRAL_ALLOWED both be TRUE; see also the
Changes entry of 12/13/05).  For example:

  struct S {
    template<typename T> friend void f(T) {}  // "friend" was previously
    void g(){ f(3.0); }                       // lost by the C++-generating
  };                                          // back end when deferring
                                              // prototype instantiation.

This is now fixed.


1/6/12   [EDGcpfe/10600,EDGcpfe/10601,EDGcpfe/12030]
Remove function pointers from PCH files (an issue with ASLR)

Many recent versions of operating systems implement some form of Address
Space Layout Randomization (ASLR) where the addresses of various portions
of a process' address space vary from invocation to invocation.
This had caused problems when using pre-compiled header files because
certain front end data structures written to PCH files contained function
pointers which were no longer valid when used in subsequent invocations
of the front end.  These function pointers have now been replaced by
indices which are used to index into the new function_pointers array,
thereby eliminating the problem.  Customers who have added their own pragma
processing will need to add a new enumerator in a_function_pointer_entry_tag
and a corresponding entry in function_pointers for each function pointer that
had been passed to add_pragma_kind_description.


1/5/12   [EDGcpfe/12537]
Name for linkage purposes in unnamed member type of class template

Standard C++ allows unnamed class types to have a "name for linkage purposes"
through typedef declarations.  For example:

  typedef class {} C;  // "C" is the name for linkage purposes of the
                       // class type being defined.

This name for linkage purposes is recorded in the a_type entry for the class.
Member class or enum types of a class template have an associated "nonreal
type" entry (in addition to the ordinary type entry representing the class or
enum type), but that entry previously never acquired a name for linkage
purposes resulting from a typedef construct like the one above.  That caused
the C++-generating back end to incorrectly render certain references to the
unnamed type (in some modes and when PROTOTYPE_INSTANTIATION_IN_IL is TRUE).
For example:

  template<typename T> struct A { };
  template<typename T> struct B {
    typedef enum { e0 } E;
    typedef A<E> AE;  // "A<E>" was previously incorrectly rendered in some
  };                  // circumstances.
  B<int> bi;

This is now fixed (i.e., the associated nonreal type now also acquires the
typedef name for linkage purposes).


1/4/12   [EDGcpfe/12541]
C++-generating back end: qualified dependent friend declaration

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end failed to add the necessary qualification in a
friend declaration in which the friend is a dependent template instance
and the name of the template is hidden by declaration in a nested scope.
This is now fixed.  For example:

  namespace X {
    template <class T> class P;
    template <class T> void foo(const P<T>&);
    template <class T> struct V {
      void foo ();                        // Hides X::foo
      friend void X::foo<>(const P<T>&);  // Previously omitted "X::"
    };
  }


1/4/12   [EDGcpfe/9255,EDGcpfe/11021]
C++11 range-based "for" statement

Support for the C++11 range-based "for" statement has been added to the front
end.  Range-based "for" statements are now accepted by default in C++11 mode
as well as C++/CLI mode and Microsoft mode when microsoft_version >= 1700.
Default support for range-based "for" statements is controlled by the new
configuration macro DEFAULT_RANGE_BASED_FOR_ENABLED.  Initializer lists have
not yet been implemented in the front end, so the initializer list variation
of the range-based "for" statement is not yet available.  Range-based "for"
statements are lowered in configurations where lowering is enabled.  This is
an example of a range-based "for" statement:

  int main() {
    int sum = 0, array[5] = { 1, 2, 3, 4, 5 };
    for (int& x : array) sum += x;
    return sum;
  }


1/3/12   [EDGcpfe/12510]
C-generating back end: incomplete class as array element type

An incomplete class type can be used in C++ as the element type in an array
declaration that is not a definition (as long as the class type is complete
before the array is used in a context that requires the element size).  The
corresponding declaration is not permitted in C, however, and recent
versions of gcc enforce this restriction, leading to errors when gcc
compiled the output of the C-generating back end.  This has now been fixed
by detecting such array declarations and synthesizing a dummy definition
for the incomplete class type.  For example:

  struct S;         // Now generated as "struct S { char dummy; };"

  extern S arr[3];  // Previously an error in the generated code
  void* p = arr;


1/1/12   [EDGcpfe/12557]
Spurious warning for number of characters in a wide character literal

The change for EDGcpfe/12252,EDGcpfe/12405 below resulted in a spurious
warning "too many characters in character constant" for wide-character
literals when multibyte characters are enabled.  This is now fixed.  For
example,  [Patch sent out 5/17/12 as part of 4.4.1.]

  wchar_t c = L'x';   // Previously warned of too many characters


12/29/11 [EDGcpfe/12545]
C++-generating back end: definition of member template of class template

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end inserted an extraneous template keyword in the
out-of-class definition of a member class template of a class template.
This is now fixed.  For example:

  template <class T> struct A {
    template <class U> struct B;
  };
  template <class T> template <class U>
  struct A<T>::B { };  // Previously generated as "A<T>::template B { }"


12/28/11 [EDGcpfe/12555]
C++-generating back end: default arguments in definitions of template members

The change of EDGcpfe/12394 should have applied only to references to
actual template instances; instead, in configurations in which
PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the C++-generating back end
sometimes put out the definition of a member of a class template with an
argument list that omitted arguments for parameters with default arguments.
This is now fixed.  For example:  [Patch sent out 5/17/12 as part of 4.4.1.]

  template<typename T, typename U=int> class A {
    static int m;
  };
  template<typename T, typename U>
  int A<T, U>::m = 10;   // Previously generated as A<T>::m
  template <typename T> A<T>& f();


12/26/11 [EDGcpfe/12533]
C++-generating back end: incorrect qualification of names in classes defined
outside their containing scope

When a class is defined outside its containing scope by means of a
qualified name, names from the scope designated by the qualifier are
visible in the definition.  The C++-generating back end did not handle such
definitions correctly, with the result that names used in the class
definition were incorrectly qualified or left unqualified in the generated
code.  This is now fixed.  For example:

  template<typename T> struct A { };
  template<typename T> struct C {
    struct A;
  };
  template<typename T>
  struct C<T>::A : ::A<T> { };  // Base specifier was previously generated
                                // without the qualifier: "C<T>::A : A<T>"


12/24/11 [EDGcpfe/12546]
C++-generating back end: extraneous typename keyword in dependent destructor
call

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the
C++-generating back end sometimes inserted an extraneous typename keyword
in an explicit invocation of a dependent type destructor.  This is now
fixed.  For example:

  template <class T> struct A {
    template <class U> struct B {
    };
  };

  template <class T, class U> void f() {
    typename A<T>::template B<U> b;
    b.A<T>::template B<U>::~B();  // Previously generated as
                                  // b.typename A<T>::template B<U>::~B()
  }


12/23/11 [EDGcpfe/12508]
Tweak on Microsoft-mode overload resolution on conversion to bind reference

A tweak has been added to the code that emulates the MSVC compiler's
behavior on looking for conversion functions when the result will
be directly bound to a reference (See Changes entry of 11/2/06).
If one of the conversion functions is a template and the other
not, the processing now issues no ambiguity error, because the
non-template will be found to be better later.

 struct A { A() {} };
 struct B {
   template <typename T> operator T&();
   operator A();
 };
 int main() {
   B p;
   A a = p;  // Formerly got a spurious error
 }


12/22/11 [EDGcpfe/12531]
GNU C++ mode: statically-named inline function in virtual call is instantiated

In g++ mode, the front end now instantiates the statically-named function
in a virtual call if the function is inline.  This resolves a problem
seen in C++-generating back end versions with PROTOTYPE_INSTANTIATIONS_IN_IL
and FUNCTION_PROTOTYPE_INSTANTIATION_DEFERRAL_ALLOWED both set to TRUE
(the latter is a non-default setting).  The problem was that, if
prototype instantiations of functions are deferred until a reference,
and a reference is never recorded because the call is virtual, the
prototype instantiation of a function was not available to provide
a body in the output.  If the generated output was compiled by a version
of g++ earlier than 4.4, g++ issued an error about the lack of a definition
for the function.

  template<typename T> struct A {
    T g()         { return h(); }
    virtual T h() { return T(); }  // Formerly, definition was not put out
  };

  extern template class A<char>;

  template <class T> struct B {
    void f() {
      A<T> *ap;
      ap->g();
    }
  };

  template void B<char>::f();


12/22/11 [EDGcpfe/12534]
C++-generating back end: incorrect template parameter name

The definition of a member of a class template need not use the same
template parameter names as those appearing in the definition of the class
template.  Under some circumstances, in configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the code generated by the
C++-generating back end referred to a template parameter using the name
from the definition of the class template instead of the one from the
member definition.  This is now fixed.  For example:
[Patch sent out 5/17/12 as part of 4.4.1.]

  template<typename T> struct S {
    static T t;
  };
  template<typename U> U S<U>::t = U();  // Previously generated as T()


-------------------------------------------------------------------------------
Version 4.4, December 21, 2011

12/20/11 [EDGcpfe/12539]
Incorrect declared_type in prototype instantiation of static data member

In configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE the front
end sometimes recorded the wrong declared_type in the a_variable entry
representing a static data member of a class template.  This could result in
the C++-generating back end rendering invalid code.  For example:

  template<typename T> struct S {
    static T x[];
  };
  template<typename T> T S<T>::x[sizeof(T)];
    // Previous rendered by the C++-generating back end as
    // "template<typename T> T S<T>::x[];".

This is now fixed.


12/20/11
Default Microsoft version changed to 1600, default GNU version to 40300


12/19/11 [EDGcpfe/12529]
Missing source sequence entry for dependent friend class declaration

The front end previously failed to record a source sequence entry for a
template-dependent friend declaration declared without a qualified name
(in configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE).
For example, in strict mode (and in many GNU C++ modes):

  template <class T> class A {
    class C;
    class B {
      friend class C;  // C is "template dependent" in some modes.
    };
  };

A consequence of such cases is that the C++-generating front end failed to
render the friend class declaration.  This is now fixed.


12/19/11
IL version number changed to 4.4


12/19/11 [EDGcpfe/7537]
Unrepresentable characters in C wide character and string literals

In --strict C and C99 modes, a character (specified via a multibyte
character or a universal-character-name) in a wide character or string
literal that is too large to be represented by a single wchar_t character
was diagnosed as an error.  According to paragraphs 9 and 11 of section
6.4.4.4 of the C99 Standard, that behavior is correct for values specified
via octal or hexadecimal escapes but not for other characters, which
produce an implementation-defined value and not an error.  The front end
now issues only a warning for wchar_t characters that are too large unless
they were the result of an octal or hexadecimal escape.  For example:

  int a = L'\U00020b9f';    // Now just a warning in --strict C99
  int b = L'\x00020b9f';    // Still an error in --strict C99


12/19/11 [EDGcpfe/12252,EDGcpfe/12405]
Surrogate pairs in wchar_t and char16_t string literals

When a wchar_t or char16_t string literal contains a character (via a
multibyte encoding or universal-character-name) that cannot be represented
in a single code unit, the front end previously truncated the character to
the size of the code unit and issued a warning.  This has now been fixed
so that the result is a UTF-16 surrogate pair representing the designated
code point.  For example:

  char16_t str[] = u"\U00020b9f";   // Previously equivalent to u"\x0b9f"
                                    // Now equivalent to u"\xd842\xdf9f"


12/16/11 [EDGcpfe/12066,EDGcpfe/9971]
universal-character-names in narrow string literals

The change for EDGcpfe/11914 resulted in universal-character-names in
narrow string literals being encoded as UTF-8 in all non-Microsoft modes,
regardless of the encoding of the source file.  This processing has now
been refined in non-GNU modes so that, when
NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is set to TRUE,
universal-character-names appearing in non-Unicode-encoded source files are
translated to the system default locale character set.  With
NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE set to FALSE, non-Unicode
source files are assumed to use the Latin-1 encoding; the value of a
universal-character-name is truncated to its lower eight bits and a warning
issued for code points above 0xff.  (In GNU modes,
universal-character-names continue to be translated to UTF-8, as is done by
the GNU compilers.)  The effect of this change is that extended characters,
whether represented in a native encoding or as universal-character-names,
will have the same output representation.  For example, in the following
Latin-1 encoded source file compiled in a non-GNU mode, strlen(str) will be
2 and both characters will be the same:

  char str[] = "«b6»\u00b6";  // The pilcrow (paragraph mark) in Latin-1
                              // and as a universal-character-name

Note: The above example must be decoded using the edg-changes-example tool.


12/15/11 [EDGcpfe/11682]
Access checking in SFINAE contexts

The C++11 rules for substitution of template arguments into function
template declarations require access violations to result in deduction
failure.  We implemented most of this as part of our original
SFINAE implementation (see 4/26/10 entry), but the access checking
did not include consideration of the context in which the template was
declared (e.g., class membership and friend status).  In addition,
access of substituted member references (e.g., T::X) was not checked
at all.  Full access checking is now done in modes in which SFINAE
access is not ignored.

  // This example resulted in a "no instance ... matches" error.
  // It now compiles successfully because the operator- function is
  // accessible to B because of friendship.
  struct B {
    template <class T> static auto f(T t1, T t2) -> decltype(t1-t2);
  };
  class A {
    friend struct B;
    A& operator-(A&);
  };
  int main() {
    A a1, a2;
    B::f(a1, a2);
  }

  // This example resulted in a spurious "S::priv is inaccessible" error.
  // It now calls f(...).
  class S {
    static const int priv = 1;
  public:
    static const int pub = 2;
  };
  template<int> struct Z { };
  template<typename T> Z<T::priv> f(T*);
  void f(...);
  void g(S* p) {
    f(p);
  }


12/14/11 [EDGcpfe/12332]
C++-generating back end, GNU compatibility: abort on __builtin_offsetof base
class member

When a GNU __builtin_offsetof operator is applied to a member of a base
class of the class named in its first argument, the C++-generating back end
aborted with an assertion failure.  This is now fixed.  For example:

  struct A {
    int i;
  };
  struct B : A { };
  int j = __builtin_offsetof(B, i);


12/14/11 [EDGcpfe/12516]
Eliding unnecessary calls to empty virtual destructors

As a followup to the changes introduced by EDGcpfe/11966 and EDGcpfe/12298,
a change has been made in the treatment of virtual destructors.  By default,
all virtual destructors have a non-empty body (by virtue of an assignment
to a virtual table pointer), but if a customer has made local changes to
remove this assignment in some circumstances, then that virtual destructor
may have appeared to have no effect and calls to it had been eliminated in all
cases.  A change has been made to eliminate calls to empty virtual destructors
when the destructor is called directly, but not if it is called through a
virtual function table pointer.  In this example:

  struct A { virtual ~A() {} };
  void f(A *pa) {
    A a;
    delete pa;
  }

the destruction call for "a" is elided, but the destruction call for "pa"
remains.


12/13/11 [EDGcpfe/12426]
Excessive recursion on switch statement with many labels

In some configurations, the front end traversed the list of case labels of a
switch statement using recursion.  For switch statements with a large number
of such labels, the recursion was likely to exceed the capabilities of the
call stack.  This is now fixed.


12/10/11 [EDGcpfe/12499]
C++-generating back end: missing qualification in template argument

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the
C++-generating back end failed to put out the necessary qualification on
a name appearing in a template argument in a dependent member function
call when the class of the object expression in the call matches the
required qualifier in the template argument.  This is now fixed.  For
example:

  struct S {
    template<typename T> void f();
    template<typename T> struct I { };
  };
  struct X {
    S s;
    template<typename T> void g() {
      typedef S::I<T> SI;
      s.f<SI>();  // Previously generated as ((s).f< I< T> > ())
                  // Now generated as ((s).f< typename S::I< T> > ())
    }
  };


12/10/11 [EDGcpfe/12501]
GNU compatibility, C-generating back end: type definitions in function
prototype scope

If a type is defined in a function prototype scope and a function pointer is
declared using that function type (via the GNU typeof extension), the
C-generating back end put out duplicate definitions of the type from the
function prototype scope.  This is now fixed.  For example, the generated
C code for the following contained two definitions of the transparent union
defined as the parameter of "f":

  void f(union { int i; } __attribute__((transparent_union)));
  typeof(f) *p;


12/10/11 [EDGcpfe/12495]
GNU compatibility, C++-generating back end: transparent union function
parameters

The C++-generating back end put out incorrect code (referencing an
undeclared union type with a name of the form __T12345678) for an argument
passed to a transparent union type (a GNU extension).  This is now fixed.
For example:

  void f(union { void* p; } __attribute__((transparent_union)));
  void g(void* q) {
    f(q);   // Previously generated as f(((union __T12345678){.p = 1}))
  }


12/9/11  [EDGcpfe/12498]
Incorrect parent recorded for dependent qualified friend template declaration

The routine entry recorded for a qualified friend function template declaration
sometimes incorrectly recorded the parent of the designated function template
if the enclosing class appeared in a namespace.  For example:

  namespace N {
    namespace M { template<typename T> void f(T); }
    template<typename T> struct S {
      template<typename U> friend void M::f(U);
        // The placeholder entry for the friend declaration previously
        // erroneously recorded N as the parent namespace for the
        // designated friend function.
    };
  }

This is now fixed.


12/9/11  [EDGcpfe/12497]
Formatting of template function types in diagnostics

To improve the readability of diagnostics, the front end was modified to
remove member typedefs from types in diagnostic output (see 10/28/05
entry).  While this improved most diagnostics, it made certain diagnostics
that refer to function template declarations, or member functions of
class templates, more verbose.  The front end now preserves such typedefs
for template-based function declarations.

The following example gives a warning about a missing return in A<T>::f.
The type listed in the instantiation traceback has changed as follows:

  old: B<C<T, T>::type, C<T *, T*>::type>::type A<T>::f() [with T=int]
  new: A<T>::X A<T>::f() [with T=int]

  template <class T, class U> struct C { typedef C<T,U> type;};
  template <class T, class U> struct B { typedef C<T,U>::type type;};
  template <class T> struct A {
    typedef B<C<T,T>::type, C<T*,T*>::type>::type X;
    X f() {}
  };
  int main() {
    A<int> ai;
    ai.f();
  }


12/8/11  [EDGcpfe/12276]
GNU compatibility: typeof constructs sometimes incorrectly parsed

The Changes entry of 6/2/10 for EDGcpfe/10710 describes a change for typeof
constructs applicable to GNU C++ mode with gnu_version >= 30400.  However,
some of the associated behavior was accidentally enabled in other GNU modes,
causing the front end to incorrectly parse certain occurrences of the typeof
construct in those modes.  For example, in GNU C mode:

  int i;
  typeof(i) (x);  // Previously erroneously parsed as a function call,
                  // which in turn resulted in a spurious error.

This regression is now fixed.


12/7/11  [EDGcpfe/12313]
Position of aggregate initializers

The front end now records the position of aggregate initializers in the
corresponding ck_aggregate entry's source_corresp.decl_position field.  It
does so both for top-level aggregate initializers (which are always brace-
enclosed) and for sub-aggregate initializers (which may or may not be brace-
enclosed).  If the ck_aggregate entry represents a brace-enclosed initializer,
the recorded position is that of the opening brace; if it represents an
initializer not enclosed in braces, the position of the first element in the
initializer is recorded instead.  For example:

  struct S { int a[3]; };
  S x = { 1, 2, 3 };  // Two ck_aggregate entries: The "outer" one records
                      // the position of "{" and the "inner" one records the
                      // position of "1" (the first element of the sub-
                      // aggregate of type "int[3]").
  S y = { { 1, { 2 }, 3 } };
                      // Two ck_aggregate entries: The "outer" one records
                      // the position of the first "{" and the "inner" one
                      // records the position of the second "{".  Note that
                      // the innermost braces (in "{ 2 }") are superfluous
                      // and do not represent an aggregate initializer: Their
                      // position is not recorded.


12/7/11  [EDGcpfe/12380]
Abort on local nonstandard anonymous union in C mode

The C++-generating back end often aborted when attempting to render a local
nonstandard anonymous union (enabled when ALLOW_NONSTANDARD_ANONYMOUS_UNIONS
is TRUE) in C mode.  For example:

  void f() {
    struct L {
      struct A { int x; };  // Nonstandard anonymous "union" previously
    };                      // triggered an abort in the C++-generating
  }                         // back end.

This is now fixed.


12/7/11  [EDGcpfe/12490]
Elided copy constructor checked and instantiated in Microsoft and GNU C++ modes

When a copy constructor call is elided, the standard requires that the
copy constructor still be callable.  Formerly, that was checked only
in strict mode.  Now, it is also checked in C++11 mode, g++ mode, and
Microsoft C++ mode.  The diagnostic issued is a warning except in
strict mode.  In all modes in which the check is done (except
Microsoft mode), if the copy constructor is a template it is now also
instantiated.  That could potentially provoke some errors that
previously were not found.

  struct A {
    A();
  private:
    A(const A&);
  };
  int main() {
    A a = A();  // Warning now in g++ and Microsoft modes
  }

Furthermore, the similar check done when a reference to const is
bound to a class rvalue (the need for which was eliminated in C++11
by core issue 391 -- see Changes entry of 3/16/07) is now done in
g++ and Microsoft C++ modes only for the appropriate version numbers
(both those compilers have now implemented core issue 391).


12/6/11  [EDGcpfe/12439]
GNU C compatibility: Excess aggregate initializers

In GNU modes, the front end ignores excess aggregate initializers (with a
warning) in various situations.  However, previously, excess initializers were
not permitted if they appeared inside the superfluous braces surrounding an
initializer for a simple non-aggregate value.  For example:

  double z[1] = { { 1.0, 2.0 } };  // Previously an error in all modes.
                                   // Now accepted in GNU C mode.

Now the excess initializers in such contexts (the "2.0" in this example) are
also ignored with a warning in GNU C mode.  (See also the Changes entry of
7/15/02.)


12/5/11  [EDGcpfe/12445]
Representation of array bounds

When the bound of an array uses an expression involving a local variable, the
a_constant entry does not directly point to a representation of the expression.
Instead, the a_local_expr_node_ref mechanism (described in the Changes entry of
4/28/06) indirectly associates a backing expression with that use of the
constant entry.  The constant entry could previously still be reused in other
contexts without an indirectly associated backing expression.  For example:

  void g(int x) {
    double z[sizeof(x) > 0 ? 2 : 4];  // The constant entry representing the
  }                                   // bound was previously the same as the
                                      // one representing the literal 2.

This proved to be inconvenient for some consumers of the IL.  Therefore,
constant entries used as array bounds are now no longer re-used elsewhere in
the IL tree if they have indirectly associated backing expressions (there is
no change for constant entries that point directly to a backing expression 
since they were never candidates for reuse).


12/3/11  [EDGcpfe/12483]
C++-generating back end: template keyword in dependent qualifiers

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the
C++-generating back end put out a name qualifier denoting an instance of a
template member of a template parameter without the necessary template
keyword.  This is now fixed.  For example:

  void f(int);
  template<typename T> struct S {
    void g() {
      f(T::template X<int>::i);  // Previously missing "template"
    }
  };


12/3/11  [EDGcpfe/12482]
C++-generating back end: placement of #pragma pack directives

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL and
USER_CONTROL_OF_STRUCT_PACKING are TRUE but MICROSOFT_EXTENSIONS_ALLOWED is
FALSE, the C++-generating back end put out #pragma pack directives that
appeared in the source preceding a class template definition in incorrect
locations.  For example,

  namespace N {
  #pragma pack(push)
  #pragma pack(1)
  template<typename T> struct S {
    T m;
  };
  #pragma pack(pop)
  }

was generated as

  namespace N { 
  template< class T> 
  #pragma pack(1)
  struct S { 
  #pragma pack ( push )
  #pragma pack ( 1 )
  T m; 
  }; 
  #pragma pack(1)
  }
  #pragma pack ( pop )

This is now fixed, and the #pragma pack directives appear in the same
locations as in the original source.


12/1/11  [EDGcpfe/12473]
Qualified function types in C mode

In C++ modes, the front end ignores type qualifiers on function types (with
a warning, unless the qualification occurs through template substitution).
This matches the requirements of the C++ standard.  The C standard, however, 
deems type qualifiers on function types (which can happen through typedefs,
or in GNU C mode, through typeof) to be undefined behavior.  The front end
previously silently accepted such qualifiers and retained them in the IL
representation, which could affect type compatibility later on.  For example:

  typedef void F();
  F const *pf;  // Previously silently accepted in C mode.  C++ modes
                // ignore the "const" with a warning.
  void g(F *p) {
    p = pf;     // Previously triggered a type incompatibility error in
  }             // C modes because pf was treated as a pointer to const.

The C mode behavior has been changed to match that of C++ modes.

The prior C mode behavior triggered an internal error in form_type_first_part
("qualifier on function type") in GNU C mode diagnostics that involved a
qualified function type formed by adding qualifiers to a typeof construct.
For example:

  void f();
  void (*p)() = (const typeof(f)*)f;  // Previously aborted.

This is fixed by the change described above.  The IL-to-string routines have
also been modified to gracefully handle qualified function types when
rendering code that is not meant to be compiled (diagnostics in particular).


12/1/11  [EDGcpfe/12446]
C++-generating back end: exception handler in class with dependent base

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the
C++-generating back end incorrectly applied the global scope-resolution
operator :: to the name in an exception handler appearing in a member
function of a class with a dependent base.  This is now fixed.  For
example:

  template<typename T> struct B {};
  template<typename T> struct D : B<T> {
    void f() {
      try { }
      catch(int e) { }  // Previously generated as (::e)
    }
  };


12/1/11  [EDGcpfe/11726,EDGcpfe/10668]
Microsoft compatibility: _NATIVE_NULLPTR_SUPPORTED macro

The headers accompanying Microsoft VC10 assume that the compiler implicitly
defines _NATIVE_NULLPTR_SUPPORTED to indicate that the non-managed version
of the nullptr keyword is available.  The front end has now been changed to
define that macro when microsoft_version is at least 1600 and nullptr
support is enabled.  For example, the following program now displays "Value
is 1" under those settings:

  extern "C" int printf(const char*, ...);
  int main() {
  #ifdef _NATIVE_NULLPTR_SUPPORTED
    printf("Value is %d\n", _NATIVE_NULLPTR_SUPPORTED);
  #else
    printf("Undefined.\n");
  #endif
    return 0;
  }


11/30/11 [EDGcpfe/12328]
Potential abort on Microsoft out-of-class member redeclaration

In Microsoft modes, the front end sometimes accepts out-of-class member
function declarations that aren't definitions (see Changes entry of 3/1/05).
When such a declaration was for a member of an overload set, the front end
accessed the wrong variant of a symbol, which could lead to an abort.
For example:

  struct S {
    void f();
    void f(int);
  };
  #pragma start_map_region("filename")
  __declspec(implementation_key(1)) void S::f();  // Could trigger an abort.
  #pragma stop_map_region

This is now fixed.


11/30/11 [EDGcpfe/9185]
Tag names of mismatched kinds

Previously, the use of a tag name with a kind ("struct", "union", etc.)
different from the same tag name declared earlier in an enclosing scope was
treated as a new declaration of that tag name.  For example:

  union U { int i; };
  void f() {
    struct U *p;  /* Previously treated as a new struct type; now an error
  }                  in many modes. */

This behavior was the consequence of an unclear specification in the original
C standard (i.e., "C90").  However, the C++ standard and the resolution of
defect report 251 for the C99 standard (part of Technical Corrigendum 3) make
it clear that such cases are errors.  The front end now diagnoses that error
in modes other than K&R C, C90, and Cfront C++; otherwise, it maintains the
prior behavior.


11/23/11 [EDGcpfe/11891]
Segfault in initialize_dtor_init_for_cleanup

In some IA-64 ABI configurations, copying of constructor inits during
IL lowering had resulted in inconsistent destruction information, leading
to a segmentation violation in initialize_dtor_init_for_cleanup (or possibly
other undefined behavior).  This example had failed (with -x in IA-64 ABI
configurations where HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS is TRUE)
and now compiles as expected:

  namespace {
    struct A {
      virtual ~A() {}
    };
    struct B : virtual A {};
    struct C {
      B b;
      C() {}
    };
    template<class T> struct D {
      template<class U> void g();
    };
  }
  void f() {
    D<int> d;
  }


11/23/11 [EDGcpfe/11542]
C99: Add support for __STDC_MB_MIGHT_NEQ_WC__ macro

Technical Corrigendum 3 for C99 added a new macro, __STDC_MB_MIGHT_NEQ_WC__,
which, when set to the integer constant 1, indicates that, in the encoding for
wchar_t, a member of the basic character set need not have a code value equal
to its value when used as the lone character in an integer character constant.
The front end now has a configuration macro STDC_MB_MIGHT_NEQ_WC that, when
set to TRUE, predefines the macro __STDC_MB_MIGHT_NEQ_WC__ (to "1").
By default __STDC_MB_MIGHT_NEQ_WC__ is undefined.


11/22/11 [EDGcpfe/12003]
VLA fields treated as zero-length arrays (GNU C mode)

In GNU C mode, the front end treats variable-length array (VLA) fields of
local structs as zero-length arrays (see the Changes entry of 3/4/02).  A new
flag ("vla_treated_as_zero_length_array") has been added to a_field entries to
indicate that such a transformation occurred.


11/22/11 [EDGcpfe/12356]
GNU compatibility: Empty member declarations with attributes in GNU modes

In GNU C++ mode, the front end now accepts an empty class member declaration
that specifies attributes (the attributes are ignored with a warning).
Although such declarations were already accepted in GNU C mode, the warning
for that case has been changed to reflect the fact that the attributes are
ignored.  For example:

  struct S {
    __attribute((aligned(32)));  // Now accepted with a warning in GNU C++
  };                             // mode.


11/22/11 [EDGcpfe/11660]
Abort on attempt to declare a friend constructor in Microsoft mode

In Microsoft mode, trying to declare a friend constructor with an elaborated
unqualified name (which is permissible in Microsoft mode for ordinary
constructor declarations) resulted in an abort in f_identical_types (trying
to dereference a NULL type pointer).  For example:

  struct S {
    friend struct S(S*);
  };

This is now fixed.


11/19/11 [EDGcpfe/11966,EDGcpfe/12298]
Removing unneeded constructions and destructions during lowering

A new configuration macro,
LOWERING_REMOVES_UNNEEDED_CONSTRUCTIONS_AND_DESTRUCTIONS, has been added to
control whether lowering removes constructions and destructions that are known
to have no effect.  Removing unneeded constructions and destructions can
greatly reduce the code size of some trivial functions, particularly when the
portable implementation of exception handling is used (where the invocation of
any destruction causes an exception handling prologue to be generated for the
function, which in turn has implications for inlining).  The implementation
doesn't detect all cases where such destructions could potentially be
eliminated (for example, a constructor or destructor that is defined to be
empty after code that refers to it has already been lowered).
LOWERING_REMOVES_UNNEEDED_CONSTRUCTIONS_AND_DESTRUCTIONS
defaults to the value of DO_IL_LOWERING (i.e., is enabled by default in
configurations that use lowering).  Some empty constructors are not removed in
Cfront ABI configurations when NEW_CAN_BE_FOLDED_INTO_CTOR is TRUE (namely
those involved in "new" expressions as well as any constructions when
exception handling is enabled).

In the example below, the newly lowered code will have no references to any of
the constructors or destructors (except in configurations where
NEW_CAN_BE_FOLDED_INTO_CTOR is TRUE):

  struct A {
    A();
    ~A();
  };
  inline A::A() {}
  inline A::~A() {}
  struct B {
    B() {}
    ~B() {}
  };
  struct C : B {};
  struct D {
    A a;
    B b;
  };
  int main () {
    A a;
    B b = B();
    C *c = new C;
    D *d = new D[5];
    delete c;
    delete[] d;
  }

This (contrived) example (with --g++ in one IA-64 ABI C-generating back end
configuration) had yielded an object file with a .text section of 1250 bytes
and a .data section of 160 bytes, but with the removal of unneeded constructors
and destructions, the .data section is eliminated and the .text section dropped
to 242 bytes.

As part of these changes, a change was made to the way the
instantiation_required flag is cleared during wrapup processing.  Previously
this flag was only cleared for entities that were being removed from the IL
(i.e., keep_in_il was FALSE).  Now, the flag is cleared for entities whose
"needed" flag is FALSE, and this processing is performed regardless of
whether unneeded entities are removed from the IL.  This may result in some
differences in prelinker output.


11/18/11 [EDGcpfe/12452]
Microsoft compatibility: Use of "." in qualified names

Older versions of the Microsoft compiler allowed "." to be used in place of
"::" in qualified names (i.e., type-name. was treated like type-name::).
This has been fixed by Microsoft, so we now only support this usage in
Microsoft bugs mode when microsoft_version <= 1400.  Note that the usage
involved here is different than field selections where the thing before
the "." is an expression, not a type.

  struct A {
    struct B {};
    static int i;
  };
  int main() {
    A.B ab;
    int i = A.i;  // Only accepted in Microsoft bugs mode when
                  //  microsoft_version <= 1400
  }


11/17/11 [EDGcpfe/12429]
Spurious error on template referring to extern "C" declaration in GNU C++ mode

In some GNU C++ modes, the front end incorrectly handled certain declarations
of extern "C" functions previously also imported from another namespace via a
using-declaration.  This manifested itself as a spurious error when a template
refers the extern "C" function.  For example:

  namespace N { extern "C" { void f(); } } 
  using N::f; 
  template<typename T> void g() { f(); }
  extern "C" void f();
  template void g<int>();  // Spurious error "no instance ... matches ...".

This is now fixed.


11/17/11 [EDGcpfe/12450]
Improvement in handling of GNU C transparent unions

The front end's handling of the gcc "transparent unions" extension has
been improved; the front end now rejects some cases it allowed
previously, which are rejected by gcc.  The type of the entity being
cast to the transparent union type must now match the type of some
member of the union exactly (except for certain cases involving null
pointer constants or void *), whereas previously any "interchangeable"
type (roughly, same kind and size, signedness and cv-qualifiers
ignored) was allowed.

  typedef union TU {
    double d;
    int i;
  } TU;
  int i;
  unsigned int ui;
  int main() {
    TU u1 = (TU)i;  // Okay
    TU u2 = (TU)ui; // Was okay, error now
  }


11/11/11 [EDGcpfe/12414]
Emulation of g++ quirk on overload resolution, adding cv-qualifiers on "this"

The front end now emulates a g++ quirk that treats an argument match
with added cv-qualification on a "this" parameter as worse than an
argument match with the same added cv-qualification under a reference
on a parameter other than the "this" parameter.  This comes up when a
const conversion function competes with a constructor with a
reference-to-const parameter, for example:

  struct A;
  struct B {
    operator A() const;
  };
  struct A {
    A(const B&);
  };
  int main() {
    B b;
    A a = b;  // g++ treats as not ambiguous, A(const B&) wins
  }

g++ does get this right in -pedantic mode, so apparently it does
recognize that it's nonstandard.


11/8/11  [EDGcpfe/11590]
Infinite loop on invalid template static data member

Version 4.3 introduced a problem that could result in an infinite loop
if a template static data member had an invalid initializer containing
braces.  Now fixed.

  template <class T> struct A {
    static int x;
  };
  template <class T> int A<T>::x ({0});
  int y = A<int>::x;


11/7/11  [EDGcpfe/11987]
vtable now emitted on explicit instantiation of class template specialization

A change has been made to emit a vtable for a class template specialization
that has an explicit instantiation (see core issue 969).  The vtable is
emitted regardless of the presence or absence of a key/decider function.  The
following example had previously failed to link (vtable for D<int> was not
defined in either translation unit), but now links without error:

  // t.h:
  struct B {
    virtual ~B() {}
  };
  template <class T> class D : public B {};

  // t1.c:
  #include "t.h"
  template class D<int>;    // now a vtable for D<int> is emitted in t1.o

  // t2.c:
  #include "t.h"
  extern template class D<int>;
  int main() {
    D<int> d;
  }


11/4/11  [EDGcpfe/12369]
Improved determination of default constructor

In some very obscure cases (involving templates, default arguments,
and parameter packs) the determination of the default constructor in
a class was incorrect, and a spurious error was issued.  Now fixed;
the full normal overload resolution is done, instead of a simplified
algorithm that gave some incorrect answers.

  struct A {
    template <class T = int> A(T = 1){}
    template <class ...T> A(T...);
  };
  A a;  // Formerly gave a spurious error:
        //  class "A" has more than one default constructor


11/3/11  [EDGcpfe/12407]
GNU compatibility: __attribute(deprecated("..."))

In GNU modes with gnu_version >= 40500, the front end now accepts an optional
string argument for the attribute "deprecated".  The argument string is
reported as part of the warning issued when an entity declared with such an
attribute is used.  (See also the Changes entry of 11/9/05.)


11/3/11  [EDGcpfe/12400]
Abort on selective overriding of __interface members

In some Microsoft-mode situations where a derived class selectively overrides
member functions from distinct indirectly-inherited __interface base classes,
the front end could abort with an internal error in interface_slot_override
(in class_decl.c).  For example:

  __interface B1 { virtual void f1() = 0; };
  __interface B2 { virtual void f2() = 0; };
  __interface C: B1, B2 {};
  struct D: C {
    void C::f1() {}
    void C::f2() {}  // Triggered an internal error.
  }; 

This is now fixed.


11/3/11  [EDGcpfe/12395]
Instantiation directive flags added to the IL

Information about explicit instantiation directives has been added
to the IL entries for template functions (in a_routine) and template
static data members (in a_variable).  The fields that have been added
are explicit_instantiation, class_explicitly_instantiated, and
explicit_do_not_instantiate.


11/2/11  [EDGcpfe/12364]
Inadvertent initk_static used for auto variables during lowering

Lowering had inadvertently used initk_static initialization for some
temporaries with automatic storage (a violation of the IL rules) when lowering
some constructs.  The C-generating back end had accepted this initialization
(it now fails an assertion check), but other back ends may have flagged the IL
as illegal.  Such constructs had been used when promoting local static
variables whose aggregate initializers contain GNU address labels, for example:

  void f() {
    struct A { A() {} };     // causes promotion of local statics
    static void *x[1] = { &&label };
  label:
    return;
  }

Also, in Cfront ABI configurations that use LOWER_EXTERN_INLINE, a local
static that is dynamically initialized to an aggregate could also generate
invalid IL:

  int f() { return 1; }
  inline int g() {
    static int a[] = {f(), -1};
    return a[0] + a[1];
  }
  int main() {
    return g();
  }


11/2/11  [EDGcpfe/11859]
Position of qualified base-class specifier in cross-reference output

When a base class specifier is a qualified name, the front end previously
reported the position of the base class name as that of the qualifier in the
cross-reference output.  Now it correctly reports the position of the
qualified identifier.  For example:

  namespace N { struct B {}; };
  struct D: N::B {};  // Previously, the cross-reference for B indicated the
                      // position for N in N::B.  Now it indicates the
                      // position of the identifier B.


11/2/11  [EDGcpfe/11663]
__w64 annotation ignored on typedef for size_t in Microsoft C++ mode

The front end previously ignored the __w64 annotation (see Changes entry of
6/18/03) when it appeared on a typedef for size_t (because the predeclared
typedef for size_t was retained; see the Changes entry of 4/20/98).
For example:

  typedef __w64 unsigned size_t;  // __w64 was previously ignored.

This is now fixed.


11/2/11  [EDGcpfe/12415]
C-generating back end, GNU compatibility: implicit declaration of function
later defined with different type

The gcc compiler accepts (with a warning) and correctly executes a file in
which a function is implicitly declared by a call and later defined with a
different type, for example

  int f() {
    g();        /* implicitly declared to return int */
  }
  void g() { }  /* defined to return void */

The code put out by the C-generating back end for such a call involved a
cast applied to the function name, to adjust its actual type to the type
expected in the context of the call.  Beginning with its version 3.4,
however, gcc explicitly tests for calling a function through a cast to a
different type and causes a runtime abort.  The C-generating back end now
uses a function pointer of the implicitly-declared type, initialized to
point to the actual function, for such calls, and gcc accepts this pattern
without error.


11/1/11  [EDGcpfe/12080]
Microsoft compatibility: additional printf/scanf type-specifier prefixes

Microsoft supports non-standard "I32", "I64", and "I" type-specifier prefixes
for parameters in format strings for printf- and scanf-like routines.  In
Microsoft emulation mode, "I32" can now be used for (signed and unsigned)
__int32 types and "I64" for (signed and unsigned) __int64 types.  "I" can be
used for ptrdiff_t and size_t types.  See
http://msdn.microsoft.com/en-us/library/tcxf1dw6(v=VS.100).aspx for more
information.  For example:

  #pragma __scanf_args
  extern "C" int sscanf(const char *, const char *,...);
  #pragma __printf_args
  extern "C" int printf(const char *,...);
  int main() {
    char *buf = "12345";
    __int32 i32;
    __int64 i64;
    sscanf(buf, "%I32d", &i32);
    i64 = i32;
    printf("%I64d\n", i64);
  }


10/28/11 [EDGcpfe/12330]
Spurious error on a dependent friend constructor declaration

Previously, attempting to name a constructor of a class template in a friend
template declaration for another class template triggered a spurious error
(the specific error depended on the mode).  For example:

  template <typename T> struct A { A() {} };
  template <typename S> struct B {
    template<typename T> friend A<T>::A();  // Previously a spurious error.
  };

This is now fixed.


10/27/11 [EDGcpfe/12132,EDGcpfe/12402]
Missing scoped enum qualification in diagnostic output

Messages referring to a scoped enumerator inadvertently omitted the enum
qualification.  This is now fixed.  For example:

struct S {
  enum class E { e };
  E::e x;  // Diagnostic previously referred to "e", now to "S::E::e".
};


10/27/11 [EDGcpfe/12344]
Incorrect source sequence entries list for repeated using-declaration

When a using-declaration referring to an overload set in a namespace scope was
repeated, the resulting source sequence entries list (in configurations with
GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE) was incorrect; specifically, it
would contain too many entries for using-declarations.  If the repeated using-
declarations appeared in a local scope and were followed by an additional
statement, the invalid list triggered an internal error in the C++-generating
back end ("wrong entry").  For example:

  namespace N {
    void f();
    void f(int);
  }
  void g() {
    using N::f;
    using N::f; // Previously incorrectly represented in some configurations.
    return;     // Previously triggered an internal error in the
  }             // C++-generating back end.

This is now fixed.


10/27/11 [EDGcpfe/12336]
C++-generating back end: Abort with members of dependent bases in type
specifiers

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the use
of a name from a dependent base class in the type specifier of a member
function or static data member defined outside the class template resulted
in an assertion failure abort in qualifier_for_unknown_base_member
(cp_gen_be.c).  This has now been fixed.  For example:

  template<typename T> struct B { typedef int type; };
  template<typename T> struct D: B<T> {
    typename D<T>::type f();
  };
  template<typename T> typename D<T>::type D<T>::f() {  // Caused an abort
    return typename D<T>::type();
  }


10/27/11 [EDGcpfe/12384]
C++-generating back end: Undeclared temporary qualifier in dependent name

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE and
DEFAULT_RECORD_FORM_OF_NAME_REFERENCE is FALSE, the C++-generating back
end sometimes used an undeclared temporary name (i.e., a name of the form
__T12345678) as a qualifier in a dependent name, causing errors when the
generated code was compiled.  This is now fixed.  For example:

  template<typename T>
  struct B {
    struct M : public T {
      int i;
    };
    M m;
  };
  template<typename T>
  struct D : B<T> {
    void f();
  };
  template<typename T> void D<T>::f() {
    this->m.i = 0;  // Previously generated as (this->m).__T12345678::i
  }


10/26/11 [EDGcpfe/12377]
Remove extra temporary created during lowering

As a result of the expression changes introduced in 4.0, an additional
temporary had been introduced during lowering when the source code included
a reference to a class rvalue that needed cv-qualification adjustment.
The extra temporary has now been removed.  For example:

  struct A { };
  A f();
  void g(const A&);
  void h() {
    g(f());   // Had used two temporaries, now uses one.
  }


10/25/11 [EDGcpfe/12366]
C++-generating back end: Member access specifiers and Microsoft attributes

The C++-generating back end previously rendered an access specifier for a
declaration after Microsoft attributes (enclosed in square brackets) for that
declaration: The resulting syntax is invalid.  For example:

  class C {
  public:
    [Any(0)] int f();  // Previously rendered as "[Any(0)] public: int f();"
  };

This is now fixed.


10/25/11 [EDGcpfe/12394]
C++-generating back end, Sun compatibility: explicit vs default template
arguments

The Sun C++ compiler on Sparc and 32-bit Solaris platforms has a bug that
causes it to mangle types differently depending on whether template
arguments are specified explicitly or are taken from default template
arguments (the version using default arguments is the correct one).  Unless
a template argument is inaccessible at the point of the reference, the
C++-generating back end always put out the names of template instances
using the complete template argument list, which sometimes resulted in the
generated code triggering the Sun mangling bug.  This has now been
addressed by keeping track of the minimum number of template arguments used
in the original source to refer to that template instance and only putting
out that number of arguments, even when there are no problems with access.
For example:

  template<typename T> struct P { };
  template<typename T, typename W = P<T> > struct M { };

  M<void*(*)()> _M;  // Formerly generated as M<void*(*)(), P<void*(*)()> >
  M<void*(*)()>& xxx() { return _M; } // ...which caused Sun CC to mangle
                                      // the name of xxx incorrectly


10/25/11 [EDGcpfe/11912]
Possible abort after recovering from a too-large enumerator constant

In some configurations that set enum_types_can_be_smaller_than_int, the front
end could end up attempting to perform integer operations on an error constant
resulting from specifying a value for an enumerator constant that is too
large.  For example:

  enum E { e = 5000000000 };  // If 5000000000 is too large, an error constant
                              // was produced for error recovery purposes, and
                              // that was later incorrectly assumed to be an
                              // integer constant.

This is now fixed.


10/24/11 [EDGcpfe/11869]
Local variables with thread-local storage

The front end previously accepted local thread-local variables with dynamic
initializers in some modes.  To match both GNU and Microsoft compilers, such
initializers are no longer permitted.  For example:

  int g();
  int f() {
    static __thread int x = g();  // Previously accepted in GNU mode; now
    return x;                     // an error.
  }


10/24/11 [EDGcpfe/12381]
Microsoft compatibility: Access checking on enum base specifiers

Microsoft compilers do not perform access checking on enum base specifiers,
causing them to accept examples like the following:

  struct S { private: typedef int I; };
  enum E: S::I { e };  // S::I should be inaccessible.

A new global variable "disable_access_checking_in_microsoft_enum_bases" now
controls whether to emulate this behavior in Microsoft modes.  A configuration
macro DEFAULT_DISABLE_ACCESS_CHECKING_IN_MICROSOFT_ENUM_BASES determines the
default initial value of that variable.


10/21/11 [EDGcpfe/12378]
Setting the needed flag on lowered complex types

An inconsistency with setting the needed flag on lowered complex types
was discovered and fixed.  This had resulted in incorrect settings for
needed flags of lowered complex types in multi-trans-unit configurations.


10/20/11 [EDGcpfe/12376]
Extra warning on "new" with ambiguous corresponding delete

The front end gave a superfluous warning message after an error on
a "new" operator whose corresponding operator delete (to be used if
an exception is thrown) is ambiguous.  Now fixed; the warning is
no longer issued.

  struct A1 {
    void operator delete(void *);
  };
  struct A2 {
    void operator delete(void *);
  };
  struct A : public A1, public A2 {
    A();
    ~A();
    void *operator new(unsigned int, float);
  };
  int main () {
    A *q = new(2.5f) A;  // Error, ambiguous operator delete
  }


10/18/11 [EDGcpfe/12317]
By-reference capture across a non-mutable lambda

When an inner lambda captures a local variable by reference across an outer
non-mutable lambda that captures that variable by value, the field modeling
the capture in the inner lambda is now a reference to a const type.
Previously, this was not the case, which resulted in spurious errors.
For example:

  int main() {
    int i = 42;
    auto outer = [i]{
      auto inner = [&i]{};  // Previously triggered an error about binding
    };                      // a const i to a non-reference.
  }

(This agrees with a pending clarification for core issue 1249.) 


10/17/11 [EDGcpfe/12358]
Incorrect source position information for alias templates

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the identifier_range and
declarator_range fields for an alias template were not set correctly.
Now fixed.

  template <typename T> using ABC = T*;


10/17/11 [EDGcpfe/12349]
Extra source positions for template parameter declarations

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, decl_pos_info in the source
correspondence for type, nontype, and template template parameters is
now provided.  In the example below, T1, T2, T3, and T4 now have the
additional position information provided.

  template <typename T1, int T2, template <typename T3> class T4> class A {};


10/17/11 [EDGcpfe/12352]
Abort while writing IL file with attribute in template

Previously, the front end could abort while writing out the representation of
a GNU __attribute or Microsoft __declspec construct that includes an argument
when that construct appeared in a template that is instantiated in a function
definition.  For example:

  template<typename> struct X {
    template <typename T> __declspec(deprecated("old"))
      void d() {}
    template <typename T>
      void f() { d<T>(); }
  };
  void g() {
    X<void> x;
    x.f<int>();  // Triggered an abort while writing out the IL file for
  }              // this translation unit.

This is now fixed.


10/17/11 [EDGcpfe/12175]
new of unknown-bound array type okay in Microsoft mode

A "new" of an array type with an unknown bound is now accepted in Microsoft
mode, and treated as equivalent to a new of an array with a bound of [0].

  int *p = new int[];  // Accepted in Microsoft mode, same as "new int[0]"


10/14/11 [EDGcpfe/12083]
Abort with malformed "defined" operator in macro expansion

In Microsoft and old-style preprocessing modes, the front end aborted when
processing a "defined" operator that is missing the identifier or the right
parenthesis when it appeared in a macro expansion.  This has now been fixed
so that the front end does not abort, although an error is still correctly
reported.  For example:

  #define DEFINED defined (X
  #if DEFINED
  #endif


10/13/11 [EDGcpfe/11949,EDGcpfe/12152]
Storage class specifiers (IL CHANGE)

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, the front end now records the
storage class specifier (e.g., "extern") that appeared on a declaration for
a variable or function in the secondary source sequence entry associated with
that declaration (for declarations that aren't definitions or primary
tentative definition).  For definitions of functions, the declared storage
class that appeared in the source is now recorded in the associated routine
entry in such configurations (field "declared_storage_class").  For
definitions of variables, there was already a "declared_storage_class" field
in the associated IL entries: It is now also set for primary tentative
definitions, but for consistency's sake it is now only present in
configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE (previously,
that field was defined unconditionally).  Previously, secondary source
sequence entries entries included a flag "explicit_storage_class" to indicate
that a storage class was specified explicitly on the associated declaration:
That flag has been removed since it is made obsolete by the new
"declared_storage_class" field.


10/12/11 [EDGcpfe/12346]
PROTOTYPE_INSTANTIATIONS_IN_IL and function prototype deferral

Deferring prototype instantiation of function templates (see the 12/13/05
entry) was not permitted with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE,
based on the assumption that customers who wanted the information about
template definitions provided by the prototype instantiations would want
to have this information for all templates, not just those that were
actually instantiated.  This restriction has now been removed, to allow
customers to make their own decisions about the tradeoffs involved.


10/12/11 [EDGcpfe/12342]
C++-generating back end: Missing template header for member template

In configurations with both PROTOTYPE_INSTANTIATIONS_IN_IL and
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, the
C++-generating back end omitted a template header for an out-of-class
definition of a member template of a class template.  This has now been
fixed.  For example:

  template<bool T> struct A {
    template<typename U> void f();
  };
  // The following was previously missing the "template<bool T>" template
  // header in the generated code:
  template<bool T> template<typename U> void A<T>::f() {}


10/11/11  [EDGcpfe/12040]
GNU C++ Compatibility: lookup of unqualified names in dependent base classes

In g++ mode, names from dependent base classes are sometimes visible.
In newer versions of g++, this is done in fewer cases.  In the example
below, the call of g(p) calls B::g in g++ versions before 4.1, but
calls ::g starting with g++ version 4.1.  We now emulate the newer
behavior when gnu_version >= 40100.

  #include <stdio.h>
  struct B {
    int g(const B&) { return 0; }
  };
  int g(const B&) { return 2; }
  template<class B> struct A : B {
    int f(const B& p) { return g(p); }
  };
  int main() {
    A<B> ab;
    printf("%s\n", ab.f(ab) == 2 ? "pass" : "fail");
  }


10/11/11 [EDGcpfe/12310]
Canonical spelling of extended identifier characters

When UNICODE_SOURCE_SUPPORTED is TRUE, the front end produces canonical
spellings of identifiers using Unicode code points to represent extended
characters, regardless of whether the source encoding is Unicode or some
other multibyte character set.  However, single-byte extended characters in
non-Unicode source files were left in the original encoding.  Also, in
configurations in which NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is
FALSE, characters from a Unicode source file that have a single-byte
representation in Latin-1 were translated to that form in the canonical
spelling.  These problems have now been addressed and such characters will
now consistently be canonicalized to a Unicode form using UTF-8 or
universal character names, depending on the value of the
IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS configuration macro.


10/10/11 [EDGcpfe/12145]
GNU compatibility: volatile asm declarations in namespace scope

In GNU mode, the front end should accept volatile asm declaration like:

  asm volatile ("xxx");

However, it failed to recognize such forms when they appear in namespace
scope.  This is now fixed.


10/7/11  [EDGcpfe/12169]
C++11 type traits helpers and non-class types

A number of type traits helpers now return FALSE instead of TRUE when applied
to reference types, function types, and/or const types.  The affected helpers
are: __has_nothrow_constructor, __has_trivial_constructor, __has_copy,
__has_nothrow_copy, __has_trivial_copy, __has_trivial_destructor,
__has_trivial_move_constructor, __has_assign, __has_nothrow_assign,
__has_trivial_assign, __has_nothrow_move_assign, __has_trivial_move_assign,
__is_trivially_copyable, and __is_pod.


10/7/11  [EDGcpfe/12325]
Uninitialized variable used in scan_new_operator

During the scan of a "new" operator within a SFINAE context (e.g.,
in a decltype specifying the return type for a template), specifically
a "new" of a non-dependent non-class type with an initializer, an
uninitialized variable was used in scan_new_operator.  The
consequence was that the initializer could be treated as if
it were an empty initializer.  Now fixed.

  template <class T> auto f(T p) -> decltype (new int(1) + p) {
    return 0;
  }
  int main() {
    f(1);
  }


10/6/11  [EDGcpfe/12319]
C++-generating back end, GNU compatibility: template argument lists in
default arguments

Versions of g++ before 4.4 had a bug that resulted in spurious errors when
a default function argument expression contains a template argument list
with more than one template argument.  Because the C++-generating back end
puts out a full template argument list in the name of an instance of a
class template, even when the source code uses default template arguments,
in some cases the generated C++-code triggered this g++ bug when the source
code does not.  This has now been addressed by unconditionally enclosing
default argument expressions in parentheses.  For example:

  template<typename T, typename U = int> struct S { };
  class C {
    void f(S<int> x = S<int>());  // Default argument previously generated
                                  // as "S<int,int>()", triggering the g++
                                  // bug; now generated as "(S<int,int>())".
  };


10/6/11  [EDGcpfe/12183]
Spurious error on call of function template with nondependent vector parameter

In GNU C++ modes, the front end previously issued a spurious error on calls to
function templates with a nondependent vector parameter.  For example:

  template<class T> void f(int __attribute((vector_size(16))) p) {}
  int main() {
    int __attribute((vector_size(16))) v;
    f<void>(v);
  }

This is now fixed.


10/5/11  [EDGcpfe/11323]
GNU compatibility: Redeclarations of "gnu_inline" functions

In GNU mode with gnu_version >= 40300, the front end now issues an error if
a function first declared with the gnu_inline attribute does not specify that
attribute on subsequent redeclarations that are explicitly "inline".
For example:

  __attribute((gnu_inline)) __inline__ void g();
  __inline__ void g() {}  // Now an error in some GNU modes because the
                          // gnu_inline attribute is missing.


10/4/11  [EDGcpfe/12287]
Rare spurious correspondence error on some template definitions

When simultaneously compiling multiple translation units in configurations
that set USE_LONG_DOUBLE_FOR_HOST_FP_VALUE to TRUE, the front end occasionally
reported a spurious correspondence error on some template definitions that
contain floating point literals.  This rare problem is now fixed.


10/4/11  [EDGcpfe/12251]
Microsoft compatibility: enumerator constant overflow

In Microsoft mode, when an enumerator constant value is too large to be
represented by the underlying integral type, the front end now issues a
warning (instead of an error) and uses the lower bits of the value
representation for the enumerator value.  For example:

  enum E: signed char {
    e = 1000  // Previously an error.  Now a warning, and e has the
  };          // value -24.


10/4/11  [EDGcpfe/12311]
C++-generating back end, GNU compatibility: missing space before postfix
attributes

The C++-generating back end normalizes the position of GNU attributes that
apply to the declarator by putting them out in the postfix position when
that is permissible.  When putting out such an attribute that appeared in
the prefix position in the original source, however, the C++-generating
back end failed to separate the attribute from the declarator with a space,
resulting in incorrect code.  This is now fixed.  For example:

  static char * __attribute__ ((__section(".init.data"))) x;
  // Previously generated as
  // static char *x__attribute((__section(".init.data" )));


10/3/11  [EDGcpfe/11870]
Abort on nontype template argument that refers to a local static constant

In some configurations (particularly those that enable the C++-generating back
end), the front aborted with an internal error in scope_of_local_variable
(il.c, "scope not found") when a nontype template argument referred to a
local static const variable.  For example:

  template<int> void f();
  void g() {
    static const unsigned N = 1;
    f<N>();  // Triggered an internal error in some configurations.
  }

This is now fixed.


10/3/11  [EDGcpfe/12073,EDGcpfe/12270]
Microsoft compatibility: Attributes on member templates

The front end now accepts Microsoft-style attributes (enclosed in single
brackets) on member templates when microsoft_version >= 1400.


9/30/11  [EDGcpfe/11512]
GNU C++ compatibility: Empty list initializer on variable declaration

Recent versions of GCC support C++11-style list initializers and make some use
of the feature in GCC system headers.  To handle some of those uses, the front
end now accepts aggregate initializers (i.e., brace-enclosed initializers for
arrays and certain class types) without a preceding "=" token in GNU C++ mode
with gnu_version >= 40400 (with a warning if C++11 mode is not also enabled).
For example:

  const int okay[3]{};  // Now accepted in some GNU C++ modes.

(See also the Changes entry of 6/15/10 for EDGcpfe/10656.)


9/30/11  [EDGcpfe/12285]
Change in deduction rules for arguments that are overloaded function templates
with explicit template arguments

In a case where overload resolution is matching an argument that is
the name of an overloaded function template with explicit template
arguments (e.g., f<1> where f is overloaded) with a parameter that
requires deduction, the front end allows a given template to
participate if the template arguments specify a single specialization
of that template.  In the past, it did not matter whether the single
specialization could match the parameter through deduction.  Now, that
is considered as well, which eliminates some needless ambiguities when
more than one template has a unique specialization, but only one of
those can be made to match the parameter.  It's not clear what the
standard requires in such a case, but the new behavior seems to match
what g++ and MSVC do, and it's one of the reasonable interpretations
of the standard's wording.

  template<class B1> void bind(void (*f)(B1));
  template<int T> void f(int);
  template<int T> void f(int, int);
  void foo() {
    bind(&f<1>);  // Now selects f(int) template instead of giving error
  }


9/30/11  [EDGcpfe/11323]
GNU compatibility: Attribute names prefixed with double underscore

Previously, the front end treated GNU-style attributes whose name was prefixed
or prefixed-and-suffixed with double underscores ("__") like the same name
without those double underscores.  Now, GNU attribute names that are prefixed
but not suffixed by a double underscore are no longer implicitly equivalent to
the non-prefixed name.  For example:

  __attribute((noreturn)) void f();      // Okay in GNU modes.
  __attribute((__noreturn__)) void f();  // Also okay in GNU modes.
  __attribute((__noreturn)) void f();    // Now an unknown attribute.
                                         // (Previously same as "noreturn".)


9/30/11  [EDGcpfe/11843]
Abort in lowering of designator in GNU vector initializer

Previously, a designator for the initializer for a GNU vector of elements
whose type is represented by a typeref entry (e.g., a const-qualified type or
a typedef) could result in an abort in num_vector_elements (types.c) when that
initializer was lowered.  For example:

  __attribute((vector_size(8))) int const cv[2] = { [1] = {10} };
    // Previously resulted in an abort in num_vector_elements.

This is now fixed.


9/30/11  [EDGcpfe/12305]
C++-generating back end, GNU compatibility: __builtin_types_compatible_p

The name of the gcc builtin pseudo-function __builtin_types_compatible_p
was misspelled in the output of the C++-generating back end as
__builtin_types_compatible.  This is now fixed.  For example:

  int i = __builtin_types_compatible_p(int, int);


9/30/11  [EDGcpfe/11856]
Microsoft C compatibility: __wchar_t

The keyword __wchar_t is now accepted in Microsoft C mode: It denotes the
standard C++ wchar_t type (i.e., it is not just a synonym for a traditional
integer type like short or int).  See also the Changes entry of 1/31/05.


9/29/11  [EDGcpfe/12296]
Mangling for implicit "this" in late-specified return type

The changes introduced for "this" in a late-specified return type
(EDGcpfe/11746,EDGcpfe/11557) changed the internal representation for
expressions that contained an implicit "this", resulting in a change in the
mangled names for such expressions.  A change has been made to restore the
original IA-64 ABI mangling, and to change the Cfront mangling to use same
mangling as for the explicit "this" case (except in cases where
ABI_COMPATIBILITY_VERSION < 440 in which case the 4.3 Cfront mangling is used).
For example:

  int a;
  struct A {
    template <class T> auto f1(T x) -> decltype(x == a);
    int a;
    template <class T> auto f2(T x) -> decltype(x == a);
  };
  void g() {
    A().f1(37);
      // IA-64: _ZN1A2f1IiEEDTeqfp_L_Z1aEET_
      // Cfront: f1__tm__2_i__1AFZ1Z_YOeq_2_I1I1aO
    A().f2(37);
      // IA-64: _ZN1A2f2IiEEDTeqfp_1aET_
      // old Cfront: f2__tm__2_i__1AFZ1Z_YOeq_2_I1IOrf_2_CP1AL_1_01aOO
      // new Cfront: f2__tm__2_i__1AFZ1Z_YOeq_2_I1IOrf_2_I0I1aOO
  }


9/29/11  [EDGcpfe/12294]
GNU C++ compatibility: Move constructors and copy constructors

In GNU C++ mode with gnu_version < 40600, the front end now generates a
traditional copy constructor and copy assignment operator if one has not been
declared by the programmer even when there is a corresponding move constructor
or move assignment operator.  This behavior can be overridden with the
command-line option --rvalue_ctor_is_copy_ctor.  (See also entry of 7/2/09
for EDGcpfe/9949.  Some of the changes for EDGcpfe/11769 and EDGcpfe/11793
were misguided and have been undone.)


9/29/11  [EDGcpfe/12167]
Zero cast to void accepted for Microsoft ignored function call

Microsoft has a deprecated extension that treats a call of the constant
zero as an ignored call.  That is,

  0(x, y, z);

does nothing.  (This is used, via macros to generate the zero, as a
way to disable debug prints/calls.)  Now, the front end also accepts
zero cast to void as the zero constant:

  ((void)0)(x, y, z)


9/28/11  [EDGcpfe/12297]
GNU C++ compatibility: Packing of non-POD fields

In GNU C++ mode with gnu_version >= 30400, fields of a non-packed, non-POD
class type (or an array thereof) are not themselves subject to packing.
For example (assuming 2-byte aligned short and 4-byte aligned int):

  struct NonPod {
    NonPod() {}
    short s;
  };
  struct __attribute((packed)) PackCheck {
    NonPod np;  // This field is not packed.
    char c;
    int i;      // This field is still packed.
    char d, e;
  };  // sizeof(PackCheck) == 10

The changes for EDGcpfe/9970 (see entry of 7/27/09) were a mistaken attempt
at emulating GCC's behavior in this area: They have been deleted.


9/28/11  [EDGcpfe/12187]
Infinite recursion loop on passing non-POD class member of packed struct
by reference in GNU C++ mode

The front end got into an infinite recursion loop (and therefore eventually
ran out of stack) while processing a call in g++ mode with gnu_version
> 30400 when the parameter has a reference type and the argument being
passed is a non-POD class-typed member of a class marked as "packed".
This bug was introduced in version 4.2; see the Changes entry for
EDGcpfe/8366 (8/25/09).  Now fixed.

  struct A {
    A();
    A(const A&);
  };
  struct __attribute__((packed)) B {
    A a;
  };
  int main() {
    B* p = 0;
    A a = p->a;  // Hangs on copy constructor call here
  }


9/28/11  [EDGcpfe/12290]
Abort on GNU C __builtin_choose_expr in constant expression

In GNU C mode, the front end sometimes aborted in expr.c (near the end
of scan_gnu_builtin_pseudo_call) when processing a __builtin_choose_expr
operation with an evaluated argument that is not constant, or is a
function name, within an expression that must be constant.  Now fixed:

  int f() { return 1; }
  int g() { return 2; }
  int (*z)() = __builtin_choose_expr(1, f, g);  // Was abort, now accepted
  int ii;
  int j = __builtin_choose_expr(1, ii, ii);  // Was abort, now error


9/28/11  [EDGcpfe/12241]
GNU C++ compatibility: Function-style casts and elaborated class names

In GNU C++ mode with gnu_version < 30400, the front end now more consistently
accepts function-style casts to a type expressed using an elaborated name
(i.e., a name like "enum E" or "struct S").  For example:

  enum E { e, f };
  struct S {
    static const E x = enum E(e);  // Now accepted in some GNU C++ modes.
  };


9/28/11  [EDGcpfe/7211,EDGcpfe/8117,EDGcpfe/10322]
Microsoft compatibility: support for-each statements

In Microsoft mode, when microsoft_version >= 1400, the front end now accepts
non-C++/CLI versions of the Microsoft for-each statement.  The two basic types
of supported for-each statements are the STL-type and the array type.  In
configurations that use lowering, these for-each statements are appropriately
lowered.  See http://msdn.microsoft.com/en-us/library/ms177203.aspx
for more information on this non-standard Microsoft extension.  Here's an
example that contains both types of accepted for-each statements:

  #include <list>
  #include <iostream>
  int main() {
    std::list<char> l;
    for each (char c in "abc") l.push_front(c);
    for each (char c in l) std::cout << c;
  }


9/27/11  [EDGcpfe/12168]
Cross-reference information for nested class template declarations

The front end previously failed to produce a cross-reference entry for a class
template declared (but not defined) in another class template.  This included
the case of friend class template declarations.  For example:

  template<typename> struct F {};
  template<typename> struct S {
    template<typename> friend struct F;  // Previously, the front end did not
  };                                     // produce a cross-reference entry
                                         // this declaration.

This is now fixed.


9/27/11  [EDGcpfe/12217]
Abort on ambiguous name with __super qualification

The front end previously aborted in corresponding_base_class ("base class not
found") on the use of an ambiguous base-class name qualified with the
Microsoft-mode keyword __super.  For example:

  struct B { virtual void f(); };
  struct C1: B {};
  struct C2: C1 {};
  struct D: C2, B {
    virtual void f() {
      __super::f();  // Previously aborted in corresponding_base_class.
    }
  };

This is now fixed (the case above now triggers an ordinary ambiguity error).


9/26/11  [EDGcpfe/11681]
Missing template parameter checks on alias templates

Like class templates, alias templates only allow packs and default arguments
at the end of the template parameter list.  We now diagnose incorrect usage.

  template<typename ...T, int> using X = int;
  template<typename T = int, typename U> using Y = int;


9/22/11  [EDGcpfe/12159]
Microsoft compatibility: Predeclare std::nullptr_t

Microsoft compilers beginning with MSVC 10 (version 1600) predeclare the
symbol nullptr_t in namespace std.  The front end now does the same in
Microsoft mode.  For example:

  void f(std::nullptr_t);   // Previously diagnosed as an error


9/22/11  [EDGcpfe/12148]
Abort with complex macro expansions

In cases where a macro expansion is large and complex (using the Boost
preprocessor library, for example), the front end could abort with
"assoc_source_line_modif: bad address" in cases where a nested macro
invocation begins in one macro expansion but its closing parenthesis
appears in a containing macro expansion.  This is now fixed.  For example:

  #include <boost/preprocessor/control/if.hpp>
  #include <boost/preprocessor/comparison/equal.hpp>
  #include <boost/preprocessor/arithmetic/sub.hpp>
  #define ASDF(x) x

  // The closing parenthesis for ASDF is not in this definition:
  #define FUNC(DIM) \
    ASDF(BOOST_PP_CAT(FUNC,BOOST_PP_SUB(DIM,1))(BOOST_PP_SUB(DIM,1))

  // The closing parenthesis of ASDF is here:
  #define FUNC1(DIM) FUNC(DIM))
  #define FUNC0(DIM) z

  FUNC1(1);    // results in "z;"


9/20/11  [EDGcpfe/12165]
Microsoft compatibility: Attributes preceding linkage specifications

In Microsoft mode, the front end now accepts Microsoft attributes (enclosed
in square brackets) preceding a linkage specification.  For example:

  [Any(1)] extern "C" void f(); // Now valid in Microsoft mode (if "Any"
                                // is an acceptable attribute).


9/20/11  [EDGcpfe/12200]
Microsoft C++ compatibility: Nested classes in __interface classes

Previously, the front end did not accept nested classes in __interface
classes.  Now such nested classes are accepted.  For example:

  __interface IC {
    struct N {};  // Previously an error; now okay.
  };


9/20/11  [EDGcpfe/6226]
Microsoft C++ compatibility: __clrcall

In Microsoft modes, __clrcall is now a calling convention keyword.  It can be
validly used only in C++/CLI mode.  For example:

  void __clrcall f();  // Accepted in C++/CLI mode.  Recognized but diagnosed
                       // as an error in other Microsoft modes.


9/19/11  [EDGcpfe/12061]
Microsoft C++ compatibility: Namespace std is predeclared

In Microsoft C++ mode, the front end now predeclares namespace std.  (This was
already the case in Sun C++ mode and in GNU C++ mode.)


9/17/11  [EDGcpfe/12099]
C++-generating back end: implicit casts in pointer-to-member template arguments

The type of a pointer-to-member constant used as a template argument may
differ in qualification from the type of the corresponding non-type template
parameter.  In such cases, the C++-generating back end added an explicit
cast in the generated code to represent the implicit conversion of the
template argument.  The resulting code, however, was incorrect, because only
integral casts are permitted in template arguments.  This has now been fixed
and the cast is omitted in the generated code.  For example:

  struct A { int i; };
  template<const int A::*> struct B;
  typedef B<&A::i> b;  // Previously generated as B<(const int A::*)(&A::i)>


9/17/11  [EDGcpfe/12170]
CTORS_RETURN_THIS/DTORS_RETURN_THIS in --dump_configuration output

The CTORS_RETURN_THIS and DTORS_RETURN_THIS values were included in the
output of the --dump_configuration command line option, even though they are
not intended to be set in defines.h and cause build errors if they are set.
They have now been removed from the output.


9/15/11  [EDGcpfe/12010]
C++-generating back end: declaration/expression ambiguity with dynamic
initialization

The C++-generating back end generated a parenthesized initializer containing
a dynamic initialization in a form that could trigger the
declaration/expression syntactic ambiguity.  This has now been fixed by
adding an extra level of parentheses around such dynamic initializations.
For example:

  struct S { };
  S s((S()));  // Previously generated as "S s(S())", which declares s as
               // a function with a parameter that is a pointer to a
               // function rather than a variable initialized with S().


9/15/11  [EDGcpfe/12160]
Attributes on dependent friend function declarations

The front end previously failed to record attributes on the representation
of a dependent friend function in a class template.  For example, assuming
GNU C++ mode:

  template<typename T> struct S {
    __attribute((noreturn)) friend void f(S) {}
  };  // Previously, the attribute was ignored.  Now it is applied and
      // recorded.


9/15/11  [EDGcpfe/10811,EDGcpfe/11221,EDGcpfe/12054]
GNU C++ compatibility: Predeclaring std::type_info

In GNU C++ mode, the front end now predeclares std::type_info.  This makes
the following example valid:

  std::type_info  *pi;

(The predeclared type is incomplete.)


9/15/11  [EDGcpfe/11716]
GNU compatibility: Attribute "const" on parameters

In GNU mode, the front end now accepts the "const" attribute on parameter
declarations.  For example:

  typedef void F();
  void g(F *pf __attribute((const)));


9/15/11  [EDGcpfe/11962]
C-generating back end: subaggregate designated initializers

In C-generating back end configurations with LOWER_DESIGNATED_INITIALIZERS
set to FALSE, subaggregate designated initializers were incorrectly
generated in cases where the original source code is not fully braced.
This is now fixed.  For example,

  struct A { int i; int j; };
  struct A a[1] = { [0].i=1, [0].j=2 };

Previously, the initializer for a in this example was generated as

  { [0]={ .i=1 }, [0]={ .j=2 } }

which has the effect of initializing a[0].i to 0 instead of to 1, as
intended.


9/15/11  [EDGcpfe/11956]
Abort of GNU C redefinition of inline function

In GNU C mode, the front end sometimes accepts a redefinition of an inline
function (the first definition is ignored after the second one; see Changes
entry of 6/18/02).  However, if both definitions included an old-style
parameter declaration, or if the two definition were not compatible, the
front end was likely to abort later on.  For example:

  extern inline void f(x) int x; {}
  inline void f(x) int x; {}
    /* The second definition previously caused an abort in
       reconcile_routine_types (decls.c). */

This is now fixed.


9/15/11  [EDGcpfe/12156]
C++0x changed to C++11

All uses of C++0x, c++0x, cpp0x, and CPP0X in the source code and
documentation have been changed to C++11, etc.  The --c++0x and --no_c++0x
command-line options have been preserved (in addition to --c++11 and
--no_c++11) for compatibility purposes.  In addition, a cpp0x_mode macro
that expands to cpp11_mode has been supplied to reduce the impact on
customer code.  The following may require changes in customer code or
code that uses the front end:

- Alternate versions of the --c++11_sfinae... options have not been provided,
  so any of the --c++0x_sfinae... options will need to be changed.

- The following macros, which formerly had CPP0X in their names, have been
  changed to use CPP11.  If you use or set these macros, you will need
  make changes to use the new names:

    CPP11_IL_EXTENSIONS_SUPPORTED
    DEFAULT_CPP11_DEPENDENT_NAME_PROCESSING
    DEFAULT_CPP11_SFINAE_ENABLED
    DEFAULT_CPP11_SFINAE_IGNORE_ACCESS
    DEFAULT_CPP11_MODE


9/14/11  [EDGcpfe/9815]
Abort on GNU C-mode void return expression in presence of VLAs

In GNU C mode, the front end accepts a return expression of type void in a
function with void return type (this is a standard feature in C++ mode, but
not in C mode).  Previously, in configurations with VLA_DEALLOCATIONS_IN_IL
set to TRUE, the front end produced an invalid expression statement entry
(one with a NULL expr field) in such a function if a variable-length array
(VLA) also had to be deallocated as part of returning from the function.
This invalid statement entry usually triggered an internal error later on
(e.g., in lowering).  For example:

  void func(int n) {
    int a[n];        // VLA must be deallocated later.
    return (void)0;  // Void-expression return resulted in an invalid
  }                  // statement in the IL.

This is now fixed.


9/14/11  [EDGcpfe/11876]
Microsoft compatibility: Friends of local classes

If a local class declares a friend class, that class is looked up in the
enclosing function, and if it is not found, it is injected in the nearest
block scope.  In Microsoft mode, the injected class name was previously
always visible in that block scope (as it is in default mode, but not e.g.
in strict mode).  Now, in Microsoft mode, the injected class name is made
invisible if that name is already visible at that point.  For example:

  #ifdef GLOBAL_S
  struct S {};
  #endif
  void g() {
    struct L {
      friend struct S;
    };
    S s;  // If GLOBAL_S is true, the injected friend is invisible and this
  }       // finds ::S.  Otherwise, the injected friend is found, and this
          // is an error since that class S is incomplete.


9/14/11  [EDGcpfe/11746,EDGcpfe/11557]
"this" permitted in late-specified return types for member functions

The front end now allows references to "this" in decltype expressions
in late-specified return types in member functions, as required by
core issue 1207 (see N3282).

  struct A {
    int i;
    auto f() const -> decltype(this->i) { return 0; }  // Okay now.
  };

This feature required a small IL CHANGE: the enk_param_ref expression
kind can now be used to refer to "this" in such contexts, by
specifying a parameter number of zero.

Changes were also made in mangling.  In the IA-64 ABI, the proposed
standard mangling ("fpT") is used.  In the Cfront ABI, the mangling
is like for a parameter reference with a parameter number of zero.


9/14/11  [EDGcpfe/11910]
C++11 and Microsoft compatibility: access checking of base-specifiers

In C++11 the base-specifiers have the same access as members of the class
being defined.  We now implement the new rules in C++11 mode.  In
addition, Microsoft compilers do something in between the C++03 and C++11
rules in that access checking for names in template arguments is
apparently deferred.  As an approximation of that behavior we use the
C++11 rules in Microsoft C++ mode.

  class B { protected: class N {} };
  // now valid in C++11 and Microsoft modes (but rejected by Microsoft)
  class D: B::N, B {};

  template<class T> struct X {};
  // Accepted by Microsoft and now allowed in C++11 and Microsoft modes
  struct E: B, X<B::N> {};


9/13/11  [EDGcpfe/11995]
C++-generating back end: erroneous elaborated type specifier in class
definition

The C++-generating back end incorrectly generated a reference to a class
type within the class definition as an elaborated type specifier (i.e.,
using the class/struct/union keyword) if another declaration with the same
name as the class appears in the scope containing the class definition.
This is now fixed.  For example:

  struct S {
    S f() { return S(); }  // Both "S"s previously generated as "struct S"
  };
  typedef S S;


9/13/11  [EDGcpfe/12100]
Spurious conflict error on visibility attribute applied to member function

In GNU C++ mode, the front emitted a spurious error if the visibility
attribute (recognized when GNU_VISIBILITY_ATTRIBUTE_ALLOWED is TRUE) is
specified on a member function of a class that is defined with a different
visibility.  For example:

  struct __attribute((visibility("default"))) S {
    __attribute((visibility("hidden"))) void f();
  };  // Previously, the "hidden" visibility was diagnosed as conflicting
      // with a "previous declaration".  Now accepted: The member attribute
      // takes precedence over the class attribute (for this member).

This is now fixed: A visibility attribute on a member function takes
precedence over that on the enclosing class.


9/13/11  [EDGcpfe/11955]
GNU C++ compatibility: injection of friend classes

The injection of friend names is disabled when gnu_version >= 40100
(see 8/9/08 entry).  We have discovered that while the non-injection of
friend functions was implemented in g++ version 4.1, the non-injection of
friend classes was implemented in version 4.0.1.  We now emulate this
g++ behavior.

  struct A { void f(); }; 
  namespace N {
    class State {
       State ( A & );
       friend class A;
    };
    // following failed with --gnu_version=40001
    State::State ( A & i ) { i.f(); }
  }



9/13/11  [EDGcpfe/11994]
C++-generating back end: typedefs from different namespaces that refer
to the same type

The C++ standard allows a using-directive lookup to find two typedefs
from different namespaces that refer to the same type without considering
the lookup ambiguous.  As a result, the hidden name table processing
did not consider the "::" qualifier to be needed in examples such as
the one below, which resulted in the name being emitted as just "fptr".
The Microsoft compiler and g++ do not implement this rule of the standard,
so they reported an ambiguity when compiling the code generated by the
C++-generating back end.  We now treat a normal lookup of a name such as
fptr as ambiguous for hidden name purposes so that the "::" qualifier
is now emitted by the C++-generating back end.

  typedef int (*fptr)();
  namespace N {
    typedef int (*fptr)();
  }
  using namespace N;
  void f(::fptr x){}  // formerly emitted as just fptr


9/12/11  [EDGcpfe/12065]
C++-generating back end: parentheses in template arguments

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the
C++-generating back end sometimes omitted necessary parentheses from template
arguments in the definition of a template generated from the prototype
instantiation.  This is now fixed.  For example:

  template<bool> struct B;
  template<int X, int Y> struct S {
    typedef B<((X == 0) || (Y > 0)) == 0> tp; // previously generated as
                                              // B<((X == 0) || (Y > 0) == 0)>
  };


9/12/11  [EDGcpfe/11536]
Use of "long float" in non-pcc modes

The front end previously accepted "long float" as a synonym for "double" in
non-strict modes.  To match the behavior of modern compilers, the front end
now issues an error on "long float" in GNU modes, and issues a warning in
most other modes (it is still silently accepted in pcc mode).


9/12/11  [EDGcpfe/11641]
Duplicate cross-reference entries

Version 4.3 changed the way in which tokens are managed during disambiguation.
This change resulted in duplicate cross-reference entries in some cases.
Now fixed.

  struct A { };
  int main() {
    void (A::*p)();  // duplicate xref entry for "A"
  }


9/10/11  [EDGcpfe/12129]
Microsoft compatibility: reduced severity for error in unrecognized attribute

Because the front end does not support the full syntax of Microsoft
attributes, a spurious "expected an argument list" error could be issued
on certain forms of attributes considered "unrecognized".  This diagnostic
is no longer issued for unrecognized attributes.

  [xxx:yyy::zzz("abc")];


9/10/11  [EDGcpfe/11865]
Cast from scoped enum to floating-point type allowed

A cast from a scoped enum type to a floating-point type is now allowed,
in accordance with core issue 833.

  enum class E { E0 };
  int main() {
    double c2 = static_cast<double>(E::E0);
  }


9/9/11   [EDGcpfe/12130]
GNU C++ compatibility: injection of friend function templates

Newer versions of g++ do not inject names from friend declarations into the
enclosing namespace scope (see 8/9/08 entry).  But while they do not
inject function or class names, they do still inject function template
names.  We now emulate this behavior in g++ mode.

  class A {
    template <class T> friend void f(T) { }
  };
  int main() {
    f(1);  // now allowed in g++ mode
  }


9/8/11   [EDGcpfe/12120]
Alignment of overlong bit fields and 128-bit integer types

The IA-64 ABI specifies that the alignment of overlong bit fields (i.e.,
bit fields whose specified length is longer than that of the specified type)
is the alignment of the largest integer type that would be accommodated by the
bit field length.  For a class type like:

  struct S {
    int i;
    long long b: 130;
  };

this could result in a different layout when 128-bit integer types are enabled
(see Changes entry of 8/2/11) since "long long" is commonly aligned at 8-byte
boundaries whereas 128-bit integers are 16-byte aligned.  The front end
therefore ignores 128-bit integer types when laying out overlong bit fields in
the IA-64 ABI, unless the bit field type is specified as a 128-bit type.  When
emulating GNU ABI bugs, 128-bit integer types are ignored altogether when
laying out overlong bit fields.  For example, assuming "long long" is 8-byte
aligned:

  struct X {
    int i;
    __int128 b: 130;  // 8-byte aligned when emulating GNU ABI bugs;
  };                  // 16-byte alignment otherwise.

This matches the somewhat surprising behavior of GCC.


9/7/11   [EDGcpfe/12098]
Abort in il_to_str.c related to template argument based on array

The front end aborted in form_array_declarator in il_to_str.c while
trying to generate the source form of an array (e.g., for
C++-generating back end output) when the array type comes from
a template parameter deduced from an array whose size if a constant
variable that is local to a function.  Now fixed.  The following
aborted in a C++-generating back end version with --g++ -tall:

  void f(const char*);
  template<typename T> void g(const T&) {
    f(__PRETTY_FUNCTION__);
  }
  void h() {
    const int N = 3;  // Local const variable
    int arr[N];       // Array with size based on local const variable
    g(arr);           // T of g deduced from that array type
  }


9/6/11   [EDGcpfe/12029]
Microsoft C++ compatibility: void parameters in template instantiations

In Microsoft C++ mode, the front end sometimes accepts a function declarator
of the form "(T)" where T is a template parameter that is instantiated with
T=void (see entry for EDGcpfe/6674, EDGcpfe/8978, EDGcpfe/9401, EDGcpfe/9430
on 12/11/08).  Additional cases are now supported.  For example:

  template<typename T, void (*F)(T)> struct C {};
  template <void (*F)(void)> struct M {
    typedef C<void, F> MF;  // Previously triggered an error for attempting
  };                        // to substitute T=void in void (*F)(T); now
                            // accepted in Microsoft mode.


9/6/11   [EDGcpfe/12032]
Microsoft compatibility: Names qualified with the name of the current class

In Microsoft bugs mode, the front end sometimes sometimes ignores a name
qualifier "Q::" in a name of the form "Q::X" when Q denotes the class
currently being defined.  This treatment as now been extended to additional
contexts, making e.g. the following example valid in Microsoft C++ bugs mode:

  class C;
  struct S {
    operator S::C*();  // Now accepted in Microsoft bugs mode even though
  };                   // there is no S::C ("S::C" is treated as just "C").


9/6/11   [EDGcpfe/12109]
Microsoft compatibility: memory region issue with attributes in function scope

If a Microsoft attribute appeared in a function scope, the attribute was
allocated in the file scope, but appeared on the function scope attributes
list, and could point to a function scope source sequence entry.  This could
result a variety of problems including an IL write/read error in C++-generating
back end versions.  Now fixed.  The problems would occur whether or not the
attribute was actually valid.

  int main() {
    [xxx];
  }


9/1/11   [EDGcpfe/11844]
Missing error on definition of friend function with template arguments

In Microsoft mode, a friend function declaration could previously be a
definition even when the declaration is for a specific instance of a function
template (i.e., template arguments are specified).  Now, such cases are
accepted only when microsoft_version is 1300.  For example:

  template<class T> void f();
  struct S {
    friend void f<int>() {}
                         // Previously accepted in all Microsoft C++ modes.
  };                     // Now only when microsoft_version == 1300.


8/31/11  [EDGcpfe/11842]
Missing error on invalid declarator in Microsoft mode

In Microsoft mode, the front end failed to diagnose an attempt to use the
name of a class template instance as a member function name.  For example,

  template<typename T> struct S {};
  class C {
    void S<int>();  // In Microsoft mode, the front end previously failed to
  };                // issue an error here.

This is now fixed.


8/26/11  [EDGcpfe/12056]
Bugs in expansion of increment/decrement of Microsoft property references

The expansion for an increment or decrement operator applied to
a Microsoft property reference was not always done correctly.
The result of the operation was considered to be the result of
the "put" function call, rather than the value (incremented or not)
of the property.  Also, if the underlying type of the property is
a class, overloaded operator+ or operator- functions were not
properly found and used (an error was issued instead).  Now fixed.

  struct A {
    __declspec(property(get=iget,put=iput)) int i;
    int idata;
    int iget() { return idata; }
    void iput(int p) { idata = p; }
  } a;
  extern "C" int printf(const char *, ...);
  int main() {
    int ii = a.i++ + 5;  // Formerly got error, now accepted
    printf("ii = %d, a.i = %d\n", ii, a.i);
    return !(ii == 5 && a.i == 1);
  }


8/26/11  [EDGcpfe/11874]
Microsoft compatibility: lookup of friend class templates

When looking up the name of a class template in a friend template declaration,
the Microsoft compiler considers names declared outside of the nearest
enclosing namespace.  We now emulate this in Microsoft mode.

  namespace N {
    template<typename T> class A;
    namespace M {
      template<typename T> void f(const T& b) {}
      template<typename U> class B {
        // The following finds N::A.  Formerly, it declared a new N::M::A
        // which was then found by the friend declaration in N::A.
        template<typename V> friend class A;
      };
    }
    template<typename T> class A : public M::B<T> {
      friend void M::f<A<T> >(const A<T>& b);
    };
  }
  int main() {
      N::A<int> a;
  }


8/25/11  [EDGcpfe/12085]
Microsoft compatibility: changes in unknown attribute diagnostic

The diagnostic for an unknown Microsoft attribute has been reduced
from an error to a warning in modes where RECOGNIZE_MICROSOFT_ATTRIBUTES
is TRUE (it was already a warning otherwise).  In addition, the attribute
name is no longer included in the diagnostic because the name fill-in
mechanism was not capable of handling compound attribute names (i.e., those
containing ":" or "::").

  [xxx] int i;


8/25/11  [EDGcpfe/10939,EDGcpfe/11622,EDGcpfe/11883,EDGcpfe/11622,
          EDGcpfe/11967, EDGcpfe/12073]
Microsoft C++ compatibility: Attributes on templates

In Microsoft C++ mode with microsoft_version >= 1400 the front end now accepts
bracketed attributes (see Changes entry of 7/30/03) on function templates and
class templates.  For example:

  struct S {
    template <class>
    [returnvalue:SA_Post(MustCheck=SA_Yes)]  // Now accepted in Microsoft
    int f() {                                // C++ mode.
      return 0;
    }
  };

See also the related Changes entry of 7/6/11.


8/17/11  [EDGcpfe/12048]
Microsoft bug: cast to non-reference type implemented by conversion function
returning reference produces lvalue

MSVC produces an lvalue result for a cast to a non-reference type if
the cast is implemented by calling a conversion function and the
conversion function returns a reference (the standard says the result
should be an rvalue).  We now emulate that in Microsoft bugs mode.

  struct A {
    operator int&();
  };
  int main() {
    A a;
    (int)a = 1;  // Accepted by MSVC, should be an error
  }


8/17/11  [EDGcpfe/12036]
Microsoft bug with dropping cv-qualifiers on lvalue returned from "?"

The Microsoft bug of dropping cv-qualifiers on the result of a "?"
operator if it is an lvalue of non-class type was apparently fixed in VC8.
Accordingly, we have turned off the emulation of that bug when
microsoft_version >= 1400.

  int f();
  const int i = f();
  const int j = f();
  int main() {
    (1 ? i : j) = 1;  // Should get an error, and now does when microsoft
                      // version >= 1400.
  }

8/17/11  [EDGcpfe/12033]
GNU C++ __builtin_offsetof did not work right with anonymous unions

The __builtin_offsetof operator available in g++ mode did not produce
correct results when asked to compute the offset of a member of an
anonymous union.  Now fixed.

  struct S {
    struct {
      char c;
      union {
        char ar[12];
      };
    } t;
  };
  int gar[__builtin_offsetof( struct S, t.ar ) ? 1 : -1];
           // Previously an error because offset of t.ar was computed as 0


8/10/11  [EDGcpfe/12011]
Deprecated string literal conversion not allowed on result of "?" in parens

The (2003) C++ standard allows a const string literal to be converted
to "char *", as a deprecated conversion:

  char *p = "a";

As an extension, the front end allows this also on the result of a
"?" operator:

  char *p = 1 ? "a" : "b";

However, in versions that have PARENS_IN_IL TRUE, the equivalent case
enclosed in parentheses did not work:

  char *p = (1 ? "a" : "b");

That's now fixed, and that case is now accepted.


8/9/11   [EDGcpfe/11921]
End-of-construct source sequence entries for local static variables

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, the front end sometimes generates
"end-of-construct" source sequence entries for local variable declarations
(when such declarations embed other declarations).  However, that entry was
mistakenly allocated in function-scope memory even for local static variables
(whose entries are recorded in file-scope memory).  For example:

  void g() {
    static int v[sizeof(union {})]; // Accepted in some GNU modes. Previously,
  }                                 // the end-of-construct entry for v was
                                    // recorded in function-scope memory.  Now
                                    // it is allocated in file-scope memory.

This is now fixed: The entry is now recorded in file-scope memory (on a
"sublist" -- see Changes entry of 3/21/94).


8/7/11   [EDGcpfe/11914, EDGcpfe/10029]
universal-character-names in narrow string literals

The way the front end handles universal-character-names in narrow string
literals has changed.  Previously the Unicode value of a
universal-character-name appearing in a narrow string literal was truncated
(with a warning) to the least-significant byte and represented as a single
character in the value.  Now, in Microsoft mode (assuming
NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is set to TRUE) the value is
the corresponding character in the system default multibyte character set
(see the entry for EDGcpfe/11712 below), and in all other cases the value
is the UTF-8 representation of the Unicode character.  For example, the
string "\u20AC" (the Euro symbol) was previously equivalent to "\0xAC"; it
is now equivalent to "\0xE2\0x82\0xAC" except in Microsoft mode.  In
Microsoft mode the value depends on the system locale; in a locale
designating Windows code page 1252, for instance, the string is equivalent
to "\0x80".


8/6/11   [EDGcpfe/11992]
Microsoft compatibility: bug on binding reference to less cv-qualified pointer

MSVC had a bug that allowed binding a reference to a pointer type to
a pointer whose underlying type is less cv-qualified.  That was 
fixed in MSVC 8, so our emulation of that is now turned off when
microsoft_version >= 1400.

  typedef const int *P;
  int main() {
    int *p;
    P &r = p;  // Now gets an error
  }


8/6/11   [EDGcpfe/11913]
Microsoft compatibility: string literals in Unicode-encoded files

When string literals are translated from a Unicode encoding to native
multibyte characters (see the entry for EDGcpfe/11712 below), the type given
by the front end to the string literal reflected the length of the string
before the translation.  This is now fixed.


8/6/11   [EDGcpfe/11951]
Abort with #define embedded inside macro argument list

In configurations in which FULLY_RESOLVED_MACRO_POSITIONS is TRUE, the
front end sometimes aborted with an assertion failure
("clone_macro_text_map_entries offset not found" or
"clone_macro_text_map_entries map entry pointer past end of entries") when
processing a macro invocation in which a #define appears within the macro
argument list.  This is now fixed.  For example:

  #define M(a, b) void f(int a, int b);
  #define A x
  M(A,
  #define B y
  B)


8/4/11   [EDGcpfe/11983]
C++-generating back end: hidden names in the unnamed namespace

When a class, struct, union, or enumeration member of the unnamed namespace
is hidden within a scope nested within the unnamed namespace, the hidden
type must be referred to using an elaborated-type-specifier.  The
C++-generating back end previously failed to do so.  This has now been
fixed.  For example:

  namespace {
    struct A { };
    struct B {
      struct A A;   // Previously omitted the "struct" keyword
    };
  }


8/4/11   [EDGcpfe/11985]
Detecting non-existent directory on some Windows systems

On Windows systems, when compiling with EDG_WIN32 set to TRUE and when the
Unix-like header file <sys/stat.h> isn't available, the is_directory utility
had returned TRUE if the specified directory didn't exist.  A change has been
made to return FALSE in that case.  This isn't a problem for most Windows
configurations because <sys/stat.h> is available.  Users can tell if their
configuration is affected by specifying a non-existent directory with the
--pch_dir command line option which should result in an "invalid PCH directory"
error.


8/2/11   [EDGcpfe/8739,EDGcpfe/9831,EDGcpfe/9890,EDGcpfe/11024,EDGcpfe/11227]
GNU compatibility: 128-bit integer types

When the new configuration macro INT128_EXTENSIONS_ALLOWED is set to TRUE, the
front end now includes 128-bit integer types in GNU modes.  These types can be
named via the predeclared typedefs __int128_t (a signed type) and __uint128_t
(an unsigned type) or via the GNU attribute "mode(TI)".  The type specifier
__int128 is also accepted when gnu_version >= 40600: It can be combined with
the unsigned and signed modifiers.


8/1/11   [EDGcpfe/11900]
C++-generating back end: spurious "template" keyword in partial specialization

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end incorrectly added a "template" keyword in the
definition of a partial specialization of a nested class template.  This is
now fixed.  For example:

  template<typename T> struct Outer {
    template<typename U, typename V> struct Inner;
  };

  template<typename T> template<typename U>
  struct Outer<T>::Inner<int, U> { };  // Previously generated as
                                       // Outer<T>::template Inner<int, U>


8/1/11   [EDGcpfe/11957]
C-generating back end: line numbers for nonstatic member functions

In configurations with gcc_is_generated_code_target and IA64_ABI set to
TRUE, the C-generating back end inserts alignment directives preceding the
definition of nonstatic member functions (see the 3/20/07 entry below).
This alignment directive appeared after the directive setting the
corresponding source position and thus caused the effective line number of
the beginning of the function to be incorrect.  The order of these
directives has now been changed to provide better correspondence with the
position of the function in the source code.


8/1/11   [EDGcpfe/11918, EDGcpfe/11935]
Non-ASCII macro names

The front end previously failed to translate the name of a macro being
defined into its internal canonical form when it contained multibyte
characters.  A reference to that name, however, looked up the identifier
using its canonical form and thus failed to find it in the symbol table.
This has now been fixed.  For example:

  #define f«e9» 2  // second character is Latin-1 e with acute accent
  int i = f«e9»;   // Previously "undefined identifier" error

Note: The above example must be decoded using the edg-changes-example tool.


7/29/11  [EDGcpfe/11953]
Abort on use of stdarg operation with multiple translation units

When simultaneously compiling multiple translation units, the C-generating
back end sometimes aborted when rendering uses of stdarg operations.  This is
now fixed.


7/28/11  [EDGcpfe/11958]
Improved hashing of template instances

The front end builds hash tables to look up instances of class
templates.  The hashing mechanism has been improved to better handle
template arguments that are function types, pointer to member types,
or template parameters.  It has also been improved for cases that have
multiple nontype template parameters of the same type (e.g., template
argument lists such as "<1,2,3>").  These changes can result in a significant
improvement in certain cases.  For example, for a Boost case that created
a large number of instantiations based on function types, the compilation
time was reduced by about 5%.


7/28/11  [EDGcpfe/11940]
GNU compatibility: Inline functions with noinline attributes

Previously, in GNU modes, a function declaration that was both inline and
noinline was recorded as not being an inline function (a warning is emitted).
Now, such a function is recorded as both "inline" and "noinline" (a warning is
still emitted).  This ensures that the code generated for the function
definition is treated like an inline functions for purposes other than
actually inlining -- in particular, such a function can be defined in multiple
translation units.

This is a slight IL CHANGE: Back ends that only inline functions marked
"inline" must now explicitly check the never_inline flag to avoid actually
inlining "noinline" functions.


7/27/11  [EDGcpfe/11767]
Configurable entry_number field in IL entry prefix

Each IL entity has an an_il_entry_prefix structure that precedes the IL entity
in memory.  The entry_number field in this structure is used (in configurations
where IL_SHOULD_BE_WRITTEN_TO_FILE and ALTERNATE_IL_FILE_FORMAT are both TRUE)
to enumerate each IL entry in the IL file.  In some very complicated programs,
it is possible that the default size of this field (typically 26 bits) may not
be sufficient to address all of the IL entries (in which case the front end
reports "program too large or complicated to compile").  A new configuration
macro, TYPE_FOR_PREFIX_ENTRY_NUMBER, has been introduced to allow configuration
of the underlying type for the entry_number bit field (to, say, an unsigned
64-bit host type).  The default value for this new macro is "unsigned int"
(except when EDG_MSDOS is TRUE, in which case it is "unsigned long"), which
corresponds to the old behavior.


7/27/11  [EDGcpfe/11936]
Incorrect IL flag for nested class template instantiations

The flag nested_class_defined_outside_of_parent was incorrectly set to TRUE
for instantiations of nested class templates defined in their parent class'
definition.  For example:

  struct S {
    template<typename T> struct N {};
      // "nested_class_defined_outside_of_parent" was mistakenly set to TRUE
      // for S::N<T>.
  };

This is now fixed.  (This problem was introduced by the removal of placeholder
types; see Changes entry of 5/18/10 for EDGcpfe/10646.)


7/26/11  [EDGcpfe/11942]
Useless code in set_routine_declared_type

Some useless code has been removed from set_routine_declared_type.  (The code
became useless as a result of the changes for EDGcpfe/10110 -- see the Changes
entry of 9/17/09.)


7/26/11  [EDGcpfe/11943]
Missing diagnostic on invalid C++0x attributes in GNU C++0x mode

In some GNU C++0x modes (--g++ --c++0x) the front end accepts GNU attributes
after a parenthesized initializer.  It accidentally also silently accepted
(and ignored) C++0x-style attributes that followed the GNU attributes in these
modes.  For example:

  int i(3) __attribute((used)) [[]];  // Previously accepted in GNU C++0x
                                      // mode; now an error.

This is now fixed (an error is issued).


7/22/11  [EDGcpfe/11934]
Assertion failures in mangling with PROTOTYPE_INSTANTIATIONS_IN_IL

In configurations where both PROTOTYPE_INSTANTIATIONS_IN_IL and
MANGLE_ALL_NAMES are TRUE, an unnamed type in a class template could result
in an assertion failure (mangled_class_encoding: tptk_member has no name);
for example (with --g++):

  template <class T> struct A {
    struct {
      int i;
    } s;
    int f() { return s.i; }
  };

Also, template parameters used in certain expressions had also caused
assertion failures (mangled_encoding_for_type: bad tk_template_param kind);
for example (with --g++):

  template <int I> struct A {
    typedef int X;
  };
  template <class T> int f(T t) {
    return A<sizeof(*t)>::X();
  }

These failures had occurred in both the Cfront and IA-64 ABIs and are now
fixed.


7/21/11  [EDGcpfe/11929]
C-generating back end: use of typedef before it is defined

In some complex programs, the C-generating back end could put out a reference
to a typedef for an array type before putting out the definition of the
typedef, resulting in code that could not be compiled by the target C
compiler.  This has now been fixed.


7/20/11  [EDGcpfe/11939]
Spurious errors following error in template declaration

Version 4.3 introduced a problem that could result in spurious errors
or warnings following other errors in template declarations.  This occurred
rarely and typically involved syntax errors in the template parameter
clause portion of the template declaration.  Now fixed.  The example
below is expected to get two errors on the static data member
definition.  In version 4.3 it would also get spurious "warning:
parsing restarts here after previous syntax error" pointing to the ";"
on line 4.


  template <class T> struct A {
    template <class U> struct B {
      static char* c;
    }; // line 4
  };
  template <class T> <class U> char* A<T>::B<U>::c = "hello";


7/20/11  [EDGcpfe/11937]
Error message when reading a PCH file that is incomplete

When using a precompiled header file that is incomplete (presumably because
another process is currently writing to it), a catastrophic error
(check_if_fill_in_used: provided diagnostic fill-in was not used) had been
issued.  Now, a more appropriate warning diagnostic is used (and the PCH
file is ignored).


7/19/11  [EDGcpfe/11932]
Memory corruption during preprocessing

The calculation of the amount of space available in the macro buffer during
preprocessing was faulty, leading to undetected buffer overflows and
consequent memory corruption while processing some extremely complex
patterns of macro invocations (such as those found in the Boost
preprocessor library, for example).  This is now fixed.


7/18/11  [EDGcpfe/11906]
Assertion failure during inlining

In Cfront configurations that use inlining, when NEW_CAN_BE_FOLDED_INTO_CTOR
is TRUE and LOWERING_NORMALIZES_BOOLEAN_CONTROLLING_EXPRESSIONS is FALSE,
inlining of some constructor functions had caused an assertion failure
("remap_var_for_inlining: wrong kind of remap").  For example (with --g++
--no_exceptions):

  struct B {
    B() {}
  };
  struct D : B {
    D() : B() {}
  } d;


7/18/11  [EDGcpfe/11924]
Change in order of return type substitution can cause errors

Version 4.3 changed the order in which types were substituted in templates.
Formerly, the return type was substituted before the function parameters.
In 4.3 the return type was substituted after the function parameters to
handle trailing return types.  This could cause hard errors in
cases where SFINAE is supposed to discard a function based on the return
type.  Now, only trailing return types are substituted after the
parameter list.  In other words, the types are substituted in the order
in which they appear in the source.  With version 4.3, the example below
causes the instantiation of A<int>, which then results in an error on
the "T::Y" in the typedef.

  template <typename T> struct A { typedef typename T::Y Y; };
  template <typename T> typename T::X f(T, typename A<T>::Y);
  void f(...){}
  int main() {
    f(1, 2);
  }


7/15/11  [EDGcpfe/11928]
GNU compatibility: Calling convention attributes

When GNU_X86_ATTRIBUTES_ALLOWED is TRUE, the front end accepts the "cdecl" and
"stdcall" attributes.  Previously, however, the function types resulting from
this attributes were not considered distinct -- this is now changed.  As a
consequence, a diagnostic is issued when redeclaring a function with a
different explicit calling convention (an error in GNU C mode, a warning in
GNU C++ mode; this matches GCC behavior).  For example:

  __attribute((cdecl)) void f(int);
  __attribute((stdcall)) void f(int) {}  // An error in GNU C mode; a warning
                                         // in GNU C++ mode.

Another consequence is that partial specialization for distinct calling
conventions are now possible.  For example:

  template<typename T> struct S;
  template<typename T> struct S<__attribute((__cdecl__)) T (*)()> {};
  template<typename T> struct S<__attribute((__stdcall__) T ()*)()> {};
    // Now accepted in GNU C++ mode (previously, a redefinition error).

In principle, the front end can handle overloading functions distinguished
only by the calling convention of the parameters/arguments, but the supported
ABIs do not encode the calling convention in mangled names.  For example:

  void f(__attribute((cdecl)) void (*pf)()) {}
  void f(__attribute((stdcall)) void (*pf)()) {}
    // Accepted by the front end, but likely to result in linker errors or
    // back-end errors because the mangled names of both functions are
    // identical.

This also matches GCC behavior.


7/14/11  [EDGcpfe/11923]
Call in decltype in member template declaration treated as nondependent

If a member template declaration contained a dependent function call in a
decltype (or other similar context) the call was correctly marked as
dependent during the prototype instantiation of the enclosing class
but could later be marked as non-dependent when the member template
declaration was rescanned as part of a real instantiation of the enclosing
class.  This could cause the incorrect function to be called or, as in
the example below, result in spurious errors (note that a mode in which
dependent name processing is done is required to observe the error).  Now
fixed.

  template<class T> T& f();
  template<bool, class T, class... Args> struct A;
  template<class T, class... Args> struct A<true, T, Args...> {	
    template<class U> static auto g(int)
			-> decltype(U(f<Args>()...), int());
    typedef decltype(g<T>(0)) type;
  };
  struct C {};
  class D {};
  struct B { B(C, const D&) {} };
  A<true, B, C, D> x;


7/14/11  [EDGcpfe/11895]
Lowering of variable types with VLA components

Previously it was possible for variables with a VLA component type (i.e.,
as a parameter) to escape to the back end with a VLA type even when
LOWER_VARIABLE_LENGTH_ARRAYS was TRUE.  A change has been made to traverse
all variable types (when LOWER_VARIABLE_LENGTH_ARRAYS is TRUE) to ensure
that these types are properly lowered.  For example:

  int (*f)(int (*a)[*]);

now lowered (with --c99 and when LOWER_VARIABLE_LENGTH_ARRAYS is TRUE):

  int (*f)(int *a);

A change was also made to suppress the VLA type traversal when no VLA types
have been seen in the translation unit.


7/14/11  [EDGcpfe/11925]
C++-generating back end: ">>" in template arguments

The change for EDGcpfe/11762 caused the C++-generating back end sometimes
to generate a template non-type argument containing a ">>" operator without
the parentheses necessary to prevent it from being interpreted (by C++0x
rules) as the closing delimiter of the template argument list.  This is now
fixed.  For example:

  template<int N> struct A { };
  template<int N> struct B {
    A<(N >> 1)> m;    // Previously sometimes generated as A<N >> 1>
  };


7/13/11  [EDGcpfe/11525]
GNU compatibility: Effect of attribute gnu_inline in GNU C++ mode

When a function is defined with the gnu_inline attribute in GNU C++ mode, the
front end now sets a new flag definition_for_inlining_only on the associated
routine entry, indicating that the function body should only be used for
inlining and not be emitted as callable code.  This flag in turn is used to
decide whether an inline function should be "instantiated" when
INSTANTIATE_EXTERN_INLINE is TRUE.  For example:

  __attribute((gnu_inline)) inline void f() {}
  int main() {
    void (*pf)() = &f;  // Requires callable code for f.
    pf();
  }

Compiling and linking just this code (in GNU C++ mode) should now result in a
linker error since no definition of f will be emitted.  The new flag is also
set for C99 "inline definitions", Microsoft-mode "dllimport" inline functions,
and GNU C-mode "extern __inline" functions; i.e., it is set whenever the
source declarations indicate that an inline function definition should not be
emitted as a standalone function by a back end.


7/12/11  [EDGcpfe/7957,EDGcpfe/11897]
GNU compatibility: increment/decrement on expressions with complex type

GNU allows (both pre- and post-) increment and decrement operations on
expressions with complex type.  These operations have the effect of increasing
or decreasing the "real" component by 1.0 (of the appropriate type) while
leaving the imaginary component unchanged (i.e., adding/subtracting 1.0+0.0i).
This is now allowed in the front end in both C and C++ GNU emulation modes
and lowered when LOWER_COMPLEX is TRUE.  For example:

  void g() {
    _Complex long double l = 0.0+1.0i;
    _Complex double d = 0.0+1.0i;
    _Complex float f = 0.0+1.0i;
    --l;
    d--;
    ++f;
    (d=f)++;    // only in C++ mode
  }


7/11/11  [EDGcpfe/7846]
Honoring determined function in nondependent call, with dependent base class

In modes that do dependent name lookup but also allow name lookup to
find unqualified names in dependent base classes (e.g., g++ mode with
gnu_version >= 30400), sometimes a function determined for a
nondependent call during the prototype instantiation was not used
during an actual instantiation.  This happened when a nonstatic member
function in a dependent base class was found by the corresponding
lookup in the real instantiation.  Now fixed.

  extern "C" int printf(const char*,...);
  struct B {
    int foo() { printf("Wrong\n"); return 1; }
  };
  int foo() { printf("Right\n"); return 0; }
  template <class T> struct C : public T {
    int caller() { return foo(); } // This should be ::foo, not B::foo.
  };
  int main() {
    C<B> c;
    return c.caller();
  }


7/11/11  [EDGcpfe/11905]
Possible reference to freed memory with MAKE_FRONT_END_CALLABLE

When using MAKE_FRONT_END_CALLABLE, if a compilation was terminated before
the front end was fully initialized (i.e., by a command-line error),
lexical_wrapup could make use of the freed input stack from a previous
compilation.  This could result in an abort or some kind of internal error.
Now fixed.


7/11/11  [EDGcpfe/11903]
Incorrect diagnostic count with MAKE_FRONT_END_CALLABLE

The error count at the end of a compilation could be incorrect when using
MAKE_FRONT_END_CALLABLE if a command-line error occurred after a compilation
in which diagnostics were issued.  Now fixed.


7/9/10   [EDGcpfe/11893]
g++ compatibility: ability to cast bound member function pointers to pointer

g++ 4.4.0 and later allow nonstandard casts of a bound
pointer-to-member function to "void *" or a pointer to function type.
The front end now emulates that behavior in GNU C++ modes when
gnu_version >= 40400.  Two new expression operators
(eok_dot_pm_func_ptr and eok_points_to_pm_func_ptr) have been added
(IL CHANGE).  Here's an example:

  struct A {
    void f() {}
  };
  struct B : A {};
  int main() {
    void (A::*amf)() = &A::f;
    void (B::*bmf)() = &B::f;
    A a;
    B b, *pb = &b;
    return !(reinterpret_cast<void *>(a.*amf) ==
             reinterpret_cast<void *>(pb->*bmf));
  }


7/8/11   [EDGcpfe/11712]
Microsoft compatibility: string literals in Unicode-encoded files

When processing a string literal appearing in a Unicode-encoded source
file, the Microsoft compiler translates each character from Unicode to the
corresponding character in the system default locale character set.  The
front end previously used the UTF-8 encoding of these characters in the
value of the string constant.  When
NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is set to TRUE, in
--microsoft mode the front end now performs the same translation as the
Microsoft compiler.


7/8/11   [EDGcpfe/11823]
GNU-mode built-in vector function corrections

The Changes entry of 3/3/11 (for EDGcpfe/11429) mentions how a change of type
was made for the built-in vector functions __builtin_ia32_loadhps,
__builtin_ia32_loadlps, __builtin_ia32_storehps, and __builtin_ia32_store_lps
when gnu_version >= 40000.  The version value for the change was unfortunately
incorrect: The change now applies when gnu_version >= 40400 instead.


7/7/11   [EDGcpfe/11889]
Identifier characters in Unicode source

When processing source files written in a Unicode encoding (with
UNICODE_SOURCE_SUPPORTED set to TRUE), the front end previously determined
whether a character in the range 0x80-0xff is an identifier character or
not using the default locale or the one specified by
LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED, based on the assumption that
this locale includes the ISO Latin-1 encoding.  On some platforms with
defective locale support and/or in some locales, however, this could result
in incorrect handling of characters in the upper half of ISO Latin-1 and
spurious "unrecognized token" errors.  The front end has now been changed
to use the specification of identifier characters from Annex E.1 of the C++
Standard (ISO/IEC 14882:2011), regardless of the locale in effect.  (This
table differs slightly from the one in Annex D in the C99 Standard, ISO/IEC
9899; however, the C Standard is currently under revision and the new C
Standard is expected to include the same settings as the C++ Standard.)
For example:

  int risqu«e9»;   // Last character is e with acute accent, previously
                   // treated as a non-identifier character in some
                   // unusual configurations.

Note: The above example must be decoded using the edg-changes-example tool.


7/7/11   [EDGcpfe/11888]
Binding a reference to const volatile to an rvalue in overload resolution

The front end has been updated for a subtlety in the overload
resolution rules for parameters that are references to const volatile.
In the C++0X standard, an attempt to bind such a parameter to an
argument that is an rvalue causes the function to be not viable.  The
2003 standard left the function as viable, and an error would be
issued if the function was selected.

  extern "C" int printf(const char*, ...);
  void g(const volatile int&) { printf("FAILED\n"); }
  void g(...) { printf("PASSED\n"); }
  int main() {
    g(int());  // Formerly got an error; now, selects the g(...) version
  }


7/6/11   [EDGcpfe/11551,EDGcpfe/11701,EDGcpfe/11816]
Microsoft C++ compatibility: Attributes on member functions

In Microsoft C++ mode the front end now accepts bracketed attributes (see
Changes entry of 7/30/03) on member functions of class templates.
For example:

  template<typename T> struct X {
    [returnvalue:SA_Post(MustCheck=SA_Yes)] int* f(T *x);
              // Attributes are now accepted here.
  };
  S<int> s;

In addition, such attributes are now also accepted on out-of-class member
function definitions.  For example:

  struct S { int f(); };
  [returnvalue:SA_Post(MustCheck=SA_Yes)] int S::f() { return 0; }
              // Attributes are now also accepted here.


7/6/11   [EDGcpfe/11873]
GNU compatibility: ELF visibility and friends

In GNU C++ mode, the front end previously applied the ELF visibility of the
enclosing class to friend function and friend class declarations.  However,
that does not match the behavior of GCC and is now no longer done.
For example:

  struct __attribute__ ((visibility("hidden"))) S {
    friend void f();
  };
  void f() {}  // No longer a "hidden" function.


7/6/11   [EDGcpfe/11849]
Removal of DEFAULT_CHAR16_T_AND_CHAR32_T_ARE_KEYWORDS configuration macro

The recently added (see Changes entry of 6/17/11) configuration macro
DEFAULT_CHAR16_T_AND_CHAR32_T_ARE_KEYWORDS has been removed and the
DEFAULT_ULITERALS_ENABLED macro is now used in its place.  Using the same
configuration macro as the initial value for both uliterals_enabled and
char16_t_and_char32_t_are_keywords reduces the likelihood that these global
variables are mis-configured.


7/6/11   [EDGcpfe/11881]
EDG_WIN32 missing in configuration output

The configuration macro EDG_WIN32 was missing from the output produced for the
command-line option --dump_configuration.  This is now fixed.


7/5/11   [EDGcpfe/11495,EDGcpfe/11860,EDGcpfe/11833]
Additional C++0x type traits helpers

When type traits helpers are enabled (see entry of 3/21/06), the front end
now accepts additional type trait pseudo-functions: __is_literal_type,
__is_trivially_copyable, __is_constructible, __is_nothrow_constructible,
__has_trivial_move_constructor, __has_trivial_move_assign,
__has_nothrow_move_assign, and __underlying_type.  The latter produces the
underlying integer type of an enumeration type.  The other pseudo-functions
are boolean predicates testing for C++0x language concepts (usually supporting
standard library type traits templates).  Some of these pseudo-functions (like
__is_literal_type) will apply to a broader class of types when additional
C++0x features (like the constexpr specifier) are implemented in the future.


7/2/11   [EDGcpfe/11826]
Conversion to any cv-qualified version of pointer for first operand of ->*

The search for a conversion from a class to a pointer to match the
first operand of a "->*" operator now considers conversion functions
to any cv-qualified version of the necessary pointer type.  For
example, in the following, the conversion to "pointer to const C"
is now considered, where previously the front end only looked for
a conversion to "pointer to C".

  struct C {};
  struct W {
    operator const C*() const;
  };
  struct X {
    typedef void (C::*pmf)() const;
    pmf f_;
  };
  void f() {
    X* xp = 0;
    W w;
    (w->*xp->f_)();  // Now accepted
  }

The implementation of this change includes a fairly large reworking of
the many context flags that were being passed into conversion routines.
There is now a bit-set of those, a_conv_context_set, so that a single
argument can be passed around instead of a cluster of individual flags.


7/1/11   [EDGcpfe/11864]
Internal error on friend template declaration in local class

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the front
aborted with an internal error in get_scope_for_list (il.c) when processing a
friend function template declaration in a local class (which is an invalid C++
construct).  For example:

  void f() {
    struct S {
      template<typename T> friend void g(T);  // Erroneous code previously
    };                                        // triggered an internal error
  }                                           // in some configurations.

This is now fixed.


7/1/11   [EDGcpfe/11466]
Incorrect namespace context when using get_definition_of_class

For customers that have provided their own code that makes use of the
hooks for lazy loading of classes (see 1/29/10 entry), the namespace
lookup context was sometimes not set properly when loading classes
defined in namespaces.  Now fixed.


6/30/11  [EDGcpfe/11811]
Diagnose invalid universal-character-names (UCNs)

A change has been made to issue a warning (error in strict mode) when
the hexadecimal value for a universal-character-name exceeds the range of
valid Universal Coded Character Set code points (i.e., is greater than
0x10FFFF).  This change affects both C and C++ modes.  The rules for validating
a UCN are slightly different between C++98/C++03 and C++0x; a change was made
to use the C++0x rules when U-literals are enabled in C++ mode (see the Changes
entry of 6/17/11).  Here's an example that results in the new diagnostic (with
--uliterals or --c++0x):

  unsigned long u = U'\U12345678'; // now gets a warning (error in strict mode)


6/29/11  [EDGcpfe/11815]
Infinite loop on function definition after friend declaration in GNU mode

In GNU C++ mode, a friend declaration in an extern "C" block that uses a
qualified name to refer to a namespace function originally not declared with
with extern "C" previously triggered an error in GNU C++ mode (and in other
modes too).  If a non-"extern C" definition of the friend function followed,
the front end entered a non-terminating loop.

  namespace N { void f(); }
  extern "C" {
    struct A {
      friend void N::f();  // Now accepted in GNU C++ mode.
    };
  }
  void N::f() {}  // Previously triggered an infinite loop.


Now, no error is issued anymore (to match the behavior of GCC) and the front
end terminates as expected.


6/29/11  [EDGcpfe/11353]
Incorrect lookup of macro name when the file scope is reactivated

In modes in which the file scope is reactivated (when using multiple
translation unit mode or implicit inclusion), if a keyword and macro
had the same name, after the file scope was reactivated the keyword
symbol would incorrectly be found in preference to the macro symbol.
Now fixed.  If the example below was compiled with a command such
as "edgcpfe -B x1.c", an error would have been issued during the implicit
inclusion of x2.c.

  file: x1.c:
  #include "x2.h"
  A<int> a;
  #define char abc

  file: x2.h:
  template <class T> struct A { A(); };

  file: x2.c:
  int char;  // spurious "invalid combination of type specifiers"


6/29/11  [EDGcpfe/11194,EDGcpfe/11783,EDGcpfe/11787]
Template template parameter mismatch should cause substitution failure

When doing template argument substitution, the front end failed to
detect cases where a substituted template template argument had
a template parameter list that was incompatible with the associated
template template parameter.  This resulted in spurious ambiguities in
cases such as the example below.  Now fixed.

  typedef char (&no_tag)[1];
  typedef char (&yes_tag)[2];
  
  template <typename T> struct has_xxx {
    template <template <typename V0> class V> struct has_xxx0 { };
    template <template <typename V0, typename V1> class V> struct has_xxx1 { };
    template <typename V> static no_tag  has_xxx_fn(...);
    template <typename V>
      static yes_tag has_xxx_fn(void *, has_xxx0 <V::template xxx>* = 0);
    template <typename V>
      static yes_tag has_xxx_fn(void *, has_xxx1 <V::template xxx>* = 0);
      static const bool value = sizeof(has_xxx_fn<T>(0)) == sizeof(yes_tag);
  };
  struct x {
    template <typename T> struct xxx {};
  };
  bool b = has_xxx<x>::value;


6/27/11  [EDGcpfe/11830]
Incorrect end position recorded on some dependent statements

The end position recorded for a while- or if-statement was sometimes incorrect
if the dependent statement of that construct was a declaration not enclosed in
braces (such end positions are recorded when EXTRA_SOURCE_POSITIONS_IN_IL is
set to TRUE).  For example:

  struct S { S(); };
  void g(int i) {
    while (i--) S x;  // End position of the while statement was previously
  }                   // not the position of the semicolon.

This is now fixed.


6/27/11  [EDGcpfe/11831]
Abort on invalid bit field declaration

In configurations with TARG_MICROSOFT_BIT_FIELD_ALLOCATION set to TRUE, the
front end could abort with an internal error in set_field_size_and_alignment
(layout.c, "bad curr_container_avail_bits adjustment") after issuing an error
on a bit field with an invalid type and an invalid size.  For example:

  struct S {
    b:200;  // Missing bit field type and invalid size: Previously could
  };        // trigger an internal error.

This is now fixed.


6/24/11  [EDGcpfe/11781]
Microsoft compatibility: acceptance of invalid explicit instantiations now
version-dependent

The front end accepts certain invalid explicit instantiation directives in
Microsoft bugs mode (see 2/17/98 entry).  This was fixed in VC 7.1, so we
now only provide this bug emulation when microsoft_version <= 1300.

  template <class T> struct A {
    template <class U> int f(int i) { return 0; }
  };
  template int A<int>::f<char>();  // now error instead of warning


6/18/11  [EDGcpfe/11808]
C-generating back end: abort on reference to variable in containing block

C-generating back end configurations could abort (in
find_local_variable_static_init) on code that takes the address of an
initialized static variable that is promoted to the global scope from a
containing block.  This is now fixed.  For example:

  const void* p;
  void f() {
    static const int x[] = { 1, -2, 3, 4 };
    {
      int i;
      p = &x;   // Could abort here
    }
  }


6/17/11 [EDGcpfe/8403,EDGcpfe/10669,EDGcpfe/11510,EDGcpfe/11628,EDGcpfe/11684,
         EDGcpfe/11800]
C++0x: Implement char16_t and char32_t types

The front end now supports the char16_t and char32_t types as adopted by N2249.
These types are available as keywords in C++0x mode and optionally when
DEFAULT_CHAR16_T_AND_CHAR32_T_ARE_KEYWORDS is TRUE or --uliterals is specified
in C++ mode.  U-literals (see the Changes entry dated 2/14/06) were previously
allowed only in C mode are now allowed in C++ mode and enabled by default in
C++0x mode.

The new DEFINE_MACRO_WHEN_CHAR16_T_AND_CHAR32_T_ARE_KEYWORDS and
MACRO_DEFINED_WHEN_CHAR16_T_AND_CHAR32_T_ARE_KEYWORDS configuration macros can
be used to define a macro (which defaults to __CHAR16_T_AND_CHAR32_T) when
char16_t and char32_t are implemented as keywords.

For GNU compatibility, when emulating version 4.4.0 and later, the
front end predefines the __CHAR16_TYPE__ and __CHAR32_TYPE__ macros with
the underlying types used by the char16_t and char32_t types, respectively.
These macros are defined in both C and C++ modes.

Also as part of these changes, the default value for the TARG_CHAR32_T_INT_KIND
configuration macro has been changed from ik_unsigned_long to ik_unsigned_int.

These new types are mangled using the encoding "g" for char16_t and "k" for
char32_t in the Cfront-like ABI (and the standard encodings for the IA-64 ABI).

  char16_t *str = u"A 16-bit character string";
  char32_t ch = U'\U00012345';  // A 32-bit character literal


6/17/11 [EDGcpfe/11809]
C++-generating back end: Postfix attributes on parameters

The C++-generating back end previously failed to render postfix attributes
on parameter declarations.  This is now fixed.


6/17/11 [EDGcpfe/11809]
GNU compatibility: Attribute "format" on function parameters

In GNU modes, the front end now accepts the attribute "format" on function
parameters.  For example:

  void g(void (*pf) (void *, const char *, ...)
                   __attribute((format(printf, 2, 3)))) {
    /* Now accepted in GNU modes. */
  }


6/17/11 [EDGcpfe/9919,EDGcpfe/11661]
GNU compatibility: __builtin_isfinite and __builtin_isnormal

In GNU modes (in configurations that have TARG_HAS_IEEE_FLOATING_POINT set to
TRUE) the front end now supports the GNU built-in functions __builtin_isfinite
and __builtin_isnormal.  A call to one of these functions with a constant
floating-point argument is folded in the front end if the internal format of
floating-point constant permits it.  For example:

  int i = __builtin_isnormal(1e-40F);  // Now equivalent to "int i = 0;" in
                                       // GNU C mode.


6/16/11 [EDGcpfe/11805]
Diagnostic position for certain catch clauses without a declarator

Certain diagnostics on catch clauses with no declarator were previously
issued at the position of the right parenthesis of the catch clause.  For
example:

  struct A { A(A const&) = delete; };
  void f() {
    try {
      f();
    } catch (A) {
          //  ^-- Error position was previously here; now on "A".
    }
  }

Now, the error position in such cases is that of the type specifier.


6/15/11 [EDGcpfe/11776]
Bad C generated due to incorrect type list ordering

When using the C-generating back end (and hence IL lowering), the front end is
careful to order the type entries on the file-scope types list in a manner
that will result in a valid sequence of C type definitions.  Changes in this
area made for version 4.2 of the front end caused it to be unable to generate
valid C for certain moderately complex Boost library test cases (found in
Boost 1.46.1).  This problem is now fixed.


6/13/11 [EDGcpfe/11794]
GNU C compatibility: Implicit function declaration followed by incompatible
explicit definition

In GNU C mode, the front end accepts an implicit declaration of a function
(created by a call) followed by an incompatible declaration of that function
in some cases.  However, previously the later explicit declaration was 
spuriously marked as "superseded": This caused the C-generating back end to
ignore the later declaration, and if that declaration was a definition, linker
errors were likely to ensue.  For example:

  int main() { f(); }  // Implicit declaration of f.
  void f() {}          // Incompatible definition of f accepted in GNU C mode.
                       // Previously, this definition was not rendered by the
                       // C-generating back end.

This is now fixed: The entry corresponding to the implicit declaration is
marked as superseded instead.


6/13/11 [EDGcpfe/11534]
Abort on substitution of template argument after deduction

Due to a regression introduced as part of the 4.2 new-style SFINAE
changes, the front end aborted while doing template parameter substitution
on an explicit template argument that's part of a deduced type.
The error was "missing rescan info on explicit template argument"
and only occurred when compilation was done with new-style (C++0x)
SFINAE turned off.  Now fixed.

  struct A {
    template <int I> void f();
  };
  template <class T, class C> struct B {
    template <T> struct E;
    template <class U> static int s(E<&U::template f<50> > *);
    static const int x = sizeof(s<C>(0));
  };
  int main() {
    return B<void (A::*)(),A>::x;
  }


6/13/11 [EDGcpfe/11796]
Abort on use of attributes when compiling multiple source files

In configurations with COMPILE_MULTIPLE_SOURCE_FILES set to TRUE the front end
could abort in calls to hash_find when simultaneously compiling multiple
source files containing attribute specifiers (e.g., GNU __attribute or
Microsoft __declspec constructs).  This is now fixed.


6/13/11 [EDGcpfe/11633,EDGcpfe/11799]
GNU __extension__ annotation sometimes dropped

In GNU mode, the front end often failed to record the __extension__ keyword.
For example:

  __extension__ long long cnt = 0;
  __extension__ typedef long long int64_type;
      /* Previously the presence of the __extension__ keyword was not recorded
         in the IL and hence the C++-generating back end did not render it. */

This is now fixed.


6/13/11 [EDGcpfe/10387]
Incorrect folding of array offset with non-compile-time-constant subscript

The folding code for the following example (characterized by a pointer
addition or subscript operation with a second operand that is an address
constant cast to an integral type) performed a reference to the wrong
variant of a front end internal structure, which might, depending on the
host architecture, cause an incorrect result or an abort.  Now fixed.

  void f();
  void g();
  char *x = ((char*)&f+(long)(char*)&g);


6/10/11 [EDGcpfe/10465]
C++-generating back end abort on template-dependent array bound

The front end aborted in form_array_declarator in il_to_str.c while
trying to render a template-dependent array bound in the C++-generating
back end, when the array bound is a simple const variable whose
value is template-dependent.  Now fixed.

  template <int n> void f(void) {
    const int b = n;
    float a[b];  // Caused abort in --g++ mode
  }


6/10/11 [EDGcpfe/10694]
C++-generating back end and dependent sizeof

In some cases, because of memory region issues, the front end discarded
the expression underlying a dependent sizeof (or similar construct)
and kept only the type.  That turned out to cause problems for
the C++-generating back end when the prototype instantiation
of a template is used to regenerate the source code: an undefined
temporary name was generated for the type.  Now the expression
is retained (in versions with PROTOTYPE_INSTANTIATIONS_IN_IL TRUE).

 template<class Y> Y g(void) {
   enum {y = sizeof(g<Y>())};  // Was sizeof(__T3141084) or the like
 }


6/9/11  [EDGcpfe/11777]
Distinguishing object-like and function-like macros

The a_macro IL entry, included when RECORD_MACROS_IN_IL is TRUE, previously
had no indication of whether the macro is object-like, taking no arguments,
or function-like.  In an IL CHANGE, the a_macro entry now contains a flag,
object_like, that is TRUE for the former and FALSE for the latter.  For
example, assuming macrop is a pointer to an a_macro entry,

  #define O 2      // macrop->object_like is TRUE
  #define F(x) x   // macrop->object_like is FALSE


6/9/11  [EDGcpfe/10723]
Abort on __builtin_offsetof applied to function

The front end aborted in scan_offsetof in expr.c while attempting to
process a GNU __builtin_offsetof where the second operand is a function
(a field is required, so an error should have been issued).  Now fixed.

  struct A {
    int x;
    void f();
  };
  void f() {
    __builtin_offsetof(A, f);
  }


6/9/11  [EDGcpfe/11285]
Spurious error on template-dependent GNU __sync_... function call

A change made in version 4.2 (see EDGcpfe/10150) caused a regression
in handling certain template-dependent calls of GNU __sync_...
functions.  Here's one case that failed, now working again:

  template<typename T> void f(T *p, T n) {
    __sync_fetch_and_add(p, n);
  }
  int main() {
    int* ip = new int;
    f(ip,3);
  }


6/8/11  [EDGcpfe/11608]
Hard error in decltype should have been deduction failure

In some cases, an error in a decltype processed in a new-style template
SFINAE context caused a hard error instead of a deduction failure.
Now fixed.

  template <class T> decltype(T::g) *f(int);
  template <class T> void f(...);
  struct X {
    static void g(long) {}
    static void g(void *) {}
  };
  int main() {
    f<X>(0); // decltype(T::g) renders the program ill-formed
             // because T::g is a set of overloaded functions.
             // Should cause deduction failure, f(...) is selected
  }


6/8/11  [EDGcpfe/11793]
g++ 4.5 and binding rvalue references to lvalues

Another tweak on the change described below for g++ 4.5 compatibility
with binding rvalue references to lvalues (EDGcpfe/11769).  It turns
out that g++ 4.5 also allows dropping cv-qualifiers when it binds
the parameter of a move constructor or move assignment operator
to an lvalue.  We now emulate that.  Also, warnings are now issued
for cases like this, for those covered by EDGcpfe/11769, and in
general when an rvalue reference is bound to an lvalue, since
that may destroy a variable that is still in scope.  [9/30/11:
This logic turned out to be flawed.  See EDGcpfe/12994.]
[12/16/11: The warnings have been reduced to remarks, since
they show up in straightforward use of the g++ 4.4 headers.
See EDGcpfe/12494.]

  struct A {
    A();
    A &operator=(A &&);
    A(A &&);
  };
  int main() {
    const A ca;
    A a = ca;  // Accepted by g++ 4.5; now accepted
    a = ca;    // Accepted by g++ 4.5; now accepted
  }


6/6/11  [EDGcpfe/11752]
Internal error on empty pack expansion with subsequent parameters

An internal error could occur (in scan_function_body) if a member function
declaration of a class template contained a pack expansion followed by
additional parameters, and the class was instantiated with an empty pack.
Now fixed.

  template <class ...T> struct A {
    virtual void f(T ..., int ){} 
  };
  A<> a;


6/3/11  [EDGcpfe/11784]
Extraneous diagnostic with missing position on invalid use of dllimport on
static data member definition

In Microsoft C++ mode, the front end issued an error ("a storage class may not
be specified here") when defining a static data member with the dllimport
attribute.  However, the error message did not include a source position and
was in fact extraneous because a clearer error message followed ("cannot
define dllimport entity").  For example:

  struct S { 
    static int sm; 
  }; 
  __declspec(dllimport) int S::sm;  // Previously triggered two errors in
                                    // Microsoft mode, one of which was
                                    // missing position information.

This is now fixed: The extraneous diagnostic is no longer issued.


6/2/11  [EDGcpfe/11769]
g++ 4.5 and binding rvalue references to lvalues

A change previously made to emulate g++'s handling of rvalue
references (see EDGcpfe/11634 below) was incomplete with regard to
g++ 4.5.  It appears that while most cases of binding an rvalue
reference to an lvalue are disallowed in g++ 4.5, that is still
allowed for the parameters of move constructors and move assignment
operators.  g++ 4.6 seems to have gone all the way to the standard
restrictions.  The following case is now accepted with
gnu_version=40500:

  struct pair {
    pair(const pair&&);
    pair& operator=(const pair&&);
  };
  void foo() {
    pair* src;
    pair dest(*src);
    dest = *src;
  }

[9/30/11: Some of this logic turned out to be flawed.  See EDGcpfe/12994.]


6/1/11   [EDGcpfe/11773]
Pointer arguments to __sync_... functions

When GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED is TRUE the front end now accepts
pointer operands for the GNU built-in __sync_... functions in GNU C++ mode
(and no longer issues a warning in GNU C mode).  Such operands are implicitly
cast to the appropriate integral type.  For example:

  int ptr_cas(void volatile **mem, void *expected, void *replacement) {
    return __sync_bool_compare_and_swap(mem, expected, replacement);
  }  // Now accepted in both GNU C++ and GNU C modes.


5/31/11  [EDGcpfe/11768]
GNU compatibility, C-generating back end: __builtin_va_list on 64-bit systems

The struct type used internally by gcc on 64-bit systems as the base of
__builtin_va_list is necessarily distinct from the type generated by the
front end and put out by the C-generating back end when the front end is
configured with GCC_BUILTIN_VARARGS is TRUE.  As a result, gcc issued
"incompatible type" warnings when the output was compiled.  The
C-generating back end has now been changed to replace the definition and
uses of this predeclared type with a typedef to the appropriate gcc type
(obtained using a typeof expression referring to __builtin_va_list) when
the front end is configured with GCC_BUILTIN_VARARGS and USE_X86_64 set to
TRUE and gcc_is_generated_code_target is also TRUE.  For example:

  void f(__builtin_va_list);
  void g() {
    __builtin_va_list v;
    f(v);    // Previously caused warnings in the generated code
  }


5/30/11  [EDGcpfe/11762]
GNU compatibility, C++-generating back end: dependent function non-type
template arguments

Beginning with version 3.4, the g++ compiler has a bug that causes it to
issue a spurious error, "'&' cannot appear in a constant-expression," when
the argument to a function-pointer non-type template argument is expressed
with an explicit & and enclosed in parentheses.  When
PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the C++-generating back end
previously used that form in the definition of a template when the argument
refers to a dependent function.  It has now been changed to omit the
unnecessary parentheses in this case.  For example:

  template<typename T> T f();
  template<typename T, T fp()> struct S { };
  template<typename T> struct X {
    typedef S<void, f<T> > s;   // Previously generated as S<void, (&f<T>)>,
                                // now as S<void, &f<T> >
  };


5/27/11  [EDGcpfe/11766]
Preprocessing directives, white space, and old-style preprocessing

Pre-ANSI C preprocessors, as well as the GNU preprocessor with the
-traditional-cpp option, only recognize a # character as the start of a
preprocessing directive if it is the first character on the line.
(Standard preprocessors allow the # to be preceded by white space.)  The
front end has now been changed to emulate this facet of older preprocessors
when --old_style_preprocessing is specified.  For example, the front end
formerly reported an error with --preprocess --old_style_preprocessing but
no longer does so:

  /* */ # not_a_directive


5/27/11  [EDGcpfe/11743,EDGcpfe/11751]
GNU compatibility: Name lookup with __builtin_va_list on 64-bit platforms

When USE_X86_64 is TRUE, __builtin_va_list is declared as an array of class
type (see EDGcpfe/10180).  Class types (or arrays-of/pointer-to class types),
when used as arguments to functions, invoke argument-dependent name lookup,
which can change the set of namespaces considered during lookup.  A change has
been made to disqualify the va_list_tag class type in the global namespace from
argument-dependent name lookup.  This example had resulted in an error (i.e.,
more than one instance of function "N::f" matches the argument list) and now
compiles successfully (with --g++):

  void f(__builtin_va_list);
  namespace N {
    void f(__builtin_va_list);
    void g(...) {
      __builtin_va_list args;
      f(args);
    }
  }


5/23/11  [EDGcpfe/11609]
GNU C++ compatibility: Using-declaration conflicting with previous declaration

Ordinarily, a using-declaration in a namespace that brings in a function whose
signature conflicts with a function already declared in that scope is an error.
Now the front end will accept such using-declarations in GNU C++ mode if the
function referred to is defined.  An attempt to make use of the resulting
overload set results in an ambiguity error.  For example:

  double f();
  namespace N {
    using ::f;
    namespace NN {
      long double f() { return N::f(); }
    }
  }
  using N::NN::f;  // Usually an error.  Now accepted in GNU C++ mode.
                   // (Requires N::NN::f() to be defined.)
  int main() {
    f();         // Ambiguous.
    ::f();       // Ambiguous.
    N::f();      // Okay.
    N::NN::f();  // Okay.
  }


5/23/11  [EDGcpfe/11523]
Abort on attribute with string literal argument

The front end previously sometimes recorded a string literal argument to an
attribute in a function-scope memory region, resulting in invalid IL since an
attribute (always stored in file-scope memory region) would end up pointing
into function-scope memory.  This could lead to aborts, in particular when
writing the IL to file.  For example:

  void f() {
    struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) S;
      // The attribute (stored in file-scope memory) ended up pointing to
      // a string constant stored in function-scope memory.
  }

This bug, introduced in version 4.2, is now fixed.


5/23/11  [EDGcpfe/11502]
Abort in set_parent_scope with local class of template

In certain configurations that perform lowering (DO_IL_LOWERING is TRUE), the
front end could abort with an internal error in set_parent_scope (il.c) during
the prototype instantiation of a function with a local class type when that
class type contained elements depending on a template parameter.  For example:

  template<typename T> void f() {
    struct A: T {    // Previously this class triggered an abort in il.c.
      A() : T() {}
    };
    extern A a;
  };

This is now fixed.


5/21/11  [EDGcpfe/11485]
Microsoft compatibility: source positions in rewritten property compound
operations

The front end rewrites compound assignment and increment/decrement
operations involving Microsoft property fields so that the IL reflects the
calls to the property's accessor functions.  In the process, however,
certain important source positions were not recorded or were recorded
incorrectly in the resulting expression nodes.  This has now been fixed.
For example, given a property reference like

  f()->prop += 15;

and with EXTRA_SOURCE_POSITIONS_IN_IL, the source range in the enk_routine
nodes of the calls to the property's "get" and "set" routines formerly
spanned the entire member access expression, "f()->prop"; it now designates
only the name of the property in the source.  Also, the node corresponding
to the addition (eok_add, etc.) had no operator position; it now contains
the position of the "+=" operator.  (The source range in this node
continues to be null_source_range, reflecting the fact that this operation
does not actually appear in the source in this form.)


5/20/11  [EDGcpfe/11462]
Invalid in-class using-declarations in Microsoft mode

In Microsoft mode, an in-class using-declaration referring to a constructor or
destructor only elicits a warning instead of an error (see Changes entry of
11/22/99).  In such cases, however, the front end failed to check certain
other constraints of the using-declaration; in particular, it did not check
that the constructor was a member of a base class.  For example:

  struct X { ~X(); };
  struct Y {
    using X::~X;  // Previously triggered just a warning in Microsoft mode,
  };              // even though X is not a base of Y.  Now an error is issued.

This is now fixed.


5/19/11  [EDGcpfe/11750]
Attributes on function template definitions and their instantiations

Previously, if a function template was first declared without a definition,
then used, and then defined, only attributes on the initial declaration were
applied to the used specialization and any attributes on the definition had
no effect on that specialization.  For example (using Microsoft mode):

  template<typename T> void f(T);
  int main() {
    f(7);  // Use of f<int>(int).
  }
  template<typename T> __declspec(nothrow) void f(T) {}
    // f<int>(int) may be fully instantiated at this point.  Previously,
    // such instantiation ignored the "nothrow" attribute from the definition.
    // Now the attribute is picked up.

Note that GNU-style attributes are unaffected because of the issue reported
by the Changes entry for EDGcpfe/11448 of 5/11/11.  (Also, the Changes entry
for EDGcpfe/9913 of 2/23/10 documents a related issue for member functions of
class templates.)


5/18/11  [EDGcpfe/11735]
Assertion failure in optimize_node_if_possible during lowering

An assertion failure had occurred (in optimize_node_if_possible) during
the lowering of certain assignment statements (involving const-qualified
classes with tail padding in the IA-64 ABI) and is now fixed.  For example:

  struct A {
    void* p;
    char c;
    A() {}
  };
  const A &f();
  void g(bool b) {
    A a;
    a = b ? f() : a;
  }


5/14/11  [EDGcpfe/11560]
Parameters following an empty function parameter pack expansion

The front end previously issued a spurious error when an empty function
parameter pack expansion was followed by another parameter declaration.
For example:

  template<typename ... T> struct S {
    void f(T ... p, int x);
  };
  S<> s;  // Empty pack expansion previously triggered an error on the
          // declaration of parameter x.  Now okay.

This is now fixed.


5/14/11  [EDGcpfe/11560]
Default arguments on members of variadic class templates

In modes that accept variadic templates (like C++0x mode), the front end now
accepts a default argument on a parameter of a member function of a class
template that is a pack expansion.  For example:

  template<typename ... T> struct S {
    void f(T ... p = 0);  // Previously disallowed in C++0x mode; now okay.
  };
  S<int, int, int> s;
  int main() { s.f(); }

Note that default arguments are not valid on function parameter packs for
function and member function templates.  E.g.:

  template<typename ... T> void f(T... p = 0);  // Error.


5/14/11  [EDGcpfe/11543,EDGcpfe/11545]
Microsoft attributes in C mode

In Microsoft C mode with microsoft_version >= 1400, the front end now accepts
bracketed attributes (see Changes entry of 7/30/03) as part of declaration
specifiers (and particularly, at the start of parameter declarations).

  int f([SA_Pre(Null=SA_No)] int *x);  /* Now accepted in some Microsoft C
                                          modes.  Previously, only accepted
                                          in Microsoft C++ modes. */


5/12/11  [EDGcpfe/10894]
Lowering of complex constants

Previously, the lowering of a shared complex constant had resulted in
undefined behavior in some cases (because a lowered complex constant -- i.e.,
an aggregate -- was unexpected in parts of the front end).  A change has been
made to delay lowering of complex constants in the file scope.  As part of this
change, the assoc_var_assigned field in a_constant has been removed and
replaced with the assoc_var variable pointer, so this is a slight IL CHANGE
(though these fields are intended to be used only by IL lowering and the C
generating back end).  This example (with --g++ --c++0x) had generated a
segmentation violation (in find_friend_functions_for_class) and now compiles
without error:

  template <class T> auto f(T x) -> decltype(__I__,x);
  void g() {
    f(__I__);
  }
  auto x = f(0);


5/11/11  [EDGcpfe/11695]
Internal error on macro in static data member initializer

In configurations with GENERATE_SOURCE_SEQUENCE_LISTS and RECORD_MACROS_IN_IL
both set to TRUE, defining a macro in an in-class static data member
initializer caused an internal error in add_src_seq_end_of_variable_if_needed
(decls.c).  For example:

  class C {
    static const int x =
  #define M
                         0;  // Previously triggered an internal error.
  };

This is now fixed.
  

5/11/11  [EDGcpfe/11448]
GNU attributes on function template redeclarations

GNU compilers appear to ignore attributes specified on function template
declarations that are redeclarations.  For example:

  int volatile x;  // To model side effects.
  template<typename T> void f();
  template<typename T> __attribute__((noinline)) void f() { x = 1; }
  int main() {
    f<int>();  // GCC will inline this call at high optimization levels
  }            // (e.g., with option -O3), ignoring the noinline attribute.

The front end previously applied the attributes collected over all declarations
to the instantiations (i.e., in the example above, noinline was not ignored on
f<int>).  Now, the front end emulates the GCC behavior by marking attributes
on redeclaration as "unrecognized": This inhibits their effect without
altogether dropping all indication of their presence (e.g., the C++-generating
back end renders them).


5/11/11  [EDGcpfe/11722]
C++-generating back end: pointers to members of globally-qualified classes

When the C++-generating back end generated the declaration of a pointer to
a data member in which the class name must be globally qualified (i.e.,
with a leading "::"), it failed to enclose the declarator in parentheses as
required to separate the member type from the class name.  This has now
been addressed by enclosing the declarators of all pointer-to-data-member
declarations in parentheses, whether the class name is globally qualified
or not.  For example:

  struct O {
    struct I {
      int O;                // Hides ::O
      typedef I (::O::*p);  // Previously generated without parens as I::O::*p
    };
  };


5/11/11  [EDGcpfe/11704]
Segmentation fault on invalid GNU case range

An invalid initial range on a GNU case range statement had resulted in a
segmentation fault and is now fixed.  For example (with --gcc):

  void f(int i) {
    switch (i) {
      case MISSING ... 10:    // had resulted in a segmentation violation
        break;
    }
  }


5/10/11  [EDGcpfe/11652]
Better error recovery on casts and new operators with multiple arguments

Error recovery is now improved for functional-notation casts and
"new" operators with more than one expression between the parentheses
when the cast or "new" type is unknown because of a previous error.

  int main() {
    typedef xx T;    // Error here, "xx" is undefined
    T(4, 5, 6);      // Now no additional error here
    new T(4, 5, 6);  // Now no additional error here
  }


5/10/11  [EDGcpfe/11659]
GNU compatibility: Explicit conversion functions

Explicit conversion functions (a C++0x feature; see the Changes entry of
4/19/11) are now enabled in GNU C++ mode when gnu_version >= 40500.  (GCC 4.5
issues a warning on uses of the feature in non-C++0x modes, but we accept it
silently.)


5/10/11  [EDGcpfe/11670]
Abort on use of __builtin_offsetof with overloaded subscript operator

The front end aborted in is_template_dependent_offsetof_member in
folding.c while processing a __builtin_offsetof operator in GNU C++
mode when a subscript operation in the offsetof is overloaded.
Now fixed (an error is issued).

  struct A {
    int operator [](int);
  };
  struct B {
    A a;
  };
  int main() {
    return __builtin_offsetof(B,a[0]);  // Error instead of abort now
  }


5/10/11  [EDGcpfe/11713]
Empty variadic template pack expansion in arguments of "new" causes abort

An empty variadic template pack expansion as the argument list for a
"new" operation on a class type could cause an abort in lower_new in
lower_init.c.  Now fixed.  This affected only configurations that
do IL lowering and that also have NEW_CAN_BE_FOLDED_INTO_CTOR set to
TRUE (and therefore, not IA-64 ABI configurations).

  struct A {
    A();
  };
  template <class... Types> void f(Types... Args) {
    new A(Args...);  // Could be an empty pack expansion, implying value
                     // initialization.  Caused abort previously.
  }
  int main() {
    f();
  }


5/6/11   [EDGcpfe/11426]
Unnamed scoped enumerations

The front end now reports an error for attempts to declare an unnamed scoped
enumeration type (in C++0x mode and certain Microsoft modes).  For example:

  enum class { e };  // Now triggers an error in C++0x mode.


5/4/11   [EDGcpfe/11644]
Performance improvement in do_using_directive_lookup

This routine has been updated to use the scope hash tables (see 1/25/11
entry) instead of the inactive list, which can result in a significant
performance improvement in compilations that use a very large number of
template instantiations.


5/3/11   [EDGcpfe/11668]
Configuration macro to control lowering of string literal types

A new configuration macro, LOWER_STRING_LITERALS_TO_NON_CONST, has been
added to control whether or not lowering removes the const qualification
of string literal types.  The front end can be configured to generate
const string literals (see string_literals_are_const), and when this new
flag is TRUE, lowering removes this const qualification.  It is desirable in
some cases to have non-const string literals (because the goal of lowering
is to generate C code, and in the C language, string literals are non-const),
but in other cases, removing the const-ness may result in strings not being
placed in read-only storage.  Lowering of string literals to non-const was
first introduced in the 4.0 release.  The default setting for
LOWER_STRING_LITERALS_TO_NON_CONST is TRUE when BACK_END_IS_C_GEN_BE is TRUE
and FALSE otherwise.  This means that configurations that use lowering and
have BACK_END_IS_C_GEN_BE set to TRUE will see no change, but configurations
that use lowering and have BACK_END_IS_C_GEN_BE set to FALSE will see a
change to pre-4.0 behavior.

Note that setting LOWER_STRING_LITERALS_TO_NON_CONST to FALSE when generating
intermediate C code will cause compilation errors when compiling the
intermediate C, as in this case:

  template <typename T> void f(T const& t);
  void g() {
    f("abc");
  }


5/3/11   [EDGcpfe/11694]
Performance improvement in find_progenitor_in_base_class

This routine has been updated to use the scope hash tables (see 1/25/11
entry) instead of the inactive list, which can result in a significant
performance improvement in compilations that use a very large number of
template instantiations.


4/29/11  [EDGcpfe/11654]
Microsoft compatibility: static_cast of field selection can be lvalue cast

In Microsoft bugs mode, a static_cast applied to an lvalue that is
a field selection using the "->" operator (including the implicit "this->"
case of that), that casts the lvalue to the same type with different
cv-qualifiers, is now treated as an lvalue cast, i.e., it produces an
lvalue result.

  class Cl {
    int mem;
     void Func( void ) const {
       static_cast<int>(mem) = -1;   // Now accepted in Microsoft bugs mode
     }
  };


4/28/11  [EDGcpfe/11664]
Source positions on stmk_init and stmk_vla_decl statements added by lowering

Generally speaking, statements added by lowering have no statement positions
(thereby indicating that they are compiler generated).  Back ends can typically
assume that a statement with no position information should be treated as
having the same position information as the previous statement.  This heuristic
didn't work with stmk_init and stmk_vla_decl statements that are added prior
to the statement being lowered (thus, when using the heuristic, appearing to
be part of the previous statement).  These statements are now given the
source position of the statement that caused their creation.  This example
(with --g++) has both stmk_init and stmk_vla_decl lowered statements
(when LOWER_VARIABLE_LENGTH_ARRAYS is FALSE):

  void f(int i) {
    i = 1;
    (int (*)[i*2]) { 0 };
  }


4/27/11  [EDGcpfe/11658]
Abort on qualified class declaration with attributes

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, the front end could previously
abort with an internal error in attach_tag_attributes when parsing a class
declaration (but not a definition) using a qualified name and with explicit
attributes.  For example:

  namespace N { struct S {}; }
  struct __declspec(dllimport) N::S;
     // Previously triggered an internal error in Microsoft C++ mode.

This is now fixed.


4/27/11  [EDGcpfe/11653]
Rendering class definitions appearing in block-extern function declarators

In some modes (like Microsoft C mode), the C++-generating back end previously
aborted with an internal error in check_for_and_take_source_seq_entry when
attempting to render a class defined in the parameter list of a block-extern
function declarator.  For example:

  int f() {
    void g(struct S { int i; } p);  // Triggered an abort in some modes.
    return 0;
  }

This is now fixed.  (See also the entry of 5/26/10 for EDGcpfe/10706.)


4/27/11  [EDGcpfe/11213]
__has_nothrow_copy and __has_nothrow_assign

Previously, the type trait pseudo-functions __has_nothrow_copy and
__has_nothrow_assign produced a "true" value only when the corresponding
copying function (constructor or assignment operator) was trivial or
explicitly declared with a "throw()" exception specification.  For example:

  struct S { virtual ~S(); };     // Not trivially copyable because the class
                                  // contains a virtual function.
  int i = __has_nothrow_copy(S);  // Previously, i was initialized to 0;
                                  // now, it is initialized to 1.

Now, the front end uses a more precise algorithm to determine whether copy
constructors and copy assignment operators can throw.  The resulting values
for __has_nothrow_copy and __has_nothrow_assign are closer to those produced
with Microsoft and GNU compilers (in the case of Microsoft, we know of no
difference in this regard).


4/25/11  [EDGcpfe/11611]
GNU compatibility, C++-generating back end: spelling of "decltype"

In --g++ mode, the front end accepts decltype and __decltype as equivalent
keywords.  The C++-generating back end always generated a decltype
construct using the "decltype" spelling; however, current versions of g++
only accept that spelling of the keyword with -std=c++0x.  Consequently,
such constructs are now generated using the "__decltype" spelling when
gcc_is_generated_code_target is TRUE.  For example:

  __decltype(0) i;   // Previously generated as "decltype(0) i;"


4/25/11  [EDGcpfe/11493]
Abort on local declaration that does not declare anything

The C++-generating back end previously aborted in gen_declaration on some
local declarations that do not declare anything.  For example:

  void f() {
    int;   // Previously aborted in "gen_declaration".
    int x;
  }

This is now fixed.


4/23/11  [EDGcpfe/11344]
GNU compatibility, C-generating back end: empty compound literals

When an initialization in --gcc mode contains an empty compound literal (a
GNU extension), the code produced by the C-generating back end contained an
incorrect "=" corresponding to the trivial initialization.  This has now
been fixed.  For example:

  struct A {
    int* m;
  };
  void f() {
    struct A a = { (int[]) {} };  // Previously resulted in "{ = }" in the
                                  // generated C code
  }


4/21/11  [EDGcpfe/11650]
Arithmetic conversions on scoped enumeration values (C++0x mode)

In C++0x mode, the front end previously erroneously considered "the usual
arithmetic conversions" when dealing with built-in operators applied to
scoped enumeration values.  For example:

  enum class E { e, f };
  void g() {
    E::e+E::f;  // Previously accepted in C++0x mode; now an error.
  }

Now, built-in arithmetic operators involving a scoped enumeration value produce
an error, and comparison operators (equality and relational) involving a scoped
enumeration value are accepted only if both operands have the same type.


4/19/11  [EDGcpfe/11367,EDGcpfe/8624,EDGcpfe/11498,EDGcpfe/11517]
explicit conversion functions

Conversion functions marked "explicit", as defined by the C++0x standard
(see paper N2437), are now implemented.  Such conversion functions
are used only for explicit casts, and not for implicit conversions.
The related concept of "boolean-converted" is also now implemented.
It allows explicit conversion functions to bool to be used to produce
a bool value in contexts like the expression of an "if" statement
even though such a context is not an explicit cast.

  struct A {
    explicit operator bool();
  };
  int main() {
    A a;
    (void)bool(a);  // Okay
    if (a) {}  // Okay
    bool b = a;  // Error
  }


4/18/11  [EDGcpfe/11476]
Microsoft C mode block-extern function declarations

Previously, in Microsoft C mode, a block-extern function declaration followed
by a file-scope declaration of the same function always resulted in the
creation of two distinct a_routine entries.  For example:

  void f() { extern int g(); }  // Creates an entry for "g()".
  int g() {}                    // Creates a second entry for "g()".

This allowed the front end to accept incompatibilities in those declarations
(they were silently accepted).  Now, the front end only creates the second
entry if the declarations are actually incompatible: In the example above only
one entry is created.  Furthermore, to be accepted, two incompatible
declarations must have "interchangeable" return types and a warning is issued.
For example, assuming int and long have the same size and alignment:

  void f() { extern int g(), h(); } 
  long g() { return 1; }  // Now a warning; a second routine entry is created.
  void h() {}             // Now an error.


4/14/11  [EDGcpfe/11491]
C-generating back end, Microsoft compatibility: padding after bit-fields

When msvc_is_generated_code_target is TRUE, the C-generating back end
failed to account for the way the Microsoft C compiler allocates bit-fields
when determining whether padding was required after a bit-field in the
generated code.  As a result, unneeded padding was sometimes introduced,
effectively causing the size of some generated structs and the offset of
members following bit-fields to be different from what they would have been
if the original code were compiled directly by the Microsoft compiler.
This has now been fixed.  For example:

  struct S {
    int i:4;
    // C-generating back end added "char __dummy[3];" to fill out the 4-byte
    // struct, but MSVC allocated the array in a separate word, making the
    // size of the struct 8 instead of 4.  No padding is now added.
  };


4/14/11  [EDGcpfe/11610]
Incorrect default template argument value within prototype instantiation

The IL for the prototype instantiation of a class could incorrectly
represent a default template argument of the prototype instantiation or
a class declared within the prototype instantiation.  Formerly, the value
used was the one originally declared as the template default argument.
It instead should have had any template parameters substituted with
those from the reference.  Now fixed.

  template <typename T> class A {
    template<typename U, bool is_pod = __is_pod(U)> struct B { };
    B<T> b;  // Was B<T,__is_pod(U)> should have been B<T,__is_pod(T)>
  };


4/14/11  [EDGcpfe/11634]
Rvalue reference can bind to lvalue in g++ 4.3 and 4.4 modes

g++ 4.3 and 4.4 implement an early version of the rules for rvalue
references, which allows an rvalue reference to bind to an lvalue.
In those modes, we now emulate that behavior.  (One of the reasons
we needed to do so is that the g++ 4.4 headers make use of such a
binding.  g++ 4.5 changed to match the rules ultimately adopted in
the standard.)

  void f(int &&);
  void f(void *);
  int main() {
    int i = 0;
    f(i);  // Okay now with --gnu_version=40400
  }


4/11/11  [EDGcpfe/11621]
Configuration of the file name suffix for C++ output files

Previously, the file name suffix of output files generated by the
C++-generating back end was always determined by the configuration macro
GEN_C_FILE_SUFFIX.  Now, a new macro GEN_CPP_FILE_SUFFIX determines the suffix
used for C++-language output (i.e., the output of the C++-generating back end
in C++ mode, but not in C mode).  The default value of the new macro is the
value of GEN_C_FILE_SUFFIX.


4/8/11   [EDGcpfe/11519]
Lowered code generation for catch(...) clause

In configurations where FORCE_STORES_OF_VARS_MODIFIED_IN_TRY_BLOCKS is TRUE
(which is the default in C generating back end configurations), lowering
had generated intermediate C code that appeared at compile time as though
the end of the "try" statement was reachable, when in fact, at run-time it
was not.  This happened only in cases when a "try" statement included a
"catch(...)" clause and no local variables were modified in the "try"
statement.  For example, this sample had generated a warning ("control reaches
end of non-void function") when the intermediate C code was compiled with 
"gcc -Wall":

  int f() {
    try {
      return 0;
    } catch (...) {
      throw;
    }
  }


4/8/11   [EDGcpfe/11613]
IA-64 ABI: assertion failure when mangling unnamed namespace

In cases where a member of an unnamed namespace is used in a template argument,
an assertion failure (in mangled_simple_id) could trigger during mangling.
This is a regression that was introduced in 4.2.  For example:
[Patch sent out 4/14/11.]

  template <bool B> struct A {
    typedef char type;
  };
  namespace {
    template <typename T> struct C {
      static const bool X = true;
    };
  }
  template <typename T> typename A<C<T>::X>::type f(void);
  void g() {
    f<char>();
  }


4/7/11   [EDGcpfe/11509]
Infinite loop or abort after friend declaration of a static extern "C" function

In Sun mode, the front end incorrectly moved a routine entry for a static
extern "C" function to a class scope if that function was referred to by a
friend declaration.  The resulting corrupt IL could later trigger an abort or
an infinite loop (e.g., in perform_scheduled_routine_moves).  For example:

  extern "C" { static void f(); };
  class C { friend void f(); };  // Entry for f moved to the wrong scope list
                                 // in some modes.
  void f() {}                    // Triggered an infinite loop or abort in
                                 // Sun mode.

This is now fixed.  [Patch sent out 4/14/11.]


4/7/11   [EDGcpfe/11617]
Variadic templates: errors caused by packs expanded during disambiguation

Spurious errors could occur in certain cases if a pack was expanded during
disambiguation.  Now fixed.  This example would get a 'no instance of
overloaded function "f" matches the argument list' during the instantiation
of g.  [Patch sent out 4/14/11.]

  template <class T1, class T2, class ... T3> struct B {
    template <class U1, class ... U2> B(U1&&, U2&&...);
  };
  template <class T0, class T1, class T2, class ... T3> struct C {
    C(const T0&){}
  };
  template <class T> T& f(T&);
  template <class T> T&& f(T&&);
  template<class T0, class T1, class... T3, class... T4>
  inline void g(T0 (T1::* const pmf)(T3...), T4&&... args) {	
    (B<T0, C<T0 (T1::*)(T3...), T0, T1, T3...>, T4...>
     (C<T0 (T1::*)(T3...), T0, T1, T3...>(pmf), ::f<T4>(args)...));
  }
  struct A { void f(int, char, double); };
  int main() {
    g(&A::f, 1, 'c', 1.0);
  }


4/7/11   [EDGcpfe/11614]
GNU C++ compatibility: __GNUC_GNU_INLINE__ and __GNUC_STDC_INLINE__ macros

With the changes to emulate GNU's handling of "extern inline" (see
EDGcpfe/8555), the front end (in GNU C mode), defines either
__GNUC_GNU_INLINE__ or __GNUC_STDC_INLINE__; however if one of those macros
was also defined in the predefined_macros.txt file, the situation could
arise that both macros are defined.  A change has been made to
make_predef_macro_table to suppress definitions for these macros.  Users
should either re-run make_predef_macro_table or remove these macro
definitions from their predefined_macros.txt file.  For example:

  #if defined(__GNUC_GNU_INLINE__) && defined(__GNUC_STDC_INLINE__)
  #error Both __GNUC_GNU_INLINE__ and __GNUC_STDC_INLINE__ are defined
  #endif


4/4/11   [EDGcpfe/11605]
Incorrect partial ordering of lvalue vs. rvalue references

Version 4.3 implemented the resolution of core issue 1164 regarding the
partial ordering of lvalue vs. rvalue references (see 1/14/11 entry).
That change incorrectly considered some cases as ordered that should
have been ambiguous.  Now fixed.  [Patch sent out 4/14/11.]

  template <class T, class U> void f(T&&, U&);
  template <class T, class U> void f(T&, U&&);
  int main() {
     int x = 1;
     f(x, x);  // now diagnosed as ambiguous
  }


4/4/11   [EDGcpfe/11604]
Host DBL_MAX with form ((double)1.79769313486231570815e+308L)

One some systems (e.g., Linux with gcc 4.5.0 or later), DBL_MAX is defined with
a cast to double.  The code in float_pt.c that converts DBL_MAX is now capable
of dealing with that form.  Note that this relates to the host definition of
DBL_MAX as seen while compiling the C source of the front end itself, which
might be different than the definition used when compiling user source code.
See also the Changes entry of 8/2/99 which describes a similar issue with
FLT_MAX.  [Patch sent out 4/14/11.]


4/3/11   [EDGcpfe/11603]
Spurious errors on member template of variadic class

Spurious errors could be issued on a member function template of a variadic
class template when the function template used the variadic template
parameters of the enclosing class.  Now fixed.  [Patch sent out 4/14/11.]

  template <class ... T> struct A {
    template <class U> void f(U, T... args);
  };
  int main() {
    A<int,int> a;
    a.f(1, 2, 3);
  }


4/1/11   [EDGcpfe/11597]
Spurious remark on second argument to main when configuration uses signed chars

When the configuration uses signed chars as the default (e.g., in Microsoft C
emulation mode), a spurious remark had been issued for the second argument
to main, even when it had the correct type.  For example (with --microsoft --c
--remarks): [Patch sent out 4/14/11.]

  int main(int argc, char **argv) {
  // had issued:
  // remark: nonstandard second parameter "char **" of
  //        "main", expected "char *[]" or "char **"
    return 0;
  }


3/31/11  [EDGcpfe/11596]
Failure to diagnose ambiguity on certain variadic templates

The following case should have been diagnosed as ambiguous, but was not.
Now fixed.  [Patch sent out 4/14/11.]

  template <class ...T> void f(T...);
  template <class ...T, class ...U> void f(U...);
  void g() {
    f(37);
  }


3/31/11  [EDGcpfe/11591]
Reference to wrong variant of expression node when PARENS_IN_IL is TRUE

In configurations with PARENS_IN_IL TRUE, in some cases code in
process_void_operand referred to the wrong variant of an expression
node after stripping off an eok_parens node.  As a consequence,
aborts could happen, e.g., in examine_expr_for_side_effect.
In source code, this would require parentheses around a void
operand, e.g., the first operand of a comma operator, or a top-level
expression.  This example provoked such an invalid reference:
[Patch sent out 4/14/11.]

  struct Z {
    Z();
  };
  void f() {
    ((Z()), 3);
  }


3/31/11  [EDGcpfe/11569]
Internal error on variadic member function template

An internal error (in find_function_template_member) could occur on the
instantiation of a variadic member function template.  Now fixed.
[Patch sent out 4/14/11.]

  template <class ...T> struct A {
    template <class _T = int>  A(T... args) {}
  };
  template <class ...T> inline void f(T... args) {
   A<T...> a(args...);
  }
  int main() {
    f();
  }


3/31/11  [EDGcpfe/11526]
is_local_to_function flag for parameter variables

Version 4.3 included a change that caused is_local_to_function to be FALSE for
certain parameter variables (in particular, for the implicit "this" parameter).
This is now fixed.  [Patch sent out 4/14/11.]


3/30/11  [EDGcpfe/10821]
Token separators in preprocessed output

When creating preprocessed output (via the -E command-line option, for
instance), the front end inserts spaces as needed to prevent separate
tokens in macro expansions from being incorrectly merged into a single
token.  This processing was missing a case, however, as illustrated in
this example:

  #define X 52
  #define TT2(x) 1.0e ## x
  #define TT(x) TT2(x)
  double y = TT(-X);

The "-" and "X" are separate tokens but were incorrectly concatenated in
the preprocessed output (but not during actual compilation), giving an
apparently well-formed floating point constant 1.0e-52.  The front end
has now been fixed to maintain the original tokenization by putting a
space between the "-" and the "5" in the preprocessed output.
[Patch sent out 4/14/11.]


3/30/11  [EDGcpfe/11530]
Multi-line whitespace keywords in preprocessing-only mode

Version 4.3 introduced whitespace-keyword processing into the front end in
preparation for support for C++/CLI.  Ordinarily whitespace keywords can be
separated by any form of white space, including line breaks.  This caused
problems in certain cases when the preprocessor was used on text that is
not C or C++ code when a word that could be the beginning of a whitespace
keyword appeared at the end of the line.  In such cases, whether or not a
whitespace keyword was recognized, the line break following the potential
start of the keyword was effectively deleted in the preprocessing output.
For example, the text

  go for
  the gold

became one line in the output in Microsoft preprocessing-only mode.  This
problem has been addressed by disallowing line breaks in whitespace
keywords when doing preprocessing only.  In certain pathological cases
(e.g., when a macro is defined with a name that is one or the other of the
tokens of a whitespace keyword and the tokens are split across lines), the
result of preprocessing-only mode can be different from that of direct
compilation, but this should be exceptionally rare.  [Patch sent out 4/14/11.]


3/30/11  [EDGcpfe/11532]
Internal error on variadic partial specialization declared then defined later

An internal error could occur (in find_placeholder_arg_for_pack) if a
variadic partial specialization was declared and then defined later.
Now fixed.  [Patch sent out 4/14/11.]

  template <class ...T> struct A {};
  template <class T, class ...U> struct A<T, U...>;
  template <class T, class ...U> struct A<T, U...> {};
  A<int, long> a;


3/30/11  [EDGcpfe/11558]
Spurious error or internal error on sizeof... of an empty pack

A spurious error or internal error could result from a sizeof... of
an empty nontype template parameter pack.  Now fixed.  The example below
got a "no instance of C<args...>::f matches the argument list, or if
INTERNAL_ERROR is defined, got an internal error in lower_type.
[Patch sent out 4/14/11.]

  template <int... I> struct A { typedef A<I..., sizeof...(I)> n; };
  template <int J> struct B { typedef typename A<>::n type; };
  template <typename... args> struct C {
#ifdef INTERNAL_ERROR
    typedef A<> my_A;
#else
    typedef typename B<sizeof...(args)>::type my_A;
#endif
    template<int... I> void f(A<I...>);
    void g() { f(my_A()); }
  };
  int main() {
    C<int> c;
    c.g();
  }


3/29/11  [EDGcpfe/11313]
C++-generating back end, Microsoft compatibility: references to
__declspec(property(...)) fields

References to fields declared with a __declspec(property(...)) attribute
are represented in the IL as calls to the associated "get" and "put" member
functions, and the output of the C++-generating back end followed suit.
The C++-generating back end has now been changed to generate these
references in the original source form, which required an IL CHANGE: the
enk_routine variant of an_expr_node is now a struct instead of just a
pointer, and in configurations in which MICROSOFT_EXTENSIONS_ALLOWED is
TRUE and DO_IL_LOWERING is FALSE, the struct contains information about the
property and the kind of accessor that the member function call represents.
For example:

  struct S {
    int g();
    void s(int);
    __declspec(property(get=g, put=s)) int v;
    void f() {
      v += 3;  // Previously generated as "this->s(this->g() + 3)"
    }
  };


3/29/11  [EDGcpfe/11513]
Microsoft compatibility: partial specialization declared outside of namespace

The Microsoft compiler allows a partial specialization of a class template
to be first declared outside of its namespace.  We now support this in
Microsoft mode.  [Patch sent out 4/14/11.]

  namespace N {
    template <typename T, typename R> struct C;
  }
  template <typename T, typename R> struct N::C {};
  template <typename T> struct N::C<T, void> {};


3/29/11  [EDGcpfe/11552]
Abort on ambiguous reference to overload set containing using-declarations

An abort could occur in progenitors_are_equivalent on a reference to
an ambiguous function that is a member of an overload set made visible
in a derived class via a using-declaration.  Now fixed.
[Patch sent out 4/14/11.]

  struct A { };
  struct B {
    void f(A& a);
    void f(A const& a);
  };
  struct C : virtual B {
    using B::f;
  };
  struct D : virtual C { };
  struct E : C, D { };
  int main() {
    E e;
    e.f(A());  // should be ambiguous
  }


3/28/11  [EDGcpfe/11428]
C++-generating back end: naming a class template prototype instantiation

In C++-generating back end configurations in which
PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the name of a class template
prototype instantiation was typically generated as the qualified name of
the template followed by a template argument list consisting of all the
names of the template parameters.  While this form of the name is correct
according to the C++ Standard, MSVC++ issued spurious errors for the
generated code in some obscure cases.  To work around this problem, the
C++-generating back end now generates such names as simply the name of
the template unless the injected-class-name of the template is hidden; in
that case, the full qualified name will still be used.  For example,

  template<typename T> struct S {
    typedef S thisclass;     // Previous generated as ::S<T>, now as S
    void f(int S) {
      typedef ::S<T> parent; // Still generated as ::S<T> because the
                             // parameter hides the injected-class-name
    }
  };


3/27/11  [EDGcpfe/11550]
Microsoft compatibility: spurious errors on complex variadic return types

Certain test cases with complex return types involving variadic templates
could result in spurious errors in Microsoft mode.  Now fixed.
[Patch sent out 4/14/11.]

  template<int... I> struct A {};
  template<class X, class Y, class I> struct B;
  template<class X, class Y, int... J> struct B<X, Y, A<J...> > {	
    typedef int Q;
  };
  template<class... U> class C {};
  template<class... U> struct D {	
    D(int,int,int){}
    template<class... Z> typename B<C<U...>, C<Z&...>, int>::Q f(Z&&... args);
  };
  int main() {
    D<char, int>(1, 2, 3);
  }


3/25/11  [EDGcpfe/11473]
Internal error when "delete []" called with pointer to array

In GNU and Microsoft emulation modes, an attempt to call "delete []" with a
pointer to an array of a class with a virtual destructor had resulted in an
internal error ("make_vptr_field_lvalue: not class type") in configurations
that use IL lowering.  This regression was introduced in 4.2 (EDGcpfe/10873)
and is now fixed.  For example: [Patch sent out 4/14/11.]

  struct A {
    virtual ~A();
  };
  typedef A Arr[2];
  void f(Arr *a) {
    delete [] a;
  }


3/25/11  [EDGcpfe/11538]
"No side effect" warning suppressed inside decltype expressions

Warnings that an expression has no side effect are now suppressed
inside decltype expressions, because decltype expressions are now
used to test SFINAE conditions, and such tests may indeed have
a SFINAE purpose even though they have no side effects.
[Patch sent out 4/14/11.]

  template <class T> auto f(T p) -> decltype((p > 0), p) { return 0; }
  int main() {
    f(1);
  }


3/24/11  [EDGcpfe/11544]
Default temporary directory changed to /tmp

On non-Windows systems the default temporary directory has been changed
from /var/tmp to /tmp, which is more likely to have faster performance
on some Unix systems (i.e., because it is a tmpfs file system based in RAM).


3/24/11  [EDGcpfe/11539]
__is_convertible_to failed to instantiate its argument types

The type trait function __is_convertible_to failed to instantiate its
argument types when they are templates, and therefore in some cases
failed to correctly determine whether one type could be converted
to another.  Now fixed.  [Patch sent out 4/14/11.]

  template <class T> struct A {
    operator A<int>() { return A<int>(); }
  };
  int main() {
    int a[__is_convertible_to(A<char>, A<int>)];  // Formerly an error
  }


3/23/11  [EDGcpfe/11533]
Implicit typename not disabled during variadic prototype instantiations

Prototype instantiations are done for variadic functions even in
modes when nonclass prototype instantiations are not enabled.  Implicit
typename processing was not disabled during such prototype instantiations,
resulting in spurious errors.  Now fixed.  [Patch sent out 4/14/11.]

  template <class ... T, class U> void f(U p, T... args) {
    U::V * p;  // spurious "redeclaration of p" error
  }


3/23/11  [EDGcpfe/11522]
Variadic failure to deduce additional elements of explicit argument list

When an explicit argument list is provided for a variadic template
argument, additional elements can be deduced from the call arguments.
This did not work correctly when the deduction was from a template
argument list in the call.  Now fixed.  [Patch sent out 4/14/11.]

  template<typename... T> class A {};
  template<int I, typename... T> void f(A<T...>&);
  int main() {
    A<int, double> t;
    f<0>(t);
  }


3/22/11  [EDGcpfe/11531]
Spurious ambiguity on partial specialization of variadic template

A spurious ambiguity in selecting a partial specialization could occur
if the partial specializations contained a function type in which the
function parameter list contained a function parameter pack.  Now fixed.
[Patch sent out 4/14/11.]

  template <class T> struct A {};
  template <class T, class ... args> struct B;
  template<class T, class... args> struct B<T(args*...)> {
    typedef int type;
  };
  template<class T, class... args> struct B<A<T>(args*...)> {
    typedef int type;
  };
  typedef int (*fp)();
  B<A<fp>()>::type x;


3/21/11  [EDGcpfe/11529]
Spurious error on variadic expansion starting with complex identifier

Under some complex conditions, including the fact that the start of a
pack expansion is an identifier that is a qualified name and/or
contains a template argument list, a spurious error could result
during an instantiation.  Now fixed.  [Patch sent out 4/14/11.]

  namespace N {
    template<class T> T&& f(T& _Arg);
    template<class... U> class A;
    template<class T, class... U> struct A<T, U...> {
      template<class... V> A(V&& ...t) {}
    };
    template<class... U> A<U &&...> g(U &&... _Args) {	
      return (A<U &&...>(::N::f<U>(_Args)...));
//                               ^ expected an expression
    }
  }
  int main() {
    N::g(1,2);
  }


3/21/11  [EDGcpfe/11528]
Microsoft compatibility: Internal error with default template arguments
and new-style SFINAE in Microsoft mode

Version 4.3 introduced a problem that could result in an internal error
(in get_expr_rescan_info) on default template arguments of function
templates in Microsoft mode when using new-style SFINAE (e.g., in C++0x mode).
Now fixed.  [Patch sent out 4/14/11.]

  template <bool b, class T> struct enable_if {
    typedef T type;
  };
  template <class T, class T2> struct is_same {
    static const bool value = true;
  };
  template <class T, class T2> struct A {
    template<class U, class... V,
           class = typename enable_if<!is_same<U, T2&>::value, void>::type>
               A(U&& u, V&&... v) { }
  };
  int main() {
    A<int, int>(1, 2);
  }


3/18/11  [EDGcpfe/11524]
Variadic member template problem when not doing nonclass prototype
instantiation

Variadic templates must have their prototype instantiations done in order
for real instantiations to be processed correctly.  Prototype instantiations
of member function templates were not being done in modes in which
nonclass prototype instantiations were not enabled.  Now fixed.
[Patch sent out 4/14/11.]

  template <class ... T> void g(T... args) {}
  template <class T> struct A {
    template <class ... U> void f(U... args) {
      g(args...);  // Spurious error when f was instantiated
    }
  };
  int main() {
    A<int> a;
    a.f(1,2,3);
  }


3/17/11  [EDGcpfe/11521]
IL display build problem on Windows without CPPCLI_ENABLING_POSSIBLE

The IL display program did not build properly on Windows when
CPPCLI_ENABLING_POSSIBLE was FALSE.  Now fixed.  [Patch sent out 4/14/11.]


3/17/11  [EDGcpfe/11520]
Access checking regression in template argument substitution

Version 4.3 introduced a regression that could cause spurious access
errors during template argument substitution.  Now fixed.
[Patch sent out 4/14/11.]

  class A {
    typedef int (A::*pmf)(int);
    template <int I> int f(int arg);
    template<pmf mf> int Cat(int arg);
    void g() {
      pmf x = &A::Cat<&A::f<1> >;  // spurious A::f<1>(int) not accessible
    }
  };


------------------------------------------------------------------------------
Version 4.3, March 17, 2011

3/17/11
Version number and IL version number changed to 4.3


3/16/11  [EDGcpfe/11495,EDGcpfe/11515]
__is_standard_layout

When type traits helpers are enabled (see entry of 3/21/06), the front end
now accepts a new type trait pseudo-function "__is_standard_layout".  Given a
complete object type (or an array thereof), it produces "true" if that type
is a scalar type or a standard layout class type.  (A "standard layout" class
type is a class type with no virtual functions or base classes, no fields or
bases that are non-standard-layout classes, and a few other constraints that
ensure that the class' memory layout can be modeled using a C-style struct.)

(This supports the implementation of the C++0x class template
std::is_standard_layout and matches a facility of GNU compilers.)


3/16/11  [EDGcpfe/11453, EDGcpfe/11492]
Invalid IL when promoting a static variable that refers to a GNU address label

In cases where a local static variable is initialized to a constant that
contains a GNU address label, and lowering determines that variables in the
scope are to be promoted to the file scope, invalid IL (a file scope constant
that pointed into the function scope) had been generated, resulting in various
errors (e.g., "remap_ptr_to_entry_number: pointer in secondary trans unit")
depending on the configuration.  The initialization of promoted static
variables that refer to GNU address labels is now re-written as executable
code, avoiding the memory region issue.  For example (with --g++):

  void f() {
    struct A { A() {} };
    static void *x = &&label;
  label: ;
  }


3/15/11  [EDGcpfe/8405]
Variadic templates

Variadic templates, as described by N2242 and extended by N2555 and
N2933, are now implemented.  They allow templates that take variable
numbers of arguments, as in

  template<class ...T> void f(T ...args) {
    int a[] = {0, args..., 5};
  }
  int main() {
    f(1, 2, 3, 4);
  }

Variadic templates are enabled by default in C++0X mode; they can also be
controlled independently of C++0X mode via the --[no_]variadic_templates
command-line options.  There is a controlling global variable,
variadic_templates_allowed, and a feature macro is optionally defined as
specified by the DEFINE_MACRO_WHEN_VARIADIC_TEMPLATES_ENABLED and
MACRO_DEFINED_WHEN_VARIADIC_TEMPLATES_ENABLED configuration macros.

Pack expansions are supported in parameter lists, argument lists,
brace-enclosed initializers, base class specifiers, mem-initializers,
exception specifications, attributes, and capture lists.

The bodies of variadic template functions are always parsed ("prototype
instantiations" are done); this is necessary in order to discover and
record the pack expansions.  Such prototype instantiations are done
regardless of whether they are usually done for templates in the
current mode and configuration.  Note, therefore, that converting
an existing template to a variadic version might produce errors for
pre-existing nonstandard or erroneous code that previously went
undiagnosed.

Implementing variadic templates required enhancements to name mangling
and demangling to support parameter packs in parameter lists and
template argument lists, and some new operators (e.g., sizeof...()).
The IA-64 ABI version of the changes has been submitted to the ABI
spec group.

Template argument lists can now contain a new kind of entry, with
kind == tak_start_of_pack_expansion, and therefore customer code
that traverses template argument lists should consider using the
new begin_template_arg_list_traversal, advance_to_next_template_arg,
and the "...simple" versions of those routines, to skip over the
start-of-pack-expansion entries.  (IL CHANGE)

Also note that in instantiations of functions that have parameter packs
it is now possible for multiple parameter variables to have the same
name.  (IL CHANGE)


3/15/11  [EDGcpfe/4477]
Only use parameters for which arguments were provided for partial ordering

When function templates contain default arguments, only the parameters
corresponding to actual arguments of the call should be used for partial
ordering purposes.  The front end now implements this rule in all modes
except Microsoft mode when microsoft_version < 1400.

  template <class T> void f(T, int = 1){}   // #1
  template <class T> void f(T*, char = 0){} // #2
  int main() {
    int *p = 0;
    f(p);  // calls #2, formerly ambiguous
  }


3/14/11  [EDGcpfe/11494]
const/volatile on function types in template arguments

The front end now accepts const- and/or volatile function types in template
arguments.  For example:

  template<typename T> struct X {};
  X<void()const> x;  // Now accepted

This agrees with the pending resolution of core issue 547.


3/11/11  [EDGcpfe/11490]
Invalid IL when HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS is TRUE

In IA-64 ABI configurations that use lowering where
HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS is TRUE, a constructor init where
an argument is passed via copy constructor had resulted in invalid IL
(where the expression type doesn't match the parameter type).  In C generating
back end configurations, this had resulted in a "check_type_of_variable_node"
internal error.  For example:

  struct A {
    A();
    A(const A&);
  };
  struct B {
    B(A) {}
  };
  struct D : virtual B {
    D(A a) : B(a) {}
  };
  A a;
  D d(a);


3/10/11  [EDGcpfe/11434]
Dependent calls now find static functions

In accordance with core issue 561, the front end in C++0X mode now
sees static functions when processing a dependent call in a template.
Previously, in accordance with the C++03 standard, such functions
were considered to be invisible to dependent calls.

  namespace N {
    static int sf(int);
  };
  using namespace N;
  template <class T> auto psf1(T p1) -> decltype(p1+sf(p1));
  int main() {
    psf1(0);  // Now accepted in C++0X mode
  }


3/10/11  [EDGcpfe/11471]
Incorrect folding of dependent function call in template in Microsoft mode

In Microsoft mode when prototype instantiations are done (an unusual
combination, since MSVC doesn't parse templates), a function call
where the left operand of the bound function is not dependent but
the right is was improperly folded to a constant.  As a result,
the generated code from the C++-generating back end did not include
the left operand and did not compile correctly.  Now fixed.

  struct Foo {
    template <typename T> void Bar(T val) {}
  };
  template <typename T> void Baz(T val) {
    Foo f;
    f.template Bar<T>(val);  // Output was Foo::Bar< T> (val); now
                             // f.Bar< T> (val)
  }

3/9/11   [EDGcpfe/11483]
Invalid reference to memory preceding a constant entry on the stack

In some cases, the front end erroneously referred to memory preceding
a constant entry on the stack to copy a bit from there to the IL lowering
flag of a newly-created constant entry.  We're not sure if there are any
observable consequences of this problem; it was observed while stepping
through a test case in a debugger.  It's possible that in some cases a
constant in an initializer might not get lowered, which could cause
aborts further on in a back end, but we don't have an example that
demonstrates that.  In any case, it's now fixed.


3/9/11   [EDGcpfe/11481]
Template deduction rescan of overloaded function or template

The new-style SFINAE changes (see entry of 4/26/10) did not handle
an overloaded function or template quite right in some cases where
the context provides a guide type that can select the instance of
the function, specifically in a non-deduced template argument.
Now fixed.

  template<typename T> int cmp1(T a, T b);
  template<typename T, int (*cmp)(T, T)> struct A { };
  template <typename T> void f (A<T,cmp1> &);
  void g() {
    A<char,cmp1> a;  // Now accepted in --c++0x mode
    f(a);
  }


3/7/11   [EDGcpfe/11463]
Internal error on certain GNU attributes applied to a typedef in a cast

The front end previously aborted with an internal error in attach_attributes
(attributes.c) when certain GNU attributes applicable to functions (like
"format") were applied to a typedef for a function type appearing in a cast.
For example:

  typedef void F(char const*, ...);
  int main() {
    (F __attribute((format(printf, 1, 2)))*)0;  // Previously triggered an
  }                                             // internal error.

This is now fixed.  In addition, when the "const" attribute (which was one of
the attributes that triggered the internal error described above) is applied
to a type, it is now ignored with a warning (to match the behavior of GCC).


3/6/11   [EDGcpfe/11464]
C++-generating back end: non-dependent qualifiers in dependent member access
expressions

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, a member
access expression in a function template in which the object expression is
dependent but the member name is qualified by a non-dependent class name
was generated without that qualifier.  This is now fixed.  For example:

  struct S { int i; };
  template<typename T> int f(T* p) {
    return p->S::i;  // Previously generated as p->i
  }


3/3/11   [EDGcpfe/11429]
GNU-mode built-in vector function corrections

A few corrections have been made to the types of built-in GNU vector functions
(like __builtin_ia32_paddq).  Vectors of one or two 64-bit integers were
previously typed as vectors of type "long" in configurations where "long" is a
64-bit type: Now they're always typed as vectors of type "long long".  In
addition, the functions __builtin_ia32_loadhps, __builtin_ia32_loadlps,
__builtin_ia32_storehps, and __builtin_ia32_store_lps now take a pointer to a
vector of floating-point entities when gnu_version >= 40000 instead of a
pointer to a vector of integer entities (as was previously the case, and as
is still the case when gnu_version < 40000).


3/1/11   [EDGcpfe/11392]
Microsoft compatibility: Casts on wide string literals in initializers

In Microsoft mode, the front end previously treated ordinary string literals
that are explicitly cast to a pointer to the underlying character type
appearing in brace-enclosed initializers as if the cast weren't there.  Now
that special treatment is also applied for wide-character string literals.
For example:

  wchar_t s[] = { (wchar_t*)L"wide" };  // Now accepted in Microsoft mode.

(See also entry of 6/16/05.)


3/1/11   [EDGcpfe/11455]
GNU and Microsoft compatibility: incorrect template information file for
instantiations from deferred friends

In Microsoft mode and g++ mode when gnu_version < 30400 (and only in
certain configurations) it is possible for incorrect entries to be emitted
in the template information (.ti) file.  This could occur for instantiations
that result from friend declarations in class templates, the processing of
which is deferred to the end of the translation unit in the modes mention
above.  In the example below, the .ti file contained a "TC" entry for
A<int>::A where no entry should have been emitted.  This could result in a
prelinker loop.  Now fixed.  The extra .ti file entry can be observed on
Linux using the defines.h.linux supplied with the release, although it does
not result in a prelinker loop on our systems.

  template <class T> struct A {
    A() { }
  };
  template <class T> struct B {
    friend void f(B b) { A<T> a; }
  };
  int main() {
   B<int> b;
   f(b);
   return 0;
  }


2/28/11  [EDGcpfe/10504]
Warnings about entities that are declared but not referenced

The front end attempts to diagnose variables and functions that are declared
but not referenced (with various exceptions; e.g., unused declarations in
header files are not diagnosed).  However, when template definitions are not
parsed in their generic forms, this could lead to spurious diagnostics.
For example:

  int const K = 1;
  template<typename> int f() { return K; }
  int main() { return f<int>(); }
    // Previously, this triggered a "declared but never referenced" warning
    // in modes that don't parse template definitions and don't instantiate
    // used template instances (such as default C++ mode).  

Now, a more conservative strategy is used to avoid such spurious diagnostics
when template definitions are not parsed and used instances are not fully
instantiated.  (On the flip side, under such circumstances, some actually
extraneous declarations may no longer be warned about either.)


2/25/11  [EDGcpfe/11376]
Abort on __asm function body starting with a comment

When ASM_FUNCTION_ALLOWED and INCLUDE_COMMENTS_IN_ASM_FUNC_BODY are TRUE, the
front end executed an invalid memcpy operation (resulting in an abort) when
processing an __asm function body starting with a comment.  For example:

  __asm int f() { /**/ }
    // Previously triggered an abort in some configurations.

This is now fixed.


2/25/11  [EDGcpfe/11370]
Template-dependent C++0x alignment attribute

In some cases, a C++0x alignment attribute with a template-dependent type
argument specified on a field or variable with a nondependent type could
trigger a spurious error.  For example:

  template<typename T> struct S {
    [[align(T)]] int x;  // Previously triggered a spurious error indicating
  };                     // a too-small alignment.

This is now fixed.


2/24/11  [EDGcpfe/11319]
__is_trivial

When type traits helpers are enabled (see entry of 3/21/06), the front end
now accepts a new type trait pseudo-function "__is_trivial".  Given a
complete object type (or an array thereof), it produces "true" if that type
is a scalar type or a class type with a trivial destructor that is trivially
default-constructible and trivially copyable/movable.

(This supports the implementation of the C++0x class template std::is_trivial
and matches a facility of GNU compilers.)


2/23/11  [EDGcpfe/11419]
Exported templates disabled by default in all modes

Because export has been removed from the C++0x language, and is not
generally supported by EDG's customers, EXPORT_ENABLING_POSSIBLE and
DEFAULT_EXPORT_TEMPLATE_ALLOWED are now FALSE by default.


2/23/11  [EDGcpfe/11416]
Memory corruption on error on recursive instantiation of default argument

A bit of IL created when a recursive instantiation error is detected while
instantiating a template default argument was in the wrong memory region,
which led to unpredictable behavior later if the storage for the entry
was reused.  Now fixed.  The problem always followed an error with the text
"recursive instantiation of default argument".


2/22/11  [EDGcpfe/11418]
Parsing of templates turned on by default in C++0X mode

The parsing of nonclass templates is now on by default in C++0X mode.
The default can be changed via DEFAULT_CPP0X_DEPENDENT_NAME_PROCESSING.
(The similar DEFAULT_DEPENDENT_NAME_PROCESSING controls the default
for pre-C++0X modes).  GNU and Microsoft C++ modes continue to do
what they did previously for the combination of those modes and
C++0X mode (parsing for GNU, no parsing for Microsoft).


2/18/11  [EDGcpfe/11406]
Incorrect lookup in template static data member initializer

If a template parameter of a class template had the same name as an
entity from the enclosing namespace, and that name was used in the
initializer of a template static data member, the namespace member was
found when the template parameter should have been.  Now fixed.

  namespace N {
    template < class T > struct A {static const int I = 1; };
    template < typename T, typename A = N::A < T > > struct B {
      typedef int I;
      static const int pos;
    };
    // Spurious "missing template argument list for class template A"
    template < typename T, typename A > const int B < T, A >::pos = (A::I)-1;
  }
  int i = N::B<int>::pos;


2/17/11  [EDGcpfe/11398]
GNU C++ compatibility: Block-extern declarations involving local types

In GNU C++ mode, block-extern variable declarations involving a local type
are now accepted with a warning (in GNU C++0x mode, as in ordinary C++0x mode,
such declarations are silently accepted).  Block-extern function declarations
are still treated as errors in GNU C++ mode (except GNU C++0x mode).
For example:

  void f() {
    struct S {};
    extern S x;        // Now accepted (with a warning) in GNU C++ modes.
    extern void g(S);  // Still an error in non-C++0x GNU C++ modes.
  }


2/17/11  [EDGcpfe/11338]
GNU C++ compatibility: __decltype

In GNU C++ modes with gnu_version >= 40300, the front end now accepts the
C++0x "decltype" feature via the alternative keyword "__decltype".  This is
the case even in non-C++0x modes.  (In GNU C++0x modes, both the standard
keyword "decltype" and the GNU alternative "__decltype" are accepted.)


2/16/11  [EDGcpfe/11395]
A template constructor should be usable as a default constructor

A template constructor that can be called with zero arguments should be
usable as a default constructor.  Now, it is.

  struct A {
    template <class T = int> A(T = 1){}
  };
  A a;  // Formerly an error; now accepted


2/15/11  [EDGcpfe/11384]
IL representation for array type with dependent but unknown bound (IL CHANGE)

The tk_array variant of an IL type has been extended so that it can
represent an array with a template-dependent but completely unknown
number of elements.  This comes up for variadic template cases like

  template <class... T> void f(T ... args) {
    int x[] = {args...};  // Array type of x has unknown number of elements
  }

The change is that a tk_array type with is_template_dependent_size_array
TRUE can have element_count_constant NULL to indicate that we have
no information on the number of elements.


2/15/11  [EDGcpfe/11383]
Lower asm statements in all modes

Expressions in asm statements had previously been lowered only when
gnu_mode was true.  A change has been made to lower them in all modes
(though the un-modified front end only generates them when gnu_mode is true).
This is useful in cases where the front end has been locally modified to accept
GNU asm statements in other modes (i.e., where gnu_mode is false).


2/10/11  [EDGcpfe/11371]
Use of temporaries in copied expressions

In certain cases (i.e., compound assignment of a Microsoft indexed property,
and the GNU conditional with omitted operand), the front end had made
reusable copies of expressions, where the lvalueness of the expression
had not yet been determined.  In cases where the copied expression was
originally an lvalue and later changed to an rvalue, assumptions
about whether the copied expression was invariant were violated, resulting
in IL that was not properly sequenced.  In the compound assignment in the
example below, it wasn't guaranteed that the same index arguments would
be passed to the get and put routines (it depended on the order of
evaluation by the back end).  Now, these routines are passed the same
index values:

  extern "C" int printf(const char *, ...);
  int i = 0;
  struct B {
    __declspec(property(get=get,put=put)) int p[][];
    int value[3];
    int get(int s, int t) { return value[t]; }
    void put(int s, int t, int v) { value[t] = v; }
  } b;
  int f() {
    i++;
    return 0;
  }
  int main () {
    b.p[0][0] = 0;
    b.p[0][1] = 1;
    b.p[0][2] = 2;
    i = 0;
    b.p[f()][i] += 100;                     // i is incremented in f()
    printf("b.p[0][0] = %d\n", b.p[0][0]);  // should print 0
    printf("b.p[0][1] = %d\n", b.p[0][1]);  // should print 101
    printf("b.p[0][2] = %d\n", b.p[0][2]);  // should print 2
  }


2/9/11   [EDGcpfe/11349]
Microsoft compatibility: function template as argument for deduced parameter

The standard requires that if a function template is passed as an
argument for a deduced parameter the parameter be considered
nondeduced (core issue 325).  MSVC apparently doesn't do that, and
instead does what we did up until version 4.1 (see change for
EDGcpfe/9711 below), which is that the template is considered not
to match, but other overloaded functions can still match.  We've
restored that behavior in Microsoft mode.

  struct A { };
  struct B {
    virtual int f(A*) = 0;
    template<typename T> int f(T* tp) {
      return g(&B::f, tp);  // Once again accepted in Microsoft mode
    }
  };
  struct C { };
  template<typename T, typename U> int g(T t, U*) {
    return 0;
  }
  void g(B* bp, C* cp) {
    bp->f(cp);
  }


2/7/11   [EDGcpfe/11331]
g++ allows real floating --> complex

g++ (as of its version 4.3) allows conversion of a real floating value
to a complex type (which is allowed by the C99 standard, but for
some reason was prohibited by g++ -- but not gcc -- up to version 4.2).
We now emulate that in g++ mode.

  void g(float f) {
    __complex__ float cf;
    cf = f;  // Now accepted in g++ mode for gnu_version >= 40300
  }


2/4/11   [EDGcpfe/11343]
Ambiguity not detected during template substitution

The substitution process used in template processing failed to detect
certain ambiguities.  As a result, the following case would fail because
both #1 and #2 were considered viable, but only #2 was viable because
#1 would result in an ambiguity during instantiation.  Now fixed.

  template <class T> void f(typename T::X* x);  // #1
  template <class T> void f(typename T::Y* x);  // #2
  struct A { typedef int X; };
  struct B {
    typedef int X;
    typedef int Y;
  };
  struct C : public A, public B {};
  int main() {
    f<C>(0);  // should call #2 because #1 is ambiguous
  }


2/1/11   [EDGcpfe/11301]
Discard template conversion functions that match standard conversions

Conversion functions that match some conversions that can be done via
standard conversions, e.g., T to T&, or derived-class to base-class,
are not supposed to be called implicitly to do conversions (they can
be called using explicit call syntax).  This has previously worked
properly for non-template conversion functions.  However, in
some cases conversion function templates produced instances that
matched some of those disallowed patterns, and were nonetheless
used for conversions.  Now fixed; such instances are now discarded.

  struct E {
    template <typename T> operator T&() const;
  };
  int main() {
    E e;
    const E& c = e;
    E& r = (E&)c;  // Conversion function no longer used
  }


2/1/11   [EDGcpfe/10868]
C++-generating back end: typedefs in qualifiers in template arguments

In most cases, in order to avoid unnecessarily verbose template argument
lists, the C++-generating back end uses the underlying type of a typedef in
a template argument instead of the typedef name itself.  This was done even
in the qualifiers in a recorded name reference when the front end is
configured with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE, which
could lead to incorrect output when the qualification required for the
underlying type is different from that of the typedef that appears in the
source code.  This has now been fixed by always using the recorded typedef
name when putting out such a name reference unless the typedef cannot be
used at that point in the source because it is inaccessible or has not yet
been declared; in those cases, the entire recorded form is ignored and the
name is generated normally.  For example:
 
  namespace N {
    template <typename T> struct S { static const bool b = false; };
  }

  template <bool> struct D { };

  template<typename T> struct X {
    typedef N::S<T> ST;
    D<ST::b && ST::b> Var;  // Previously generated as "S<T>::b"
  };


1/31/11  [EDGcpfe/11307]
Incorrect reuse of temporaries in some lowered full expressions

During the lowering of certain full expressions, some subexpressions (e.g.,
VLAs, lambdas, compound literals) were mistakenly being treated as full
expressions, causing temporary variables to be reused before the end of
the full expression.  This has now been fixed.  In this example (with --g++
--c++0x), in the cases indicated below, the same temporary was being used for
the first and third arguments in the call to f():

  extern "C" int printf(const char *,...);
  int ret = 0;
  struct A {
    ~A() {}
  };
  void f(A a1, int, A a2) {
    if (&a1 == &a2) {
      printf("FAIL\n");
      ret = 1;
    }
  }
  struct B { int i; };
  int main() {
    int i = 2;
    f(A(), 0, A());                  // okay (different temporaries)
    f(A(), ({0;}), A());             // okay (different temporaries)
    f(A(), []{return 0;}(), A());    // okay (different temporaries)
    f(A(), [&i]{return 0;}(), A());  // bad (same temporary used)
    f(A(), ((int(*)[i]){0},0), A()); // bad (same temporary used)
    f(A(), ((B){i},0), A());         // bad (same temporary used)
    return ret;
  }


1/29/11  [EDGcpfe/11303]
Suppress warning about unusable template parameter if it has a default value

The front end issues a warning if a template constructor or conversion
operator declares a template parameter that is not used in the function
type, under the assumption that such a template parameter could not be
deduced.  Now that default arguments are allowed for template parameters
of function templates (see 6/23/10 entry), such template parameters
could be used even though they are not part of the function type.
Furthermore, this is a useful technique when using "enable_if" like
techniques.  The warning is now suppressed for template parameters that
have default values.

  struct X {
    template <class T, class = typename T::X> X(T) {}
  };
  struct A { typedef int X; };
  int main() {
    A a;
    X x(a);  // okay: A has a type member X
    X x2(1);  // error: no matching constructor
  }


1/28/11  [EDGcpfe/11312]
Microsoft property references and subscripting

Further changes to be more compatible with Microsoft property
references and subscripting (see EDGcpfe/11049 below for the previous
round of changes): this time, if a property has a "get" accessor that
returns a class type that has an operator[] function, and there
are no overloaded accessor functions that have parameters (and
therefore could be used for subscripting), the class-returning accessor
is called in a subscripting context to produce the class object, which
can then be subscripted.

  extern "C" int printf(const char *, ...);
  struct X {
    X &operator[](int) { printf("0\n"); static X lx; return lx; }
  } xx;
  struct A {
    __declspec(property(get=getp,put=putp)) X x;
    X getp() { printf("1\n"); return xx; }
    void putp(int) { printf("2\n"); }
  } a;
  int main() {
    X x = a.x[1];  // Now accepted, prints 1 0
  }


1/25/11  [EDGcpfe/10641, EDGcpfe/11310]
Reducing use of inactive list to improve performance

The front end now constructs hash tables for the names in a given scope.
This allows us to eliminate many of the uses of the inactive list
that have proven to be performance bottlenecks.  This mechanism will be
applied to more uses of the inactive list in the future.


1/24/11  [EDGcpfe/11302]
Abort on malformed friend template declaration in Microsoft-mode

In Microsoft C++ mode, the front end aborted (null pointer indirection in
is_constructor_decl) on certain malformed friend template declarations
referring to a nested class template of an incomplete class template.
For example:

  template<typename> class C;
  struct S {
    template<typename T> template<typename U>
      friend struct C<T>::N<U>;  // Previously triggered an abort.
  };


The abort is now fixed, but unlike the Microsoft compiler, such erroneous
constructs still elicit errors.


1/20/11  [EDGcpfe/11295]
GNU C++ compatibility: List initializers in return statements

In version 4.2, the front end added support in GNU C++0x mode for a small
subset of C++0x list initialization syntax (see Changes entry of 6/15/10).  
Recent GCC versions also accept this syntax (with a warning) in non-C++0x
modes.  The front end now emulates that behavior in GNU C++ mode.

  struct S { int x; };
  S f() { return { 42 }; }  // Now accepted with --g++ (with a warning).


1/18/11  [EDGcpfe/11290]
C++-generating back end: typedefs to decltype or typeof as template arguments

In most cases, in order to avoid unnecessarily verbose template argument
lists, the C++-generating back end uses the underlying type of a typedef as
a template argument instead of the typedef name itself.  When the
underlying type is a C++0x decltype or GNU typeof, however, the resulting
code was sometimes erroneous.  For example, the operand of a decltype might
be inaccessible in the context in which the template-id is used, or (in a
configuration with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE) a
name in the operand might be generated without the necessary qualification.
This has now been fixed by using the typedef name instead of the underlying
type when the underlying type is a decltype or typeof construct.  For
example:

  struct S {
    static int f();
    typedef decltype(f()) type;
  };
  template<typename T> struct X;
  typedef X<S::type> xi;  // Previously generated as X<decltype(f())> when
                          // name references are recorded


1/18/11  [EDGcpfe/11191]
Bound function for static template with explicit arguments treated as
simple function

A reference to a static member function template with explicit template
arguments that identify a single instance of the template can now be
used as a function address.  Formerly, it was viewed as a bound
function, and a spurious error was issued ("a pointer to a bound
function may only be used to call the function") if it wasn't
immediately called.

  struct A {
    template <class T> static void f();
  } a;
  int main() {
    void (*p)() = a.f<int>;  // No longer an error
  }


1/18/11  [EDGcpfe/11289]
Internal error on using-declaration of operator=

An internal error could occur (in add_symbol_to_overload_list) if a class
contained a using-declaration referring to a base class operator= function
followed by the declaration of an operator= function or template that did
not suppress the generation of the implicitly declared operator=.  Now fixed.

  template <class T> struct A { };
  template <class T> struct C {};
  template <class T> struct B : public A <T> {
    using A<T>::operator=; 
    template <class U> B& operator=(C <U>& rhs) { return *this; }
  };
  int main() {
    B<int> b;
    C<int> c;
    b = c;
  }


1/18/10  [EDGcpfe/11282]
Source sequence entries and local static variables

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, a variable usually points to the
source sequence entry that corresponds to its primary declaration.  An
exception is a variable that has only been declared using block-extern
declarations (see Changes entry of 3/5/97).  However, the implementation of
that exception accidentally caused local static variables not to point back to
their associated source sequence entry.  That is now fixed.  For example:

  void f() {
    static int si;  // Previously the a_variable entry did not point to the
  }                 // source sequence entry for this declaration.


1/17/11  [EDGcpfe/11262]
Microsoft compatibility: Binding a reference to non-const to a bit field
in overload resolution

The C++ standard requires that in overload resolution a parameter of
type lvalue reference to non-const should be allowed to bind to an
argument that is a bit-field lvalue.  Later, if the function is chosen,
an error is issued because such a reference cannot bind to a bit field.
MSVC seems to disallow such cases early in overload resolution (checked in
6.0 through 10.0), and now we emulate that in Microsoft mode.

  struct A {
    int i:2;
  };
  void f(int &);
  void f(int);
  int main() {
    A a;
    f(a.i);  // No longer ambiguous in Microsoft mode; chooses f(int)
  }


1/17/11  [EDGcpfe/11288]
Microsoft compatibility: Defining __STDC__ macro

The Microsoft compiler does not define __STDC__, and neither does the
front end in Microsoft emulation mode, but that behavior can cause problems
when using Microsoft emulation mode with non-Microsoft system headers.
In particular, on Linux systems (with GNU headers) when __STDC__ is not defined
and <stdio.h> is included, "const" is defined as a NULL macro (effectively
disabling it during the rest of the compilation).  To allow user control over
this behavior, a new configuration macro DEFINE_STDC_IN_MICROSOFT_MODE has been
added.  Its default value is FALSE on Windows systems (i.e., when EDG_WIN32 is
TRUE), otherwise its value is TRUE.  In this C++ example, on a Linux system
using GNU headers, when emulating Microsoft, an error had been issued
("function 'f' has already been defined"), but now with
DEFINE_STDC_IN_MICROSOFT_MODE set to TRUE, the example compiles properly
(creating a pair of overloaded functions):

  #include <stdio.h>
  void f(const char *) {}
  void f(char *) {}


1/15/11  [EDGcpfe/11277]
Exception specifications on templates when exceptions are disabled

The front end was changed to issue a warning instead of an error on
exception specifications on function definitions when support for
exceptions was disabled (see 1/16/06 entry).  This change failed to
address such diagnostics on function templates and member functions of
class templates.  Now fixed.  Formerly, the following example would produce
an error with the --strict and --no_exceptions option.  It now produces
a warning.

  template <class T> void f(T) throw() {}


1/14/11  [EDGcpfe/11270]
Partial ordering of lvalue vs. rvalue references

Core issue 1164 clarified that an lvalue reference parameter should be
considered more specialized than an rvalue reference parameter.  We
now implement the revised rules, except in Microsoft, g++, and Sun modes.

  template<typename T> int f(T&);
  template<typename T> int f(T&&);
  int i;
  int j = f(i);  // formerly ambiguous, now calls f(T&)

1/11/11  [EDGcpfe/11262]
Microsoft compatibility: Binding an rvalue reference to a bit field

MSVC10's implementation of rvalue references includes the late change to
the standard's wording that disallows binding an rvalue reference to an
lvalue.  However, apparently MSVC does not apply that rule to bit-field
lvalues; in that case it allows the bit-field reference to be converted
to an rvalue and the rvalue reference to be bound to that.  We now
emulate that behavior in Microsoft bugs mode.

  struct AA {
    int foo : 6;
  };
  void bar(int &&);
  void bar(int &);
  int main() {
    AA aa;
    AA *obj = &aa;
    int &&r = obj->foo;  // Now okay in Microsoft bugs mode
    bar(obj->foo);       // Now selects bar(int &&) in Microsoft bugs mode
  }


1/7/11   [EDGcpfe/11261]
Internal error on lambdas with implicit return type in some configurations

In some configurations with MAINTAIN_NEEDED_FLAGS set to FALSE and
IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE, the front end could abort with an
internal error in scope_for_routine ("scope for routine is NULL") when parsing
a lambda expression with an implicit return type.  For example:

  void f() {
    int total = 0;
    auto lambda = [&total](int x){ return x; };
      // Previously aborted.
  }

This is now fixed.


1/7/11   [EDGcpfe/11254]
GNU C++ compatibility: __GXX_RTTI macro

According to the GNU documentation, the __GXX_RTTI macro is defined (with
a value of 1) when runtime type identification is enabled.  The front end
now emulates that behavior (in g++ emulation mode when gnu_version >= 40300).
Accordingly, users should remove any setting of __GXX_RTTI in their
predefined_macros.txt file (newer versions of make_predef_macro_table now
suppress that macro from the predefined_macros.txt file).


1/4/11   [EDGcpfe/11245]
GNU C++ compatibility: Mangling of local closure types

When multiple C++0x lambdas appear in a function, the IA-64 ABI introduces a
"discriminator" value to uniquely mangle closure types associated with lambdas
that have the same signature.  GCC, however, enforces distinct values even
when two local lambdas have different signatures, which results in nonstandard
encodings.  Now, when emulating GNU ABI bugs, the front end assigns
discriminator values corresponding to the encodings produced by GCC.
For example:

  int main() {
    int a = []{ return 37; }();         // Discriminator == 1
    int b([](int& a){ return a; }(a));  // Discriminator == 2 when emulating
  }                                     // GNU ABI bugs; 1 otherwise.
  


1/4/11   [EDGcpfe/11146]
GNU C++ compatibility: Attributes in conversion function names

In GNU C++ mode, the front end now accepts a type that starts with a GNU
attribute in the name of a conversion function.  For example:

  struct S {
    operator __attribute((vector_size(16))) float();  // Now accepted.
  };


1/3/11   [EDGcpfe/11189]
Position information for a GNU C function definition displacing an earlier
"extern __inline__" definition

In GNU C mode, an "extern __inline__" function definition can be displaced by
another definition appearing later in the translation unit (see Changes entry
of 6/18/02).  Previously, the displacing routine entry incorrectly recorded
the position information of the displaced routine entry.  This is now fixed:
The position of the later definition is now correctly recorded in the
corresponding IL entry.


1/3/11   [EDGcpfe/11239]
Microsoft compatibility: "<" handled incorrectly with --parse_templates

When parsing nonclass templates in Microsoft mode, a "<" was sometimes
incorrectly treated as starting a template argument list when it should
have been treated as a less-than sign.  This was a regression introduced
in version 4.2.  Now fixed.

  template <class T> struct A {
    int i,j;   
  };
  template <class T> struct C : A<T> {
    void f(); 
    A<T> ap; 
  };
  template <class T> void C<T>::f() {
    if (ap.i < ap.i) { }
  }


1/3/11   [EDGcpfe/11240]
Microsoft compatibility: abort on ill-formed class template declaration

An abort could occur (in copy_type_with_substitution) on the declaration
of a Microsoft in-class specialization if the enclosing class was declared
with an illegal specifier ("static", in the case of the example below).
Now fixed.

  template<typename T1, typename T2> static struct A {
    template<bool Bool> inline T1 f(T2 x);
    template<> inline T1 f<false>(T2 x) { return (T1)x; }
  };


12/23/10 [EDGcpfe/11236]
Internal error in select_overloaded_copy_constructor

A change introduced in version 4.2 caused an abort in
select_overloaded_copy_constructor ("NULL constructor") in some
cases when a function has a parameter of an incomplete class
type and is potentially called with an argument of that same
class type.  Now fixed.

  class Incomp;
  struct A {
    A();
    A(Incomp);
    void operator+(const A&);
    void operator+(const Incomp &);
  };
  void g(const Incomp &p) {
    A() + p;
  }


12/23/10 [EDGcpfe/11235]
No multi-level pointer conversions if pointer representations differ

The implicit conversions defined for multi-level pointers, e.g.,
"pointer to pointer to int" to "pointer to const pointer to const int",
are now disallowed if any of the underlying pointer representations
differ, e.g., one is 32-bit and the other 64-bit, or one is a near
pointer and the other a far pointer.  For example, in --microsoft_16
mode:

  int x;
  int near *np;
  const int far *const far *fpp;
  int main() {
    np = &x;
    fpp = &np; // Now an error
    x = **fpp; // Without error, this is allowed and harmful
  }


12/22/10 [EDGcpfe/11087]
Source position of dependent member function in call expression

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
source position information in the enk_constant node designating a
dependent member function in a member function call was incorrect, with
both the starting position and, in configurations with
EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE, the ending position referring to
the left parenthesis following the member function name.  The positions
are now set correctly.  For example:

  template<typename T> struct A;
  template<typename T> struct B {
    A<T> a;
    int f() {
      return a.g();  // position of enk_constant node for g previously had
                     // position of ( instead
    }
  };


12/22/10 [EDGcpfe/11206]
C++-generating back end, GNU compatibility: template keyword before template-id
in prototype instantiation

In certain circumstances, g++ incorrectly reports an error when the template
keyword is omitted before a non-dependent template-id.  (Standard C++ only
requires the template keyword preceding a dependent template-id.)  In
configurations in which the C++-generating back end generates the definition
of templates from their prototype instantiations and
gcc_is_generated_code_target is TRUE, the C++-generating back end now works
around this problem by adding the template keyword preceding function names
that are generated with explicit template arguments.  For example:

  struct A {
    template<int N> int f();
  };
  template<int> struct B {
    A* ap;
    void g(B* bp) {
      bp->ap->f<1>();  // template keyword not required but triggers g++
                       // bug if omitted; now generated as
                       //    bp->ap->template f<1>()
    }
  };


12/19/10 [EDGcpfe/11225]
Explicit instantiation of class cannot be followed by "extern template"

An explicit instantiation of an instance of a class template cannot be
followed by an "extern template" (to suppress the instantiation of the
class members) of the same instance.  Formerly, the front end would
respect the last such directive encountered.  Now, a diagnostic is
is issued (a warning in g++ mode and a discretionary error in other modes),
and the "extern template" is ignored.  Note that if the class had direct
members that were affected by the instantiation directive, diagnostics
were issued on those members, but now the diagnostic is issued on
the class itself instead.  But if the class had no direct members affected by
the directive, no diagnostic was issued and the virtual function table was
suppressed when it should have been emitted (when using the IA-64 ABI).
Now, the vtable is emitted (when the diagnostic issued is not an error).

  // vtable for B<int> should have been emitted, but was not
  struct A {
    virtual ~A() {};
   void f() {}
  };
  template<class T> struct B : public A { };
  template class B<int>;
  extern template class B<int>;
  int main () {
    B<int> d;
    d.f();
  }


12/18/10 [EDGcpfe/11224]
Microsoft mode: quirk with "?" and class rvalues eliminated as of VC10

A quirk of Microsoft mode related to the "?" operator and suppressing a
copy of a class rvalue is now disabled as of microsoft_version=1600,
to match the behavior of VC10.  The quirk interacts very badly with
rvalue references, allowing stealing of the contents of a class lvalue,
which is presumably why Microsoft fixed that issue when it added
rvalue references.

  extern "C" int printf(const char*,...);
  struct string {
    string(const string& _Right) {}
    string() {}
    string(const char* ptr) {}
    string(string&&) {
      printf("Ouch\n");
    }
  };
  int main() {
    string x("test");
    string thief = true ? x : "empty";  // Contents of x were stolen
  }


12/17/10 [EDGcpfe/11160]
GNU built-in variadic parameter operations

In configurations with GCC_BUILTIN_VARARGS set to TRUE, the front end supports
GCC-like built-in variadic parameter operators like __builtin_va_start and
__builtin_va_arg.  Previously, these operators were implemented as keywords.
Now they're implemented as GNU built-in functions that are handled specially.
As a consequence of this change, a program can e.g. declare local variables
with the names of these operators, or, in C++ mode, qualify the operator
names with "::".  E.g.:

  void f(__builtin_va_list a, __builtin_va_list b) {
    ::__builtin_va_copy(a, b);  // Now accepted in g++ mode.
    int __builtin_va_end = 1;   // Now accepted in g++ mode.
  }


12/15/10 [EDGcpfe/11220]
Pure-specifiers ("= 0") on member function definitions

The grammar in the C++ standard does not permit a member function declaration
with a pure-specifier (i.e., "= 0" following the parameter list) to also be a
function definition.  Version 4.2 unintentionally dropped that restriction.
It has now been reinstated (a discretionary error is issued), except in
Microsoft mode (where a warning is issued).  For example:

  struct S {
    virtual void f() = 0 {}  // Accidentally accepted in version 4.2.
  };                         // Now an error (except in Microsoft mode).


12/14/10 [EDGcpfe/11210]
Old-style specializations, guiding declarations, and parameter qualifiers

In modes that allow them, guiding declarations that are also old-style
specialization definitions acquired top-level parameter type qualifiers (those
recorded in a_param_type entries) from the template declaration but those
qualifiers were not applied to the corresponding parameter variable type
(a_variable entries).  In addition to resulting in inconsistent IL, the C code
generated by the C-generating back end was not compilable with Microsoft's
Visual C version 6 compiler.  For example:

  template<class T> void f(T const) {}
  void f(int) {}  // Old-style specialization and guiding declaration: This
                  // previously had inconsistent types recorded in the
                  // a_param_type and corresponding a_variable entries.

This is now fixed: The types declared in the specialization definition are
recorded in all cases.


12/14/10 [EDGcpfe/8817]
Spurious error on nontype template parameter followed by "<"

A spurious error could be issued if a nontype template parameter was followed
by an "<".  Now fixed.

  template<int i, bool b = i < 2> struct A {};
  A<1> a;


12/9/10  [EDGcpfe/11201]
Spurious errors on C++0x trailing return type with multiple specifiers

In C++0x mode, the front end mistakenly reported that the "auto" specifier
announcing a trailing return type was invalid when another specifier (like
"inline") preceded it.  For example:

  inline auto f()->int;  // Previously triggered spurious errors in C++0x
                         // mode.

This is now fixed.


12/8/10  [EDGcpfe/11197]
C++-generating back end, GNU/Microsoft compatibility: name references in
prototype instantiations with dependent base classes

The C++ Standard says that the lookup for an unqualified name in a class
template scope never looks into a dependent base, and the output of the
C++-generating back end when template definitions are generated from the
prototype instantiations relied on this feature.  The Microsoft and GNU C++
compilers, however, do not implement this rule, leading to some programs
having a different meaning in the generated code than they did in the
original source, as a name that originally referred to a declaration
outside the class template might be taken by the target compiler to refer
to a member of a dependent base.  This is now fixed: if the target compiler
searches dependent bases in unqualified name lookup, names in class
templates with dependent bases that refer to declarations outside the
template that previously were generated as unqualified names are now
qualified names in the generated code.  For example:

  template<int I> struct Base {
    struct A { };
  };

  template<int I> struct Derived {
    struct A { };
    struct B: Base<I> {
      typedef typename Derived::A A;  // Previously generated as
                                      //   typedef A A;
    };
  };


12/8/10  [EDGcpfe/11038]
GNU C compatibility: Redefining an integer typedef from a system header

In GNU C mode, a typedef for an integer type declared in a system header can
now be redeclared to an enum type with the same underlying type (a warning is
issued in such cases).  For example:

  # 1 "/a/system/file.h" 3
  typedef unsigned X;

  # 1 "/any/file.c" 
  typedef enum { e } X;  // Now accepted in GNU C mode (with a warning)


12/8/10  [EDGcpfe/11129]
C++-generating back end: friend function template declarations in prototype
instantiations

In configurations in which class template definitions are generated from
prototype instantiations, the C++-generating back end failed to add an
empty template argument list in a friend declaration referring to a
previously-declared function template.  The friend declaration thus
incorrectly declared a new, non-template function.  This is now fixed.  For
example:

  template<typename T> void f(T);
  template<typename T> struct S {
    friend void f<>(T);  // Previously generated as "void f(T)"
  };


12/5/10  [EDGcpfe/11166]
C++-generating back end, GNU compatibility: compound literals and designated
initializers

As extensions to C++, g++ accepts compound literals as in C99, as well as a
non-standard form of C99 designated initializers.  The front end also
accepts these constructs in --g++ mode, but the C++-generating back end was
formerly unable to generate code containing them.  This is now fixed.  For
example:

  union dbl { unsigned char __c; double __d; };
  double s_positiveInfinity = (__extension__ ((dbl){ __c: 12 }).__d);


12/3/10  [EDGcpfe/11165]
C++-generating back end: prototype instantiation name with unnamed parameters

In configurations in which PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, a
reference to the name of a class template prototype instantiation was
generated as a qualified name, i.e., referring to the class template
instead of to its injected-class-name, followed by a template argument list
composed of the template parameters.  If one or more of the parameters is
unnamed, the resulting output referred to an undeclared temporary name and
consequently was uncompilable.  This has now been fixed so that the bare
injected-class-name is used in such cases.  For example:

  template<int> struct S {
    S* next;  // Previously generated as ::S<__T29299888> *next
  };


12/2/10  [EDGcpfe/11180]
C++-generating back end: abort with COMPILE_MULTIPLE_SOURCE_FILES

In configurations with BACK_END_IS_CP_GEN_BE and COMPILE_MULTIPLE_SOURCE_FILES
set to TRUE, the front end could abort while processing files after the
first because a data structure used in mapping template parameter names was
not reinitialized between source files.  This is now fixed.


12/1/10  [EDGcpfe/11198]
Assertion failure in mangled_unnamed_type_encoding

In some configurations (mainly used for internal front end testing), mangling
of an unnamed enumerator type could cause an assertion failure in
mangled_unnamed_type_encoding.  Now fixed.  For example:

  enum { e };


11/30/10 [EDGcpfe/11150]
C++-generating back end: incorrect cast in dynamic initialization

When generating a dynamic initialization of a variable with a qualified
class type in which the initializer is a constructor call with a single
argument, the C++-generating back end represented the constructor call as a
cast to the qualified type.  This resulted in incorrect code when the
copy constructor of the class does not accept an argument of the qualified
type.  This has now been fixed to use the unqualified class type in the
generated cast.  For example:

  struct S {
    S(int);
    S(const S&);
  };
  volatile S s = S(0);  // Previously generated as ((volatile S)(0))


11/29/10 [EDGcpfe/11186]
Spurious "recursive instantiation of default argument" error

Version 4.2 introduced a regression that could result in a spurious
"recursive instantiation of default argument" message in some cases.
Now fixed.

  template <class K1, class K2> struct A {
    A(const K1& k1 = K1(), const K2& k2 = K2() ) : m1(k1), m2(k2) { }
    template <class A> bool operator()(A& a) const { return true; }
    K1 m1;
    K2 m2;
  };
  int main() {
    A< A<int, int>, int > aii;
  }


11/29/10 [EDGcpfe/11118]
Values of type trait helpers applied to non-class types in non-Microsoft modes

The type trait helper builtins, e.g., __has_assign, were originally
implemented for Microsoft mode, and, in accordance with the behavior of
MSVC, all returned false when applied to a non-class type.  However,
g++ (sensibly) returns true for many of those cases.  For example,
it's reasonable that __has_assign(int) should return TRUE, since indeed
one can assign ints.  Now, in all non-Microsoft modes, the type traits
return these improved values.

  extern "C" int printf(const char*, ...);
  enum E { e0 };
  bool b = __has_assign(E);
  int main() {
    printf("%d\n", b);  // Prints "1" now except in Microsoft mode
  }


11/29/10 [EDGcpfe/11187]
Assertion failure in set_source_corresp_name when creating pre-compiled header

In cases where a mangling pre-pass is run prior to creating a pre-compiled
header (see EDGcpfe/10231), an enumerator initializer that referred to a
previously mangled qualified enumerator would cause an assertion failure in
set_source_corresp_name.  This type of assertion failure might also occur
in other similar situations (i.e., referring to previously mangled entities
after creating a pre-compiled header).  For example (with --create_pch):

  // File ex.h:
  struct A {
    enum { e };
  };

  // File ex.c:
  #include "ex.h"
  enum {
    e1 = A::e
  };


11/22/10 [EDGcpfe/11169]
Microsoft compatibility: incorrect locale used for current directory name

The incorrect locale was used for translating the current directory name
into the internal encoding used in the front end.  This could result in the
failure to find include files in the current directory when the current
directory contains multibyte characters.  Now fixed.


11/18/10 [EDGcpfe/11155]
Position information with GNU statements

Two changes have been made to the position information recorded for GNU
statements.  First, the position of a prefix "__extension__" token is now
consistently recorded as the start of the associated statement.  Second, for
a GNU statement expression, the starting and ending positions recorded in the
associated enk_statement node now correspond to the positions of the
parentheses; previously, the position of the braces was recorded instead.
For example:

  void f() {
    __extension__({ 1; });
      // The starting position of the outer stmk_expr statement is now
      // that of the "__extension__" token.  The enk_statement node
      // representing "({ 1; })" now record the positions of the "(" and
      // ")" as the starting and ending positions.
  }


11/17/10 [EDGcpfe/11128]
asm operand marked with "+" now treated as both used and modified

In GNU mode, an asm operand marked with "+", which indicates the operand is
both read and written, is now handled that way by the front end with
regard to tracking uses of variables.  For example, the following
case no longer gets a spurious "set but never used" warning on data_p:

  int foo(const float *data) {
    const float *data_p = data;
    int result = 0;
    for (int i = 0; i < 10; i++) {
      asm (" ld.global %0, [%1]; "
           " add.u32 %1, %1, 4; "
           : "=r"(result), "+r"(data_p));
    }
    return result;
  }


11/17/10 [EDGcpfe/11162]
POSIX-style positional specifier for precision in printf formatting string

The front end now recognizes a POSIX-style positional specifier on the
precision specification in a printf formatting string.  (Such specifiers
were already recognized right after the "%" and on the field width
specification.  See DEFAULT_CHECK_PRINTF_SCANF_POSITIONAL_ARGS.)
The previous failure to recognize such a specifier resulted in spurious
warnings in some cases, as in this example:

  int main() {
    char buf[1024];
    sprintf(buf,"%1$*2$.*2$s","abcd", 2 );
    //                  ^^^ This is now handled properly
  }


11/16/10 [EDGcpfe/11164]
Incorrect using-directive lookup

A using-directive lookup could produce incorrect results if an initial
using-directive lookup was done (creating a synthesized projection symbol)
followed by a declaration of a new using-directive that refers to a symbol
that was declared before the original using-directive lookup.  Now fixed.

  namespace A {
    void f(){}
  }
  using namespace A;
  namespace B {
    void f(int){}  // symbol made visible by using-directive here
  }
  void g() {
    f();  // synthesized projection symbol created here
  }
  using namespace B;  // using-directive here
  void g2() {
    f(1);  // failed to find f(int)
  }


11/16/10 [EDGcpfe/11151]
Comma operator allowed in unevaluated constant expression in C99 mode

The C99 standard says (6.6p3) that a comma operator is allowed in a constant
expression if the expression is unevaluated.  We now allow that in
C99 mode.

  int *p = (1 ? 0 : (0, 0));  // Okay now in C99 mode (null pointer constant)


11/11/10 [EDGcpfe/11143]
Abort on namespace extension definition with GNU attributes

In GNU C++ mode, version 4.2 introduced a bug when processing a namespace
extension definition with a namespace attribute specification.  This bug
could result in an internal error ("address not in any mem block") in
ptr_remap_function (il_read.c) in some configurations.  For most namespaces
the abort occurred on the third definition of the namespace (but for
predeclared namespaces, like std, it would occur on the second explicit
definition).  For example:

  namespace N __attribute(()) {}
  namespace N __attribute(()) {}
  namespace N __attribute(()) {}  // This definition triggered an abort in
                                  // some configurations.

This is now fixed.


11/5/10  [EDGcpfe/11142]
Microsoft compatibility: abort on class template that uses its own default
argument

A change in version 4.2 introduced an abort in Microsoft mode on certain
cases in which a class template made use of one of its own default template
arguments.  Now fixed.

  template<class U> class B {
    template <class T,
	     template <class T1, class B = ::B<T1> > class C> struct D {
      typedef typename C<T>::iterator iter;
    };
  };


11/4/10  [EDGcpfe/11130]
Build problem with PTR_TO_INCOMP_ARRAY_ARITHMETIC_ALLOWED

The function check_object_or_incomp_pointer_operand in exprutil.c had a
typographical error that caused a build error when
PTR_TO_INCOMP_ARRAY_ARITHMETIC_ALLOWED is TRUE.  This is now fixed.


11/4/10  [EDGcpfe/11125]
Comma expression is not an lvalue in GNU C mode with gnu_version >= 40000

gcc used to consider a comma expression like "(x, y)" as an lvalue, and
we have emulated that.  It appears that in gcc 4.0 that quirk was eliminated,
so we have turned the emulation off for corresponding values of gnu_version.

  int i, j;
  int main() {
    (i, j) = 1;  // Now an error in gcc mode with gnu_version >= 40000
  }

Additionally, compound lvalues like the above are no longer allowed
as asm output operands, even in C++ mode (an error is issued).
Given that IL lowering has not lowered such expressions properly when
they are asm operands, it is unlikely that such cases are widely used.
IL lowering could handle most of the cases, but has no way to
represent the lowered cases if the result is a bit field, so it seems
wiser to disallow them until a need is demonstrated.


11/2/10  [EDGcpfe/11105]
C-generating back end, GNU compatibility: passing empty class objects by value

Because the C++ Standard requires that an empty class object have size
1, the C-generating back end generated the corresponding struct with a
one-byte padding field.  However, on 64-bit architectures, g++ passes
empty class objects in function calls using the distinctive calling
sequence that gcc uses for an empty struct (which is not permitted in
Standard C but is accepted as an extension by gcc).  If code generated
by the C-generating back end is compiled with gcc and linked with code
compiled by g++ on a 64-bit platform, the resulting mismatched calling
sequences can lead to crashes and other errors.

To accommodate this usage, a new configuration macro,
USE_EMPTY_STRUCT_IN_GENERATED_C, has been added; its default value is TRUE
when BACK_END_IS_C_GEN_BE and GCC_IS_GENERATED_CODE_TARGET are TRUE and
TARG_SIZEOF_POINTER is 8, and FALSE otherwise.  This is the initial value for
the global variable use_empty_struct_in_generated_c.  When that is TRUE, an
empty class will be represented in the generated C code as an empty struct,
and appropriate accommodations will be made to preserve the assumed layout
and initialization in the generated code.


11/2/10  [EDGcpfe/11103]
Spurious error in class template with explicit "override" (Microsoft mode)

Version 4.2 of the front end introduced a bug that triggered spurious errors
on some virtual member functions of class templates marked with the "override"
specifier.  For example:

  template<class T> struct C {
    typedef int I;
    virtual void f(I);
  };
  template<class T> struct D: C<T> {
    virtual void f(I) override;
  };

This is now fixed.  (The problem was introduced by the changes for
EDGcpfe/10573; see entry of 4/22/10.)


11/2/10  [EDGcpfe/11114]
Abort on promotion of bit field with template-dependent type

The front end aborted on attempting to determine the promoted type for
a bit field with a dependent type, in modes that do prototype instantiations.
Now fixed.  For example (with --g++ --gnu_version=30400):

  template <class T> struct A {
    enum E { e };
    E m:8;
    void f() {
      switch (m) {}
    }
  };
  int main() {
    A<int> a;
    a.f();
  }


11/1/10  [EDGcpfe/11098]
C++-generating back end, GNU compatibility: multiple declarations of gnu_inline
functions

The GNU compilers accept a non-inline declaration of a function followed by
an inline definition with the gnu_inline attribute, but versions beginning
with 4.3 issue an error if the original declaration is inline but without
the gnu_inline attribute.  The C++-generating back end previously
transformed the acceptable form of such declarations into the unacceptable
form by adding the inline specifier to every declaration of a function
whose definition is inline.  This has now been fixed by unconditionally
putting out the gnu_inline attribute along with the inline specifier.  For
example:

  void f();    // Previously generated as "inline void f();"
               // Now generated as "__attribute((gnu_inline)) inline f();"
  __attribute((gnu_inline)) inline void f() { }


10/29/10 [EDGcpfe/11111]
Abort on GNU attributes with multiple arguments in some configurations

In configurations with IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE and
ALTERNATE_IL_FILE_FORMAT set to FALSE, the front end sometimes aborted
with an internal error ("ptr_remap_function: address not in any mem block").
This was especially likely when GENERATE_SOURCE_SEQUENCE_LISTS is TRUE.
For example:

  void f(char *p, char *q) __attribute((nonnull(1,2)));
    // Previously caused the front end to abort in some configurations.

This is now fixed.


10/28/10 [EDGcpfe/11099]
Cast of pointer to member from virtual base to derived in Microsoft C++ mode

The Microsoft compiler allows a nonstandard cast of a pointer to member
from a virtual base class to a derived class.  That's possible because
the Microsoft ABI representation for pointers to members includes extra
information that's not available in most other ABIs.  We now allow
such casts in Microsoft mode if
PTR_TO_MEMBER_REPR_SUPPORTS_CAST_FROM_VIRTUAL_BASE is TRUE.

  class A {
  public:
    virtual void m() const;
  };  
  class B : virtual public A {};
  typedef void (B::*ptm)() const;
  void f(ptm) {}
  void g() {
    f(&B::m);
  }

As part of this change, we have added a new macro DOING_SOURCE_ANALYSIS
that can be set to TRUE to indicate a configuration that is primarily
doing source analysis rather than compilation to object code.  That
allows relaxation of some checks (like the above) that are dependent
on the target ABI.  It's set by default in versions that do not
do IL lowering, e.g., C++-generating back end versions, and having it
set to TRUE will get PTR_TO_MEMBER_REPR_SUPPORTS_CAST_FROM_VIRTUAL_BASE
set to TRUE by default if Microsoft extensions are supported.


10/28/10 [EDGcpfe/11100]
Dropping cv-qualifiers on reinterpret_cast to pointer-to-function type

In GNU C++ and Microsoft C++ modes, reinterpret_cast now allows dropping
cv-qualifiers on a cast to a pointer-to-function type.  This is nonstandard.
For example:

  void foo(const void* handler) {
    reinterpret_cast<void (*)(int)>(handler);
  }


10/27/10 [EDGcpfe/11097]
C++-generating back end, Microsoft compatibility: < operator in non-type
template arguments

The Microsoft C++ compiler has a bug in which it sometimes mistakes a <
operator appearing in a non-type template argument as the beginning of a
nested template argument list, resulting in spurious errors.  For example:

  template<bool B> struct A;
  template<typename T> struct B;
  template<typename T> struct C {
    typedef typename A<B<T>::m < 5>::type type; // error in MSVC++
  };

When msvc_is_generated_code_target is TRUE, the C++-generating back end now
avoids triggering this bug by unconditionally enclosing the left operand of
a < operator in parentheses when it appears inside a template argument
list.


10/26/10 [EDGcpfe/11095]
Invalid orphan entry structure for attributes

The front end sometimes must place attribute entries (an_attribute) on an
"orphaned entries list".  However, when writing the IL to a file, the front
end failed to correctly remap the pointers to that list.  The resulting
invalid IL file could easily trigger internal errors later on (e.g., in the
stand-alone IL display utility).  The following GNU-mode example suffered
from this problem:

  void f(int p __attribute((unused))) { return; }

This is now fixed.


10/25/10 [EDGcpfe/11089]
MICROSOFT_MODE_TYPE_INFO_IN_NAMESPACE_STD missing in configuration output

The configuration macro MICROSOFT_MODE_TYPE_INFO_IN_NAMESPACE_STD was missing
from the output produced for the command-line option --dump_configuration.
This is now fixed.


10/25/10 [EDGcpfe/11086]
Microsoft compatibility: Zero array bounds

Previously, in Microsoft modes, a zero array bound ([0]) was allowed for a
field declaration and was treated exactly like an unspecified bound ([]); see
the Changes entry of 4/30/95.  Now this has been extended to all declarators
that appear in a class definition.  E.g.:

  struct S {
    typedef int A[0];  // Now accepted in Microsoft C++ mode, and treated
  };                   // as "typedef int A[];".


10/25/10 [EDGcpfe/11092]
Pointers to incompletely-defined types as operands to built-in operators
in overload resolution

The pseudo-prototypes to be used to represent built-in operators in
overload resolution (described in [over.built] of the C++ standard)
specify "pointer to object type" in several cases (e.g., for the "*"
indirection operator).  The front end implemented those as "pointer to
complete object type", which was wrong and caused a spurious error
on cases like the following:

  template <class T> struct A {
    operator T*();
  };
  class B;
  void foo() {
    A<B> ab;
    *ab;
  }

Now fixed.


10/19/10 [EDGcpfe/11046]
C++-generating back end: Incorrect template parameter names

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE and in
which name references are recorded, template parameters used as qualifiers
in a template definition could reflect the spelling used in the original
declaration of the template instead of the spelling in the definition.
This is now fixed.  For example:

  template<typename T> void f();
  template<typename U> void f() {
    int i = U::g();  // Previously generated as T::g();
  }


10/19/10 [EDGcpfe/11085]
Microsoft C++ compatibility: disambiguation regression with declspec

A change made in version 4.2 to deal with disambiguation in Microsoft
mode (see 4/20/10 entry) caused a regression for certain cases that
made use of __declspec.  Now fixed.

  void f() {
    struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) x;
  }


10/18/10 [EDGcpfe/11041,EDGcpfe/11074,EDGcpfe/11083]
GNU compatibility: Behavior of gnu_inline

The primary purpose of the GNU gnu_inline attribute is to indicate that
GNU C89 semantics should be associated with the GNU __inline keyword (see
Changes entry of 9/29/09).  Now it also allows an inline function definition
to be replaced by a later non-inline definition in GNU C++ mode (a warning
is still issued).  E.g.:

  __attribute((gnu_inline)) inline void f() {}
  void f() {}
    // Previously a redefinition error in GNU C++ mode; now accepted with
    // a warning.

Also, previously a function first declared without the gnu_inline attribute
and later redeclared with that attribute always resulted in an error.  Now,
an error is issued only if the original declaration made the function inline.
For example:

  void g();
  __attribute((gnu_inline)) __inline void g() {}
    // Previously an error because the original declaration of g does not
    // specify the attribute; now accepted because the original declaration
    // was not inline.


10/18/10 [EDGcpfe/11065]
Spurious warnings on some GNU attribute specifiers

In version 4.2, the front end sometimes issued a spurious warning when a
type-transforming attribute (like vector_size) appeared in the same syntactic
location as a non-type-transforming attribute (like noinline).  For example:

  __attribute((vector_size(8), noinline)) int f();
      // The 4.2 front end spuriously warned that "noinline" does not
      // apply here.

This is now fixed.


10/18/10 [EDGcpfe/11072,EDGcpfe/11079]
Microsoft compatibility: Redeclarations changing linkage

In Microsoft mode, the front end now accepts a redeclaration with internal
("static") linkage inside an extern "C" block following a previous declaration
for the same entity that resulted in external linkage (a warning is issued).
For example:

  void f();  // External linkage
  extern "C" { static void f() {} }
             // Internal linkage: Conflict is now accepted with a warning.


10/17/10 [EDGcpfe/11080]
GNU C++ mode: volatile bitwise-copyable expression can be passed as argument

g++ (since version 4.2) appears to allow an lvalue of a volatile bitwise-
copyable class type to be passed as an argument to a call even though
the generated copy constructor for the class would not be able to copy
the value, and therefore according to the standard the argument should not
be valid.  Other kinds of copies (e.g., in initialization) appear to get
an error as expected.

  struct A {};
  bool operator==(A, A);
  void f() {
    A a;
    if (*(volatile A *)&a == a);  // Nonstandard, but now accepted in g++ mode
  }


10/13/10 [EDGcpfe/11067]
Conditional compilation should test __sun and __sparc

In several places there were conditional compilation tests that use SOLARIS
(which is used internally at EDG).  These have been changed to the more
standard __sun.  In addition, there are places that check whether the
macros "sun" and "sparc" are defined.  These have been changed to __sun and
__sparc, respectively.


10/12/10 [EDGcpfe/11043]
C++-generating back end aborts on old-style member function specialization

In version 4.2, the C++-generating back end aborted in Microsoft mode with
microsoft_version >= 1310 when attempting to render the definition of an
old-style specialization of a member function of a class template.  (The
abort occurred in bypass_prototyped_param_src_seq_entries in cp_gen_be.c.)
For example:

  template<typename> struct S {
    void f();
  };
  void S<int>::f() {  // The C++-generating back end previously aborted
    int x = 3;        // when attempting to render this definition.
  }

This is now fixed.  (This is a regression introduced in version 4.2 by the
changes for EDGcpfe/10128; see the Changes entry of 12/16/09.)



10/12/10 [EDGcpfe/11070]
Microsoft C++ compatibility: dllexport and const variables

In C++, const variables defined in namespace scope normally have linkage by
default (i.e., as if they were defined with the keyword "static").  In
Microsoft C++ mode with microsoft_version >= 1400, however, the front end now
gives const variables defined in namespace scope external linkage by default
if the variable was declared with __declspec(dllexport).  Previously, such a
declaration (without an explicit "extern" specifier) was an error because
__declspec(dllexport) cannot be specified on entities with internal linkage.
For example:

  __declspec(dllexport) int const x = 3;
    // Previously an error because const variables have internal linkage
    // by default.  Now accepted and x is given external linkage (when
    // microsoft_version >= 1400).


10/8/10  [EDGcpfe/11066]
Abort reading name references from standalone utility program

In versions with PROTOTYPE_INSTANTIATION_IN_IL an abort could occur
in a standalone utility program when reading an IL file containing name
reference entries for prototype instantiations.  Now fixed.  The
example below would abort in the IL display program if an IL file
was created by, for example, a C++-generating back end version configured
with prototype instantiations in the IL.

  template <bool b> struct A { };
  template <typename T> struct B  { };
  template <typename U> class C {
    template <typename U2> typename A<B<U2>::v>::t f() { return 0; }
  };
  C<char> cC;
  C<wchar_t> wC;


10/8/10  [EDGcpfe/11062]
C++-generating back end, GNU compatibility: __builtin_stdarg_start

In configurations with GCC_BUILTIN_VARARGS and either
CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT or
GCC_BUILTIN_VARARGS_IN_GENERATED_CODE set to TRUE, the C++-generating back
end used the obsolete builtin __builtin_stdarg_start instead of the current
__builtin_va_start for references to va_start in --g++ and --gcc mode.  It
has now been changed to use the older form only when
gnu_target_version_number is less than 30300.  For example:

  void f(int i, ...) {
    __builtin_va_list args;
    __builtin_va_start(args, i);  // Previously generated as
                                  // __builtin_stdarg_start
    __builtin_va_end(args);
  }


10/7/10  [EDGcpfe/11049]
Microsoft property references and subscripting

The expansion of Microsoft mode property field references did not match
MSVC in some cases where a property field is subscripted.  It appears
that if the property has a "get" function that takes no arguments and
returns a pointer, MSVC will use that to convert the property to a
pointer value which is then subscripted by the following [...].
Formerly, the front end always tried to match such a case against
a "get" or "put" function that could take all the subscripts as
arguments.

  class Accessor {
    char *theStr;
    __declspec( property( get=_GetString, put=_PutString) ) char *strProp;
    char *_GetString() { return(theStr); }
    void _PutString(char *s) { theStr=s; }
    bool IsStrNonNull() {
      return(strProp[0]!=NULL);  // Formerly got an error
    }
  };


10/7/10  [EDGcpfe/11052]
Microsoft mode handling of "?" operator with interconvertible 2nd/3rd operands

According to the C++ standard, if the second and third operands of a "?"
operator have different class types and are each convertible to the other, the
operator is ambiguous.  In such cases, MSVC favors the second operand,
converting the third operand to the type of the second.  Now, we do
that too.

  extern "C" int printf(const char *, ...);
  struct B;
  struct A {
    A() {}
    A(const A&) {}
    A(const B&) { printf("converting B to A\n"); }
  };
  struct B {
    B() {}
    B(const B&) {}
    B(const A&) { printf("converting A to B\n"); }
  };
  int main() {
    int foo = 1;
    foo ? A() : B();
    foo = 0;
    foo ? A() : B();  // Now prints "converting B to A" in Microsoft bugs mode
  }


10/6/10  [EDGcpfe/11051]
Incorrect handling of return value type in template

In versions that do IL lowering, functions that return a class by
value are changed to use an added parameter when the class must be returned
by calling a copy constructor.  In some cases where the return type of
a template is a nonreal class (one whose arguments are template parameters),
the front end sometimes concluded that instances of the template needed to
use an added parameter even when that wasn't in fact necessary.  Among other
things, this could mean that different instances of the template function
had different numbers of parameters.  Now fixed.  The following example
generated incorrect C code when compiled with the C-generating back end,
because the type of f<int> did not match the type of the parameter of
the instance of g.

 template <class T> struct A {};
 template <class T> A<T> f() {
   return A<T>();
 }
 template <class T> void g(T) {}
 int main() {
   g(f<int>);
 }


10/5/10  [EDGcpfe/11034]
GNU attributes following an enum definition

In version 4.2, GNU attributes immediately following the definition of an
enumeration type were not handled properly (a regression).  For example:

  typedef enum { e } __attribute((mode(byte))) E;
    // In version 4.2, the underlying type of the enumeration was not
    // changed to a byte-sized integer.

This is now fixed.


10/5/10  [EDGcpfe/11042]
C++-generating back end: Attributes missing in explicit instantiations

In version 4.2, Microsoft __declspec attributes specified on explicit
instantiation directives were sometimes not rendered by the C++-generating
back end (a regression).  For example:

  template<class T> struct __declspec(dllimport) S {};
  template struct __declspec(dllimport) S<int>;

This is now fixed.


10/5/10  [EDGcpfe/11047]
Some nonreal types still unintentionally shared

Starting with version 4.2, nonreal types based on template parameter were
no longer shared (see 5/4/10 entry).  However, certain types that
indirectly made use of template parameters were still shared when they
should not have been.  In the example below the return type of "f" in the
instantiations of A<char> and A<wchar_t> (typename B<C<U>::value>::type)
shared the same type when they should not have because the two instances of
C<U>::value were not considered distinct.  Now fixed.

  template <bool b> struct B { };
  template <typename T> struct C { };
  template <typename T> class A {
    template <typename U> typename B<C<U>::value>::type f() { return 0; }
  };
  A<char> achar;
  A<wchar_t> awchar;


10/4/10  [EDGcpfe/11045]
Attributes duplicated by C++-generating back end

In version 4.2, when a declaration has both prefix and postfix attributes, the
C++-generating back end sometimes duplicated the prefix attributes (the result
was frequently invalid code).  For example (in C++0x mode):

  [[noreturn]] int f [[carries_dependency]] ();
    // In version 4.2, the C++-generating back end rendered this as:
    //   [[noreturn, noreturn]] int f [[carries_dependency]]();
    // which is invalid C++0x (the attribute cannot be repeated).
  int i = f();

This is now fixed.


10/4/10  [EDGcpfe/11040]
C++-generating back end aborts on duplicate using-declaration

The front end previously generated an invalid list of source sequence entries
when parsing two using-declarations in a function definition (when
GENERATE_SOURCE_SEQUENCE_LISTS is TRUE).  This in turn triggered an internal
error in gen_declaration ("bad entity kind on source seq list", cp_gen_be.c).
For example:

  void f();
  void g() {
    using ::f;
    using ::f;  // Duplicate using-declaration previously triggered an
    f();        // internal error in cp_gen_be.c.
  }

This is now fixed.


9/30/10  [EDGcpfe/11015]
C++-generating back end: inaccessible types with accessible typedefs

In some cases the C++-generating back end emitted a reference to a type
that is inaccessible or uses inaccessible names in its template arguments,
even though the source code referred to the type using a public typedef.
This problem occurred when generating qualifiers in cases where name
references are not recorded and in template arguments (where the template
argument reflects the first reference to the instance, which might have
occurred in a context in which the name is accessible).  The C++-generating
back end has now been changed to keep track of publicly-accessible typedefs
to potentially-inaccessible types and to substitute the typedef for a use
of the type in a context where it is inaccessible.  (Note that in cases
where more than one public typedef names the same inaccessible type, the
typedef appearing in the generated code might not be the one used in the
source.)  For example:

  class A {
    struct priv {
      typedef int I;
    };
  public:
    typedef priv pub;
  };
  A::pub::I i;    // Previously generated as A::priv::I


9/29/10  [EDGcpfe/10795]
GNU C++ mode constant variables with pointer values

The change made for EDGcpfe/9421, for uses in g++ mode of const variables
initialized with constant addresses, wasn't quite right.  It broke cases
like:

  int i;
  int *const p = &i;
  template <int* pi = p>
  struct A {};

which is accepted by all version of g++.  A further tweak has now been made.


9/28/10  [EDGcpfe/11017,EDGcpfe/10898,EDGcpfe/10196]
C++-generating back end, GNU compatibility: initializers for vector types

In C++-generating back end configurations with GNU_VECTOR_TYPES_ALLOWED set
to TRUE, an initializer for a variable with a vector type caused an assertion
failure in gen_initializer_constant.  This is now fixed.  For example:

  typedef int int4 __attribute__((vector_size(16)));
  int4 a = {0, 1, 2, 3};    // Previously aborted


9/27/10  [EDGcpfe/10112]
Enum types with explicit underlying type "bool"

In C++0x mode, the front end previously did not accept bool as an explicit
underlying type for an enum type.  For example:

  enum E: bool { x };  // Previously "bool" was diagnosed as an error in
                       // C++0x mode.

This restriction is now removed in C++0x mode (it is still enforced in some
Microsoft modes).


9/27/10  [EDGcpfe/11033]
C++-generating back end and attributes in friend declarations

The new attributes framework of version 4.2 introduced a bug causing the C++-
generating back end to fail to render attributes on certain friend function
declarations.  For example:

  struct __declspec(dllimport) S {
    friend __declspec(dllimport) void f(S);
      // The front previously did not render "__declspec(dllimport)"
      // in this friend declaration.
  };

This is now fixed.


9/27/10  [EDGcpfe/11032]
Representation of integral types (IL CHANGE)

IL entries representing integer and enumeration types (i.e., a_type entries
of kind tk_integer) now point to a supplement entry via the variant field
variant.integer.extra_info.  Some of the variant fields have been moved to
this supplement.  This includes the "base_type" field, which is now present
in all configurations (previously, it was present only when
PROTOTYPE_INSTANTIATIONS_IN_IL or BACK_END_IS_CP_GEN_BE were TRUE).


9/27/10  [EDGcpfe/10720]
C++-generating back end: expressions in non-type template arguments

The front end previously did not retain backing expressions for non-type
template argument constants, with the consequence that the C++-generating
back end always generated the template argument as simply the folded
constant value.  This caused problems with the generated code if the
argument expression contains a reference that causes the instantiation of
another template, since that template might not otherwise be instantiated.
This issue has been addressed (for the first reference to a given template
instance only, since the instance's template argument list reflects the
arguments given in that initial reference) by the addition of the
KEEP_TEMPLATE_ARG_EXPR_THAT_CAUSES_INSTANTIATION configuration macro.  If
that is TRUE (and TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is
FALSE), a non-type template argument that causes an instantiation in the
first reference to an instance of a template will be recorded as a backing
expression for the template argument constant.  (The C++-generating back
end only uses the backing expression for the first reference to the
template instance, in order to avoid scope issues for names appearing in
the expression.)  For example:

  template<typename T> struct A {
    enum { I = 4 };
  };
  template<int N> struct B { };
  B<A<int>::I> b4;   // previously generated as B<4>


9/24/10  [EDGcpfe/11026]
Unnecessary instantiation of class to determine related-class relationship

The front end unnecessarily instantiated a class template as part of
determining a related-class relationship for a Microsoft bugs mode
feature.  Specifically, in checking whether a conversion from "pointer to X"
to "pointer to X" (i.e., the same type) is a cast to an ambiguous base
class, it instantiated X even though the fact that there is no base
class relationship can be determined without doing so.  Now, the class
is not instantiated in such cases.  Because the change was made at a
low level, it's possible that in some other obscure cases (even
non-Microsoft-mode cases) the front end will no longer instantiate a
class where formerly it did so.

  template<typename T> struct X {
    enum { E=sizeof(T) };
  };
  struct S;
  typedef X<S> XS;
  XS* f(XS *p) { return p; }  // No longer gets an error in
                              // Microsoft bugs mode

This bug was introduced in version 4.1.


9/24/10  [EDGcpfe/11029]
Incorrect consistency check on "*" operator over pointer to cv-qualified
function type

A consistency check on the result type of the "*" operator gave a spurious
abort on cases where the type of the operand is a pointer to a cv-qualified
function type.  cv-qualifiers over a function type are ignored, but the
consistency check failed to drop them in doing the check.  Now fixed.

  typedef void foo(void);
  void f(const foo* v) {
    (*v)();  // Formerly aborted in C99 mode
  }


9/24/10  [EDGcpfe/11030]
GNU C++ compatibility: allow redeclaration of class template from using-decl

In g++ mode, a class template made visible via a using-declaration can now
be redeclared or defined in the scope containing the using-declaration.

  namespace N {
   template <class T> struct A {};
  }
  using N::A;
  template <class T> struct A;


9/23/10  [EDGcpfe/11031]
is_template_dependent_context used in folding.c after scope stack empty

folding.c contained some calls of is_template_dependent_context that
in some cases were executed after the scope stack was empty.  These
have been replaced by uses of a new macro context_may_have_dependent_types,
which guards the call of is_template_dependent_context appropriately
for use outside the front end proper.


9/23/10  [EDGcpfe/10951]
Microsoft and GNU C++ compatibility: lookup of friend class names

The Microsoft compiler and certain versions of g++ incorrectly consider
names outside of the nearest enclosing namespace when looking for a prior
declaration of a class named in a friend class declaration.  A bug in our
emulation of this feature caused friend declarations from class templates
to be handled incorrectly (resulting in a spurious access error on X in the
example below).  This is now fixed.  In addition, g++ versions 4.0 and
newer correctly limit the lookup to the nearest enclosing namespace, so we
now disable our emulation when gnu_version >= 40000.

  class A;
  namespace N {
    template <class T> class X {
      X(){}
      friend class A;
    };
    class Y {
      Y(){}
      friend class A;
    };
  }
  class A {
    A(){}
    N::X<int> x;
    N::Y y;
  };


9/21/10  [EDGcpfe/11008]
C-generating back end: support for tail-padding reuse

The IA64 ABI requires in some cases that derived class members be allocated
in the tail padding of base class subobjects, but the C-generating back end
was unable to support tail-padding reuse and thus did not comply with this
requirement.  This limitation has now been lifted, and the default setting
for TARG_REUSE_TAIL_PADDING has been changed to TRUE for C-generating back
end configurations with IA64_ABI set to TRUE.  In this configuration, the
members of base classes with reusable tail padding are "promoted" into the
derived class in the generated C code and member access expressions
designating such promoted members are adjusted accordingly.  The previous
class layout in the generated code can be retained by explicitly setting
TARG_REUSE_TAIL_PADDING to FALSE.


9/21/10  [EDGcpfe/10981]
GNU compatibility: Additional IA-32 built-in functions

In GNU modes with GNU_BUILTIN_IA32_VECTOR_FUNCTIONS_ALLOWED set to TRUE, the
front end now predeclares the following functions: __builtin_ia32_bsrsi,
__builtin_ia32_bsrdi, __builtin_ia32_rdpmc, __builtin_ia32_rdtsc,
__builtin_ia32_rdtscp, __builtin_ia32_rolqi, __builtin_ia32_rolhi,
__builtin_ia32_rolsi, __builtin_ia32_roldi, __builtin_ia32_rorqi,
__builtin_ia32_rorhi, __builtin_ia32_rorsi, and __builtin_ia32_rordi.


9/17/10  [EDGcpfe/8731,EDGcpfe/11011]
Determining the type underlying va_list/__builtin_va_list

A new global variable type_underlying_va_list has been introduced to control
the default type underlying va_list or (in GNU modes) __builtin_va_list.  This
variable is NULL by default, but customers can set it to something appropriate
in sys_predef.c.

When <stdarg.h> is treated as a built-in header and type_underlying_va_list is
non-NULL, it is used as the type underlying the generated va_list typedef.
Furthermore, when type_underlying_va_list is NULL, the default type underlying
va_list in Microsoft modes is now char* instead of void* (it's still void* in
non-Microsoft modes).

Similarly, in GNU modes with GCC_BUILTIN_VARARGS, type_underlying_va_list is
used as the type underlying __builtin_va_list if it is non-NULL.  Furthermore,
when type_underlying_va_list is NULL and USE_X86_64 is FALSE, the type
underlying __builtin_va_list is now char* (instead of void*) by default.


9/16/10  [EDGcpfe/10977]
Abort on instantiation of function template with noalias or restrict attribute

The new attributes framework of version 4.2 introduced a bug causing the front
end to abort with an internal error in update_routine_modifiers (decls.c)
during the instantiation of a function template declared with the Microsoft
__declspec attributes "noalias" or "restrict".  For example:

  template<typename T> __declspec(noalias) void f(T) {}
  template void f(int);  // Previously triggered an internal error.

This is now fixed.


9/16/10  [EDGcpfe/11009]
Spurious errors on uses of parameters declared as arrays of const elements

A bug introduced in version 4.2 caused the front end to incorrectly treat a
parameter declared with a type "array of const T" as being a "const" (i.e.,
immutable) parameter.  This resulted in spurious errors.  For example:

  void f(char const p[]) {
    while (*p++);  // Version 4.2 incorrectly issued an error because it
  }                // considered p to be "const".

This is now fixed.


9/14/10  [EDGcpfe/11010]
Internal error in dtor_initializer on using-declaration for operator delete

In some cases, the front end previously aborted with an internal error in
dtor_initializer (decl_inits.c) when processing the definition of a destructor
of a class containing a using-declaration for a set of "delete" operators in a
base class.  For example:

  struct B {
    void  operator delete(void*);
    void  operator delete(void*, void*);
    virtual ~B();
  };
  struct D: B {
    using B::operator delete;
    ~D() {}  // The front end previously aborted when processing this
  };         // destructor definition.

This is now fixed.


9/14/10  [EDGcpfe/10969,EDGcpfe/11016]
Specifiers position information with prefix attributes

The implementation of the new attributes framework (see entries of 1/25/10 and
12/3/09) changed the starting position of declaration specifiers (recorded
when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE) when the specifiers are preceded by
prefix attributes.  Before the new framework, the starting position was that
of the first prefix attribute; with the new framework, it became the position
of the first specifier following the prefix attributes.  Now, the original
position (that of the first prefix attributes) has been restored.
For example:

  __declspec(dllimport) void f() {}

If ptr is a pointer to the a_routine entry for f, then
  ptr->source_corresp.decl_pos_info->specifiers_range.start
now once again holds the position of the "__declspec" token (in version 4.2 it
indicated the position of the "void" token).  In addition, in versions prior
to 4.2, the front end failed to record the end position of a prefix attribute
specified on a constructor or destructor declaration as the end position of
the specifiers in the associated a_routine entry.  For example:

  struct __declspec(dllexport) S { S(); };
  __declspec(dllexport) S::S() {}  // Previously the end position of the
                                   // specifiers was null.

This is now fixed.


9/14/10  [EDGcpfe/11005]
Microsoft __declspec(align(...)) ignored on class nested in template class

In Microsoft C++ mode, the __declspec(align(...)) attribute was incorrectly
ignored on a class nested in a class template when that class template was
instantiated.  For example:

  template<typename T> struct S {
    struct __declspec(align(16)) N {};
  };
  S<int>::N n;  // S<int>::N was previously not aligned according to the
                // __declspec attribute.

This is now fixed.


9/13/10  [EDGcpfe/10945]
GNU/Microsoft compatibility: Invalid virtual override returns in templates

In GNU and Microsoft C++ modes, the front end no longer requires identical
or covariant return types when checking a virtual function of a prototype
instantiation of a class template (the constraint is still imposed when the
class template is fully instantiated).  For example:

  struct B { virtual int f(); };
  template<typename T> struct D: B {
    virtual float f();  // No error issued when parsing the generic template
  };                    // in GNU or Microsoft mode.
  template struct D<int>;  // An error is issued during this instantiation.


9/13/10  [EDGcpfe/11007]
GNU compatibility: define __STDC_VERSION__ in C99 mode

The change (see the 1/13/09 entry for EDGcpfe/6518 below) not to define
__STDC_VERSION__ in Microsoft and GNU C modes was too sweeping; gcc does,
in fact, define that standard macro in C99 ("std=c99") mode.  The front
end has now been changed to emulate this behavior.


9/12/10  [EDGcpfe/11004]
Use of inttypes.h on systems without stdint.h

Starting with version 4.2, the front end attempts to use stdint.h to
define integer types with specific sizes (e.g., int32_t).  A different
mechanism was provided for systems such as Solaris that don't provide
stdint.h, but provide an alternate header to define such types.  In
4.2 the alternate header was "sys/int_types.h".  This has been changed
to "inttypes.h", which is more portable.  See the 1/26/10 entry for more
information.

9/10/10  [EDGcpfe/11002]
cv-qualifier lost on SFINAE rescan of cast to reference

The front end failed to correctly process a case like

  struct A {
    template <class T> operator volatile T();
  };
  struct B {
    B();
    virtual void f();
    template <class T> operator T() const;
  };
  A aa;
  template <class T> auto f(T p) -> decltype(p || (const B &)(aa));
  int main() {
    f(1);
  }

where a cast to a reference type involved both a conversion function call
and then a cv-qualifier adjustment, and the cast was rescanned in a C++0X
SFINAE context.  Now fixed.


9/9/10   [EDGcpfe/10998]
Microsoft C++ mode: incorrect error on conversions for "?" operator

The special Microsoft C++ bug emulation for conversions and reference binding
(see Changes entry of 11/2/06) turns out not to be applicable when
analyzing possible conversions on operands of a "?" operator (the
conversions there are defined in terms of a reference binding, but
apparently MSVC goes through a different path).  Now fixed, and a case
like the one below no longer gets a spurious error in Microsoft mode:

  class C {};
  template<typename T> struct A {
    operator T();
    operator T&() const;
  };
  void foo() {
    A<const C> a;
    const C b;
    true ? a : b;
  }


9/9/10   [EDGcpfe/11001]
Possible buffer overrun in tildize_locator

tildize_locator could potentially write one past the end of the ident_buffer.
Now fixed.


9/9/10   [EDGcpfe/11000]
Abort in statement() if the structured statement stack is reallocated

An abort could occur (in statement()) if the structured statement stack
was reallocated.  Now fixed.


9/9/10   [EDGcpfe/10999]
Abort in wrapup_scopes with RECORD_HIDDEN_NAMES_IN_IL

In versions with RECORD_HIDDEN_NAMES_IN_IL enabled, an abort could occur
in wrapup_scopes if hidden name processing resulted in the reallocation
of the scope stack.  Now fixed.  The example below aborts in certain
configurations with RECORD_HIDDEN_NAMES_IN_IL.

  int main() {
    struct X0 { struct X1 { struct X2 { struct X3 { struct X4 {
      struct X5 { struct X6 { struct X7 { struct X8 { }; }; }; };
    }; }; }; }; };
    X0::X1::X2::X3::X4::X5::X6::X7::X8 x;
  }


9/7/10   [EDGcpfe/10989]
Abort on multi-argument functional-notation cast as argument of overloadable
operator in constant expression

The front end aborted in do_constant_generic_operand_transformations in
exprutil.c while processing an invalid functional-notation cast having
multiple arguments in a constant expression, when the cast is an operand
of an overloadable operator.  Now fixed (an error is detected).

  template <int I> struct A { };
  int i;
  template <class T> auto f(T p) -> decltype(A<i + T(1, 2)>()) {}
  int main() {
    f(1);
  }


9/6/10   [EDGcpfe/10990]
Abort on invalid selection of member template in SFINAE context

In certain obscure cases involving a call of a member function in a
C++0X SFINAE context, where the member name is given as a member of a
template parameter and using the "template" form (e.g., p1.T::template f<>),
and the selection object and member classes are unrelated, and the
entity found as the member is a virtual function, the front end aborted
in final_overrider (overload.c).  Now the deduction fails as it should.

  struct A {
    virtual void f(A *p);
  };
  struct B { };
  template <class T, class U> auto g(T p1, U p2) ->
                                   decltype(p1 . U::template f<>(0)) { }
  int main() {
    A a;
    B b;
    g(b, a);
  }


8/30/10  [EDGcpfe/10961]
Invalid IL for "?" operation containing unevaluated GNU statement expression

The front end produced invalid IL for a "?" operator that can be folded
to a constant, when the discarded operand contains a GNU statement
expression that defines a scope.  The incorrect IL could cause aborts
later, e.g., an IL write/read error in versions that write an IL
file in the alternate file format.  This bug was introduced in version 4.0
and is now fixed (the "?" operation is not folded to a constant).

  int main() {
    int i = 1 ? 1 :({ int j = 1; j; });
  }


8/27/10  [EDGcpfe/10937]
C++-generating back end, GNU compatibility: Unneeded parentheses in expressions

The C++-generating back end sometimes parenthesized the operands to
overloaded operator functions called using operator notation, even when the
parentheses are not needed because of the precedence of the operator with
respect to its operands.  With certain expressions, older versions of g++
(prior to 3.4) were confused by the extra parentheses and reported spurious
errors for the generated code.  The C++-generating back end has now been
changed to suppress most unneeded parentheses when the operator precedence
makes them unnecessary.  For example:

  struct S {
    S();
    S& operator=(const S&);
  };
  void f() {
    S s;
    s = S();  // Previously generated as "s = (S())", confusing g++
  }


8/27/10  [EDGcpfe/10936]
Microsoft C++ mode: no access checking on type name in "new"

Some versions of MSVC appear not to do access checking on the type
specified in a "new".  (Access checking on the constructor, if any,
is still done.)  We now emulate that in Microsoft mode for the
appropriate values of microsoft_version.

  class A {
    class N { };
  };
  class B : public A {
    void f() {
      new N();  // No error with --microsoft_version=1400, for example,
                // even though A::N is inaccessible
    }
  };


8/26/10  [EDGcpfe/10965]
GNU C++ mode: g++ dependency check in PARENS_IN_IL configuration

The checking added for EDGcpfe/10527 failed to allow for the presence of
eok_parens nodes in the expression tree.  As a result, the check was
ineffective for code containing parentheses in configurations in which
PARENS_IN_IL is TRUE.  This is now fixed.  For example:

  template <class T> class C;
  template <> struct C<int> {
    void foo(int);
  };
  template <class T> struct X : C<T> {
    int *m;
    virtual void f() {
      foo(*(this->m));   // Previously reported as error with PARENS_IN_IL
    }
  };
  X<int> x;


------------------------------------------------------------------------------
Version 4.2, August 25, 2010

8/23/10
IL version number updated to 4.2


8/23/10  [EDGcpfe/10948]
GNU compatibility: Discriminators for anonymous union types

The IA-64 ABI uses small integers called "discriminators" to distinguish
the mangled names of unnamed types, but the ABI excludes anonymous union
types from this numbering.    GCC, however, includes anonymous types in this
numbering: When IA64_ABI and emulate_gnu_abi_bugs are TRUE, the front end
now does the same.  For example (with --c++0x and assuming the IA-64 ABI):

  template<class T> T f(T);
  struct A {
    union { int i; };  // Anonymous union.
    struct {} s;       // The discriminator value of the unnamed struct is
  } a;                 // now increased by one when emulate_gnu_abi_bugs is
                       // TRUE.
  int main() {
    f(a.s);   // Previously always mangled as _Z1fIN1AUt_EET_S2_;
              // now _Z1fIN1AUt0_EET_S2_ (when emulate_gnu_abi_bugs is TRUE).
  }


8/22/10  [EDGcpfe/10940]
Abort on indirect call through a pointer with the GNU "sentinel" attribute

In GNU modes, a call through a pointer-to-function declared with the "sentinel"
attribute was likely to cause the front end to abort (due to a null-pointer
indirection) in warn_if_missing_sentinel (overload.c).  For example:

  void (*pf)(char *, ...) __attribute((sentinel));
  void g() { pf("Check", (void*)0); }  // Previously triggered an abort.

This is now fixed.  (The front end does not currently fully check the sentinel
on indirect calls.)


8/18/10  [EDGcpfe/10931]
Missing error on invalid default exception handler

The C++ standard requires a default exception handler to be the last handler
associated with a try-block: The front end therefore normally issues an error
for any handler that follows a default handler.  The front end also warns on
cases where a handler is masked by a previous handler (e.g., because both
handlers are for the same type).  However, if a handler X is preceded both by
a default handler and an earlier handler that masks X, a warning was issued
but not an error (even though such a situation is invalid).  For example:

  void f() try {
  } catch (int) {
  } catch (...) {
  } catch (int) {  // Previously accepted with a warning.  Now an error
  }                // is also issued.


8/18/10  [EDGcpfe/10893]
GNU compatibility: Attribute always_inline

The front end now ignores the GNU attribute "always_inline" when it appears on
the declaration of a typedef, variable, parameter, or field.  (Previously, an
error was issued.)  For example:

  struct S {
    int i __attribute((always_inline));  // Now accepted with a warning.
  };


8/12/10  [EDGcpfe/10925,EDGcpfe/2484]
Extend the lifetime of a temporary used as the second operand of a comma
operation when bound to a reference

A temporary that is the second operand of a comma operation now has its
lifetime extended when it is bound to a reference (see core issue 462).
This example had printed "second" before "first" and now prints "first"
before "second":

  extern "C" int printf(const char*,...);
  struct A {
    ~A() { printf ("second\n"); }
  };
  int main () {
    const A &ra ((0,A()));
    printf ("first\n");
  }


8/12/10  [EDGcpfe/10927]
No use of Microsoft property fields as objectless nonstatic member references

The language feature that allows use of nonstatic data members without an
associated object within unevaluated expressions (see EDGcpfe/8402 below)
should not have allowed Microsoft property fields, since they don't have
associated storage.  An attempt at such a thing formerly caused an abort.
Now, such references produce an error.

  struct A {
    __declspec(property(get=f)) int i;
  };
  int i = sizeof(A::i);  // Error now in Microsoft mode


8/11/10  [EDGcpfe/10901]
Microsoft compatibility: __declspec(deprecated(...)) with wide strings

In Microsoft mode with microsoft_version >= 1400, the front end accepts
__declspec(deprecated(...)) with a string literal argument (see the entry of
11/9/05).  Before the introduction of the new general attributes framework
(see entries of 1/25/10 and 12/3/09), wide string literal arguments were
accidentally accepted, but they were treated as narrow strings containing the
bytes of the wide-string encoding: Corresponding deprecation diagnostics were
not correctly rendered.  For example:

  __declspec(deprecated(L"Old")) int x;
  int y = x;  // Previously triggered a strange diagnostic.

This is now fixed.  Wide-string literal arguments are accepted with a remark
in __declspec(deprecated(...)), and a corresponding diagnostic no longer
attempts to render the wide string.  The general attributes framework
correctly records the wide string in the IL (using an a_constant entry).


8/11/10  [EDGcpfe/10919]
C-generating back end: missing wide character string literal variables

The C-generating back end generates initialized variables for wide
character string literals.  When annotations are enabled in the
generated C code (using, for example, the -d0 command line option),
the back end sometimes placed such variables into the #if 0/#endif
blocks used to display unneeded generated code even when the variables
were, in fact, needed, resulting in compilation errors on the
generated code.  This is now fixed.  For example, when code was
generated for the following test case with the "-d0 --g++ --c++0x"
command line options, the variable containing the L"zzz" constant
appeared only inside a #if 0/#endif block.

  template <class T> auto f(T x) -> decltype(x == L"zzz") {return true;}
  void g() {
    f(L"zzz");
  }


8/10/10  [EDGcpfe/10911]
C++-generating back end: decl/expr ambiguity with value init operand

The C++-generating back end formerly enclosed all operands of the sizeof
operator in parentheses.  This resulted in incorrect generated code when
the operand is a value initialization, because in "sizeof(T())" the
parentheses allow "T()" to be interpreted either as an expression or as
the declaration of a type (a function with no parameters returning "T").
The C++ Standard says that such cases are to be treated as declarations,
resulting in an erroneous attempt to take the size of a function type.
This has now been fixed by suppressing the redundant parentheses when the
operand is a dynamic initialization.  For example:

  typedef int I;
  int main () {
    int i;
    i = sizeof I();   // Previously generated as "sizeof(I())"
  }

A similar issue sometimes occurred in other contexts, where extra
parentheses required the expression to be interpreted as a cast.  This is
also now fixed by omitting the extra parentheses.  For example:

  typedef short T;
  int i = T() + 1;   // Previously generated as "((T()) + 1)"


8/10/10  [EDGcpfe/10910]
C++-generating back end: incorrect function-style casts in generated code

In configurations with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE, if a
value initialization uses a template type parameter and the corresponding
template argument is an unnamed type that must be expressed using multiple
tokens, the C++-generating back end generated the expression using an
incorrect syntax for the function-style cast.  This has now been fixed to
use a C-style cast of the constant 0 in such cases.  For example:

  template<typename T> void f() {
    T();  // Previously generated as "char *()" in f<char *>(), now
          // generated as "(char *)0"
  }
  void g() {
    f<char *>();
  }


8/9/10   [EDGcpfe/10909]
C++-generating back end: typename keyword in dependent dynamic init expression

In configurations in which template definitions are generated from the
prototype instantiations, the C++-generating back end failed to add
"typename" keywords in references to dependent types appearing in dynamic
initialization expressions.  This is now fixed.  For example:

  template <template <class _T> class T, class U> void f() {
    typename T<U>::B();   // "typename" previously omitted in generated code
  }


8/5/10   [EDGcpfe/10892]
Type for std::type_info vtable is now incomplete when vtable is not defined

The vtable variable defined for std::type_info had the incorrect number of
array elements in some cases.  To avoid a link-time type mismatch, a change has
been made to use an incomplete type for the std::type_info vtable variable in
cases where the vtable is not being defined in the translation unit.  This
change affects both IA-64 and Cfront ABIs.  In this case:

  #ifdef INCLUDE
  #include <typeinfo>
  #endif
  int main() {
    throw 0;
  }

The vtable variable is now declared (in the Cfront ABI) as
"extern const struct __C2 __vtbl__Q2_3std9type_info[]" where previously
the array size was one when INCLUDE was not defined (indicating that the
lowering version of std::type_info was being used) and four when INCLUDE was
defined (a bug).  Neither of these values matched the correct value (two).


8/5/10   [EDGcpfe/10896]
GNU C++ suppression of argument-dependent lookup because of explicit template
argument list

The g++ bug that suppressed argument-dependent lookup when an
explicit template argument list is given has apparently been fixed
in g++ 4.4, so we now turn off the emulation of that bug when
gnu_version is 40400 or greater.

  template <class T> void f(T *) {}
  struct A {} a;
  template <class T> void g(T p) {
    f<A>(p);  // No error now in g++ mode with gnu_version >= 40400
  }
  template <class T> void f(A) {}
  int main() {
    g(a);
  }


8/4/10   [EDGcpfe/10895]
Abort on GNU __builtin_offsetof that names a reference-typed field

The front end aborted (in folding.c, add_offset_of_accessed_member)
while attempting to process a GNU C++ __builtin_offsetof that names
a field that has a reference type.  Now fixed (an error is issued).

  struct A {
    int &r;
  } a;
  int i = __builtin_offsetof(A, r);


8/2/10   [EDGcpfe/10885]
Handling va_list that is an array type

The support for the builtin operations of <stdarg.h> now correctly
handles the case where the builtin va_list type is an array type.
This became more important with the addition of an array-typed
va_list for USE_X86_64 configurations, as described in the Changes
entry for EDGcpfe/10180 below.


8/2/10   [EDGcpfe/8844]
Performance in the presence of a large number of #includes

The mechanism used to eliminate the redundant inclusion of files did
not perform well when using a very large number of include files
spread over a very large number of directories (e.g., thousands of
files spread over thousands of directories).  The hash table used
to track such includes is now resized as needed resulting in much
better performance.


8/2/10   [EDGcpfe/10887]
Abort on copy optimization with conversion function returning volatile class

The front end aborted (in expr.c, scan_ctor_arguments) while attempting to
do copy constructor elision in a case where the source is the result of
calling a conversion function that returns a volatile class type.
(In theory, this could also occur for conversion functions returning
any customer-added cv-qualifiers.)  Now fixed.

  struct A {
    A();
    A(const A&);
  };
  struct B {
    operator volatile A();
  };
  int main() {
    B b;
    A a(b);
  }


8/1/10   [EDGcpfe/10884]
Invalid "type_as_subobject" created for certain unions

In configurations with IA64_ABI and TARG_REUSE_TAIL_PADDING set to TRUE,
IL lowering incorrectly recorded a struct type as the type to be used for
a base class subobject (the "type_as_subobject" field) for a non-POD union
with tail padding.  For example:

  union U {
  private:      // Private members make U a non-POD.
    int i;      // Assume a 4-byte aligned int type.
    char c[6];
  };  // Usually U has size 8 including 2 bytes of tail padding.
      // Previously, type_as_subobject for U mistakenly pointed to a
      // struct type.

This is now fixed: The type_as_subobject field for a union now always points
to the union itself.


7/30/10  [EDGcpfe/10882]
Members of prototype instantiations were sometimes instantiated

Sometimes, the front end instantiated members of the current prototype
instantiation.  This is incorrect, though it was hard to observe
any negative consequences from doing so (versions with EXPENSIVE_CHECKING
sometimes caught this and aborted).  Now fixed: these instantiations are
no longer done.

  template <class T> struct A {
    template <class U> void f(U) {}
    void g() {
      &A::f<int>;  // A::f<int> should not be instantiated in the prototype
                   // instantiation
    }
  };


7/29/10  [EDGcpfe/10859]
C-generating back end: duplicate parameter names in function declarations

In some GNU modes (see the 2/28/06 and 7/21/10 entries below), the front
end accepts duplicate parameter names in function declarations.  Preserving
those names in the generated C, however, results in invalid code.  The
C-generating back end has now been changed to replace the name of a
parameter that is the same as that of an earlier one with a generated
temporary name.  For example:

  void f(int i, int i);  // Now generated (with IA64_ABI) as
                         // void _Z1fii(int i, int __T22766712);
  void g() {
    f(0, 0);
  }


7/29/10  [EDGcpfe/10876]
Effect of "#pragma pack(n)" on base classes

Previously, the front end did not consider "#pragma pack(n)" directives when 
aligning base class subobjects.  Now, when the new configuration macro
TARG_USER_CONTROL_OF_STRUCT_PACKING_AFFECTS_BASE_CLASSES is set to TRUE, base
classes are handled much like fields in this respect.  The new macro is TRUE
by default when ABI_COMPATIBILITY_VERSION >= 402 (and hence this is a
potential ABI CHANGE).  For example:

  struct B { int i; };  // Usually aligned on a 4-byte boundary.
  #pragma pack(1)
  struct D: B {
    char c;
  };  // Previously, struct D always had the same alignment as struct B.
      // Now it may have an alignment of 1 in some configurations.

The new behavior matches that of GNU and Microsoft compilers.


7/29/10  [EDGcpfe/10869]
Abort creating string form of address constant of anonymous union member

Calling form_address_constant (in a context other than from the C- or
C++-generating back ends) with an address constant designating a member of
an anonymous union and cast to a non-pointer type resulted in an assertion
failure in select_union_field_for_addr_constant.  This is now fixed.  For
example, the following code previously aborted while attempting to display
the return type of the function in a diagnostic warning about the missing
return statement in the function's definition:

  static union { int i; };
  template<typename T>
  auto f(T x)->T(*)[sizeof((decltype(__alignof__(*x)))&i)] { }


7/29/10  [EDGcpfe/10818]
Recording the form of name references

The C++0x SFINAE rules (see 4/26/10 entry) require that the exact form
of certain names be recorded in order to generate the required mangled
names.  As a result, the code to record name references is now always
present in the front end.   Formerly it was only present when the macro
RECORD_FORM_OF_NAME_REFERENCE was TRUE.  The record_form_of_name_reference
variable is now used to specify whether name references should be recorded
for all names (name references are always recorded in contexts in which
the information is needed for name mangling).  The default value of the
variable is specified by the macro DEFAULT_RECORD_FORM_OF_NAME_REFERENCE.
For compatibility with earlier defines.h files, RECORD_FORM_OF_NAME_REFERENCE
is used to set the default for DEFAULT_RECORD_FORM_OF_NAME_REFERENCE if
it has not been explicitly defined.


7/28/10  [EDGcpfe/10877]
Abort on aggregate initializer involving GNU-mode zero-length array

Previously, in GNU modes, an aggregate (i.e., brace-enclosed) initializer for 
a multidimensional array with a non-top-level dimension of zero triggered an
assertion error in start_aggregate_init_scan_loop (decl_inits.c).
For example:

  int x[2][0] = {};  // Previously aborted in GNU modes.

This is now fixed.


7/28/10  [EDGcpfe/10858]
C++-generating back end: qualified name in function call to avoid
argument-dependent lookup

In configurations in which DEFAULT_RECORD_FORM_OF_NAME_REFERENCE is FALSE,
the C++-generating back end failed to qualify the name of a function in a
call expression when it was qualified in the original source form.  The
resulting generated code could thus trigger argument-dependent lookup in
calls where the original source did not.  The front end now flags call
expressions in which argument-dependent lookup was suppressed because the
function name was qualified, and the C++-generating back end uses this flag
to determine when a function name must be qualified.  For example:

  struct S { };
  void f(S*);
  namespace N {
    void f(S*);
    void g(S* p) {
      N::f(p);    // Previously generated as f(p), which is ambiguous
                  // because of argument-dependent lookup
    }
  }


7/24/10  [EDGcpfe/10873]
Use virtual destructor final overrider for delete [] (GNU and Microsoft modes)

A change has been made to emulate GNU and Microsoft's behavior when the
object of an array delete operation has a virtual destructor.  Rather than
pass the address of the object's destructor to the appropriate runtime
routine, the address of the final overrider for the destructor from the
object's vtable is now passed instead.  This non-standard behavior can
result in unpredictable behavior when the size of the base and derived
classes are not the same.  The previous behavior is retained in all modes
except GNU and Microsoft emulation modes.  For example:

  int result = 0;
  struct B {
    virtual ~B() {}
  };
  struct D: B {
    ~D(){ result = 1; }
  };
  int main() {
    B *b = new D[2];
    delete [] b;
    return result;    // now returns 1 in GNU and Microsoft emulation modes
  }


7/22/10  [EDGcpfe/10849]
Abort on GNU C transparent union with large unnamed bit field

In GNU C mode, the front end previously aborted with an internal error in
check_if_fill_in_used ("provided diagnostic fill-in was not used") if a union
with the transparent_union attribute contains an unnamed bit field whose size
exceeds the first field of the union (which is invalid for a transparent
union).  For example:

  union U {
    char c;
    long long : 48;  // Previously triggered an internal error.
  } __attribute((transparent_union));

This is now fixed (a warning is emitted for the invalid attribute).


7/22/10  [EDGcpfe/10861]
Abort on use of PCH in file whose first token is a constant

If a file that uses a precompiled header file has a constant as the first
token after the portion of the compilation that comes from the PCH,
an abort could occur (in f_set_trans_unit_corresp).  Now fixed.  Note that
a constant in such a location results in a syntax error.


  // File that creates the PCH
  #define ASDF
  #pragma hdrstop
  int i = 0;

  // File that uses the PCH
  #define ASDF
  #pragma hdrstop
  0
  int i = 0;



7/22/10  [EDGcpfe/10865]
Abort on template-dependent designator subscript (GNU C++ mode)

In GNU C++ mode, the front end accepts designated initializers, but previously
it would abort with an internal error ("bad constant kind") in decl_inits.c
(function scan_array_element_subscript) when attempting to process a template-
dependent array designator.  For example:

  template<int N> void f() {
    int x[10] = { [N] = 2 };  // Previously aborted during prototype
  }                           // instantiation.
  template void f<1>();

This is now fixed: Template-dependent array designators are diagnosed with an
error (since GCC does not appear to accept them either).


7/22/10  [EDGcpfe/10864]
Abort on GNU statement expression in function prototype scope

The front end previously aborted in push_object_lifetime with an internal
error ("parent is in file scope memory, new olp is not") when a GNU statement
expression appeared in the function prototype scope of a declaration appearing
in a local scope.  For example:

  int f() {
    void g(decltype(({f();}))*);  // Previously triggered an internal error.
  }

This is now fixed: The front end now issues an error (without aborting) on
such cases.


7/21/10  [EDGcpfe/10860]
GNU C++ compatibility: Duplicate parameter names

Previously, the front end accepted duplicate function parameter names in all
GNU C++ modes.  Now, this is only the case when gnu_version < 40300.  (See
also the Changes entry of 2/28/06.)


7/21/10  [EDGcpfe/10853]
Parameter visibility in GNU C++ modes with trailing return types

GNU C++ compilers prior to version 4.4 keep parameters invisible until the
associated function declarator is completed (see Changes entries of 9/1/05 and
5/7/10).  The emulation of this behavior is now disabled (regardless of the
value of gnu_version) if trailing return types or lambdas (which can use
trailing return type syntax) are enabled, because it is not unusual for a
trailing return type to refer to a parameter.


7/21/10  [EDGcpfe/10855]
Abort on GNU statement expression in ctor-initializer

In configurations with MICROSOFT_EXTENSIONS_ALLOWED set to TRUE, the front
could abort with an internal error in compound_statement (statements.c) if
a GNU statement expression appeared in a ctor-initializer.  For example:

  struct S {
    S(): i(({ int x = 3; x;})) {}
    int i;
  };

This is now fixed: The internal error is no longer triggered (but statement
expressions are still not allowed in ctor-initializers).


7/21/10  [EDGcpfe/10463]
Mangling changes to support new SFINAE rules

Substantial additions have been made to both IA-64 and Cfront ABI mangling in
order to accommodate the additional expression operators and constructs that
can arise because of the new SFINAE rules of WG21 paper N2634, and, in the
case of the IA-64 ABI, we've submitted updates to the ABI spec and we conform
to the updated specification.  The front end documentation has been updated to
include the new mangling codes for the Cfront ABI.  When using the IA-64 ABI,
GNU compatibility can be achieved by setting emulate_gnu_abi_bugs to TRUE.
Generally speaking, the changes are backward compatible, but there are certain
corner cases where the ABI doesn't preserve backward compatibility (for
example, the previous version mangled all casts with a single encoding, but now
each cast has its own encoding).  To the extent possible, setting
ABI_COMPATIBILITY_VERSION < 402 provides the previous behavior.


7/21/10  [EDGcpfe/10848]
Abort on return optimization of aggregate class initialized with { ... }

In versions configured to do partial lowering of exception-handling
constructs (IL lowering plus DO_FULL_PORTABLE_EH_LOWERING FALSE and
GENERATE_EH_TABLES TRUE), the front end aborted in
make_handle_for_entity ("non-simple indirection") while attempting
to handle return value optimization for a returned variable that has
an "aggregate" class type and is initialized by a brace-enclosed
aggregate initialization.  Now fixed, by disabling the return
value optimization for variables of aggregate class type in such
configurations.

  struct A { virtual ~A(); };
  struct B {
    A a;
    A a2;
    A a3;
  };
  B f() {
    B b = { A(), A(), A() };
    return b;
  }


7/20/10  [EDGcpfe/10833]
GNU ABI compatibility: #pragma pack(n) and attribute "aligned"

Previously, when a "#pragma pack(n)" construct was in effect in GNU mode (with
a nonzero n), the effect of the GNU attribute "aligned" applied to a bit field
was mistakenly ignored.  This is now fixed.

  #pragma pack(4)
  struct S {
    char c;
    int i:1 __attribute((aligned(4)));
  };  // Previously, S had size 4 on a typical 32-bit int platform;
      // now S has size 8 on that same platform.

(See also the Changes entry of 10/20/03 for GNU-mode effects of "#pragma pack"
on bit fields.)


7/18/10  [EDGcpfe/10712]
Multibyte characters ending in '\' followed only by white space

In configurations in which MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED and
BACKSLASH_CAN_OCCUR_AS_PART_OF_MULTIBYTE_CHAR are both TRUE, the front end
incorrectly treated a 0x5c occurring as the last byte of a multibyte
character as if it were a backslash character when it is followed only
by one or more white space characters.  The result of this error was an
incorrect line splice in GNU modes (see the 3/15/05 entry) and a spurious
warning in non-GNU modes (see the 1/14/09 entry).  This is now fixed.  For
example, the front end formerly issued a warning about a "\" followed by
white space for the following when compiled in --microsoft mode:

  #pragma setlocale(".932")
  void f() {
    // The characters after the // below are 0x8b 0x40 0x94 0x5c 0x20
    //«8b»@«94»\ 
  }

Note: The above example must be decoded using the edg-changes-example tool.


7/18/10  [EDGcpfe/9244]
Value of __LINE__ in a multi-line macro invocation

When expanding the __LINE__ macro inside the expansion of a macro whose
invocation covers more than one line, the front end previously used the
source position of the macro name.  The C and C++ Standards are not
completely clear on this point, but other major compilers use the source
position of the closing right parenthesis.  The front end has now been
changed to follow suit.  For example:

  extern "C" int printf(const char*, ...);
  #define M() printf("%d\n", __LINE__)
  int main() {
    M(        // Previously printed "4", now "5"
     );
  }


7/15/10  [EDGcpfe/10839]
Use of freed param_id entry for parameter of function template instance

The param_id entry for a parameter of an instance of a function template
was being freed even though the parameter symbol still made use of it.
This could result in various kinds of errors or internal errors.  Now
fixed.  The error occurred in versions without source sequence lists
during the instantiation of a default argument of the function template.


7/15/10  [EDGcpfe/10835]
Implicit definition of virtual destructor forced in fewer places

The implicit definition of a virtual destructor is now forced in
fewer places.  That allows an example like the following to compile,
where defining the destructor in this compilation formerly caused an
error.  (The destructor will be required somewhere in the linked
program, but it doesn't have to be defined in this translation
unit.)


  template<typename T> struct A {
    ~A() {
      m->f();  // Formerly, an error was issued here
    }
    T *m;
  };
  struct Base {
   virtual ~Base();
   int f();
  };
  struct D1 : public Base {
   virtual ~D1();
  };
  class B;
  struct D2 : public Base {
   virtual void foo();
   A<B> m_name;
  };
  void check () {
    D1* v = 0;
    (void*) dynamic_cast<const D2*>(v);
  }


7/14/10  [EDGcpfe/10838]
decltype(...) as the type in a functional-notation cast

The type in a functional-notation cast can now be specified by way of the
decltype construct, e.g.,

  k = decltype(i)(j);  // Casts "j" to the decltype of "i"


7/14/10  [EDGcpfe/10832]
Spurious error on initializer expression that starts with a string literal

The front end previously sometimes issued a spurious error if an initializer
expression started with a string literal but was followed by an operation
(e.g., a subscript).  For example:

  char x[] = { "abc"[1], 0 };  // Previously triggered a spurious error.

This is now fixed.


7/14/10  [EDGcpfe/10831]
Microsoft compatibility: "static" specifier on out-of-class member declaration

Ordinarily, the storage specifier "static" cannot be specified on an out-of-
class member declaration (not even if it is a static member).  Now, however,
if the declaration is a template declaration in Microsoft bugs mode, the
"static" keyword is ignored with a warning.  For example:

  template<class T> struct S { void f(); };
  template<class T> static void S<T>::f() {}
    // Previously always an error.  Now only elicits a warning in
    // Microsoft bugs mode.


7/13/10  [EDGcpfe/10825]
GNU compatibility: __alignof and attribute "packed"

In GNU modes, __alignof applied to a field selection operation produces the
alignment of the indicated field (which may include the effect of certain
attributes and/or pragmas).  Previously, however, the "packed" attribute
applied to the class enclosing the field was ignored.  For example:

  struct __attribute((packed)) S {
    char x;
    int y;
  } s;
  unsigned f() {
    return __alignof(s.y);  // Previously returned the alignment of "int";
  }                         // now returns 1.

This is now fixed.

Furthermore, the result of __alignof for a field selection expression
designating a field declared with the "packed" attribute was previously always
equal to one, even if the field was explicitly aligned to a larger value.  Now
this behavior is limited to GNU modes with gnu_version < 30400.  For example:

  struct T {
    char x;
    int y __attribute((packed, aligned(2)));
  } t;
  unsigned g() {
    return __alignof(t.y);  // Previously always returned 1; now returns 2 if
  }                         // gnu_version >= 30400.

(See also the Changes entry of 8/23/07.)


7/12/10  [EDGcpfe/10812]
Microsoft compatibility: use of class template without argument list

The Microsoft compiler allows a class template to reference another class
template without providing a template argument list.  An error is only
produced by the Microsoft compiler if the template is actually instantiated.
We now emulate this behavior in Microsoft bugs mode.

  template<typename X> struct A {   
    typedef int i;
  };  
  template<typename Y> struct B {   
    typedef typename A::i i;  // should be A<Y>::i
  };  


7/12/10  [EDGcpfe/10765]
C++-generating back end: nullptr in default argument of template alias

In some cases in which nullptr is used in a default argument of a template
alias, a use of that alias could result in generated code that was missing
a needed cast of that nullptr argument.  This is now fixed.  For example:

  template<typename T, T (*p)() = nullptr> using A = decltype(p());
  template<typename T> struct S { };
  template<typename T> using B = S<A<T>>;

The type in the last line was previously incorrectly generated as

  S<decltype((nullptr()))>

It is now correctly generated as

  S<decltype((((T (*)(void))nullptr)()))>


7/11/10  [EDGcpfe/10766]
C++-generating back end: missing qualification for hidden template alias

The C++-generating back end failed to generate the necessary qualification
for the name of a template alias that is hidden by another declaration.
This is now fixed.  For example:

  struct A {
    template<typename T> using B = T;
  };
  struct B: A::B<A> {
    A::B<int> i;   // Previously generated as B<int>, missing "A::"
  };


7/11/10  [EDGcpfe/10816]
Assertion failure with FULLY_RESOLVED_MACRO_POSITIONS and multibyte characters

In configurations in which FULLY_RESOLVED_MACRO_POSITIONS is TRUE, compiling
a source file with multibyte characters could result in an assertion failure
in clone_macro_text_map_entries ("map entry pointer past end of entries
array").  This is now fixed.  For example:

  #define M(x) x;
  void f() {
    M("«a1d6a4a4a4a4»"); // Assertion failure with --multibyte_chars
  }

Note: The above example must be decoded using the edg-changes-example tool.


7/7/10   [EDGcpfe/10780]
C++-generating back end: references to hidden partial specializations

The C++-generating back end failed to use the necessary qualification when
referring to a partial specialization of a class template when the name of
the template is hidden by another entity.  This has now been fixed.  For
example:

  namespace N {
    template<typename T> class F;
    template<typename R> class F<R ()> { };
    namespace M {
      namespace F { }     // hides class template F
      struct S {
        N::F<void()> fv;  // formerly generated as F<void()>, missing "N::"
      };
    }
  }


7/7/10   [EDGcpfe/10817]
GNU C++ compatibility: allow use of enum as qualifier in C++0x mode

g++ does not normally find an enumeration name when looking up a name
that precedes a "::", but it does find the name in g++'s C++0x mode.  We
now emulate the g++ behavior in C++0x mode when g++ mode is also used.

  typedef enum T {t1} X;
  int x = X::t1;


7/7/10   [EDGcpfe/10810]
GNU C compatibility: Incompatible block-extern and implicit declarations

GNU C sometimes permits two block-extern declarations of the same function
to have incompatible types.  The changes for EDGcpfe/10053 (entry of 10/30/09)
restricted this behavior to gnu_version < 30400.  GCC 4.x, however, also
allows a block-extern declaration that is incompatible with an implicit
declaration: This is now emulated when gnu_version >= 40000.  For example:

  void g(void) { f(1); }  // Implicit declaration with "int" return type.
  void h(void) {
    void f(int);  // Conflicting type not an error when gnu_version >= 40000.
    f(2);
  }

The example above was accepted in all GNU C modes with version 4.1 of the
front end, but the changes for EDGcpfe/10053 triggered an error when
gnu_version >= 30400.  Now the example is accepted again (with a warning)
when gnu_version >= 40000.


7/2/10   [EDGcpfe/10800]
GNU C++ mode: call of member of current class is falsely considered dependent
as a call argument

Another wrinkle on the previous change for EDGcpfe/10527: In a template,
g++ considers a call of a function in the current class to be dependent
as a call argument even if its return type is known.  Now emulated in
GNU C++ mode.

  template <class T> struct B {
    static T* B_func(int);
  };
  template <class T> struct D : public B<T> {
    int D_func();
    void mf() {
      B_func(D_func());  // B_func is found because of argument-dependent
                         // lookup because D_func() is falsely taken to
                         // be dependent
    }
  };
  int main() {
    D<char> d;
    d.mf();
  }


7/2/10   [EDGcpfe/10793]
Nonreal member name fails to bind to reference-typed nontype template parameter

A spurious error was issued on a use of a member of a template parameter
class as a nontype template argument for a template parameter of reference
type.  Now fixed.

template<typename A, typename K> class X {};
template<typename A, typename K, X<A, K> const& RK> struct B {};
template<typename A>
class FK : public B<A, typename A::KeyType, A::primaryKey> {};  


7/2/10   [EDGcpfe/10799]
Elimination of "[with T=T]" from prototype instantiation diagnostics

Certain diagnostics that refer to prototype instantiations included
template argument information of the form "[with T=T]".  This was
already suppressed in many contexts, and is now suppressed in more
cases.

  // gets "missing return ..." when nonclass prototype instantiations are
  // enabled
  template <class T> int A(T) {}


7/1/10   [EDGcpfe/10229]
Internal error in create_nonreal_progenitor_symbol

An internal error could occur in create_nonreal_progenitor_symbol when
doing a prototype instantiation of a function that contains a reference
to an undefined member of class that has a local class as a base class.
Now fixed.

  template <class T> void f(T) {
    class A {};
    class B : public A {};
    B b;
    if (b.B::X == 1) {}  // internal error on lookup of B::X in A
  }


7/1/10   [EDGcpfe/10787]
Spurious error on new-expression followed by subscript in some GNU modes

In GNU C++ mode with gnu_version < 30400, the front end previously issued a
spurious error when a new-expression enclosed in parentheses was followed by
a subscript operation.  In configurations with EXPENSIVE_CHECKING set to TRUE
the front end subsequently aborted with an internal error ("stop token array
not all zero").  For example:

  void f() {
    (new int)[5];  // Previously triggered a spurious error in some GNU
  }                // modes (and an internal error in some configurations).

This is now fixed.


7/1/10   [EDGcpfe/10773]
IA-64 ABI: mangling of sizeof/alignof with non-dependent types

Although not explicitly stated previously in the IA-64 ABI, it was common
practice to use the value of a non-dependent sizeof/alignof when mangled as
part of a template name (rather than its explicit mangling).  In cases where
a non-dependent sizeof/alignof appeared as a subexpression in a larger
dependent expression (even one with an implied cast that does not appear in the
mangled name), the sizeof/alignof had been mangled explicitly.  This has been
changed such that any non-dependent sizeof/alignof is mangled using its value,
regardless of whether or not it appears in the context of a dependent
expression.  This provides better compatibility with g++'s behavior (g++ 4.0
and later also "fold" non-dependent sizeof/alignof for mangling) in this
area (though not 100% as g++ generates a different mangled name for the last
case in this example).  The previous behavior is restored when 
ABI_COMPATIBILITY_VERSION < 402 or emulate_gnu_abi_bugs is TRUE and
gnu_version < 40000.  For example (with a configuration where size_t is
unsigned long):

  template <class T, T N> struct S {};
  template <class T> void f1(S<T, sizeof(char)>);
  template <class T> void f2(S<T, sizeof(char)+sizeof(char)>);
  template <class T> void f3(S<T, (T)sizeof(sizeof(char))>);
  S<int,sizeof(char)> s1;
  S<int,sizeof(char)+sizeof(char)> s2;
  S<int,sizeof(sizeof(char))> s3;
  int main() {
    f1(s1); // was: _Z2f1IiEv1SIT_XstcEE
            // now: _Z2f1IiEv1SIT_Lm1EE
    f2(s2); // was: _Z2f2IiEv1SIT_XplstcstcEE
            // now: _Z2f2IiEv1SIT_Lm2EE
    f3(s3); // was: _Z2f3IiEv1SIT_XcvS1_szstcEE
            // now: _Z2f3IiEv1SIT_XcvS1_Lm8EEE
            // g++: _Z2f3IiEv1SIT_XcvS1_szLm1EEE
  }


6/30/10  [EDGcpfe/10764]
C++-generating back end: names of conversion operators

The C++-generating back end generated the name of a conversion operator in
its declaration inside the class based on the type used in its definition
outside the class.  This could cause problems when that type involves
typedefs or template aliases that are defined after the declaration of the
conversion operator.  This has been fixed to use the original types from
the in-class declaration (the out-of-class definition remains unchanged).
For example:

  typedef int INT;
  typedef char CHAR;
  struct S {
    operator INT();   // Previously generated as operator int()
    operator CHAR();  // Previously generated as operator a<char>()
  };
  typedef int Int;
  template<typename T> using a = T;
  S::operator Int() { return 0; }
  S::operator a<char>() { return 0; }


6/29/10  [EDGcpfe/10744]
GNU C++ compatibility: Emit typeinfo for complex types

Lowering had mistakenly assumed that the typeinfo for complex types was
supplied by the runtime library and consequently did not emit it when
needed, resulting in linker errors.  This has now been fixed.  For example,
this program (with --g++) had resulted in a linker error and now links cleanly:

  int main() {
    throw(__I__);
  }


6/29/10  [EDGcpfe/10781]
GNU C++ compatibility: incorrect C++-generating back end output for
g++ code with missing template keyword

The g++ compiler accepts a call of a dependent function template without
the use of the "template" keyword in some cases (see 9/22/08 entry).
In such cases the code emitted by the C++-generating back end failed to
include the template argument list for the call.  Now fixed.

  template<int DIM, class T> void get(const T& x) {
    x.get<DIM>();  // template argument list omitted in output
  }


6/29/10  [EDGcpfe/10783]
More folding of operands to __builtin_constant_p

Operands to the GNU C builtin function __builtin_constant_p are now more
aggressively folded to constants, which of course is desirable since the
point of the builtin is to test whether the operand is constant.  This
test case formerly got an error in gcc mode and now compiles correctly:

  int f();
  int main() {
    sizeof(struct { int x:(__builtin_constant_p(
                             __builtin_constant_p(1) ? 1 : f()
                                               )
                          ); });
    return 0;
  }


6/28/10  [EDGcpfe/10616]
c++0x: exported templates no longer supported

The C++0x standard no longer includes exported templates.  This feature is
now disabled by default in C++0x mode.


6/26/10  [EDGcpfe/10778]
Abort on destructible entity in dead code of conditional whose result is
constant

The front end encountered an internal error in
discard_constant_expr_object_lifetime in exprutil.c when processing
a ?, &&, or || operator whose overall result is constant, and that
has an operand that is unevaluated because the first operand is a
known constant, and furthermore this unevaluated operand includes a
destructible temporary.  Now fixed.

  struct A {
    ~A() {}
    operator int() { return 0; }
  };
  int i = 0 && A();
  int main() { }

This involves a very small IL CHANGE: a dynamic init entry that is
potentially evaluated but not evaluated and has a non-NULL destructor
field may now have a NULL lifetime field indicating that the
destruction was not put onto any object lifetime list (it's not
needed, after all, since the initialization is dead code).


6/25/10  [EDGcpfe/10687]
Microsoft compatibility: default Microsoft attribute behavior

Formerly, the use of Microsoft attributes (those of the form "[...]")
in versions other than C++-generating back end versions would result in
"unrecognized attribute" warnings.  This was reasonable behavior when
attributes were rarely used, but with the introduction of source annotation
attributes (also known as SAL attributes) virtually any program that makes
use of the Microsoft header files makes some use of attributes.
Consequently, the default configuration is now to have attributes
recognized (in Microsoft mode).  Specifically, the default value of
RECOGNIZE_MICROSOFT_ATTRIBUTES is now always TRUE.  The default value of
SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING continues to be TRUE, meaning that
no semantic processing of attributes beyond verifying the validity of the
attribute name is done.


6/23/10  [EDGcpfe/10759]
Enumeration constants as case label constants in C

The type of an enumeration constant in C is int, not the enumeration type.
The IL does make it possible to determine the enumeration type, however,
via the variant.integer.enum_info.affiliated_type field in the constant's
type.  Case label constants are converted to the type of the expression in
the containing switch statement, and when that type is something other than
int, a backing expression for an enumeration constant appearing as the
case_value in a_switch_case_entry is created designating the original
enumeration constant and thus allowing the affiliated_type to be found.
When the switch expression's type is int, however, no backing expression
was created and the constant's type was just int, with no affiliated_type.
This has now been fixed so that a backing expression is always created for
a case_value constant resulting from use of an enumeration constant for a
case label.  For example:

  enum E { e0 };
  void f(int i) {
    switch(i) {
      case e0:  /* Now has backing expression designating "e0". */
        break;
    }
  }


6/23/10  [EDGcpfe/10771]
Checking pragmas not enabled by default with EXPENSIVE_CHECKING

Formerly, ADD_CHECKING_PRAGMAS_FOR_INTERNAL_TESTING was enabled by default
when EXPENSIVE_CHECKING was enabled.  Unlike other checks enabled by
EXPENSIVE_CHECKING, the checking pragmas can change the code that is
generated, whether functions can be inlined, etc., which may be surprising.
The default for ADD_CHECKING_PRAGMAS_FOR_INTERNAL_TESTING is now always FALSE.


6/23/10  [EDGcpfe/7122]
Default template arguments for function templates

The C++ standard was updated by core issue 226 to allow default template
arguments to be specified for function templates.  This is now supported
by the front end.

  template <class T, class U = T> void f(T, U = 1){}
  int main() {
    f(1);      // U uses the default of T (which is int in this case)
    f(1, 2.0); // U deduced as double
  }


6/19/10  [EDGcpfe/10760]
Unlowered pointer to member type kind in dynamic initialization

In cases where a dynamic initialization involves a type that contains a
function type with a parameter type that is passed via a copy constructor, a
cast operation is added after the expression has been lowered, and that cast
operation may have an unlowered type_kind.  In configurations that use the
C generating back end, this unlowered IL causes an assertion failure in
dump_expr in c_gen_be on this example (--c++0x):

  struct A {};
  struct B {
    B(const B&) {}
  };
  template <class T> auto f(T x) -> decltype(*new T A::*);
  void g() {
    B (B::*a)(B);
    auto p = f(a);
  }


6/18/10  [EDGcpfe/10561]
Microsoft C++ compatibility: Multiple extern "C" definitions

In Microsoft C++ bugs mode, the front end now accepts multiple definitions of
the same extern "C" function in different namespaces (each such definition
is associated with a different a_routine entry).  For example:

  namespace N { extern "C" void f() { } }
  namespace M { extern "C" void f() { } }  // Previously always an error; now
                                           // accepted in Microsoft bugs mode.

Cases like these are likely to result in a linker error, but if the functions
are declared "inline", an error may be avoided.


6/18/10  [EDGcpfe/10585]
C++0x attribute "final" (IL CHANGE)

When the "final" attribute was originally added to the working paper for the
next C++ standard ("C++0x"), its use on a class type indicated that all
virtual members of that class type were implicitly "final", but the class
could still be derived from.  Later, the working paper was revised such that
the "final" attribute now means that a class cannot be used as a base class
type: The front end now reflects this.  For example:

  struct [[final]] B {};
  struct D: B {};  // Error: B is a final class.

The new meaning of "final" for class types is now identical to that of the
Microsoft-specific "sealed" modifier for class types.  Therefore, the flag
"sealed" in a_type has been eliminated, and the "sealed" modifier is now
instead reflected in the "final" flag.  (This is an IL CHANGE.)


6/18/10  [EDGcpfe/10758]
Incorrect IA-64 ABI mangling for lvalue routine used as a nontype template
argument

In cases where an lvalue routine is used as a nontype template argument,
an extra "ad" (representing the "address of" operator) had mistakenly been
added to the IA-64 mangled name of the template.  Note that by removing the
extra mangled operator, the template argument no longer needs to be mangled
as an expression, so the "X ... E" <template-arg> production is no longer
used.  This has now been fixed (the previous behavior is retained when
ABI_COMPATIBILITY_VERSION < 402).  For example:

  template <class T> struct A {
    template <void (*PF)()> struct B {};
  };
  void ff();
  template<class T> typename A<T>::template B<ff> f(T);
  int main() {
    f(1);   // was: _Z1fIiEN1AIT_E1BIXadL_Z2ffvEEEES1_
            // now: _Z1fIiEN1AIT_E1BIL_Z2ffvEEES1_
  }

6/18/10  [EDGcpfe/10734]
Source sequence entry pointer for using-declaration entries

The front end previously failed to set the "source_sequence_entry" pointer in
a_using_decl entries.  This is now fixed.


6/18/10  [EDGcpfe/10644]
Spurious remark on checking of printf %ls specifier against const wide string

The checking of printf/scanf formatting specifiers generated a spurious
remark when matching up a %ls (wide string) formatting specifier with
an argument that is a const wide string.  Now fixed.

  #pragma __printf_args
  void printa(char const *s, ...);
  void faw(void) { printa("%ls", L"a"); }   // Formerly produced remark


6/17/10  [EDGcpfe/10756]
Lifetime of call-result temporary bound to reference not extended

In a regression introduced in version 4.0, a temporary rvalue of class type
that can be bitwise copied (i.e., no copy constructor is needed), returned
from a function call and bound to a reference with static lifetime, was not
extended to static lifetime.  This was because there was no explicit
front end temporary (enk_temp_init and associated dynamic initialization
entry) generated in that case whose lifetime could be adjusted.  Now,
such a temporary is generated and its lifetime is properly extended.

  struct S {
    int x;
    S() : x(7) {}
  };
  S s;
  S f() { return s; }
  const S& cr = f();  // Lifetime of returned value is now extended
  int main() {
    if (cr.x != 7) {
      return 1;
    }
  }


6/16/10  [EDGcpfe/10755]
GNU C++0x mode: Typedefs and unnamed types as template arguments

Previously, in GNU C++0x mode ("--g++ --c++0x"), a typedef of a template
parameter could imbue a name for linkage purposes when the template parameter
was substituted by an unnamed class or enumeration type (e.g., a closure type
for a lambda expression).  For example:

  template<class T> void f(T) { typedef T X; }
  int main() {
    f([]{});
    f([]{});
      // Previously, both closure types were given the name "X" for linkage
      // purposes.  (Resulting e.g. in invalid generated C code.)
  }

This is now fixed (i.e., no name for linkage purposes is imbued in such cases).


6/16/10  [EDGcpfe/10757]
Explicit template argument for reference-typed parameter not seen as dependent

In a regression introduced in version 4.0, an explicit nontype template
argument passed to a reference-typed template parameter was not seen as
dependent when appropriate, and overload resolution on a call with
such an explicit template argument was not correctly deferred until
the actual instantiation of the template.  As a consequence, various
aborts could occur, e.g., "lower_constant: bad kind" in IL lowering.
Now fixed.

  typedef int ZP;
  template <ZP& I> ZP f() {}
  void h(ZP) {}
  template <ZP& I> struct X {
    void g() {
      h(f<I>());
    }
  };
  ZP z;
  int main() {
    X<z> x; 
    x.g();
  }


6/15/10  [EDGcpfe/10722]
Microsoft compatibility: internal error on __super use of using-declaration

In Microsoft mode, an internal error could occur (in add_symbol_to_super_set)
on a function call in which the function was named using the __super keyword
and where the set of functions being considered included a function made
visible by a using-declaration.  Now fixed.

  struct  C1 {
    virtual void f(double);
    virtual void f(long);
  };	
  struct C2 : C1 {
    using C1::f;
    virtual void f(long);
  };
  struct  C3 : public C2 {
    void g(long l) { __super::f(l); }
  };


6/15/10  [EDGcpfe/10656]
GNU C++0x compatibility: List initializers in return statements

Recent versions of GCC support C++0x-style list initializers and make some
use of the feature in return statements that appear in GCC system headers.
The front end does not yet accept C++0x list initializers in general, but
in GNU C++0x mode it now accepts some list initialization cases in return
statements.  For example:

  struct S { int x; };
  S f() { return { 42 }; }  // Now accepted with --g++ --c++0x


6/15/10
Default GNU version changed to 4.2

The default value of DEFAULT_GNU_VERSION, which specifies the default
version of gcc/g++ to be emulated, has been updated to 40200, which
corresponds to gcc/g++ version 4.2.


6/14/10  [EDGcpfe/10751]
C++-generating back end: template aliases in generated code

The C++-generating back end used the underlying type of a template alias
instead of the alias itself in the generated code.  This is now fixed.  For
example:

  template<int I> struct S { };
  template<int I> using X = S<I+1>;
  X<5> x5;  // Previously generated as "S<6> x5;"


6/10/10  [EDGcpfe/10740]
Internal error on specialization of nonreal class

An internal error could occur (in various places) on an attempt to
specialize a nonreal class.  Now fixed.

  template <template <class> class T,
            typename X = class T<int> { T(); }> struct A {};



6/10/10  [EDGcpfe/10627]
Internal error on missing template argument list on template from base class

An internal error (in scan_field_selection_operator) could occur on a
reference to a class template from a base class referenced as a member of a
derived class.  The internal error would occur if the reference omitted
the template argument list.  Now fixed.

  struct A {
    template <class U> struct C {};
  };
  struct B : A { };
  template <class T> void f(T p) {
    p.T::C();  // missing argument list for A::C (inherited in B)
  }
  int main() {
    f(B());
  }


6/10/10  [EDGcpfe/10736]
GNU C compatibility: "static" function declarations in local scopes

In default C mode, the front end accepts (as an extension) a function
declaration in a local scope with the "static" specifier.  For example:

  void g() {
    static void f();  // Nonstandard, but accepted in default C mode.
  }

Such a function is given internal linkage (i.e., as if it had been declared
with "static" in the file scope).  Previously, such declarations were handled
identically in GNU C modes.  Now, when gnu_version >= 40000, such declarations
trigger an error, and when gnu_version < 30400, the "static" specifier is
ignored (in the example above, this results in f having external linkage).


6/10/10  [EDGcpfe/10737]
Internal error during deduction on array with invalid substituted bound

An internal error could occur in copy_array_type_with_substitution if
the result of the copy was a substituted array bound with an invalid
type.  Now fixed.

  template <class T> struct A {};
  template <class T, class U, U I> void f(A<T> (*)(U(&)[I])) {}
  int main() {
    f<int,double,37>(0);
  }


6/9/10   [EDGcpfe/10557]
Microsoft compatibility: __uuidof and explicit class template specialization

In Microsoft mode, the front end previously ignored a uuid specified on an
explicit specialization of a class template when scanning a uuidof operator.
This is now fixed.  For example:

  template<typename T> class C;
  template<>
    class __declspec(uuid("73BD59D0-7FB0-45E4-A44E-A4494EABE793")) C<int> {
    };
  int main() {
    (void)__uuidof(C<int>);  // Previously an error.  Now accepted.
  }


6/9/10   [EDGcpfe/10559]
Microsoft compatibility: __builtin_alignof

In Microsoft modes, the new keyword __builtin_alignof is now equivalent to
__alignof.


6/8/10   [EDGcpfe/10728]
GNU compatibility: Attributes on explicit instantiations

IN GNU C++ modes, the front end now accepts GNU attributes on explicit
instantiation directives for function template specializations.  For example:

  template<class T> void f(T);
  template __attribute((deprecated)) void f(int);  // Now accepted.
  int main() {
    f(42);  // Warning: f<int>(int) is deprecated.
  }


6/6/10   [EDGcpfe/10713]
C++-generating back end: Qualification in prototype instantiation calls to
members of class templates

In configurations in which the C++-generating back end generates the
definition of a function template from the prototype instantiation, the
qualification used in naming member functions of class templates was
sometimes incorrect, potentially leading to invoking the wrong variant of
a virtual function.  The source form of the reference to the function is
now correctly reproduced in the output when RECORD_FORM_OF_NAME_REFERENCE
is set to TRUE.  For example:

  template<typename T> struct B {
    virtual void f();
  };
  template<typename T> void g(B<T>& ref, B<T>* ptr) {
    ptr->B<T>::f();  // Previously generated as ptr->f()
    ref.f();         // Previously generated as ref.B<T>::f()
  }


6/4/10   [EDGcpfe/10570]
GNU C compatibility: Flexible array member initializer constraints

In GNU C mode, the front end accepts aggregate initializers for flexible array
members (see Changes entry of 9/1/04).  Now, an additional constraint is
enforced (to match the behavior of GCC): The variable being initialized must
have static storage duration.  For example:

  typedef struct S { int n; int a[]; } S;
  void g() {
    S s1 = { 1, { 2 } };  // Previously accepted in GNU C mode; now an error.
    static S s2 = { 3, { 4 } };  // Still accepted in GNU C mode.
  }


6/4/10   [EDGcpfe/10686,EDGcpfe/10624]
IA-64 ABI: Alignment of class with explicitly aligned empty base class type

The front end previously failed to ensure that a derived class be at least
as strictly aligned as a base class if the base class was empty.  For example,
in g++ mode:

  struct __attribute((aligned(16))) B {};
  struct D: B {};  // Previously, the alignment of B was not reflected in the
                   // alignment of D (i.e., the alignment of D could be 1).

This is now fixed.  However, when emulate_gnu_abi_bugs is TRUE and
gnu_abi_version < 40300, the previous behavior is maintained since it matches
that of corresponding GCC versions.


6/3/10   [EDGcpfe/10724]
Additional flexibility in the setting of __STDC__

Some systems (e.g., some versions of Intel Solaris) require __STDC__ to
be zero while compiling the system header files.  The front end already
has the ability to set __STDC__ to zero in system headers but there was
not a configuration macro to set this as the default behavior.  The
DEFAULT_STDC_ZERO_IN_SYSTEM_HEADERS macro has been added to provide this
capability.  In addition, when a system header is not being processed
the __STDC__ macro now has the value it would have if __STDC__ was not
being treated specially in system headers (formerly __STDC__ would always
be 1 when not in a system header).

6/2/10   [EDGcpfe/10721]
Abort on aggregate initializer involving an unnamed bit field

The front end aborted during lowering in lower_dynamic_init_aggregate_constant
("have constant, no field") in some cases with an aggregate initializer that
does not initialize all the fields of a class type that also includes an
unnamed bit field.  For example:

  struct D { D(); };
  struct A {
    int i;
    D   d;
    int :0;
  };
  int main() { A x = { 0 }; }  // Previously triggered an internal error.

This is now fixed.


6/2/10   [EDGcpfe/10710]
GNU C++ typeof applied to an expression can be written without parentheses

gcc and g++ have an extension, typeof, that can be used to extract
the type of an expression and use it in a declaration.  typeof(x),
for example, means the type of the expression "x".  Heretofore,
the front end has required that the operand of typeof always be
enclosed in parentheses, but it turns out that, since version 3.4,
g++ (but not gcc) allows typeof to be applied to an unparenthesized
expression.  We now allow the same, in GNU C++ mode, with gnu_version
>= 30400.

  int main() {
    typeof (int *) p = (int *)0;  // typeof applied to a type
    typeof (p) p2 = (int *)0;     // typeof applied to a parenthesized expr
    typeof p p3 = (int *)0;       // typeof applied to an unparenthesized expr;
                                  // now accepted in g++ mode.
  }


6/1/10   [EDGcpfe/10690]
GNU compatibility: Attribute may_alias

In GNU modes with gnu_version >= 30300, the front end now accepts the GNU
attribute "may_alias" (the attribute indicates that the standard rules
regarding aliasing for pointers to different types are weakened so that a
back end should not rely on them).  For example:

  typedef int __attribute((may_alias)) AliasedInt;


6/1/10   [EDGcpfe/10716]
Another tweak on gcc do-nothing casts

In GNU C mode, a cast of a class rvalue to the same type (ignoring
cv-qualifiers) is now accepted and ignored.

  typedef struct A { int i; } A;
  extern A f();
  int main() {
    (A)f();  // Now accepted
  }


5/26/10  [EDGcpfe/10705]
GNU compatibility: __extension__ on function parameter declarations

Previously, the front end accepted the __extension__ keyword on function
parameter declarations in GNU C mode.  E.g.:

  void f(__extension__ int p);  // No longer accepted in GNU C mode.

This is no longer accepted since GNU compilers do not permit such either.
Furthermore, the diagnostic issued in GNU C++ mode has been improved.


5/26/10  [EDGcpfe/10706]
C++-generating back end abort in Microsoft C mode on type declared in a
function prototype scope

In Microsoft C mode, the C++-generating back end previously could abort in
gen_declaration_statement when a class type was declared in a function
prototype scope of a block-extern declaration.  For example:

  void f() {
    void g(struct X *px);  // Previously triggered an abort in the
  }                        // C++-generating back end.

This is now fixed.


5/26/10  [EDGcpfe/10704]
Microsoft compatibility: incorrect locale used for identifier characters

The native_multibyte_locale variable was incorrectly declared as static
in host_envir.h.  This could result in an incorrect locale being used in
lexical.c for the conversion of multibyte characters in identifiers.
Now fixed.

5/26/10  [EDGcpfe/9169]
Extra flags on typeref entries for decltype and typeof

The typeref entries for types named via decltype or typeof now have an
additional flag, is_dependent_decltype_or_typeof, that indicates that
the operand expression is dependent (including cases where the final
type is not dependent but a subexpression is).  The typeof case also
has a new flag is_typeof_with_type_operand that indicates that the
operand of typeof is a type, i.e., typeof(type-name), rather than
an expression.


5/25/10  [EDGcpfe/10700]
Use of uninitialized variable in update_instantiation_flags

When an explicit instantiation was followed by an "extern template"
declaration, an unset variable was passed from update_instantiation_flags to
update_instantiation_required_flag after a diagnostic was issued.  Now fixed.

  template <typename T> struct A {
    A(){};
  };
  template class A<char>;
  extern template class A<char>;


5/23/10  [EDGcpfe/9290]
GNU: Remove warning when local labels are used outside of statement expressions

The GNU compiler allows local labels to be used at the beginning of any block
statement.  The warning issued by the front end when local labels were declared
outside of statement expressions has been removed.  This example had previously
resulted in a warning (in --gcc or --g++ mode), and doesn't any longer:

  void f() {
    __label__ l1;
    goto l1;
  l1:;
  }


5/19/10  [EDGcpfe/10703]
UNARY_PLUS_IN_IL eliminated; unary plus operator is always present in IL

The UNARY_PLUS_IN_IL macro, which controlled whether unary "+" operators
would be put into the IL, has now been eliminated, with the consequence
that customers that formerly had this macro set to FALSE will now see
eok_unary_plus operators in the IL and must be prepared to handle them
(IL CHANGE).  Lowering has been modified to remove the eok_unary_plus
operation (by overwriting it with its operand), so customers who use lowering
should see no change.  This change was made to ensure that such operators are
always available in the new-style SFINAE implementation.


5/18/10  [EDGcpfe/10646]
Placeholder types removed (IL CHANGE)

Previously, the front end generated "placeholder typeref" types on the file-
scope types list to indicate the order in which types (in other scopes) were
encountered.  This was needed particularly to produce lowered IL that would
cause the C-generating back end to render correct C code -- i.e., code where
the definition of a type appeared before a declaration that depended on that
definition.  (Lowering used the placeholder types as markers to insert types
promoted from other scopes.)
Now, the same goal is achieved without placeholder types: After IL lowering
the types list is sorted to meet the requirements of the C-generating back end.
Whether this sorting is done is determined by the configuration macro
ENSURE_LOWERED_TYPE_LIST_ORDERING (it must be TRUE if the C-generating back end
is used).


5/17/10  [EDGcpfe/9169]
enk_param_ref nodes (IL CHANGE)

Previously, the IL definition had no way to represent a reference to a function
parameter if that reference appeared outside the definition of the function.
For example:

  auto f(int n)->decltype(n);

Prior to the C++0x SFINAE implementation (see Changes entry of 4/26/10), such
parameter references were replaced by "dummy expressions" producing the type of
the parameter (these dummy expressions dereferenced a null pointer constant).

Now, a new expression node kind enk_param_ref is used to represent the
indicated parameter.  Since there can be multiple a_type entries for a given
function type, enk_param_ref nodes cannot point directly to such type entries
(or to their associated a_param_type entries).  Instead, a coordinate system
is used (somewhat similar to the coordinates used for template parameters),
and code that tracks function declarators can use the coordinates of an
enk_param_ref node to identify a corresponding a_param_type entry.


5/13/10  [EDGcpfe/10680]
C++-generating back end: members of dependent base classes in prototype
instantiations

In a configuration in which template definitions are generated from the
prototype instantiation rather than the string form of the template, the
C++-generating back end failed to use a qualified name for a dependent name
that is assumed to come from a dependent base class, thus making the name
non-dependent in the generated code.  This has now been fixed.  For example:

  template<typename T> struct B {
    typedef int I;
  };
  template<typename T> struct D: B<T> {
    typename D::I m;    // Previously generated as "I m;"
  };


5/9/10   [EDGcpfe/10681]
C++-generating back end: template headers with unintentional digraphs

In a configuration in which template definitions are generated from
prototype instantiations, the header of a template whose first parameter is
a non-type parameter whose type name is qualified using the global scope
operator "::" was written by the C++-generating back end with no space
between the "<" and "::" tokens, inadvertently forming the "<:" digraph
(the alternate token spelling for "[").  This is now fixed.  For example:

  typedef int I;
  namespace N {
    template< ::I n> struct S;  // Formerly generated as "template<::I..."
  }


5/9/10   [EDGcpfe/10678]
C++-generating back end: user-defined conversions in folded conditional
expressions

When a conditional expression has a constant expression as its first operand,
the front end may fold the expression so that the IL contains only the
selected operand in place of the conditional expression.  If that operand
involves an implicit call to a conversion function to bring the type of the
operand to the result type of the expression, the C++-generating back end
omitted the call and thus, because of the suppression of the conditional
expression, generated incorrect code.  This has now been fixed by generating
the implicit call to the conversion function as an explicit cast.  For
example:

  struct A {
    A();
    operator int();
  } a;
  void f(int);
  void f(A);
  int main() {
    f(1 ? a : 0);  // Previously generated as f(a), which selected the
                   // wrong overload.  Now generated as f((int)a).
  }


5/7/10   [EDGcpfe/10682]
GNU C++ compatibility: Visibility of parameters

GNU C++ compilers prior to version 4.4 keep parameters invisible until the
associated function declarator is completed (see Changes entry of 9/1/05).
In later versions, however, g++ only keeps the parameters invisible while
parsing default arguments.  We now emulate that behavior when
gnu_version >= 40400.  For example:

  struct S;
  void f1(S *S, S *T);   // Accepted in GNU C++ mode with gnu_version < 40400.
  int x();
  void f2(int x = x());  // Accepted in all GNU C++ modes.


5/5/10   [EDGcpfe/10645]
Templates rejected on non-dependent parameters before deduction

In overload resolution, function templates are now rejected before deduction
is done if it can be shown that any of the non-dependent parameters cannot
match.  If all those parameters are okay, deduction is then done and the
remaining parameters are checked.  This can speed up overload resolution,
and in some cases avoids errors caused by instantiations needed to develop
the function type.  For example:

  template <class T> struct Z {
    typedef T::x xx;
  };
  template <class T> Z<T>::xx f(void *, T);
  template <class T> void f(int, T);
  struct A {} a;
  int main() {
    f(1, a);  // Okay now.  Formerly provoked an error on the instantiation
              // of the Z<T> in the return type, with T=A.  Now the first f
              // is ruled out on the basis of the first parameter without
              // doing deduction and producing the routine type.
  }

The C++ standard does not mandate a particular behavior here; it allows
but does not require such instantiations.  However, test cases like the
above are accepted by recent versions of g++, and it seems reasonable to
do so.


5/4/10   [EDGcpfe/10653]
Microsoft mode: old-style cast forming pointer-to-member of overloaded function

The Microsoft compiler allows an old-style cast applied to a pointer-to-member
for an overloaded function to select a function from the overload set even
if the classes of the pointer-to-members are not related (the member types
must still be identical).  The effect is like a reinterpret_cast applied
to the pointer to member for the selected function.

  struct B {
    void foo(short*);
    void foo(int*);
  };
  struct C {};
  int main() {
    (void (C::*)(short *))&B::foo;
  }


5/4/10   [EDGcpfe/10659]
Nonreal types based on template parameters no longer shared

Formerly, nonreal types based on template parameters were shared (i.e.,
in the example below A<T> and A<U> would refer to the same type because
they are both A<template-parameter#1>).  Such types are no longer shared.

  template <class T> struct A {};
  template <class T> void f(A<T>){}
  template <class U> void g(A<U>){}


5/3/10   [EDGcpfe/10666]
Abort when a local pragma refers to a local class or local static variable

The front end sometimes aborted with an "IL entry write-read difference" when
dealing with a translation unit containing a function whose body is eliminated
but which contains a pragma referring to a local class or local static
variable.  For example:

  inline void g() {
  #pragma test_next_decl
    struct S {};
  }

For this to occur, the following configuration macros all had to be TRUE:
SCOPE_ORPHANED_LIST_PROCESSING_NEEDED, MAINTAIN_NEEDED_FLAGS,
GENERATE_SOURCE_SEQUENCE_LISTS, and IL_SHOULD_BE_WRITTEN_TO_FILE.
This is now fixed.

5/2/10   [EDGcpfe/10666]
Abort in find_parent_var_of_anon_union_type

The front end aborted in find_parent_var_of_anon_union_type with
the message "var not found" in some obscure cases.  The most common
cause is a side effect of setting EXPENSIVE_CHECKING to TRUE and
compiling a function-local anonymous union that contains a nested
type definition.  Now fixed.

  typedef class A q;
  struct B {
     B(q *);
  };
  struct C {
    inline int f(void);
  };
  int C::f(void) {
    union {
      struct {
        unsigned x;
      } y;
    };
   return 0;
  }
  B::B(q *) {}


4/30/10  [EDGcpfe/10642]
Performance improvement in finding class template instantiations

A hash table is now used to look for a previously created instantiation
of a class.  This improves the performance when there are a large number
of instantiations of a given class template.


4/30/10  [EDGcpfe/10651]
const variable accepted in constant expressions in GNU C mode

gcc, when run with -O1 or higher, accepts const variables in constant
expressions, presumably because value propagation done in optimization
replaces the variables by their constant values.  It's kind of
inconsistent about where and how it allows this.  For example:

  const int i = 2;
  void f(int x) {
    switch (x) {
      case i:      // Error from gcc (now accepted by EDG)
      case i + 3:; // Okay from gcc (now accepted by EDG)
    }
  }

The front end now accepts all uses of initialized integral const variables
in constant expressions in gcc mode, with a warning.  That's more cases
than gcc allows, but we found it hard to try to limit our emulation to
just what gcc accepts.


4/30/10  [EDGcpfe/10655]
GNU C compatibility: __builtin_pow and constant-expressions

In GNU C modes with gnu_version >= 30400, the front end now accepts certain
calls to __builtin_pow in constant-expression contexts.  Specifically, the
call is folded to a constant if both arguments are constants and the second
argument (the power) has a small nonnegative integer value.  For example:

  int x[(int)__builtin_pow(7.1, 2.0)];  // Now accepted in GNU C mode because
                                        // 2.0 is a small integer value.
                                        // Same as "int x[50];".

Calls to __builtin_powf and __builtin_powl are treated similarly.  The exact
subset of calls that are folded by the front end differs somewhat from GCC's
but calls that occur in constant-expressions in actual code are likely to be
foldable by the front end.


4/29/10  [EDGcpfe/10353,EDGcpfe/10664]
GNU C++ mode compound literals outside of functions now static

In g++ mode, compound literals written outside of functions are now
considered static.  Formerly, they had lifetime that ended at the
end of the full expression.

  int *x = (int[]){100,200};  // Now works at file scope


4/28/10  [EDGcpfe/8984]
GNU compatibility: common/nocommon variables

In GNU C mode, the front end already accepted the "nocommon" attribute: The
intent of the attribute is to indicate that a "tentatively defined" variable
should not be placed in "common" storage (implying that it is treated like an
ordinary definition: duplicate tentative definitions should then result in
linker errors).

A new command-line option "--default_nocommon_tentative_definitions" now
indicates that all tentative definitions should be treated by default as if
they were declared with the "nocommon" attribute (this matches the GCC option
"-fno-common").  The front end now also accepts the GNU "common" attribute to
override the behavior implied by this new command-line option for a specific
variable.  For example:

  __attribute((common)) int x;  /* Tentative definition is always placed in
                                   "common" storage -- even if the option
                                   --default_nocommon_tentative_definitions
                                   is specified. */

The command-line option "--default_common_tentative_definitions" (matching
GCC's "-fcommon") is also accepted.  Its only effect is to cancel out a prior
occurrence of "--default_nocommon_tentative_definitions".

Finally, the "common" and "nocommon" attributes are now accepted in GNU C++
mode (even though they presumably have no effect in that mode since C++ has no
notion of "tentatively defined" variables).  This matches the behavior of GCC
(and makes it easier to use the attributes in code that may be compiled both
as C and C++).

Note: The new is_common flag in a_variable, like the existing is_not_common
flag, only reflects the presence of the corresponding GNU attribute.  Back
ends are responsible for determining the appropriate storage for various
variables.  For example, it appears that GCC will avoid placing a tentatively
defined variable in "common" storage if that variable is declared with the
"section" attribute; such a variable will not have its is_not_common flag set
to TRUE if it was not declared with the "nocommon" attribute.  Similarly, a
variable definition with an initializer can include the "nocommon" attribute
(and hence have its is_common flag set to TRUE), but it should not be placed
in "common" storage.


4/28/10  [EDGcpfe/10649]
C++-generating back end: incorrect qualified names with MANGLE_ALL_NAMES

In configurations in which names in the IL are mangled, such as with
MANGLE_ALL_NAMES set to TRUE, the C++-generating back end sometimes
generated names that should have been unqualified as qualified names using
an undeclared temporary name ("__Txxxxxxxx" notation) as the qualifier.
This is now fixed.  For example, in a MANGLE_ALL_NAMES configuration in
which function template definitions are generated from the prototype
instantiation, the following call to A<T>::f() was incorrectly generated:

  template<typename T> struct A {
    void f();
  };
  template<typename T> struct B {
    A<T>* g();
  };
  template<typename T> void h(B<T> b) {
    b.g()->f();  // Previously generated as (b.B<T>::g())->__T22750416::f()
  }


4/27/10  [EDGcpfe/10648]
Abort in some decltype/typeof cases involving multiple translation units

When simultaneously compiling multiple translation units, the front end
sometimes aborted with an assertion failure "correspondence busy" in
f_set_no_trans_unit_corresp (trans_corresp.c).  This occurred in relatively
complex situations involving typedefs whose underlying type was expressed
using a decltype (or typeof) construct, and only after a correspondence error
was already issued.  This is now fixed.


4/26/10  [EDGcpfe/9169]
C++0X SFINAE implementation

The C++0X standard introduced some new rules for template deduction
(see WG21 paper N2634).  When a function template is considered in
overload resolution, part of the process is "template argument
deduction," which is an attempt to find values for the template
parameters of that template that will specify a template instance that
is a viable function for the call.  The deduction rules require that
any expressions that appear in the template type be valid after
substitution of the deduced template arguments for the template
parameters.  Whereas in older versions of the standard "valid" was
underspecified, and was widely interpreted as a restriction to only
certain kinds of simple expressions, the C++0X rules now allow
arbitrarily complex expressions inside unevaluated contexts (e.g.,
sizeof and decltype), and "valid" is defined by the normal semantic
rules of the language, except that access checking is not done (but
see below).  So, for example:

  template <class T> auto f(T p1, T p2) -> decltype(p1 + p2) {
    return p1 + p2;
  };
  struct A {
    const A & operator +(const A&);
  };
  A a1, a2;
  int main() {
    f(a1, a2);
  }

Here, the call is valid only if the expression "p1+p2" is valid, which
is true only if there is a valid meaning for the "+" operator,
possibly found by doing overload resolution as in this case.  Any error
detected during this process should cause only a failure of deduction
for that template, and not a hard error.  (This idea is summarized in
the acronym that is often used to refer to this non-error-producing
deduction process, SFINAE, which stands for Substitution Failure Is
Not An Error.)

This is now implemented in the front end.  The new-style SFINAE is
enabled by default in C++0X mode, and can be enabled manually via
--c++0x_sfinae.  DEFAULT_CPP0X_SFINAE_ENABLED can be used to enable
it by default in non-C++0x mode, but it will still be disabled by
default in some versions of Microsoft and GNU modes (because those
compilers didn't yet do SFINAE according to the new rules in those
versions).

Note that this involved a rather large set of changes in the
expression-processing routines (expr.c, exprutil.c, and overload.c),
and an added set of coding rules in those routines (for example,
the normal error-reporting routines cannot be called directly,
because errors must be trapped in deduction contexts).  Customer
additions in those files may have to be reworked to follow the
new conventions.  See the section titled "Rescanning Expressions"
in the internal documentation for details.

N2634 says that access checking is not done during SFINAE processing,
but the standards committee, at its Rapperswil meeting (August 2010),
seems to be leaning in the direction of eliminating that special
case, so access errors would be treated like any other errors
during template deduction.  Accordingly, we have implemented that.
However, both behaviors will remain available; see the
DEFAULT_CPP0X_SFINAE_IGNORE_ACCESS macro, and the
--c++0x_sfinae_ignore_access and --no_c++0x_sfinae_ignore_access
command-line options.


4/23/10 [EDGcpfe/7875]
Use one-step thunk when possible in IA-64 ABI

When a virtual function in a virtual base class is overridden, the IA-64
ABI specifies that a thunk must be generated that adjusts the "this" pointer
in two steps, first to the beginning of the virtual base class subobject and
then, using the function's vcall offset, to the subobject of the overriding
function's class.  In cases where an existing one-step thunk with the correct
adjustment already exists, the front end now uses that one-step thunk rather
than a two-step thunk.  This behavior now more closely emulates g++'s
behavior in this area.  In this example, two-step thunks had been used in the
vtable entries for the C-in-D destructors, but one-step thunks are now used:

  struct A { virtual ~A(); };
  struct B : A {};
  struct C : virtual A {};
  struct D : B, C {};
  D d;


4/22/10 [EDGcpfe/10573]
Microsoft compatibility: specialization of base class member from derived class

The Microsoft compiler allows an explicit specialization of a template from
a base class to be defined in a derived class.  This is only allowed when
the base class and derived classes are both instances of the same template
(e.g., a one or both are partial or full specializations).  We now emulate
this behavior in Microsoft mode.  This feature is needed for certain
versions of the Boost typeof library for the Microsoft compiler. 

  template <class T> struct A {
    template <class U> struct B;
  };
  template <class T> struct A<T*> : public A<T> {
    template <> struct B<int> {};
  };
  A<int*>::B<int> ab;


4/22/10 [EDGcpfe/10643]
Missing diagnostic when the "auto" type specifier follows another type name

In C++0x mode, the front end failed to issue a diagnostic when the "auto" type
specifier follows another type specifier.  For example:

  double auto x = 3.0;  // Previously treated like "double x = 3.0;".
                        // Now an error.

Now such cases trigger an error.


4/22/10 [EDGcpfe/9266]
Option to disable nonstandard GNU keywords

A new command-line option "--no_nonstd_gnu_keywords" has been added to the
front end.  In non-GNU modes, the option has no effect.   In GNU modes the
option disables GNU-specific keywords that do not start with underscores
(notably: typeof).  The converse option "--nonstd_gnu_keywords" is available
in GNU modes only and enables those GNU-specific keywords if the were disabled
by a prior occurrence of the "--no_nonstd_gnu_keywords" option.


4/20/10 [EDGcpfe/10574]
Microsoft compatibility: incorrect disambiguation with multiple type keywords

In Microsoft mode, disambiguation must handle nonstandard casts containing
multiple keywords (such as "unsigned int(5)").  A problem in the way such
cases were handled caused disambiguation to be attempted in cases in which
it was not needed and to sometimes produce an incorrect result.  Now fixed.

  struct A {
    template <int I, int J> unsigned long f();
  };
  int main() {
    A a;
    unsigned long l = a.f<1, 2>();
  };


4/20/10 [EDGcpfe/10206]
Rename routines and fields associated with covariant return types

Routines and fields whose name had contained "covariant_return_type" have been
renamed (replacing "covariant_return_type" with "wrapper" in most cases).
The renaming reflects the fact that these routines/fields are also used to
create thunks (which adjust the "this" pointer) in the IA-64 ABI, and not just
the wrapper routines that are necessary to do covariant return type adjustment.
Customers whose code makes use of the
overriding_function_for_covariant_return_type and/or
overridden_function_for_covariant_return_type fields in a_routine will need to
change their code to use overriding_function_for_wrapper and
overridden_function_for_wrapper, respectively.  Although nothing functionally
has changed, this still represents an IL CHANGE.


4/20/10 [EDGcpfe/10531]
GNU compatibility: Attribute "aligned" on cast types

In GNU modes, the front end now applies the "aligned" attribute when it
appears on a cast type.  For example:

  int main() {
    return __alignof((int __attribute((aligned(16))))x);
  }      // Returns 16.

Previously, such attributes were ignored with a warning.


4/19/10 [EDGcpfe/10539]
Eliminate use of a virtual thunk in some cases in the IA-64 ABI

When populating virtual function tables in the IA-64 ABI, lowering attempts to
avoid the use of thunks when possible.  Lowering now checks for the case where
the offset required is zero in the complete object, and suppresses the use
of a virtual thunk in this case.  This provides more optimal run-time
performance and is closer to g++'s behavior.  In the example below, the
construction vtable for the D-in-A subobject had referred to virtual thunks for
invoking (complete and subobject) D::~D and now refers directly to (complete
and subobject) D::~D:

  struct B {
    virtual void f();
    virtual ~B() {}
  };
  struct D: virtual B {
    virtual ~D() {}
  };
  struct A: virtual D {
    virtual void g();
  };
  void A::g() {}


4/19/10 [EDGcpfe/10639]
GNU and Microsoft compatibility: Fields with incomplete types

In Microsoft and some GNU modes (those with gnu_version < 30400), the front
end previously accepted fields (i.e., data members) with incomplete types in
templates.  Now, it also accepts arrays of incomplete types under those
circumstances.  For example:

  struct I;
  template<class T> struct S {
    I i[3];  // Now accepted in Microsoft mode (and in GNU mode when
  };         // gnu_version < 30400).


4/16/10 [EDGcpfe/10623]
Incorrect lvalueness on backing expression for "?" operation on string literals

The front end produced an incorrect backing expression for a constant
that results from the folding of a "?" operator to a constant.  The
expression should have been marked as an lvalue and wasn't.  The
failure cases were ones where the first operand is constant and the
second and third operands are string literals with the same length.
Now fixed: the "?" operator is not folded, following the general rule
that operators with lvalue results are not folded to constants.  The
problem was visible in versions that use the backing expressions,
e.g., C++-generating back ends versions aborted with an internal
error ("is_lvalue incorrectly set"), whereas versions that use IL
lowering would generally not have seen this problem.

  const char* test(void) {
    return 1 ? "" : "";
  }

4/15/10 [EDGcpfe/10633]
Abort on destructor call using ambiguous name

An abort could occur (in f_is_generalized_identifier_start) if a destructor
call used an ambiguous name after the tilde.  Now fixed.

  namespace A {
    int A;
  }
  using namespace A; 
  int main() {
    int* p = 0;
    p->A::~A( );
  }


4/14/10 [EDGcpfe/10599]
Abort on invalid "auto" variable redeclaration first declared with class type

In C++0x mode, first declaring a variable with a class type and then
redeclaring it with an "auto" type specifier that is deduced to a non-class
type previously resulted in an abort (the exact nature of the abort depends on
the specific case).  For example:

  extern struct S {} x;
  auto x = 42;  // Previously resulted in an abort (after issuing an
                // appropriate error message).

This is now fixed.


4/8/10  [EDGcpfe/8404,EDGcpfe/10541]
C++0x: Alias and alias template declarations

Alias declarations and alias template declarations are now supported in
C++0x mode.  As part of this change the type entries for tk_typeref types
now have a supplement (a_typeref_type_supplement -- IL CHANGE).  The expr
field previously in the a_type entry has been moved to the supplement.

  using X = int;
  X x;  // equivalent to "int x"
  template <typename T> using Y = T*;
  Y<int> yi;  // equivalent to "int* yi"


4/8/10  [EDGcpfe/10595]
Internal error during mangling done by instantiation wrapup

In certain error cases, an internal error (in various places) could occur
during the name mangling that is done as part of instantiation wrapup.
This name mangling is now suppressed if any errors have been issued.  Note
that the example below requires a mode in which local types can be used as
template arguments (e.g., C++0x mode).

  template < class T > int h ( T ) {return 0; }
  template < class T > int f ( T ) { 
    struct _A1_<int> { 
      int x(int) { return 1 ; } 
      int g () { return h(x); } 
    }; 
  } 
  int main () { 
    f(1);
  }


4/8/10  [EDGcpfe/10359]
Internal error in full_specialization on invalid specialization

An internal error (in full_specialization) could occur on certain invalid
explicit specializations.  Now fixed.

  struct A { 
    template <class T> void operator delete(void*, T) {}
    template <> void operator delete<float>(void*, float);
  };


4/5/10  [EDGcpfe/10580]
Spurious redeclaration error on block-extern variables in templates

In C++ modes that perform prototype instantiations of function templates (such
as strict mode and GNU C++ mode with gnu_version >= 30400), instantiating a
function template containing a block-extern variable declaration with a
template dependent type resulted in a spurious error when the function
template was instantiated.  For example:

  template<typename T> void g(T) {
    extern T x[2];  // Block-extern declaration of variable x.  When g is
  }                 // instantiated, a spurious error was sometimes reported.
  template void g(double);

This is now fixed.


4/5/10  [EDGcpfe/10581]
C++-generating back end: repeated "mutable" specifier

When a class member declaration declares more than one field and includes the
"mutable" specifier, the C++-generating back end incorrectly repeated the
"mutable" specifier for each field in the list.  This is now fixed.  For
example:

  struct S {
    mutable int i, j;  // Previously generated as "mutable int i, mutable j;"
  };


4/2/10  [EDGcpfe/10575]
Microsoft compatibility: Functions depending on types with no linkage

C++0x allows function with external linkage to depend on types with no linkage
provided the function is defined in the translation unit where the types are
defined: This was implemented in version 4.1 (see Changes entry for
EDGcpfe/9627 of 3/17/09).  Prior to version 4.1, the same rule applied in
Microsoft modes with microsoft_version >= 1400, but without the requirement
that the function be defined in the same translation unit.  The implementation
of the C++0x rule accidentally imposed that constraint in Microsoft modes
(which is a regression).  That is now fixed: The definition is no longer
required in Microsoft modes (a warning is issued since a missing definition is
likely to result in a linker error later on).  For example:

  typedef struct {} *T;
  void g(T);            // Missing definition of "g" no longer triggers an
  void f(T x) { g(x); } // error in Microsoft modes.


4/2/10  [EDGcpfe/10565]
C++-generating back end: multi-declarator friend declarations

For a friend declaration declaring more than one function, the C++-generating
back end erroneously repeated the "friend" keyword for each declarator.  This
is now fixed.  For example:

  class C {
    friend int f(), g();  // Previously generated "friend int f(), friend g();"
  }


4/1/10  [EDGcpfe/10147]
Assertion failure in set_primary_ctor_or_dtor_kind

Prior to version 4.0, a constructor of an unnamed local class had been given a
mangled name; however, due to changes in 4.0, such constructors were not given
mangled names in configurations where local entities are not promoted to file
scope.  This caused an assertion failure on such cases (in
set_primary_ctor_or_dtor_kind in lower_init.c).  A change has been made to give
mangled names to constructors of local unnamed types in all cases.  This
failure occurs in IA-64 ABI configurations where
PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE is FALSE.  This regression was introduced
in version 4.0 and is now fixed.  For example:

  void f() {
    struct {
      struct A {
        A() {}
      } a;
    } x;
  }


3/26/10  [EDGcpfe/9976]
C++0x: Attributes "override", "hiding", and "base_check"

In C++0x mode, the front end now supports the standard attributes "override",
"hiding", and "base_check".  Attribute "override" indicates that a virtual
function overrides a matching function in a base class.  "hiding" indicates
that a derived-class member hides a base class member.  "base_check" can
appear on a class definition, and causes the front end to issue errors if
overriding virtual functions are not marked with [[override]] or hiding
members are not marked with [[hiding]].  For example:

  struct B { virtual void f(), f(int); };
  struct[[base_check]] D: B {
    [[override]] virtual void f();      // Okay.
    [[override]] virtual void f(char);  // Error: No overridden f(char) in B.
    virtual void f(int);                // Error: Missing [[override]].
  };


3/26/10  [EDGcpfe/10558]
Microsoft compatibility: spurious error on empty __if_exists

A spurious error would occur if there were no tokens inside an __if_exists
or __if_not_exists in which the test was true.  The error would also occur when
the directive was not literally empty but when there were no effective
tokens as a result of a nested __if_exists or __if_not_exists that produced
no tokens (because its test was false).  Now fixed.

  struct A {
    enum {e1};
    // Both of these cases resulted in errors
    __if_exists(e1) { }
    typedef int type;
    __if_exists(e1) { __if_not_exists(type) { typedef int type; }}
  };


3/24/10  [EDGcpfe/10550]
Internal error on nonstandard friend declaration in Sun mode class template

While parsing templates in Sun mode, the front end accepts certain nonstandard
references to undefined templates.  Version 4.1 introduced an internal error
("ensure_il_scope_exists: NULL IL scope" in il.c) triggered when such a
nonstandard reference appeared in a friend class declaration.  For example:

  template<class T> struct S {
    friend class C<T>;  // Previously triggered an internal error in Sun
  };                    // mode.

This is now fixed.

(A similar abort could also occur in GNU C++ mode, but in GNU C++ mode such
cases have now become invalid (see Changes entry for EDGcpfe/10554 below).)


3/23/10  [EDGcpfe/10554]
GNU C++ compatibility: limiting use of undefined template

Certain versions of g++ allow the use of an undefined function template in
the definition of a class template (i.e., case #1 below).  The change made
to allow that usage also permitted #2, which is not accepted by g++.  In
addition, newer versions of g++ (3.4 and beyond) no longer allow #1.  We now
reject #2 in all g++ modes and accept #1 only  when gnu_version is < 30400.

  template <class T> struct A {
    friend void f<>(A<T>); // #1
    friend class X<T>;  // #2
  };


3/23/10  [EDGcpfe/10551]
Diagnostic pragma information not saved in PCH files

The diagnostic severity information for diagnostic pragmas was not saved
in precompiled header files.  As a result, such pragmas would not take
effect in compilations making use of the precompiled header.  Now fixed.

  file: test.h:
  #pragma diag_suppress=declared_but_not_referenced
  int i;

  file: test.c:
  #include "test.h"
  int main() {
    int x;  // warning was issued on use of PCH
  }


3/23/10  [EDGcpfe/10546]
GNU C++ compatibility: local types in template argument deduction

Beginning with version 4.1, g++ treats the use of a local type as a template
argument as a deduction failure rather than selecting the function and
issuing an error as was done in earlier versions.  We now emulate this
behavior in g++ mode when gnu_version is >= 40100.

  template <class T> void f(T);  // #1
  void f(...);  // #2
  int main() {
    struct X {};
    X x;
    f(x);  // now calls #2
  }


3/22/10  [EDGcpfe/9924,EDGcpfe/10545]
GNU compatibility: Attribute "weakref" behavior

Previously, if a GNU attribute "weakref" (gnu_version >= 40100) referred to an
entity that was declared but not defined in the same translation unit, the
effect was as if the alias was a declaration with an "asm name" corresponding
to the aliased name.  Now, the attribute is handled normally (by pointing the
aliased_routine or aliased_variable field to the aliased entity).  
For example (assuming gnu_version >= 40200):

  void f();
  static void g() __attribute((weakref("f")));
    // Previously treated as "void g() __asm("f") __attribute((weakref));".


3/20/10  [EDGcpfe/10549]
Memory corruption after multi-line invocation of complex macros

If a macro invocation spans more than one line and the expansion of the
macro is large enough to result in reallocation of the macro buffer, the
front end sometimes wrote through a dangling pointer into the buffer's
previous location, scribbling on data structures subsequently allocated in
the newly-freed space.  This has now been fixed.


3/19/10  [EDGcpfe/10493]
GNU C compatibility: First-field constraints for transparent unions

In GNU C mode, a union whose first field has a floating-point type cannot be
transparent: The transparent_union attribute applied to such a union is
ignored with a warning.  Similarly, when gnu_version >= 40000, the first field
cannot be a bit field.  For example:

  union T {
    float f;
    int i;
  }  __attribute((transparent_union));  // The attribute is ignored with a
                                        // warning.


3/18/10  [EDGcpfe/9345,EDGcpfe/10330,EDGcpfe/10406]
Microsoft compatibility: Predeclaring ::type_info

In Microsoft mode the front end previously predeclared type_info in the global
namespace provided DEFAULT_TYPE_INFO_IN_NAMESPACE_STD was set to FALSE (if it
was set to TRUE, the type_info structure was invisible until a declaration was
seen in the source).  See the Changes entry of 12/7/05.  Now, a separate macro
MICROSOFT_MODE_TYPE_INFO_IN_NAMESPACE_STD is used to control this feature and
the DEFAULT_TYPE_INFO_IN_NAMESPACE_STD macro controls where the front end
places type_info in non-Microsoft modes.
MICROSOFT_MODE_TYPE_INFO_IN_NAMESPACE_STD is FALSE by default, which matches
Microsoft compilers and is almost always what is desired.  Front end
applications that want Microsoft-like behavior in general but must link with
a run-time support library that places type_info in namespace std can set the
macro to TRUE instead, but this is expected to be unusual (e.g., it is unlikely
to work when processing code that includes the standard Microsoft headers,
since those headers will declare type_info in the global namespace).

In addition, in Microsoft mode pragma_define_type_info_is_required is set to
FALSE if type_info is predeclared in the global namespace (which, as described
above, is now the common case).  This ensures that the type_info structure
appearing in Microsoft header files is handled correctly (i.e., no special
pragma is required on the header-file definition of type_info).


3/16/10  [EDGcpfe/10533]
Force definition of typeinfo for types in catch clauses

In configurations where DO_FULL_PORTABLE_EH_LOWERING is FALSE, the typeinfo
entries for types used in catch clauses may not be marked as needed in the IL.
A change has been made to force the definition of the effective typeinfo for
types used in catch clauses (in anticipation that the back end will need them).
There is no change in configurations where DO_FULL_PORTABLE_EH_LOWERING is
TRUE (the typeinfo continues to be emitted as needed by the constructs added
during lowering).  This example had not generated typeinfo for D, but now does:

  struct B { virtual ~B(); };
  struct D : B {};
  void f() {
    try {}
    catch (D &d) {}
  }


3/16/10  [EDGcpfe/10449]
Spurious error on qualified destructor name during prototype instantiation

A spurious error was issued on a dependent qualified destructor name
in modes in which nonclass prototype instantiations are done.  Now fixed.

  class A { };
  template< class X > void f(void *p) {
    typedef typename X::C * my_type;
    my_type my  = (my_type)p;
    (*my ).X::C::~C(); // spurious error here
    my->X::C::~C();    // ... and here
  }
  struct G { typedef A C; };
  void g(void *x) {
    f<G>(x);
  }


3/16/10  [EDGcpfe/10528]
Abort on extern "C" function when guiding declarations are enabled

An abort could occur (in find_or_create_master_instance) when an extern
"C" function is declared in more than one namespace, a later function
template is declared that matches the type of the extern "C" function,
and guiding declarations are enabled.  The abort occurred only if C and
C++ function types are not distinct.  Now fixed.

  extern "C" int func(int);
  namespace N {
    extern "C" int func(int x);
    template <class T> T func(T x) { }
  }


3/15/10  [EDGcpfe/10531]
GNU compatibility: Default alignment for __attribute((aligned))

In GNU modes, specifying __attribute((aligned)) (i.e., without an argument to
the "aligned" attribute) is equivalent to setting the alignment to a value
indicated by the configuration macro TARG_MAXIMUM_INTRINSIC_ALIGNMENT.
Previously, that macro was set to 8 by default, but it appears that recent
versions of GCC treat __attribute((aligned)) as __attribute((aligned(16)))
on many popular platforms.  The default value for the configuration macro
TARG_MAXIMUM_INTRINSIC_ALIGNMENT is therefore now set to 16.


3/15/10  [EDGcpfe/10526]
Spurious error on array initializer in template

In modes that perform prototype instantiations of function templates (such as
strict mode and some GNU C++ modes), the front end sometimes issued a spurious
error on an aggregate initializer for an array with a template-dependent
element type.  The diagnostic erroneously claimed too many initializer values
are present (when in fact the number of allowable initializer values is not
fixed since the underlying element type is a priori unknown).  For example:

  template<typename T> struct S {
    struct X;
    void f() {
      X x[2] = { 1, 2, 3 };  // Previously triggered a "too many initializer
    }                        // values" error.
  };

This is now fixed.


3/12/10  [EDGcpfe/10527]
GNU C++ mode: "this->x" is falsely considered dependent as a call argument

g++ falsely considers an expression like "this->x" in a template to 
be dependent even if the type of the member "x" is non-dependent.
Now, in g++ mode, we also consider that expression to be dependent
when it's an argument to a call (but not in all other cases).

  template <class T> class C;
  template <> struct C<int> {
    int m1;
    void foo(int);
  };
  template <class T> struct X : C<T> {
    int m2;
    virtual void f() {
      foo(this->m1);   // Okay
      foo(this->m2);   // Error according to standard; now accepted in
                       // g++ mode (because call is taken as dependent)
    }
  };
  X<int> x;


3/10/10  [EDGcpfe/10521]
GNU C++ mode: deduction of conversion function template returning reference

The template deduction for a conversion function template returning a
reference to a cv-qualified type has been adjusted to match g++ in
GNU C++ mode.  g++ appears to use the rules in [temp.deduct.conv] of the
standard before they were corrected by core issue 976.

  template<typename>
  struct C {
    C();
    template <class U> C(const C<U>&);
    template <class U> operator const C<U>&() const;
  };
  const C<const int> foo() {
    const C<int> obj;
    return obj;  // Should be ambiguous, now unambiguous in g++ mode
  }


3/5/10   [EDGcpfe/10011]
C-generating back end, GNU compatibility: inline weak functions

Beginning with version 4.4, gcc does not allow a routine to be marked as
both weak and inline.  Because the C-generating back end, when
gcc_is_generated_code_target is TRUE, uses weak symbols as a workaround for
the absence of support for COMDAT groups, this combination occurred for
inline functions that are assigned to a COMDAT group.  The C-generating
back end has now been modified to suppress the inline specifier for such
functions.  For example:

  struct S {
    void foo () { typedef S X; }  // Previously weak inline, now just weak
    void bar ();
  };
  void S::bar () { foo (); }


3/5/10   [EDGcpfe/10509]
Microsoft compatibility: use of template class instance in __if_exists

When an instance of a class template is named in a Microsoft __if_exists
or __if_not_exists directive, it should only be considered to exist if the
instance has been instantiated, is in the process of being instantiated,
or been explicitly specialized.  We now emulate the Microsoft behavior
correctly in Microsoft mode.  Formerly, such instances were always
considered to exist.  The example below now prints "Does not exist".

  #include <stdio.h>
  template <int N> struct A;
  template <typename T> struct B {
    __if_exists(A<1>) {
      static const bool val = true;
    }
    __if_not_exists(A<1>) {
      static const bool val = false;
    }
  };
  int main() {
    if (B<int>::val) {
      printf("Exists\n");
    } else {
      printf("Does not exist\n");
    }
  }


3/4/10   [EDGcpfe/10519]
"extern template" should be ignored for explicitly specialized entities

An "extern template" directive should have been ignored for entities that
were explicitly specialized, but was not.  Now fixed.  In the example
below, when using the IA-64 ABI, A<char>::f should have been emitted in
a COMDAT group, but was not.

  template<class T> class A {
    virtual void f();
  };
  template<> inline void A<char>::f() {}
  extern template class A<char>;


3/3/10   [EDGcpfe/10518]
Fix to setting of decltype_expr_not_parenthesized flag

The decltype_expr_not_parenthesized flag in a tk_typeref type, used
to indicate the presence of significant parentheses around the
expression in a decltype, was not set correctly in some cases.
Now, it is correctly set to to TRUE only when (a) no parentheses
surround the expression, and (b) that lack of parentheses is
significant, i.e., for id-expressions and member access operators.
So, something like "decltype(a.f(x))" will now have the flag
FALSE, because while it has no parentheses the parentheses are
not significant around a function call.


3/2/10   [EDGcpfe/10512]
enk_runtime_sizeof renamed enk_sizeof

IL CHANGE: The IL expression node kind enk_runtime_sizeof was originally
used exclusively for sizeof applied to variable-length arrays.  Since
then, however, it has been used in a lot of contexts for non-VLA
(i.e., non-runtime) sizeofs, for example in backing expressions for
constants, in prototype instantiations, and with the SIZEOF_TYPE_IS_UNKNOWN
feature.  Therefore, we have now renamed it enk_sizeof to reflect
its generality.  The enumerator enk_runtime_sizeof continues to be
defined (as equal to enk_sizeof), but customers will have to change code
that references the sizeof variant of an_expr_node, which has also been
renamed.  References like p->variant.runtime_sizeof.x must be changed to
p->variant.sizeof_info.x.


3/1/10   [EDGcpfe/10505]
Abort on template-dependent array size in local class of a function template

In configurations with IA64_ABI set to TRUE and C++ modes (like strict mode)
that parse templates in their generic form, the front end aborted in
num_array_elements (types.c) when a local class of a function template
contained a field with a template-dependent array bound.  For example:

  template <typename T> void f() {
    struct C { int x[59][sizeof(T)]; };
      // Previously aborted in num_array_elements (in strict mode).
  }

This is now fixed.


3/1/10   [EDGcpfe/10351]
GNU C++ compatibility: Template-dependent vector_size attribute

In GNU C++ mode, the element type for the GNU vector_size attribute can now
be template-dependent.  When gnu_version >= 40400, the vector size parameter
of the attribute can be dependent too.  For example:

  template<class T> void f() {
    __attribute((vector_size(16))) T x;  // Now accepted in GNU C++ mode.
    __attribute((vector_size(sizeof(T)))) int y;
             // Also accepted in GNU C++ mode when gnu_version >= 40400.
  }
  template void f<int>();

However, as is the case with current GCC compilers, such uses are currently
not supported in contexts requiring deduction and substitution.  E.g.:

  template<class T> void g(T __attribute((vector_size(16)))) {}
  template void g<float>(float __attribute((vector_size(16))));
    // Error: No matching template.


2/26/10  [EDGcpfe/10503]
Exception handling in C++0x mode

In C++0x mode, support for exception handling is now enabled by default.


2/24/10  [EDGcpfe/9095]
GNU compatibility: Attribute vector_size after a function or array declarator

In GNU modes with gnu_version >= 40000, the front end now applies a vector_size
attribute appearing after a function or array declarator to, respectively, the
return type or element type of that function or array.  For example:

  int f() __attribute((vector_size(16)));
    // Same as "int __attribute((vector_size(16))) f();


2/23/10  [EDGcpfe/9913]
Attributes on instantiations of member functions of class templates

Previously, an attribute appearing on an out-of-class definition of a member
function of a class template was silently ignored.  Now the attribute is
applied when instantiating the member definition.  For example:

  template<class T> struct S { void f(); };
  template<class T> __attribute((noinline)) void S<T>::f() {}
  template struct S<int>;  // Attribute noinline is applied to S<int>::f
                           // when S<int>::f is fully instantiated.


2/23/10  [EDGcpfe/10489]
Unneeded-entity removal keeps class definition for "->" vacuous destructor call

The removal of unneeded entities now recognizes that a vacuous destructor
call using the "->" form, where the left operand is a pointer to class,
requires that the definition of the underlying class be kept.  It was not
formerly, which caused the C++-generating back end to produce uncompilable
code for cases like:

  struct A { int i; } *p;
  int main() {
    p->~A();
  }

Vacuous destructor calls in the "." form did not have this problem.


2/19/10  [EDGcpfe/10439]
C-generating back end, GNU compatibility: placement of visibility attribute

The C-generating back end previously emitted function attributes, including
(in configurations in which GNU_VISIBILITY_ATTRIBUTE_ALLOWED is TRUE)
"visibility" attributes, immediately preceding the function name.  However,
the "visibility" attribute can apply both to functions and to types,
leading to ambiguity when the attribute followed the return type and
preceded the function name.  Prior to gcc version 4.0, gcc resolved this
ambiguity in favor of the function, but newer versions apply the attribute
to the return type.  To avoid this problem, the C-generating back end now
emits function attributes at the beginning of the declaration, where there
is no ambiguity.  For example, with

  struct __attribute__((visibility("default"))) S {
    void* f();
  };
  void* S::f() { return 0; }

the C-generating back end previously generated the function definition as

  void *__attribute__((visibility("default"))) _ZN1S1fEv(...

resulting in a warning when the generated code was compiled with recent
versions of gcc that the "visibility" attribute was ignored on non-class
types; now it generates

  __attribute__((visibility("default"))) void *_ZN1S1fEv(...


2/19/10  [EDGcpfe/10456]
Visibility of variable with parenthesized initializer

In some GNU and Microsoft modes, a variable declaration is invisible in its
own parenthesized initializer (see Changes entries of 12/12/02 and 7/27/01).
However, in those modes the front end previously also made prior declarations
of the same entity invisible, which does not match the behavior of the GNU
and Microsoft compilers.  For example:

  extern int x;
  int x((int)&x);  // Previously x in "&x" was not found in some GNU and
                   // Microsoft modes.

This is now fixed.


2/19/10  [EDGcpfe/10275]
C-generating back end, GNU compatibility: builtin functions with LOWER_COMPLEX

In C-generating back end configurations with GNU_COMPLEX_EXTENSIONS_ALLOWED
and LOWER_COMPLEX set to TRUE, use of a builtin function whose parameters
or return value are a complex type resulted in errors when compiling the
generated code, because the lowered complex type is different from the
type expected by gcc.  The C-generating back end has now been changed to
emit declarations for such builtin functions, overriding the builtin
declaration and avoiding the error.  For example:

  __complex__ double f(__complex__ double z) {
    return __builtin_csqrt(z);    // Previously an error in the generated code
  }


2/17/10  [EDGcpfe/10469]
Microsoft compatibility: class_rvalue.float_field is considered an lvalue

For some reason, MSVC considers a selection of a floating-point field out
of a class rvalue to be an lvalue sometimes.  We now emulate that in
Microsoft bugs mode.

  typedef float T;
  struct A {
    A(T);
    T x;
  };
  int main() {
    T *x;
    x = &(A(0.0f).x);  // Accepted by MSVC
  }


2/17/10  [EDGcpfe/10405]
typeid applied to *this in constructor or destructor now known at compile time

The result of applying the typeid operator to "*this" in a constructor
or destructor is now considered to be known at compile time, instead of
being a runtime type determination.

  #include <typeinfo>
  extern "C" int printf(const char *,...);
  struct C {
    C(std::type_info const& t) : type(t) {}
    virtual ~C() {}
    std::type_info const& type;
  };
  struct X : public C {
    X() : C(typeid(* this)) {}  // Works now; formerly aborted at runtime
  };
  int main() {
    X c;
    printf("%s\n",c.type.name());
  }

It is probable that [basic.life]p6 of the C++ standard makes the above
undefined behavior, but we have at least one example of a real program
doing this, and g++ seems to treat the type as statically known, so it
seems like the right thing for us to do as well.


2/17/10  [EDGcpfe/10459]
Assertion failure when inlining function with VLAs

In configurations where LOWER_VARIABLE_LENGTH_ARRAYS is FALSE and inlining
is enabled, an attempt to inline a function that contains a VLA will result
in an assertion failure ("find_vla_dimension: not found").  Functions
containing VLAs are no longer considered candidates for inlining (when
LOWER_VARIABLE_LENGTH_ARRAYS is FALSE); a remark is issued in this case.
For example (with --vla):

  inline int f(int i) {
    return sizeof (char[i]);
  }
  void g(int x) {
    f(x);
  }


2/16/10  [EDGcpfe/10349]
Infinite loop on designator into nonstandard anonymous union (GNU C mode)

In GNU C mode, a designated initializer for a member of a nonstandard
anonymous union (or struct) could previously result in an infinite loop.
For example:

  struct X {
    union {
      struct {
        int i;
      };
    };
  } x = {{{ .i = 1 }}};  // Previously caused the front end to "hang" in
                         // GNU C mode.

This is now fixed.


2/16/10  [EDGcpfe/10404]
GNU compatibility: __builtin_fpclassify

In GNU modes with gnu_version >= 40400 the front end now predeclares
__builtin_fpclassify and checks that calls to that function include six
arguments, the last of which is a real floating-point value.  For example:

  int g(double x) {
    return __builtin_fpclassify(1, 2, 3, 4, 5, x);
                 // Now accepted in GNU modes with gnu_version >= 40400.
  }

GNU's gcc compiler (but not g++) accepts calls to  __builtin_fpclassify in
constant-expression contexts, but it is currently not practical to emulate
that feature in the front end.


2/16/10  [EDGcpfe/10395]
Using-declarations and C-linkage functions in GNU C++ mode

In GNU C++ mode, the front end previously issued an error on the declaration
of an extern "C" function that was previously also declared (in the same
scope) through a using-declaration.  Now such cases are accepted when
gnu_version >= 30400.  For example:

  namespace N {
    extern "C" void f();
  }
  using N::f;
  extern "C" void f();  // Previously an error in all GNU C++ modes; now
                        // accepted when gnu_version >= 30400.

Note that it appears that some (but not all) builds of GNU C++ 3.4.x still
issue an error on the example above; we are not aware of any GNU C++ 4.x
version that issues such an error.  (Also, examples like these are valid C++
and therefore accepted in default and strict C++ modes.)


2/16/10  [EDGcpfe/10453]
GNU C compatibility: _Complex/__complex without type specifier

In GNU C mode (but not in GNU C++ mode), specifying _Complex or __complex
without a type specifier ("float" or "double") now has the same effect as
specifying "_Complex double".  Previously such situations were diagnosed with
an error.  For example:

  _Complex z = 1.0+2.0i;  // Now accepted in GNU C mode; same as
                          // "_Complex double z = 1.0+2.0i;"


2/12/10  [EDGcpfe/6708]
Floating-point literal allowed as template argument with MSVC >= 7.1

The MSVC compiler continues to allow floating-point constants as
template arguments (as long as they are eventually converted to
integral) even though floating non-type template parameters were
disallowed as of MSVC version 7.1.  We now do the same.

 template <long l> struct C {};
 typedef C<100.0> ctype; // Now allowed with microsoft_version >= 1310


2/11/10  [EDGcpfe/10237]
Local variable capture across several lambdas

The front end now accepts the extension to lambdas described in N2998,
i.e., that a lambda can reference a local variable of the enclosing
function even if the lambda is enclosed inside one or more other
lambdas.  The variable is implicitly captured by each of the
intervening lambdas, if necessary.  For example:

  int main() {
    int i  = 37;
    int j = [&]()->int{ return [&]()->int{ return i;}();}();
    if (j != 37) return 1;
  }


2/10/10  [EDGcpfe/10410]
Attributes on parameter declarations and their associated variables

Some parameter attributes affect the type of a parameter.  In some cases
involving such attributes, the type of the associated variable entry (in
function definitions) was not updated accordingly.  This happened most
commonly when the parameter type was expressed through a typedef for a
function or pointer to function type.  For example (in GNU modes):

  typedef void F();
  void f(F *p __attribute((stdcall))) {}
    // Previously, the type of the variable p did not reflect the modified
    // calling convention.

This is now fixed.


2/9/10   [EDGcpfe/10410]
c_gen_be, GNU: Function attributes missing in parameter declaration

The output of the C-generating back end contains generated declarations of
functions that are defined in the file, in addition to the definitions of
those functions.  If one of the parameters of a function is declared to be
a function pointer with GNU function attributes, those attributes were
omitted from the parameter declaration in the generated declaration of the
function.  This is now fixed.  For example, the generated declaration for
the following function did not contain the __stdcall__ attribute:

  void f(void (*p)() __attribute__((__stdcall__))) { }


2/9/10   [EDGcpfe/10399]
__thread keyword in template definitions

The __thread keyword (sometimes allowed in GNU and Sun modes) was not
handled properly by the disambiguation/prescan routines.  This could result
in spurious errors in the definitions of template class members outside of
their class.  Now fixed.

  template <class T> class A {
    static __thread int i;
  };
  template <class T> __thread int A<T>::i = 0;


2/8/10   [EDGcpfe/10403]
Abort on invalid specialization of class

An abort could occur (in default_argument_fixup_for_class) if an attempt was
made to specialize a class in a class scope and if an incorrect name was
used for the class.  Now fixed.  In the example below, the closing brace of
M was omitted (commented-out) causing the specialization of N<char> to look
like a specialization in the class scope of M.  In addition, the explicit
specialization of N<char> did not use the correct name of the template.

  namespace N {
    template <class charT> class M { // }; note commented-out closing brace
    template<> class N<char>  { // Was supposed to be M<char>
      N(int* i = 0);
    };
  }


2/8/10   [EDGcpfe/10356]
GNU attribute packed and bit fields

In GNU modes, bit fields are allowed to "straddle" byte boundaries when the
attribute "packed" is applied to the enclosing class type (see Changes entry of
10/11/05).  However, GCC compilers from version 4.1.0 through 4.3.x disabled
this behavior: We now emulate that for values of gnu_abi_version values in the
range 40100-40399 (in configurations where IA64_ABI is TRUE).  For example:

  struct __attribute__((packed)) S {
    char c1:6, c2:6, c3:6, c4:6;
  }  // sizeof(S) is 4 when gnu_abi_version is in the range 40100-40399;
     // otherwise, sizeof(S) is 3.

Also, in configurations with IA64_ABI set to TRUE "byte straddling" was
previously disabled (causing sizeof(S) to be 4 in the example above) when
gnu_abi_version < 30300 and emulate_gnu_abi_bugs is TRUE, but that special
case has been removed because testing with early GCC versions did not
reproduce the behavior.


2/2/10   [EDGcpfe/10285]
Performance improvement with heavy use of macros

In configurations in which FULLY_RESOLVED_MACRO_POSITIONS is FALSE, all
source positions of text occurring within a macro expansion reflect the
position of the outermost macro invocation.  The front end now takes
advantage of that fact to speed up the process of determining source
positions for program constructs.  Depending on how heavily the file being
compiled relies on macros, the performance improvement could range from
negligible to a few percent.


2/1/10   [EDGcpfe/10384]
End positions of case labels in Microsoft mode

In Microsoft mode, an incorrect end position was previously recorded for an
expression node associated with a case label constant (when the macro
EXTRA_SOURCE_POSITIONS_IN_IL is TRUE).  For example:

  void f(unsigned int i) {
    switch (i) {
      case 1:   // Previously the constant recorded for "1" pointed to an
        break;  // expression with the wrong end position.
    }
  }

This is now fixed.


1/29/10  [EDGcpfe/10376]
Interface to permit the lazy loading of class definitions

A mechanism has been added to provide a hook to do the lazy loading of
class definitions.  This mechanism is not actually used by the front end
at this point.  The mechanism causes get_definition_of_class to be
called when an incomplete type is used in a context in which a complete type
is should be provided if possible.  To use this mechanism a customer would
need to modify get_definition_of_class to construct a string containing
the class definition to be used.  This mechanism cannot be used to
do lazy loading of class templates or local classes.  The mechanism
is enabled by setting the GET_DEFINITION_OF_CLASS_NEEDED configuration
macro.


1/29/10  [EDGcpfe/10393]
Save mangled type encodings in Cfront ABI to increase performance

During the name mangling process for the Cfront ABI, mangled names of types
are used, when available, as a quick way to obtain a mangled encoding for the
type.  In many cases, types are not given mangled names, so this shortcut is
not available.  A change has been made to store a mangled encoding for a
type in the (newly renamed) unmangled_name_or_mangled_encoding field of its
a_source_correspondence.  This field can now contain the mangled encoding for
a type (only in the Cfront ABI); the field is used as a mangled encoding only
when name_has_been_mangled is FALSE (and continues to point to the unmangled
name otherwise).  Subsequent requests for a mangled encoding for the type
use the saved value.


1/28/10  [EDGcpfe/9019]
GNU attribute "visibility" and linkage

The front end now ignores the GNU "visibility" attribute (with a warning) when
it is applied to a function or variable that doesn't have external linkage.
For example:

  static int n __attribute((visibility("hidden")));
    // Previously silently accepted and the IL entry for n was marked as
    // having "hidden" visibility.  Now the attribute is ignored with a
    // warning.


1/28/10  [EDGcpfe/10375]
Thread locality and redeclarations

The front end was previously always silent when two declarations of the same
variable were encountered with different thread locality specifications (the
__thread keyword or the Microsoft __declspec(thread) specifier).  Now an error
is issued if the variable is first declared with no thread locality, and later
declared as being thread local.  In non-Microsoft modes, a (discretionary)
error is also issued when a variable first declared as thread local is later
declared without a thread locality specifier.  For example:

  extern int n;
  __thread int n;  // Now always an error.

(See also the Changes entries of 9/18/02 and 12/13/04.)


1/27/10  [EDGcpfe/10394]
Better name mangling performance in some configurations

In the final name mangling step, mangled names are examined to see if they
need to be compressed (Cfront ABI only) and/or truncated to fit within
the configured maximum mangled name length.  In configurations where
compression and truncation are disabled (see variables compress_mangled_names
and max_mangled_name_length and their corresponding configuration macros
DEFAULT_COMPRESS_MANGLED_NAMES and DEFAULT_MAX_MANGLED_NAME_LENGTH), the
final name mangling pass has been eliminated thereby increasing performance.


1/26/10  [EDGcpfe/10018,EDGcpfe/10345]
Microsoft compatibility: dllimport static data members are not instantiated

In Microsoft mode, the definitions of static data members of class templates
are no longer instantiated.  For example:

  template<typename> struct S {
    __declspec(dllimport) static int x;
  };
  template <typename T> int S<T>::x = S<T>::y;
  template int S<void>::x;  // Previously an error, because S<void>::y was
                            // not found during instantiation.  Now okay,
                            // since the definition of S<void>::x is not
                            // instantiated.


1/26/10  [EDGcpfe/10390]
Default value of TYPE_FOR_AN_FP_VALUE_PART was incorrect for 64-bit systems

The default value for TYPE_FOR_AN_FP_VALUE_PART ("unsigned long") caused
an incorrect configuration when used on 64-bit systems.  The default value has
been changed to "uint32_t" which will produce a 32-bit unsigned type on both
32-bit and 64-bit systems.


1/26/10  [EDGcpfe/10388]
Use of standard typedefs for selected integer types

The front end now includes the C99/C++0x header file stdint.h to provide
typedefs for integral types of specific sizes.  If the stdint.h header
is not available the front end provides definitions of the necessary
typedefs.  On Solaris, this is done by using the sys/int_types.h header.
In other environments this is done by providing our own typedefs.
The macro USE_STDINT_HEADER specifies whether or not the stdint.h header
should be included.  If the macro is not set, the basics.h header will
set it automatically in environments where the header is known to exist.
The macro USE_INT_TYPES_HEADER specifies whether or not the Solaris
sys/int_types.h header should be included.  If the macro is not set, the
basics.h header will set it automatically on Solaris.  The macro
SUPPRESS_DEFINITION_OF_STDINT_TYPES specifies that the default versions
of the types should not be provided even when USE_STDINT_HEADER and
USE_INT_TYPES_HEADER are both FALSE.  The default versions of the typedefs
that we provide should work on virtually all systems, but the types can
be customized, if needed, using configuration macros.  For example, the
int32_t type can be set to use a particular type using the macro
"#define EDG_INT32_T some_type".


1/26/10  [EDGcpfe/10381]
Abort in update_routine_declared_type with severe syntax errors

In some unusual cases involving function templates with severe syntax errors,
the front end aborted with an internal error in update_routine_declared_type
(declarator.c).  This is now fixed.


1/26/10  [EDGcpfe/10372]
New utility routine to return the number of elements in a vector type

A new routine num_vector_elements has been added that returns the number of
elements in a vector type.  The number of elements in a vector is determined by
dividing the size of the vector type by the size of the vector element.  In
many cases, vector types and array types are treated similarly, but there was
no direct way to determine the element count (arrays have the
array.variant.number_of_elements field as well as the num_array_elements
routine).  The new routine is available only in configurations where
GNU_VECTOR_TYPES_ALLOWED is TRUE.


1/25/10  [EDGcpfe/10369]
GNU C++ compatibility: lookup of name following "." or "->"

In an expression such as "a.X::y", the standard requires that X be looked up
in both the class of the left operand of the "." or "->" operator and in the
context of the expression, and that if it is found in both places the types
must match.  g++ (versions 3.3 and newer) always use the type from the
class of the left operand.  Formerly, we gave a warning and used the type from
the context of the expression.   In g++ mode with gnu_version >= 30300
we now use the class of the left operand.

  struct B { int y; };
  struct A : public B {
    typedef B X;
  };
  class X {};
  int main() {
    A a;
    return a.X::y;
  }


1/25/10  [EDGcpfe/10382]
Microsoft __declspec attributes

Microsoft __declspec attributes are now handled through the general attributes
framework (see entry of 12/3/09).  This has caused the wording of some
diagnostics to change (and in some cases, the severity of diagnostics has been
adjusted to match that of Microsoft compilers). 

IL CHANGE: Several Microsoft-specific "modifier flags" (e.g., DM_NOTHROW) that
had a bit field counterpart (e.g., never_throws) for equivalent GNU attributes
have been removed and the corresponding bit field is now used instead.


1/23/10  [EDGcpfe/10363]
Function template named "main" should only be diagnosed in the global scope

The front end issued an error on any declaration of a function template
named "main".  Such an error should only be issued if the template is
being declared in the global scope.  Now fixed.

  namespace N {
    template<class T> int main(int argc, char **argv) { return 0; }
  }


1/23/10  [EDGcpfe/10380]
Abort on invalid specialization of enclosing class

An abort could occur (in default_argument_fixup_for_class) if an attempt was
made to specialize a class within its own scope (this situation could
inadvertently arise from a missing closing brace on the original class
definition).  Now fixed.

  template <class T> class Foo {
    template <> class Foo<char>  {
      public: Foo(int* i = 0);
    };
  };


1/21/10  [EDGcpfe/10357]
Locale set too late for multibyte operations in command-line processing

When LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED is defined and
MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is TRUE, the front end uses the specified
locale for multibyte character conversions.  The setting of the locale was
not done until after the command-line had been processed.  As a result, any
multibyte operations done while processing the command-line could produce
incorrect results.  The locale is now set before the command-line is
processed if the new macro ALWAYS_SET_MULTIBYTE_LOCALE is TRUE.  The
value of DEFAULT_MULTIBYTE_CHARS_IN_SOURCE_ENABLED is used as the default
value of ALWAYS_SET_MULTIBYTE_LOCALE.  When ALWAYS_SET_MULTIBYTE_LOCALE
is FALSE, the locale is now set when the --multibyte_chars option is
encountered on the command-line.

A similar issue existed with NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE
on Windows.  See the 9/3/09 entry for more information.


1/20/10  [EDGcpfe/10374,EDGcpfe/10377]
Abort when mangling unnamed namespace types

The mangling of certain entities relies on the creation of a unique "module id"
for each translation unit (to avoid collisions with similarly named entities in
other translation units).  When possible, a variable or routine with an
external definition is used as a portion of the module id, creating (along with
the name of the file) a unique and repeatable string.  When such a variable or
routine definition is not available, a module id that is repeatable but may not
be unique (in limited cases) is generated and used.  A change has been made to
allow such non-unique module ids to be used when required by name mangling.

The following example illustrates a regression introduced in 4.1 that had
caused an assertion failure in lower_name.c (module_id_for_source_corresp):

  struct B {
    virtual void f();
  };
  template<typename T> struct D : B {};
  namespace {
    struct S {};
  }
  struct A : D<S> {
    void f() {}
  };


1/20/10  [EDGcpfe/10198]
Abort on invalid member template definition with prototype instantiations in IL

An abort could occur (in get_scope_for_list) on an invalid definition of
a member template (when the enclosing class of the definition is incomplete)
when PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE.  Now fixed.

  template <typename T> struct O {
    struct I;
  };
  template <typename T> struct O<T>::I::S {};


1/19/10  [EDGcpfe/8363,EDGcpfe/8785,EDGcpfe/8829,EDGcpfe/8977,EDGcpfe/9429
          EDGcpfe/9810,EDGcpfe/9997]
Microsoft compatibility: Source annotation attributes

Microsoft source annotation attributes are now accepted in Microsoft mode.
The attributes that have been added are SA_FormatString, SA_InvalidCheck,
SA_Post, SA_Pre, SA_PostRange, SA_PreRange, SA_PostBound, SA_PreBound,
SA_Success, and source_annotation_attribute.  In addition, each of the
attributes without the SA_ prefix is also accepted in C++ mode.  A target
specifier that precedes an attribute (e.g., the "returnvalue" in the example
below) is also accepted now.  We do not currently do any validation of the
target specifiers or the arguments of the source annotation attributes.  The
Microsoft compiler requires that the SourceAnnotations.h header be included
for these attributes to be used.  We do not currently require that header
to be included.

[returnvalue:SA_Post(MustCheck=SA_Yes)] int f([SA_Pre(Null=SA_No)] int *x);


1/18/10  [EDGcpfe/8082]
Remark when comparing signed and unsigned operands

When a signed value is converted to an unsigned type, a small negative
value becomes a large positive value, which can produce surprising results
in a comparison operation.  The front end now issues a remark when such
conversions are applied to non-constant operands in relational expressions
(there is already a separate warning if a negative constant value is
converted to an unsigned type, so the remark is not issued for constant
operands).  For example:

  bool f(int i, unsigned u) {
    return i > u;    // Now gives a remark
  }


1/12/10  [EDGcpfe/10364]
Abort in mangled_type_name_full when mangling unnamed nested type in a
class template

In configurations where PROTOTYPE_INSTANTIATIONS_IN_IL and MANGLE_ALL_NAMES
are both TRUE, the mangling of an unnamed type in a class template
could cause an assertion failure (in mangled_type_name_full) when the IA-64
ABI is used.  This occurs only in certain circumstances, for example when
the class template is a namespace member.  For example:

  namespace N {
    template <typename T> struct A {
      struct {} s;
    };
  }


1/8/10   [EDGcpfe/10358]
Use of preprocessing immediate pragmas in pragma operators

Formerly, preprocessing immediate pragmas could not be used in _Pragma
operators (including the Microsoft __pragma operator in Microsoft mode).
Most such pragmas may now be used in pragma operators.  Only the hdrstop
and no_pch pragmas still require the #pragma syntax to be used.

  _Pragma("once")  // now allowed


1/7/10   [EDGcpfe/10132]
Mangling of _Complex types in the IA-64 ABI

Previously, substitutions were not allocated when mangling _Complex types,
causing some IA-64 mangled names to be incorrect.  This has now been fixed.
The old behavior is retained when ABI_COMPATIBILITY_VERSION < 402.  In the
example below, f<T> had been mangled as _Z1fICdET_S0_ and is now mangled as
_Z1fICdET_S1_:

  template <class T> T f(T) {}
  void f() {
    _Complex double c;
    f(c);
  }


1/7/10   [EDGcpfe/9504]
GNU: values assigned to multi-dimensional arrays when using range extended
designator initializers

The initialization of a multi-dimensional array with range extended designators
had produced a different set of values than GNU in cases where the extended
designators did not fully specify all dimensions of the aggregate and the
initializers specified by the extended designator were not brace enclosed.
This is a tweak to the change of 1/25/07.  For example:

  extern int printf(const char *,...);
  int s[2][2][2] = { [0 ... 1][0] = 1, 2, 3, 4 };
  int main() {
    int i, j;
    for (i=0; i<2; i++)
      for (j=0; j<2; j++)
        printf("s[%d][%d] [0] = %d [1] = %d\n", i, j, s[i][j][0], s[i][j][1]);
    return 0;
  }

The above example had produced:

  s[0][0] [0] = 1 [1] = 2
  s[0][1] [0] = 0 [1] = 0
  s[1][0] [0] = 1 [1] = 2
  s[1][1] [0] = 3 [1] = 4

and now matches GNU's output (note the value of s[0][0][1]):

  s[0][0] [0] = 1 [1] = 0
  s[0][1] [0] = 0 [1] = 0
  s[1][0] [0] = 1 [1] = 2
  s[1][1] [0] = 3 [1] = 4


1/6/10   [EDGcpfe/10354]
IL display of GNU assigned goto statement entries

The IL display utility failed to display the expression operand of a GNU
assigned goto (stmk_assigned_goto) statement.  This is now fixed.


1/6/10   [EDGcpfe/9965]
Microsoft compatibility: include_alias pragma

The Microsoft include_alias pragma is now supported in Microsoft mode.
See http://msdn.microsoft.com/en-us/library/wbeh5h91.aspx for more information
about the pragma.

  #pragma include_alias("a_long_file_name.h","short.h")
  // The include will actually open the file short.h
  #include "a_long_file_name.h"


1/5/10   [EDGcpfe/10346]
Ensure that MODULE_ID_NEEDED is TRUE whenever NEED_NAME_MANGLING is TRUE

In some configurations, it was possible for NEED_NAME_MANGLING to be TRUE and
MODULE_ID_NEEDED to be FALSE.  This could lead to compilation errors when
compiling lower_name.c.  This has now been fixed.


1/4/10   [EDGcpfe/10347]
Confusing use of next_two_tokens

The front end contained a few uses of next_two_tokens (such as the example
below) in which the return value was treated as a boolean value while it
is actually a token kind.  This code worked properly but could be confusing
to both users and analysis tools.  Now fixed.

  if (next_two_tokens(tok_lparen, &token_2) && token_2 == tok_rparen) { ... }

1/2/10   [EDGcpfe/8811]
Abort with name of function-style macro as last token of a file

If the last token of a file (source or header) is the name of a
function-style macro, and the last token before the start of that line is
also the name of a function-style macro not followed by '(', the front end
aborted with the message, "internal error: add_source_line_modif: more than
one line_start_source_line_modif."  This is now fixed.  For example:

  #define M()
  M
  M


1/1/10   [EDGcpfe/10117]
C++-generating back end: "typename" keyword for non-class dependent types

The C++ Standard requires that a dependent type be prefixed with the
"typename" keyword.  When the C++-generating back end generated a template
definition from the prototype instantiation and a dependent type was not
a class, however, it failed to add the necessary "typename" prefix.  This
is now fixed.  For example:

  template<typename T> struct X {
    typedef int S;
    S f();
  };
  template<typename T> typename X<T>::S X<T>::f() {
                    // ^^^^^^^^ formerly omitted, now correctly put out
    return 0;
  }


12/24/09 [EDGcpfe/7276]
Microsoft compatibility: missing right parenthesis in "defined" operator

As noted in the 5/9/97 entry, early versions of the Microsoft preprocessor
accepted uses of the "defined" operator in which the closing right
parenthesis is omitted, and the front end emulated this behavior.
Beginning with version 7.1, however, the Microsoft preprocessor correctly
diagnoses this error, and the front end has been changed to follow suit,
depending on the version being emulated.  For example:

    #if defined(X    // Now an error with microsoft_version > 1300


12/23/09 [EDGcpfe/7420]
C++-generating back end: deprecated string literal conversion

C++ permits use of a string literal (which has type "array of const char"
or "array of const wchar_t") in a context requiring a pointer to non-const
char or wchar_t, respectively.  This (deprecated) implicit conversion
appears in the IL as a compiler-generated cast, and the C++-generating back
end makes the cast explicit in the generated code to allow for cases in
which the target compiler may not allow the implicit conversion.  This cast
was omitted, however, for wide string literals and in cases where the
target type was a pointer to a typedef for char instead of a pointer
directly to char.  This is now fixed so that the casts appear in these
cases.  For example:

  typedef char T;
  void f() {
    T* x = "";         // now generated as ((T *)("")),
    wchar_t* y = L"";  // now generated as ((wchar_t *)(L""))
  }


12/23/09 [EDGcpfe/10328]
GNU C compatibility: abs in constant-expressions

In GNU C mode, calls of __builtin_abs with a constant integer argument are
now folded to the result value.  Declarations of "abs" that match the
standard C library requirement are now also considered to be aliases to
__builtin_abs, so an expression like "abs(-2)" will now be folded to 2 in a
constant expression in GNU C mode.  See also the very similar change
for strlen in EDGcpfe/10179.


12/22/09 [EDGcpfe/10200]
Sun compatibility: in-class specializations

The Sun compiler allows in-class specializations of member class and function
templates.  We previously supported such specializations in Microsoft mode.
We now also allow them in Sun mode.

  struct A {
    template<typename T> struct B { };
    template<> struct B<int> { };
  };


12/21/09 [EDGcpfe/6570]
Internal error on invalid multibyte character in string on Windows

An internal error could occur (in conv_string_literal) on a wide character
string literal containing a multibyte character that was invalid in the
current native multibyte locale.  The internal error was caused by a
Windows bug that caused _mblen_l to return a different length than
_mbtowc_l.  Now fixed.  This test case demonstrates the problem when run
with a native multibyte locale of 932 (Japanese).

  extern wchar_t const x[] = L"Á hola !";


12/18/09 [EDGcpfe/10333]
Abort when lowering partially initialized aggregate containing vector types

In configurations where vectors are permitted (typically GNU modes), the
lowering of an aggregate constant that contains designated initializers and
partially initializes an aggregate that contains vector types can cause an
abort in lowering.  When EXPENSIVE_CHECKING is TRUE, any aggregate involving
vector types and designated initializers had caused an abort
("lower_aggregate_designated_initializers: type mismatch").  When
EXPENSIVE_CHECKING is FALSE, a use of designated initializers that caused
lowering to insert a zero of vector type, had resulted in an assertion failure
("form_constant: error constant").  Both of these are now fixed.  For example
(--gcc):

  int __attribute__((vector_size(16))) x[2] = { [1] = { 1 } };


12/18/09 [EDGcpfe/10340]
String literals are now const by default in C++ mode

C++98 made string literals const (unlike C).  Formerly, we made them
non-const in default mode for compatibility purposes.  Most compilers
now make string literals const, so string literals are now const by default
in C++ mode.

  void f(char*){}        // #1
  void f(const char*){}  // #2
  int main() {
    f("hello");  // now calls #2 in default mode
  }


12/17/09 [EDGcpfe/10176]
Instantiation of nested class that is part of another declaration

Formerly, if a nested class of a class template was part of some other
declaration (e.g., in the typedef of "type" in the example below), the front
end would instantiate the nested class as part of the instantiation of the
enclosing class.  Such nested classes are now only instantiated if needed
(just like normal nested classes of class templates).

  template <typename T> struct C {
    typedef struct S { T t; } type;
  };
  struct D {
    C<D> c;  // used to give incomplete type error during instantiation
  };


12/17/09 [EDGcpfe/10150]
Spurious error on call of __sync_... function in template

In GNU modes, the front end accepts various built-in functions for atomic
memory access when the configuration macro GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED
is TRUE (see Changes entry of 7/31/07).  However, a spurious error was issued
when a call to such a function appears in a function template and the first
argument's type is "pointer to template parameter" (during prototype
instantiation).  For example:

  template<typename T> void f(T *p, T n) {
    __sync_fetch_and_add(p, n);  // Previously triggered a spurious error
  }                              // in some GNU modes.

This is now fixed.


12/17/09 [EDGcpfe/10337]
Microsoft compatibility: __nullptr keyword

The Microsoft compiler recognizes the __nullptr keyword as a synonym (in
native code only) for the C++0x nullptr keyword.  The front end has now been
changed to accept __nullptr as an alternate spelling for nullptr in Microsoft
mode.  For example:

  int* p = __nullptr;   // valid in --microsoft mode


12/17/09 [EDGcpfe/10338]
Destructible entity descriptors were being lost during compilation

In certain cases, lowering would allocate an a_destructible_entity_descr
IL entity and never free it, causing the entity to appear "lost" when
displaying the amount of space used (-d-space_used command line option).
This is now fixed (and doesn't affect the IL that is generated).  For example,
this case had caused leakage (with -x):

  struct A {
    A() {}
    void *operator new(__EDG_SIZE_TYPE__, int* p) { return p; }
    void operator delete(void*, int*) {}
  };
  void f() {
    int *p = 0;
    new(p) A();
  }


12/17/09 [EDGcpfe/10336]
Partial ordering and rvalue references

Formerly, partial ordering required references to be of the same kind (rvalue
or lvalue) in order to determine the ordering of parameters.  Now the kind
of reference does not have any effect on partial ordering.

  template<class T> void f(const T &x) { }
  template<class T> void f(T &&x) { }
  int main() {
    const int i = 1;
    f(i);  // formerly ambiguous, now accepted
  }


12/17/09 [EDGcpfe/10312,EDGcpfe/10313]
Template substitution resulting in expressions involving std::nullptr_t

The draft C++ Standard permits only a limited set of operations on operands
of type std::nullptr_t, and attempts to use nullptr in invalid ways are
caught in ordinary code when the expression is scanned.  Template argument
substitution bypasses these checks, however; this formerly allowed creation
of invalid expressions, resulting in various aborts.  This has now been
addressed by checking the validity of expressions involving operands of type
std::nullptr_t during template argument substitution and treating invalid
expressions as substitution failures.  For example:

  typedef decltype(nullptr) nullptr_t;
  template<template<nullptr_t _T> class T, typename U, U N>
    void f(T<~N>) { }
  template<nullptr_t N> struct B { };
  void g() {
    B<nullptr> b;
    f<B, nullptr_t, nullptr>(b);  // Formerly aborted, now gives
                                  // "no matching instance" error
  }


12/16/09 [EDGcpfe/10231]
Name mangling pre-pass before precompiled header file generation

In an attempt to reduce the total amount of compilation time when using
precompiled header files, a name mangling pre-pass is now invoked before
writing a precompiled header file.  Although this slightly increases the
compilation time when creating a precompiled header file, it often reduces the
compilation time when the precompiled header file is subsequently used.  During
this mangling pre-pass, any entities (e.g., members of unnamed namespaces,
unnamed types) whose mangled name is dependent on the value of the "module id"
are skipped (leaving these entities unmangled until the regular mangling pass
near the end of the compilation).


12/16/09 [EDGcpfe/10240]
Abort after malformed string in GNU asm declaration

A malformed string in a GNU asm declaration could cause the front end to
incorrectly access memory (and often abort) later on.  For example:

  void f() {
    int i = 0.0;
    asm("
        : : "r"(i) );  // First argument is a malformed (unterminated) string
  }                    // string when gnu_version >= 30300.  This triggered an
                       // abort in validate_symbolic_operand_references.

This is now fixed.


12/16/09 [EDGcpfe/10128]
Microsoft compatibility: template parameters in old-style specialization

The Microsoft compiler allows the use of template parameters in old-style
specializations.  We now emulate this in Microsoft mode.  Note that older
versions of the Microsoft compiler allowed template parameters to be used
in all kinds of specializations, but the other uses were no longer
supported as of version 7.1 (see 3/31/05 entry for more information).

  template <int i> struct C {
    int f();
  };
  int C<1>::f() {
    return i;  // i is visible in Microsoft mode
  }
  int main() {
    C<1> c;
    return c.f();
  }


12/15/09 [EDGcpfe/10326]
Spurious "declaration hides parameter" remark on friend function in template

The definition of a friend function of a class template is not evaluated
unless it is used.  If the evaluation was initiated by a reference from
another function, a variable declared in the friend could result in a
spurious "declaration hides parameter" remark.  Now fixed.

  template<typename T> struct A {
    friend void f(A*) { int k; };  // spurious '"k" hides parameter'
    inline void g(T k) { f(this); }
  };
  int main() {
    A<int> a;
    a.g(1);
  }


12/15/09 [EDGcpfe/9690]
GNU compatibility: Attributes error and warning

In GNU modes with gnu_version >= 40000, the front end now accepts attributes
error and warning on function declarations.  Note that the attributes are
recorded in the IL, but no diagnostics implied by these attributes are emitted
by the front end since such diagnostics depend on back end optimizations.
For example:

  __attribute((error("Not eliminated"))) void f() {}
  int main() {
    f();  // The front end will not issue an error on this call.  If a
  }       // back end does not eliminate the call, it is responsible for
          // emitting the diagnostic.


12/15/09 [EDGcpfe/9690]
GNU compatibility: Attribute externally_visible

In GNU modes with gnu_version >= 40000, the front end now accepts attribute
externally_visible on function and variable declarations with external
linkage.


12/15/09 [EDGcpfe/9690]
GNU compatibility: Attributes artificial, cold, flatten, and hot

The attributes artificial, cold, flatten and hot are now accepted by the front
end in some GNU C and C++ modes.  "artificial" and "flatten" require
gnu_version >= 40000; "cold" and "hot" require gnu_version >= 40300.


12/15/09 [EDGcpfe/10323]
Instantiate entities before precompiled header file creation

The front end can now be configured to instantiate entities before creating
a precompiled header file.  In modes in which templates are instantiated in
every translation unit in which they are used, this can improve performance
of translation units making use of the precompiled header file.  This
feature is controlled by the instantiate_before_pch_creation variable, the
initial value of which is given by INSTANTIATE_BEFORE_PCH_CREATION.
INSTANTIATE_TEMPLATES_EVERYWHERE_USED is used as the default value of
INSTANTIATE_BEFORE_PCH_CREATION.  Instantiations are only done before
writing the precompiled header file if the instantiation mode is tim_used
or tim_all (tim_used is the default when INSTANTIATE_TEMPLATES_EVERYWHERE_USED
is being used).  There is a small possibility that use of this option could
cause a change in behavior of programs as it changes the point in the
translation unit in which the instantiation is done.


12/14/09 [EDGcpfe/9568,EDGcpfe/9690]
GNU compatibility: Attribute alloc_size

In GNU modes with gnu_version > 40200, the front end now accepts attribute
alloc_size.  For example:

  void* allocate(int n) __attribute((alloc_size(1)));


12/14/09 [EDGcpfe/10320]
GNU C compatibility: Duplicate signed/unsigned in typedef declarations

In GNU C mode, the front end accepts duplicate "signed" or "unsigned" keywords
when gnu_version < 30300.  Now, it also accepts this duplication in typedef
declarations when gnu_version < 40000.  For example:

  typedef unsigned unsigned char X;  // Accepted in GNU C mode with
                                     // gnu_version < 40000.


12/14/09 [EDGcpfe/10315]
Abort when lowering zero initialization of some classes with std::nullptr_t

An assertion failure had occurred (in lower_zero_initialization in lower_il.c)
when lowering the zero initialization of an entity that contains both a pointer
to data member and an entity of type std::nullptr_t.  This was a problem only
in the IA-64 ABI and is now fixed.  For example (--c++0x):

  struct A {
    int A::*pm;
    decltype(nullptr) n;
    void f();
  };
  void f() {
    A().f();
  }


12/14/09 [EDGcpfe/10256]
C++-generating back end: RECORD_FORM_OF_NAME_REFERENCE and template arguments

When the front end is configured with RECORD_FORM_OF_NAME_REFERENCE as
TRUE, the form of the reference captured for a name appearing in a template
argument is the one used in the first reference to the template instance.
If that reference occurs nested inside a class or namespace and the
argument refers to a member of that class or namespace or one of its
parents using an unqualified or partially-qualified name, the
C++-generating back end used that form of the name in the argument, even in
contexts in which the name is no longer visible, resulting in erroneous
generated code.  This has been fixed by never using the captured form of
name reference when generating template arguments.  For example:

  namespace N {
    struct S { void f(); };
    template <void (S::*)()> struct Z { };
    Z<&S::f> z;
  }
  N::Z<&N::S::f> zz;    // Formerly generated as "N::Z< &S::f>"


12/11/09 [EDGcpfe/10289]
Abort on cast of std::nullptr_t expression to pointer to member function

Casting of an expression with side effects whose type is std::nullptr_t to a
pointer to member function can result in the lowered expression having the
incorrect type if the expression contains an eok_comma or eok_question
operation.  In C generating back end configurations this caused an assertion
failure (e.g., "dump_expr: bad type on eok_comma").  For example (--c++0x):

  typedef decltype(nullptr) nullptr_t;
  struct A {};
  void f() {};
  void (A::*pmf)(void) = (nullptr_t) (f(), nullptr);


12/11/09 [EDGcpfe/10170]
GNU built-in functions that do not return

The GNU built-in function __builtin_abort, __builtin_exit, __builtin__exit,
__builtin__Exit, __builtin_longjmp, and __builtin_trap are now marked as not
returning (i.e., the "does_not_return" flag in the associated routine type
supplement is TRUE).  This prevents spurious warnings in some functions
declared with the "noreturn" attribute.  E.g.:

  __attribute((noreturn)) void f() {  // Previously elicited a spurious
    __builtin_exit(2);                // warning claiming that f does return.
  }


12/11/09 [EDGcpfe/10319]
Reduce the number of cases where lowering is delayed when waiting for module id

A change was made in version 4.1 (see Changes entry for EDGcpfe/9904) to
delay lowering of a function scope if lowering of that function scope might
lead to a mangling request that cannot be satisfied because a module id
has not yet been determined.  With this change, lowering of all routines
was delayed in modes where local types are allowed as template arguments
(i.e., --c++0x or --microsoft_version >= 1400).  This contributed to increased
compilation times when pre-compiled header files were used as routines stored
in the PCH files were no longer lowered (in the modes specified above),
necessitating lowering of these routines when the PCH files were later used.
A change has been made to delay lowering in these modes only when the function
contains local types.

Separately, a change has been made to disqualify any entity in a system header
file from being the basis of a module id.


12/11/09 [EDGcpfe/10193]
Bit-field size constraints in templates

The front end performs a number of checks on the size of a bit-field and its
relation to the base type of that field, and issues diagnostics accordingly.
However, when the type and/or size of a bit field was template-dependent,
spurious warnings or errors could be emitted.  For example:

  enum E { start, end = 0xFFFF };
  template<typename T, int n> struct S {
    T b1: 36;  // Triggered a spurious warning when int is a 32-bit type.
    E e: n;    // Triggered a spurious warning.
  };

This is now fixed.

A related change was also made to avoid emitting confusing diagnostics on a
bit field that was already diagnosed as an error.  For example:

  struct X { double d:36; };  // Triggered a confusing warning about the
                              // bit field size after reporting an error
                              // about the bit field type.


12/9/09  [EDGcpfe/9848]
GNU compatibility: Attribute tls_model

In GNU modes with gnu_version >= 30300, the front end now supports attribute
"tls_model" on thread-local variables (in configurations that set the macro
THREAD_LOCAL_STORAGE_SPECIFIER_ALLOWED to TRUE).  For example:

  __thread int x __attribute((tls_model("global-dynamic")));


12/9/09  [EDGcpfe/10309]
Unlowered pointer to member function constant in some file scope aggregates

In configurations that enable exception handling, a pointer to member
function constant that appears in a file scope aggregate that also contains 
members that require destruction resulted in the pointer to member function
constant not being lowered.  For example (with -x):

  struct A {
    ~A() {}
    void f(void) {}
  };
  struct B {
    void (A::*pmf)(void);
    A a;
  } b[] = { &A::f, A() };


12/9/09  [EDGcpfe/10189]
Incorrect lookup with multiple template parameter clauses

Name lookup was not done properly in the presence of multiple template
parameter clauses.  This resulted in errors such as finding the incorrect
B in the definition of N::C<B>::f(B) in the example below.  Now fixed.

  namespace N {
    template<class B> struct C {
      template<class T> void f(B);
    };
    template<class T> class B {};
  }
  template<class B> template<class T> void N::C<B>::f(B) {;}


12/8/09  [EDGcpfe/10283]
Missing diagnostic on namespace declared with template-id in GNU C++ mode

In g++ mode when gnu_version is < 40300, a class and a namespace can be
declared with the same name in a given scope (see the Changes entry of
6/12/09).  However, the front end silently ignored what looked like template
arguments following the namespace name in such cases (a regression introduced
in version 4.1).  In some configurations this could lead to an internal error
(in record_defeatable_name_hiding_for_single_entity) later on.  For example:

  template <class T> struct A {};
  namespace A<short> {}  // Previously unintentionally accepted in g++ mode.

This is now fixed: An error is issued for such constructs.


12/8/09  [EDGcpfe/10269]
Invalid IL (and bad generated C) for lambda in initializer for namespace-scope
variable

When a lambda appeared in an initializer for a namespace-scope variable that
appeared outside of the namespace of the variable, the closure type did not
appear on the file scope's types list in the lowered IL.  This resulted in
invalid code generated by the C-generating back end.  For example:

  namespace N { extern int i; }
  int N::i = []{ return 1; }();  // Previously resulted in invalid IL.

This is now fixed.


12/8/09  [EDGcpfe/10307]
GNU C++ compatibility: template keyword with missing template argument list

A change made in version 4.1 resulted in spurious errors in some uses of
the "template" keyword in g++ mode when gnu_version is >= 30400.  Now fixed.
See the 12/19/08 entry for information about the original change.

  struct A {
    template <class T> class B {};
  };
  template <template <class> class TT> struct X {
    TT<int> y;
  };
  template <class T> struct C {
    X<T::template B> x;  // error on this line
  };


12/7/09  [EDGcpfe/10308]
GNU compatibility: removal of duplicate search paths with the -I- option

The change described in the 11/23/09 entry for removing search paths that
are specified as both system and non-system did not correctly handle the
case when the search path that was removed was the one immediately
preceding the -I- option, which identifies the start of paths to be used
for the <...> form of header name.  For example, command line options of
the form

  -Ifoo -I- --sys_include foo

could result in failure to find any system headers.  This is now fixed.


12/7/09  [EDGcpfe/10281, EDGcpfe/10282]
Memory region issues when inlining

The lowering post pass introduced as part of the expression rewrite
changes for 4.0 (see the 7/24/08 Changes entry) was mistakenly being performed
on expressions being used as the source for an inlined function rather than
on the copied expressions.  Though mostly harmless, in certain cases the
post pass could modify the expression, resulting in an expression that
crossed memory regions.  Incorrectly modified expressions could result in many
different failure modes, including (but not limited to) assertion failures
"remap_ptr_to_entry_number: pointer in secondary trans unit" and
"set_expr_node_kind: bad kind".  For example (--c++0x):

  typedef decltype(nullptr) nullptr_t;
  template <template <class _T, _T x> class T> struct A {
    T<nullptr_t, nullptr> x;
  };
  template <class T, T x> struct B {
    T y;
    B() : y(x) {}
  };
  A<B> ab;


12/7/09  [EDGcpfe/10295]
Abort on base class conversion in template when folding constant address

There was an abort in get_pointer_offset ("bad kind") on attempting to
fold an lvalue to a constant address in the presence of a conversion to a
base class where the underlying address is template-dependent.  Now fixed.
The problem presented itself in a use of offsetof with --parse_templates
and --microsoft:

  #define offsetof(s,m) \
    (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
  template <class T> class SmartPtrBase {
   public:
    T* p;
  };
  template <class T> class SmartPtr : public SmartPtrBase<T> {};
  template <class T> void function() {
    struct Foo {
      SmartPtr<char> m_ptr;
    };
    size_t offset = offsetof(Foo, m_ptr.p);
  }


12/7/09  [EDGcpfe/10291]
Assertion failure when lowering certain pointer to member function comparisons

Lowering of a pointer to member function comparison expression in the file
scope where one of the operands is a pointer to member function constant and
the constant also appears earlier in the expression had caused an assertion
failure (in repr_for_ptr_to_member_function_constant in lower_il.c) and is now
fixed.  For example:

  struct A {
    void f(void) {}
  };
  void (A::*p)(void);
  bool x = (&A::f, (&A::f == p));


12/6/09  [EDGcpfe/10297]
Comparing nullptr with an integral null pointer constant

The current draft C++ Standard does not allow comparison of a value of type
std::nullptr_t with an integral null pointer constant nor to use them as
the second and third operands of a conditional (?:) operator, so the front
end treated such expressions as errors (except in Microsoft mode, where
they were accepted).  The C++ Standard Committee is expected to change this
rule at the next meeting (see core language issue 963), however, so the
front end has been changed to follow suit.  For example, the following two
declarations are now accepted without error in --strict mode:

  bool b = nullptr == 0;
  int* p = b ? nullptr : 0;


12/6/09  [EDGcpfe/10296]
Comparing nullptr with a dependent-type constant during argument deduction

The front end formerly failed an assertion when comparing nullptr to a
constant with a dependent type during template argument deduction.  This is
now fixed.  For example:

  template<bool N> struct A { };
  template<typename T, T t> int f(A<t == nullptr>);
  A<true> a;
  int i = f<int,0>(a);


12/4/09  [EDGcpfe/10288]
Lowering inadvertently introduces an lvalue as first operand of an eok_comma

Some expressions generated during lowering resulted in an eok_comma
operation whose first operand is an lvalue.  The example that follows had
generated incorrect IL.  In (4.0 and later) configurations that use the C
generating back end, the example had caused an assertion failure ("dump_expr:
lvalue-returning operation").

  struct A {
    int x;
    static int y;
    A(int z = 0) {}
  } a;
  void f() {
    (a = 0).y;
  }


12/4/09  [EDGcpfe/10264]
Non-type template parameter of type std::nullptr_t with integral null pointer
constant

The current draft C++ Standard does not permit use of std::nullptr_t as the
type of a non-type template parameter, although in anticipation of a change
in this regard the front end currently accepts this usage.  It is expected
that if the Standard Committee makes this change, use of an integral null
pointer constant as an argument to such a parameter will require a cast,
just as a cast is necessary when passing 0 to a non-type template parameter
with a pointer type.  The front end formerly did not enforce that
requirement for std::nullptr_t but now does.  For example:

  typedef decltype(nullptr) nullptr_t;
  template<nullptr_t NULL> struct S { };
  S<0> s_null;    // Now an error, requires a cast


12/3/09  [EDGcpfe/8293,EDGcpfe/9067,EDGcpfe/9253,EDGcpfe/9531,EDGcpfe/9861,
          EDGcpfe/10280]
Attributes

The original framework supporting GNU attributes in the front end dealt with
a few attributes for GNU C compatibility.  Since then, many attributes have
been added and most are also accepted in C++ modes.  The original framework
didn't make it particularly convenient to add simple attributes, and it didn't
deal well with C++ templates.  It also did not provide much support for source
analysis of attributes (for example, no position information was available in
the IL for attribute constructs).

Because of these limitations and the needs of C++0x attributes, the front end
now includes a new framework for attributes (that replaces the original GNU
attributes framework).  It initially implements GNU attributes and C++0x
attributes, but it is also designed to handle Microsoft-style __declspec
attributes in the future.

In C++0x mode, the attributes "align", "carries_dependency", "final", and
"noreturn" are now supported.  For example:

  [[noreturn]] void f() {}  // Warning is issued: calls to f() do return.

(The standard attributes feature was added to the C++0x working paper by
document N2761, adopted at the September, 2008 (San Francisco) meeting.  Some
of the attributes were added subsequently through additional documents.)

In GNU C++ mode, attributes with template-dependent arguments are now handled
correctly.  For example:

  template<int N> struct S {
    struct __attribute((aligned(N))) {} s;  // Previously an error (invalid
  };                                        // attribute argument); now okay.

When both GNU_EXTENSIONS_ALLOWED and SUN_EXTENSIONS_ALLOWED are TRUE, the
front end now accepts some GNU attributes in Sun mode.  The Sun mode
attributes are "aligned", "constructor", "destructor", "packed", "visibility",
and "weak".  (When GNU_EXTENSIONS_ALLOWED is TRUE, the global variable
gnu_attributes_enabled now controls whether GNU attribute syntax is accepted.)

Attributes are now represented directly in the IL (via an_attribute entries).
The new configuration macro RECORD_UNRECOGNIZED_ATTRIBUTES determines whether
unrecognized attributes are recorded in the IL (when FALSE, unrecognized
attributes elicit a warning).

Adding new attributes is now much simplified: See the comments at the top of
attribute.c for an overview.


12/3/09  [EDGcpfe/10266]
Casting to std::nullptr_t

The front end accepted a cast of a pointer or pointer to member to
std::nullptr_t, on the grounds that such a cast is the inverse of a
standard conversion.  Although the current draft Standard does not forbid
these casts, this omission is almost certainly the result of an oversight
when the nullptr keyword was adopted, and an issue will be raised with the
C++ Standard Committee.  In the meantime, the front end has been changed to
treat such casts as errors.  For example:

  typedef decltype(nullptr) nullptr_t;
  void* p = nullptr;
  nullptr_t np = static_cast<nullptr_t>(p);    // Now an error


12/3/09  [EDGcpfe/10276]
Non-lowered type_kind for lowered assignment to pointer to member (IA-64 ABI)

type_kinds are supposed to be lowered (see the Changes for entry for
EDGcpfe/10048), but were not properly lowered in the case of a routine added
during lowering to zero-initialize an entity of pointer to member type.
This problem is specific to the IA-64 ABI.  In C generating back end
configurations, this example fails an assertion check in dump_expr:

  struct A {};
  typedef double A::*pd;
  struct B {
    pd a[37];
    B();
  };
  B::B() : a() {}


12/3/09  [EDGcpfe/10262]
Abort during lowering of some assignments to temporaries when CHECKING is TRUE

In configurations where CHECKING is TRUE, the creation of an assignment of an
expression whose type is a typedef for a class to a temporary had caused
a segmentation violation and is now fixed.  For example:

  struct A {
    void f() {}
  };
  typedef void (A::*pmf)(void);
  pmf p;
  bool b = (p != (throw, &A::f));


12/2/09  [EDGcpfe/10263]
Use of nullptr in non-type template arguments

The front end incorrectly issued an error when nullptr appears as an
operand in an expression used as a non-type template argument.  This is now
fixed.  For example:

  template <int* x> struct A {};
  A<true ? nullptr : nullptr> a3;


12/2/09  [EDGcpfe/10265]
Casting to std::nullptr_t in an integral constant expression

The front end incorrectly issued an error when a cast to std::nullptr_t
appears in an integral constant expression.  This is now fixed.  For example:

  typedef decltype(nullptr) nullptr_t;
  int x[(nullptr_t)nullptr ? 3 : 4];    // No longer an error


12/2/09  [EDGcpfe/10273]
Internal error on truncated template

An internal error (in copy_tokens_from_cache) could occur on a
template definition that was truncated causing the end of file to
appear in the body of the template.  The internal error would occur if
certain kinds of disambiguation were triggered at the point at which
the file was truncated.  Now fixed.

  template <class T, class U> bool f(T x, U y) {
  decltype (


12/1/09  [EDGcpfe/10268]
Abort on multiple lambdas in namespace reactivation scope

An abort could occur (in add_lambda_closure_to_types_list) if multiple
lambdas occurred in a namespace reactivation scope.  This could occur if
a variable was declared in a namespace scope and then defined outside of
the namespace.  Now fixed.

  namespace N {
    extern int i;
  }
  int N::i = []{return 1;}() + []{return 2;}();



11/28/09 [EDGcpfe/10255]
Using nullptr in integral constant expressions

Use of nullptr, cast to an integral type, in an integral constant expression
is well-formed; however, the front end formerly issued an error for such
constructs.  This is now fixed.  For example:

  enum E { e0 = int(nullptr) };   // No longer an error


11/28/09 [EDGcpfe/10245]
Using std::nullptr_t() as a non-type template argument

The front end previously issued an error when an explicit temporary of type
std::nullptr_t is used as a non-type template argument.  This is now fixed.
For example:

  typedef decltype(nullptr) nullptr_t;
  template<int* P> struct S { };
  S<nullptr_t()> s;    // Formerly an error, now accepted


11/24/09 [EDGcpfe/10243]
Error suppression in expression-processing routines

In preparation for some SFINAE changes (see N2634), the diagnostic
output in the expression-processing routines (expr.c, exprutil.c, and
overload.c) has been reworked so that diagnostics can be suppressed
when necessary.  Customer additions to those files may have to be
updated.  For many of the simpler diagnostics, a simple change of
called routine is sufficient:

  pos_error       --> expr_pos_error
  pos_warning     --> expr_pos_warning
  pos_diagnostic  --> expr_pos_diagnostic

Other calls have to be enclosed in a test of expr_error_should_be_issued
or expr_diagnostic_should_be_issued, as appropriate.  Any access-checking
code must be conditioned on expr_access_checking_should_be_done.


11/24/09 [EDGcpfe/10216]
Lowering of cast of pointer to member function to std::nullptr_t

Lowering of a cast to std::nullptr_t where the operand is a pointer to member
function expression with side effects had caused invalid IL to be generated
(causing illegal generated C code in C generating back end configurations).
This is now fixed.  For example (--c++0x):

  struct A {
    void f() {}
  };
  void f() {
    typedef void (A::*T)(void);
    T p = ( decltype(nullptr) ) *new T;
  }


11/24/09 [EDGcpfe/10221]
Improper lowering of cast of std::nullptr_t to pointer to member function type

Expressions of std::nullptr_t type that are cast to a pointer to member
function type had been replaced during lowering by a constant aggregate
representing a null pointer to member function constant.  These aggregate
constants had caused an assertion failure (in
repr_for_ptr_to_member_function_constant in lower_il.c) in some pointer to
member function comparison cases and have now been replaced with a temporary
variable initialized to the proper value.  For example (--c++0x):

  struct S { void f(); };
  bool f(bool b) {
    return &S::f != (b ? nullptr : nullptr);
  }


11/24/09 [EDGcpfe/10222]
Improperly lowered lvalue eok_comma on some std::nullptr_t operations

Lowering of certain operations with type std::nullptr_t could result in
improper lowering of an inserted eok_comma operation (leaving
returns_lvalue_instead_of_usual_rvalue set to TRUE), resulting in an assertion
failure ("dump_expr: lvalue-returning operation") in C generating back end
configurations.  This is now fixed.  For example (--c++0x):

  typedef decltype(nullptr) T;
  void f() {
    T t;
    t = (T&&)nullptr;
  }


11/23/09 [EDGcpfe/10238]
GNU C++ compatibility: Meaning of block-extern declarations in namespaces

Consider:

  namespace N { struct S { void f(); }; }
  void N::S::f() {
    void g();  // ::g in g++ mode, N::g otherwise.
  }

In standard C++, the meaning of the block-extern declaration of g in N::S::f
is "as if" the function definition had appeared in namespace N: It is a
declaration of N::g.  Previously, we adhered to that behavior in all modes.
Now, in GNU C++ mode, the block-extern declaration of g is instead treated as
a declaration of ::g.  This change also applies to block-extern declarations
of variables.

An entirely similar change was previously made for non-class-member function
definitions (see Changes entry of EDGcpfe/9830).


11/23/09 [EDGcpfe/10219]
Assertion failure when lowering throw of nullptr in file scope

Lowering a throw of type std::nullptr_t in a file scope expression had
caused an assertion failure ("missing typeinfo variable") in configurations
where DO_FULL_PORTABLE_EH_LOWERING is TRUE.  This is now fixed.
For example (--c++0x -x):

  int x = (1 ? throw nullptr : 1);


11/23/09 [EDGcpfe/10239]
GNU compatibility: include directory specified as both system and non-system

Version 4.1 introduced a GNU compatibility feature that ignores a -I option
naming a directory that was also specified using the --sys_include
option (see the 7/2/09 entry).  This facility did not work properly in
some cases where the removed directory was the first entry on the search
list used for the "#include <...>" form of include.  Now fixed.


11/23/09 [EDGcpfe/10217]
Incorrect setting of result_is_not_used flag in some lowered expressions

Top-level lvalue expressions are rewritten as rvalue expressions during
lowering.  If, during this rewriting, the expression type is changed to
void (because it contains an eok_question operation whose second and
third operands have different types after being rewritten), it is possible that
the result_is_not_used flag may be set incorrectly in some portion of the
expression.  For users of the C generating back end, this had resulted in an
assertion failure in check_result_not_used_flag.  For example:

  typedef int T;
  T x;
  void f() {
    0, (0, (0 ? *new T : x));
  }


11/20/09 [EDGcpfe/10159,EDGcpfe/10220]
Spurious error when member function fails to hide a using-declaration

When the declaration of a member function or member function template matches
a declaration brought in by a using-declaration, the front end previously
failed to hide the declaration brought in from the base class.  This could
result in spurious ambiguity errors later on, most commonly when calling
member function templates.  For example:

  struct B { template <class T> int f(T); };
  struct D: B { 
    using B::f;
    template <class T> int f(T);
  };
  void g(D *p) {
    p->f(1);  // Previously triggered a spurious ambiguity error.
  }

This is now fixed.


11/20/09 [EDGcpfe/10114]
Include directory search issue introduced in version 3.7

Version 3.7 included changes to improve the performance of the include
search process.  One of the changes suppressed the opening of a file that
had previously been included and that contained include guard code.  The
comparison of file names in this check used a canonical version of the
name, which caused names such as "x.h" and "some_dir/../x.h" to be
considered the same. This had the effect of disabling a technique that can
be used to ensure that the x.h file is found in a specific directory (the
one that also contains a some_dir directory).  The comparison used in such
cases has now been changed to not use the canonical form of the file name.


11/19/09 [EDGcpfe/10191]
Internal error on mem-initializer referring to anonymous union member

In configurations with EXPENSIVE_CHECKING set to TRUE, the front end aborted
with an internal error in ctor_initializer when a mem-initializer refers to a
member of a namespace-scope anonymous union.  For example:

  static union { int x, y; };
  struct A {
    A() : x(y) {}  // Previously triggered an internal error.
  };

This regression was introduced in version 4.0 and is now fixed: An ordinary
error is issued.


11/18/09 [EDGcpfe/10209]
C-generating back end: covariant member functions with ellipsis

A bug was introduced in version 4.1 that caused incorrect generated C code
for covariant member functions with an ellipsis parameter.  The bug affected
both IA-64 and Cfront ABIs and is now fixed.  For example:

  extern "C" int printf(const char *,...);
  struct A {
    virtual ~A() { }
  };
  struct B {
    virtual B *f(...) {
      return this;
    }
  };
  struct D: A, B {
    D *f(...) {
      printf("D::f\n");
      return this;
    }
  } d;
  int main() {
    B *pb = &d;
    pb->f();
  }


11/17/09 [EDGcpfe/10187]
GNU C++ compatibility: injected class lookup

A name such as A::A sometimes refers to the injected class name of A and
sometimes refers to the constructor of A.  In g++ 3.4, such lookups were
made more standard-conforming, but some names were still treated as
injected classes when they should not be.  In particular, this occurs in
contexts in which an expression is being scanned.  We now emulate this
portion of the g++ behavior when gnu_version is >= 30400 (this code is also
accepted for for gnu_version < 30400 because we emulate the more lax g++
behavior in such cases).

  struct A { A(int x); };
  void f(const A &);
  void g() { f(A::A(1)); }


11/17/09 [EDGcpfe/10169]
File names in diagnostics now converted to native multibyte characters

When NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is TRUE on Windows,
file names in diagnostic output and other forms of output (e.g., makefile
dependency information, the __FILE__ macro, etc.) are now converted to
the native multibyte character set.  File names were already converted
from native multibyte characters to UTF-8 on input, so this allows the
names to be output in the same character set used for input.  The conversion
(in both directions) is only done when DEFAULT_UNICODE_SOURCE_KIND is
usk_none.

11/16/09 [EDGcpfe/10207]
No outside-of-object warning on integer add/subtract of value based on pointer

A "pointer points outside of underlying object" warning is no longer issued
on a constant integer operation based on a constant address cast to an integer
type.  

  unsigned int x;
  void func(void){
    unsigned int y;
    y = (unsigned int)(&x) + 0x10000000;  // Warning no longer issued
  }


11/14/09 [EDGcpfe/10180]
GNU compatibility: __builtin_va_list and 64-bit x86 target

In GNU modes with configurations that set USE_X86_64 to TRUE, the front end
now predeclares __builtin_va_list in a way that is equivalent to:

       struct __va_list_tag {
         unsigned int  gp_offset;
         unsigned int  fp_offset;
         void          *overflow_arg_area;
         void          *reg_save_area;
       };
       typedef struct __va_list_tag __builtin_va_list[1];


11/14/09 [EDGcpfe/10034]
eok_array_to_pointer nodes now marked as compiler_generated

eok_array_to_pointer nodes, used to indicate the implicit decay of an
array to a pointer to the first element, are now marked as compiler
generated.  They also have no source position now.


11/14/09 [EDGcpfe/10134]
inline user replacement for operator delete[]

The other half of the inline operator new[] change described in the Changes
entry of 6/26/09:  The front end now generates code that will call an
inline replacement operator delete[] at runtime.

   extern void myfree(void *);
   inline void operator delete[](void *p) { myfree(p); }
   struct S { ~S(); };
   void f(S *p) { delete [] p; }


11/13/09  [EDGcpfe/10201]
Individuate only class/struct/enum unnamed types

A change has been made to consider only class/struct/enum unnamed types
for individuation (see Changes entry of 7/27/09); previously all types were
checked, which could have led to unexpected manglings for types added by
customers.  In some cases, this might also affect the selection of a module id
(which in turn can affect the order functions are lowered in) since a module
id cannot be a symbol that needs individuation.  This is now fixed.


11/13/09  [EDGcpfe/10203]
Internal error on referenced but not defined member of prototype instantiation

An internal error could occur in C++-generating back end versions in modes
in which decls_using_types_without_linkage_allowed is TRUE (e.g., c++0x mode,
Microsoft mode when microsoft_version is >= 1400).  The internal error
occurred in f_entity_can_be_instantiated on examples in which a member
function of a prototype instantiation was considered referenced but was
not defined.  Now fixed.

  struct X {
    template <class T> struct A {
      static T& make_t();
      enum E { e1 = sizeof(make_t()) };
   };
 };


11/12/09  [EDGcpfe/8545]
Minor folding issue with constant subscript validity checking

A minor mistake in folding could cause a spurious warning about a subscript
being out of range when the array size is large enough that it would be
a negative number when expressed in a_targ_ptrdiff_t.  This only happened
with certain configurations where a_targ_size_t and a_targ_ptrdiff_t are
as big as a_host_large_unsigned.  Now fixed.

  extern char a[0xC0000000];
  char *p = &a[0];  // Got spurious warning in some configurations


11/10/09  [EDGcpfe/10192]
Missing parent value for block scopes under condition scopes

A block scope entry (a_scope of kind sck_block) previously had a NULL parent
scope if the block scope appeared under a condition scope.  For example:

  void f() {
    if (int i = 3)  // Condition scope.
    {               // Block scope: Previously with a NULL parent pointer.
      int x = 4;
    }
  }

This is now fixed: The block scope's parent pointer now points to the condition
scope.


11/10/09  [EDGcpfe/10179]
GNU C compatibility: strlen in constant-expressions

In GNU C mode, the front end now treats ordinary declarations of the function
strlen much like an alias for the predeclared __builtin_strlen (provided the
types match and that the declaration is not a definition).  As a consequence,
calls to strlen with a string literal argument are evaluated by the front end
and are therefore usable in constant-expression contexts (because we have
also added folding for __builtin_strlen with a string literal argument).
If a definition is provided for strlen, the equivalence with the built-in
function is disabled.  For example:

  /* Assume __builtin_strlen returns an unsigned int. */
  unsigned strlen(char const*);
  unsigned L = strlen("xyz");  // Okay; same as "unsigned L = 3;".
  unsigned strlen(char const *str) {  // Definition disables equivalence.
    return 0;
  }
  unsigned N = strlen("xyz");  // Error: Initializer is not constant.


11/9/09  [EDGcpfe/10131]
Microsoft and GNU C++ compatibility: partial ordering in non-call contexts

Version 4.1 included a change in the handling of partial ordering in
non-call contexts to resolve a standards conformance issue (see the
6/5/08 entry).  However, the Microsoft and g++ compilers still handle such
cases incorrectly.  We have now restored the old behavior in g++ and Microsoft
modes.

  template <class T> T f(const T* p);
  template <class T> int f(T* p);
  // ambiguous specialization, but accepted in g++ and Microsoft modes
  template <> int f(const int*){return 0;}


11/6/09  [EDGcpfe/10182]
Abort in parsed template overload resolution on address-of-overloaded-function

In modes that do prototype instantiations of templates (e.g.,
--parse_templates), the front end aborted in overload.c
(in determine_arg_match_level) while processing an argument that is the
address of an overloaded function from the current template.
Now fixed.

  template<class F, class T> void f(F (T::*f)(void)) {}
  template <typename T> struct A {
    void g ();
    static void g (int);
    A() {
      f(&A::g);  // Caused abort with --parse_templates
    }
  };
  A<void> b;


11/4/09  [EDGcpfe/8710]
Set DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE to TRUE in platform
specific defines.h.*

The DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE macro is now explicitly
set to TRUE in all of the platform specific defines.h.* files.  This macro
should be set to TRUE in cases where GUARD_MACRO_FOR_VA_LIST is set
(as it is in defines.h.solaris and defines.h.win32).  It should also be TRUE
in cases where the primary compiler is gcc based (i.e., defines.h.linux,
defines.h.macosx).


11/3/09  [EDGcpfe/10172]
Microsoft compatibility: conversion for direct reference binding

The previous changes in the area of Microsoft compatibility and
conversions for direct reference binding (see entries of 5/3/07
and 11/2/06) still did not get it quite right.  A case like the
one below got an internal error in overload.c in
conversion_for_direct_reference_binding_possible.  It should be
considered unambiguous (as in non-Microsoft mode), and now it is.

  struct A { };
  struct B {
    operator A();
    operator A&();
  };
  int main() {
    B b;
    (const A&)b;  // Should pick operator A&()
  }


10/30/09 [EDGcpfe/10163]
Spurious errors on Microsoft-style parameter attributes

In a function declaration whose first parameter involves a parenthesized
declarator, and the second parameter starts with Microsoft-style (bracketed)
attributes, the front end often issued spurious errors (in Microsoft mode).
For example:

  void f(char (&a)[10], [in] int b[]);
    // Previously triggered multiple spurious errors, the first of which
    // suggesting that the type of f is incomplete.

This is now fixed.


10/30/09 [EDGcpfe/10053]
Abort in lower_c99.c (in match_routine_type_in_call)

Previously, in all GNU C modes, incompatible block-external declarations
declared in different function scopes were allowed (with a warning).  Lowering
of calls to functions redeclared with a different number of parameters could
lead to an assertion failure in lower_c99.c (in match_routine_type_in_call).
A change has been made to be more compatible with GNU's behavior in this area;
an error is now issued when gnu_version >= 30400.  The code is still accepted
(with a warning) when gnu_version < 30400.  Here is an example that previously
caused the assertion failure:

  void g(void) {
    extern void f(int x, int y);
    f(1, 2);
  }
  void h(void) {
    extern void f(int x);
    f(3);
  }

[ See also Changes entry for EDGcpfe/10810. ]


10/29/09 [EDGcpfe/10161]
Saving backing expressions for constants when IL lowering is done

In version 4.0, the recording of backing expressions for constants,
formerly included only if RECORD_CONSTANT_EXPRESSIONS_IN_IL was TRUE,
was made unconditional.  However, when IL lowering is done that
recording was turned off, because it's not very useful and it can
be confusing.  It turns out some customers do want the backing expressions
recorded even with IL lowering, e.g., to produce fuller debug information.
Therefore, we've added a new flag RECORD_BACKING_EXPRS_WITH_IL_LOWERING,
which can be set to request those expressions.


10/28/09 [EDGcpfe/10145]
C++0x: configuration macro to disable C++0x features requiring back end support

A new configuration macro CPP0X_IL_EXTENSIONS_SUPPORTED has been introduced
to disable any C++0x features that require back end (or runtime library)
support.  A back end that is not prepared to deal with C++0x features should
set this flag to FALSE.  When TRUE (the default), back ends and the runtime
library must be prepared to deal with any enabled C++0x feature.  The value of
this macro is passed to the runtime library (when --building_runtime is
specified) as __EDG_CPP0X_IL_EXTENSIONS_SUPPORTED.  C++0x features that have no
back end (or runtime library) impact are not affected by the setting of this
macro.


10/27/09 [EDGcpfe/10167]
Microsoft compatibility: spurious error on __if_exists of class template

A Microsoft __if_exists directive that names a class template resulted
in a spurious "missing template argument list" error.  Now fixed.

  struct A {
    template<int id> struct X {};
  };
  struct B : public A {
    int i;
  __if_not_exists(X) {
    template<int id> struct X {};
  }
  };


10/27/09 [EDGcpfe/10141]
Microsoft compatibility: abort on __if_exists

An abort could occur (in make_projection_symbol) if the first token after
the opening brace of a class is an __if_exists operation.  Now fixed.

  struct A {
  __if_not_exists(X) {
  template<int id> struct X {};
  }
  };
  struct B : public A {
  __if_not_exists(X) {
  template<int id> struct X {};
  }
  };


10/26/09 [EDGcpfe/10146]
Aborts and spurious errors on using-declarations in class templates

The front end previously contained some bugs in the area of using-declarations
appearing in classes nested in class templates.  These bugs often resulted in
spurious errors, internal errors, or aborts due to null indirections.  (The
aborts occurred in create_member_using_declaration.)  For example:

  struct B { int b; };

  template<class T> struct X {
    struct C {};
    struct D: C {
      struct N: T {
        using B::b;  // Previously triggered a spurious error.
        using D::c;  // Previously triggered an internal error.
      };
    };
  };

These bugs are now fixed.


10/26/09 [EDGcpfe/10143]
Mangling of C++0x lambdas caused assertion failure in some configurations

In configurations where PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE is FALSE,
mangling of a lambda in a function scope had caused an assertion failure in
lower_name.c (in call_operator_function_type_for_lambda).  This has now been
fixed.  For example:

  void f() {
     [](){};
  }


10/26/09 [EDGcpfe/10162]
GNU compatibility: asm names and attribute "alias"

In GNU modes, the front end accepts an attribute "alias" that refers to an asm
name.  However, if a function or variable name appeared both as a regular name
and as an asm name, the alias was previously resolved to the entity with the
asm name.  This could later trigger warnings or errors if that entity did not
have a definition.  Now, the alias resolution method gives precedence to the
entity with a definition.  For example (GNU C mode):

  void renamed() __asm("f");  // (1): "f" as an asm name.
  void f() {}                 // (2): "f" as an ordinary name.
  void alt() __attribute((alias("f")));
                              // Previously resolved to (1), which triggered
                              // a warning or error because "renamed" has no
                              // definition.  Now, resolves to (2).


10/23/09 [EDGcpfe/10107]
New configuration macro to specify size of an IA-64 vtable entry

In nearly all cases, the sizes of the types of entities that are stored in an
IA-64 vtable (i.e., offsets, pointers to type_info, pointers to virtual
function) are identical; therefore the internal representation of a vtable in
the front end is an array of homogeneous entities (previously of the type
specified by the integer kind TARG_PTRDIFF_T_INT_KIND).  To better accommodate
an architecture where the size of an offset (ptrdiff_t) is smaller than the
size of a pointer, a new configuration macro TARG_IA64_VTABLE_ENTRY_INT_KIND
has been introduced that allows more control over the size of an IA-64 vtable
entry.  See the description of TARG_IA64_VTABLE_ENTRY_INT_KIND in targ_def.h
for more information.

Also defines a corresponding macro __EDG_IA64_VTABLE_ENTRY_TYPE that is passed
to the runtime library when --building_runtime is used.  When changing the
value of this macro, the runtime library must be recompiled.


10/22/09 [EDGcpfe/10166]
Microsoft C++ compatibility: spurious error with ADL in version 4.1

The change made for the 1/21/09 entry (which is part of version 4.1) resulted
in an incorrect argument-dependent lookup for cases in which the normal
lookup returned a symbol from a using-directive lookup.  Now fixed.

  struct A {};
  void f(A);
  namespace N {
    namespace {
      struct B {};
      template <typename T> void f(B);
    }
   void B(A a) { f(a); }  // f(A) not found by this call
  }


10/22/09 [EDGcpfe/10164]
Typo in prep_reference_initializer_operand could lead to spurious errors

A typo in prep_reference_initializer_operand in overload.c caused operands
to be overwritten with error operands (without issuing an error), leading
to spurious errors being reported by lowering (or potentially a back end).
The problem occurs only in some old and anachronism modes.  This regression
was introduced in 4.1 and is now fixed.  For example:

  struct A {};
  A& a = A();   // when allowed (as an anachronism) a warning is issued and
                // operand may be mistakenly overwritten by an error operand


10/21/09 [EDGcpfe/10160]
Related class cast incorrectly treated as reinterpret_cast in g++ mode

The change of 3/24/09 introduced a regression in g++ mode.  A cast
to a base or derived class was incorrectly treated as, effectively,
a reinterpret_cast (one that would not adjust the pointer to deal
with the base-derived class offset).  This problem existed only
when gnu_version is less than 30400.  Now fixed.

  struct B1 {
    int i;
  };
  struct B2 {
    int i;
  };
  struct D : B1, B2 { };
  int main() {
    D d;
    D *pd = &d;
    B2 *p = (B2 *)pd;  // Incorrect cast generated
  }


10/18/09 [EDGcpfe/10062]
Clearer diagnostic on invalid call

The diagnostic that the expression preceding the parentheses of what
appears to be a call does not have pointer-to-function type has been
clarified.


10/16/09 [EDGcpfe/10157]
GNU C++ mode parsing of unevaluated operands of "?" within template argument

In GNU C++ mode, the parsing of unevaluated operands of a "?" operator
inside parentheses inside a nontype template argument could sometimes
incorrectly group the operands of the expression because of a confusion
about whether a ">" operator should close the template argument (it
shouldn't).  Now fixed.

  template <int Value> struct thing { enum { v = Value }; };
  int bar (){
    return thing <(3 > 2 ? 4 : 3 > 1 ? 2 : 1)> ().v;  // Should be 4, was 2
  }


10/16/09 [EDGcpfe/10154]
Deduction of rvalue reference parameter when argument is a function

The processing for the special "perfect forwarding" template deduction
trick, which allows a template with a parameter of type "T&&" to bind to
an lvalue argument by deducing T as an lvalue reference, did not work
correctly when the argument is a function lvalue.  Now fixed.

  template<class T> void test(T&& r);
  void f();
  int main() {
    int i;
    test(i);  // Previously accepted (non-function lvalue)
    test(f);  // Previously rejected, now accepted as well
  }


10/15/09 [EDGcpfe/10126]
Pseudo-destructor called on array type

Other compilers, including Microsoft and GNU, allow a pseudo-destructor call
in which the destructor type (e.g. ~T) is an array type but the type of the
object is a pointer.  We now allow such usage except in strict mode.

  template <typename T > struct A {
    void f(void) {
      m[0].~T();  // now allowed
    }
    T* m;
  };
  int main() {
    A<float[4]> afloat;
    afloat.f();
  }


10/15/09 [EDGcpfe/10115]
GNU array mem-initializers

g++ allows constructor mem-initializers for array members to have non-empty
initializers if the member is an array of a class type with a copy
constructor.  We now emulate that in g++ mode.

  struct A {
    A();
    A(const A&);
  };
  struct B {
    A arr[2];
    B(const B&p) : arr(p.arr) {}  // Now allowed in GNU C++ mode
  };


10/13/09 [EDGcpfe/10120]
GNU C++ compatibility: internal error on typeof a template static data member

An internal error (in complete_template_static_data_member_type_is_needed)
could occur when a GNU __typeof was used to determine the type of a
template static data member of the current class.  Now fixed.

  template <int i> struct C { };
  template <int i> struct D {
    static C<2> myc;
    void f(__typeof(myc) c);
  };
  D<2> d;


10/12/09 [EDGcpfe/7570,EDGcpfe/9679,EDGcpfe/9968]
Extra spaces between tokens in preprocessor output

In order to ensure that preprocessor output (the result of the -E and
related command-line options) has the same meaning as the original input,
the front end inserts extra spaces to separate tokens that should not be
combined.  For example,

  #define M(x) -x
  int f(int i) {
    return M(-)i;   // output is "return - -i", not "return --i"
  }

However, the front end is sometimes used to preprocess arbitrary text that
is not C/C++, and in such cases it may insert spaces that make the result
unusable for its intended purpose.  To facilitate such uses, the front end
now accepts the --no_token_separators_in_pp_output command-line option to
suppress all such extra spaces (white space from the source that occurs in
macro expansions is normalized to a single space character).


10/12/09 [EDGcpfe/10106]
Ambiguity on explicit specialization that matches with or without reference

A spurious ambiguity was reported in an explicit specialization that matched
two function templates, one in which types matched exactly (A& vs. T& in the
example below) and one in which the reference was part of the deduced
type below (A& vs. T in the example below).  We now accept this example:

  struct A { 
    template <class T> A(T);
    template <class T> A(T&);
  }; 

  template<> inline A::A(A &) { } 


10/7/09  [EDGcpfe/9955]
Preprocessing output of #pragma directives followed by multi-line comments

A #pragma directive in which the end of its physical source line occurs
within a multi-line comment was not correctly copied to the preprocessing
output file (with the -E and related command-line options).  For example,
given the file

  #pragma once  /* ensure that this file
                   is only included once */

the -E output was

                   is only included once */

This has now been fixed and correctly produces the preprocessing output

  #pragma once


10/6/09  [EDGcpfe/10138]
Missing destructor calls in some cases when using the IA-64 ABI

In IA-64 ABI configurations where both
HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS and
IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS are TRUE, and exception handling
is disabled, the code generated by lowering for a complete destructor of a
class with a virtual base was incorrect.  The generated code mistakenly omitted
calls to destroy any virtual bases.  This regression was introduced in 4.1
and is now fixed.  For example:

  int result = 1;
  struct B {
    ~B() {
      result = 0;
    }
  };
  struct D : virtual B {
    ~D() {}
  };
  int main() {
    { D d; }          // D::B mistakenly not destroyed
    return result;    // had returned 1, now 0
  }


10/6/09  [EDGcpfe/9593]
GNU compatibility: static_cast to pointer to cv-qualified derived class

In versions 3.4 through at least 4.4 of g++, there is a bug such that
using static_cast to convert a pointer to a cv-unqualified base class into
a pointer to a cv-qualified derived class drops the cv-qualification from
the result type.  The front end now emulates this bug in g++ mode when
gnu_version is >= 30400.  For example:

  struct B { };
  struct D: B { };
  D* g(B* p) {
    return static_cast<const D*>(p);  // Now accepted in newer g++ modes
  }


9/29/09  [EDGcpfe/8555]
GNU C99 inlining modes

In C99, an "inline" function definition that is not declared with a storage
class like "extern" or "static" is used only for inlining: No linkable version
is emitted.  If, however, the function is declared with "extern" then an
externally linkable copy is emitted.  Before C99 came along, GNU C89 supported
a similar inlining model with the opposite convention: "extern" indicates that
the function should not be emitted with external linkage.

Early versions of GCC followed the GNU C89 convention even in C99 mode, but
starting with GCC 4.3, the standard C99 convention is followed (in C99 mode,
not in the default C89 mode).  We now emulate that behavior when gnu_version
>= 40300.

GCC also provides some transition aids that we emulate.  First, a command-line
option (ours is "--gcc89_inlining") is available to force the GNU C89 rules
for "inline".  Second, an attribute "gnu_inline" allows the GNU C89 rules to
be enforced on specific functions.  For example:

  __attribute((gnu_inline)) extern inline void g() {}
    // No copy of g is emitted for external linkage, even when
    // gnu_version >= 40300.
  int main() {
    g();
  }

(Our implementation of this attribute is slightly more permissive that GCC's
in that GCC requires the attribute on every declaration of a specific function,
while we only require it on the first declaration of the function.)

Finally, when gnu_version >= 40103, the macro __GNUC_GNU_INLINE__ is
predefined to "1" if the GNU C89 rules are in effect, or the macro
__GNUC_STDC_INLINE__ is predefined to "1" if the standard C99 rules are in
effect.


9/29/09  [EDGcpfe/10130]
Constant field selection in non-constant expression in Microsoft mode

To emulate MSVC++, the front end in Microsoft mode now treats an
expression like x.k, where k is a member constant (such as an enumerator),
as a constant in non-constant expressions also.  It was already treated
as a constant in constant expressions.

  struct I {
    enum {e = 1};
  };
  struct C {
    void foo();
    I i;
  };
  void C::foo() {
    const int elem = i.e;
    int arr[elem];  // Now accepted; elem is a constant-valued variable
  }

Similarly, x.v, where v is a const static data member, is now also folded
to a constant in non-constant expressions in Microsoft mode.


9/28/09  [EDGcpfe/10121]
Assertion failure in add_discriminator in IA-64 ABI configurations

In IA-64 ABI configurations where ABI_COMPATIBILITY_VERSION < 401,
the mangling of certain names (e.g., a nested class name in a local class)
could result in an assertion failure in lower_name.c (in add_discriminator).
This regression was introduced in 4.1 and is now fixed.  For example:

  void f(void) {
    struct A {
      struct B {};  // had caused an assertion failure in add_discriminator
    };
  }


9/25/09  [EDGcpfe/10123]
Source sequence entries with IL lowering

Ordinarily, source sequence entries cannot be enabled when IL lowering is
done, because that's sort of useless; IL lowering doesn't maintain them
properly.  For those who really want that anyway, there has been a
special "trust me, I know what I'm doing" flag called
ALLOW_SOURCE_SEQUENCE_LISTS_WITH_IL_LOWERING.  However, as of version
4.0, that merely allows the feature to be compiled in; the generation
of source sequence entries is still suppressed when IL lowering will
be done.  To go one step further to "trust me, I really know what I'm
doing", we've now added another flag,
PRESERVE_SOURCE_SEQUENCE_LISTS_WITH_IL_LOWERING, which allows the
source sequence entries to be generated and then preserves them
in IL lowering.  This is still not recommended, but now those who
really want to do it have a way of requesting it.


9/24/09  [EDGcpfe/10074]
Sun mode: copy constructors better than other functions

Sun C++ mode now favors copy constructors over other kinds of functions in
some cases in overload resolution.  This reflects some fuzziness in
the Sun compiler's implementation of copy-initialization versus
direct-initialization.

  struct A {
    A(const A &);
    A(char);
  };
  struct B {
    B(const B &);
    B(char);
    operator char () const;
    operator A () const;
  };
  int main() {
    A a = (char)1;
    B b = (char)2;
    a = (A)b;  // Ambiguous, but now accepted in Sun mode
  }


9/22/09  [EDGcpfe/9513,EDGcpfe/9590,EDGcpfe/10105]
GNU C compatibility: Undefined static functions

Ordinarily, referencing a static function that is not defined results in a
compile-time error (since such a reference cannot normally be resolved).  Now,
in GNU C mode, such references cause the static function to be given external
linkage instead (i.e., as if the function had been declared "extern") and a
warning is issued.  For example:

  /* f.c */
  void f() {}

  /* main.c */
  static void f();
  int main() {
    f();      /* Resolves to the f() defined in f.c. */
    return 0;
  }

Static aliases (declared with the GNU attribute "alias") are now also treated
differently: No diagnostic is issued when they are undefined (and the linkage
of the alias remains internal).  For example:

  static void f() __attribute((alias("xx")));
            /* Now accepted (without a diagnostic). */
  int main() {
    f();
  }


9/17/09  [EDGcpfe/10110]
Parameter names are always recorded (RECORD_NAME_IN_PARAM_TYPE_ENTRY removed)

Previously, the configuration macro RECORD_NAME_IN_PARAM_TYPE_ENTRY determined
whether parameter names were recorded in nondefining function declarations.
Now, that macro has been dropped and the behavior is as when the macro was
TRUE: Parameter names are always recorded.


9/17/09  [EDGcpfe/10089]
Template conversion function to const type to initialize reference to const

A template conversion function that returns a const-qualified type is
now considered usable for a conversion in the initializer of a
reference to const:

  template <class T> struct A {};
  struct B {
    template <class U> operator const A<U>();
  };
  void foo() {
    B b;
    const A<int> &e = b;
  }


9/16/09  [EDGcpfe/10104]
Microsoft compatibility: pointer and false as operands of "?"

As noted in the 2/6/05 entry, MSVC++ accepts a pointer/pointer to member
and a bool as the second and third operands of a "?" operator, and the
front end does as well in Microsoft bugs mode.  Generally, this construct
has type bool.  When the bool operand has the constant value "false,"
however, MSVC++ interprets it as a null pointer constant and the result
type is that of the pointer/pointer to member operand.  The front end
failed to emulate this special case but has now been changed to do so.  For
example:

  int* f(int* p, bool b) {
    return b ? p : false;   // Expression now has type int*, not bool
  }


9/16/09  [EDGcpfe/10082]
Internal error on template overloaded with using-declaration

In modes that do prototype instantiations of templates, a call of a
name that corresponded to a template overloaded with a using-declaration
resulted in an abort in scan_identifier in expr.c.  Now fixed.

  template<class T>
  struct A {
    void f(int);
  };
  template<class T> struct C : public A<T> {
    template<int x> void f() {
      f(1);
    }
    using A<T>::f;
  };
  int main() {
    C<int> c;
    c.f<1>();
  }


9/16/09  [EDGcpfe/10059]
Internal error on deduced type with unevaluated template default arguments

An internal error (in instantiate_default_arguments_of_template_matching)
could occur in modes in which nonstandard default argument deduction
is done (e.g., g++ mode and Microsoft mode for some microsoft_version values)
if a deduced type contained unevaluated template default arguments.
This was addressed previously in the change of 11/1/07; this change deals
specifically with cases that involve non-template static members of
class templates, which were not properly addressed by the previous
change.

  template <typename T> struct A {
    static void f(int i = 1);
  };
  template <typename F> inline void g(F func) {
    func();
  }
  int main() {
    g(&A<int>::f);
  }

As part of this change, this nonstandard feature has now been turned off
in g++ mode for gnu_version >= 40300.  It was and remains turned off
in Microsoft mode with microsoft_version >= 1310.


9/15/09  [EDGcpfe/10096]
GNU compatibility: mangling of array bounds as expressions

Early versions of g++ incorrectly mangled array bounds as expressions in some
contexts and we emulated that behavior when emulate_gnu_abi_bugs was TRUE.  The
bug has since been fixed by GNU (in version 3.4.0), so emulation of this bug is
no longer performed when gnu_version >= 30400 (and emulate_gnu_abi_bugs is
TRUE).  For example:

  template <int I> void f(int (&)[I + 1][3]) {}
  void f1() {
    int y[3][3];
    f<2>(y);  // now _Z1fILi2EEvRAplT_Li1E_A3_i when gnu_version >= 30400
              // and emulate_gnu_abi_bugs is TRUE
              // (had been _Z1fILi2EEvRAplT_Li1E_ALi3E_i)
  }


9/15/09  [EDGcpfe/10094]
GNU compatibility: mangling of template parameter as a parent

Early versions of g++ used an incorrect mangling of template parameters when
used as parents and we emulated that behavior when emulate_gnu_abi_bugs is
TRUE.  The bug has since been fixed by GNU (in version 3.4.0), so 
emulation of this bug is no longer performed when gnu_version >= 30400
(and emulate_gnu_abi_bugs is TRUE).  For example:

  struct A {
    struct B {};
  };
  template <class T> void f(typename T::B) {}
  void f() {
    A::B ab;
    f<A>(ab); // now _Z1fI1AEvNT_1BE when gnu_version >= 30400 and
              // emulate_gnu_abi_bugs is TRUE (had been _Z1fI1AEvN1T1BE)
  }


9/15/09  [EDGcpfe/10035]
GNU compatibility, C++-generating back end: template argument lists for
explicit specializations

The C++-generating back end suppressed template argument lists in
references to an instance of a function template in the generated code if
the source code never referred to that instance using an explicit template
argument list.  This suppression also applied to declarations and
definitions of generated explicit specializations in configurations in
which NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is set to
TRUE.  Recent versions of g++, however, have a bug that results in spurious
errors under certain obscure circumstances if the template argument list is
omitted from the declaration or definition of an explicit specialization of
a function template.  The C++-generating back end has now been changed to
generate the template argument list unconditionally in such declarations
and definitions when gcc_is_generated_code_target is TRUE.


9/15/09  [EDGcpfe/9739]
Microsoft and GNU C++ compatibility: partial ordering and functions

The Microsoft and g++ compilers consider a pointer to function to be
compatible with a reference to function for partial ordering purposes.
As a result, they accept examples like the one below instead of reporting
an ambiguity.  We now emulate this behavior in Microsoft and g++ mode (when
gnu_version is >= 40100).

  template <typename T> void f(T** p, void (*)()); // #1
  template <typename T> void f(T* p, void (&)());  // #2
  void x(){}
  void g(int** p) {
    f(p, x);  // calls #1
  }


9/15/09  [EDGcpfe/10086]
GNU compatibility, C- and C++-generating back ends: extended asm syntax

The C- and C++-generating back ends failed to preserve the GNU extended asm
syntax for instructions with no operands and no clobbers.  This is now
fixed.  For example:

  void f() {
    asm("xorps %%xmm0,%%xmm0" : :);  // Previously generated as
                                     // asm("xorps %%xmm0,%%xmm0");


9/14/09  [EDGcpfe/8623, EDGcpfe/9926]
C++0x: nullptr keyword

In C++0x mode and in Microsoft C++ mode with microsoft_version >= 1600, the
front end now accepts the "nullptr" keyword as a null pointer constant.
This feature was added to the C++0x working paper by document N2431,
adopted at the October, 2007 (Kona) meeting and was modified by document
N2656, approved at the June, 2008 (Sophia Antipolis) meeting.


9/11/09  [EDGcpfe/10075]
Template constructors with first argument same as the class

Template constructors that, after deduction, have a first parameter
that is the same type as the constructor's class now cause a deduction
failure.  More specifically, they have to have exactly one argument,
or, if they have default arguments, those default arguments must not
be used in the call being deduced.

  struct A {
    A(int) {}
    template <class T> A(T);  // With T=A, deduction fails
    template <class T> A(T&);
  };
  int main() {
    A a(37);
    A b = a;  // Was ambiguous, now selects A(T&)
  }

9/11/09  [EDGcpfe/10083]
GNU compatibility: IA-64 mangling of non-dependent pointer to member
template parameters

Early versions of g++ (3.3 and earlier) had mangled a reference to a
non-dependent pointer to member in a template parameter incorrectly and
we emulated that behavior when emulate_gnu_abi_bugs was TRUE.  The g++ bug
has since been fixed (when -fabi-version is 2 or later -- the default in
version 3.4.0), so a change has been made to emulate this bug only when
gnu_abi_version is less than 30400 (and emulate_gnu_abi_bugs is TRUE).
For example (when gnu_abi_version >= 30400 and emulate_gnu_abi_bugs is TRUE):

  struct A {
    int i;
    void f(void);
  };
  template <int A::*p> void g(void) {}
  template <void (A::*)(void)> void h(void) {}
  int main() {
    g<&A::i>(); // was _Z1gIXadsr1ANS0_1iEEEvv  now _Z1gIXadL_ZN1A1iEEEEvv
    h<&A::f>(); // was _Z1hIXadsr1ANS0_1fEvEEvv now _Z1hIXadL_ZN1A1fEvEEEvv
  }


9/10/09  [EDGcpfe/10081]
GNU compatibility: Additional built-in IA-32 vector functions

To improve compatibility with GCC 4.4, the front end now predeclares the
following new functions in GNU C and C++ modes: __builtin__ia32_psllwi,
__builtin__ia32_pslldi, __builtin__ia32_psllqi, __builtin__ia32_psrlwi,
__builtin__ia32_psrldi, __builtin__ia32_psrlqi, __builtin__ia32_psrawi, and
__builtin__ia32_psradi.  The types of the corresponding functions without the
trailing "i" in their names (e.g., __builtin_ia32_psllw) have also been
adjusted to reflect the types used in GCC 4.4 (when gnu_version >= 40400).
Similarly, a new function __builtin_ia32_movq128 is now predeclared, and the
types of the functions __builtin_ia32_addq and __builtin_ia32_addq is
adjusted when gnu_version >= 40400.

Taken together, these changes allow the front end to compile the headers
"mmintrin.h" and "xmmintrin.h" that come with GCC 4.4 (except that
"xmmintrin.h" contains a typedef that is invalid in C++ mode).


9/9/09   [EDGcpfe/10078, EDGcpfe/10080]
Microsoft and GNU C++ compatibility: nonstandard template friend declarations

Microsoft and g++ allow template friend class declarations that refer to a
member of the current template class but that do not specify the enclosing
class' template parameter lists in the friend declaration as required by the
standard.   We now accept such declarations in Microsoft and g++ modes.

  template <class T> struct A {
    template <int i> class B;
    template <int i> friend class B;
    // should be:
    // template <class T> template <bool b> friend class C<T>::Foo;
  };
  int main() {
    A<int> a;
  }


9/9/09   [EDGcpfe/10073]
Spurious error on constructor with template-dependent const field

In some C++ modes, including strict mode and some GNU C++ modes, the front end
sometimes issued a spurious error on a constructor that did not explicitly
initialize a template-dependent const field.  For example:

  template<class T> struct S {
    S() {}      // Previously, a spurious error was issued in strict mode
    T const x;  // because x was not explicitly initialized.
  };

This is now fixed (i.e., such cases are now accepted in all modes).


9/9/09   [EDGcpfe/10071,EDGcpfe/10076]
GNU compatibility: Operand and result types for calls to __sync_... functions

In GNU modes, the front end accepts various built-in functions for atomic
memory access when the configuration macro GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED
is TRUE (see Changes entry of 7/31/07).  Previously, only operands of integral
and enumeration types were acceptable when calling these functions.  Now
pointer types are also acceptable operand types (such operands are cast to the
integers prior to the call), and the result of such a call is adjusted to
produce a pointer type (since the underlying routine produces an integer type).
For example:

  void *f(void **ptr, void *oldval, void *newval) {
    return __sync_val_compare_and_swap(ptr, oldval, newval);
      /* Now accepted in GCC mode. */
  }

9/7/09   [EDGcpfe/10077]
GNU compatibility: static initialization using compound literal lvalues

Version 4.0 inadvertently disabled the change described in the 11/8/06
entry, in which lvalues referring to compound literals are considered to
be constant values.  This regression has now been fixed.


9/3/09   [EDGcpfe/9951]
Incorrect conversion of multibyte file names from command-line on Windows

File names specified on the command-line using native multibyte characters
(when NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is TRUE on Windows)
were not converted properly.  This would result in spurious errors opening
files.  Now fixed.

9/2/09   [EDGcpfe/10058]
Infinite loop on classes that convert to each other

The front end could get into a recursion loop that eventually would
cause an abort when the stack is exhausted, on a case involving classes
that can convert to each other.  This is an additional case of the
problem resolved by the Changes entry of 4/10/02.  Now fixed.

  struct A;
  struct B {
    B(const A&);
    B(B&);
  };
  struct A {
    A(B);
  };
  B func(const B& b) {
    return b;  // Stack overflow here
  }


9/1/09   [EDGcpfe/9894]
GNU: Emulate missing underscore in IA-64 mangling of template arguments

In GNU version 3.4.0, a regression was introduced where an underscore in the
mangling of a reference to an external name when used as a template argument
was omitted.  This defect was resolved in g++ 4.0, but only when -fabi-version
is set to version 3 (or later) -- the default abi version as of this writing is
still 2.  We now emulate this behavior in GNU emulation mode (when
gnu_abi_version >= 30400 and emulate_gnu_abi_bugs is TRUE).  The old
behavior is preserved when ABI_COMPATIBILITY_VERSION is less than 402.  For
example:

  template <int& I, void (&p)(void)> struct A {};
  int x;
  void f(void) {}
  A<x, f> a; // now produces _Z1AILZ1xELZ1fvEE when gnu_abi_version >= 30400
             // and emulate_gnu_abi_bugs is TRUE, _Z1AIL_Z1xEL_Z1fvEE otherwise


8/31/09  [EDGcpfe/9054]
GNU: invalid IL when inlining routine with address-of-label GNU extension

Inlining a routine that contains a GNU address-of-label extension caused
invalid IL to be generated (causing an IL write-read abort in some
configurations).  To fix this, routines that contain a label whose address has
been taken are no longer candidates for inlining.  For example:

  static inline void *f(void) {
  here:;
    return &&here;  // had aborted, now won't be inlined
  }
  void g(void) {
    f();
  }


8/31/09  [EDGcpfe/9039]
Abort when lowering destructors with function try block

Lowering a destructor with a function try block containing a return statement
that has an associated pragma caused an IL write-read assertion failure in
configurations where DO_FULL_PORTABLE_EH_LOWERING is TRUE and exception
handling is enabled.  This is now fixed.  For example:

  struct A {
    ~A() try {
#pragma foo
      return;    // caused an IL write-read difference in some configurations
    } catch (...) {
    }
  } a;


8/31/09  [EDGcpfe/9543, EDGcpfe/9895]
Incorrect IA-64 ABI mangling for some template arguments

The IA-64 ABI mangling produced for template arguments that are internally
represented as a ck_address to a reference type was incorrect.  Such
constructs had been mangled as though they were expressions (i.e., using
"X...E" delimiters).  For backwards compatibility, the previous behavior
is preserved when ABI_COMPATIBILITY_VERSION is less than 402 and also when
emulating GNU versions earlier than 3.4 (when emulate_gnu_abi_bugs is TRUE).
For example:

  template <int& I> struct A {
    A() {}
  };
  int x;
  A<x> a;   // A<x> had been mangled as _Z1AIXL_Z1xEEE, now _Z1AIL_Z1xEE


8/31/09  [EDGcpfe/10061]
Internal error on invalid template declaration

Certain invalid template declarations could result in an internal error
in map_token_numbers_to_cache_pointers.  Now fixed.

  template <typename T> void func(int n =


8/28/09  [EDGcpfe/8832]
Update defines.h.linux to build 32 bit target on 64 bit host

A change has been made to the defines.h.linux sample configuration file to
enable simplified building of a 32 bit target configuration on a 64 bit Linux
host.  To build such a configuration, simply set the configuration macro
USE_X86_64 to FALSE.


8/28/09  [EDGcpfe/9982]
Utility function to identify pointer operations with "restrict" semantics

A new utility routine node_is_pointer_with_restrict_semantics has been added
to assist those dealing with the aliasing implications of the "restrict"
qualifier in back ends.  Given an expression node that is a pointer
(e.g., the operand of an eok_indirect), it returns TRUE if the referenced
entity should be considered to be unaliased because of "restrict".


8/28/09  [EDGcpfe/10048]
Lowering of operation type_kinds

As a result of the expression changes introduced in 4.0 (see the Changes entry
of 8/19/08), operations now have an associated type_kind field (that specifies
the kind of type the operation acts on).  While this field was correctly
lowered for operations involving the eok_assign operator, other operators, as
well as any assignments generated during the lowering process (e.g., when
introducing a temporary variable), were left in their un-lowered form, causing
back ends to see tk_fixed_point, tk_complex, and tk_ptr_to_member type_kinds.
This is now fixed.  For example:

  void f() {
    _Complex double x;
    x += x;
  }


8/27/09  [EDGcpfe/10056]
Microsoft C++ compatibility: abort on specialization of nested class

An abort could occur (in push_simple_instantiation_scope) on a specialization
of a nested class of a class template.  The abort occurred in Microsoft
mode with microsoft_version <= 1300 when the nested class was declared but
not defined in the template.  Now fixed.

  template <class T> class A {
    class B;
  };
  class A<int>::B {};


8/26/09  [EDGcpfe/10041]
reinterpret_cast of pointer-to-function to pointer-to-pointer allowed again

As part of the change of 3/25/09 in version 4.1 to fix the handling of
casts of functions to reference-to-object, we introduced a limitation
that a function cannot be cast to a reference-to-pointer.  This was
necessitated by an IL representation limitation that causes problems in
distinguishing such a cast from a cast of a function to a
reference-to-function, and we chose to prohibit a very unusual (and
conditionally-supported) cast to avoid the problem with the more
common cast.  Unfortunately, while doing so we also prohibited casting a
pointer-to-function to a pointer-to-pointer, which we also thought was
very unlikely to turn up in programs.  We've now been sent some code
that compiles with the Microsoft compiler that uses such a cast, so
we've reinstated the pointer case while still prohibiting the
reference case.

  void f();
  int main() {
    (void (*&)())f;   // Still disallowed
    (void **)&f;      // Allowed once again
  }


8/26/09  [EDGcpfe/10031]
Multiplication added for variable-sized array new marked as compiler-generated

The eok_multiply operation added by the front end to multiply the bound
of a variable-sized array new by the element size is now marked with
the compiler-generated flag.

  void f(int param) {
    int *s = new int[param+1];
  }


8/25/09  [EDGcpfe/10052]
Optimization of virtual function calls with default arguments

The fix for the bug described in the 2/20/08 entry, in which default
arguments were ignored when a virtual function call was optimized to be
non-virtual, was inadvertently disabled in the released version 4.0.  This
regression has now been fixed.


8/25/09  [EDGcpfe/8366]
GNU C++ compatibility: passing packed field to reference to const parameter

g++, from version 3.4 on, uses a temporary when a reference to a field
declared "packed" is passed to a parameter that is a reference to const type.
This ensures that the reference is not an unaligned pointer and mostly
preserves the standard semantics.  Now, in g++ mode we do the same.
Reference bindings outside of calls are unaffected.

  int x;
  void ConstRef (const int &p) { x = p; }
  struct  __attribute__ ((packed)) Packed {
    char c;
    int i;
  };
  Packed p = {0, 1};
  int main () {
    ConstRef (p.i);  // Copies p.i to a temporary and passes that
  }

[ Update: Original wording said "reference to nonconst" instead of "reference
to const".  See also the more recent entry for EDGcpfe/14508. ]


8/25/09  [EDGcpfe/9163]
C++0x: Trailing return types

In C++0x mode and in Microsoft C++ mode with microsoft_version >= 1600, the
front end now accepts "trailing return types" in function declarators
following an "auto" type specifier.  For example:

  auto f()->int;  // Same as int f();

This change was voted into the C++ committee's working paper for the next
standard in February 2008 (meeting in Bellevue, through proposal numbered
N2541).  A change to that proposal was made through Core issue 681, resolved
by N2757, which was voted into the working paper in September 2008 (meeting in
San Francisco).

The C++ committee is still considering an alternative syntax for this feature;
e.g., the "auto" type specifier might get changed to something else.


8/25/09  [EDGcpfe/10047]
Microsoft compatibility: default Microsoft version changed

The default Microsoft version number (specified by DEFAULT_MICROSOFT_VERSION)
is now 1400.  This corresponds to the value of _MSC_VER used with Visual
C++ 8.0.


8/25/09  [EDGcpfe/8583]
Incorrect IL generated for ::delete and deleting destructors

In cases where ::delete is called on a base class object with a virtual
destructor and a user declared operator delete, the pointer to the base
class object was being passed to ::delete instead of a pointer to the most
derived object.  This had resulted in a runtime abort in most configurations
and is now fixed (except in configurations where ABI_CHANGES_FOR_RTTI is
FALSE where the behavior is unchanged).  For example:

  struct B {
    B() {}
    virtual ~B() {}
    int x;
    void operator delete(void *) {}
  };
  struct D : virtual B {
    D() {}
    virtual ~D() {}
    int y;
  };
  int main (void) {
    B *b = ::new D;
    ::delete b;   // had deleted an incorrect pointer causing a runtime abort
  }


8/24/09  [EDGcpfe/7780]
Spurious error on redeclaration of partial specialization

Most class members may not be redeclared outside of their class, but this is
not the case for partial specializations.  We no longer issue an error for
such usage.

  template <class T> struct A {
    template<class T1> struct B {};
    template <class T1> struct B<T1*>;
  };
  // Spurious redeclaration error on next line
  template <class T>  template <class T1> struct A<T>::B<T1*>;


8/24/09  [EDGcpfe/9424]
GNU C++ compatibility: mangling of function pointer types declared with
noreturn or volatile attributes

In g++ version 4.0 and later, function pointer types with the noreturn or
volatile attribute are mangled as though the routine pointed to is volatile.
The front end now mimics this behavior in GNU emulation mode.  For example:

  typedef int (*vfp) (int*) __attribute__((volatile));
  typedef int (*nfp) (int*) __attribute__((noreturn));
  void f(vfp, nfp);
  int main() {
    vfp vp = 0;
    nfp np = 0;
    f(vp, np);   // now mangled as: _Z1fPVFiPiES2_ (had been _Z1fPFiPiES1_)
    return 0;
  }


8/20/09  [EDGcpfe/10019]
Invalid definition of macro DSI_LAST

The macro DSI_LAST, defined in decl_spec.h, was erroneously defined in terms
of an undefined identifier DSI_TRAILING_RETURN_TYPE.  This is now fixed.


8/19/09  [EDGcpfe/9973]
Spurious ambiguity with built-in operator and multiple conversion functions

Overload resolution gave a spurious ambiguity error when processing
a built-in operator with class operands when the class of the second
operand has multiple conversion functions that return essentially the
same type (this is possible when one returns a type T and the other
returns T&), and the type returned is not one that is returned by
any conversion function for the class type of the first operand.
Now fixed.

  struct A { };
  struct B {
    operator A*&();
    operator A*() const;
  };
  struct B_const {
    operator const A*() const;
    operator const A*&();
  };
  struct C: B_const { };
  bool f(const B& d1, C& d2) {
    return d1 == d2;  // Formerly got ambiguity error
  }


8/18/09  [EDGcpfe/10016]
Binding rvalue reference to lvalue in overload resolution

Overload resolution did not deal correctly with a case where an rvalue
reference parameter is matched against an lvalue argument.  It mistakenly
considered that a match if the argument type did not match the underlying
type of the rvalue reference but could be converted to it.  Now fixed.

  void foo(long&&);
  void foo(const long&);
  int main() {
    int n = 1;
    foo(n);  // Should match foo(const long &), but foo(long &&) was allowed
             // and considered a better match, which then provoked an error.
  }


8/18/09  [EDGcpfe/10025]
Trimming of string literals in aggregate initializers in GNU C mode

In C mode, string literals are stripped of the terminating null character if
that character wouldn't fit in the destination type.  In some GNU C cases
involving aggregate initializers, this trimming was not performed.
For example:

  struct { char a[3]; } sa[2] = { "xxx", "yyy" };
    /* Previously, "xxx" and "yyy" had length 4 in GNU C mode; now they
       have length 3. */

This is now fixed.

Also, similar GNU C situations with string literals that were too long (by
more than the terminating null character) were not diagnosed and the overlong
literals were not trimmed.  This too is now fixed: A warning is issued and the
IL representation of the string literal is trimmed to the length of the
destination type.  For example:

  struct { char a[3]; } sb[2] = { "xxxxxx", "yyyyyy" };
    /* Accepted in GNU C mode.  Previously, no diagnostic was issued and
       the IL did not reflect the required truncation of the string
       literals. */


8/17/09  [EDGcpfe/9834]
Severity of ambiguous class member reference diagnostic in strict mode

Certain ambiguous class member references were issued as warnings
instead of as strict ANSI diagnostics (warning or error depending on
mode) in strict mode.  Now fixed.

  template <class T> class A {};
  struct B {
    template <typename T> void A(T);
  };
  int main() {
    B b;
    b.A<int>(0);  // now strict ANSI diagnostic
  }


8/17/09  [EDGcpfe/9961]
Lookup in template instantiations in default mode

When the C++98 standard was issued, the lookup rules for templates were
different than those supported by most compilers at the time.  To provide
better compatibility with those compilers our default mode used nonstandard
lookup rules that were part of the C++98 working paper for some time during
the development of the standard.  In this mode, names were looked up in
both the namespace of the template definition and in the namespace in which
a template entity was first referenced in a way that would require an
instantiation.  We have gradually been phasing out the use of these
rules; they are no longer used in g++, Microsoft or Sun modes.  We have
now disabled these lookup rules by default in default mode.  The default
behavior is controlled by the DEFAULT_NONSTANDARD_INSTANTIATION_LOOKUP
macro.  The default behavior can be overridden by the new command-line
options --[no_]nonstd_instantiation_lookup.  Formerly, the example below
printed "in ::f(int)" in default mode.  It now prints "in N::f(float").


  #include <stdio.h>
  namespace N {
    void f(float){printf("in N::f(float)\n");}
    template<class T> void g(T) {
      f(2);
    }
  }
  void f(int){printf("in ::f(int)\n");}
  int main(void) {
     N::g(1);
  }


8/17/09  [EDGcpfe/9415,EDGcpfe/10021]
Pure specifier ("= 0") in templates

In Microsoft, GNU, and Sun modes, the front end now accepts the "= 0" specifier
following a member function declaration of a class template even when the
function is certain not to be virtual.  For example:

  template<typename T> struct S {
    void f() = 0;  // Now silently accepted in GNU, Microsoft, and Sun C++
  };               // modes.  An error is issued if the template is
                   // instantiated.

Similarly, in Microsoft mode and in GNU mode with gnu_version < 40200 a member
function template can be followed by "= 0": No diagnostic is issued until the
template is instantiated.

  struct X {
    template<typename> void f() = 0;  // Now silently accepted in Microsoft
  };                                  // mode and in some GNU modes.

For all such cases, an error is still issued if the template is instantiated.


8/17/09  [EDGcpfe/9999]
GNU C++ compatibility: qualified name in namespace template declaration

A qualified name may now be used in the initial declaration of a namespace
scope template function declaration for all gnu_version values.  Formerly,
this was only allowed when gnu_version is >= 30400.

  namespace N {
    template <class T> void N::f() {}
  }


8/17/09  [EDGcpfe/10028]
Instantiation of function declaration should ignore names declared later

In some modes (e.g., when dependent name processing is not enabled), names
declared after a declaration of a function template were visible for the
instantiation of the declaration of a function template instance.  This
could result in spurious errors.  Such names are now ignored for the
partial instantiation of a function template.  Note that such names are
still visible in the body of the function template in such modes.

  namespace N {
    struct A {};
    template <class T> void f(N::A, T) {}
    class N {};  // formerly hid namespace N
  }
  int main() {
    N::A na;
    f(na, 1);  // formerly "instantiation resulted in invalid function"
  }


8/14/09  [EDGcpfe/10027]
Deduction failure with explicit template arguments and deduced nontype param

In a call of a function template in which some (but not all) of the template
arguments are explicitly specified, deduction could fail if the type of
a deduced nontype argument depended on an explicitly specified argument.
Now fixed.

  struct A { int i; };
  template <typename T, int T::*> struct B {};
  template <typename T, int T::* v> void f(B<T, v>){}
  int main() {
    B<A, &A::i> b;
    f<A>(b);  // spurious "no instance matches the argument list"
  }


8/14/09  [EDGcpfe/10020]
GNU compatibility: Effect of multiple "aligned" attributes

In GNU modes, if multiple "aligned" attributes appear on a variable declaration
those appearing before the variable name now take precedence over those
appearing after the name (previously, it was the reverse).  For example:

  #define A(x) __attribute((aligned(x)))
  int A(8) v A(32);  // v is now 8-byte aligned (previously, it was 32-byte
                     // aligned).


8/13/09  [EDGcpfe/9938]
Incorrect default argument when class is instantiated in default argument

In modes in which nonclass prototype instantiations are performed, if the
prototype instantiation of a default argument caused an instantiation of
the enclosing class, the resulting instantiation could be missing default
argument information for some of its members.  This could result in
spurious errors or other incorrect behavior.  Now fixed.

  template <class T> struct A {
    A(){}
    A(int i, A<double> c = A<double>::invalid()){}
    static A<T> invalid();
    void f(T = -1){}
  };
  int main() {
    A<double> a;
    a.f();  // spurious "too few arguments" error
  }


8/12/09 [EDGcpfe/10012]
Lowering generated incorrect cast for assignment to static guard variable

In IA-64 ABI configurations where IA64_ABI_USE_GUARD_ACQUIRE_RELEASE and
IA64_ABI_USE_INT_STATIC_INIT_GUARD are both FALSE, the generated cast on the
assignment to the guard variable was incorrect, resulting in a warning when the
generated code was compiled (in configurations that use the C generating back
end).  This regression was introduced in 4.0 and is now fixed.  For example:

  extern int f();
  void g() {
    static int i = f();
  }


8/11/09 [EDGcpfe/9995]
Dead code removal in conditional operators operating on "this"

As a result of the changes of 10/13/08 to remove dead code from conditional
operators during lowering, conditional operators whose first argument is "this"
were optimized under the assumption that "this" cannot be NULL in a member
function.  This assumption is already made in several places in lowering and
inlining, resulting in resulting in the removal of a NULL pointer check on
related class casts as well as optimizations in constructors in the Cfront ABI
when NEW_CAN_BE_FOLDED_INTO_CTOR is TRUE.  Invoking a member function through a
NULL pointer is undefined behavior (though GNU and Microsoft compilers allow
it).  A change has been made to add a variable,
assume_this_cannot_be_null_in_conditional_operators, to control whether
lowering can assume that "this" cannot be NULL when performing dead code
removal on conditional operators.  The initial value for the variable is given
by the configuration macro ASSUME_THIS_CANNOT_BE_NULL_IN_CONDITIONAL_OPERATORS
(and defaults to the setting of DO_IL_LOWERING).  The variable is set to FALSE
at run-time in GNU and Microsoft modes to emulate their behavior in this area.
Lowering continues to assume that "this" cannot be NULL in virtual member
functions.  Here's an example showing the types of expressions that are
affected:

  struct A {
    int f(int i) {
      i = this || 1;    // dead code removed when
      i = this ? 1 : 0; // assume_this_cannot_be_null_in_conditional_operators
                        // is TRUE
      return i;
    }
  };
  int main() {
    A *a = 0;
    return a->f(1);    // allowed at run-time by GNU/Microsoft compilers
  }
  

8/11/09 [EDGcpfe/10017]
Incorrect lvalue setting for lowered enk_object_lifetime

In configurations that use lowering, a top-level lvalue enk_object_lifetime
operation was not being properly rewritten as an rvalue, resulting in
an lvalue mismatch with the expression it introduces.  This issue was
introduced in 4.0 and is now fixed.  This example (with -x) illustrates
the problem:

  struct A {
    ~A();
  };
  A g();
  void f(void) {
    A x;
    x = g();
  }


8/7/09  [EDGcpfe/9707]
Microsoft compatibility: both derived and virtual base classes have dllimport
attribute

In IA-64 ABI configurations when using Microsoft emulation mode, a derived
class based upon a virtual class and requiring a virtual function table where
both classes have the dllimport attribute specified had resulted in an
assertion failure (in define_one_virtual_function_table).  This is now fixed.
For example:

  struct __declspec(dllimport) B {
    virtual ~B();
    int i;
  };
  struct __declspec(dllimport) D : virtual B {};
  D d;


------------------------------------------------------------------------------
Version 4.1, August 6, 2009

8/3/09
IL version number changed to 4.1


8/3/09   [EDGcpfe/10000]
"stmt" pointer in a_switch_case_entry not walked properly

The "stmt" parent pointer in a_switch_case_entry was not walked in the right
way, with the consequence that with ALTERNATE_IL_FILE_FORMAT set to 0
an attempt to read back in an IL file containing a switch case would
fail if the "stmt" pointer was referenced (the pointer value was not
remapped in the read, and therefore was essentially random).


8/2/09   [EDGcpfe/10001]
Incorrect mangling for local class in Cfront ABI

In the Cfront ABI, the mangled encoding for a local class type contains the
enclosing function name as well as "__L" followed by a number meant to 
uniquely identify the class within the function.  It was possible for such
a local class to have been given two different mangled encodings (with two
different "unique" numbers) in the same compilation.  This problem could
cause an instantiation loop in the prelinker as was the case with this
example (--c++0x):

  template <class T> void f(T) {}
  template <typename T> void g(T t) {
    struct A {} a;
    struct B {} b;    // mangled with __L0 and __L1, causing prelinker loop
    f(&b);
  }
  int main() {
    g([]{
          struct C {} c;
          f(&c);
        });
  }


7/30/09  [EDGcpfe/9705]
GNU C++ compatibility: "inline template"

The GNU "inline template" feature is now supported in g++ mode.  This may
be used to cause the vtable for a class to be emitted in a given compilation.

  template <class T> struct A {
    virtual void f();
  };
  template <class T> void A<T>::f(){}
  inline template class A<int>;  // vtable for A<int> will be emitted


7/30/09  [EDGcpfe/9730]
GNU C++ compatibility: missing "template" keyword in member template reference

g++ versions before 4.1.1 allow certain dependent member class template
references to omit the "template" keyword.  It may be omitted when the
template argument list matches the implied template argument list of
the prototype instantiation.  In the example below, in the reference to
A<T>::B<...> the template parameter T has the same coordinates (position and
nesting depth) as the T of the prototype instantiation of A, so the
template keyword can be omitted.

  template <class T> struct A {
    template <class T2> struct B {};
  };
  template <class T, class U> struct C {
    A<T>::B<T> ab1;  // g++ accepts
    A<T>::B<U> ab2;  // g++ accepts
    A<U>::B<T> ab3;  // g++ gives error
    typename A<U>::template B<T> ab4;  // correct syntax
  };


7/29/09  [EDGcpfe/9986]
GNU C++ compatibility: invisible symbols used in qualified declarators

Friend names are not injected (i.e., are marked as invisible) in g++
mode when gnu_version is >= 40100.  g++ versions < 4.3 allow such
invisible names to be used in qualified declarators.   We now emulate
this behavior in g++ mode when gnu_version is < 40300.

  namespace N {
    class A {
      friend int f();
    };
  }
  int N::f() { return 0; }  // okay in g++ mode when gnu_version < 40300


7/28/09  [EDGcpfe/9952]
Run-time support "throw" routines marked as not returning

The run-time support routines implementing exception throwing (e.g. "__throw")
are now marked as not returning (flag does_not_return), and when
GCC_IS_GENERATED_CODE_TARGET the corresponding attribute is emitted by the
C-generating back end on the declaration of such a routine.  This avoids
spurious warnings when compiling the code generated by the C-generating back
end with GCC.  For example:

  __attribute((noreturn)) void f() {  // Previously the C code generated for
     throw 1;                         // this routine elicited GCC warnings.
  }


7/28/09  [EDGcpfe/9987]
GNU attributes accidentally dropped on certain function templates

In GNU modes attributes were accidentally dropped when they appeared before
the return type of a function template declaration if that return type was a
pointer or reference (formed with a "*" or "&" token, rather than indirectly
through a typedef).  For example:

  template<typename T> __attribute((always_inline)) inline
  int *f() {    // The attribute was previously ignored on all instances
    return 0;   // of f.
  }

This is now fixed.


7/27/09  [EDGcpfe/9970]
GNU C++ compatibility: __attribute((packed)) on class type with non-POD field

In GNU C++ mode with gnu_version >= 30400, the front end now ignores attribute
"packed" applied to a class type with a member that is a non-POD field.  A
warning is issued in such cases.  For example:

  struct N { N() {} int i; };
  struct S {
    char a;
    N n;
  } __attribute((packed));  // This attribute is now ignored with a warning
                            // because field n is not a POD.


7/27/09  [EDGcpfe/9963]
#pragma pack(pop) with no corresponding "push"

Previously, when a "#pragma pack(pop)" directive was encountered with no
matching "push", a warning or error was issued, and any packing directive in
effect was discarded.  Now, such an unmatched directive has no other effect
but the diagnostic.  The new behavior matches that of GNU and Microsoft
compilers.  For example:

  #pragma pack(2)
  #pragma pack(pop)  // Previously nullified the effect of the
                     // "#pragma pack(2)" directive.  Now, only a
                     // warning (in GNU or Microsoft mode) or an
                     // error (in other modes) is issued.
  struct S {
    char a;
    double b;
  } x;               // __alignof(x) is now 2 because #pragma pack(2)
                     // is still in effect.


7/27/09  [EDGcpfe/9428, EDGcpfe/9554]
Mangling of unnamed types and lambdas

With the advent of C++0x, unnamed types (lambdas, class/struct/unions, enums) 
can appear in contexts where a mangled encoding for the type name is required
(for example, a local unnamed type used as template type parameter or a lambda
defined in a default argument of a member function).  Mangled encodings
for these unnamed types are now produced by the front end in both the IA-64 and
Cfront ABIs (in all modes).  The IA-64 ABI specification has been updated to
specify manglings for these types (and we follow those rules); mangling in the
Cfront ABI required an EDG extension (see the C++ front end documentation).

In configurations where local types can be used as template type arguments
(i.e., --c++0x or --microsoft_mode >= 1400), the possibility exists for
local types to be used in the mangled name of a globally visible function.
This could result in linker conflicts because instantiations of distinct
functions could be given the same name.  To prevent this, unnamed classes and
enums in namespaces (including the global namespace), as well as static
functions, are now "individuated", that is, their mangled names are now
adjusted to appear "as if" they are part of a translation unit specific
namespace (this fabricated "namespace" incorporates the translation unit's
module id to provide a unique symbol).  The resulting mangled names should
not collide with names from other translation units and can be used in the
mangled names of template functions.

See also the Changes entry in the util directory for corresponding demangling
changes.  Here are some sample unnamed types and their mangled names (--c++0x):

  int module_id = 0;
  struct { int i; } s;
      // IA-64:  _ZN25_INTERNAL_4_ex_c_afc2b591Ut_E
      // Cfront: __Q2_26__INTERNAL_4_ex_c_afc2b5915__Ut1
  struct A {
    enum { e = 1 } E;
      // IA-64:  _ZN1AUt_E
      // Cfront: __Q2_1A5__Ut1
    static int m;
  } a;
  int A::m = [](float x) { return (int)x; }(2.0);
      // IA-64:  _ZN1A1mMUlfE_E
      // Cfront: __Q3_1A1m8__Um1_Ff
  void f(int i = [](char a, char b) { return a - b; }('1', '0')) {}
      // IA-64:  _ZZ1fiEd_UlccE_
      // Cfront: __23__Ud1_1_FcT1__L0__f__Fi


7/22/09  [EDGcpfe/9980]
Spurious warning on guiding declaration of static template

A spurious warning was issued on a predeclared guiding declaration of a
static function template.  Now fixed.  For more information about guiding
declarations, see the 10/9/02 entry "Guiding declarations disabled in
default mode".

  static void f(int);
  template <class T> static void f(T);
  int main() {
    f(1);
  }
  static void f(int){}


7/21/09  [EDGcpfe/9966]
Abort of Microsoft-mode out-of-class member function declaration in block scope

In Microsoft mode, a member function can be redeclared without an associated
definition outside its parent class.  Previously, such a redeclaration could
result in an abort in pop_stmt_stack (in statements.c) if it appeared in a
block scope (which is an error in itself) with an invalid type.  For example:

  struct S { void f(); };
  int main() {
    int S::f();  // This invalid redeclaration previously triggered an abort
  }              // in statements.c.

This is now fixed.


7/18/09  [EDGcpfe/9874]
GNU C++ compatibility: "T &" in template can be deduced to match "this"

g++ mode now allows template deduction for a parameter of type "T &"
to match an argument "this", by deducing a const type for T.

  template <class T> void gg(T &r) { r = 0; }
  struct A {
    void f() {
      gg(this);  // T deduced as "A *const", assignment in gg gets error
    }
  };


7/10/09  [EDGcpfe/9951]
Default locale for multibyte processing under Windows

When NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is TRUE on Windows
the default locale used for translating multibyte characters was the
locale associated with the current ANSI code page.  This has been changed
to use the locale associated with the current system default code page
so that, for example, on a Japanese system, the Japanese locale will
be used by default.


7/9/09   [EDGcpfe/9947]
Problems with native multibyte character support on Windows

Two problems that occur when NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE
is TRUE on Windows have been fixed.  An incorrect "count" parameter was
passed to mblen_l and mbtowc_l, so these calls would fail if the default
locale was not a multibyte locale.  In addition, special code that determines
whether a character sequence that ends with a backslash is in fact a backslash
or the end of a multibyte character was not enabled, causing some multibyte
characters to be erroneously treated as line splices.  These have been fixed.
Both of these problems have the effect of causing the declaration of "i"
to be treated as part of the previous comment line, resulting in "i" being
undefined in the printf call in the example below.

  #pragma setlocale(".932")
  extern "C" int printf(const char *, ...);
  int main(void) {
    // The characters after the // below are 0x8b 0x40 0x94 0x5c
    //«8b»@«94»\
    int i=10;
    printf("%d\n", i);
  }

Note: The above example must be decoded using the edg-changes-example tool.


7/7/09   [EDGcpfe/9956]
Spurious error on vacuous destructor call of enum type

A spurious error was issued on certain uses of enum types in vacuous
destructor calls.  Now fixed.

  enum E {};
  int main() {
    E e;
    e.::E::~E();
  }


7/7/09   [EDGcpfe/9803]
Reachability analysis with comma expressions

When determining whether a given statement is reachable, the front end
considers constant-valued expressions in the conditions of loop and "if"
statements.  It previously failed to take into account comma expressions in
which the second operand is such an expression.  This is now fixed.  For
example, the front end failed to recognize that the loop in the following
code does not exit:

  int f(int j) {
    for (int i=0; ++j, true; ++i) {
      if (i == 5) return 0;
    }
  }    // Previously warned of missing "return" statement here


7/7/09   [EDGcpfe/9958]
GNU compatibility: #include_next in file included using an absolute path name

If an #include_next directive is used in a source file that was included
using an absolute path name we now treat the directive as a normal include
(emulating the GNU behavior).  Formerly, an empty search path would be used,
resulting in a catastrophic error.


7/2/09   [EDGcpfe/9949]
C++0x: Move constructors and copy constructors

By default, we currently disable the generation of an implicit copy constructor
when a move constructor (see the Changes entry of 4/9/09 for rvalue references)
is declared in a class.  For example:

  struct S { S(S&&); } s;
  S c(s);  //  An error by default in C++0x mode.

However, this language rule is still pending a decision of the C++ committee,
and some other implementations do not disable the copy constructor in such
cases.  Therefore, new command-line options --rvalue_ctor_is_copy_ctor and
--rvalue_ctor_is_not_copy_ctor allow the behavior of the front end to be
controlled manually (e.g., with the option --rvalue_ctor_is_not_copy_ctor the
example above is accepted in C++0x mode).  In addition, in Microsoft mode with
microsoft_version >= 1600, the default behavior corresponds to the option
--rvalue_ctor_is_not_copy_ctor (which reflects our understanding of what the
forthcoming version of Microsoft Visual C++ will do).

The same uncertainty applies to move assignment operators and copy assignment
operators: The options just described affect these in the same way.


7/2/09   [EDGcpfe/9954]
GNU C++ compatibility: typename followed by a qualified constructor name

A name like A::A is defined as referring to the constructor and not the
injected class name.  If such a name is prefixed by "typename", g++
treats it as naming the injected class name (note there is never a reason
to say A::A to name a type as it is sufficient to just say A).  We now
emulate this behavior in g++ mode when gnu_version is >= 30400 (this example
was already accepted when gnu_version is < 30400).

  template <class T> struct A {
    A();
  };
  template <class T> struct B {
    B(A<T>);
  };
  template <class T> void f() {
    new B<T>(typename A<T>::A()); // should be new B<T>(A<T>())
  }
  int main() {
    f<int>();
  }


7/2/09   [EDGcpfe/9948]
GNU compatibility: include directory specified as both system and non-system

Beginning with version 3.3, gcc and g++ ignore a non-system include search
directory if that directory is also being used as a system include directory.
We now emulate this behavior in GNU mode when gnu_version is >= 30300.  A
warning is issued.

The command:

  edgcpfe -I/usr/include -I. --sys_include=/usr/include t.c

is treated as:

  edgcpfe -I. --sys_include=/usr/include t.c


7/2/09   [EDGcpfe/9946]
dynamic_cast to pointer to incomplete class in prototype instantiation

The front end no longer issues an error on a dynamic_cast to a pointer
to an incomplete class type during the prototype instantiation of a
template (except in strict mode).  An error would of course be issued
during a real instantiation if the type remains incomplete.  This
relaxation makes it slightly easier to compile real-world template
code, where the underlying type gets defined before any instantiation
is done.

  struct A;
  template <class T> void f(T *t) {
    A *p = dynamic_cast<A *>(t);  // No error now with --parse_templates
  }
  struct A { };
  struct B : A {} b;
  int main() {
    f(&b);  // No error, before or now
  }

The same relaxation is applied to the type of the operand.


7/1/09   [EDGcpfe/9944]
Missing diagnostic for referenced local class pure virtual destructor

The front end sometimes failed to issue an error for the failure to define
a pure virtual destructor of a local class when the destructor is referenced.
This happened when the local class was nested more than one level deep
in the containing function.  The failure to issue an error could
cause link-time errors or back end aborts later.  Now fixed.

  void f() {
    struct AA {
      void g() {
        struct A {
          virtual ~A() = 0;  // Formerly, no error was issued
        };
        struct B : A { };
        new B;
      }
    };
    AA aa;
    aa.g();
  }


6/30/09  [EDGcpfe/9402]
Diagnostics for nonstandard parameters to main()

The C and C++ Standards recognize two acceptable forms for the definition
of the main() function: with no parameters or as main(int, char *[]).
(Other forms are permitted as extensions.)  The front end now issues
remarks if main() is declared with a different number of parameters or
with parameter types different from those mentioned in the Standards.  For
example:

  int main(char *p) {    // Now results in remarks for wrong parameter type
  }                      // and wrong number of parameters.


6/29/09  [EDGcpfe/9918]
C++-generating back end: Abort or nonterminating loop with Microsoft-mode
in-class specialization

In Microsoft mode the C++-generating back -- when compiled with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE -- sometimes aborted with an
internal error in gen_variable_decl (cp_gen_be.c) when handling certain
in-class specializations of member class templates.  Other similar cases
instead resulted in a nonterminating loop.  (In-class specializations
are a Microsoft extension.)  For example:

  template<typename T> struct S {
    template<int> struct N {};
    template<> struct N<0> {
      template<typename> struct I {};
    };
  };
  template struct S<int>;  // Triggered an "infinite loop" in cp_gen_be.c.

This is now fixed.  (The underlying problem was the incorrect generation of
source sequence entries for prototype instantiations, rather than a bug in
the C++-generating back end proper.)


6/29/09  [EDGcpfe/9940]
C++-generating back end: "new auto(func)" with exception specification

If the type in a new-expression is specified using the "auto"
type-specifier and the initializer is a function with an exception
specification, the code generated by the C++-generating back end included
the exception specification in the type-specifier of the new-expression.
This is now fixed.  For example:

  void f() throw();
  void g() {
    new auto(f);  // Previously generated as "new (void (*)(void) throw())(f)",
                  // now as                  "new (void (*)(void))(f)"
  }


6/29/09  [EDGcpfe/9939]
typeid of variable with dependent "auto" type in prototype instantiation

When the typeid operator is applied to a variable with a dependent type
declared using the "auto" type-specifier in a function template and the
front end is configured to include prototype instantiations in the IL, the
resulting enk_typeid node referred to the "auto" type placeholder with no
indication of what that type might be.  This has now been changed so that
the node refers to the original expression operand.  For example:

  #include <typeinfo>
  template <typename T> void f(T t) {
    auto x(t);
    typeid(x);    // Formerly effectively "typeid(auto)"
  }


6/26/09  [EDGcpfe/9932]
Missing error on GNU case range conflict

In some cases, the front end failed to issue an error when a GNU case range
conflicted with another case in the same switch statement.  This is a
regression introduced in version 4.0 (see also Changes entry of 4/15/08).
For example:

  void g(int i) {
    switch (i) {
      case 2:
      case 1 ... 3:  // Previously no error, even though this conflicts
        break;       // with "case 2:".
    }
  }

This is now fixed.


6/26/09  [EDGcpfe/9719]
Instantiation loop on template static data member needed only for its size

In a case where a template static data member is instantiated only to
determine its size (i.e., it's not otherwise used) and the static
data member requires dynamic initialization, the front end was confused
about whether the template static data member is really needed, and
as a result the template prelinker got into an instantiation loop.
Now fixed.

  template <class T> struct A {
    static T tab[];
  };
  int ff();
  template <class T> T A<T>::tab[] = { ff() };
  const int N = sizeof(A<wchar_t>::tab) / sizeof(wchar_t);
  int main() {
    A<wchar_t> a;
  }


6/26/09  [EDGcpfe/9941]
Abort in PI-in-IL version on lambda referencing constant in enclosing function

An abort in remap_ptr_to_entry_number ("pointer in secondary trans unit")
could occur in a case where a nested function (a lambda) used the
constant-expression value of a static variable from the enclosing function,
in a configuration that keeps prototype instantiations in the IL
(PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE), and a mode that parses
templates (e.g., strict mode).  That abort reflects the fact that the
IL included a pointer from one function-scope memory region to another,
which is not allowed; in configurations without IL writing/reading, the
problem might manifest itself it other ways.  Now fixed.


6/25/09  [EDGcpfe/9835]
Call new runtime routine on invocation of a deleted virtual function

As a result of the C++0x feature to delete a function (see Changes entry of
4/1/09), it is now possible to delete a virtual function.  As specified
by recent modifications to the IA-64 ABI, the virtual table entry
corresponding to the deleted virtual function now points to the new
__cxa_deleted_virtual runtime routine.  A similar routine (named
__deleted_virtual_called) is invoked under the same circumstances in the
Cfront ABI.  The expectation is that these runtime routines will terminate the
program after optionally producing a diagnostic.  See also the corresponding
entry in the lib_src Changes file.  For example:

  struct B {
    virtual void f() = delete;
  } b;
  struct D {
    virtual void f() {}
  };
  int main() {
    D *d = (D*) &b;
    d->f();
    return 0;
  }


6/26/09  [EDGcpfe/9935]
inline user replacement for operator new[]

The C++ standard allows the user to write his own replacement for
the default operator new and operator new[]; however, it does not allow
that replacement to be inline (see core issue 412).  As a concession to
users, however, the front end now generates code that will call an
inline replacement operator new[] at runtime.  This worked formerly
(accidentally) when exceptions were enabled and the entity being
allocated has a destructor, but now it works in all cases.


6/24/09  [EDGcpfe/9934]
GNU C++ compatibility: specialization after use of static data member

The diagnostic issued when a template static data member is explicitly
specialized after it has been used has been reduced to a warning in
g++ mode.

  template <class T> struct A {
    static int i;
  };
  int j = A<int>::i;
  template <> int A<int>::i = 1;


6/23/09  [EDGcpfe/9820]
Abort on complete object type determination for multi-dimensional array

A change in version 4.0 caused an assertion failure in types.c, in
examine_expr_for_complete_object_type, while attempting to determine
the complete object type for an expression involving a multi-dimensional
array.  Now fixed.

  struct A {
    virtual void f();
  };
  A a[5][4];
  int main() {
    int i = 1, j = 2;
    a[i][j].f();
  }


6/23/09  [EDGcpfe/9929]
Initialization guard variable of static variable in unused extern inline

Previously, when lowering created an external initialization guard variable
for a static variable in an unused extern inline function, the definition
of the initialization guard variable was maintained in the IL.  Such a
definition is now marked as unneeded.  For example:

  struct A {
    A(int) {}
  };
  inline void f(void) {
    static A a = 5;   // Initialization guard variable (_ZGVZ1fvE1a in the
                      // IA-64 ABI or __LSG__a__L0__f__Fv in the Cfront ABI)
                      // is now marked as unneeded.
  }


6/19/09  [EDGcpfe/5922]
Incorrect mangling of nested local entities with same name in IA-64 ABI

The IA-64 ABI manglings of nested local entities with the same name were
incorrect; the discriminator (used to differentiate between entities of the
same name) had been emitted after the initial entity name rather than at the
end of the nested entity.  The resulting mangled names couldn't be properly
decoded and were incompatible with those produced by g++.  This is now fixed.
The previous behavior can be restored by setting ABI_COMPATIBILITY_VERSION <
401.  No changes have been made to the Cfront ABI.  For example:

  void x() {
    { struct X {}; }
    struct X {
      void f() { f(); }    // was _ZZ1xvEN1X_01fEv, now _ZZ1xvEN1X1fE_0v
    } x1;
    x1.f();
    { struct X {
        void f() { f(); }  // was _ZZ1xvEN1X_11fEv, now _ZZ1xvEN1X1fE_1v
      } x2;
      x2.f();
    }
  }


6/19/09  [EDGcpfe/9922]
Spurious incompatibility error for template-dependent block-extern declaration

When PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the front end sometimes issued a
spurious "declaration is incompatible" error on block-extern declarations of
functions with a template-dependent type.  (This happened in modes, like
strict mode, where templates are parsed in their generic form.)  For example:

  void f() {}
  template <class T> void g() {
    T f();  // Previously triggered a spurious error.
  }

This is now fixed.


6/16/09  [EDGcpfe/9917]
Severe compilation slowdown due to checking of GNU "deprecated" attribute

In certain complex template cases, the checking of GNU "deprecated" attributes
(function warn_about_use_of_deprecated_type in types.c) could dominate overall
compile time.  This is now fixed.


6/16/09  [EDGcpfe/9916]
Partial ordering and array types

Partial ordering would fail to consider two templates as ordered if the
deduction process resulted in a function type with an invalid return
type (in this example an array type).  The return type should not be
considered for partial ordering purposes.  Now fixed.

  template <class T> T f(T t);
  template <class U, int N> U * f(U (&r)[N]) { return r; }
  int main() {
    int arr[3] = { 1, 2, 3 };
    f(arr);  // formerly resulted in spurious ambiguity
  }       


6/15/09  [EDGcpfe/9617]
C++0x: Empty declarations

In strict C++0x mode, the front end now accepts empty declarations in file
and namespace scopes.  (They were previously accepted with a remark in non-
strict modes; now no remark is issued in any C++0x mode.)  For example:

  ;  // Now accepted in strict C++0x mode.
  

6/15/09  [EDGcpfe/9826]
Empty substatements in if-statements

The front end now issues a remark when the "then" or "else" branch of an
if-statement is an empty statement (i.e., a semicolon), except if an empty
"then" branch is followed by an "else" branch.  For example:

  void g(int i) {
    if (i);        // Now triggers a remark.
    if (i);        // No remark because an "else" follows.
    else;          // Now triggers a remark.
  }


6/12/09  [EDGcpfe/9910]
Unused flag case_fallthrough_label removed

The field case_fallthrough_label of a_label has been removed since it was no
longer used in any way after the switch statement representation changes of
version 4.0 (see Changes entry of 4/15/08).


6/12/09  [EDGcpfe/9862,EDGcpfe/9920]
GNU C++ compatibility: namespace and class in the same scope

In g++ mode when gnu_version is < 40300, a class and a namespace can be
declared with the same name in a given scope.  A lookup of the name finds
the class, except when a namespace is required.

  namespace N { typedef int X; }
  struct N { typedef int Y; };  // g++ accepts this
  N::X x;  // error N has no X
  N::Y y;  // okay
  namespace N {}  // okay

  namespace M {
    struct S { enum E { }; };
    namespace S {}
  }
  using namespace M;
  S::E f() { return S::E(0); }  // okay


6/10/09  [EDGcpfe/9904]
Delay lowering of function scopes until a module id can be created

A "module id" is used during name mangling to provide a unique and repeatable
mangling for certain entities.  If possible, a variable or routine with
an external definition is used as a portion of the module id.  If a request
to mangle a name were to occur too early in the compilation process (before
a suitable variable or routine definition had been found), either an inferior
module name would be generated (in the case of unnamed namespaces), or an
assertion (in module_id_for_source_corresp) would fail.  Therefore, we had
delayed lowering of certain functions (i.e., some static functions when
exported templates are allowed) to ensure getting a better module id.

A change has been made to delay the lowering of all functions that may require
a module id until a suitable variable or routine definition has occurred, at
which time the queued functions are immediately lowered.  Functions that
may require a module id are those that need to be externalized (when
exported templates are enabled), those contained in unnamed namespaces, and
those that may contain local types that need to be individuated to avoid
similarly named types in other translation units (in --c++0x mode or when
microsoft_version >= 1400).


6/10/09  [EDGcpfe/9884]
Assertion failure when return value optimization variable used as an rvalue

When DO_RETURN_VALUE_OPTIMIZATION_IN_LOWERING is TRUE and a function to
which the return value optimization applies is lowered, if it contains
a use of the return variable as an rvalue in the function, the
type of the expression will not match the type of the substituted temporary
variable.  In C generating back end configurations, this could lead to an
internal error ("check_type_of_variable_node: enk_variable has wrong type").
This is a 4.0 regression and is now fixed.  For example:

  struct A {
    ~A();
  };
  void g(A x);
  A f(void) {
    A x;
    g(x);
    return x;
  }


6/10/09  [EDGcpfe/9852]
Bitwise copies when default bitwise copy constructor is overloaded

In cases where the generated trivial (bitwise) copy constructor of a
class is overloaded with other user-written constructors, there were
some cases where the front end generated a call to the copy constructor
instead of implementing that call as a bitwise copy.  Such cases were
unusual (the normal cases were optimized), and were usually inlined
anyway, resulting in essentially identical code.  Now, however, the
bitwise copy is generated directly.

  struct A {
    int i;
    A();
    ~A();
  };
  struct B : public A {
  };
  int main() {
    B b;
    A a = b;  // The copy constructor was called previously; now, bitwise copy
  }


6/9/09   [EDGcpfe/9877]
Microsoft compatibility: Out-of-namespace template redeclaration

In Microsoft mode, a template may be redeclared outside of its class or
namespace.  Previously, this was restricted to when microsoft_version <= 1300
(see Changes entry of 11/1/05), but the case of a namespace member class is
also accepted by more recent Microsoft compilers: The front end now emulates
that behavior.  For example:

  namespace A {
    template <class T> struct B {};
  }
  template <class T> struct A::B;  // Now accepted in all Microsoft C++ modes.

  struct C {
    template <class T> struct D {};
  };
  template <class T> struct C::D;  // Still requires microsoft_version <= 1300.


6/8/09   [EDGcpfe/9864]
Folding of constant addressing expression cast to an integral type

Constant-valued addressing expressions cast to an integral type
are now almost always folded to a constant value.  Some changes in version
4.0 had caused such expressions not to be folded in certain contexts.

  int i;
  int main() {
    int z = (int)&i;  // Was folded in version 4.0
    z = (int)&i;      // Was not folded in version 4.0, now folded again
  }

As part of this change, the position on diagnostics issued due to
conversions or constant folding in casts has been changed to point to
the beginning of the cast rather than the operand of the cast.


6/9/09   [EDGcpfe/8594]
GNU compatibility: __COUNTER__ and __TIMESTAMP__ macros

Recent versions of gcc and g++ implement the __COUNTER__ and __TIMESTAMP__
macros (see the 7/15/04 and 6/27/03 entries below, respectively).  The
front end has been changed to define these macros in GNU emulation modes
as well, without regard to the value of gnu_version.


6/8/09   [EDGcpfe/9417]
Microsoft compatibility: trailing whitespace in quoted header names

The Microsoft preprocessor ignores trailing whitespace in the quoted form
of header names.  The front end, however, preserved that whitespace for
its internal processing, although a #include with a header name containing
trailing blanks often succeeded, depending on the characteristics of the
C stdio library with which the front end was built.  This is now fixed.
For example:

  /* File x.h: */
  #pragma once;
  int i = 5;

  /* File x.cpp: */
  #include "x.h"
  #include "x.h "    // Previously included twice in spite of #pragma once


6/8/09   [EDGcpfe/9858]
eok_reference_to/eok_ref_indirect in mangled expression causes internal error

With the expression changes introduced in 4.0, it is now possible for an
expression for a template parameter to contain a compiler generated
eok_reference_to or eok_ref_indirect operation when used with reference-typed
arguments or parameters.  This had caused an internal error
("mangled_encoding_for_expression: bad operator") in IA-64 ABI mode when the
expression was mangled.  These operations are now ignored for the purposes
of mangling.  This regression was introduced in 4.0 and is now fixed.  For
example:

  int i;
  template<class T, int& I> struct B {
    B() {}
    template <class T1, int& I1> B(const B<T1, I1>&) {}
  };
  template <class T> struct A : T {
    A() {
       B<int, i>(*this);
    }
  };
  A<B<void, i> > a;


6/8/09   [EDGcpfe/9876]
GNU compatibility: __builtin_isnan and __builtin_isinf

When the configuration macro TARG_HAS_IEEE_FLOATING_POINT is TRUE, the front
end now accepts the GNU built-in functions __builtin_isnan and __builtin_isinf
in GNU modes.  If a call to such a function has an argument that is a
floating-point constant, the result is also a constant.  For example:

  int i = __builtin_isnan(0.0/0.0);  // Same as "int i = 1;".


6/8/09   [EDGcpfe/9871]
Warning on pointer subtraction producing address outside array restored

The warning that a pointer subtraction operation produces an address
outside of an underlying array, which disappeared in certain cases after
the 4.0 expression changes, has been restored.

  int main() {
    int a[3];
    int *p;
    p = a - 1;  // Warning is once again issued
  }


6/8/09   [EDGcpfe/9887]
Array placement new with default arguments lowered incorrectly

An array placement new call to an operator new[] routine that has one or
more default arguments was lowered incorrectly (the default arguments
were not passed to operator new[]).  This problem existed in both ABIs.
This regression was introduced in 4.0 and is now fixed.  For example:

  typedef __EDG_SIZE_TYPE__ size_t;
  int arg_value = 0;
  struct A {
    A() {}
    void* operator new[](size_t size, int x = 57) {
      arg_value = x;
      return (void*)0;
    }
  };
  int main() {
    A *a = new A[10];
    return (arg_value == 57) ? 0 : 1;
  }


6/8/09   [EDGcpfe/8933]
Microsoft compatibility: unterminated macro invocations inside macro arguments

Although the C and C++ Standards require that macro arguments be expanded
as if they comprised the entire file, in isolation from the text following
the top-level macro invocation, the Microsoft preprocessor allows the
opening parenthesis of a macro invocation to appear in a macro argument and
the corresponding closing parenthesis in the following text.  The front
end now emulates this behavior in Microsoft bugs mode.  For example:

  #define M1(x) x
  #define M2 M1
  #define M3 M2(a
  #define M4(x) x

  M4(M3))    // Previously an error, now accepted


6/8/09   [EDGcpfe/9879]
Subscripting operations with invalid subscripts can again be constant addresses

As part of the expression changes in version 4.0, subscript operations
with an invalid subscript (one that falls outside the base object) were
deliberately not folded to constant addresses, with the thought that
back ends might appreciate not having to represent such address
constants.  This turned out to be the wrong choice, particularly in
C mode where such things would get errors when used in constant
initializers, so such operations are once again considered to have
constant addresses.

  int array[] = { 1, 2 };
  int *p = &array[-1];  /* Once again accepted in C mode */


6/6/09   [EDGcpfe/9844]
Conversion of string literal to pointer to other character type allowed again

The front end has an extension in both C and C++ modes that allows a
string literal to be converted to a pointer to a character type other
than char.  For example:

  const unsigned char *p = "abc";

The changes for expression handling in 4.0 broke the recognition of
this conversion in some cases, and in other cases made it valid only
when FAVOR_CONSTANT_RESULT_FOR_NONSTATIC_INIT is TRUE (and that option
is not supposed to affect validity of any programs).  Now fixed.

  void f(const unsigned char*);
  int main() {
    f("abc");  // Got an error in version 4.0, now accepted again
  }


6/5/09   [EDGcpfe/9800]
Handling of braces in default arguments

In C++98/03 it was not possible for default argument expressions to
contain braces.  That is no longer true as a result of some C++0x features
(e.g., lambdas) and GNU features (compound literals in C++).  Braces
are now handled properly in default argument expressions.

  struct A {
    int i;
    void f(A = (A){0}){}  // now accepted (in g++ mode)
  };
  void g(int);
  void f(void (*p)(int) = []{return &g;}()) {}  // now accepted (C++0x mode)


6/4/09   [EDGcpfe/8916]
Treatment of potential dependent cast followed by +, -, *, or & when using
implicit typename

When implicit typename is used there is an ambiguity between a cast of
a unary operation (where the name is assumed to be a typename) and a
binary operation (where the name is assumed to not be a type).  This can
occur for the operators that can be used as both unary and binary
operators (+, -, * and &).  Formerly such cases were taken as casts,
but they are now assumed to be binary operations.  If a cast is
intended, it must be written with typename (as is required by the
standard), or the operand of the cast can be enclosed in parentheses
(which is still nonstandard).

  template <class T> struct A {
    static const int value = 0;
  };
  template <int check> struct B {
    typedef int type;
  };
  // Is (A<T>::value)+1 a cast or expression?
  template <typename T> typename B<((A<T>::value) + 1)>::type f(T) {
    return 0;
  }
  int main() {
    f(1);
  }


6/4/09   [EDGcpfe/9712]
Searching for preinclude files when using the -I- option

Normally, the current directory is included in the search path when
the front end is looking for a preinclude file, but when the -I- option
is used, this was not the case.  The front end now includes the current
directory when searching for a preinclude file, even when the -I- option
has been used.

6/3/09   [EDGcpfe/9720]
Lvalue cast does not apply to bit-field expression

In some C modes, an lvalue cast to a similar cast remains an lvalue.
This is called an "lvalue cast" and is an extension relative to the C
standard.  The front end incorrectly allowed such a cast on bit-field
operands, which could cause problems later in compilation.  It no
longer does.

  struct S {
    int i3 : 3;
  } s;
  int *func(void) {
    return &(int)s.i3;  /* Now gets an error in (e.g.) --old_c mode */
  }


6/3/09   [EDGcpfe/9860]
Microsoft __based pointer types incorrectly considered equivalent to non-based

Pointer types based on a variable, a Microsoft extension, were incorrectly
considered to be the same as the similar non-based pointer types.  As
a consequence, in cases like the following the cast was dropped.  Now
fixed.

  char DummyBuffer[10];
  char *Base = DummyBuffer;
  typedef char *PUNBASED;
  typedef char __based(Base) *PBASED;
  PBASED bp;
  PUNBASED p;
  void f() {
    bp = (PBASED)p;
  }


5/29/09  [EDGcpfe/9585]
Backing expressions for address constants

When folding an address expression to a constant, the front end failed to
attach the original expression as the backing expression for the
newly-created constant.  As a result, it was impossible to determine which
member of a union sub-object was being addressed.  The front end now
preserves backing expressions for folded address constants.  For example:

  struct bar {
    double p;
    union {
      int a;
      int b;
    };
  } v;
  int *p = &v.b;  // Could not previously distinguish between v.a and v.b


5/28/09  [EDGcpfe/9011]
Diagnostic output with incorrect number of arguments in a macro invocation

The diagnostic issued by the front end when too many arguments are supplied
in a macro invocation previously omitted the name of the macro, which was
confusing in cases when the invocation appears in expanded macro text
rather than directly in the source.  For example,

  #define foo(a,b) a+b
  #define foo1(a,b,c) foo(a,b,c)
  #define foo2 foo1(1,2,3)

  int f() {
    return foo2;
  }

The diagnostic now includes the name of the macro, "foo".  Also, the caret
in the output with --macro_positions_in_diagnostics formerly pointed to the
"3" in the definition of "foo2" (the source position of the text being
passed as the extra argument).  This has now been changed to point to "foo"
in the definition of "foo1".  The name of the macro is now also included
when too few arguments are supplied in a macro invocation.


5/28/09  [EDGcpfe/9785]
Pointer-to-reference-member constants

The front end previously failed to diagnose pointer-to-member constants that
referred to reference members.  In version 4.0 (but not in prior versions)
this often resulted in an internal error in scan_ptr_to_member_operator
(expr.c) when the constant was used in any way.  For example:

  struct S { S(); int &x; };
  int main() {
    S().*(&S::x);  // Previously resulted in an internal error.  Now, a
  }                // diagnostic is emitted on "&S::x".

Similar problems could occur when such pointer-to-member constants appear in
the deduction of template parameters or auto type specifiers.  This is now
fixed.


5/28/09  [EDGcpfe/7681]
C++0x: __STDC_HOSTED__

In C++0x mode the front end now predefines the macro __STDC_HOSTED__ to the
value of the STDC_HOSTED configuration macro, as it previously did in C99
mode.  This change was specified in paper N1653, which was adopted at the
October, 2005 meeting of the C++ Standard Committee in Mont Tremblant,
Canada.


5/27/09  [EDGcpfe/9839]
Incorrect deduction of "auto*" in new-expressions

In C++0x mode, the front end ignored pointer declarator operators when
deducing the allocated type for a new-expression with the "auto" specifier.
For example:

  int *p = new auto*(0);  // Previously accepted and treated as "new auto(0)".

This is now fixed: The "auto" in the example cannot be deduced and an error
is issued.


5/27/09  [EDGcpfe/7491]
static inline functions, one-instantiation-per-object, and LOWER_EXTERN_INLINE

In configurations with LOWER_EXTERN_INLINE and ONE_INSTANTIATION_PER_OBJECT
set to TRUE, and in a compilation where one-instantiation-per-object mode
is enabled (e.g., by --one_instantiation_per_object), if a template
instance calls a static inline function, that function was made external
but the body was not put out anywhere, which caused a link-time failure.
Now fixed: the function is defined in the primary object file of the
compilation.  In the following example, "foo" was formerly unresolved
at link time.

  static inline int foo(void) {
    int i = 0;
    // loop to prevent front end inlining
    for (int j = 0; j < i; j++)
      i++;
    return 1;
  }
  template <int N> int bar() {
    return foo();
  }
  int main() {
    return bar<1>();
  }


5/27/09  [EDGcpfe/9846]
Lowering of class assignment can inadvertently change expression type

In configurations where TARG_REUSE_TAIL_PADDING is set to TRUE, lowering
inadvertently changed the type of a class assignment expression, which
could result in various assertion failures in C generating back end
configurations (or just expressions with incorrect types in other
configurations).  This regression was introduced in 4.0 and is now fixed.
For example:

  struct A {
    double d;
    char c;
    A();
  } a;
  void f() {
    0, a = a;   // internal error: dump_expr: bad type on eok_comma
  }


5/26/09  [EDGcpfe/9840]
Microsoft compatibility: CV-qualified parameter types and virtual overriding

In Microsoft bugs mode, the front end previously considered top-level parameter
type qualifiers when determining whether a function in a derived class
overrides a virtual function in a base class (see Changes entry of 9/18/97).
This is now no longer done if microsoft_version >= 1500.  For example:

  struct B { virtual void f(int) = 0; };
  struct D: B {
    void f(int const);  // Overrides B::f(int) when microsoft_version >= 1500,
  };                    // but not when microsoft_version < 1500 (in Microsoft
                        // bugs mode).


5/20/09  [EDGcpfe/8656, EDGcpfe/9811]
Creating an abstract parameter type should be a deduction failure

The example below resulted in a spurious "parameter of abstract type
is not allowed" error when attempting to instantiate "F(T) with T=Abstract".
It was instantiated while determining whether C(F, int*) was a viable
function, even though C(Abstract&,F) ends up being selected for the
construction of c.  The instantiation should not have been performed
because the attempt to create a function type with a parameter (or
return type) of abstract class type should have caused deduction to fail.
Now fixed.

  struct Abstract { virtual void f() const = 0; };
  struct F { template <class T> F(T); };
  struct C {
    C(F, int*);      // #1
    C(Abstract&,F);  // #2
  };
  void f() {
    Abstract* a = 0;
    C c(*a, 1);  // calls #2
  }

The Microsoft and g++ compilers do not allow instances of function templates
to have abstract parameter or return types (as in the example above), but
they do allow them to have parameters of function type that have such types.
So they accept examples like the one below where f is instantiated with a
parameter type of "void (*)(A)", even though A is an abstract class type.
We continue to accept such cases in Microsoft and g++ mode.

  template<class T> inline int f(void(*)(T) = 0) {
    return 1;
  }
  template<class T> inline int g(T*) {
    return f<T>();
  }
  struct A {
    void h() { g(this); }
    virtual void vf() = 0;
  };


5/20/09  [EDGcpfe/9808]
Destructions for partially constructed aggregates

In configurations where exceptions are enabled and lowering generates
exception handling tables, an exception thrown during the construction of
an aggregate could have resulted in some objects being destroyed multiple
times.  When region table entries were cloned (because of overlapping
object lifetimes), the destructions for partially constructed aggregates
were mistakenly cloned as well, resulting in duplicate destructions for
these objects if an exception were to be thrown at certain points before
the object was fully constructed.  This example had returned -1 and now
returns 0 (with --g++):

  int alive = 0;
  struct X {
    X() {}
    ~X() {
      static bool thrown = 0;
      if (!thrown) {
        thrown = true;
        throw 1;
      }
    }
  };
  struct A {
    A() { alive++; }
    A(const A&, const X& = X()) { alive++; }
    ~A() { alive--; }
  };
  struct B {
    A a1, a2;
  };
  int main() {
    try {
      A a;
      B b = (B){ a, a };    // b.a1 was mistakenly destroyed twice
    } catch (...) {}
    return alive;
  }


5/20/09  [EDGcpfe/9830]
GNU compatibility: Meaning of block-extern declarations in namespaces

Consider:

  namespace N {
    void f();
    void g();
  }
  void N::f() {
    void g();  // ::g in GNU C++ mode; N::g in all other C++ modes.
    g();
  }
  void g() {}

In standard C++, the meaning of the block-extern declaration of g in N::f is
"as if" the function definition had appeared in namespace N: It is a
declaration of N::g.  Previously, we adhered to that behavior in all modes.
Now, in GNU C++ mode, the block-extern declaration of g is instead treated as
a declaration of ::g.  This change also applies to block-extern declarations
of variables.


5/18/09  [EDGcpfe/9779]
Reference types in new-expressions

Previously, an ampersand (&) or double-ampersand (&&) following a type name
in a new-expression was not treated as specifying a reference type if the type
name was not parenthesized.  Instead, such tokens were treated as operators
(bitwise or logical "and").  Now, such tokens are treated as part of the
type description, which results in an error (since reference types aren't
object types).  For example:

  struct X {};
  void operator&(X*, X);
  void f(X x) {
    new X& x;  // Previously accepted as "(new X) & x;".  Now treated like
  }            // "new (X&) x;", which is an error.


5/18/09  [EDGcpfe/9822]
Local type with a base class can result in an assertion failure

In configurations that use lowering, the combination of a local type with
a virtual base class resulted in an assertion failure (in set_parent_scope)
when lowering of the local function is delayed (e.g., in strict mode).
For example (with --strict):

  struct A {};
  void f() {
    struct B {
      B() {
        struct C : virtual A {};
      }
    };
  }

Also, this example failed in the same way in some IA-64 ABI configurations:

  struct B {
    double bm;
  };
  void f() {
    {
      struct D : B {
        char dm;
      };
    }
  }


5/15/09  [EDGcpfe/9814]
"&" operator in IL for resolved "&overloaded-function"

The expression changes made in 4.0 did not preserve a source "&" operator
in the case where it is applied to an overloaded function name.
In general, this was not a problem, in that "f" and "&f" both represent the
address of the function, but it did lose information that might be useful
for source analysis, and in some cases with rvalue references and the
C++-generating back end it could produce code that would not compile:

  template <class T> void g(T x) {}
  template <class T> void f(T&& x) {}
  void h() {
    f(&g<short>);  // &g<short> is valid, but g<short> is not
  }

Now fixed; the IL "&" operator is now present for such cases.


5/15/09  [EDGcpfe/9771]
GNU compatibility: __attribute((format(...))) and non-function declarations

Previously, the GNU "format" attribute was accepted only on function
declarations.  Now, it is also allowed on declarations of pointer-to-function
variables and on typedefs for function and pointer-to-function types.
For example:

  typedef void (*PPF)(char const*, ...)  __attribute((format(printf, 1, 2)));
  void g(PPF print) {
    print("%s\n", 10);  // Triggers a warning because 10 doesn't match "%s".
  }


5/15/09  [EDGcpfe/9809]
Embedded C: spurious "out-of-scope" diagnostics

In embedded C mode, spurious "using out-of-scope declaration" warnings
(and possibly other errors) were sometimes issued if an entity declared as a
block extern in one function was also declared as a local object of a
later function.  Now fixed.

  void f1() {
    extern int k;
  }
  int f2() {
    int k;
    k = 2;
    return k;
  }


5/14/09  [EDGcpfe/9497]
Exception handling of arrays in partially constructed aggregates

In configurations where exception handling tables are generated, these
tables incorrectly omitted cleanup entries for destruction of
arrays in partially constructed aggregates.  This occurred only when the array
element is not the last member of the aggregate, has both a constructor and
destructor, and the array is initialized as a whole via a call to a runtime
routine.

In configurations where exceptions are enabled but exception handling
tables are not generated, back ends should make sure to treat the dynamic
init for an array as pertaining to the entire array when array_element_sequence
of the an_init_pos_descr entry associated with the dynamic init is TRUE.

Here's an example where ~A() hadn't been called and is now called
(and prints "A destroyed"):

  extern "C" int printf(const char *,...);
  struct A {
    A() {}
    ~A() { printf("A destroyed\n"); }
  };
  struct B {
    B() { throw 1; }
  };
  struct C {
    A a[1];
    B b;
  };
  int main() {
    try {
      C c = {};
    } catch (...) {}
    return 0;
  }


5/14/09  [EDGcpfe/9801]
static_temp moved from an_expr_node to a_dynamic_init (IL CHANGE)

The static_temp field has been moved from an_expr_node to a_dynamic_init.
Its value remains the same for enk_temp_inits and is now also used to indicate
whether a closure variable for an enk_lambda should be static.


5/13/09  [EDGcpfe/9804]
GNU compatibility: __attribute((mode(word))) on 64-bit platforms

In GNU modes, applying __attribute((mode(word))) to an integer type previously
produced an integer type of size equal to sizeof(int) by default.  Now it
produces a type of size equal to sizeof(long) by default: This has no effect
on typical 32-bit platforms, but on many 64-bit platforms the resulting type
is now usually the 64-bit type "long" instead of the 32-bit type "int".
For example:

  typedef int Word __attribute((mode(word)));
    // Word is now usually a synonym for "long" on 64-bit platforms.

(This reflects the default setting of the configuration macro TARG_WORD_MODE.)


5/13/09  [EDGcpfe/9773]
Microsoft compatibility: spurious errors on Microsoft attributes

Our implementation of Microsoft attributes does some basic error checking
of the attributes but does not otherwise do semantic processing of them.
Currently, the only exception is the uuid attribute, which has the effect
of setting the uuid of the class to which the attribute applies.  The
SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING flag causes the attributes to be
parsed but suppresses any validation the arguments.  However, it also has
had the effect of suppressing the processing of the uuid attribute.

It has come to our attention that our attribute definitions do not always
match what is actually accepted by the Microsoft compiler (in many cases
what is accepted by the Microsoft compiler differs from the Microsoft
documentation).  Because we do not do semantic processing of attributes
(except for uuid), what is most important to many of our customers is the
ability to process a source file containing attributes without issuing
spurious errors.

We do plan to update our attribute support to more closely match the
Microsoft compiler, but in the meantime we have modified the definition
of SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING to apply to all attributes
except uuid (internally this means that it applies to "unrecognized" and
"misc" attributes).  This allows the widest range of code to be accepted
by avoiding spurious errors while still correctly processing the uuid
attribute.


5/13/09  [EDGcpfe/9806]
const static data members initialized outside the class are not constants

A static data member with a const integral type that is initialized inside
the class can be used later in the program as a constant.  If the data
member is defined and initialized outside the class, however, the standard
says it should not be considered a constant, but until now the front end
has considered it constant anyway.  Now fixed.

  struct A {
    static const int i;
  };
  const int A::i = 1;
  int x[A::i];  // Now an error -- A::i is not a constant (in strict mode)

Because of existing practice, non-template static data members initialized
outside the class continue to be treated as constants except in strict mode.
Template static data members initialized outside the class are now always
considered non-constant.


5/13/09  [EDGcpfe/9778]
Microsoft compatibility: internal error on missing uuid attribute arguments

An internal error could occur (in process_ms_attr_uuid) if a uuid
attribute reference failed to specify a uuid value.  Now fixed.  The
error would occur in versions in which RECOGNIZE_MICROSOFT_ATTRIBUTES is
TRUE and SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING is FALSE.

  [uuid]
  __interface I { };


5/13/09 [EDGcpfe/9802]
Destructions of partially constructed aggregates

In configurations where exception handling is enabled, the region table entry
had been suppressed for a destructible entity if it was the last entity in an
aggregate (because no user code was thought to have been able to execute
between construction of the last element of the partially constructed aggregate
and the time the aggregate was considered fully constructed).  It turns out
that in some cases (like the case below where a default argument is supplied to
a copy constructor), a destructor (that could potentially invoke user code) can
be executed in this interval, necessitating the extra region table entry.  The
optimization (to suppress the region table entry) is now disabled in these
cases.  Here is an example that demonstrates the issue:

  struct A {
    A() {};
    ~A() {};
    A(const A& p, const A& = A()) {}
  };
  struct B {
    A a;
  };
  void test() {
    A a;
    B b = { a };
  }


5/12/09 [EDGcpfe/9334]
VLA dimension expressions in sizeof arguments

In modes accepting variable-length arrays (VLAs), references to entities
occurring in VLA dimension expressions within sizeof arguments no longer
contribute to those entities being "needed" if the dimension is not
actually evaluated.  For example:

  static int f();  // Undefined static function: Error if needed.
  int main() {
    sizeof(int(*)[f()]);  // The dimension [f()] is not evaluated.  f is thus
    return 0;             // not "needed" and the program is valid.
  }                       // Previously, an error was issued because f
                          // was considered "needed".


5/12/09 [EDGcpfe/9548]
Assertion failure on initialization of aggregate with one destructible entity

In configurations where exception handling is enabled, the initialization
of an aggregate with exactly one entity where that entity requires a
destruction could have resulted in an assertion failure
("add_dyn_init_cleanup: no temps") in cases involving overlapping object
lifetimes.  For example (--g++):

  struct A {
    ~A() {}
  };
  struct B {
    A a;
  };
  void f() {
    const B& b = (B){ A() };
  }


5/11/09 [EDGcpfe/9772]
Be more selective about variables that can be used in a "module id"

A "module id" is used during name mangling to provide a unique and repeatable
mangling for certain entities.  If possible, a variable or routine with
an external definition is used as a portion of the module id.  A change
has been made to disqualify variables that have been promoted from the
local scope as well as variables that are generated during the lowering
process from module id consideration.  This example had used N::f()::X
as part of the module id and now falls back to a secondary module id
algorithm:

  namespace N {
    inline void f() {
      static int X = 1;
    }
  }
  static void g() {
    N::f();
  }


5/11/09 [EDGcpfe/9780]
g++: Abort in lower_il.c (lower_constant) on string literal initializer

In g++ compatibility mode, a string literal initializer for a non-const char
array in an aggregate struct initialization could cause an assertion failure in
lower_constant.  This regression was introduced in 4.0 and is now fixed.  For
example:

  struct A {
    char x[5];
  };
  void f() {
    A a[1] = {""}; // caused: internal error: assertion failed at: "lower_il.c"
  }


5/10/09 [EDGcpfe/9793]
Internal error on specialization in invalid scope

An internal error could occur (in set_nested_template_class_symbol_info)
on a specialization of a class template in an invalid scope (the example
below requires a mode in which nonclass templates are parsed, such as strict
mode).  Now fixed.

  struct A {
    template <class T> struct B {};
    template < class U > void f ( U ) { 
      struct A::B<int> {};
    }
  };


5/8/09  [EDGcpfe/9784]
Error recovery abort while flushing tokens

An abort could occur (in normal_id_lookup called from is_template_reference)
when flushing tokens for certain unusual invalid test cases.  Now fixed.

  namespace {
    void A() { }
  }
  int A;
  template <class T> A::X(A<T>);


5/8/09  [EDGcpfe/9758]
Abort on invalid asm function

An abort could occur (in copy_from_source_to_asm_func_buffer) on certain
invalid asm function definitions.  Now fixed.

  asm void func(x) // asm functions must be prototyped
  int x;
  {
  }


5/5/09  [EDGcpfe/9657]
Delayed lowering of function scopes

Typically, lowering of a function scope takes place immediately after the front
end has generated IL for the function, but there are instances when lowering of
a function scope is delayed (see should_delay_lowering_on_function).  Delaying
lowering of a function can change the relative order in which functions are
lowered and lead to some undesired results.  For example, these two samples
compile without error in default mode, but yielded an internal error and an
inadvertent suppression of vtables in strict mode (in IA-64 configurations):

  struct A {};
  void f() {
    struct B : virtual A {  // internal error in lower_il.c:
      B() { struct X {}; }  //   define_one_virtual_function_table
    };
  }

Also:

  struct A {
    void f() {
      struct B : virtual A { // no virtual function table emitted for A::f()::B
        B() { struct X {}; }
        ~B() { struct X {}; }
      };
      B b;
    }
  };
  int main() {
    A a;
    a.f();
    return 0;
  }

A change has been made to delay the lowering of all enclosing functions
that encompass a function whose lowering has been delayed.  This keeps the
relative ordering of lowering the same for nested functions.


5/5/09   [EDGcpfe/9768,EDGcpfe/9756,EDGcpfe/9799]
Lowering of question operator can result in invalid IL

In configurations that use lowering, an lvalue question operator whose value
is discarded could be lowered incorrectly resulting in invalid IL (and hence
invalid generated C in configurations that use the C generating back end).
This regression was introduced in 4.0 and is now fixed.  For example:

  void f(bool b) {
    struct A {} a;
    float x;
    b ? a : a = a;
    b ? a = a : a;
    b ? (*new float) : x = x;
    b ? x = x : (*new float);
  }


5/1/09   [EDGcpfe/9694]
Lowering of initializations requiring temporaries in condition declarations

When lowering condition declarations whose initialization to a constant
requires a temporary variable, the initialization of the temporary mistakenly
occurred before the definition of the temporary, resulting in invalid generated
C code.  This regression was introduced in 4.0 and is now fixed.  For example:

  void f() {
    if (char* const& s = "zzz");
    for (;char* const& s = "zzz";);
    while (char* const& s = "zzz");
  }


4/29/09  [EDGcpfe/6861]
C-generating back end: alignment padding for unions

The size of the padding member inserted by the C-generating back end into a
union definition for alignment purposes was computed as if the padding
member were allocated at the position following the largest member of the
union, rather than at the beginning of the union, as all union members are.
This is now fixed.  For example:

  union U {
    char arr[10];
    int  i;
  };

Assuming a 4-byte alignment requirement for int, the C-generating back end
previously inserted the member declaration

  char __dummy[2];

but now inserts

  char __dummy[12];


4/29/09  [EDGcpfe/8476]
GNU compatibility: \E escape sequence

The GNU compiler accepts \e and \E as escape sequences designating the
ASCII "ESC" character.  In GNU emulation modes, the front end recognized
the first but not the second.  This is now fixed.  For example:

  char *home = "\E[H";   // Now equivalent in --gcc mode to "\0x1b[H"


4/29/09  [EDGcpfe/8841]
GNU compatibility: text following #ident string

The GNU compiler ignores, with a warning, extra text following the string
in a #ident directive.  In configurations in which IDENT_DIRECTIVE_AND_PRAGMA
is TRUE, the front end issued an error for such directives.  This diagnostic
has now been relaxed to a warning, and the resulting pragma will be entered
into the IL.  For example:

  #ident "ABC"$    // Previously diagnosed as an error, now a warning


4/29/09  [EDGcpfe/9459]
Microsoft compatibility: #pragma conform(forScope, ...)

In Microsoft modes, the front end now accepts the following pragma syntax to
control the behavior of declarations in for-init-scope:

  #pragma conform(forScope, on|off)
  #pragma conform(forScope, show)
  #pragma conform(forScope, push|pop [ , <identifier> [ , on|off ] ] )

([...] indicates an optional component; | indicates a choice between tokens).

The first form with "on" enables standard for-init-scope behavior.  The "off"
variant enables the for-init-scope behavior of the current Microsoft mode,
except when microsoft_version >= 1310: In that case the default behavior when
microsoft_version == 1310 is enabled.

The second form ("show") triggers a warning that reflects the current state
of the pragma.

The third form with "push" pushes the state of the current behavior on a stack
and, optionally, associates a given identifier with that state.  The "pop"
variant without an identifier restores the last recorded state and pops it
from the stack.  The variant with an identifier restores the last state that
was pushed with the same identifier and pops it and all later recorded states
from the stack.  The "push" and "pop" variants that included an identifier
naming a state can also be followed by "on" or "off", which behaves as if the
first form above had followed the "push" or "pop".

In C mode, the pragma is recognized and parsed, but it has no effect.

For example:

  #pragma conform(forScope, push, xxx, on)
    // Standard for-scope rules are now in effect.  A state describing the
    // default rules is on the stack.
  void f1() {
    for (int i; false;);
    for (int i; false;);  // Okay
  }
  #pragma conform(forScope, off)
    // Old-style rules are in effect (the default state is still on the
    // stack).
  int f2() {
    for (int i = 2; false;);
    return i;  // Okay.
  }
  #pragma conform(forScope, pop, xxx)
    // Default for-scope rules are restored.
  #pragma conform(forScope, show)
    // Triggers a warning indicating whether the current for-scope rules
    // conform to the standard or not.


4/28/09  [EDGcpfe/9743]
Microsoft compatibility: partial ordering of pointer-to-member functions

The Microsoft compiler, when deducing template arguments from a function type,
only compared the qualifiers of member functions if the type in the call
(including the type effectively considered to be the type of in the call
for partial ordering purposes) had a non-empty set of qualifiers.  In the
example below, this caused declaration #1 to be preferred to #2 for partial
ordering purposes.  We mow emulate this behavior in Microsoft mode.

  template< class T, class R > inline void f(R (T::*f)() ) { }  // #1
  template< class T, class R > inline void f(R (T::*f)() const ) { } // #2
  struct B {
    int * g() { return 0;}
    const int* g() const { return 0;}
    void h() { f(&B::g); }  // calls #1
  };
  int main() {
    B p;
   p.h();
  }


4/28/09  [EDGcpfe/8040]
Spurious abstract class error during prototype instantiation

When doing prototype instantiation of the constructor of a class template,
if a ctor-initializer names a dependent base class using a non-dependent
name, and the base class is a not-yet-instantiated instance of a class
template that will be an abstract class, the front end incorrectly reported
an error for the use of the abstract class type.  Now fixed.  For example:

  template <typename T> struct B {
    B(T);
    virtual void f() = 0;
  };
  template <typename T> struct I: T {
    I(): B<int>(0) { }   // Formerly reported an error on use of B<int>
  };

(Note that I<T> can be instantiated only with T=B<int> and only as a base
class of a class that has an overrider for the pure virtual function.)


4/28/09  [EDGcpfe/9741]
Brace-enclosed initializers and template-dependent variables

When parsing brace-enclosed initializers (also known as aggregate initializers)
for template-dependent variables, the front end previously often failed to
create correct IL for the initializer.  This is not a problem when template
prototype instantiations are not recorded in the IL, but it could result in
aborts in the C++-generating back end otherwise (i.e., when the macro
PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, and the compilation mode parses
templates in their generic forms).  The following example:

  template<typename> struct S { int x; };
  template<typename T> void f() {
    S<T> t = {0};  // Template-dependent variable with brace-enclosed
  }                // initializer.

previously aborted in gen_initializer_constant (cp_gen_be.c) with an internal
error ("ran out of fields") if prototype instantiations were recorded in the
IL.  This is now fixed.

As a consequence of this fix, designated initializers are no longer permitted
in prototype instantiations of brace-enclosed initializers for template
dependent variables.  For example:

  template<typename T> void f() {
    T x = { .i = 1 };  // Error: Designator into a template-dependent type
  }
  struct X { int i; };
  template void f<X>();

(GCC appears to impose a similar constraint on GNU-style designators.)


4/23/09  [EDGcpfe/9709]
Missing source position in eok_parens node in backing expression for constant

When PARENS_IN_IL is TRUE and a constant expression in parentheses was
scanned, the backing expression for the constant did not have the
source positions of the "(" and ")" recorded in it.  Now fixed.


4/23/09  [EDGcpfe/9708]
Build failure in IL display program when PARENS_IN_IL is TRUE

The IL display program did not build correctly (it got linker errors
due to a missing external "f_skip_parens") when PARENS_IN_IL is TRUE.
Now fixed.


4/23/09  [EDGcpfe/8099,EDGcpfe/8572,EDGcpfe/9667]
Change in processing of immediate pragmas

The behavior of pragmas with a binding kind of "immediate" has been changed.
Formerly, such pragmas were processed when the next regular token was
processed.  In the example below, the pragma was not processed until the
"int" token was fetched.  This created surprising behavior when a pragma was
intended to affect a preprocessing directive.  Now, pbk_immediate pragmas
are processed immediately after they have been scanned.  If they are associated
with a token that has been cached, they are also scanned again when the token
from the cache is rescanned.  Tokens are cached and rescanned in a number
of contexts, the most common ones are templates (where the cache is used
to generate the instantiations), and class member functions and default
arguments (which must be evaluated in the context of the complete class).

  // warning instead of remark on undefined preprocessing identifier X
  #pragma diag_warning 193
  #if X   // a warning is now issued here
  int x;
  #endif

In general, most customer-provided immediate pragmas should be changed to
next_token pragmas.  The interface to add_immediate_pragma_kind_description
has been changed to insure that any existing calls to this routine must
be changed in some way so that a silent change in behavior for such pragmas
is not possible (i.e., a compilation error will occur for unchanged calls).
If the pragma should be changed to the new definition of an immediate
pragma, the is_pseudo_pragma argument should be removed from the call.


4/22/09  [EDGcpfe/9727]
Missing error on casting a bit field to a reference type

The expression changes in version 4.0 introduced a regression,
specifically a failure to check for the error of casting a bit-field
expression to a reference type.  That's invalid because it effectively
takes the address of the bit field.  Now fixed.

  struct A {
    int i : 2;
  };
  int main() {
    A a;
    (int &)a.i;  // Once again diagnosed as an error
  }


4/22/09  [EDGcpfe/9729]
Spurious ambiguity on increment, decrement, or compound assignment with
  operand of enumeration type

Overload resolution gave a spurious ambiguity error when considering
an overloaded operator for an increment, decrement, or compound assignment
(e.g., +=) when the first/only operand has an enumerated type and an
operator function is available that matches the use less than perfectly.
The problem was that a builtin operator was considered to compete with the
user-written operator function.  In fact, there are no builtin
operators of those kinds that operate on enums.  Now fixed.

  enum E { e1 } e;
  int operator+=(const E&, unsigned int);
  int main() {
    e += 1;
  }


4/19/09  [EDGcpfe/7275]
Microsoft compatibility: multiple #else directives

Early versions of the Microsoft preprocessor accepted extra #else
directives without complaint, but more recent versions correctly diagnose
the error.  The front end previously emulated the earlier behavior without
regard for microsoft_version, but it has now been changed to issue a
discretionary error for microsoft_version >= 1200.  (The error has been
made discretionary in non-Microsoft modes, as well.)  For example:

  #if 0
  #else
  #else    // Previously a warning in Microsoft mode, now an error for
           // microsoft_version >= 1200
  #endif


4/19/09  [EDGcpfe/8537]
GNU compatibility, C++-generating back end: init_priority attribute

The GNU init_priority attribute is accepted by g++ only on variable
definitions, but the C++-generating back end put it out on both the
definition and all non-defining declarations of a variable with that
attribute.  This is now fixed.  For example,

  struct S { };
  struct T {
    static S s;   // Previously incorrectly generated as
                  // static S s __attribute((__init_priority__(101)));
  };
  S T::s __attribute__((init_priority(101)));


4/19/09  [EDGcpfe/9725]
C++0x: disabling variadic macros

The front end ignored the --no_variadic_macros command-line option in C++0x
mode.  This is now fixed.


4/19/09  [EDGcpfe/8659]
Sun compatibility: variadic macros

The Sun compiler accepts variadic macros, but the front end in --sun mode
failed to do so.  This is now fixed.  For example:

  #define LOG(fmt, ...) printf(fmt, __VA_ARGS__)
  void f() {
    LOG("%d, %d\n", 1, 2);
  }


4/18/09  [EDGcpfe/9606]
C++-generating back end: overflow calculating next enumeration value

When generating the definition of an enumeration, the C++-generating back
end determines whether to emit an explicit value for the second and
subsequent enumerators by incrementing the value of the preceding
enumerator and comparing that expected value with the actual value of the
enumeration constant.  If the calculation of the expected value overflows,
producing the value 0, and the actual value of the enumerator is 0, the
required explicit value for the enumerator was incorrectly omitted.  This
is now fixed.  For example, if the front end is configured to use 64-bit
long longs as the internal representation of integral constants, the
following code was incorrectly generated:

  enum E {
    HUGE = 0xffffffffffffffff,
    NEXT = 0    // Explicit value "= 0" was formerly omitted
  };


4/18/09  [EDGcpfe/9721]
Function and array values in unevaluated GNU-mode constant expressions

The GNU-mode feature that allows non-constant expressions to appear in
unevaluated parts of constant expressions (e.g., a dead second or
third operand of a "?" operator) has been tweaked to not give errors
on function- and array-typed operands.  In particular, such operands
that decay to constant values, which are valid even without an
extension, formerly got spurious errors and no longer do.

  void f();
  void (*p)() = 0 ? f : (void (*)())0;  // Now accepted in --gcc mode


4/17/09  [EDGcpfe/9714]
GNU compatibility: __builtin_dwarf_sp_column

In GNU modes, the front end now predeclares __builtin_dwarf_sp_column.


4/17/09  [EDGcpfe/9706]
Cast to bool incorrectly seen as lvalue cast in g++ < 3.4 mode

A cast from a char type to bool was incorrectly treated as an ignored
lvalue cast in g++ emulation mode with gnu_version < 30400.  Now fixed.

   unsigned char var = 2;
   int main() {
       printf("%d\n", (bool)var);  // Should print 1, printed 2 previously
       return 0;
   }


4/17/09  [EDGcpfe/9724]
Incorrect scope orphaned list header list in multi-trans-unit case

In some cases when multiple translation units are compiled in one
compilation, the il_header.scope_orphaned_list_headers list included
some entries that shouldn't be there.  The effect of the extra entries
was that certain local types were both on the file scope list (after
lowering) and on an orphaned list, with the consequence that the
generated code from the C-generating back end got duplicate-definition
errors on those types.  (Other back ends would presumably see similar
problems.)  The exact conditions needed to provoke the problem are
complex, but they involve functions that need not be copied to the
primary IL because there is already a copy of them there, and have
local types, followed by other functions with additional local types,
in a secondary translation unit.  Now fixed.

file 1:
  struct A {
    virtual int f(int x) {
      return [x]{return x;}();
    }
  };

file 2:
  struct A {
    virtual int f(int x) {
      return [x]{return x;}();
    }
  };
  int main() {
    A a;
    [](A* ap){return ap->f(1);}(&a);
  }


4/17/09  [EDGcpfe/9723]
cv-qualification of parameters in IA-64 ABI alternate entry points

In IA-64 ABI configurations that use lowering, the cv-qualification of
parameters (including the "this" parameter) was inadvertently dropped in
definitions of alternate entry points for constructors/destructors.  In this
example:

  struct A {
    A(const volatile int i) {}
  };

the lowered subobject constructor had been defined as "void _ZN1AC2Ei(
struct A *, int)" and is now "void _ZN1AC2Ei(struct A *const, const volatile
int)" (which matches the definition of the complete object constructor).


4/17/09  [EDGcpfe/9710]
Aborts resulting from invalid source position values

In configurations in which FULLY_RESOLVED_MACRO_POSITIONS is TRUE, the front
end sometimes failed to set the orig_seq and orig_column fields of
a_source_position objects, which could lead to aborts resulting from invalid
values in these fields.  This is now fixed.


4/17/09  [EDGcpfe/7890]
GNU compatibility, C++-generating back end: __complex__ keyword

The C++-generating back end generated uses of the GNU __complex__ keyword
as the corresponding C99 _Complex keyword.  Now fixed.  For example:

  typedef __complex__ float FC;  // Previously generated as _Complex float

(Note that this change also affects diagnostic output involving these
types: messages in GNU emulation modes will refer to "__complex__" instead
of "_Complex".)


4/17/09  [EDGcpfe/9074]
Microsoft compatibility, C++-generating back end: override, abstract, sealed

The Microsoft function modifiers override, abstract, and sealed (see the
entry of 2/2/06) were incorrectly generated by the C++-generating back end
when the function is cv-qualified.  Now fixed.  For example:

  struct S {
    virtual void f() const abstract;  // Previously generated as constabstract
  };


4/16/09  [EDGcpfe/7870]
GNU compatibility, C++-generating back end: __offsetof built-in operator

In a function template definition generated from the string form of the
template, the C++-generating back end represented the GNU __offsetof
operator as __INTADDR__, an EDG-specific operator.  This is now fixed.  For
example,

  template <typename T> struct S {
    int x;
    int f() {
      return __offsetof((unsigned)&(static_cast<S*>(0)->x));
          // ^^^^^^^^^^ Previously generated as __INTADDR__
    }
  };


4/16/09  [EDGcpfe/8743]
GNU compatibility, C++-generating back end: __asm__ keyword

In an asm-declaration or (in a function template definition generated from
the string form of the template) an asm-statement, the C++-generating back
end used "asm" as the keyword when gcc_is_generated_code_target is TRUE.
This form of the keyword is not accepted by gcc in -ansi mode, so "__asm__"
is now used when generating code for a gcc target.  For example:

  __asm__("foo: ret");  /* asm-declaration, now preserves __asm__ spelling */


4/16/09  [EDGcpfe/9717]
Abort in matching_template_function on name found by using-directive lookup

An abort could occur in matching_template_function on a reference to
a function template in a context treated as taking the address of an
overloaded function if the template came from an overload set produced by
a using-directive lookup.  Now fixed.

  template <class T> int f(const T &) { return 0; }
  namespace N {
    int f () ;
  }
  using namespace N;
  int g() { f(&f<short>); }


4/15/09  [EDGcpfe/9711]
Function template argument should cause parameter to be nondeduced

If the set of functions passed to a parameter of a function template contains
a function template (but not a template-id) the associated parameter should
be treated as a nondeduced context (this was clarified by core issue 325).
Formerly, the front end did not consider all such contexts as nondeduced,
which could result in spurious errors in some cases.  Now fixed.

  template<class T> void g(T,void (*pf) (T)) { }
  template <class T> void f(T) {}
  template <class T> void h(T) {}
  void h(char){}
  int main() {
    g(0,f);  // spurious "no instance ... matches the argument list"
    g(0,h);  // spurious "no instance ... matches the argument list"
  }


4/10/09  [EDGcpfe/9556]
GNU compatibility: __builtin_bswap32 and __builtin_bswap64

In GNU modes, the front end now predeclares the byte swapping functions
__builtin_bswap32 and __builtin_bswap64.


4/10/09  [EDGcpfe/8530]
C++-generating back end, Microsoft and Sun compatibility: __alignof

When msvc_is_generated_code_target is TRUE, the C++-generating back end
generated uses of the __alignof operator in templates as __ALIGNOF__, which
is not accepted by MSVC++.  This is now fixed.  In addition, the __alignof
operator is now accepted in --sun mode.  For example:

  template <typename T> unsigned f() {
    return __alignof(T);    // Previously generated as __ALIGNOF__(T)
  }


4/9/09   [EDGcpfe/9517,EDGcpfe/9586,EDGcpfe/9673]
GNU compatibility: Builtin I/O functions with va_list parameter

In GNU mode, the front end previously declared some builtin I/O functions with
a parameter of type char* where type va_list should have been used instead
(va_list is often, but not always, a synonym for char*).  This is now fixed.
The affected functions are __builtin___vsnprintf_chk, __builtin___vsprintf_chk,
__builtin_vfprintf, __builtin_vfscanf, __builtin_vprintf, __builtin_vscanf,
__builtin_vsnprintf, __builtin_vsprintf, and __builtin_vsscanf.


4/9/09   [EDGcpfe/9656]
Exception specifications when initializing a reference to a function

The original C++ standard (aka. C++98) required that in the initialization of
a reference to a function the exception specifications of the source entity
and the referenced function type match exactly.  Technical Corrigendum 1 for
that standard (TC1, aka. C++03) revised that rule to match the pointer case:
The referenced function type is required to allow any exceptions allowed by
the source entity, but it can also allow other exceptions.  (This was the
resolution of the C++ committee's Core issue 25.)  The front end now
implements the new rule.  For example (assuming exceptions are enabled):

  void f() throw(int);
  void (&rf1)() = f;          // Previously a spurious error.  Now allowed.
  void (&rf2)() throw() = f;  // Still an error.


4/9/09   [EDGcpfe/9660]
Options to control "auto"

New command-line options now control whether in C++ modes "auto" is a type
specifier, a storage class specifier, or both.  The defaults are determined by
the new configuration macros DEFAULT_AUTO_STORAGE_CLASS_SPECIFIER_ENABLED and
DEFAULT_AUTO_TYPE_SPECIFIER_ENABLED (they cannot both be FALSE).  The command-
line option --auto_type/--no_auto_type enables or disables "auto" as a type
specifier.  Similarly, --auto_storage/--no_auto_storage enables or disables
"auto" as a storage class specifier.
"auto" can be enabled both as a storage class and as a type specifier.  Some
ambiguous uses are treated as storage class specifiers in that case.
For example:

  typedef int T;
  int x;
  void f() {
    auto T(x);  // Variable T initialized with x in normal C++0x mode.
  }             // Variable x with type T if "auto" can be both a type
                // specifier and a storage class specifier.

--auto_type also disables "auto" as a storage class specifier (which matches
normal C++0x behavior) unless the option --auto_storage is used explicitly.
The options --no_auto_storage and --no_auto_type cannot be used simultaneously.


4/9/09   [EDGcpfe/9669]
Inlining a reference cast of a parameter could cause assertion failure

Inlining a routine that contains a reference cast of an lvalue parameter
resulted in an assertion failure ("remap_var_for_inlining: wrong kind of
remap").  This regression was introduced in 4.0 and is now fixed.  For example:

  inline void f(int i) {
    int j = (int&)i;
  }
  void g(int i) {
    f(i);
  }


4/9/09   [EDGcpfe/9659]
Microsoft compatibility: C++0x features

In Microsoft mode with microsoft_version >= 1600 the front end now enables the
following C++0x features:
  - "auto" as a type specifier (and "auto" as a storage class is disabled)
  - decltype
  - lambdas
  - rvalue references
  - static_assert


4/9/09   [EDGcpfe/8056]
Rvalue references

Rvalue references, a C++0X feature described by N2118 (with a significant
change in N2844) and voted in at the October 2006 (Portland) meeting of
the C++ standards committee, has now been implemented.  The feature is
enabled implicitly in C++0x mode, and can also be controlled separately
by --[no_]rvalue_refs and DEFAULT_RVALUE_REFERENCES_ENABLED.  The
existence of rvalue references allows the declaration of "move
constructors", which can be used to efficiently copy class objects
by transferring the resources from a source object that is soon to
be defunct to a destination object.

IL CHANGE: The tk_pointer variant of a_type now has an is_rvalue_reference
field, which further refines the existing is_reference flag.  There's
also a new is_rvalue_reference_cast flag in expression operation nodes.

ABI CHANGE: New mangling forms have been added for rvalue references.
The IA-64 ABI form matches the Itanium ABI specification.  The demangler
has been updated to handle these new encodings.

The standards committee is still unsure about how rvalue references
to functions should work.  In particular, a cast to an rvalue-reference-
to-function or a function call returning such a type is said to return
an rvalue of function type, which is something that otherwise doesn't
exist in the language.  While we await the committee's decision on
how that should work, we have made the result in such cases decay to
a pointer to function, which is at least well defined in the current
standard.


4/9/09   [EDGcpfe/9584]
Microsoft compatibility: #pragma comment

The front end has been changed to recognize and process (as a pbk_immediate
pragma) the Microsoft comment #pragma, the syntax of which is

  #pragma comment(kind [, "str"] )

where "kind" is one of the identifiers compiler, exestr, lib, linker, or
user.  Macro expansion and string literal concatenation are performed on
the pragma's arguments and the syntax is checked; if correct, the pragma
is entered into the IL.  Variant fields have been added to a_pragma to
represent the kind and, if present, string arguments.


4/8/09   [EDGcpfe/9675]
Abort on excess initializers for zero-length array in GNU modes

In GNU modes, extraneous elements in an aggregate initializer are often
accepted with a warning.  However, in some cases involving zero-length arrays
(another GNU extension) the front end aborted with an internal error in
get_initializer (decl_inits.c) when dealing with such excess initializers.
For example:

  int a[][0] = { 3 };  // Previously triggered an abort in GNU modes.

This is now fixed.


4/8/09   [EDGcpfe/9692]
Microsoft compatibility: stringized omitted arguments

The Microsoft preprocessor has special handling when stringizing omitted
(as opposed to empty) arguments: such arguments expand to nothing rather
than to "".  The front end now emulates this behavior in Microsoft mode.
For example:

  #define M(x, ...) #__VA_ARGS__
  M(a)    // Previously expanded to "", now to nothing
  M(a,)   // Continues to expand to "", as with Microsoft preprocessor


4/7/09   [EDGcpfe/8402]
Objectless references to non-static data members

In the 2003 C++ Standard, the name of a non-static class data member could
appear only in a member function of that class or one derived from it, in a
member access expression (x.m or p->m), or to form a pointer to member
(&X::m).  C++0x relaxes that restriction to allow such names as an
unevaluated operand, such as sizeof(X::m), typeid(X::m), and
decltype(X::m).  The front end now accepts this usage in C++0x mode and
non-strict C++98/03 mode; such references are transformed into a
compiler-generated member access expression using 0 cast to the appropriate
type as the object pointer.  As an extension, the front end also accepts
these references as subexpressions of unevaluated operands, such as
sizeof(X::arr[0]), even in strict C++0x mode, in anticipation of an
expected relaxation of that restriction in the Standard.


4/6/09   [EDGcpfe/9540]
Mangling unnamed enum template parameter member causes assertion failure

In configurations where PROTOTYPE_INSTANTIATIONS_IN_IL and MANGLE_ALL_NAMES
are both TRUE, the mangling of a typedef for an unnamed enum used as a
template parameter member caused an assertion failure in
mangled_type_name_full.  The failure had occurred in both ABIs and is now
fixed.  For example:

  template <class T> struct A {
    typedef enum {} unnamed;
    void f(unnamed);
  };
  template <class T> void A<T>::f(unnamed t) {}


4/3/09   [EDGcpfe/8221,EDGcpfe/8337,EDGcpfe/8898,EDGcpfe/9045,EDGcpfe/9346,
          EDGcpfe/9689]
GNU compatibility: __builtin_offsetof and nonconstant subscripts

Previously, the built-in operation __builtin_offsetof (only accepted in some
GNU modes) allowed in its second argument only field selections and constant
array subscripts (see Changes entry of 6/6/06).  Now nonconstant subscripts
are also allowed.  For example:

  struct S { float f[10]; };
  unsigned long g(int n) {
    return __builtin_offsetof(struct S, f[n]);  // Now accepted in some GNU
  }                                             // modes.

This is the first case of an enk_builtin_operation node that is not always
folded to a constant (and therefore an IL CHANGE).  In configurations that
use lowering, the enk_builtin_operation/bok_offsetof expression is lowered
to an expression whose value is the offset.


4/3/09   [EDGcpfe/9454]
Microsoft compatibility: __annotation

In Microsoft modes with microsoft_version >= 1300, the front end now
predeclares a function "__annotation" with the following signature:
  extern "C" void __cdecl __annotation(wchar_t*, ...);
(or its equivalent in C mode).


4/2/09   [EDGcpfe/9453]
Spurious ambiguity when declaring a conversion operator template instance

When explicitly specializing a conversion operator template belonging to a set
of member function templates only distinguished by cv-qualification, the front
end issued a spurious error.  For example:

  struct S {
    template<class T> operator T();
    template<class T> operator T() const;
  };
  template<> S::operator int() const;  // Previously resulted in a spurious
                                       // error.

This spurious error could also occur with other contexts that declare a
conversion template instance (e.g., friend declarations).  This is now fixed.


4/2/09   [EDGcpfe/9680]
Spurious access errors for certain access checks in deferred contexts

In some contexts access checking must be deferred until the front end knows
which entity is being declared (e.g., in the example below, the entity might
be given access as a friend).  The checks for some implicitly invoked
functions and elided copy constructors were not deferred, which could
result in spurious access errors.  Now fixed.

  class A {
  public:
    friend int f(A*);
    friend int f(A);
    A(int) {}
  private:
    int x;
    A() : x(37) {}
    A(const A&) {}
  };
  int f(A* = new A){return 0;}  // A::A() accessible
  int f(A = A(1)){return 0;}    // A::A(const A&) accessible (strict mode)


4/1/09   [EDGcpfe/9658]
Abort on unterminated string in failing static_assert

A static_assert declaration whose first argument is "false" (i.e., the
assertion fails) and whose second argument is a string literal with a missing
terminating quotation mark (") triggered an internal error in
make_static_assert_string_for_output (decls.c).  For example:

  static_assert(false, ");  // Previously triggered an internal error.

This is now fixed.  (static_assert is a C++0x feature; see Changes entry of
8/25/06.)


4/1/09   [EDGcpfe/9668]
Microsoft compatibility: rescanning of commas in macro expansions

As described in the 4/15/06 entry, the Microsoft preprocessor generally
considers commas occurring inside macro arguments not to delimit macro
arguments when the expanded text is rescanned for further macro
invocations.  If, however, the expanded text appears in the argument list
of a macro invocation occurring in an argument to another macro, such
commas do delimit arguments in that nested macro invocation.  For example:

  #define E(x) x
  #define A(x) E(M(x))
  #define M(x, y) A=x, B=y
  #define s A,B
  A(s)

Here the text "A,B" is considered to be two arguments in the invocation of
macro M because that invocation occurs in the argument of macro E; if the
definition of macro A were

  #define A(x) M(x)

the string "A,B" would have been considered to be one argument.  The front
end's Microsoft emulation failed to allow for this exception to the general
rule for handling commas appearing in macro arguments; this is now fixed.


4/1/09   [EDGcpfe/9678]
Microsoft compatibility: support for __identifier("string")

Microsoft documents the __identifier facility as taking a keyword
token as its argument.  If a string literal is used as an argument, the
Microsoft compiler gives an error by default, but this error can be
downgraded by use of a pragma.  This usage is exploited in the Microsoft
header files.  We now give a discretionary error for a string literal in
an __identifier operator.  Because it is a discretionary error, it will
automatically be suppressed in files from system include directories.

  namespace __identifier("<CrtlImplementationDetails>") { }


4/1/09   [EDGcpfe/9677]
Internal error on static data member array with its size used in initializer

An internal error (in define_template_static_data_member) could occur if
a template static data member array had its array size specified in an
out-of-class definition and the array bound made use of the size of the
array.  Now fixed.

  template <class T> struct A {
    static int x[];
  };
  template <class T> int A <T>::x[sizeof(x)];
  A<short> a;
  int i = sizeof(A<short>::x);


4/1/09   [EDGcpfe/8529]
Defaulted and deleted functions

In C++0x mode, the front end now implements deleted functions ("= delete;")
and defaulted special member functions ("= default;").  A deleted function is
a function declaration that cannot be referenced.  For example:

  int f(int) = delete;
  short f(short);
  int x = f(3);         // Error: selected function is deleted.
  int y = f((short)3);  // Okay.

Special member functions that can be implicitly defined can instead be
explicitly declared but with a "default definition".  As the following example
shows, the default definition can be specified inside or outside the enclosing
class definition, but only if it appears inside the class can that class be a
POD type (if all other constraints for POD types are fulfilled).

  struct S { S(S const&) = default; };
  struct T { T(T const&); };
  T::T(T const&) = default;
  static_assert(__is_pod(S), "S is a POD");
  static_assert(!__is_pod(T), "T is not a POD");

This change was voted into the C++ committee's working paper for the next
standard in July 2007 (meeting in Toronto, through proposal numbered N2346).


4/1/09  [EDGcpfe/9671]
Internal error in check_type_of_variable_node for const string literal

In configurations where ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS is TRUE,
lowering did not properly modify the type of the variable substituted for
string constants when they occurred as operands of a comma or question
operator, resulting in an internal error in check_type_of_variable_node
(in C generating back end configurations).  The error occurred only in modes
where string literals are treated as const (e.g., GNU, Microsoft, Sun, strict).
This example had failed (--c++0x -A -tused) and now compiles correctly:

  template <class T> void f(bool b) {
    decltype("abc") x = (b ? "abc" : "abc");
    decltype("abc") y = (b , "abc");
  }
  void g() {
    f<void>(true);
  }


3/31/09  [EDGcpfe/9672]
IA-64 ABI: Internal error on friend definition when parsing templates

In IA-64 ABI configurations, an internal error could occur in
routine_needed_even_if_unreferenced on a friend function template
specialization declaration when nonclass templates are being parsed.
Now fixed.

  template < class T > void f (T) { }
  template < class T > class A {
    friend void f < T > (T) {}
  };


3/31/09  [EDGcpfe/9455]
Microsoft compatibility: friend lookup when not using ADL

When looking for a function in a call in which argument-dependent lookup
is suppressed, the Microsoft compiler ignores friend functions that include
definitions.  These functions are not ignored if argument-dependent lookup
is done.  In the example below, the call would be ambiguous if ADL had been
done (i.e., by removing the parentheses around f) or if the friend declaration
did not include a definition.  We now emulate this behavior in Microsoft mode.

  class C { 
    friend int f(C) { return 1; }  // #1
  };
  int f(C const&) { return 0; }  // #2
  int main() {
    C c;
    return (f)(c);  // calls #2
  }


3/31/09  [EDGcpfe/9662]
Uses of decltype applied to parameters within the parameter list

The checking for errors on uses of decltype on parameters has been
improved to catch uses of parameters within default argument expressions
in the same parameter list, as in

  void f (int i = (decltype(i))0) {}  // Error now detected

Also, the type determined by decltype in such cases is now correctly
the declared parameter type instead of reference-to that type.
For example:

  void h (int i, int j[sizeof((decltype(i))0)]) {}  // Now accepted


3/30/09  [EDGcpfe/9638]
GNU compatibility: __builtin_va_arg_pack and __builtin_va_arg_pack_len

In GNU modes, the front end now predeclares the special built-in functions
__builtin_va_arg_pack and __builtin_va_arg_pack_len.  These functions are used
by GCC's C library to safely forward variadic arguments passed to inline
functions.  The front end will issue an error for uses that are not in an
inline function with an ellipsis parameter.  Code-generating back ends should
replace invocations of __builtin_va_arg_pack with the variadic arguments
passed to the enclosing (inline) function, and replace invocations of
__builtin_va_arg_pack_len with the number of variadic arguments passed to the
enclosing function.  (The GCC back end issues an error when an invocation a
function containing __builtin_va_arg_pack or __builtin_va_arg_pack_len cannot
be expanded inline.)  For example:

  void g(int, ...);
  __inline void f1(int n ...) {
    g(__builtin_va_arg_pack_len(), __builtin_va_arg_pack());
        // Now accepted in GNU modes.
  }
  void f2(int n, ...) {
    g(__builtin_va_arg_pack_len(), __builtin_va_arg_pack());
        // Error: f2 is not an inline function.
  }


3/30/09  [EDGcpfe/9557]
Incorrect diagnostic for function name token during instantiation

When one of the various function name tokens appears in a class template
outside of a function definition, the error message issued when the
template is instantiated referred to the wrong token instead of the
function name token.  For example, the following

  template <typename T> struct S {
    static const int i = sizeof(__FUNCTION__);
  };
  X<int> x;

produced a message referring to "the reserved identifier 'i'" instead of
"the reserved identifier '__FUNCTION__'".  Now fixed.


3/27/09  [EDGcpfe/9661]
Missing diagnostic on missing default argument on member function template

The front end failed to diagnose a member function template that had a
parameter with a default argument followed by a parameter without one.
Now fixed.

  struct B {
    template <class T> B (T, int dummy = 1, T); 
  };


3/25/09  [EDGcpfe/9647]
Incorrect generated code for cast of function to reference-to-object

Now that a reinterpret_cast of a pointer to function to a pointer to object
is allowed (see Changes entry of 6/7/07), the similar case using references
is also allowed.  However, the changes to the IL representation of
expressions made for 4.0 broke the handling of such cases in the
C-generating back and the C++-generating back end.  For the former,
the generated C code was incorrect, and for the latter the front end
aborted.  Now fixed in both cases.

  void f() {}
  int main() {
    int i = (int &)f;
  }


3/25/09  [EDGcpfe/9642]
Lowered static reference initialization can generate bad C code

In configurations that use the C generating back end, certain static reference
initializations (those involving initialization to the address of a temporary
in routines whose static variables are promoted during the lowering process)
could have resulted in generated C code that doesn't compile.  This is now
fixed.  This example had failed to compile:

  struct A { int i; };
  void f() {
    static const A &r = A();
    int i = r.i;
    struct B { ~B() {} } b;
  }


3/24/09  [EDGcpfe/9633,EDGcpfe/5781,EDGcpfe/6502,EDGcpfe/8146,EDGcpfe/8465,
          EDGcpfe/9138]
g++ mode lvalue casts, again

In g++ mode with gnu_version < 30400, casts from integral to same-sized
integral types (see Changes entry of 9/15/05), and from pointer type
to same-sized pointer type (new with this change) can leave the result
as an lvalue.  These casts are no longer ignored in assignment and
increment/decrement contexts.

  int main() {
    int *pi;
    void *pv;
    (void*)pi = pv;  // g++ 3.3 accepts this, and now we do also
  }

3/23/09  [EDGcpfe/7682]
_Pragma operator now supported in C++ mode

The _Pragma operator (originally from C99 and already supported in GNU mode),
is now supported in non-strict C++98/C++03 mode and in all C++0x modes.

  _Pragma("test_next_decl")
  int i;

3/23/09  [EDGcpfe/9632]
GNU C++ compatibility: Overriding a virtual function returning void*

In GNU C++ mode, the front end now accepts overriding a virtual function
returning a void* pointer with a virtual function returning another pointer
type.  A warning is issued in such cases.  For example:

  struct B {
    virtual void* f();
  };
  struct D: B {
    B* f() { return this; }  // Now accepted in GNU C++ mode.
  };

(Unlike covariant return types -- see Changes entry of 11/4/96 -- this
does not involve pointer adjustments.)  



3/23/09  [EDGcpfe/9644]
Internal error on local class that derives from nonreal class

When nonclass prototype instantiations are being used, an internal error
could occur (in find_copy_assignment_operator) on the declaration of
a local class that has a nonreal base class.  Now fixed.  This particular
example requires strict mode.

  template <class T> struct A {};
  template <class U> void f(U x) {
    struct B { };
    struct D : A<B> { };
  }


3/23/09  [EDGcpfe/9631]
GNU C++ compatibility: Member declarations that don't declare anything

In GNU C++ mode, the front end now accepts (with a warning) a member
declaration that doesn't declare anything if that declaration refers to a
class or enumeration type using an elaborated type name.  For example:

  struct X;
  struct S {
    struct ::X;  // Now accepted in g++ mode.
  };


3/21/09  [EDGcpfe/9641]
Use of uninitialized variable in constant address folding

Code in constant_lvalue_address in folding.c could make use of an
uninitialized variable and consequently build an invalid constant,
which could cause aborts later (e.g., in alloc_shareable_constant
in il.c).  This problem was introduced in version 4.0.  Now fixed.
This test case provoked the problem in --c++0x --strict mode:

  auto x = []{return 59;};
  typedef decltype(x) T;
  template <const T& cr> struct C {
    static int y[4];
  };
  template <const T& cr> int C<cr>::y[] = {
  [] () -> const int & { return y [ (sizeof []{}) ] ; } ()
  };


3/20/09  [EDGcpfe/9451]
Deduction failure substituting template arguments into dependent template

Template argument deduction would fail if the function template contained
a dependent template (i.e., one whose template parameter list cannot be
known until the template parameters on which it depends have values),
and the actual template to which the dependent template resolves had
nontype template parameters that depend on the types of other template
parameters.  In the example below, T::template V is the dependent template.
It resolves to S::V, and S::V has a nontype template parameter that depends
on another template parameter (t has type T).  Now fixed.

  struct S {
    template<class T, T t> struct V {
      static const int C = t;
    };
  };

  template<class T, int I> int f(int(&)[T::template V<int,I>::C]) { return 1; }

  int main() {
    int y[3];
    return !(f<S,3>(y) == 1);
  }


3/18/09  [EDGcpfe/9626]
Infinite loop with delayed nested class in a local class member function

Lowering of a delayed nested class (i.e., the definition appears after
a declaration in a nested class) in a local class member function could
result in an infinite loop in promote_type_list.  Now fixed.  For example:

  struct A {
    void g() {
      struct B {
        struct C;
      };
      struct B::C {
        void f() {}
      } x;
      x.f();
    }
  } a;
  int main() {
    a.g();
  }


3/17/09  [EDGcpfe/9628]
"referenced but not defined" diagnostic missing for nested class members

A member of a class in an unnamed namespace must be defined if it is used
or if it is a virtual function.  Diagnostics were issued for top-level
classes but not for nested classes.  Now fixed.

  namespace {
    struct A {
      struct B {
        static void f();   // should get error
        virtual void g();  // should get error
      };
    };
    void g() { A::B::f(); }
  }


3/17/09  [EDGcpfe/9627]
C++0x: Types without linkage in declarations of entities with linkage

In C++98/C++03, an entity with linkage cannot be declared using a type
without linkage.  C++0x allows local and unnamed types to be used as
template arguments requiring this rule to be revised.  The new rules
allow such declarations provided that if the entity is used it must also
be defined in the same translation unit.  We now use the new rules in
modes in which local and unnamed types can be used as template arguments
(C++0x mode and Microsoft mode when microsoft_version is >= 1400).

  template <class T> struct A {
    // can now be instantiated with local class X
    void f(T){}
    friend void g(A){}
  };

  template <class T> inline void f(T t) {
    A<T> a;
    a.f(t);
    g(a);
  }

  int main() {
    class X {};
    X x;
    f(x);
  }


3/17/09 [EDGcpfe/9524,EDGcpfe/9651]
Unmangled member function in local class type

In certain cases (involving a function whose lowering is delayed and a local
class member that can't be inlined), the names in a local class were not
mangled, causing compilation errors in generated C code.  This example had
generated incorrect C code (in strict mode) and now compiles cleanly:

  struct A {
    void f() {
      struct B {
        void g() {
          struct C {
            void operator()() { for(;;); }  // unmangled in generated C
          } c;
          (c(), 0);
        } 
      } b;
      b.g();
    }
  } a;
  void h() {
    a.f();
  } 


3/17/09 [EDGcpfe/9625]
Incorrect message for undefined member of unnamed namespace

A change in version 3.6 inadvertently changed the diagnostic issued when
a referenced member function in an unnamed namespace was not defined (the
incorrect message said that a virtual function was not defined).  Now fixed.

  namespace {
    struct A {
      static void f();
    };
    void g() { A::f(); }
  }


3/16/09 [EDGcpfe/9622]
Internal error on ambiguous using-directive lookup with EXPENSIVE_CHECKING

An internal error could occur (in add_symbol_to_lookup_set) in versions
with EXPENSIVE_CHECKING enabled when a symbol for an ambiguous using-directive
lookup is reused.  Now fixed.

  namespace N {
    typedef int g ; 
  }
  using namespace N;
  void g() {
    g();
    g();
  }


3/16/09 [EDGcpfe/9619]
Instantiation based on nonreal type not always considered nonreal

An instantiation of a class template based on a nonreal class that does
not directly depend on a template parameter incorrectly resulted in a
real instantiation instead of a nonreal one.  This could result in
various kinds of incorrect behavior and/or internal errors.  This has
been fixed.  The example below resulted in an internal error in
prep_generic_operand_full.

  template <class T> struct A {
    template <class U> static T f() { }
    static int g(int i = f<T>()());
  };

  template <class T> void h() {
    class Q {};
    A<Q> a;
    a.g();
  }


3/16/09 [EDGcpfe/9550]
Local type used as template type argument leads to incorrect generated C

In modes where local types can be used as template type arguments (i.e.,
--c++0x and --microsoft_version >= 1400), the definition of the local type
in the generated C code may follow its use in the template, causing an
error when compiling the generated C code.  A change has been made to sort
the file types list (when ENSURE_LOWERED_TYPE_LIST_ORDERING is TRUE) whenever
the front end detects that a local type has been used as a template type
argument.  Back ends that require a type definition to precede its use (such
as the C generating back end) should set ENSURE_LOWERED_TYPE_LIST_ORDERING to
TRUE.  For example:

  template <class T> struct S {
    T m;          // had generated "error: field `m' has incomplete type"
  };              // when generated C was compiled
  void f() {
    struct A {};
    S<A> s;
  }


3/13/09 [EDGcpfe/9605]
Abort in lowering on some operations involving rvalue class adjustments

Certain expressions involving rvalue class adjustments (e.g., on a question
mark expression with a throw operand) could cause an assertion failure during
lowering (in optimize_node_if_possible).  Similar cases can also cause an abort
in c_gen_be (internal error: wrong result type for &).  This regression was
introduced in 4.0.  This example had aborted and is now fixed:

  struct A {};
  A f(int i, const A& x) {
    return i ? throw : x;   // assertion failure in optimize_node_if_possible
  }


3/13/09 [EDGcpfe/6929,EDGcpfe/9615]
Abort on invalid designated initializer in C++ mode

In C++ modes with designated initializers enabled (e.g., GNU C++ mode), the
front end triggered an internal error "get_field_designator: non-field member"
(decl_inits.c) when a designator referred to a member that was was not a
nonstatic data member.  For example:

  struct S { static int x; };
  S s = { .i = 0 };  // Previously triggered an internal error.

This is now fixed.


3/13/09 [EDGcpfe/9612]
Invalid generated C code for some delayed nested class definitions

In some cases, delayed nested class definitions (accepted in GNU and
Microsoft modes) resulted in generated C code that produced errors when
compiled.  This is now fixed.  For example:

  struct A {
    struct B {
      struct C;
    } b;
    struct B::C {     // delayed nested class definition
      void f() {}
    } x;              // had generated "error: field `x' has incomplete type"
  } a;                // diagnostic when compiling generated C
                      
  int main() {
    a.x.f();
  }


3/13/09 [EDGcpfe/9608]
Internal error on using-declaration in local class of a function template

A using-declaration in a local class of a function template could trigger an
internal error in member_using_declaration (class_decl.c).  For example:

  template <class T> void f() {
    struct B : T { };
    struct D : B {
      using B::m;  // Previously aborted with an internal error.
    };
  }

This is now fixed.


3/13/09 [EDGcpfe/9597]
Warning on unreachable loops

Previously, the front end issued a warning if a loop construct was not
reachable sequentially from the preceding statement.  This warning was
frequently misunderstood when the loop was reachable via a goto or switch into
the loop body.  A warning is now only issued when a loop does not contain a
label definition or an active switch case.  For example:

  void f() {
    goto middle;
    while (1) { // Warning ("loop is not reachable from preceding code") no
  middle:;      // longer issued because the loop contains a label definition.
    }
  }


3/13/09  [EDGcpfe/9611]
Change IA-64 mangled encoding of Microsoft explicitly overridden functions

The IA-64 ABI mangling of Microsoft explicitly overridden functions
used the local extension 'O' (see the Changes entry of 7/18/03).  The letter
'O' has since been designated to encode rvalue references in the IA-64 ABI.
To avoid a conflict, the letter 'Q' will now be used as a local extension to
the IA-64 ABI when encoding Microsoft explicitly overridden functions.
The Cfront ABI is unchanged.


3/13/09  [EDGcpfe/9609]
Internal error on use of union with nonreal base class

A union cannot have base classes.  If an attempt was made to declare
a union with a nonreal base class, an internal error (in
create_nonreal_progenitor_symbol) could occur later on a reference
to a member not found in the union.  Now fixed.

  template <class T> int f(T x) {
    union A : T { };
    A a;
    return a.T::f();  // internal error here
  }


3/13/09  [EDGcpfe/9607]
Preventing UNICODE mode from being used to build on Windows

The front end is not intended to be built in UNICODE mode on Windows.
Doing so results in warnings and can result in incorrect behavior if
those warnings are not addressed.  A #error test has been added to
ensure that UNICODE mode is not inadvertently used to build the front
end.


3/12/09  [EDGcpfe/9595]
Exception-specification mismatch on function declared with a typedef

When a function is first declared using a typedef type for the function type,
a redeclaration of that function with a conflicting exception-specification
failed to elicit a diagnostic.  For example:

  typedef void F();
  F f;
  void f() throw() {}  // Previously failed to elicit an error.

This is now fixed.


3/12/09  [EDGcpfe/9274, EDGcpfe/9567]
Abort when VLA typedef is promoted from local scope during lowering

In C++ configurations where VLAs are allowed and not lowered (i.e.,
LOWER_VARIABLE_LENGTH_ARRAYS is FALSE), a VLA typedef occurring in a local
scope would cause a write-read error to occur.  This has now been fixed.
For example:

  void f(int n) {
    struct A { void f() {} };   // causes lowering to promote all local types
    typedef int T[n];           // VLA typedef had caused an abort
  }


2/27/09  [EDGcpfe/9313, EDGcpfe/9575]
GNU compatibility: V16 vector mode name prefix

In GNU modes, the front end now accepts "V16" as a vector mode name prefix.
For example:

  typedef int v16qi __attribute((mode(V16QI)));  // Now accepted in GNU modes.


2/27/09  [EDGcpfe/9161]
C++0x: "auto" is always a type specifier

In C++0x mode, the traditional meaning of "auto" as a storage class specifier
is no longer enabled.  "auto" is thus always a type specifier in C++0x.
For example:

  typedef int T;
  int x;
  void f() {
    auto T(x);   // This is now the declaration of a variable T initialized
                 // with x (and hence of the same type as x).  Previously, it
                 // was the declaration of a variable x of type T.
    auto int y;  // Now an error: Multiple type specifiers.
  }

This change was voted into the C++ committee's working paper for the next
standard in February 2008 (meeting in Bellevue, through proposal numbered
N2546).


2/26/09  [EDGcpfe/9577]
Abort on decltype applied to template-dependent cast

The front end aborted in decltype_from_operand in expr.c on processing
a decltype operator whose operand is an old-style cast that is
template-dependent.  Now fixed.

  template <class T, T I> void f() {
    decltype((T *)I) y;  // Aborted with --c++0x --strict
  }


2/26/09  [EDGcpfe/9572]
Abort on reinterpret_cast of overloaded function to reference type

The front end sometimes aborted on processing a reinterpret_cast from
an overloaded function to a reference type.  An error is now issued
instead.

  void f();
  void f(int);
  int main() {
    reinterpret_cast<void (&)()>(f);
  }


2/25/09  [EDGcpfe/9558]
GNU C compatibility: Field conflicts with anonymous unions

In GNU C mode, more cases of fields from anonymous unions (a GNU extension in
C mode) conflicting with a field of the same name in an enclosing class are
now accepted.  (See also the Changes entries of 1/12/05 and 2/27/03).
For example:

  struct S {
    int c;
    union {
      int u;
      float c;  // Conflicts with field c of type int.  Now accepted in
    };          // GNU C mode.
  };


2/24/09  [EDGcpfe/9561]
Delete of pointer-to-array treated as delete[]

A delete of a pointer-to-array type, which has undefined behavior according
to the C++ standard, is now treated as a delete[] of the underlying array.
(g++ and MSVC++ both handle such a case in that way.)

  int main() {
    int *p = new int[100];
    int (*q)[100] = (int (*)[100])p;
    delete q;  // Now means the same as "delete[] (int *)q"
  }


2/23/09  [EDGcpfe/9560]
Restrict-qualified member functions

Previously, in C++ modes that accept a restrict qualifier on a member function
declaration, the front end treated that qualifier as participating in the type
of the member function.  Now, this is not the case.  For example:

  struct S {
    void f();
  };
  void S::f() restrict {  // Now accepted in C++ modes that accept "restrict",
    // ...                // even though it doesn't match the original
  }                       // declaration.  "this" is a restrict-qualified
                          // pointer in the function definition.

Note that unlike the standard cv-qualifiers on member function declarations
(which are qualifiers for the type pointed to by this), "restrict" is a top-
level qualifier for the hidden "this" parameter.  The new behavior is thus a
correction that treats qualifiers on "this" like qualifiers on other
parameters.

This change involves an IL CHANGE: The "restrict" qualifier (TQ_RESTRICT) is
now recorded in the new "this_qualifiers" field of the routine type
supplement for the member function, and not in its "qualifiers" field.

This change also has an ABI implication: Previously, the "restrict" qualifier
on member functions was erroneously encoded into the mangled name of the
member function.  That is no longer the case.


2/23/09  [EDGcpfe/9560]
GNU C++ compatibility: __restrict on typedefs and template parameters

In GNU C++ mode, the front end now ignores __restrict on typedef types if the
underlying type of the typedef is not a pointer type.  Similarly, __restrict
is ignored on template parameters if the corresponding argument is not a
pointer type.  For example:

  typedef float F;
  F __restrict f;  // Now accepted in g++ mode.

A remark is issued in such cases.


2/23/09  [EDGcpfe/9565]
Type comparison should compare qualifiers even with no "this" class

When comparing routine types, the front end failed to compare the qualifiers
if neither type had a "this" class.  As a result, in the example below
the declaration of a2 would find the type created by the declaration of a1
instead of attempting to generate a new instance of A.

  template <class T> struct A;
  template <class T> struct A<T ()> { };
  typedef int F() const;
  A<int ()> a1;
  A<F> a2;  // previously accepted if a1 was present, now
            // "incomplete type not allowed" (because F does not match the
            // partial specialization)


2/23/09  [EDGcpfe/9559]
GNU C++ compatibility: extra template parameter list on partial specialization

g++ allows an extra empty template parameter list to be specified in the
declaration of a partial specialization.  We now provide limited support
for this feature in g++ mode.  The support is limited to cases in which
the partial specialization has no out-of-class definitions of its members.
Because we only provide limited support of this feature, our default action
in g++ mode is to reduce the severity of the diagnostic for this case from
an error to a discretionary error.  Users can then reduce the severity
further if needed.  The severity will actually also be reduced for the
unsupported cases (i.e., those with out-of-class definitions), but an error
will be issued on any such out-of-class definitions because the extra
template parameter list is not in fact ignored.

  template <class T> struct A {};
  template <> template <class T> struct A<T*> { };


2/20/09  [EDGcpfe/9373]
New predefined macros for types of size_t and ptrdiff_t

Two EDG-specific predefined macros have been added: the value of the new
__EDG_SIZE_TYPE__ macro is the type of size_t; the value of
__EDG_PTRDIFF_TYPE__ is the type of ptrdiff_t.  Similar predefined macros
__SIZE_TYPE__ and __PTRDIFF_TYPE__ were already available in Linux
configurations.  Here is an example:

  #include <typeinfo>
  int main() {
    // Returns zero in all configurations.
    return typeid(__EDG_SIZE_TYPE__) != typeid(sizeof(int)) ||
           typeid(__EDG_PTRDIFF_TYPE__) != typeid((char *)0 - (char *)0);
  }


2/20/09  [EDGcpfe/9084, EDGcpfe/9664]
IA-64 ABI constructor/destructor changes

In IA-64 ABI versions through (and including) 4.0, construction/destruction of
virtual base class objects was delegated from the complete object
constructor/destructor to the subobject constructor/destructor; such delegation
was indicated at run-time by passing a NULL for the construction vtable
argument to the subobject constructor/destructor.  The IA-64 ABI (in section
3.3.1) doesn't allow for the possibility of a NULL VTT argument, causing a
potential run-time issue if an EDG-generated complete constructor/destructor
were to invoke a GNU generated constructor/destructor.  In practice this is
rare because the complete and subobject constructor/destructors are typically
emitted in the same translation unit.  In versions after 4.0, the default
behavior has changed to handle virtual bases in the complete object
constructor/destructor (HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS is TRUE)
and not in the subobject constructor/destructor
(HANDLE_VIRTUAL_BASES_IN_SUBOBJECT_CTOR_DTORS is FALSE).  This behavior can be
altered by setting these configuration macros individually (at least one must
be TRUE).  In particular, if the possibility exists that a pre-4.0 complete
object constructor/destructor can call a post-4.0 subobject
constructor/destructor, then HANDLE_VIRTUAL_BASES_IN_SUBOBJECT_CTOR_DTORS
should be set to TRUE.  Setting both flags to TRUE will ensure IA-64 ABI
compatibility as well as backward compatibility (at the cost of larger
constructor/destructors).  The Cfront ABI handling is unchanged.  This is
an ABI change for IA-64 ABI configurations.


2/19/09  [EDGcpfe/9446]
Microsoft compatibility: casts to ambiguous direct base classes

The Microsoft compiler allows casts and implicit conversions from a
pointer to a class to a pointer to an ambiguous base class in certain
contexts, if one instance of the ambiguous base class is a direct base.
We now emulate that behavior in Microsoft bugs mode.

  __interface IUnknown {};
  class D1: public IUnknown {};
  class D2: public D1, public IUnknown {};
  int main() {
    D2 d;
    IUnknown * p = static_cast<IUnknown*>(&d);  // Allowed, with a warning
  }


2/18/09  [EDGcpfe/9522]
Microsoft compatibility: __ptr64 on 64-bit targets

Microsoft compilers appear to ignore the __ptr64 modifier for 64-bit targets.
Although the front end still records __ptr64 on 64-bit targets, it now ignores
that modifier for type-equivalence purposes.  For example:

  extern int *p;
  int *__ptr64 p;  // Now accepted on 64-bit platforms.

Note that the target is considered to be "64-bit" if the target settings for
size_t correspond to a 64-bit type.  Also note that there is no similar
behavior for __ptr32 on 32-bit platforms.


2/18/09  [EDGcpfe/9519]
Microsoft compatibility: For-init-scope and condition-scope hiding

In Microsoft C++ mode, the front end now allows declaring a variable in a
loop with the same name as a for-init-scope or condition-scope declaration
if a for-statement previously appeared in the loop.  For example:

  void f() {
    for (int i = 0; int c = i<10 ; ++i) {
      for (; 0;);
      int i, c;  // Now accepted in all Microsoft C++ modes.
    }
  }

Some such cases were already accepted when microsoft_version < 1400 because of
nonstandard for-init scope rules in those modes (e.g., see Changes entry of
3/16/07), but now they are also accepted when microsoft_version >= 1400.


2/18/09  [EDGcpfe/9539]
Removal of dead code in logical operations caused internal error

In configurations that use lowering, the removal of dead code in logical
operations (i.e., || or &&) could sometimes erroneously change the type
of the expression, causing the C generating back end to complain about
a mismatched type (e.g., "internal error: dump_expr: bad type on eok_comma").
This regression was introduced in 4.0 and is now fixed.  For example, these
statements had all caused internal errors in dump_expr:

  void f(int i) {
    i, 1 || i;            
    i ? 1 || i : 0 || i;
    [&]{ return i , 1 && i; }();    // with --c++0x
  }


2/18/09  [EDGcpfe/9542]
Microsoft compatibility: internal error on invalid class template

In Microsoft mode, when microsoft_version is >= 1400, an internal error
could occur in instantiate_class_template on a class template declaration
with an extra identifier between the class name and the class definition.
Now fixed.

  template <class T> class A B {};


2/18/09  [EDGcpfe/9546]
C++0x: missing diagnostic on enumeration used in pointer-to-member

In C++0x, some enumeration types can be used in qualified names.  However,
the front end failed to diagnose the use of an enumeration type in a
pointer-to-member declarator.  In most cases this was silently accepted, but 
could result in an internal error or other incorrect behavior.  Now fixed.

  enum class E { e1 };
  int E::* x;


2/17/09  [EDGcpfe/9549]
Abort on enum definition with global scope qualifier

The front end aborted in move_to_end_of_types_list (in il.c) when processing
an enum definition with a global scope qualifier outside the global scope.
For example:

  enum E *p;
  namespace N {
    enum ::E { e };  // Previously triggered an abort.
  }

This is now fixed (an error is issued on such cases).


2/17/09  [EDGcpfe/8805, EDGcpfe/9547]
Local classes and prototype instantiations

Previously, the front end did not record local classes in function templates
in the types list of their associated scope.  This could lead to incorrect
code generation by the C++-generating back end when templates are rendered
from prototype instantiations (when PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE and
templates are parsed in their generic form, e.g. because of a command-line
option like "--parse_templates" or "--strict").  For example:

  template<class T> void f() {
    struct B { typedef int I; };
    struct D: B {
      typedef B::I I;  // In some circumstances the typedef was previously
    };                 // rendered as "typedef I I;".
  }

This is now fixed.


2/17/09  [EDGcpfe/9510]
Abort on decltype applied to member function name

The front end aborted in make_node_from_operand ("converting unexpected
operand kind") while processing a use of decltype applied to the
name of a member function.  Now fixed (an error is issued).

  struct A {
    void f(double);
    template < class T > decltype(f) g( T ) { }  // Formerly provoked abort
  };


2/15/09  [EDGcpfe/9532]
Abort on decltype of nontype template parameter

The front end aborted in decltype_from_operand in expr.c on a use of
decltype applied to a nontype template parameter identitier.  Now fixed.

  template <class U, U I> inline void f() {
    auto x2 = sizeof (decltype(I));  // Formerly caused an abort
  }
  int main() {
    f<int, 1>();
  }


2/14/09  [EDGcpfe/9166]
Lambdas

The front end now implements lambda functions, a C++0X feature described
in N2550.  The feature is enabled in --c++0x mode, and can also be
enabled or disabled separately via --lambdas, --no_lambdas, and
the DEFAULT_LAMBDAS_ENABLED macro.

The present version implements the mutable keyword of N2658, but not
the requirement that in certain cases the closure class has
std::reference_closure as a base class (the standards committee
eliminated that requirement later).


2/13/09  [EDGcpfe/9538]
Parent scope of "this" parameter

Previously, the a_variable entry associated with an implicit "this" parameter
had its parent scope set to NULL.  Now, the parent scope of the "this"
parameter variable is the associated member function scope.


2/13/09  [EDGcpfe/9508]
Source positions of enk_routine node in call with implicit "this"

In configurations in which EXTRA_SOURCE_POSITIONS_IN_IL is TRUE,
enk_routine nodes that are operands of an eok_points_to_member_call in
which the object expression is implicitly "this" were missing their
expr_range source positions.  Now fixed.  For example:

  struct S {
    void f();
    void g() {
      f();    // enk_routine now has expr_range positions
    }
  }


2/12/09  [EDGcpfe/9507]
Source positions of enk_variable nodes with reference type

In configurations in which EXTRA_SOURCE_POSITIONS_IN_IL is TRUE,
enk_variable nodes with reference type that should have had expr_range
information were missing those source positions.  Now fixed.  For example:

  void f(int& a) {
    a = 5;    // enk_variable node now has expr_range positions
  }


2/12/09  [EDGcpfe/9480]
Source positions of function call expression nodes

In configurations in which EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, function
call nodes (eok_call, etc.) that should have had expr_range and
operator_position information were missing those source positions if they
appeared under an enk_temp_init or an eok_ref_indirect expression node.
This is now fixed.  For example:

  struct S { S(const S&); };
  S& f_ref();
  S f_copy();
  void f() {
    f_ref();    // eok_call node now has source positions
    f_copy();   // eok_call_node now has source positions
  }


2/12/09  [EDGcpfe/9521]
Representation of empty statements (IL CHANGE)

The configuration macro REPRESENT_EMPTY_STATEMENTS_IN_IL has been removed.
Empty statements are now always represented using statement entries of kind
stmk_empty (this previously corresponded to REPRESENT_EMPTY_STATEMENTS_IN_IL
set to TRUE).  This is an IL CHANGE for configurations that previously had
REPRESENT_EMPTY_STATEMENTS_IN_IL set to FALSE (explicitly, or by default).
See also the Changes entry of 12/15/99.


2/12/09  [EDGcpfe/9536]
Abort on new of dependent array of error type

The front end aborted (in select_destructor) on processing a new of
an array type whose bounds are template-dependent and whose element type
is unknown because of an error.  Now fixed.

  template <int I> void f() {
    new X[I+1]();  // Previously aborted in --strict mode
                   // X is undefined, so the element type is an error
  }


2/12/09  [EDGcpfe/9529]
Abort on Microsoft-mode in-class specialization appearing in a class template

When performing nonclass prototype instantiations in Microsoft mode (i.e.,
with the command-line options "--microsoft --parse_templates") in
configurations that have TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
and FRIEND_AND_MEMBER_DEFINITIONS_MAY_BE_MOVED_OUT_OF_CLASS set to TRUE,
the front end aborted in inline_function_fixup_for_class when dealing with
a Microsoft-mode in-class specialization appearing in a class template.
For example:

  template<class T> struct S {
    template<class U> T f(U) {}
    template<> T f(int) {}  // Triggered an abort under some circumstances.
  };

This is now fixed.


2/12/09  [EDGcpfe/9447]
Microsoft compatibility: support for additional attributes

In Microsoft mode, the front end now supports the following additional
attributes: as_expression, as_string, attribute, custom, default_value,
defaultvtable, help_string, hook, multi_value, notify_atlprov, optional,
process_early, repeatable, requires_value, soap_namespace, unhook, usage,
v1_alttype, v1_early, and v1_name.  These attributes are only supported
to the extent that their names are recognized as valid attributes.  No
attempt is made to verify that they are used in appropriate locations or
that their arguments are acceptable.


2/11/09  [EDGcpfe/9527,EDGcpfe/9551]
Abort when a const string literal is explicitly cast

An explicit cast of a const string literal caused an assertion
failure in lower_operation_on_const_string_if_necessary in modes where string
literals are treated as const (e.g., GNU, Microsoft, Sun, strict).  Casts to
references as well as other types of casts could lead to this failure.
This regression was introduced in 4.0 and is now fixed.  For example:

  template <class T> T f() {
    return (T&) "zzz";  // cast to reference caused an assertion failure
  }
  void g() {
    f<char>();
    1, void("xxx");    // explicit cast caused an assertion failure
  }


2/11/09  [EDGcpfe/9520]
Microsoft compatibility: Explicit template arguments on function templates

In Microsoft mode, the front end now ignores (with a warning) explicit
template arguments that appear on a non-member function template
redeclaration.  For example:

  template<typename T> void f();
  template<typename T> void f<T>();      // <T> ignored with a warning.
  template<typename T> void f<int*>() {} // <int*> ignored with a warning;
                                         // this defines the previously
                                         // declared template.


2/6/09   [EDGcpfe/9512]
Abort when a local type is introduced outside a declaration

In C++ modes with DO_IL_LOWERING set to TRUE, the front end sometimes aborted
in delete_types_from_decl_stmts (lower_il.c) if a local type was introduced
outside a declaration (e.g., in a cast) in a function that also contained a
local class with a member function.  For example:

  void g() {
    struct L { void f() {} };  // Local class with member function.
    (enum E*)0;                // Local enum type introduced outside a
  }                            // declaration.  This caused lowering to abort.

This is now fixed.


2/5/09   [EDGcpfe/9488]
Abort on invalid enum-qualified name in C++0x mode

The front end previously aborted in class_qualified_id_lookup (lookup.c) on
certain invalid uses of enum qualifiers.  For example:

  enum E {};
  E::X int;  // Triggered an abort in C++0x mode.

This is now fixed.


2/4/09   [EDGcpfe/9500]
Display of switch case entries

The IL display utility displayed an incorrect value for the next_on_sorted_list
field of a switch case entry.  Now fixed.

2/3/09   [EDGcpfe/9489]
Parent scopes of function prototype scopes

IL CHANGE: Previously, the parent pointer of a function prototype scope entry
pointed to that entry itself.  Now, the parent pointer of a function prototype
scope is NULL, unless that scope is nested in another function prototype scope
(in which case the pointer points to the latter scope).


2/3/09   [EDGcpfe/9490]
Spurious error on member function call in presence of selective overriders

In Microsoft mode, a call to a member function could result in a spurious
error if that member was part of an overload set containing multiple selective
overriders (a Microsoft extension).  For example:

  __interface I1 { void f(); };
  __interface I2 { void f(); };
  struct D: I1, I2 {
    void I1::f() {}
    void I2::f() {}
    int f(int);
  } d;
  int x = d.f(3);  // Previously resulted in a spurious error.

This is now fixed.


2/1/09   [EDGcpfe/9491]
Microsoft C++ compatibility: conversion of const string literal to void *

In Microsoft C++ mode, a const string literal is now considered to be
convertible to void * for argument passing in overload resolution.
Formerly, this deprecated conversion was allowed in other contexts but
not in overload resolution.  (See the Changes entry of 4/21/05.)

  void foo(int, void *);
  void foo(const char *, void *);
  int main() {
    foo("","");  // No longer ambiguous with microsoft_version=1310
  }


1/30/09  [EDGcpfe/9496]
Abort on certain complex initializers for static data members

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, static data member initializers
containing definitions of class types of functions triggered an abort in
add_src_seq_end_of_variable_if_needed (decls.c).  For example:

  struct S {
    static void *x[1];
  };
  void *S::x[1] = { (void*)(struct X {}*)0 }; // Triggered an abort.

This is now fixed.  (Such constructs are invalid in standard C++, but accepted
in GNU C++ mode.)


1/30/09  [EDGcpfe/9495]
Microsoft compatibility: allow "typename void"

The Microsoft compiler allows "typename void" to be used in template
declarations as equivalent to just "void" to indicate a function with
no parameters.  We now accept this in Microsoft bugs mode.

  template <class T> void f(typename void) {}


1/30/09  [EDGcpfe/9494]
C++-generating back end: abort with "auto" type specifier

In configurations in which IL_SHOULD_BE_WRITTEN_TO_FILE is TRUE and
PROTOTYPE_INSTANTIATIONS_IN_IL is FALSE, a local variable defined with the
"auto" type specifier could cause an abort in the C++-generating back end.
Now fixed.  For example:

  void f() {
    auto x = 5;    // Previously aborted generating this definition
  }


1/29/09  [EDGcpfe/8401]
Microsoft compatibility: typename in expressions in template instantiations

The Microsoft compiler allows the typename keyword to be used in expressions
in template contexts when it is not followed by a type.  We now accept this
usage in Microsoft bugs mode (with a warning).  In addition, similar
support for incorrect uses of typename in declarations (10/20/08, 6/1/08,
4/17/06, 5/6/03) is now controlled by microsoft_bugs instead of
microsoft_mode.

  struct A {
    static int f() { return 0; }
  };
  template <class T> inline void f(T) {
    // now allowed in Microsoft mode (formerly '"A::f" is not a type name')
    int x = typename A::f();
  }
  int main() {
    f(1);
  }


1/27/09  [EDGcpfe/9479]
Microsoft compatibility: macro expansion in attributes

Macros are now expanded in Microsoft attributes (which are accepted in
Microsoft mode).

  #define MY_UUID "366BD604-AE26-4F01-A44D-A2F557BB3165"
  [ uuid( MY_UUID ) ] class A {};  // now accepted


1/27/09  [EDGcpfe/9466, EDGcpfe/9481]
GNU compatibility: Implicit conversions between vector types

In GNU modes with gnu_version >= 40000 and gnu_version < 40300, the front end
now accepts (with a warning) implicit conversions between vector types of the
same size (in bytes) and the same kind (i.e., both vectors must be floating-
point vectors, or both must be integer vectors), but with differing element
types.  For example:

  typedef int v4i __attribute((vector_size(16)));
  typedef short v8s __attribute((vector_size(16)));
  v8s f(v4i x) {
    return x;  // Now accepted in some GNU modes.
  }

(GNU_VECTOR_TYPES_ALLOWED must be TRUE to enable vector types.)


1/26/09  [EDGcpfe/9467]
Cast of rvalue to same type retained in gcc mode

In GNU C mode, casts of an expression to the same type are
deleted because we believe gcc does that, which is visible in the
way that gcc allows such expressions to be used as lvalues.  However,
when the operand is an rvalue there's no compatibility issue (the
result of the cast is an rvalue either way), so we now retain the
cast in such cases, which provides IL that is closer to the source form.


1/26/09  [EDGcpfe/9473]
Microsoft compatibility: dropping __restrict on arguments

In Microsoft mode, when __restrict is accepted (microsoft_version >= 1400),
the __restrict qualifier is now allowed to be dropped on argument matches
in overload resolution and in direct reference binding.  See the Changes
entry of 8/15/08 for the previous change in this area.

  template <class T> struct C {
    void foo();
    void foo(const T& src );
  };
  void f() {
   int* __restrict pGroup;
   int *const &r = pGroup;  // Now accepted
   C<int*> c;
   c.foo(pGroup);  // Now accepted (formerly, no function matched)
  }


1/23/09  [EDGcpfe/9468]
GNU compatibility, C- and C++-generating back ends: position of vector_size
attribute

In configurations with GNU_VECTOR_TYPES_ALLOWED, the C-generating and
C++-generating back ends generated typedefs for vector types by placing the
vector_size attribute at the beginning of the declaration, preceding the
element type, while an alignment attribute (if any) appeared following the
typedef name.  Versions 4.1 and newer of the GNU compilers issue an error
with this style of declaration if the vector size is such that the default
alignment is too small.  The front end has been changed to address this
problem by moving the vector_size attribute in a typedef declaration to
follow the typedef name as well.  For example:

  typedef int v16i __attribute__((vector_size(16), aligned(16)));
  // Formerly generated as
  //
  //   typedef __attribute__((vector_size(16))) int v16i
  //                                           __attribute__((aligned(16)))
  //
  // Now generated as
  //
  //   typedef int v16i __attribute__((vector_size(16)))
  //                                           __attribute__((aligned(16)))


1/23/09  [EDGcpfe/9469]
GNU compatibility: Parameter types of builtin __sync_... functions

In GNU modes, the front end accepts various built-in functions for atomic
memory access when the configuration macro GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED
is TRUE (see Changes entry of 7/31/07).  Previously, the front end
predeclared those functions assuming that the integer types unsigned short,
unsigned int, and unsigned long had sizes 2, 4, and 8, respectively.  This is
commonly true in 64-bit environments, but not in 32-bit environments.  Since
32-bit versions of GCC also support these functions, the front end now selects
integral types of sizes 2, 4, and 8, based on the target configuration, and
uses those to predeclare the __sync_... function parameter types as
appropriate (an internal error may be triggered if no integer type of the
appropriate size is available for the target configuration).
 

1/23/09  [EDGcpfe/9448]
Microsoft compatibility: accept UUID strings without quotes in attributes 

The Microsoft compiler allows a UUID string to be specified in an attribute
without surrounding quotes.  We now accept this in Microsoft mode when
Microsoft attributes are enabled.

  [uuid(066BD604-AE26-4F01-A44D-B2F557BB3165)] class A {};


1/23/09  [EDGcpfe/9464]
Microsoft compatibility: __restrict on constructors and destructors

In Microsoft mode with microsoft_version >= 1400, the front end now accepts
the keyword __restrict on destructors.  The qualifier affects the signature
of the destructor.  For example:

  struct D { ~D() __restrict; };  // Accepted in Microsoft mode.
  D::~D() {}                      // Error: missing __restrict.

In addition, __restrict is also accepted on out-of-class constructor
definitions, but in those cases, it is ignored (with a warning).

  struct C { C(); };    // __restrict would not be accepted here.
  C::C() __restrict {}  // Accepted in Microsoft mode (__restrict ignored).


1/23/09  [EDGcpfe/9458, EDGcpfe/4641]
Cast of non-class expression to reference-to-const non-class now allowed

A cast of an expression with non-class type to a reference to const of
a different type is now accepted, if the source expression can be
converted to the underlying type of the reference.  For example:

  int main() {
    static_cast<const long &>(123);  // Now accepted
  }

The source expression is converted into a temporary of the underlying
type of the cast, and an lvalue for the temporary is returned as the
result.


1/23/09  [EDGcpfe/9475]
Invalid IL for compound assignments with GNU vectors

In GNU modes, the front end generated a spurious cast on the second operand
of certain compound assignments with GNU vector operands.  This also caused
the C-generating back end to produce invalid output.  For example:

  typedef int V __attribute((vector_size(16)));
  void f(V v1, V v2) {
    v1 -= v2;  // Previously, a spurious cast to int was generated on top of
  }            // the v2 operand.

This is now fixed.


1/22/09  [EDGcpfe/9456]
Microsoft-mode explicit overriders and dependent base classes (IL CHANGE)

In Microsoft mode, the front end accepts a construct to indicate that a
pure virtual function from a specific base class should be overridden (see
Changes entry of 7/18/03).  However, the front end did not properly handle
explicitly overriding a member of a template-dependent base class.
For example:

  struct B { virtual void f() = 0; };
  template<typename T> struct X: T {
    void T::f() {}  // Previously triggered an error because T was not
  };                // recognized to be a base of X<T>.

More complex examples were prone to abort.  This is now fixed.

IL CHANGE: The fix included replacing the overridden_function field of
a_routine (a_routine*) by an overridden_functions list (an_il_entity_list*).


1/21/09  [EDGcpfe/9368]
Microsoft compatibility: even more on ADL and friend injection

We have made several changes over the years (see 5/24/06 entry for the
most recent one) to emulate the friend visibility quirks of MSVC++ 7.1
and newer versions.  We have determined that our previous emulations did not
accurately reflect the underlying mechanism being used by the Microsoft
compiler.  We have now implemented what we believe to be a more faithful
emulation of their behavior.  The Microsoft compiler does not search
namespaces during argument-dependent lookup if those namespaces were
searched during the normal lookup.  In addition, operator functions that
are defined in friend function declarations and are called using operator
notation are not visible when found by a normal lookup.  This new mechanism
replaces the earlier emulations that we provided.

The rework was motivated by the example below.  In Microsoft mode we
failed to find N::operator<= for the call.  This is now fixed.

  namespace N {
    struct A {};
    template <class T, class U> struct B {
      friend bool operator<=(const T& x, const U& y) { return false; }
    };
    template struct B<A, A>;
  }

  namespace M {
    class C {
      N::A temp1,temp2;
      void foo(){
        temp1 <= temp2;  // spurious 'no matching "<="'
      }  
    };
  }


1/21/09  [EDGcpfe/9410]
Overflow in size calculation for text buffer allocation

To perform macro expansion, the front end maintains several extensible text
buffers; when they become full, a new buffer is allocated and the contents
copied.  The interface of the functions controlling this reallocation
typically involves a sizeof_t parameter specifying the amount of additional
space required, and the new buffer size is calculated from that and the
current allocation size.  This calculation could conceivably overflow the
sizeof_t variable used for the result, which could cause allocation of a
too-small buffer and consequently overwrite other memory.  The front end
now checks for such overflows and aborts with a catastrophic error if one
occurs.


1/21/09  [EDGcpfe/8628]
Enable exceptions in Microsoft C++ mode

Exceptions are now enabled by default in Microsoft C++ mode.  Exceptions can
be explicitly disabled using the --no_exceptions command line argument.
Additionally, an optional, one-time warning (similar to the one emitted by
MSVC++ when no /EH option is given) is issued (in Microsoft mode) when a try
statement or function try block is encountered.  This new warning is
controlled by a new global variable, warn_on_try_statement, whose initial
value is FALSE.  Implementations wishing to emulate this Microsoft behavior
should set warn_on_try_statement to TRUE.


1/20/09  [EDGcpfe/9462]
Microsoft compatibility: Interface templates

In Microsoft mode, interface templates are now accepted.  For example:

  template<typename T> __interface IF {
    void f(T);
  };

(See also the Changes entry of 6/2/03 that introduced non-template interface
class types.)


1/19/09  [EDGcpfe/9449]
Spurious errors on some uses of __sptr/__uptr in Microsoft C++ mode

Although the front end supports __sptr/__uptr in Microsoft mode (see the
entry of 5/22/07), some valid uses triggered spurious errors in Microsoft
C++ mode.  For example:

  int* __uptr p = (int* __uptr)(0xFFFFFFFF);  // Previously a spurious error.

This is now fixed.


1/19/09  [EDGcpfe/9202, EDGcpfe/9450]
Some dynamic_casts allowed even when RTTI is disabled

Formerly, when RTTI (runtime type information) is disabled (e.g.,
with --no_rtti), the dynamic_cast operator was not permitted at
all -- in fact, the keyword was not even recognized.  Now,
dynamic_cast operations that can be done without use of runtime
type information are permitted even when RTTI is disabled.
In addition, when the IA-64 ABI is used, a dynamic_cast to void *
is also permitted, because the IA-64 ABI has a way of getting from
an object to its complete object without using RTTI.  One reason
we have made this change is that g++ accepts such cases.

  struct A {
    virtual ~A() { }
  };
  struct B : A {};
  A* f();
  void foo(B* pb) {
    A *p = dynamic_cast<A *>(pb);      // Now accepted with --no_rtti
    void* v = dynamic_cast<void*>(pb); // Now accepted with --no_rtti, IA-64
    B* b = dynamic_cast<B*>(f());      // Still not accepted with --no_rtti
  }


1/19/09  [EDGcpfe/9457]
GNU C++ compatibility: Visibility of a static const member in its initializer

In GNU C++ mode, a static const class member with an in-class initializer is
now invisible until the end of the initializer.  (This same behavior was
already implemented in Microsoft bugs mode: See the Changes entry of 11/7/07.)
For example:

  enum { x = 3 };
  struct y { static int const x = x; };  // Now accepted in GNU mode.

Note that this matches the GNU behavior, but GCC often diagnoses such cases
because it checks that certain identifiers used in a class definition retain
their meaning when reconsidered in the context of the completed definition.
(This check is permitted by the C++ standard but not currently performed by
the EDG front end.)  E.g., the example above elicits an error from g++, but
the following similar example does not:

  template<int V> struct x { enum { N = V }; };
  struct y { static int const x = x<3>::N; };  // Now accepted in GNU mode.


1/16/09  [EDGcpfe/9461]
Invalid next pointer on constant, with template, IA-64 ABI, multiple
  translation units

In some convoluted cases involving the IA-64 ABI, multiple translation
units, templates, and a set of string constants that happen to hash to the
same bucket of the shareable constants table, the "next" pointer on
certain shared constants was not cleared, and as a consequence IL
traversal operations later might have gotten an internal error.  In
particular, when an IL write and read using the alternate file format
was done, it detected a write-read error.  Now fixed.

1/15/09  [EDGcpfe/9441]
GNU compatibility: __real/__imag and integral arguments

In GNU C and C++ mode, the front end now accepts __real and __imag operators
applied to arguments of integral (and enumeration) types.  A warning is issued
in such cases.  As with arguments of real floating point types, __real applied
to an integral operand leaves the operand unchanged, and __imag applied to an
integral operand produces a zero of the same type as the operand.  For example:

  long i = __imag(3L);  // Accepted in GNU modes.  Same as "long i = 0L;".


1/15/09  [EDGcpfe/9443]
GNU and Microsoft compatibility: Default arguments on explicit instantiations

In GNU and Microsoft modes, the front end now accepts explicit instantiations
with default arguments (with a warning).  Any default arguments are ignored.
For example:

  template<class T> void f(T) {}
  template void f(int = 3);  // Accepted with a warning in GNU and Microsoft
                             // modes.
  int main() {
    f();  // Still an error in all modes.
  }


1/14/09  [EDGcpfe/7873]
IA-64 ABI: String literal sequence numbers and fetch_pp_tokens

When the IA-64 ABI is being used the front end should not attempt to
assign string literal sequence numbers when fetch_pp_tokens is TRUE.
This cannot occur in the front end as provided by EDG, but customer-provided
code (such as pragma processing routines) could give rise to such a
condition, resulting in an internal error.  The front end now suppresses
the assignment of string literal sequence numbers when fetch_pp_tokens is
TRUE.


1/14/09  [EDGcpfe/9063]
Issue warning in non-GNU modes for trailing backslash followed by white space

In GNU modes, emulating the GNU preprocessor, white space following a
backslash character is ignored, causing the backslash to be treated as a
line splice.  In non-GNU modes, such a sequence is not a line splice;
however, because trailing white space is generally invisible, the front end
now issues a warning for this case.  For example,

  /* There is a space at the end of the next line: */
  #define ADD \ 
    b + c;        // Errors in non-GNU mode: invalid declaration, etc.
  int f(int b, int c) {
    return ADD    // Error in non-GNU mode: '\' is not a valid token
  }

The errors issued for this code could be confusing if there were no
indication that the apparent line splice was not, in fact, processed as
such.


1/14/09  [EDGcpfe/2960]
Missing diagnostic on "inline" used in template static data member declaration

No diagnostic was issued if the "inline" keyword was used in the declaration
of a template static data member.  Now fixed.

  template <class T> struct A {
    static int x[];
  };
  template <class T> inline int A<T>::x[] = {1, 2, 3};  // inline not allowed


1/14/09  [EDGcpfe/8026]
Build issue with float_pt.c on some versions of Solaris

Some versions of Solaris define isnan as a macro.  This causes build
errors in float_pt.c because it contains an extern declaration of isnan.
The extern declaration of isnan is now only declared if isnan is not a
macro name.


1/14/09  [EDGcpfe/6404]
Predefined macro entry that is defined in all modes

It is now possible to specify that a macro in the predefined macro table
is to be defined in all modes.  This is done by using a mode name of "all".
See the 4/27/04 entry for more information about the predefined macro file.


1/14/09  [EDGcpfe/9044]
Point at which declaration position of full specializations is set

The symbol declaration position for an entity that is explicitly
specialized is updated to refer to the position of the explicit
specialization.  Formerly, the position was set before the call of
record_symbol_declaration.  It is now set after that call.  This will
not result in any observable differences in the front end as provided
by EDG, but may be useful for customers that have added processing
to record_symbol_declaration.

  template <class T> struct A {
    static int i;
  };
  template <> int A<int>::i;
  // decl_position set to ^--here after record_symbol_declaration


1/14/09  [EDGcpfe/8175]
Spurious error on empty --preinclude_macros file

If an empty --preinclude_macros file was used, a spurious "missing closing
quote" error was issued.  Now fixed.


1/13/09  [EDGcpfe/9437]
Underlying type of enumerator constants

In C++0x mode, the underlying type of an enumerator constant is fixed as soon
as the constant is encountered if an underlying type was specified explicitly
or if the enumeration type is "scoped" ("enum class" syntax).  The front end
previously failed to apply that rule and instead applied the underlying type
after all the enumerator constants had been seen.  For example (assuming a
32-bit int type):

  enum E: unsigned long long {
    x = 0xFFFFFFFF,  // x previously started with type "unsigned int".
    y = x+1          // Previously, y ended up with value 0.
  };
  static_assert(y == 0x100000000, "Error");  // Assertion now succeeds.

This is now fixed.


1/13/09  [EDGcpfe/9442, EDGcpfe/5847]
"extern template" after explicit instantiation should have no effect

An "extern template" directive (a Microsoft, GNU, and C++0x feature
that is now accepted in all modes) can be used to suppress
instantiations.  The C++0x rules (which are also used in the other
modes) prohibit an "extern template" directive from following an
explicit instantiation.  The diagnostic is issued as a discretionary
error or warning depending on the mode.  Because the compilation can
complete after such a diagnostic, an "extern template" that follows an
explicit instantiation should have no effect.  Formerly, the front end
still suppressed the instantiations in such cases.  This has been
fixed (i.e., an instantiation of A<char>::g will be emitted by the
example below).

  template <typename T> struct A {
    void g();
  };
  template <typename T> void A<T>::g(){}
  template class A<char>;
  extern template class A<char>;  // cannot follow explicit instantiation


1/13/09  [EDGcpfe/5847]
GNU C++ compatibility: allow "extern template" after explicit instantiation

An "extern template" directive is now allowed after an explicit instantiation
in g++ mode.  A warning is issued.

  template <typename T> struct A {
    void g();
  };
  template <typename T> void A<T>::g(){}
  template class A<char>;
  extern template class A<char>;


1/13/09  [EDGcpfe/8140]
Improved support for internationalization of write_signoff

write_signoff has been updated to eliminate hard-coded message text (e.g.,
"detected in the compilation of").  The strings used are now accessed
using the error_msg.txt file.


1/13/09  [EDGcpfe/8369]
Error issued on invalid template directory name

If an invalid directory is used as the argument of the --template_directory
option an error is now issued.  Formerly, the front end would silently fail
to find definitions for exported templates that were used, resulting in
linker errors later.


1/13/09  [EDGcpfe/6518]
Microsoft and GNU C compatibility: __STDC_VERSION__ should not be defined

The Microsoft and GNU C compilers do not define __STDC_VERSION__.  We now
emulate this behavior in Microsoft and GNU C modes.

1/13/09  [EDGcpfe/8139]
Possible use of freed memory in write_signoff

Although this cannot occur in the front end as provided by EDG, customer
changes (such as calling the back end even in the presence of errors) could
cause write_signoff to access memory that has already been freed.  The file
scope memory region is now freed after write_signoff has been called.


1/12/09  [EDGcpfe/9438]
Abort on GNU vector_size attribute applied to a typedef or cv-qualified type

Applying the GNU attribute "vector_size" to a typedef type or to a qualified
type resulted in an abort (in apply_vector_size_attribute) on many host
platforms.  On some other platforms, some of these cases could abort in
form_type_specifier (il_to_str.c) in an internal error ("typeref is not a
typedef").  For example:

  typedef int __attribute((mode(QI))) qi;
  typedef qi __attribute((vector_size(16))) v16qi;  // Triggered an abort
                                                    // on many hosts.

This is now fixed.


1/12/09  [EDGcpfe/6817]
GNU C++ compatibility: missing diagnostic on constructor using-declaration

A change made in version 3.5 had the unintended effect of, in g++ mode,
eliminating the diagnostic on a using-declaration that names a constructor.
Now fixed.

  struct A {
    A();
  };
  class B : public A {
    using A::A;  // formerly no error was issued in g++ mode
  };


1/9/09   [EDGcpfe/9427, EDGcpfe/9460]
GNU compatibility: Built-in IA-32 vector functions

When the new macro GNU_BUILTIN_IA32_VECTOR_FUNCTIONS_ALLOWED is set to TRUE,
the front end now predeclares a large number of GNU builtin functions that
map on vector instruction set extensions for IA-32 processors.  These
instruction set extensions include MMX, 3DNow!, SSE, SSE2, SSE3, Supplemental
SSE3, SSE4.1, SSE4.2, SSE4a, and SSE5.  (Although the new functions mostly
implement operations on GNU vector types, some also deal with other things
such as memory fences.)  Setting GNU_BUILTIN_IA32_VECTOR_FUNCTIONS_ALLOWED to
TRUE also requires that LONG_LONG_ALLOWED is TRUE, and that the sizes of
"short", "int", and "long long" are 2, 4, and 8, respectively.


1/9/09   [EDGcpfe/8674]
Internal error on error during IL read

An internal error (in find_seq_in_lookup_table) could occur if a diagnostic
was issued during the IL read process.  This has been fixed.


1/9/09   [EDGcpfe/7713]
IL file not cleaned up in some error cases

When a named IL file is being used (i.e., the IL file is not a temporary
file) if the front end exits with a catastrophic error or internal error
after the IL file has been opened, the IL file was not removed.  Now fixed.

1/7/09   [EDGcpfe/9061]
Abort on static data member in invalid class template definition

An abort could occur (in find_static_data_member_template) if a syntax error
occurred during the parsing of the template definition but that error no longer
existed at the point at which an instantiation of the class was attempted.
Now fixed.

  namespace N { }
  // N::B does not exist at template definition time, but does when an
  // instantiation is done later.
  template <typename T> struct A : N::B<T> {
    static int i;
  };
  namespace N {
    template <typename T> struct B {};
  }
  A<int> ai;


1/7/09   [EDGcpfe/9405]
Microsoft compatibility: friend class declaration can refer to typedef

The Microsoft compiler allows a friend class declaration that names a
typedef to be used to make the underlying class a friend.  We now emulate
this behavior in Microsoft mode.

  struct A { void f(); };
  class B {
  protected:
    static int i;
    typedef A my_A;
    friend class my_A;  // formerly declared a new class named my_A
  };
  void B::my_A::f() {
    B::i;  // formerly resulted in an access error here
  }


1/2/09   [EDGcpfe/8330]
Microsoft compatibility: Calling conventions and pointer-to-member-function
compatibility 

In Microsoft mode, the front end previously ignored calling conventions when
checking compatibility of pointer-to-member-function initializations and
assignments.  For example:

  struct S { void f(); };              // Default convention (__thiscall).
  void (__stdcall S::*pmf)() = &S::f;  // Previously accepted.  Now an error.

This is now fixed: Incompatible calling conventions are errors in such cases.


12/23/08 [EDGcpfe/9421]
GNU C++ mode const variables with constant pointer initial values

A small tweak has been made in g++ mode processing of uses of
const-typed pointer variables with constant initial values: when
gnu_version is >= 30300, they are no longer considered constant,
i.e., the use of the variable is not replaced by the constant itself.

  extern void g(char const *, char const *);
  void f() {
    char const *const s = "abc";
    g(s,s);  // Now passes "s" for both arguments, not "abc"
  }

12/22/08 [EDGcpfe/9168]
C++0x: local and unnamed types as template arguments

In C++0x mode, local and unnamed types can be used as template arguments
(this was already allowed in some modes).

  template <typename T> void f(T){}
  enum {e1};
  int main() {
    struct B {} b;
    f(b);
    f(e1);
  }


12/19/08 [EDGcpfe/9395]
Abort in trans_corresp.c on complex nested template cases

When simultaneously compiling multiple translation units, the front end
sometimes aborted with an assertion failure "Noncanonical instantiation list"
in update_canonical_entry (trans_corresp.c).  This situation only occurs under
a complex combination of conditions (involving nested class templates) and we
know of no small example to demonstrate it.  The underlying problem, however,
has been fixed. 


12/19/08 [EDGcpfe/9422]
GNU C++ compatibility: template keyword with missing template argument list

g++ accepts a qualified name in which the template keyword is followed by
an identifier that does not have a template argument list.  Formerly, we
rejected this in all modes in which nonclass templates were parsed.  We
now accept this usage in g++ mode when gnu_version is >= 30400.

  template <typename V> struct c {
    template <typename V2> static int g(V2 v) { return 0; }
  };
  template<typename V> struct A {
    static int f() { return c<V>::template g(0); }  // g should have templ args
  };
  int main() {
    A<int>::f();
  }


12/18/08 [EDGcpfe/9408]
GNU mode abort on nondependent block-extern functions in function templates

In GNU mode with gnu_version >= 30400, declaring and calling a function that
is not template dependent inside a function template (or a member function of
a class template) resulted in invalid IL when the template was instantiated.
The problem triggered an internal error when reading in the resulting IL file
("IL entry write-read difference").  For example:

  template <typename T> void g() {
    void f();  // Nondependent function declaration.
    f();
  }
  void h() { g<int>(); }  // Instantiation of g<int> resulted in invalid IL
                          // in some GNU modes.

This is now fixed.


12/18/08 [EDGcpfe/9413]
GNU C++ compatibility: Internal error on dependent nested template reference

An internal error (in check_expected_errors) could occur in g++ mode when
gnu_version is >= 30400 when a name of the form A<T>::B<T2> is used in a
prototype instantiation, where A is the name of some other class template
and B is intended to name a member class template of A.  This has been
fixed.  Note that the offending line in the example below is invalid
although it is accepted in some modes.  We now give an error in g++ mode
when gnu_version is >= 30400, and accept the code when gnu_version is < 30400
(which matches the behavior of the respective g++ versions).

  template <class T> struct Q {
    template <class T2> struct B { int j; };
  };
  template <class T> struct A {
    Q<T>::B<T> bt;  // missing typename and template keywords
    // should be: typename Q<T>::template B<T> bt;
   int get(T) { return(bt.j); }
  };
  int main() {
    A<char*> a;
    a.get("xxx");
  }


12/18/08 [EDGcpfe/9409]
Abort after compatibility error in K&R/pcc mode

In K&R/pcc mode (command-line option -K or --old_c), the front end aborted
with an internal error in create_external_symbol_for_linked_entity (decls.c)
after encountering certain incompatible redeclarations.  For example:

  int x;
  short x; /* Redeclaration error was followed by an internal error in
              K&R/pcc mode. */

This is now fixed.


12/17/08 [EDGcpfe/9419]
GNU compatibility: Built-in bit counting functions

In GNU modes, the front end predeclares a number of bit counting functions:
__builtin_ffs, __builtin_clz, __builtin_ctz, __builtin_popcount,
__builtin_parity, and variants of all these for unsigned long and unsigned
long long arguments.  Now, calls to these routines are folded to constants
if the argument is a constant integer whose value can be represented by
a_host_large_unsigned.  For example:

  char x[__builtin_popcount(0xFF00)];  
    // Now accepted in GNU modes. Same as "char x[8];" since popcount
    // counts the number of "one bits" in its argument.


12/17/08 [EDGcpfe/8920]
Invalid IL structure as a result of pointer-to-member deduction

While processing template deduction on a pointer-to-member-function,
the front end produced a situation where two routine types pointed at
the same parameter type list, which is not permitted.  This would cause
problems if the IL is subsequently walked, in particular to read back
in an IL file when ALTERNATE_IL_FILE_FORMAT is FALSE (the abort in
that case said "ptr_remap_function: address not in any mem block").

  template <typename T>
  struct is_member_function_pointer{ static const bool value = false; };
  template <class R, class T, class A0, class A1>
  struct is_member_function_pointer<R (T::*)(A0, A1)>{
    static const bool value = true;
  };
  template <typename T> struct is_member_pointer
  { static const bool value = is_member_function_pointer<T>::value; };
  template <typename T, typename U> struct is_member_pointer<U T::*>
  { static const bool value = true; };
  struct UDT {
    int f4(int, float);
  };
  typedef int (UDT::*mf4)(int, float);
  bool y = is_member_pointer<mf4>::value;


12/17/08 [EDGcpfe/9420]
Microsoft compatibility: error on template member with multiple default args

The Microsoft compiler accepts but ignores default arguments on out-of-class
definitions of member functions of class templates.  We emulate this
behavior in Microsoft mode but cases with more than one default argument
incorrectly resulted in an error.  Now fixed.

  template <typename T> struct S {
    S(int x, int y);
  };
  template <class T> inline S<T>::S(int x=0, int y=0) { }


12/17/08 [EDGcpfe/8418]
C++-generating back end: Abort with STANDALONE_CP_GEN_BE

The table of operator names used to generate operator-syntax function
calls (e.g., a call to operator+ from an expression like "a+b") was not
initialized when the C++-generating back end is built as a standalone
program, causing an abort.  This is now fixed.


12/17/08 [EDGcpfe/9406]
Microsoft compatibility: Old-style specializations of function templates

In Microsoft C++ mode, old-style specializations of function templates using
explicit template arguments were not accepted when microsoft_version >= 1310
(see Changes entry of 3/21/03).  However, it appears that Microsoft compilers
do accept such specializations if the associated template instance is used
prior to the specializing declaration.  For example:

  template<typename> void f() {}
  template void f<int>();  // (1): f<int> instance is used here.
  void f<int>() {}  // Old-style specialization now accepted in all Microsoft
                    // Microsoft modes.  It would not be accepted if line (1)
                    // were removed and microsoft_version >= 1310.

We now emulate this Microsoft behavior.


12/16/08 [EDGcpfe/9414]
Build error in standalone programs with PROTOTYPE_INSTANTIATIONS_IN_IL

In standalone utility programs configured with CHECKING and
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, builds failed to link because
of unresolved references to is_template_dependent_type.  This routine is
used in checking expression operands for lvalue/rvalue correctness, so the
error has been addressed by not performing this check in such
configurations.


12/15/08 [EDGcpfe/9380]
Value-dependent potential null pointer constant in overload resolution

In a template prototype instantiation, a value-dependent expression
that could potentially have integral type and value zero, and therefore
potentially be a null pointer constant, has heretofore been treated as
such.  Now, in most modes such a constant is not considered convertible
to a pointer type in an argument match.

  struct S {
   S(int);
   S(int*);
  };
  template<class T> void foo() {
    S s(sizeof(T)-1);  // Was ambiguous, now picks S(int)
                       // S(int *) is no longer a possibility
  }
  template void foo<int>();

In GNU C++ mode, however, the handling is slightly different: the
occurrence of such a constant in an argument list is considered to
make the call dependent, which causes overload resolution to be
delayed to any real instantiations of the template.  (In the example
above, that would mean an ambiguity would be produced if foo<char>
were instantiated.)


12/15/08 [EDGcpfe/9412]
Abort on Microsoft out-of-class member redeclaration

In Microsoft mode with microsoft_version < 1310, the front end accepts an out-
of-class redeclaration of a member function even when that redeclaration is not
a definition.  Furthermore, such redeclarations can appear in local scopes.
However, if such a member function redeclaration appeared within the scope of
its own definition, the front end sometimes produced invalid IL that led to
internal errors ("IL write-read difference") when attempting to read the
resulting IL file.  For example:

  struct S { void f(int i); };
  void S::f(int i) {
    void S::f(int i);  // Accepted in some Microsoft modes.  Triggered
  };                   // internal errors in some configurations.

This is now fixed.


12/15/08 [EDGcpfe/8561]
Abort on floating-point constant in case label in Microsoft mode

The front end aborted ("case_label: case value not int") on encountering
a floating-point constant in a case label in Microsoft mode.  Now, it
issues an error as has been done in other modes.

  int main() {
    int i = 0;
    switch (i) {
      case 1.1:;  // Got internal error previously
    }
  }


12/11/08 [EDGcpfe/9407]
Discretionary errors suppressed in files from system include directories

Formerly, warnings were automatically suppressed on code that came from
system include directories.  Now discretionary errors are also suppressed
in such cases.  If the files below are compiled with the command:
  edgcpfe --sys_include=include test.c
The compile now succeeds with no diagnostics (formerly a discretionary
error was issued).

  include/x.h:
  enum E {x,};

  test.c:
  #include "x.h"


12/11/08 [EDGcpfe/6851]
Include guard code added to files in which it was missing

Include guard code has been added to those header files that lacked it,
except for walk_entry.h which must be capable of being included more than
once.


12/11/08 [EDGcpfe/9367]
Microsoft C++ compatibility: allow integral conversions in deduction

In Microsoft mode, a nontype template parameter can be deduced from a
context in which an implicit integral conversion has been done on the
template parameter.  In the example below, A<c> is interpreted as
A<(int)c>, so "c" should not be deducible there, but this is accepted by
the Microsoft compiler and we now accept it in Microsoft mode.

  template <int c> class A {};
  template <long c> void f(A<c>) {}
  void g() {
     A<89> a;
     f(a);  // deduction succeeds in Microsoft mode
  }

12/11/08 [EDGcpfe/6674, EDGcpfe/8978, EDGcpfe/9401, EDGcpfe/9430]
Microsoft C++ compatibility: void parameters in template instantiations

In Microsoft C++ mode, an ordinary (i.e., nontemplate) member function of a
class template is treated as a function taking no arguments if it has a single
parameter whose type is void after instantiation.  For example:

  template<typename T> struct S {
    int f(T);
  };
  int r = S<void>().f();  // Accepted in Microsoft C++ mode.


12/11/08 [EDGcpfe/9394]
Microsoft C++ compatibility: dllimport/dllexport and explicit instantiations

Version 4.0 modified the effect of dllimport/dllexport on member functions of
class templates when explicitly instantiating those member functions (see the
Changes entry for EDGcpfe/9369 on 11/24/08).  Specifically, dllexport/dllimport
applied to the class template is carried over to the explicit instantiation
if the instantiation does not itself specify dllimport or dllexport.  However,
this behavior was unintentionally disabled if the instantiated class member was
overloaded with other members.  For example:

  struct I;
  template<typename T> struct __declspec(dllimport) X {
    void f(T *p) { p->i(); }
    void f();                 // f is now overloaded.
  };
  template void X<I>::f(I*);  // Previously, this ignored dllimport because
                              // X<I>::f is overloaded, which in turn triggered
                              // an error (because I is incomplete).  Now, this
                              // is accepted because dllimport means "do not
                              // instantiate".

This is now fixed.


12/8/08  [EDGcpfe/9400]
MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED used before set in host_envir.h

The MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED macro is used before it is set
in host_envir.h if it is not defined in the defines.h file.  This could
result in spurious #error diagnostics.  Now fixed.

------------------------------------------------------------------------------
Version 4.0, December 5, 2008

12/5/08
IL version number changed to 4.0


12/3/08  [EDGcpfe/9390, EDGcpfe/9393]
Changes in IL representation of member function calls

IL CHANGE: The IL representation for calls has been reworked so that
for member calls the operator gives a better indication of the source
form.  eok_member_call (see the Changes entry of 11/9/08) has been split into

  eok_dot_member_call        for the x.f(args) form
  eok_points_to_member_call  for the p->f(args) form

Similarly, the pointer-to-member call operator eok_pm_call has been split into

  eok_dot_pm_call            for the (x.*f)(args) form
  eok_points_to_pm_call      for the (p->*f)(args) form

In both cases, the selector object is a class lvalue or rvalue for
the "dot" form, and a pointer to class for the "points_to" form (see
the Changes entry of 11/6/08).

The eok_virtual_call operator has been eliminated.  The fact that a call
has virtual function semantics is now indicated by the is_virtual_call
flag in the an_expr_node operation variant.


12/2/08  [EDGcpfe/9386]
C-generating back end: restoring default after #pragma pack

When a struct definition is preceded by a #pragma pack directive changing
the default packing alignment, it should be followed by a #pragma pack()
directive to restore the default alignment value.  In configurations in
which GCC_IS_GENERATED_CODE_TARGET is TRUE, the #pragma pack() directive
was omitted.  Now fixed.  For example:

  #pragma pack(1)
  struct S { /* ... */ };
  #pragma pack()    /* Previously omitted, now generated. */


11/24/08 [EDGcpfe/9285]
Support for native character sets when Unicode source is supported

When UNICODE_SOURCE_SUPPORTED is TRUE (see 4/13/08 Changes entry) it is
now possible to accept both Unicode source files and source files
that use a non-Unicode character encoding.  This is enabled by the
NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE flag.  This feature requires the
ability to translate other character sets to and from Unicode.  Such a
facility is provided in newer versions of the Windows API (Microsoft version
1400 and above) so this feature is enabled when the front end is built with
EDG_WIN32 TRUE.  This feature can be used on other platform if customers
provide the required conversion routines.  On non-Windows platforms, enabling
NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE will result in #error directives
being issued at the points in the front end that require customization.

When Microsoft extensions are enabled and EDG_WIN32 is TRUE, this feature
enables support for the Microsoft setlocale pragma, which specifies the
character encoding to be used for the translation to and from Unicode.

In identifiers and file names, native characters are translated to their
UTF-8 equivalent.  In wide strings, native characters are translated to
their Unicode equivalent.  In narrow strings, they are left in their
original form. 


11/24/08 [EDGcpfe/9369]
Microsoft C++ compatibility: dllimport/dllexport and explicit instantiations

In Microsoft C++ mode, explicitly instantiating an ordinary (i.e., nontemplate)
member function of a class template applies the dllimport/dllexport specifiers
from the template to the instantiation directive if no such specifiers appeared
on the directive itself.  This includes the "do not instantiate" meaning of the
dllimport specifier.  For example:

  struct I;
  template<typename T> struct __declspec(dllimport) X {
    void f(T *p) { p->i(); }
  };
  template void X<I>::f(I*);  // Treated as if __declspec(dllimport) appeared
                              // on this directive (and therefore no error is
                              // issued even though struct I is incomplete).


11/22/08 [EDGcpfe/9259]
Build error with STANDALONE_IL_DISPLAY
In certain configurations a compilation error occurred when building the
standalone IL display program, resulting from the use of an undefined
typedef name.  This is now fixed.


11/21/08 [EDGcpfe/9218]
Microsoft C++ compatibility: Explicit overriding of an interface member

In Microsoft mode, the front end accepts declarations of pure virtual member
functions with a class qualifier to indicate that only the virtual member in
the indicated class is overridden by the qualified declaration (see Changes
entry of 7/18/03).

Previously, the qualifier was used to determine the member function being
overridden, but did not affect the base subobjects in which it is overridden.
That observation still applies to base subobjects of ordinary class or struct
types.  For example:

  struct B { virtual void f() = 0; };
  struct C1: B {};
  struct C2: B {};
  struct D: C1, C2 {
    void C1::f() {}  // Overrides f in both base subobjects of type B.
    void C2::f() {}  // Error: Redeclaration of B::f overrider.
  }; 

However, when the class qualifier refers to an interface, only the member
found in that specific interface is overridden.  For example: 

  __interface B {
    virtual void f() = 0;
  };
  __interface C1: B {};
  __interface C2: B {};
  struct D: C1, C2 {
    void C1::f() {}  // Overrides B::f (only) in the C1::B subobject.
    void C2::f() {}  // Overrides B::f (only) in the C2::B subobject.
  };

Note that for such cases special routine entries (called "interface slots")
are added to the interfaces (C1::f and C2::f in the example above).  These are
pointed to by IL entries for the selectively overriding member functions (and
used for name mangling, though they can otherwise be ignored for code-
generation purposes).


11/21/08 [EDGcpfe/9284]
New DUMP_CONFIG_ENABLED configuration macro for --dump_configuration

A new DUMP_CONFIG_ENABLED configuration macro has been added to control
whether or not the --dump_configuration option (see Changes entry of 6/20/07)
is available.  DUMP_CONFIG_ENABLED is set to TRUE when DEBUG is TRUE, and
defaults to TRUE otherwise; therefore DUMP_CONFIG_ENABLED must be explicitly
set to FALSE in defines.h if the --dump_configuration option is not desired.


11/19/08 [EDGcpfe/8431]
Microsoft compatibility: classes instantiated when needed for ADL

Newer versions of the Microsoft compiler no longer fail to instantiate
classes to determine their associated classes and namespaces for
argument-dependent lookup purposes (see 3/6/06 entry).  We now disable
our emulation of this bug when microsoft_version is >= 1500.

  template<class T> class A {
    friend void f(const A& a) { }
  };
  void g(const A<int>& a) {
    f(a);  // error: '"f" undefined' when microsoft_version is < 1500
  } 


11/19/08 [EDGcpfe/9121]
Offsets silently dropped when ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS is TRUE

In C++ configurations that use lowering and where
ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS is TRUE (the default in IA-64 ABI
configurations), an offset to an address string constant was being silently
dropped when the string constant was converted to a static variable.  
This is now fixed.  For example:

  extern "C" int strcmp(const char *, const char *);
  extern inline const char *f() {
    const char *x = "abc"+1;    // the offset (1) was silently discarded
    return x;
  }
  int main() {
    return strcmp("bc", f());   // had returned non-zero, now zero
  }


11/18/08 [EDGcpfe/9355]
Microsoft compatibility: Inherited const member functions named as friends

In Microsoft mode, the front end allows friend declarations to refer to
inherited member functions of a class (see Changes entry of 8/4/00).  However,
a spurious error was issued if the friend declaration was for a const (or
volatile) member function.  For example:

  struct B { void f() const; };
  struct D: B {};
  struct X {
    friend void D::f() const;  // Triggered a spurious type compatibility
  };                           // error in Microsoft C++ mode.

This is now fixed.


11/13/08 [EDGcpfe/9093]
Invalid lowered complex compound assignments in GNU C++ mode

In GNU C++ mode, builtin complex types are supported.  However, when such
types are lowered (LOWER_COMPLEX is TRUE), the code generated for compound
assignments of complex values was invalid in some cases.  For example:

  typedef _Complex double CZ;
  CZ& f();
  void g() {
    f() += f();  // The lowered code attempted to "add" struct values.
  }

This is now fixed.


11/13/08 [EDGcpfe/9151]
Imaginary types and compound assignments

Multiply-assign or divide-assign operations involving imaginary types (a
feature of C99) were sometimes lowered (when LOWER_COMPLEX is TRUE) to
incorrect forms.  For example:

  void f(_Imaginary float i) {
    i /= i;  // Should have the same effect as "i = 0.0;", but previously
  }          // the effect after lowering was as "i = __I__;".

This is now fixed.


11/12/08 [EDGcpfe/9347]

In Microsoft bugs mode, a type template parameter can now be declared by
repeating the introductory keyword "typename", and optionally following it by
the keyword "class".  For example:

  template<typename typename> class C;  // Accepted in Microsoft bugs mode.
  template<typename class X> class C;   // Ditto.
  template<typename typename class> class C; // Ditto.
  template<class class X> class C;      // Still an error (in all modes).

See also the Changes entry of 3/3/04, which documents a similar issue in other
contexts.


11/12/08 [EDGcpfe/9111]
Top-level casts to void are always preserved in unlowered IL

A change has been made to retain top-level casts to void in unlowered IL.
If the PRESERVE_TOP_LEVEL_CASTS_TO_VOID_IN_IL configuration macro is set
to FALSE (the default), these top-level casts are then removed during
the lowering process.


11/11/08 [EDGcpfe/9340]
GNU C++ compatibility: floating-point operations in template arguments

GNU C++ mode now allows floating-point constants and operations in
template argument expressions as long as the final result is integral.

  template <int xi> struct foo {};
  foo< ( 3.1 < 2.3) > d;


11/10/08 [EDGcpfe/9189]
GNU C++ compatibility: ELF visibility and function templates

In GNU C++ mode, the ELF visibility attribute specified on a class type (which
is only effective when gnu_version >= 40000) now applies to the instances of
that class' member templates by default (that default may still be overridden
by an attribute on the member template).  For example:

  struct __attribute((visibility("hidden"))) S {
    template<typename T> void f1() {}
  };
  template void S::f1<int>();  // S::f1<int> now has "hidden" ELF visibility.

Furthermore, an ELF visibility attribute specified on the explicit
specialization of a function template no longer triggers a warning about an
attribute conflict when the function template itself has an ELF visibility
attribute.  Instead, the visibility specified on the specialization now takes
precedence.  For example:

  template<typename T> __attribute((visibility("protected"))) void g() {}
  template<>  __attribute((visibility("internal"))) void g<double>() {}
        // Specialization no longer triggers a warning; g<double> has
        // "internal" visibility.


11/9/08  [EDGcpfe/9343]
eok_member_call operator

IL CHANGE:  Non-virtual member function calls are now represented by
a new eok_member_call operator rather than an eok_call operator.
eok_generic_call and eok_generic_member_call, formerly used for
dependent calls in prototype instantiations, have been eliminated;
eok_call or eok_member_call are now used for those as well.


11/6/08  [EDGcpfe/9268]
Selector on call can now be class lvalue or rvalue in addition to pointer

IL CHANGE: The selector object on a member function call can now be a
class lvalue, a class rvalue, or a pointer to a class object.  Formerly,
it was always a pointer to a class object.  eok_call, eok_virtual_call,
eok_pm_call, and eok_virtual_function_ptr now allow such a class-typed
object.


11/6/08  [EDGcpfe/9268]
eok_class_rvalue_adjust operator

IL CHANGE: A new operator, eok_class_rvalue_adjust, has been added to
indicate cv-qualifier adjustments on class rvalues, for example when
they are used as selector objects on member function calls.  When
LOWER_CLASS_RVALUE_ADJUST is TRUE, IL lowering will rewrite these
adjustments by taking the address of the class rvalue, casting the
pointer to the proper type, and indirecting to get back to a class
object.


11/4/08  [EDGcpfe/9215, EDGcpfe/9333]
GNU C/C99 compatibility: Implicit int

In C89 mode, a function definition can omit its return type, in which case
type int is assumed.  Other declarations (e.g., variable declarations and
function declarations that aren't definitions) can also omit "int", provided
another specifier (e.g., static) is present.  In C99 mode, there is no such
"implicit int" rule by default.

In GNU C and C99 modes, the implicit int rule now applies to all function,
variable, and typedef declarations.  A warning is issued for any declaration
relying on this rule (except when declaring "main").  For example:

  f() { return 3; }  // Now accepted (with a warning) in GNU C99 mode.
  x;                 // Now accepted in GNU C and C99 modes (with a warning).


10/31/08 [EDGcpfe/8528, EDGcpfe/8747]
C++0x: Scoped enumeration types

In C++0x mode, the front end now accepts scoped enumeration types (defined
with the keyword sequence "enum class") and explicit underlying integer types
for enumeration types.  For example:

  enum class Primary { red, green, blue };
  enum class Danger { green, yellow, red };    // No conflict on "red".
  enum Code: unsigned char { yes, no, maybe }; // sizeof(Code) == 1
  void f() {
    Primary p = Primary::red;  // Enum-qualifier is required to access
                               // scoped enumerator constants.
    Code c = Code::maybe;  // Enum qualifier is allowed (but not required)
  }                        // for ordinary enumeration types.

This change was voted into the C++ committee's working paper for the next
standard in July 2007 (meeting in Toronto, through proposal numbered N2347).


10/31/08 [EDGcpfe/9331]
Microsoft compatibility: Extended modifiers on enum specifiers

Previously, in Microsoft mode, the front end issued an error on all __declspec
modifiers appearing on C-mode enum specifiers, and silently ignored most other
modifiers on enum specifiers.  This has now been revised to match the behavior
of Microsoft compilers: Some modifiers result in an error in both C and C++
modes, some result in an error in C mode only, and most others are ignored
(with a warning).  As before, the only valid modifier with an effect is the
__declspec(uuid(...)) modifier in C++ mode (see also Changes entry of
1/26/01).  For example:

  enum __declspec(uuid("11111111-1111-1111-1111-111111111111") E1;
                                         // Okay in Microsoft C++ mode, but
                                         // an error in Microsoft C mode.
  enum __declspec(dllexport) E2 { e2 };  // Now ignored with a warning.
  enum __single_inheritance E3 { e3 };   // Now an error in Microsoft C mode,
                                         // but ignored with a warning in C++
                                         // mode.


10/30/08 [EDGcpfe/9245]
GNU attribute diagnostics

Several diagnostics for GNU attributes have been revised to include the name
of the attribute that is involved.  This is especially useful in contexts
where several attributes are encapsulated in a macro.  For example:

  #define X __attribute((noreturn)) __attribute((warn_unused_result))
  X void f();  // warn_unused_result is ignored when the return type
               // is void.


10/30/08 [EDGcpfe/9326]
GNU C++ mode: explicit template argument list on call turns off argument
dependent lookup

g++ appears to suppress argument-dependent lookup on a call if an
explicit template argument list is specified.  (This is nonstandard;
14.8.1p8 of the C++ standard has a clear statement and example showing
that argument-dependent lookup should still be done in that case.)
This behavior is now emulated in GNU C++ mode.

  template <class T> void f(T *);
  namespace N {
    template <class T> void f(T);
    struct A {};
  }
  int main() {
    N::A a;
    f<N::A>(a);  // g++ does not do argument-dependent lookup, gives error
  }


10/29/08 [EDGcpfe/9276]
Diagnostic when introducing a DLL attribute on a redeclaration

In Microsoft mode, an error is issued if a variable or function was first
declared without a DLL attribute (dllimport or dllexport), and later was
redeclared with such an attribute.  Now, that error is discretionary (and
the DLL attribute is applied to the entity).  For example:

  int f();
  __declspec(dllimport) int f();  // The error issued for this redeclaration
                                  // is now discretionary.


10/29/08 [EDGcpfe/8156, EDGcpfe/7042]
Assertion failure in mangled_class_encoding

In IA-64 ABI configurations where PROTOTYPE_INSTANTIATIONS_IN_IL and
MANGLE_ALL_NAMES are both TRUE, an attempt to produce a mangled name for a
non-type member of a template parameter class whose type is unknown yielded
an assertion failure ("mangled_class_encoding: bad template param kind").
This is now fixed.  Here is an example that previously aborted:

  template <class T> struct S { };
  template<class T> int f(S<T>* p) {
    return (p->x).template f<typename S<T>::t> ();
  }


10/28/08 [EDGcpfe/9312]
GNU C compatibility: Unprototyped redeclarations

In GNU C mode with gnu_version < 40000, when a function is first declared with
a prototyped declaration and then redeclared with an unprototyped declaration,
type qualifier differences are ignored on the function's return type.
For example:

  const int f(void);    // Prototyped declaration.
  int f() { return 0; } // Unprototyped declaration: Missing "const" is
                        // accepted when gnu_version < 40000.


10/28/08 [EDGcpfe/5824,EDGcpfe/9316]
Out-of-order constructor initializers

A remark is now issued if the initializers for members and bases specified
on a constructor definition do not appear in the order in which the
initializations will be done.  For example:

  struct S {
    S(int i, int j): y(i), x(j) {}  // Remark: The initialization of x is
    int x, y;                       // done before that of y.
  };


10/28/08 [EDGcpfe/9324]
IA-64 ABI name mangling for enumerators and namespace member constants

Previously, the names of enumerators and namespace member constants were
mangled using a "__" prefix in IA-64 ABI mode; a change has been made to use
the "_Z" prefix instead.  This change allows these mangled names to be
decoded and is consistent with manglings that occur for similar types
that are defined in functions.  See also a similar change on 12/19/06 for
local nested classes.  Here is an example:

  struct S {
    enum E { e };   // mangling for e had been __N1S1eE, now _ZN1S1eE
  };
  namespace N {
    enum E { e };   // mangling for e had been __N1N1eE, now _ZN1N1eE
  }
  void f() {
    enum E { e };   // mangling for e still _ZZ1fvE1e_5
  }


10/27/08 [EDGcpfe/9315]
Microsoft compatibility: The keyword "default"

Recent Microsoft compilers (MSVC8 and later) treat the identifier "default"
as a keyword only when it is followed by a colon.  In Microsoft mode with
microsoft_version >= 1400, we approximate that behavior by treating the
identifier "default" as a keyword only when it is followed by a colon in a
location where a label can legitimately appear.  For example:

  // Assume Microsoft mode with microsoft_version >= 1400.
  int default(int default) {  // "default" is twice an ordinary identifier.
    switch (default) {        // "default" is an ordinary identifier.
      default:                // "default" is a keyword.
        return default ? default : 3;
    }                         // "default" is twice an ordinary identifier.
  }

Note that the last occurrence of "default" above is treated as a keyword by
Microsoft compilers (because it is followed by a colon), but not by the EDG
front end (because a label cannot appear there).  The example is therefore
accepted by the EDG front end in Microsoft mode, but not by MSVC8.


10/27/08 [EDGcpfe/9214]
Assertion failure when unnamed dependent enum type is used in cfront ABI

The use of an unnamed enum type as a dependent type in a class template caused
an assertion failure in lower_name.c when using the cfront ABI.  This
regression occurred as a result of changes described by the Changes entry
of 9/13/07.  Here is an example that previously aborted and is now fixed:

  template <int I> struct S {
    typedef enum { e } E;   // caused an assertion failure in lower_name.c
    void f(E);
  };
  S<0> s;


10/23/08 [EDGcpfe/9309]
Microsoft compatibility: Union with struct containing a flexible array member

Various modes, including Microsoft modes, accept a class or struct type whose
last field has a class type with a flexible array member.  In Microsoft mode,
a class type with a flexible member can also appear in union types, and in
those cases the flexible member can be any member of the union (not just the
last one).  In Microsoft bugs mode, the front end now allows a field of such
a union type to be followed by another field, if the field with the flexible
member in the union is not the last field.  (This matches the behavior of
Microsoft compilers.)  For example:

  struct F {
    float f[];
  };
  union X {
    F fs;  // Flexible member in a union, but not the last field.
    int i;
  };
  struct Y {
    union X x;  // Accepted in Microsoft bugs mode, even though x is not the
    int y;      // last field.
  };


10/23/08 [EDGcpfe/8822]
printf/scanf checking of arguments with template-dependent types

The checking of the arguments for printf/scanf-like functions now
considers arguments with template-dependent types to match any
formatting specifier.  This comes up only in modes that do prototype
instantiations of functions.  Formerly, such checks produced a spurious
warning about an incompatible argument.


10/23/08 [EDGcpfe/8474]
Array rvalue as first operand of GNU two-operand "?"

The front end aborted on processing a GNU two-operand "?" operator
(one where the second operand is omitted) when the first operand is
an array rvalue.  Now fixed.

  struct s { char c[1]; };
  struct s f(void);
  char *f(void) { return (f().c ? : 0); }


10/22/08 [EDGcpfe/8781]
Operation type for shift-assignment

When implementing a compound assignment operator, its operands must be
converted to the "operation type".  This operation type is determined by the
function compound_assignment_operation_type (called expression_operation_type
in earlier versions), but that function produced erroneous results for the <<=
and >>= operators when the first argument was a small integral type (like char
or unsigned short) requiring integral promotion.  This is now fixed.


10/21/08 [EDGcpfe/8514]
GNU __builtin_constant_p in integral constant expressions

The GNU builtin function __builtin_constant_p (and some similar functions
that can return a constant value) are now allowed in integral constant
expressions in g++ mode when gnu_version >= 40000.

  int main() {
    switch (1) {
      case (__builtin_constant_p(2) ? 3 : 4):  // Now accepted
      return 0;
    }
  }


10/21/08 [EDGcpfe/9173]
Use of uninitialized variable for source position after error in "?"

The processing for the error of a missing ":" in a "?" operator made
use of an uninitialized variable in setting the end position of the
operation when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE.  Now fixed.

  int main() {
    int i = 1;
    i ? i;  // End position on error operand was garbage
  }


10/21/08 [EDGcpfe/9288]
More emulation of GNU lvalue casts

gcc ignored a cast to the same type in versions prior to 4.0, which
meant a cast like that did not force an expression to be an rvalue.
It appears that in some cases casts like that to struct/union types are
still mostly ignored in versions 4.1 and later.  We have made a
change to approximately emulate that.

  struct A {int i;} a;
  void g(struct A);
  void f() {
    ((struct A)a).i = 0;  // No error now in gcc 4.1 mode
    int i;
    (int)i = 0;           // Still error in gcc 4.1 mode
    (struct A)a = a;      // gcc 4.1 gives error, we give no error now
    g((const struct A)a); // No error now in gcc 4.1 mode
  }


10/20/08 [EDGcpfe/9269]
New eok_lvalue_adjust operator to adjust lvalue type

IL CHANGE: A new eok_lvalue_adjust operator has been added, which is
used to adjust the type of an lvalue.  That is, its operand is an lvalue,
and it produces an lvalue that refers to the same object but with a new
type.  This operator is typically used to adjust the cv-qualifiers
on an lvalue (e.g., to add "const").  It is not eliminated by IL lowering,
so it will be seen even in lowered IL.


10/20/08 [EDGcpfe/9296]
GNU C++ compatibility: Default arguments in friend function declarations

In GNU C++ mode, the front end now always accepts default arguments in friend
function declarations.  Previously, the default arguments were only accepted
if friend injection was enabled (see also the Changes entry of 8/9/08).
For example:

  struct S { 
    friend void f(int n = 3);  // Now always accepted in GNU C++ mode.
  };

Also, the error emitted for cases like this in other modes (when friend
injection is disabled) has been made discretionary.


10/20/08 [EDGcpfe/9298]
Microsoft compatibility: typename accepted on globally qualified name

The Microsoft compiler allows a globally qualified name to be used in
a typename specifier.  We now accept this in Microsoft mode.

  template <typename T> struct A {};
  template <class U> struct B {
    typedef typename ::A<U> my_A;
  };


10/20/08 [EDGcpfe/9297]
GNU C++ compatibility: Support for type traits

In GNU C++ mode with gnu_version >= 40300, the front end now supports the
following type trait pseudo-functions: __has_nothrow_assign,
__has_nothrow_constructor, __has_nothrow_copy, __has_trivial_assign,
__has_trivial_constructor, __has_trivial_copy, __has_trivial_destructor,
__is_abstract, __is_class, __is_convertible_to, __is_empty, __is_enum,
__is_pod, __is_polymorphic, and __is_union.  This is the same list as
documented in the Changes entry of 3/21/06.  However, in GNU C++ mode
__has_nothrow_copy always produces 0 when the class a compiler-generated
nontrivial copy constructor (in other modes, it may produce a true value
if the generated constructor is known not to throw).  Note that in GNU modes
with gnu_version < 40300, type traits are disabled even if the macro
DEFAULT_TYPE_TRAITS_HELPERS_ENABLED is TRUE, because some earlier g++ header
files declare identifiers like "__is_empty".


10/15/08 [EDGcpfe/9282]
New flag in il_header: il_has_C_semantics

A new flag has been added to the il_header; il_has_C_semantics indicates
whether the IL has C semantics (TRUE) or C++ semantics (FALSE).  The IL
has C language semantics if the source program was compiled in C mode,
or if the source program was compiled in C++ mode and then lowered.  There are
subtle differences between the two; for example, in C++ IL, it's okay to cast
an lvalue directly to void.


10/14/08  [EDGcpfe/9235]
Column number in source position is now a logical column number

Formerly, the column field of a_source_position was the byte number within
the source line.  This is the same as a logical column number except when
multibyte characters are used.  The byte number had been an acceptable
representation even for source that uses multibyte characters, but presented
problems now that the front end can read UTF-16 files.  When the front end
reads UTF-16 source the characters are converted into UTF-8 internally.
Consequently, the byte number represented the position in the internal
representation, which cannot be readily mapped back to a position in the
original source line.  To address this, the column number field now represents
the logical column number, in which each source character counts as one
logical character regardless of the number of bytes used to represent it.


10/13/08 [EDGcpfe/9260]
ELF visibility semantics in non-GNU modes

In GNU modes, the front end supports the "visibility" attribute and pragma to
control the ELF visibility of functions and variables (including generated
variables like typeinfo objects).  In order to make it easier for customers to
adopt similar facilities in other dialects, the code implementing the main
semantics of these GNU constructs has been enabled even when gcc_mode and
gpp_mode are FALSE.  By themselves, these changes do not affect the behavior
of the front end because the syntax to control ELF visibility still requires
a GNU mode.  The configuration macros GNU_VISIBILITY_ATTRIBUTE_ALLOWED and
GNU_EXTENSIONS_ALLOWED must still be TRUE to enable the code.


10/13/08 [EDGcpfe/9106]
IL representation for casts of class values to base and derived classes

IL CHANGE:  The eok_base_class_cast and eok_derived_class_cast
operators now apply to class lvalues and class rvalues in addition to
pointers to class objects.  The form and type of the result matches
the form and type of the operand (e.g., an eok_base_class_cast that
casts a class rvalue to a base class produces a class rvalue result).


10/13/08 [EDGcpfe/9103]
Elimination of dead code under conditional operators

Dead code under the operators "?", "&&", and "||", which formerly was
eliminated in the front end proper when 
ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS was TRUE, is no
longer removed (and the macro has been eliminated).  So, an expression
like "1 || x" is no longer transformed to simply "1" in the front end.
IL lowering now does these transformations instead, so customers
using IL lowering will see essentially no difference, and customers
not using IL lowering will never see the dead code removed.


10/8/08  [EDGcpfe/8856]
Representation of declaration statements (IL CHANGE)

Previously, stmk_decl statement entries represented a sequence of one or more
consecutive declaration statements.  Such entries were only generated when
GENERATE_SOURCE_SEQUENCE_LISTS was TRUE, and they pointed either to a source
sequence entry pointing back to the stmk_decl entry (when the macro
SRC_SEQ_ENTRIES_FOR_DECL_STMTS was TRUE) or to the source sequence entry for
the first declared entity (when SRC_SEQ_ENTRIES_FOR_DECL_STMTS was FALSE).

Now, stmk_decl statements are generated in all configurations and a distinct
stmk_decl entry is created for each declaration statement.  If source sequence
entries are generated, they point to their own source sequence entry.  (The
configuration macro SRC_SEQ_ENTRIES_FOR_DECL_STMTS has been removed.)
Furthermore, stmk_decl statement entries now point to a list of variables,
functions and types declared by the declaration statement (in its own scope;
e.g., types declared in an embedded function prototype scope are not included).

This is a significant IL CHANGE.


10/6/08  [EDGcpfe/9261]
End position on "new" expression with parenthesized type

The end position indicated in a "new" expression was incorrect when
the type specified is parenthesized and there is no initializer.
The position indicated was the end of the declarator instead of the
position of the closing parenthesis.  Now fixed.

  typedef void (**ppfn)(void);
  int main() {
    ppfn fn;
    fn = new (void(*)(void));  // End position is now correct
  }


9/30/08  [EDGcpfe/9100]
Representation of casts

Previously, casts with no effect and some casts that changed the type of a
value without affecting the underlying representation were not represented
using an explicit eok_cast node.  Instead, the underlying expression's type
was usually modified directly (an "IL shorthand"), although in some cases
nothing was recorded at all.

Now, casts that appear in the source are always represented using an actual
node.  In addition, if an implicit cast has any effect at all (either by
changing a type, or by removing "bitfieldness") then it is recorded with an
eok_cast node; otherwise, it is not recorded at all.  The IL shorthand of
modifying the "type" field of an expression node directly has been removed.

In GNU and Microsoft nodes, some casts with no effect are still not recorded
to match the behavior of GNU and Microsoft compilers (specifically, to retain
the lvalueness of the cast expression).  For example:

  void f(int x) {
    (int)x = 3;  // Accept in GNU C mode: The cast is not recorded.
  }

The configuration macro PRESERVE_EFFECTLESS_EXPLICIT_CASTS_IN_IL has been
deleted, since its function is now subsumed in the changes described above.


9/26/08  [EDGcpfe/9217]
GNU C compatibility: Array elements with flexible array members

In GNU C mode, the front end now accepts (with a warning) arrays whose
element type is a class type with a flexible array member.  For example:

  struct F { int n; float x[]; };  // Flexible array member x.
  struct F y[3];  // Now accepted in GNU C mode (with a warning).

(Note: In GNU C++ mode, such code was already accepted, because "flexible
array members" are treated as zero-length array members in that mode.  See
Changes entry of 10/17/02.)


9/26/08  [EDGcpfe/9241]
Microsoft compatibility: internal error on class template in Microsoft
in-class specialization

An internal error could occur on a Microsoft in-class specialization that
contained a class template.  The internal error could occur in a number
of places depending on the example.  In this example, the internal error
occurred in prep_generic_operand_full.  Now fixed.

 template<int N> struct A { };
 template<> struct A<1> {
      template <typename T> struct B {
        typedef T* const ptr_B;
      };
 };
  struct C {
    template<int N> struct D { };
    template<> struct D<1> {
      template<class T> struct B {
        typename A<1>::B<T>::ptr_B b_ptr;
        B(typename A<1>::B<T>::ptr_B p):b_ptr(p){}
      };
    };
  };

9/26/08  [EDGcpfe/9229]
GNU compatibility: Attributes in casts

In GNU mode, the front end previously issued an error when encountering an
attribute on the type name in a cast.  Now, such attributes are accepted:
If applicable, they modify the type; otherwise, they are ignored with a
warning.  For example:

  long f(float x) {
    return (__attribute((mode(DI), deprecated)) int)x;
    // The "mode" attribute is applied to "int"; the "deprecated" attribute
  } // is ignored with a warning.

This change also applies to other type names -- like template type arguments
-- that aren't directly specifying the type of a declaration.


9/26/08  [EDGcpfe/9231]
GNU compatibility: __builtin_memchr

In GNU modes, the front end now predeclares __builtin_memchr.


9/24/08  [EDGcpfe/9238]
targ_ptrdiff_t_min and targ_ptrdiff_t_max are not used

targ_ptrdiff_t_min, targ_ptrdiff_t_max, TARG_PTRDIFF_T_MIN and
TARG_PTRDIFF_T_MAX are not actually used in the front end except for
their initialization and in consistency checking code. They have now
been eliminated.

9/24/08  [EDGcpfe/9226]
GNU attributes on classes nested in class templates

The front end previously ignored GNU attributes specified on class definitions
appearing in class templates.  For example:

  template<typename T> struct X {
    struct __attribute((aligned(64))) Y {};
  };
  X<int>::Y y;  // Previously the attribute on Y was ignored.

This behavior was unintentional and is now fixed: The attributes are applied
as expected.


9/22/08  [EDGcpfe/9222]
Preserve address_taken flag on variable merged from multiple translation units

The address_taken flag setting on a variable in a secondary translation
unit is now transferred to the corresponding primary translation unit
variable when the variables are merged.  For example:

file1.cpp:
  extern int i;

file2.cpp:
  extern int i;
  int *p = &i;

The remaining instance of variable "i" in the merged IL now has its
address_taken flag set.

9/22/08  [EDGcpfe/9234]
Missing "template" keyword on dependent call

Core issue 141 fixed a defect in the standard that required a "<" to be
interpreted as the start of a template argument list in a context such as
"x.y<..." if the normal lookup in the scope of the reference found a
function template.  The similar rule for class templates makes sense, but
for function templates there is no way in that context that a valid program
could use the template found by the normal lookup.  We now implement the
resolution of core issue 141 and issue a diagnostic on the example below
(in modes in which nonclass templates are parsed).  This is very similar to
the GNU compatibility issue below except that the front end only allowed
the invalid code for this entry when the current context found a function
template, not when it found an overload set containing a function template
(as in the entry below).

  template <typename T> struct A {
    template <typename U> void f(U);
  };
  template<typename T> struct B {
    template <typename U> void f(U);
    A<T> a;
    void g(T t) {
      a.f<T>(t);  // an error should be issued here
    }
  };

9/22/08  [EDGcpfe/9232]
GNU C++ compatibility: missing "template" keyword on dependent call

The g++ compiler accepts a call of a dependent function template without
the use of the "template" keyword if a normal lookup in the scope of the
reference finds a function template or an overload set containing a
function template (even though that function template will not end up being
the one that is actually called).  We now emulate this in g++ mode.  Formerly,
an error would be issued in modes in which nonclass prototype instantiations
are done (gnu_version >= 30400 or the --parse_templates option is used).

  template <typename T> struct A {
    template <typename U> void f(U);
  };
  template<typename T> struct B {
    template <typename U> void f(U);
    void f(){}
    A<T> a;
    void g(T t) {
      a.f<T>(t);  // accepted in g++ mode - should be written as:
                  // a.f template <T>(t); 
    }
  };
  int main() {
    B<int> b;
    b.g(1);
  }

9/12/08  [EDGcpfe/9203]
Base and derived class casts in backing expressions for address constants

The backing expressions for address constants now include base class and
derived class casts where appropriate.  Formerly, the backing expression
was left unchanged when such a cast was folded, which no longer matched
the constant (though it was harmless in terms of C++-generating back end
output).  Now fixed.

  struct B {
    int x;
  };
  struct C {
    virtual int f() {
      return 3;
    }
  };
  struct D : public B, public C {
  };
  D g_d;
  int g_var1=g_d.f();  // Backing expression for constant for left operand
                       // now includes base class cast, in versions that
                       // maintain backing expressions


9/12/08  [EDGcpfe/9221]
Abort on reference-to-reference-to-function construct

Attempting to add a type qualifier (like "const") to a function type through
a reference-to-reference construct resulted in an internal error (in
make_qualified_type, il.c).  For example:

  void f() {
    typedef void (&RF)();
    RF const &rf = f;  // Previously triggered an internal error.
  }

This is now fixed: The type qualifier is ignored (with a warning).


9/11/08  [EDGcpfe/9208]
Invalid IL for designators into anonymous unions

In some modes (like Microsoft C99 mode), a designator can refer to a field of
a nested anonymous union.  In some cases involving multiple levels of
anonymous unions (including "nonstandard anonymous unions"), the IL describing
an initializer containing designators into those unions was invalid.
For example:

  struct X {
    union {  // Anonymous union.
      int i;
      struct {  // Nonstandard anonymous union.
        float f;
        short s;
      };
    };
  };
  struct X x = { .s = 7 };  // Invalid IL created for the aggregate
                            // initializer constant.

This is now fixed.


9/10/08  [EDGcpfe/7621]
Lookup of names in name qualifiers

The lookup of names before the "::" in a qualified name did not correctly
implement the behavior required by the standard.  If the lookup of a name
before the "::" encountered an enum name or a non-class typedef that name
was ignored and the lookup continued to look for names in enclosing scopes.
The standard requires that such names be returned by the lookup (resulting
in an error).  The Microsoft and GNU compilers do not implement the rules
required by the standard, so our behavior in Microsoft and GNU modes matches
the behavior of those compilers as noted below.

  // Now results in an error except in g++ mode when gnu_version is < 30400
  namespace N {
    const int a = 42;
    enum N { e };
    int i = N::a; // error: N refers to enum not namespace
  }

  // Now results in an error except in g++ mode when gnu_version is < 30400
  // and Microsoft mode
  namespace M {
    const int a = 42;
    typedef int M;
    int i = M::a; // error: M refers to typedef not namespace
  }

9/9/08   [EDGcpfe/9108]
New representation for parentheses

IL CHANGE: Parentheses are now (optionally) represented in the IL by
means of expression nodes with an operator of eok_parens.  These are
not usually generated; PARENS_IN_IL must be set to TRUE to request
them.  When present, these nodes represent instances of parentheses
in source expressions, and, if EXTRA_SOURCE_POSITIONS_IN_IL is TRUE,
provide detailed position information on those parentheses.

The mechanism previously enabled by EXPR_RANGE_MODIFIERS_IN_IL, which
used an_expr_range_modifier entries to provide source positions
for operators that were not explicit in the IL, has been eliminated.

Parentheses are not used or allowed in versions that use IL lowering,
so compiler customers will see no difference from this change.
Customers that do enable PARENS_IN_IL should note that it introduces
a problem very similar to the skip_typerefs problem for types: one
must be careful to strip parentheses off an expression before checking
the operator.  That can be done by calling skip_parens.

9/9/08   [EDGcpfe/9210]
Optimization in sequence number to file and line translation

The sequence number to file/line translation uses a cache so that multiple
translations that refer to the same source file region can be handled quickly.
When a new entry is added to the lookup table, the cache is now updated to
refer to the new entry rather than simply clearing the cache as was done
previously.  This is of particular use when a cross-reference file is being
generated as that process involves many additional sequence number
translations.

9/8/08   [EDGcpfe/8651]
Microsoft compatibility: Typedefs for class and enum types

In Microsoft C++ mode with Microsoft bugs mode enabled (the default), a
typedef for a named class or enum to that same name (and declared in the same
scope) is marked as invisible and does not affect later declarations.
For example:

  typedef struct S {} S;
  double S = 1.0;  // Now accepted in Microsoft C++ bugs mode.


9/7/08   [EDGcpfe/5460, EDGcpfe/7192, EDGcpfe/7756, EDGcpfe/9188]
Assertion failure with nested template with same name as friend template

A template friend declaration that declared a class template with the
same name as a nested class of the enclosing class template resulted
in an internal error in find_class_template_member.  Now fixed.

  template <class T> class A {
    template <class U> friend struct B; 
    template <class U> struct B { }; 
  };

9/6/08   [EDGcpfe/9209]
Allow implicit typename to be used when parsing nonclass templates

Implicit typename processing is disabled by default in modes in which
nonclass templates are parsed.  Formerly, this was done even if implicit
typename was explicitly enabled by a command-line option.  Implicit
typename is no longer disabled if it was explicitly requested (even though
this combination is seldom what the user really wants).

9/4/08   [EDGcpfe/9143]
GNU compatibility: Alias names mapping on multiple declarations

In GNU modes, when an alias attribute referred to an asm name used for
multiple declarations, the last declaration with that asm name was picked
(arbitrarily) as the aliased declaration.  Now, the earliest declaration
that is either defined or itself an alias is picked instead.  This avoids
some spurious warnings and results in IL that more closely matches the
behavior of the GCC compiler and its assembler.  For example:

  void f() {}
  void f1() __asm("X") __attribute((alias("f")));
  void f2() __asm("X");
  void g() __attribute((alias("X")));
    // Previously aliased to f2 (with a warning), and recorded as __asm("X").
    // Now aliased to f1 (with no asm name for g).


9/4/08   [EDGcpfe/9206]
C++-generating back end: incorrect handling of function try blocks

In modes in which the C++-generating back end generates template bodies from
recorded template strings, function try blocks were not handled properly
resulting in the "try" keyword being emitted twice in the generated code.
This has been fixed.

  template <class T> struct A {
   ~A() try { } catch(int) { }
  };

9/3/08   [EDGcpfe/7699]
Abort during argument deduction involving address constants

In some fairly unusual cases, the front end aborted (usually with an internal
error "not integral type" in get_integer_attributes) during the deduction of
template arguments that involve computations on address constants.  For
example:

  template<int> struct X {};
  template<typename T> X<T()+1> f();  // (1)
  template<typename T> void f();      // (2)
  int main() {
    f<int*>();  // An attempt to partially instantiate template (1) previously
  }             // triggered an abort.  Now, (1) fails to deduce and (2) is
                // selected instead.

This is now fixed and such situations are now treated as an ordinary deduction
failure.


8/29/08  [EDGcpfe/9198]
Invalid IL for cast of complex value to bool in g++ mode

In g++ mode with lowering of complex types enabled (LOWER_COMPLEX is TRUE),
the front end failed to fully lower the cast of a complex value to bool.
This could also lead to the generation of invalid code by the C-generating
back end.  For example:

  _Complex float z;
  void f() { if (z) {} }  // The implicit cast of "z" to bool (in g++ mode)
                          // was previously not fully lowered.

This is now fixed.


8/28/08  [EDGcpfe/9099,EDGcpfe/7640]
C99 _Bool type after lowering

Previously, the "bool_type" flag of the IL entry representing the C99 _Bool
type was set to FALSE by IL lowering (thereby making the type it describes
identical to the underlying integer type of _Bool).  This is no longer done:
The bool_type flag remains TRUE in the lowered IL.


8/28/08  [EDGcpfe/9099]
Normalization of boolean controlling expressions

Previously, boolean controlling expressions (e.g., the expression that
determines which way an if-statement branches) were unconditionally normalized
to produce a 0/1 value.  This normalization (often achieved by adding a "!= 0"
on top of the expression appearing in the source) was performed in the front
end proper.

This normalization is now optional and it is performed as part of the IL
lowering process.  Whether normalization happens is determined by the new
configuration macro LOWERING_NORMALIZES_BOOLEAN_CONTROLLING_EXPRESSIONS.
Note that a consequence of setting this macro to TRUE is that IL lowering
will happen even for plain C89 input source.


8/25/08  [EDGcpfe/9110]
Result of eok_bassign is now void

The result of the IL operator eok_bassign is now "void".  Previously, the
result of eok_bassign was its first operand (an lvalue).  (eok_bassign
represents a bcopy/memcpy-like operation.  It is only produced by internally
generated code such as generated assignment operators and constructs created
by IL lowering.)


8/21/08  [EDGcpfe/9126]
GNU and Microsoft compatibility: Abstract class parameters in templates

Usually, any attempt to create a parameter type that is an abstract class type
is diagnosed as an error by the front end.  Now, only a warning is issued in
GNU and Microsoft C++ modes if the parameter is the result of the declaration
or instantiation of a function template, and if the abstract-type parameter is
not a parameter of the function template itself.  For example:

  struct A { virtual void p() = 0; };
  template<typename T> void f(void (*)(T)) {}
  int main() {
    f<A>(0);  // Now elicits a warning instead of an error.
  }


8/21/08  [EDGcpfe/9180]
GNU compatibility: Allow promotion to long long in C99 mode

In cases where both gcc mode and c99 mode are enabled (i.e., emulating
gcc -std=c99), promotion to long long is now allowed.  Long long promotion
remains disabled in gcc mode when c99 mode is not specified.  This changes
the behavior of this program when --gcc and --c99 are specified together:

  int printf(const char *,...);
  int main() {
   long long l = -2147483648L;
   printf("%lld\n", l);   // now prints -2147483648
   return 0;
  }

8/21/08  [EDGcpfe/9183]
Declaration specifiers flag without effect

The macro DSI_IN_ABSTRACT_FUNC_DECLARATOR (used as a flag value for calls to
decl_specifiers) has been removed.  Its use in the front end had no effect,
and it was not actually set for abstract function declarators.

8/19/08  [EDGcpfe/9097]
Representation of operators in IL expressions (IL CHANGE)

Operators in IL expressions are represented using values ("operator kinds") of
type an_expr_operator_kind.  Previously, many operators (like addition,
subtraction, etc.) were mapped on distinct operator kinds depending on the
class of types the operation applied to.  For example, addition was encoded
with eok_iadd for integer-like types, eok_fadd for non-complex floating-point
types, etc.

Now, each operator is mostly mapped onto a single operator kind, and a new
"type_kind" field in type an_expr_node indicates which type class the operator
applies to.  A few exceptions remain for cases where we decided that the
semantics of the operator were sufficiently unique to warrant a different
operator kind.  Most notable is the case of pointer arithmetic, which is still
represented using eok_padd, eok_psubtract, and eok_pdiff rather than the more
generic eok_add and eok_subtract.

This is a significant IL CHANGE, and customers will likely have to change
their code.  However, we expect that it will simplify code in many cases, and
it also will ease any future addition of operations on new type kinds.


8/18/08  [EDGcpfe/9051]
Internal error: "get_integer_attributes: not integral type"

In configurations with RECORD_CONSTANT_EXPRESSIONS_IN_IL set to TRUE,
inlining of calls that contain operations on pointer to data members could
result in an internal error: "get_integer_attributes: not integral type".
This is now fixed.  For example:

  struct A { int i; };
  struct D : public A {
    int A_pmd_fa(D *pD, int D::*pmd) { return pD->*pmd; }
  };
  main() {
    D *pD;
    pD->A_pmd_fa(pD, &A::i);
  }

8/16/08  [EDGcpfe/9149]
Excess instantiations of static data members

The front end recorded the need for instantiations of static data members
of class templates unnecessarily in some cases.  Specifically, it did so
when or static data member was used in a prototype instantiation or
when a constant-valued static data member was used only as a constant.
These extra instantiations were largely invisible because removal of
unneeded entities would eliminate those static data members, which would
clear the instantiation request.  However, users with configurations
that have both automatic template instantiation and no removal of
unneeded entities would have seen the instantiations.  Now fixed.

8/15/08  [EDGcpfe/9094]
GNU compatibility: Attribute "aligned" on functions

In GNU modes with gnu_version >= 40300, the front end now accepts the
"aligned" attribute applied to functions.  For example:

  void f() __attribute((aligned(8)));

The attribute value is recorded in the function's type, but is otherwise
ignored by the front end.


8/15/08  [EDGcpfe/9157]
Dropping of __restrict qualifier allowed in Microsoft-mode conversion

Microsoft mode now allows the implicit dropping of a __restrict type
qualifier in a conversion.  (Actually, MSVC8 considers dropping
__restrict as identical to adding __restrict, though we don't know
why.)  The handling for __unaligned has been changed to the same,
which is a more accurate emulation of MSVC's behavior (see Changes
entries of 4/23/08 and 9/19/07 for previous iterations on this).

  int **p;
  void test(int * __restrict * m) {
    p = m;  // Now accepted in Microsoft mode (with microsoft_version >= 1400)
  }

8/14/08  [EDGcpfe/9136]
ELF visibility of external variables created during IL lowering

In configurations with GNU_VISIBILITY_ATTRIBUTE_ALLOWED set to TRUE, The front
end now records an appropriate ELF visibility kind in variables generated by
IL lowering.  This includes virtual function tables, typeinfo variables, and
promoted local static variables.  For example (assuming GNU C++ mode):

  struct __attribute((visibility("hidden"))) HiddenClass {
    virtual void f();
  };
  void HiddenClass::f() {}
  // The a_variable entries representing the virtual function table and the
  // typeinfo struct for HiddenClass will now have their ELF_visibility field
  // set to evk_hidden.

8/14/08  [EDGcpfe/6432]
Additional information about file I/O failures

Formerly, when the front end detected an I/O failure, it would produce a
general message such as "cannot open source file ..." or "error
while writing ... file", but no information was provided about the cause
of the failure.  The general message is still used in the common case of
attempting to open a file that does not exist, but for other kinds of errors
additional information is provided in the message.  For example, if you
specify a source file that you don't have permission to read, the message
will say 'cannot open source file "x.c": Permission denied'.  For some of
the errors, the text is provided by our error_msg.txt file.  In most cases
the text is provided by the host system's strerror routine.  A few of
the Windows-specific routines in host_envir.c use the Windows routines
GetLastError and FormatMessage to produce the text.

As part of this change, the handling of output file error checking has
been revised.  The front end no longer prohibits the use of certain file
suffixes for output files.  The suffix list was incomplete, so rather than
try to provide a complete list of suffixes, the opening of output files
is now postponed until the primary source file has been identified.  The
front end ensures that the primary source file is not accidentally overwritten
as a result of a mistyped command line (e.g., "edgcpfe --xref x.c x.c").

If the --error_output option is used to redirect diagnostics to a file other
than stderr, the new file is now opened after all command-line processing
has been done.  This ensures that all command-line diagnostics will be
issued to stderr.  Formerly, command-line diagnostics that followed the
--error_output option would be directed to the new file.

8/11/08  [EDGcpfe/9141]
Assertion failure: "add_dyn_init_cleanup: no temps"

An object allocated by a new operator with a default argument must be
deleted by its matching deallocation function during exception handling.
In cases where an object requiring initialization was allocated by a
new operator with a default argument, and a matching deallocation delete
function existed, and the allocation had an overlapping temporary lifetime with
another dynamic initialization, an assertion failure was triggered during
lowering.  This has now been fixed.

  typedef unsigned int size_t;
  struct A {
    virtual void f() {}
    void *operator new(size_t sz, size_t t = 0) { return 0; }
    void operator delete(void *p, size_t sz) { }
  };
  struct B {  
    B (A* p);
    ~B ();
  }; 
  int main() {
    B b(new A);  // triggered an assertion failure
  }

8/9/08   [EDGcpfe/7930]
GNU C++ compatibility: friend injection enabled/disabled based on gnu_version

Formerly, friend injection was not specially enabled or disabled in g++
mode (the default friend injection mode was used).  In g++ mode, friend
injection is now enabled if gnu_version is < 40100 and disabled otherwise.

  class X {
    friend void f(X*);
    friend class Y;
  };
  int main() {
    Y* y;  // Y not declared without friend injection
    f(0);  // f not declared without friend injection
  }

8/7/08   [EDGcpfe/9120]
Template with dependent explicit argument is dependent argument to call

A function template with an explicit argument list that contains at
least one template-dependent argument is now considered dependent
as an argument to a call.  That makes an example like the following
be accepted in strict mode:

  template <class T, int> void One(T*) {}
  template <class T> int Two(void (*)(T*)) { return 0; }
  template <int I> static int Foo(void *)
  { return Two<int> (One<int, I>); }
  int g(int (*)(void*));
  int main() { return g(Foo<8>); }

8/7/08   Constant expressions unconditionally recorded in IL

The features previously controlled by RECORD_CONSTANT_EXPRESSIONS_IN_IL,
RECORD_TEMPLATE_DECL_CONSTANT_EXPRESSIONS_IN_IL, and
RECORD_GENERAL_CONSTANT_EXPRESSIONS_IN_IL are now unconditionally included
in the front end.  These macros are no longer used.

8/5/08   Reference to freed memory in db_source_file_for_seq_info

When db_source_file_for_seq_info was called from fe_wrapup in configurations
that write an IL file, it referenced memory that had already been freed.
Now fixed.

8/5/08   Checking for references to freed memory

A mechanism to help detect references to freed memory has been added.  If
the configuration flag OVERWRITE_FREED_MEM_BLOCKS is set, memory blocks
that are part of memory regions will be overwritten before being put on
the available list or freed, so that any later references to the memory
will be more likely to be noticed.  The new flag is set by default when
EXPENSIVE_CHECKING is enabled.

8/4/08   Abort in cp_gen_be.c on imaginary division in C99 mode

In C99 mode, dividing a real value by an imaginary value (C99 _Imaginary type)
triggered an internal error in the C++-generating back end (cp_gen_be.c).
For example:

  int main() {
    _Imaginary float jf;
    float f;
    jf = f/jf;  // Triggered an internal error in cp_gen_be.c.
  }

This is now fixed.

8/1/08   GNU C++ compatibility: elaborated type specifier naming enum typedef

Older versions of g++ (up to 3.3) allow an elaborated type specifier to
name a typedef to an unnamed enum type.  We now emulate this in g++ mode
when gnu_version is < 30400.

  typedef enum {} T;
  enum T t;

8/1/08   Improve performance of free_all_memory_regions

For very large programs the processing done by free_all_memory_regions
could be quite expensive because free_memory_region attempts to coalesce
contiguous memory blocks back into larger ones.  Since free_all_memory_regions
frees all memory, this processing is unnecessary.  free_all_memory_regions
now simply discards all of the complete blocks allocated for memory
regions.  This optimization is most significant when not writing an IL file
(many of the memory regions are freed earlier when an IL file is used).

7/31/08  Memory corruption when USE_LONG_DOUBLE_FOR_HOST_FP_VALUE is FALSE

The routine make_huge_fp_value could cause memory corruption when
USE_LONG_DOUBLE_FOR_HOST_FP_VALUE and TARG_HAS_IEEE_FLOATING_POINT are both
FALSE.  This has been fixed.  This example (which requires GNU mode) would
write past the end of an_internal_float_value in such configurations,
although on most systems this would not result in an abort or other
observable incorrect behavior.

  int main() {
   long double f = __builtin_huge_vall();
  }

7/31/08  Internal error on unique function template specialization reference
         with nontype template arguments

An internal error (in create_initial_template_arg_list) could occur
when using an explicit template argument list to identify a unique instance
of a function template, and the explicit template argument list contained
a nontype template argument.  Now fixed.

  struct Base { template<int I> int func(void) { return I + 1; } };
  struct Derived : public Base {};
  typedef int (Derived::*func_ptr) (void);
  void f(void) { func_ptr ptr = &Derived::func<1>; }

7/30/08  Prelinker loop when using implicit inclusion

A prelinker loop could occur when using implicit inclusion if the scanning
of the implicitly included file (but not the instantiation of the templates
in the file) resulted in additional instantiations.  This has been fixed.

file test.c:

  #include "C.h"
  template <class T> struct A {
    static void f();
  };
  template <class T> void A<T>::f() {
    C<T>::g();
   }
   int main() {
       A<int>::f();
   }
   template <class T> int B<T>::g() { return 0; }

file C.h:

   template <class T> struct B { static int g(); };
   template <class T> struct C { static void g(); };

file C.c:

  int x = B<int>::g();
  template <class T> void C<T>::g() { }

7/28/08  GNU compatibility: Vector modes (IL CHANGE)

When GNU_VECTOR_TYPES_ALLOWED is TRUE, the front end now supports vector mode
names as arguments to the "mode" attribute in GNU mode.  For example:

  __attribute((mode(V4SI))) int x;  // Vector of 4 int elements.

See also the Changes entry of 7/15/08, which describes the vector_size
attribute.  As part of this change, the "mode" field of a_param_type entries
has been removed (an IL CHANGE).

7/28/08  Removal of tests of CIL and CFE

Because the FORTRAN-specific parts of the IL have been removed (see below),
the tests of CIL and CFE are no longer needed and have been removed.

7/28/08  Removal of FORTRAN-specific IL entities

The FORTRAN-specific code previously guarded by the FIL and FFE macros has
been removed from the front end  (IL CHANGE).  As part of this change
two changes were made to the a_label entry: the variant.exec_stmt field
is now simply exec_stmt and the used_in_assign field has been renamed
address_taken.

7/25/08  Improved performance in applications with many PCH files

Some applications essentially have one precompiled header file for each
primary source file.  In such cases, it is better to use the PCH file
associated with the primary source file instead of searching through a
potentially large number of PCH files for an optimal one.  In automatic
precompiled header mode (i.e., when using the normal --pch option) the
front end now looks for a PCH file that matches the primary source file
before searching for other PCH files.

7/25/08  Lowering: Pointers to functions with cv-qualified copy constructed
                   parameters

During lowering, function arguments that are passed via a copy constructor
are re-written as pointers and any cv-qualification is dropped in the resulting
lowered function type.  This can cause a type mismatch in generated C code when
a function pointer with such a type is used as an argument, as the source of an
assignment statement or in an initialization.  In such cases, a cast is now
introduced to cast the function pointer to the proper type.  This change
doesn't affect C or C++ modes where functions are unprototyped (i.e., in cfront
mode or when MAKE_ALL_FUNCTIONS_UNPROTOTYPED is TRUE).  For example:

  struct A { ~A(){} };
  void g(const volatile A){}
  int main() {
    void (&r)(A) = g;
  }

7/24/08  Representation of lvalues in IL expressions changed

The IL for expressions has been significantly changed (IL CHANGE).
The new form identifies each node as an lvalue or rvalue, and makes
lvalues first class entities.  (In the old form, lvalues were represented
as addresses.  While this was self-consistent, it was confusing for some,
and we received many questions about it.)  The new form also preserves
all source operators in the tree.  No operators are implicit, and no
operators are translated to forms that make it hard to recover the
original source form.  Most noticeably, there is now an "&" operator,
member selection and subscripting operators are simplified, and there
are new operators that deal explicitly with references.

These changes are not backward-compatible, and customers will likely
have to change their code.  Detailed documentation on the changes and
how to update existing code is available from EDG.

7/17/08  Performance issues with using-directive lookups

When a lookup is done that makes use of using-directives, the result of
the lookup is saved so that the symbol may be reused by a subsequent
lookup.  In some cases, the saved symbol was created improperly causing
it to be considered unsuitable when looking for a saved symbol in a
subsequent lookup.  This could result in a large number of symbols on
the saved symbol list, causing poor compilation performance.  This has
been fixed.  This test case, which does 100,000 lookups, formerly took
over a minute to compile and now takes under a second (on a typical x86
system).

  namespace N {
    int i;
  }
  using namespace N;
  #define x0(x) x; x; x; x; x; x; x; x; x; x;
  #define x1(x) x0(x) x0(x) x0(x) x0(x) x0(x) x0(x) x0(x) x0(x) x0(x) x0(x)
  #define x2(x) x1(x) x1(x) x1(x) x1(x) x1(x) x1(x) x1(x) x1(x) x1(x) x1(x)
  #define x3(x) x2(x) x2(x) x2(x) x2(x) x2(x) x2(x) x2(x) x2(x) x2(x) x2(x)
  #define x4(x) x3(x) x3(x) x3(x) x3(x) x3(x) x3(x) x3(x) x3(x) x3(x) x3(x)
  void f() {
    x4(i++);
  }

7/16/08  decl_pos in a_decl_pos_block not set

The decl_pos field of the a_decl_pos_block entry was not being set.  This has
been fixed.  The a_decl_pos_block entries are not part of the IL, but this
could cause unexpected results if customer-supplied code made use of the field.

7/15/08  GNU compatibility: Attribute vector_size

In GNU modes, the front end now accepts the "vector_size" attribute applied to
integer, enum, and floating-point types.  The new configuration macro
GNU_VECTOR_TYPES_ALLOWED must be TRUE to enable this feature (it is FALSE by
default).  The "vector_size" attribute creates a "vector" type; operations on
such a type may be mapped on special CPU instructions by a back end.
For example:

  #define vector(N) __attribute((vector_size(N)))
  vector(16) int f() {
    vector(16) int x = { 1, 2, 3, 4 };
    return x;
  }

As the example shows, the brace-initializer syntax is supported for vectors
(but designators are not allowed).  The argument to the vector size attribute
is the length of the vector in bytes (it must be an integer constant and a
power of two).  E.g., "vector(16) int" designates a vector of four int
elements on a machine with a 4-byte int type.

Currently, template-dependent vector types are not allowed.  This mostly
matches GCC's behavior, except that GCC will accept but ignore a vector type
whose element type is nondependent but whose size (the argument to the vector
size attribute) is dependent; the EDG front end issues an error on such cases.
For example:

  #define vector(N) __attribute((vector_size(N)))
  template<typename T, int N> void f() {
    vector(16) T v;   // Error with GCC and EDG.
    vector(N) int w;  // Error with EDG; same as "int w;" with GCC.
  }

When the IA-64 ABI is enabled (IA64_ABI is TRUE), lowering produces the same
mangling for vector types as GCC.  Unfortunately, this mangling ignores the
size of the vector, and may therefore produces conflicting manglings (this
matches the GCC behavior).  For example:

  #define vector(N) __attribute((vector_size(N)))
  void f(vector(8) float) {}   // (1)
  void f(vector(16) float) {}  // Same mangled name as (1) with the IA-64 ABI.

When the Cfront ABI is enabled (IA64_ABI is FALSE), an unambiguous encoding
is used and the example above creates no problems.

7/15/08  IL entries set before cross-reference entries are generated

In general, a symbol is set to point to its associated IL entry before
a cross-reference entry for that symbol is generated.  A few exceptions
to this rule were discovered and corrected.  Symbols for template parameters
(of all kinds) and for both member and nonmember function templates now
refer to their associated IL entries before any cross-reference entries
are generated for them.  In the example below, the symbols for x, y, z, g,
T, and X::f now have their associated IL entries set when their cross-reference
entries are generated.

  template<int x, class y, template<int> class z> void g(y (*)[x]) { }
  class X {
    template<class T> void f(T t) {}
  };

7/15/08  Overload resolution adjustment in Microsoft mode

In a corner case involving a class with no user-written constructors -- only
a default bitwise copy constructor -- and another class with a conversion
function to a reference to const of the first class, overload resolution in
Microsoft mode incorrectly failed to find the conversion function.  Now fixed.
Sun mode is also affected similarly; old versions of the Sun compiler
did fail to find the conversion, but newer versions do it correctly, and
we now do that as well in Sun mode.

  struct A {};
  struct B {
    operator const A&();
  };
  void foo() {
    B b;
    A a = b;  // Formerly got a spurious error in Microsoft mode
  }

7/14/08  Cross-reference entries for template instantiations

When cross-reference output is enabled, a reference to an instance of a class
template would result in the generation of a reference entry ("R").  If the
reference triggered a full instantiation, a definition entry ("D") was
emitted first.  Otherwise, partial instantiations of function templates
generated a declaration entry ("d", see Changes entry of 6/1/08).

Now all template instantiations generate a "T" entry (for full instantiations)
or a "t" entry (for partial instantiations) instead of the "D"/"d" entries.
Note that the partial instantiation of a class template also generates a "t"
entry (whereas previously no "d" entry was created for that case).
For example:

  template <class T> struct A {
    struct B {};
  };
  int main() {
    A<int> *a;     // "t" entry for A<int>
    A<int>::B *ab; // "T" entry for A<int> and "d" entry for A<int>::B.
  }

7/11/08  Parameter type cv-qualifiers and deduced routine types

When a template parameter was deduced from a function type, the deduced type
had parameter type entries with the cv-qualifiers from the parameter type
entries of the source type.  This could result in unexpected types in the
lowered IL.  The example below, when compiled with a C-generating back end
version, produced C code that resulted in warnings from some C compilers.
The cv-qualifiers are now removed from the parameter type entries of
routine types that result from type deduction.

  struct A { ~A(){} };
  template <class T> void f(T v) {
    void (&r)(A) = *v;
  }
  void g(const volatile A){}
  int main() {
   f(g);
  }

7/9/08   Performance improvement in qualified lookup in dependent base classes

When a name is looked up in a dependent base class, the projection symbol
that is created is marked as invisible so that it will not be found by
subsequent normal lookups.  Such projection symbols should be found by
qualified lookups, but were not.  This would result in a new projection
symbol being created for each lookup, which in turn slowed down subsequent
lookups because of the large number of symbols on the inactive list.  This
has been fixed.

  template <int I> struct B { typedef int X; };
  template <int I> struct A : B<I> {};
  int main() {
    { typedef A<1>::X x; }
    { typedef A<1>::X x; }
    // repeat above many times
  }

7/7/08   Mismatched qualifiers should cause deduction failure

When matching a function type from a template declaration with an actual
type, the front end did not check for matching cv-qualifiers.  In the
example below, this caused the partial specialization to be used instead
of the primary template.  This has been fixed.  Note that the difference
between this case and the one in the entry below is that in this case the
type in the template is itself a function type.  In the entry below, the
type in the template is just a template parameter type which is then deduced
to be a function type.

  template <class T> struct A;
  template <class U> struct A<U()> { };
  typedef void (fp)() const;
  int main() {
    A<fp> a;  // incomplete type error (does not match partial specialization)
  }

7/7/08   Qualifiers should be retained when deducing a function type

In template argument deduction, a function type can be deduced from a
member function type.  If the member function included cv-qualifiers those
qualifiers should be retained as part of the function type, but were instead
being dropped by the front end.  This resulted in problems such as the failure
to match the partial specialization in this example.  Now fixed.

  template<typename T> struct A;
  template<typename T, typename U> struct A<T U::*> {
    typedef U type;
  };
  struct S { };
  typedef A<int (S::*)()>::type       t0;  // accepted
  typedef A<int (S::*)() const>::type t1;  // previously rejected

7/3/08   Remark on assumed array size in C mode

In C mode, a file scope array declared without a specified size is assumed
to have a size of one.  A remark is now issued in such cases.

  int a[];

7/3/08   Abort if error output is directed to an invalid file

If the --error_output option was used to specify an invalid output
file, the front end would abort attempting to issue the "invalid error
output file" message.  Now fixed.

6/27/08  Lowering of certain dynamic aggregate initializations could produce 
         "assign_entry_number: non-file-scope ptr" internal error when
         exceptions are enabled

As a result of the changes described in the entry of 11/8/07, lowering of file
scope dynamic initializations of nested aggregates that contained elements
requiring destruction as well as constants could have resulted in an internal
error ("assign_entry_number: non-file-scope ptr").  This problem manifested
itself only when exceptions were enabled.  This is now fixed.  For example:

  struct S {
    ~S();
  };
  struct X {
    S a[1];
    int b;
  };
  static X dat[] = { { {}, 0} };

6/26/08  GNU C++ compatibility: friend template declaration with mismatched
         template parameter list

The g++ compiler accepts a friend class template declaration in which the
template parameter list does not match the original declaration if the
class template name is specified as a qualified name.  We now accept this
usage in g++ mode (a warning is issued).

  namespace N {
   template <typename T, typename U> struct A { };
  }
  struct  B {
    template<typename T> friend struct N::A;
  };

6/26/08  GNU compatibility: Size constraints on transparent unions

In GNU mode, the front end only treated a union as a transparent union if it
was declared with the transparent_union attribute, and if all its members had
equal size.  Now, if the first member is an integer type, subsequent integer
members may have a smaller size than the initial integer member.  For example:

  typedef union {
    short s;
    char c;
  } TU __attribute((transparent_union));
    // Now a valid transparent_union (previously a warning was issued, and
    // the attribute was effectively ignored).

6/26/08  Microsoft compatibility: spurious incomplete type errors on
         nested class templates in in-class specializations

Member class templates declared inside Microsoft mode in-class specializations
were not handled properly, resulting in spurious "incomplete type not allowed"
errors on an attempt to instantiate the member class template.  Now fixed.

  template<class T> struct X {
    template<class T3> struct A { };
    template <> struct A<int> {
      template <class T2> struct B {
        typedef int Y;
      };
      typedef typename B<int>::Y  Y;
    }; 
    typedef typename A<int>::Y  Y;
  }; 
  typedef X<int>::Y xy;


6/26/08  Diagnostics for duplicate type qualifiers

The severity of the diagnostic issued for a duplicated const, volatile, or
restrict qualifier has been reduced in many modes.  Specifically, the
diagnostic is now a warning in all nonstrict modes (and, as was already the
case, in strict C99 mode).  In strict non-C99 modes, a discretionary error
is issued (previously, the error was not discretionary).  For example:

  int const const i = 1;  // Now a warning instead of an error in default C
                          // mode.

6/26/08  Abort or infinite loop on member declaration with Microsoft attribute

In configurations that set GENERATE_SOURCE_SEQUENCE_LISTS to TRUE, the front
end aborted (in any of various places) or ran into an infinite loop (in
cp_gen_be.c) with member declarations that included a Microsoft attribute.
For example:

  __interface IX {
    [id(0)] int f();  // Could trigger an abort or an infinite loop,
  };                  // depending on the exact front end configuration.

This is now fixed.

6/16/08  Emulation of g++ on emission of typeinfo variables, IA-64 ABI

It appears that g++ puts out typeinfo definitions in some cases where
the IA-64 ABI does not require them.  We dealt with some of these cases
previously (see entry of 11/29/07).  Now, we've noticed that even in some
cases where a class has a key function g++ puts out a typeinfo variable
when referenced, rather than just where the virtual function table
is defined.  Specifically, g++ seems to do that when the class
is a template class.  We now emulate that.

  class a { virtual void f(); };
  template <class AT> struct FA {
    virtual void g();  // Never defined
  };
  int main() {
    a *p = 0;
    void *q = (void*)dynamic_cast<FA<int>*>(p);
  }

6/8/08   Call with explicit template argument that is const variable with
         dependent value

Overload resolution now treats a call in a template that specifies
an explicit argument that is a function-local const variable whose
type is not dependent but whose value is dependent as a dependent
call when template definitions are parsed.  Formerly, this was not
done and the front end aborted in IL lowering with the error
"lower_constant: bad kind".

  template <unsigned u> static inline float f(const float a) { return a;}
  template <unsigned u> static inline float g(const float a) {
    static const unsigned cvar = u;
    return f<cvar>(a);  // Caused abort in --parse_templates mode
  }
  int main() {
    float pi = 3.14f;
    g<2>(pi);
  }

6/5/08   Declaration position of explicit specialization declaration

Formerly, the declaration position of an explicit specialization would be
updated by a repeated non-defining declaration of the explicit specialization.
Now, the declaration position will only be set by the first declaration of
the explicit specialization, and by a subsequent definition of the explicit
specialization (if the initial declaration was not a definition).

  template <class T> void f(T) {}
  template <> void f(int);  // decl_position of f(int) set here
  template <> void f(int);  // decl_position of f(int) formerly updated here
  template <> void f(int){} // decl_position of f(int) updated here

6/5/08   Partial ordering in non-call contexts

A number of issues with regard to the partial ordering of function templates
were not adequately specified in the standard.  Core issue 214, which is
part of the current working paper but not part of C++ 03, clarifies the
handling of partial ordering of function templates in non-call contexts.
These contexts include taking the address of a function, and declarative
contexts (explicit specializations, explicit instantiations, and friend
declarations).  In such contexts the entire function type participates
in partial ordering, so examples like the one below should not be ambiguous.
The front end now considers the entire function type in such contexts.

  template<class T, class U, class V> struct Y { };
  struct X {
    template<class T>          Y< T, void *, int> to_y();
    template<class T, class U> Y< T, U, int>      to_y();
  };
  template<> Y<char, void *, int>  X::to_y<char> ();        // !!!
  template<> Y<char, int *, int>   X::to_y<char, int *> ();
  void g() {
    X x;
    x.to_y<char> ();
    x.to_y<char, int *> ();
  }

6/5/08   Invalid IL for calls in multi-translation-unit mode

In some cases, the code generated by IL lowering for calls was
incorrect when multiple translation units were compiled
together, in that the call assumed a parameter was added to
return the result, and the called function did not have that added
parameter.  This occurred when a function was called in a
secondary translation unit but not in the primary translation
unit, and the return type of the function is a class that
is not fully instantiated in the primary translation.  The
problem was that the value_returned_by_cctor flag in the routine
in the primary translation unit was not properly set to TRUE,
with the consequence that IL lowering did not add the parameter.
Now fixed.

Primary translation unit:

  struct Z {};
  template <class U> struct B {
    B() {}
    ~B() {}
    template <class S> operator S();
  };
  template <template <class _T> class T> struct CT3 {
    T<Z> f();
    CT3() {}
  };
  struct C5 : CT3<B> {};

Secondary translation unit:
  struct Z {};
  template <class U> struct B {
    B() {}
    ~B() {}
    template <class S> operator S();
  };
  template <template <class _T> class T> struct CT3 {
    T<Z> f();
    CT3() {}
  };

6/4/08   Spurious remark on variable with nontrivial destructor

The front end no longer issues a "declared but not referenced" remark for
variable declarations that imply the call of a nontrivial destructor.
For example:

  int main() {
    struct S { ~S() {} } s;  // Previously a remark could be issued for
  }                          // the declaration of s.

6/3/08   Incorrect token count in reusable caches

The token_count field in reusable token caches (present only when
DEBUG code is enabled) was decremented twice when a token was removed
by remove_token_from_cache.  This did not cause any incorrect
behavior but could cause the "space used" output to incorrectly
report the space used for reusable token caches.  Now fixed.

6/3/08   GNU compatibility: Const-qualified arrays with explicit alignment

In GNU mode, it is possible to specify an explicit alignment on a typedef for
an array type.  Previously, the explicit alignment was ignored if a qualifier
(like const or volatile) was applied to the typedef type.  Now, the alignment
is retained when gnu_version >= 40000.  For example:

  typedef float VF[4] __attribute((aligned(16))); 
  struct S { 
    char c; 
    VF const f;  // Previously treated as having the usual alignment of type
  };             // float; now treated as having alignment 16 when
                 // gnu_version >= 40000.

6/3/08   Specifiers position for declarations including a linkage specifier

Version 3.9 of the front end erroneously changed the "start" position of
the "specifiers_range" field of a_decl_position_supplement (in configurations
that set EXTRA_SOURCE_POSITIONS_IN_IL to TRUE) to ignore linkage specifiers
(like extern "C").  For example:

  extern "C" int f() {};  // specifiers_range.start pointed to the "int"
                          // token instead of to the "extern" token.

This is now fixed.

6/3/08   Microsoft compatibility: typeid operations in template arguments

In Microsoft mode the front end now accepts nontype template arguments
involving typeid operations: Only the "address" of the result can be used
(either as a pointer value or as a reference binding).  For example:

  #include <typeinfo>
  template<std::type_info const&> struct X {};
  X<typeid(float)> x;  // Accepted in Microsoft mode.

Polymorphic typeid(...) constructs are not allowed in this context.

In order to support this capability two new a_constant entry variations were
introduced: an abk_typeid variant for ck_address constants (used for typeid
operations on types or expressions that are not template-dependent), and a
tpck_typeid variant for ck_template_param constants (to cover the template-
dependent cases).

6/2/08   Microsoft compatibility: private typedef used in qualified name

The Microsoft compiler allows a private typedef from a base class to be used
as the qualifier in a qualified name.  We now accept this in Microsoft mode.

  struct A {
    typedef int value_type;
  };
  class B {
  private:
    typedef A Data;
  };
  class C : public B {
    // Data is inaccessible, but allowed now in Microsoft mode
    Data::value_type vt;
  };

6/1/08   Cross-reference entry for partial instantiation of function

When cross-reference output is enabled, a reference to an instance of
a function template would result in the generation of a reference entry
("R"), and (if the function was instantiated in that translation unit) a
definition entry ("D"), but no declaration entry ("d") was generated.
A declaration entry is now generated when the partial instantiation of
the function is performed.

  template <class T> void f(T){}
  int main() {
    f(1);
  }

6/1/08   Microsoft compatibility: typename before type keyword

In Microsoft mode, the typename keyword can be followed by something other
than an identifier (see 5/6/03 entry).  The disambiguation routines did
not handle this properly in some cases, resulting in spurious errors.
Now fixed.

  template <class T> class A {
    void f();
  };
  template <class T> typename void A<T>::f() { }

5/30/08  Microsoft and GNU C++ compatibility: incorrect nesting depth on
         friend class template declaration

Microsoft and g++ accept a friend class template declaration with an
incorrect number of template parameter clauses.  This is now accepted in
Microsoft and g++ modes.  This example was actually accepted in Microsoft
mode for microsoft_version <= 1310 but the friend declaration was not
considered to name the member B (i.e., it was accepted but did not do the
right thing).

  template <typename T> struct A {
    template <typename U> class B {
      template <typename V> friend class B;
      // The following is the syntax that should be used:
      // template <typename V> template <typename W> friend class A<V>::B;
    };
  };
  void f() {
    A<int>::B<char> ab;
  }

5/29/08  Cast from pointer to integral in template argument inside template

The existing extension that allows casting from an integer constant to
a pointer and back to an integral type within a template argument has
been extended to also allow the case where the underlying constant
is based on a template parameter.  This comes up in expansions of
offsetof used within template arguments (specifically, with MSVC++ 8).

5/29/08  Address of GNU register variable taken in static initializer

The IL for a reference to a file-scope variable with a GNU register
name specification in some cases took the address of the variable
gratuitously.  Now fixed.

  typedef struct {
    unsigned int word;
  } A;
  register A vara __asm("ax");
  int x = vara.word;  // Formerly took address of vara.word, then added "*"

5/28/08  GNU compatibility: incorrect handling of line splice with
         carriage return/line feed line termination

When ACCEPT_GNU_CARRIAGE_RETURN_LINE_TERMINATOR is TRUE and when using GNU
mode, a file with carriage return followed by line feed line termination
did not work properly when a line with a line splice was followed by an
empty line.  Now fixed.  The example below resulted in a spurious error
("x undefined").

  // comment \\

  int x;
  int *y = &x;


5/27/08  Incorrect setting of assoc_operator_new_routine

In versions in which NEW_CAN_BE_FOLDED_INTO_CTOR is TRUE, the value
returned by find_default_operator_new_sym, which is used to set the
assoc_operator_new_routine field of the class type supplement, could
incorrectly be NULL.  This could occur when the operator new symbol for
a given class is an overload set containing projection symbols.  This
is now fixed when ABI_COMPATIBILITY_VERSION is >= 311.

  struct A {
    void *operator new(unsigned int,int);
  };
  struct B {
    void *operator new(unsigned int);
    void *operator new(unsigned int,float);
  };
  struct C : A,B {
    using B::operator new;
    using A::operator new;
    C(){}
  };
  int main() {
    C* p = new C;
  }

5/27/08  Internal error copying default argument during class instantiation

An internal error could occur in copy_routine_type_default_args
in versions in which CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
is TRUE (this is typically true in certain C++-generating back end
configurations).  The error occurred when a class template contained a
virtual member function that was declared with the "inline" keyword.
Now fixed.

  template <class T> struct A {
    void f(const int param=0);
    inline virtual void ttt() { f(); }
  };
  template <class T> class B {
    void g(A<T> *a);
  };
  template<class T> void B<T>::g(A<T>* a) {
    a->f();
  }
  template class B<int>;

5/22/08  dllimport and multi-translation-unit mode

When simultaneously processing multiple translation units in Microsoft mode,
the front end now prefers a non-dllimport inline function definition for
inclusion in the final IL.  For example:

  // Primary source file:
  __declspec(dllimport) __inline int g() { return 1; }
  void f1() { g(); }

  // Secondary source file:
  __declspec(dllexport) __inline int g() { return 2; }
  void f2() { g(); }

Now the definition of the secondary source file (in this example) will be the
one retained in the final IL.

5/22/08  Invalid declarations of enum types with explicit underlying type

In C++0x mode and in some Microsoft modes, an enum definition can include an
explicit underlying type.  Such a construct must include a brace-enclosed list
of enumerator constants.  However, when such a list was omitted, the front end
failed to diagnose the error, and in some configurations aborted with an 
internal error in set_src_seq_secondary_decl_fields (src_seq.c).  For example:

  enum E : int;  // Now elicits a syntax error.  Previously accepted, or
                 // an internal error was triggered.

This is now fixed: A syntax error is issued.

5/22/08  Abort on certain decltype expressions in C++0x mode

In C++0x mode, the front end could abort with an internal error (in expr.c)
when processing a decltype construct whose argument was an indirection
operator (unary "*") applied to an identifier.  For example:

  void f(int *&p) {
    decltype(*p) r = *p;  // Triggered an abort in C++0x mode.
  }

This is now fixed.

5/22/08  Conditional execution flag reset in some dynamic initializations

As a result of the changes outlined in the Changes entry of 11/8/07,
the inside_conditional_expression flag of a dynamic initialization may have
been inadvertently set to FALSE.  This occurred, for example, in cases
where a default argument is set to an expression that contains a
question mark operator, leading to cases where incorrect cleanup was
performed as in this example:

  struct S {
    ~S();
    int i;
  };
  bool flag = false;
  void test(int foo = flag ? S().i : 0);  // Previously generated an
                                          // unconditional destruction
                                          // for temporary (even in the case
                                          // where no temporary was created).
  void f() {
    test();
  }

This is now fixed.

5/21/08  Linked declarations in different scopes

Previously, when cross-reference output was enabled, the front end often
emitted a "reference" line (code "R") in that output for a declaration in one
scope that is linked to a previous declaration in another scope.  Now the "R"
lines are no longer emitted for such cases, since the later declaration isn't
really a "reference" at all.  For example:

  int x;  // Line 1: definition (code "D")
  void f() {
    extern int x;  // Line 3: declaration (code "d"); previously also
  }                // reported as a reference (code "R").

Furthermore, when a variable or function was first declared in a block-extern
declaration, and later declared in file or namespace scope, the assoc_info
pointer of the corresponding IL entry remained pointing to the symbol
associated with the local declaration.  Now, it is updated to point to the
nonlocal declaration.  For example:

  void g() {
    extern int y;  // The assoc_info pointer of y points to local symbol.
  }
  int y;  // The assoc_info pointer of y is now updated to point to the file
          // scope symbol.

5/21/08  Expanding macros in pragmas scanned as pp-tokens

Formerly, the front end did not support macro expansion in pragmas scanned
as pp-tokens.  Attempting to create such a pragma would result in an
internal error in add_pragma_kind_description.  It is now possible to
request that macros be expanded in such pragmas (by passing TRUE as the
expand_macros parameter of the add_xxx_pragma_kind_description routines).

5/19/08  Calling find_base_class_of from a back end

Previously, calling find_base_class_of from a back end led to an abort because
the function always attempted to instantiate template classes.  Now, no
instantiation is attempted if the call originates from a back end (i.e., if
the global variable in_front_end is FALSE), and the function can therefore
safely be called from a back end.

5/19/08  GNU compatibility: Attributes on member function templates

GNU attributes specified on member function templates are now applied to the
instantiations of such templates.  For example:

 struct S { template<int N> void f() __attribute__((weak)); };
 template<int N> void S::f() {}
 template void S::f<3>();  // Instance now has "is_weak" flag set to TRUE.

5/19/08  Abort in GCC mode when initializer uses designators in a
         compound literal

As a result of the changes outlined in the Changes entry of 4/5/07, a bug
was introduced that caused an assertion failure ("designator was missed by
lowering") in c_gen_be.c.  The assertion failed in GNU C emulation mode in
configurations that have the LOWER_DESIGNATED_INITIALIZERS configuration macro
set to TRUE when a compound literal with a designator is used as an
initializer.  Now fixed.  For example:

  typedef struct {
    int a[2];
  } T;

  struct S {
    T x;
  } s = {
    (T) { { [0] = 0 } }   // caused an assertion failure in c_gen_be.c
  };

5/16/08  Initialization of a static data member of a template could be
         performed multiple times in certain configurations

In IA-64 ABI configurations where TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE
is TRUE and IA64_ABI_USE_GUARD_ACQUIRE_RELEASE is FALSE, the guard code
inserted during lowering to guarantee that the initialization of a static data
member of a template occurs only once was incorrect.  As a result, the
initialization of the static data member of a template could occur multiple
times.  This is typically only a problem when template resolution is done by
instantiating everything (-tall) and then having the (specially-modified)
linker discard duplicate copies of instantiated routines.  Now fixed.
For example (with -tall):

  struct S {
    S();
  };
  template <typename T> struct X {
    static S sm;
  };
  template <typename T> S X<T>::sm; // incorrect guard code generated
  X<int> x;

5/8/08   Microsoft compatibility: dllexport/dllimport and local static
         variables in inline functions

In Microsoft mode, a local static variable now acquires the DLL interface of
its enclosing inline function when it is promoted out of that function by IL
lowering.  (In the case of dllimport, this also means that any initializer is
discarded.)  The same treatment is applied to any compiler-generated
"initialization guard variable" associated with the local static variable.
For example:

  struct __declspec(dllexport) X {
    X();
  };
  __declspec(dllexport) inline void f() {
    static X x;  // x and its associated "guard variable" are promoted to
  }              // file scope, and now both become dllexport variables.

5/7/08   GNU compatibility: Subtracting label addresses (IL CHANGE)

In GNU modes, the difference between two label addresses (which are themselves
a GNU extension) is now sometimes folded into a new constant entry of kind
ck_label_difference.  The integer value of such a constant is not known by the
front end, but the associated expressions can now appear in certain additional
contexts (such as C mode initializers for local static variable declarations).
For example:

  long f() {
    static long d = &&L2 - &&L1;  // Now accepted in GNU C mode.
  L1: L2:
    return d;
  }

5/7/08   Hidden names are no longer included in IL when lowering is performed

IL lowering does not update the hidden-name information generated by the front
end.  As a consequence, configurations that have both RECORD_HIDDEN_NAMES_IN_IL
and DO_IL_LOWERING set to TRUE can generate inconsistent IL if lowering removes
an IL entry that appears on the hidden-name list.  This is not a recommended
configuration (ALLOW_HIDDEN_NAMES_IN_IL_WITH_IL_LOWERING must also be set to
TRUE to acknowledge that the configuration is indeed desired).  A change has
been made to discard the hidden-name list during lowering (the hidden names
will still be emitted in the IL if lowering is disabled at run-time with the
--no_il_lowering command line option).  Here is an example that previously
generated an IL inconsistency (with --microsoft):

  struct X {
    __declspec(property(put=Set)) int i;
    int Set(int i);
  };
  struct Y {
    __declspec(property(put=Set)) int i;
    int Set(int i);
  };

5/7/08   Abort with FULLY_RESOLVED_MACRO_POSITIONS and complex stringized
         arguments

In a configuration with FULLY_RESOLVED_MACRO_POSITIONS, a stringized
multi-token macro argument resulted in incorrect text map entries that could
cause an assertion failure in get_source_pos_from_macro_text_map.  This is
now fixed.  For example:

  #define M(x) #x
  char *p = M(a b c);   /* Could cause an abort. */

5/2/08   Microsoft compatibility: typeid of incomplete class types

In Microsoft mode, the front end now accepts (with a warning) the typeid
operator applied to an incomplete class type or to an expression with an
incomplete class type.  The class is treated as a nonpolymorphic class in
such cases: The result of the operation is unaffected by the dynamic type of
the complete object passed to typeid.  For example:

  #include <stdio.h>
  #include <typeinfo>
  struct B;
  void f(B *p) {
    printf("%s\n", typeid(*p).name()); // Accepted with a warning in Microsoft
  }                                    // mode.
  struct B { virtual ~B() {} };
  struct D: B {} d;
  int main() { f(&d); }  // Prints the typeid name of B; not D.

5/1/08   Extended position information for friend functions in class templates

The IL entries created for friend function declarations appearing in class
templates failed to include extended source position information when the
configuration macro EXTRA_SOURCE_POSITIONS_IN_IL is TRUE.  This is now fixed.

4/29/08  Microsoft compatibility: dllexport and inline functions

In Microsoft mode, the front end now marks inline functions declared with
__declspec(dllexport) as needing an out-of-line copy (need_out_of_line_copy
flag of a_routine entry).  An out-of-line copy was already generated when
INSTANTIATE_EXTERN_INLINE is TRUE, but now one is also created in other
configurations.  For example:

  __declspec(dllexport) inline void f() {}  // Function is now always marked
                                            // as needing an out-of-line copy.

4/29/08  GNU C compatibility: Redeclarations and transparent unions

In GNU C mode, a function can be redeclared with a parameter type that is a
transparent union type with a field type that matches the corresponding
parameter type in the original declaration (see Changes entry of 6/20/02).
Previously, the composite type resulting from such a redeclaration was always
the transparent union.  Now, if the redeclaration is not a definition, the
original type is retained.  For example:

  union __attribute((transparent_union)) TU { int i; int *p; };
  void f(int i);            // First declaration.
  void f(union TU tu);      // Redeclaration, type "int" retained.
  void g(int x) { f(&x); }  // Warning: int*->int conversion.
  void f(union TU tu) {}    // Definition, type "tu" retained.
  void h(int x) { f(&x); }  // No warning, no conversion.

This brings the front end behavior closer to that of GCC's, but GCC appears to
retain the original type even when the redeclaration is a definition.  We do
not implement that GCC behavior to avoid excessive disruption of internal
structure of the front end.

4/28/08  Spurious C++0x mode error on friend function definition in template

In strict C++0x mode, the front end issued a spurious error on an (inline)
friend function definition appearing in a class template.  (This is a
regression introduced in version 3.10 of the front end.)  For example:

  template<typename T> struct S {
    friend void f() {}  // Previously a spurious error in strict C++0x mode
  };                    // ("function cannot be declared inline after its
                        // definition").

This is now fixed.

4/25/08  Emit an entire diagnostic in a single system call

Previously, diagnostic messages were written piece by piece to the
error output file.  In cases where multiple compilations are being performed
in parallel and the same unbuffered output file is used for each
(e.g., stderr), diagnostics from these compilations can appear intermixed.
A change has been made to collect all pieces of a diagnostic in a local buffer
and emit the entire diagnostic with a single system call.

4/23/08  Microsoft __unaligned can be dropped in reinterpret_cast

In Microsoft mode, the __unaligned qualifier at the top level
in a pointer can now be dropped in a reinterpret_cast or, at any
level other than the first, in a static_cast or reinterpret_cast.

int main() {
  __unaligned unsigned char *p = 0;
  reinterpret_cast<unsigned char *>(p);  // Now accepted
  __unaligned unsigned char **q = 0;
  static_cast<unsigned char**>(q);       // Now accepted
}

4/23/08  Overload resolution conversion cost for float operand to builtin

In accordance with Core Issue 425, the type "float" is now considered a
promoted arithmetic type for purposes of matching builtin operators in
overload resolution.  A case like the following is no longer ambiguous:

  struct A {
    A(float);
  };
  A operator *(const A&, float);
  enum E { e1 };
  int main() {
    E e = e1;
    e * 12.0f;  // No longer considered ambiguous
  }

4/17/08  GNU compatibility: #pragma GCC visibility

In GNU C and C++ modes with gnu_version >= 40200, the front end now supports
the "#pragma GCC visibility" constructs when GNU_VISIBILITY_ATTRIBUTE_ALLOWED
is TRUE.  For example:

  #pragma GCC visibility push(hidden)
  void f1() {}   // Has "hidden" visibility.
  #pragma GCC visibility pop
  void f2() {}   // Has unspecified visibility.

In addition, the visibility attribute for namespaces (see Changes entry of
9/15/06) now pushes an entry on the visibility stack, and an entry is popped
at the end of that namespace scope.  This matches the behavior of the GNU C++
compiler, but can lead to surprises:

  namespace N __attribute((visibility(internal))) {
  #pragma GCC visibility push(hidden)
  }  // Implicit #pragma GCC visibility pop.
  void f() {}  // Has "internal" visibility.

A warning is issued in cases like this.

4/15/08  Representation of switch statements (IL CHANGE)

The representation of switch statements in the IL has been changed to more
closely match their specification in C and C++.

Previously, a switch statement was represented in a way that corresponds to
the most common use pattern: A list of "switch clauses" with (by default) an
implicit "break" at the end.  Each clause included information about the case
values (possibly "default") associated with that clause.  Uses that did not
match the common case (like falling through to the next case, or having a
case appear in a nested block) were handled using generated gotos and labels.
A configuration macro RECORD_SWITCH_CASE_ENTRIES (see entry of 10/3/06)
enabled an IL extension recording more precise information about individual
cases.

In the new representation, "case" and "default" labels are represented using
a new stmk_switch_case statement kind.  Each stmk_switch_case points to an
entry of type a_switch_case_entry, which describes that case (the case value
or whether it's a default case, position information, etc.).  The stmk_switch
statement associated with such a case points to the list of all cases (via an
entry of type a_switch_stmt_descr).  All "break" statements out of a switch
are explicitly represented using stmk_goto statements pointing to a label
that has the switch_break_label flag set to TRUE.

The configuration macro RECORD_SWITCH_CASE_ENTRIES is no longer used in the
front end.  The macro EXTRA_SOURCE_POSITIONS_IN_IL adds more position
information to a_switch_case_entry (e.g., the position of the colon token).
When GNU_EXTENSIONS_ALLOWED is TRUE, a_switch_case_entry can record a GNU
case range (i.e., a construct like "case 1 ... 10:"); there is no longer a
configuration option to expand such a range into a list of individual case
values.

4/13/08  Unicode in source code

The front end now supports Unicode source files in the UTF-8 and
UTF-16 encodings.  This is enabled by UNICODE_SOURCE_SUPPORTED.
The type of source code in a file can be specified by a
byte order mark (BOM) at the start of the file (see Changes entry
of 2/17/06), or by way of the new --unicode_source_kind command-line
option.  There is also a macro DEFAULT_UNICODE_SOURCE_KIND that
can be used to establish the default for files without a byte
order mark.  

UTF-16 source code can be in the little-endian or big-endian
format, and is converted immediately to UTF-8 on input.  Therefore,
"column numbers" in UTF-16 source are based on the UTF-8 version,
which works fine for caret positions in diagnostics but may be a
bit weird for other uses.

When UNICODE_SOURCE_SUPPORTED is set to TRUE, identifiers and
file name strings in the front end will be represented in UTF-8.
For file names, there is the expectation that the standard system
fopen will be able to deal with UTF-8 file names.  If that isn't
the case, some host-specific code may have to be added to fopen_interface.
(For Windows-hosted configurations, specific code is provided which
calls the _wfopen function.)

If UTF-8 identifier name strings are somehow undesirable (e.g.,
a back end or linker can't handle them), the macro
IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS can be set to FALSE,
in which case characters in identifiers outside of the basic
character set will be rendered in the \uXXXX or \UXXXXXXXX
form already used for UCNs.  Note, however, that the encoded
form will come out in diagnostic messages that name an entity
in the source.

If DEFAULT_UNICODE_SOURCE_KIND is usk_none, source files without
a byte order mark are assumed to be encoded in ISO-8859-1 (otherwise
known as Latin-1), which matches the first 256 code points in
Unicode.  Such a mode (which is the default for Windows-hosted
versions) is a hybrid mode in which some files are Unicode and
some are not, and in which therefore a character like a u-umlaut
would be encoded differently depending on the kind of source file
it appears in.  Such characters in ISO-8859-1 files will be
converted to UTF-8 (or the identifier encoding \uXXXX) when they
appear in identifiers and file names.  In hybrid configurations,
characters in textual preprocessing output will always be converted
to UTF-8 if DEFAULT_UNICODE_SOURCE_KIND is not usk_none, and to
ISO-8859-1 otherwise.  Characters that cannot be represented in
ISO-8859-1 in the latter case are converted to "?".

4/13/08  Non-basic characters now allowed in identifiers

Characters outside of the basic character set are now allowed in
identifiers.  This includes things like accented European characters
in character sets like Latin-1, and true multibyte character
codes in character encodings like Shift-JIS.  For either of
those cases, an appropriate value of LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED
must be set if the default locale of "" does not produce the proper
character set.  If IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS is
TRUE, the identifier name strings created by the front end will
include multibyte characters; if it is FALSE, multibyte characters
will be encoded in those strings as \mXXXX or \MXXXXXXXX, where XXXX
is the hexadecimal value of the multibyte character (this is similar
to the \uXXXX encoding already used for UCN characters; indeed, if
UNICODE_SOURCE_SUPPORTED is also TRUE, the UCN form is used for
both).  Note that the encoded form, if selected, comes out in diagnostic
messages that name an entity in the source.

4/13/08  Caret position on diagnostic for source line with multibyte characters

The caret to indicate the source position in a diagnostic is now correct
in the presence of multibyte characters in the displayed source line.

4/9/08   GNU compatibility: constructor/destructor attribute arguments

In GNU C and C++ modes, the front end now accepts an optional "priority"
argument for the attributes "constructor" and "destructor".  This extension
is only supported in configurations with GNU_INIT_PRIORITY_ATTRIBUTE_ALLOWED
set to TRUE.  The priority argument (a value in the range 101 ... 65535)
affects the order in which startup and termination functions are run
(smaller values indicate earlier startup and later termination).
For example:

  __attribute((constructor(300))) void f1() {}
  __attribute((constructor(200))) void f2() {}
    // f1 and f2 will be called at program startup, and the latter will be
    // called before the former.

Note that IL lowering does not treat a function marked with the "constructor"
or "destructor" attribute specially: The task of ensuring that the function
is called at the appropriate time is the responsibility of the back end.

4/8/08   GNU versions for delayed nested class definitions in class scopes

The Changes entry of 1/26/06 describes how the front end accepts delayed
nested class definitions in GNU C++ mode when gnu_version < 30400.  However,
later versions of the GNU C++ compiler also accept such constructs.  The front
end has therefore been updated to allow delayed nested class definitions in
GNU C++ mode for all values of gnu_version.  Furthermore, when gnu_version is
less than 30300, it is not required that the delayed definition appear in a
parent class of the class being defined.  For example:

  struct A {
    struct B {
      struct C1;
      struct C2;
    };
    struct B::C1 {};  // Now accepted for all values of gnu_version.
  };
  struct X {
    struct A::B::C2 {};  // Accepted in GNU mode when gnu_version < 30300.
  };

4/8/08   Invalid access to variant field of a_routine on redeclaration of
         a function that drops an exception specification

When a function with an exception specification was redeclared without that
exception specification, the front end read an invalid variant (union) field
of the associated a_routine entry.

  void f() throw();
  void f();

This is now fixed.  (This was unlikely to have any effect on the front end
behavior, but it was reported by some analysis tools.)
[Patch sent out 4/17/08.]

4/8/08   GNU C mode abort on invalid initialization with compound literal

In GNU C mode, the front end sometimes silently created invalid IL for an
aggregate initialization containing a compound literal.  This in turn triggered
an assertion failure ("constant, but no field") in dump_initializer_part
(c_gen_be.c).  The problematic cases involve a field of an empty struct type.
For example:

  typedef struct { } R;
  typedef struct { R r; } S;  // Field r of empty struct type R.
  S s = { (S){{}} };          // Previously triggered an abort in the
                              // C-generating back end.

Such cases are normally errors (because the type of the compound literal does
not match the type of the field it corresponds to), but GCC treats the invalid
initializer as an "excess initializer" and discards it with a warning.  We now
emulate that behavior (the resulting IL is now valid, and no abort is triggered
in the C-generating back end).  [Patch sent out 4/17/08.]

4/7/08   GNU compatibility: Field alignment of complex types

When TARG_DUAL_ALIGNMENTS_FOR_BUILTIN_TYPES is set to TRUE, a built-in type may
have one "normal" or "intrinsic" alignment used when laying out complete object
of that type, and another "field" alignment used when laying out a field of
that same type.  (See Changes entry of 10/7/02.)
Previously, the front end failed to consider the "field" alignment for fields
of complex (or imaginary) type.  For example:

  struct S {
    char i;
    _Complex double z;  // Double may have "intrinsic" alignment 8, and
  };                    // "field" alignment 4.

In a configuration where "double" has an "intrinsic" alignment of 8, and a
"field" alignment of 4, S previously had size 24.  Now it will have size 20,
which matches the behavior of GCC.  [Patch sent out 4/17/08.]

4/4/08   Spurious constructor template parsing errors

The front end previously did not accept constructor template declarations
involving a parenthesized constructor declarator.  For example:

  struct S {
    template<class T> (S)(T);  // Previously a spurious error.
  };

This is now fixed.  This fix also enables the front end to accept an explicit
Microsoft-mode calling convention on constructor template declarations.
For example:

  struct M {
    template<class T> __thiscall S(T);  // Now accepted in Microsoft mode.
  };

[Patch sent out 4/17/08.]

3/31/08  Uninitialized field in a_destructible_entity_descr in configurations
         that use lowering but set GENERATE_EH_TABLES to FALSE

In configurations that use lowering but generate their own exception
handling tables (i.e., GENERATE_EH_TABLES is FALSE), the
cleanup_state_to_set_when_starting_destruction field of
a_destructible_entity_descr was not properly initialized and could cause
undefined behavior.  This is now fixed.  [Patch sent out 4/17/08.]

3/28/08  Abort in find_member_function_template

An abort could occur in find_member_function_template if a class template
contained an unusable conversion function (e.g., one that converts to a
a base class) and an overload set with at least one function template.
This has been fixed.

  class B {};
  template <class T> struct A : public B {
    template <class T2> void f(T2){}
    template <class T2> void f(T2*){}
    operator B();
  };
  A<int> ai;

[Patch sent out 4/17/08.]

3/25/08  C++-generating back end: qualified names in generated template
         instances

In configurations where class and/or nonclass template instantiations are
included in source sequence lists and RECORD_FORM_OF_NAME_REFERENCE is
TRUE, the generated explicit instantiations could contain incorrect
qualified names when the name in the template is qualified by a template
parameter and the corresponding template argument is itself a qualified
name.  This is now fixed.  For example:

  struct X {
    struct S {
      static int i;
    };
  };
  template <typename T> void f() {
    int i = T::i;    // Formerly generated as "S::i", now "X::S::i"
  }
  void g() {
    f<X::S>();
  }

[Patch sent out 4/17/08.]

3/25/08  Microsoft compatibility: __interface first declared as struct

In Microsoft mode, a type can now be first declared as a struct, and later
defined with the keyword "__interface".  For example:

  struct Inter;
  __interface Inter {};  // Now accepted in Microsoft mode.

Our behavior differs slightly from that of Microsoft's compilers in that the
latter require that in cases like these the definition specify IUnknown as a
base class.  [Patch sent out 4/17/08.]

3/25/08  Internal error on null character at end of string in Microsoft mode

The front end aborted with an assertion failure
("conv_string_literal: length miscalculated") on encountering a
null (zero) character just before the closing quote of a string literal
in Microsoft mode.  Now fixed.

  char x[] = "abc0";  // Where "0" represents a null character

[Patch sent out 4/17/08.]

3/24/08  Abort on use of GNU __sync_... functions in templates

In configurations with GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED set to TRUE, the
front end accepts a variety of built-in functions for atomic memory access
(see the Changes entry of 7/31/07).  However, when calls to such functions
appeared in templates, the front end aborted with an internal error in expr.c
(function "adjust_gnu_sync_call").  A spurious error message was often also
issued.  This is now fixed.  [Patch sent out 4/17/08.]

3/24/08  Internal error when additional arguments follow an argument
         needing a VLA adjustment in GCC and C99 modes

As a result of the changes described in the Changes entry of 5/29/07,
the front end aborts with an internal error in dump_expr in cases where
one or more arguments follow an argument whose type is adjusted to
match the type of the corresponding parameter in a block-extern function
prototype (see the Changes entry of 5/29/07 for more details on this case).
This error occurs only when argument or parameter lists contain variable length
array types (VLAs) and the front end is configured to perform IL lowering.
Here is an example that previously aborted and is now fixed:

  int l = 1, m = 2;
  void f(int a[l][m], int i);
  void g() {
    int a[l][m];
    void f(int a[*][*], int);
    f(a, 10);                 // caused an internal error in dump_expr
  }

[Patch sent out 4/17/08.]

3/21/08  Comma-separated declarations

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, the front end now records whether
a declaration is separated from a prior declaration using a comma only.
For example, in:

  int p, *q, (*r)();

the declarations of q and r now have a flag is_decl_after_first_in_comma_list
set to TRUE (in the source correspondence entry if it is the primary
declaration, or in a secondary source sequence entry otherwise).  The C++-
generating back end uses this flag to more accurately reconstruct its input
(the example above is no longer reconstructed as three declarations separated
by semicolons).

3/18/08  C-mode assertion failure in change_c_type_correspondence

When simultaneously compiling multiple translation units in C mode, the front
end sometimes aborted with an assertion failure in change_c_type_correspondence
(trans_corresp.c).  The exact circumstances for this failure are complex, and
we know of no small example to demonstrate it.  The underlying problem,
however, has been fixed.  [Patch sent out 4/17/08.]

3/18/08  Changes in Microsoft __assume expression handling

Previously, lowering of an expression that contained temporaries that are
generated both within an __assume expression as well as outside of it caused an
assertion failure in modify_init_entity_node in lower_init.c.  Expressions
within an __assume statement are now scanned with the assumption that they will
never be evaluated (like expressions within a sizeof).  As a consequence,
symbols used within an __assume expression will no longer be marked as
referenced, potentially causing some diagnostic differences.  The front end has
always silently discarded complex __assume expressions (i.e., those that
produce side effects) as a way of avoiding potential problems with the
destruction of temporaries; a new warning has been added to inform the user
when the expression is being discarded.  For example:

  struct A {
    ~A();
  };
  int f(A);
  A g() {
    A a = (__assume(f(A())), A());  // caused assertion failure in lower_init.c
                                    // now generates a new warning
    return A();
  }

[Patch sent out 4/17/08.]

3/18/08  Extended position information for nonstandard friend declarations

In many C++ modes, nonstandard forms of friend class declarations are accepted.
For example:

  struct S {};
  class C { friend S; };  // Nonstandard equivalent of "friend class S;"

However, the source sequence entry associated with such declarations previously
failed to include extended source position information when the configuration
macro EXTRA_SOURCE_POSITIONS_IN_IL is TRUE.  This is now fixed.
[Patch sent out 4/17/08.]

3/18/08  Invalid tokens in unrecognized pragmas

When the front end is generating preprocessed output in configurations where
INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL is TRUE an error was issued on an
invalid token in an unrecognized pragma.  Now fixed.

  #pragma some_unknown_pragma @

[Patch sent out 4/17/08.]

3/17/08  Microsoft bugs mode cast to cv-qualified class type drops qualifiers

MSVC++, through 8.0 at least, seems to discard the cv-qualifiers on a
cast to a cv-qualified class type.  We now emulate that in Microsoft
bugs mode.

  struct A {
    A() {}
    A(const A&) {}
    ~A() {}
  };
  void f(A&) {}
  int main() {
    A a;
    const A ca;
    f((const A)a);  // Accepted by MSVC++, and now by EDG
    f(ca);          // Gets error from MSVC++, and still from EDG
  }

[Patch sent out 4/17/08.]

3/13/08  Build error in cp_gen_be.c when MICROSOFT_EXTENSIONS_ALLOWED &&
         !NEAR_AND_FAR_ALLOWED

In configurations with MICROSOFT_EXTENSIONS_ALLOWED set to TRUE and
NEAR_AND_FAR_ALLOWED set to FALSE, the C++-generating back end (cp_gen_be.c)
did not build correctly.  This is now fixed.  [Patch sent out 4/17/08.]

3/5/08   Parent entities (IL CHANGE)

Previously, type a_source_correspondence contained a field "parent" of type
a_parent_class_or_namespace to describe the parent class or namespace of an
IL entry.  This "parent" field is now replaced by a "parent_scope" field,
which points to an entry of type a_scope.  This change has the following
consequences:

  - Many more entities now describe their parent entity.  For example,
    entries for local variables have their parent_scope set to the
    sck_function or sck_block scope they are associated with.
  - Struct types always have an associated "class type supplement",
    even in C mode or when generated by IL lowering.
  - Struct types with a body (a definition) always have associated scopes,
    even in C mode or when generated by IL lowering.

The new "parent_scope" field is currently set to null if setting it to the
actual parent scope entry would violate the constraint that pointers in file
scope memory cannot point to entries in function scope memory.  (E.g., a local
class type is stored in file scope memory, and its "parent_scope" can
therefore not point to a sck_block or sck_function scope entry.)  The macro
get_parent_scope_of can be used to obtain the parent scope even when the
parent_scope field itself is null.

A related change was made to the representation of scopes: Type a_scope now
includes a field "parent", which points to the enclosing scope (or null, in
case of the file scope).

A number of macros are provided to access parent classes and namespaces, and
to test for their existence.  (See il.h: is_namespace_member, parent_class_of,
etc.)  These are useful to help transitioning existing code to the new
representation.

3/4/08   GNU compatibility: "cleanup" attribute on an unused variable

The presence of the GNU "cleanup" attribute was not considered in
determining whether a non-static variable was used or not.  Variables with
this attribute are now always considered to be referenced, used, and (in
configurations in which MAINTAIN_NEEDED_FLAGS is TRUE) needed by virtue of
the implicit call to the cleanup routine when the variable goes out of
scope.  For example:

  void cl (void *a);
  void f() {
    int a __attribute__ ((cleanup (cl)));  /* No longer considered unused. */
  }

[Patch sent out 4/17/08.]

3/4/08   No warning on non-POD class passed to ellipsis in unevaluated context

A warning is no longer issued when an object of non-POD class type is passed
to an ellipsis parameter, if the call occurs in an unevaluated context.
This is desirable because of the proliferation of use of this sort of
case in template metaprogramming.

  struct A {
    A();
    A(const A&);
    ~A();
  };
  template <class T> struct B {
    static char f(int);
    static int f(...);
    static const int i = sizeof(f(T()));  // Warning no longer issued.
  };
  int main() {
    B<A> ba;
  }

[Patch sent out 4/17/08.]

3/3/08   Microsoft compatibility: Interface-like types

In Microsoft mode, the front end already recognizes the Microsoft struct types
IUnknown and IDispatch to be "interface-like" in that __interface types can
derive from them.  This has now been extended to certain other types.  A class
type is now also considered "interface-like" if it directly or indirectly
derives from IUnknown or IDispatch, and
  - it does not contain any (static or nonstatic) data member, constructor,
    destructor, friend declaration, typedef declaration, and
  - every one of its base classes is a public nonvirtual interface or
    interface-like class.
For example:

  struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {};
  struct Interface_like: IUnknown {};
  __interface X: Interface_like {};  // Now accepted in Microsoft mode.

A new flag "is_interface_like" has been added to a_type entries: It is set to
TRUE for interface-like class types.

2/25/08  Access checking for related class casts in templates

Some cases like the following caused spurious accessibility errors
when prototype instantiations of templates are done (e.g., strict
mode or g++ mode at or after 3.4).  Access checking is supposed to be
suppressed in such contexts, because full information is not
always available, but it was still done for base class accessibility
(which is handled separately from member accessibility).  Now,
that part of access checking is also suppressed.

  class A {};
  class D : private A {
    template <class T> friend class B;
  };
  template <class T>
  struct B {
    void update() {
      A* a;
      static_cast<D*>(a);  // Formerly got spurious error
    }
  };
  void foo() {
    B<int> x;
    x.update();
  }

[Patch sent out 4/17/08.]

2/24/08  Incorrect IL for constant, with name reference information

In configurations with RECORD_FORM_OF_NAME_REFERENCE set to TRUE
(e.g., C++-generating back end configurations), in some cases
a use of an enumerator constant resulted in IL that had the
same name reference entry on more than one list.  This is
invalid, and could cause aborts in, among others, versions
that write an IL file ("ptr_remap_function: address not in any 
mem block").  Now fixed.

  struct S {
    enum E { N };
    int array[N+1];
  };
  struct S1 {
    void get(int x = S::N);
  };
  template <typename T, T Number> struct S2 { };
  struct S3 : public S2<S::E, S::N> { };

[Patch sent out 4/17/08.]

2/22/08  Microsoft compatibility: Default va_list type

The default type for va_list in Microsoft mode -- in effect when the global
variable pass_stdarg_references_to_generated_code is TRUE -- is now char*
(instead of void*).

2/22/08  Abort with #pragma on nonstandard Microsoft/Sun mode declaration

In Microsoft and Sun modes, a class declaration (not definition) with the same
name as a preceding class template declaration is ignored (with a warning).
However, if that ignored declaration had a #pragma directive applied to it,
the front end could abort ("IL entry write-read difference") in configurations
that have IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE.  For example (assuming
INCLUDE_EDG_TEST_PRAGMAS is TRUE):

  template<typename T> struct S;
  #pragma test_next_decl
  struct S;  // Previously could trigger an IL write-read failure.

This is now fixed.  [Patch sent out 4/17/08.]

2/22/08  Diagnostic for invalid function qualifiers

The diagnostic indicating that a type qualifier is not allowed on certain
types of functions (e.g., nonmember functions or static member functions)
now explicitly mentions the class of functions affected.  For example:

  struct S {
    static void f() const;   // Error.  The diagnostic now mentions "static
  };                         // member function" explicitly.

2/22/08  GNU switch case range values sometimes lost

In configurations with RECORD_SWITCH_CASE_ENTRIES set to FALSE, a GNU switch
case range immediately followed by another switch case (single value or range)
resulted in only the first value of the range being retained.  For example:

  void f(int x) {
    switch (x) {
      case 1 ... 3:  /* Previously made equivalent to "case 1:". */
      case 7:
        break;
    }
  }

This is now fixed.  [Patch sent out 4/17/08.]

2/22/08  GNU C compatibility: Type of block-extern variable declarations

The Changes entry of 4/21/03 describes how in GNU C mode the type of a block-
extern variable declaration is the composite type of the locally declared type
and the previously obtained type.  Later, however, that behavior was
erroneously made conditional on gnu_version < 30400.  The latter change is now
undone.  For example:

  extern char x[10];
  void f(void) {
    extern char x[];
    char y[sizeof x];  // Now accepted again in all GNU C modes.
  }

[Patch sent out 4/17/08.]

2/22/08  Wrong end positions for some constructs followed by #if

In configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE, the front end
records the end positions of most constructs.  In some cases, if a construct
was followed by a #if preprocessing directive, the end position of the
construct was mistakenly set to that of the #if directive.  For example:

  void f() {
    for (;;) {}  // End position of stmk_for entry was set to the position of
  #if 1          // the digit "1" instead of to the position of the "}".
  #endif
  }

This is now fixed.  [Patch sent out 4/17/08.]

2/20/08  Optimization of virtual function calls with default arguments

In configurations in which OPTIMIZE_VIRTUAL_FUNCTION_CALLS is TRUE, a
virtual call that was optimized to a direct call to an overriding function
failed to use the default arguments from the statically-chosen function.
This is now fixed.  For example:

  struct B {
    virtual void f(int=0);
  };
  struct D: B {
    void f(int);
  };
  D d;
  void g() {
    ((B*)&d)->f();   // Previously caused "too few arguments" error
  }

2/19/08  Microsoft compatibility: Explicit instantiation after explicit
         specialization

In Microsoft mode with microsoft_version == 1200, an explicit instantiation of
a class template that was previously explicitly specialized cancels the
explicit specialization if that specialization did not provide a definition.
For example:

  template<class T> struct S {};
  template<> struct S<int>;  // Explicit specialization without a definition.
  template struct S<int>;    // Explicit instantiation cancels the explicit
                             // specialization when microsoft_version == 1200.
  S<int> s;                  // Okay when microsoft_version == 1200.

Cases that appear to be broken by the change in treatment of old-style
specializations in Microsoft mode as described in the Changes entry of 8/2/07
are restored by this change.

2/19/08  GNU compatibility: nonnull attribute with multiple parameters

A nonnull attribute specifying more than one parameter number was incorrectly
treated as if no parameter numbers were given, i.e., as if all parameters
were to be checked for null arguments.  This is now fixed.  For example,

  void f(void *p, void *q, void *r) __attribute((nonnull(1, 3)));
  void g() {
    int a,b;
    f(&a, 0, &b);  // Incorrectly warned about parameter 2
  }

[Patch sent out 4/17/08.]

2/13/08  Microsoft mode abort with property fields and IA-64 ABI

In Microsoft mode with IA-64 ABI configurations, the front end sometimes
aborted ("num_array_elements: array with unspecified bound") when dealing
with certain class types containing both a property field and a real field
with empty class type.  For example:

  struct E {};
  struct M {
    __declspec(property(get = f)) int x[];  // Previous triggered an internal
    int f(int);                             // error.
    E e;                                    // Field with empty class type.
  };

This is now fixed.  [Patch sent out 4/17/08.]

2/13/08  Sun and Microsoft C++ compatibility: Nonstandard friend class template

In Sun and Microsoft C++ the front end accepts a friend class template without
a leading template parameter clause if the referenced template is visible (see
the Changes entries of 9/3/03 and 6/6/06).  However, this extension previously
excluded the case where the nominated template is currently being defined. That
unintended exception has now been removed.  For example:

  template<typename T> class C {
    static int i;
    friend class C;  // Now treated as "template<typename> friend class C;".
  public:
    template<typename T2> static void f() {
      C<T2>::i = 0;  // Now valid even when T2 != T.
    }
  };
  int main() {
    C<int>::f<char>();  // Now accepted (in Sun and Microsoft C++ modes).
  }

2/12/08  Point of destruction of runtime exception object adjusted

The point at which the exception object maintained by the runtime is
destroyed in the case where a catch clause throws a new exception
(not a rethrow of the current exception) was not correct according
to the C++ standard.  Formerly, it was destroyed sometime before the
catch clause parameter, and it should be destroyed immediately after
that parameter.  We have changed the front end and runtime to correct
this.  This change only affects configurations that use IL
lowering and have GENERATE_EH_TABLES set to TRUE.  In those
configurations, there is an ABI CHANGE: an additional region table
entry is put out to indicate the point at which the exception
object should be destroyed, and that region table entry requests
a call of a new runtime routine __destroy_exception_object.
This new routine is also called instead of __free_thrown_object
in the case that the catch clause is left via goto or return.
__free_thrown_object remains in the runtime for backward
compatibility, and the code used to indicate a try block in
the EH stack has been renumbered so that previously-compiled
code will continue to function (and behave as it did previously)
even with the new runtime.  See the runtime Changes file for more
information.

2/8/08   Abort on use of reference-to-function conversion function

The front end aborted ("take_address_of_lvalue: not an lvalue") on
processing a cast to reference where the source operand is converted
to the desired type by way of a conversion function that returns a
reference to a function type.  Now fixed.

  typedef int (&RF)(int);
  struct X {
    int x;
    operator RF();
  };
  void test(X& obj) {
    ((RF)obj)(0);
  }

[Patch sent out 4/17/08.]

2/7/08   Spurious VLA diagnostic in GNU C++ mode

In GNU C++ modes with gnu_version >= 30400, the front end sometimes issued
spurious errors relating to variable-length arrays when declaring a local
array with a template-dependent bound.  This is now fixed.  For example:

  template<typename T> void f() {
    static T x[sizeof(T)];  // Spurious error when compiled with:
  }                         //   -tused --gnu_version=30400
  template void f<int>();

As a result of this change, in configurations in which prototype
instantiations are included in the IL, the expression for a dependent
bound will be represented by the variant.array.variant.element_count_constant
field of the type entry.  If the expression associated with that constant
refers to a local variable, the expression will be removed from the constant
to a local expr_ref node (see the 1/29/08 and 4/28/06 Changes entries).  The
affected expression pointers are the expr, templ_sizeof.expr, and (for
configurations in which RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE)
constant->expr fields of the constant's variant.template_param.variant union,
and the use of the local expr_ref node is indicated by the
variant.array.constant_bound_expr_in_local_expr_node_ref flag.
[Patch sent out 4/17/08.]

2/7/08   Constant expressions in local array bounds

In configurations in which RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, the
variant.array.bound_constant in the a_type entry for an array type used in
a function scope preserved the associated expression, as expected; however,
the expressions associated with any constants appearing in that top-level
expression were lost.  This is now fixed.  For example, the "sizeof"
operation in the following case is now represented by an enk_runtime_sizeof
node in the expression tree for the bound constant:

  void f() {
    char *data = new char[sizeof(int)+3];
  }

[Patch sent out 4/17/08.]

2/6/08   Microsoft compatibility: concatenation with __VA_ARGS__

The Microsoft compiler is nonstandard in its handling of the __VA_ARGS__
macro parameter in that it always expands the corresponding macro argument,
even when it is the operand of the "##" concatenation operator.  The front
end has been changed to emulate this behavior in --microsoft mode.  For
example:

  #define M(a, ...) a ## __VA_ARGS__
  #define TWO 2
  M(1,TWO)       // Expands to 12, not 1TWO, in --microsoft mode

[Patch sent out 4/17/08.]

2/6/08   Microsoft compatibility: template friend declarations apply to
         explicit specializations

A template friend declaration that refers to a member of a class template
should not apply to a similar member of an explicitly specialized class,
but the Microsoft compiler does apply such friendship.  We now emulate
this behavior in Microsoft mode.

  template<class T> struct A { void f(); };
  class C {
    int i;
    template<class T> friend void A<T>::f();
  };
  template<> struct A<char> { void f(); };
  void A<char>::f() {
    C c;
    c.i = 0; // allowed in Microsoft mode
  }

1/31/08  Builtin va_arg returns lvalue in Microsoft and Sun modes

The va_arg macro of the <stdarg.h> header, when treated as a builtin
because DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE is TRUE,
has to date been treated as an rvalue.  It turns out MSVC++ and the
Sun C++ compiler treat it as an lvalue, so now we do also in those modes.
The global variable va_arg_returns_lvalue controls this, though
there is at present no associated command-line option nor
default-value macro.

  #include <stdarg.h>
  void dimsum(double num,...) {
    extern void mytest( double & );
    va_list argptr;
    va_start(argptr,num);
    for(; num> 0; num--) {
      mytest( va_arg(argptr, double));  // Okay in Microsoft and Sun modes
    }
    va_end(argptr);
  }

1/30/08  traverse_statement with upc_notify, upc_wait, and upc_barrier

Traversing a UPC synchronization statement (upc_notify, upc_wait, and
upc_barrier) failed to process the statement's optional expression argument.
Now fixed.  For example:

  void f() {
    int i=1, j=2;
    upc_barrier i+j;    // "i+j" now included by traverse_statement
  }

[Patch sent out 4/17/08.]

1/29/08  Memory region issues for array bounds with
         RECORD_CONSTANT_EXPRESSIONS_IN_IL

In configurations in which RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, an
array bound in which the expression is constant but refers to a local
variable could cause an abort resulting from a reference to function-scope
memory from the file scope.  This is now fixed.  For example:

  void f() {
    int i;
    int a[1||i];    // Previously could cause an abort
  }

This problem is a variation of the one described in the 7/26/05 Changes
entry, and it updates the resolution for that issue.  For examples like the
one described there, the expression for the array bound constant was simply
omitted from the IL.  In all these cases, the current change removes the
expression from the array bound constant but uses the a_local_expr_node_ref
mechanism described in the 4/28/06 Changes entry to record the expression
without violating memory region constraints.  These cases are identified by
the new flag constant_bound_expr_in_local_expr_node_ref in the
variant.array section of a_type.  [Patch sent out 4/17/08.]

1/29/08  Pragmas and Microsoft-mode duplicate function template specialization

In Microsoft bugs mode with microsoft_version == 1200, the front end accepts
and discards duplicate function template specializations (see Changes entry of
9/9/03).  However, if a pragma was applied to the discarded definition, the IL
representation was not correctly discarded, and aborts could result in many
configurations.  For example (assuming INCLUDE_EDG_TEST_PRAGMAS is TRUE):

  template<class T> int g(T) { return 0; }
  int g(int) { return 1; }
  #pragma test_next_decl
  int g(int) { return 2; }

[Patch sent out 4/17/08.]

This is now fixed (the pragma is discarded along with the declaration).

1/28/08  Pragmas and C-mode implicit function declarations

The front end no longer attempts to bind pragmas to the implicit declaration
of a function in C mode.  In addition to being a surprising effect, such a
binding could result in an internal error in non_fs_remap_checking ("func
number in file scope").  For example (assuming INCLUDE_EDG_TEST_PRAGMAS is
set to TRUE):

  int g() {
  #pragma test_bind_next_pass
    return f();  // "f" implicitly declared in C mode.  Previously, the
  }              // pragma bound to "f" instead of to the return
                 // statement, which led to an internal error in some
                 // configurations.  Now the pragma binds to the return
                 // statement.

[Patch sent out 4/17/08.]

1/24/08  Abort when mangling nonreal class templates that contain
         unnamed enums or class members

As a result of the changes described in the Changes entry of 9/13/07,
in configurations where PROTOTYPE_INSTANTIATIONS_IN_IL and MANGLE_ALL_NAMES
is TRUE, an assertion in lower_name.c was triggered when mangling the type
of an unnamed enum or class member in a nonreal class template.
This is now fixed.  For example:

  template <typename T>
  class A {
    struct { int i; };    // previously generated an assertion failure
    enum { e };           // previously generated an assertion failure
  };

[Patch sent out 4/17/08.]

1/23/08  Duplicate typeinfo types when using precompiled headers

In configurations where exception handling is not enabled, and lowering
of RTTI constructs (i.e., dynamic_cast or typeid) is required by a header
file that is being precompiled, the typeinfo types that were added
during lowering will be added again when the precompiled header file
is used subsequently, causing two sets of typeinfo types.  The erroneous
behavior was the result of only recording the state of typeinfo_types when
exceptions_enabled was TRUE, despite its use in RTTI cases.  The
state of typeinfo_types (and all other state variables in lower_eh.c
and lower_name.c) is now saved/restored unconditionally when precompiled
headers are used.  For example:

  file t1.h:

  struct B { virtual ~B(); };
  struct D: B { };
  int f(B *pb) {
    return (dynamic_cast<D*>(pb)) != 0;   // requires RTTI in a PCH
  }

  file t1.C:

  #include "t1.h"
  int main() {
    return 0;
  }

[Patch sent out 4/17/08.]

1/23/08  Check for preproc_immediate pragmas in begin_rescan_of_pragma_tokens

"preproc_immediate" pragmas must be scanned when they are encountered -- they
cannot be cached and rescanned later.  Formerly, this restriction was not
enforced by begin_rescan_of_pragma_tokens.  If a user pragma processing
routine called begin_rescan_of_pragma_tokens for a preproc_immediate pragma,
it would receive an unexpected sequence of tokens.  An assertion check
has been added to begin_rescan_of_pragma_tokens to detect this incorrect
usage. 

1/22/08  C++-generating back end: pseudo-destructors in generated instances

In configurations in which the output of the C++-generating back end contains
explicit specializations for generated instances of function templates (i.e.,
with NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE),
the generated code sometimes rendered pseudo-destructors using type keywords
directly.  Such code is not valid according to the C++ Standard and is
rejected by many compilers.  This has now been fixed by generating a typedef
and using the typedef name instead of the type keyword in the code generated
for pseudo-destructors.  For instance, the pseudo-destructor in the generated
instance foo<void>(void *p) in the following example was previously generated
as "p->void::~void()" and now as something like "p->__T9963512::~__T9963512()"
(where __T9963512 is the name of a generated typedef for void).  (Note that
pseudo-destructors that appeared directly in the original source using type
keywords will retain that form in the generated code.)

  template <class T> void foo(T *p) {
    p->~T();
  }
  void bar(void *p) {
    foo(p);
  }

1/20/08  Microsoft compatibility: ambiguous injected class name in qualifier

If a class has two base classes that are instances of the same class
template, the Microsoft compiler (starting with version 8) allows a
reference to the ambiguous injected class as the qualifier in a
qualified name.  This should be ambiguous, but the Microsoft compiler
selects the injected class name from the first base class.  The Microsoft
compiler allows the name following the injected class name to be
any kind of member except a nonstatic data member.  Our emulation,
however, accepts any kind of reference.  For that reason, and because
this is a particularly dangerous feature, we give a discretionary error
and let users downgrade the diagnostic if they really need the
feature.  It is dangerous because even in the case where the name
after the qualifier refers to a static entity, the definition of the
entity can be different in the two instances of the class template
being used (as is the case with Q::X and Q::eq in the example below).

  template <typename T> struct Q {
    void f(){}
    int i;
    typedef T X;
    enum E {e1 = sizeof(T)};

  };
  struct C : public Q<int>,  Q<double> {
    void foo();
  };
  void C::foo () {
    Q::f();  // Accepted by VC8
    int i = Q::i;  // Error in VC8
    Q::X x;  // Accepted by VC8
   int y = (int)Q::e1;  // Accepted by VC8
  }

1/20/08  Another tweak to GNU lookup inside templates

Another adjustment to the emulation of GNU lookup rules on calls inside
templates (see change of 8/7/07 for the most recent in a continuing series):
Calls written in operator form seem to see functions declared after
the point of use in all cases.

  struct A {};
  struct C {};
  bool operator>>=(A, int);
  template <class T> void foo() {
    C value;
    value >>= 3;  // g++ >= 3.4 finds the post declared function
  }
  bool operator>>=(C,int);
  int main() {
    foo<int>();
  }

1/19/08  Repeated error message on inaccessible destructor in throw

In some cases, the error for an inaccessible destructor in a throw
operation was duplicated.  Now fixed.  This problem was introduced in
version 3.6.

  class A {
  public:
      A() {}
  private:
      ~A() {}
  };
  void foo() {
    try {
      throw A();  // Same error message twice previously
    }
    catch (...) {}
  }

1/16/08  Abort on nested class with invalid GNU attributes

In GNU C++ mode, the use of GNU attributes in invalid syntactic locations
of nested class declarations sometimes triggered an abort.  For example:

  template<int T> struct S {
    __attribute__ ((aligned(16)))  // Invalid attribute location for nested
    struct bar {};                 // class declaration.
    struct bar;                    // Internal error was triggered during
  };                               // the instantiation of S<0>.
  S<0> f;

This is now fixed.  A warning is now issued about the attribute not being
valid at that syntactic location.  [Patch sent out 4/17/08.]

1/8/08   Name linkage of class types in cfront mode

In cfront mode, class types initially have internal name linkage, which is
changed to external (C++) name linkage if the class is involved in the
declaration of an entity (variable, function, or class type) which itself has
external name linkage.  Previously, however, this process excluded class types
involved in the declaration of entities with extern "C" name linkage, or
appearing within anonymous union types.  Those exclusions could trigger
spurious errors when simultaneously compiling multiple translation units.
For example:

  // Primary translation unit:
  struct S {};            // Internal name linkage.
  extern "C" void f(S*);  // S previously not updated because of extern "C".

  // Secondary translation unit: (same as primary)
  struct S {};
  extern "C" void f(S*);
      // Previously triggered a spurious correspondence error because the
      // two types S were considered distinct (i.e., with internal linkage).

This is now fixed: The previously excluded cases are no longer excluded.

1/5/08   Validity of tokens created by macro concatenation

According to the C and C++ standards, it is undefined behavior if the two
preprocessing tokens joined by a ## operator do not form a valid preprocessing
token.  The front end now checks for this situation in strict and GNU modes;
the behavior in other modes is controlled by the new configuration macro
DEFAULT_CHECK_CONCATENATIONS.  The default behavior can be overridden by the
new command-line option --[no_]check_concatenations.  For example:

  #define MINUS_5(x) x ## -5
  int i = MINUS_5(0);   // Now an error in strict mode: '0-' is not a
                        // valid token
  #define IGNORE /##/
  IGNORE int j;         // Now diagnosed in non-Microsoft modes as an invalid
                        // token when concatenation checking is in effect

1/2/08   NULL file pointer passed to fclose when using implicit inclusion

When implicit inclusion mode is being used, a NULL file pointer could be
passed to fclose if a file declares but does not define a template, that
file has a name that would be found by the implicit inclusion mechanism and
that file had already been explicitly or implicitly included.  Now fixed.

  file t1.c:

  #include "t2.c"
  int main() { f(1); }

  file t2.c:

  #ifndef T2
  #define T2
  template <class T> void f(T);
  #endif

[Patch sent out 4/17/08.]

12/22/07 Anachronisms mode and reference to function

A change made in version 3.8 introduced a bug in anachronisms mode:
When an overloaded function parameter that is a reference to function
is passed an argument that is a pointer or pointer to member to an
overloaded function, an internal error was issued ("cast_operand:
bad func symbol").  Such cases once again result in an error instead
of an internal error.

  void f(long);
  void f(int);
  void g(int);
  void g(void (&r)(long));
  int main() {
    g(&f);  // Error again rather than abort in anachronisms mode
  }

12/21/07 Spurious errors in complex multi-translation unit cases

A bug that triggered spurious errors in very complex multi-translation-unit
cases has been fixed.  The spurious errors indicated that a class template
instance was different in two translation units.

12/21/07 Array-to-pointer decay in inexact template argument deduction

When checking for a deduction match based on a qualification conversion,
the front end did not use the type after array-to-pointer decay (as clarified
by core issue 522) resulting in an error in examples such as the one below.
This has been fixed.

  template<class T> void f(const T* const args[]){}
  int main() {
    char* arr[1] = {};
    f(arr);
  }

12/18/07 Display of enumerator values

The IL display utility displayed the name of an enumerator instead of its
numeric value in the "integer_value" field of an enumeration constant.  Now
fixed.

12/17/07  Overeager generation of base class virtual destructors

In some cases -- corresponding to instances where a virtual function table
will be defined -- the front end forces definitions of virtual functions
in a class and in its base classes, which affects instantiatable
functions and compiler-generated virtual destructors.  Base class
destructors, as it turns out, need not be generated by this process,
because they will be overridden in the derived class and will therefore
never be pointed to directly from the derived class virtual function
table.  Therefore, the front end no longer generates them in such
cases.  This avoids errors (not spurious, but not required and not
issued by g++ or MSVC++) in examples where a destructor cannot be
instantiated on a given type, as in the following:

  struct A {
    virtual ~A();
  };
  template <class T> struct Templ {
    ~Templ() { p->f();}  // Formerly, an error here
    T* p;
  };
  class Incomplete;
  class  B : public A {
    Templ<Incomplete> x;
  };
  struct C : public B {
    C();
    virtual ~C();
  };
  struct D : public C {
    D() {}
  };

12/12/07  GNU compatibility: Function attributes in local scopes

In GNU modes with gnu_version >= 40000 the front end now ignores the function
attributes "alias" and "weakref" when they appear in local scopes (with a
warning).  For example:

  void f() {
    void g() __attribute((alias("G")));  // Attribute ignored with a warning
  }                                      // when gnu_version >= 40000.


12/12/07  GNU attribute warn_unused_result lost on redeclaration

When a function first declared with the GNU attribute warn_unused_result was
later defined without that attribute, the attribute was lost altogether.
For example:

  int f() __attribute((warn_unused_result));
  int f() { return 0; }  // Attribute was lost here.
  void g() { f(); }      // No warning was issued here.

This is now fixed.  [Patch sent out 4/17/08.]

12/12/07  Internal error in Microsoft mode with multiple translation units and
          user-declared operator new[]/delete[]

In Microsoft mode with microsoft_version >= 1400, the front end triggered an
internal error in trans_corresp.c ("Expected a class member") when
simultaneously compiling multiple translation units some of which explicitly
declare operator new[] or operator delete[] and some of which don't.
For example:

  // Primary translation unit:
  int main() {}

  // Secondary translation unit:
  void* operator new[](unsigned); // Assumes size_t is "unsigned int".
                                  // Triggered an abort in trans_corresp.c.

This is now fixed.  (This is a regression introduced by the changes described
in the entry of 9/11/07.)  [Patch sent out 4/17/08.]

12/12/07 Incorrect suppression of header file inclusion

The extension of header file inclusion guards to recognize "#if defined"
and "#if !defined" forms (see the Changes entry of 3/20/07) did not
correctly handle the case in which a header begins with a non-guard #if
immediately followed by a #if of the correct form to be an inclusion guard.
Such files were erroneously deemed to be candidates for suppression of
subsequent #includes.  This is now fixed.  For example:

  file x.h:

  #if A            // Not an inclusion guard
  #if !defined(B)
  #define B
  #endif
  // Additional code
  #endif

  file x.cpp:

  #define A 1
  #include "x.h"
  #include "x.h"   // Inclusion previously incorrectly suppressed

[Patch sent out 4/17/08.]

12/6/07   --error_output leaves file open when using MAKE_FRONT_END_CALLABLE

In configurations where MAKE_FRONT_END_CALLABLE is TRUE and the
--error_output command line option is used to direct errors to
a file, the file is not closed when the front end completes
the compilation (either normally or as the result of an error).
This is now fixed.  [Patch sent out 4/17/08.]

12/3/07   Conversion to _Bool in gcc mode was not done properly

GNU C mode has the _Bool keyword of C99, and conversion to a _Bool is
defined as in C99 (non-zero converts to 1, zero to 0).  Previously,
this was not emulated (normal integer conversion rules were used).
Now fixed.

int main() {
  int y = 100;
  _Bool a = y;  // Should produce 1 in a in --gcc mode
}

[Patch sent out 4/17/08.]

11/29/07  Some typeinfo variables decoupled from virtual function tables

IL lowering for both the Cfront-like and IA-64 ABIs now allows typeinfo
variables for certain classes to be defined independently from the
virtual function tables for those classes.  (Formerly, the typeinfo
variable was always defined if and only if the virtual function table
variable was defined.)  The "certain classes" are those that do not
have a key/decider function, and for which the virtual function
table is therefore considered "optional" -- i.e., defined only if
referenced.

In certain cases, this change means that virtual functions of a
class are no longer instantiated, and therefore some diagnostics
previously issued no longer are.  For example:

  #include <typeinfo>
  template <class T> struct vector {
    ~vector() {
      T* t;
      t->~T();  // Formerly flagged as an error when destructor for
                // vector<Incomplete> was instantiated
    };
  };
  struct Base {
    virtual ~Base();
  };
  struct Incomplete;
  struct Derived : public Base {
    vector<Incomplete> i;
  };
  void f() {
    Derived* t;
    const std::type_info &r = typeid(t);
  }

11/28/07  GNU C++ compatibility: incorrectly specified class template arguments

g++ allows a member of a nested class of a class template to be defined
using an incorrect template argument list.  We now emulate this in g++
mode.  A warning is issued.

  template <class T, class V> struct Outer {
    struct Inner {
      void f();
    };
  };
  template <class T, class V> void Outer<T, int>::Inner::f() { }
                                            ^ should be V

11/27/07  Warning if #include_next is used in primary source file

If an #include_next directive is used in a primary source file, we now
issue a warning and treat the directive as a normal include (emulating the
GNU behavior).  Formerly, an empty search path would be used, resulting in
a catastrophic error.

11/27/07  New size_of_type macro

Internal to the front end, the size field of a tk_void or tk_routine type is
represented as zero even though the size of these (void and function) types
is defined to be one in GCC emulation mode.  The new size_of_type macro
simply returns the size field of the specified type except in the cases
described above (i.e., in GCC emulation mode when the type is tk_void
or tk_routine) when it returns one.

11/26/07  GNU C++ compatibility: emulation of g++ using-directive
          visibility rules

In template instantiations, the function symbols made visible by
using-directives vary depending on the version of g++ being used. The
front end has been updated to better emulate the GNU behavior in g++ mode.

In this example:

  namespace N1 {
    template<typename T> inline void f(const T&, const T&) { }
  }

  template<typename T> inline void f(T const&, T const&) { }

  template<typename T> inline void g(T const& val1, T const& val2) {
    f<int>(val1, val2);  // call #1
    f(val1, val2);       // call #2
  }

  int v1;
  int v2;

  int main() {
    g(v1, v2);
  }

  using namespace N1;

We now match the behavior of the various g++ versions, except as noted below.
Formerly, both calls were ambiguous for all gnu_version values.

Call #1 is:

  - ambiguous in g++ 3.2
  - accepted in g++ 3.3, but we give an ambiguity
  - accepted in g++ 3.4 and above

Call #2 is:

  - ambiguous in g++ 3.2
  - accepted in g++ 3.3, but we give an ambiguity
  - ambiguous in g++ 3.4
  - ambiguous in g++ 4.0
  - accepted in g++ 4.1

11/26/07  Incorrect partial ordering when one parameter is a cv-qualified
          reference

Partial ordering did not produce the right result when the parameter of one
of the routines was a cv-qualified reference and the other parameter was
a value parameter.  This problem resulted in a spurious ambiguity
in the example below.  Now fixed.

  template<class T> class A { };
  template<class T> bool operator==(const A<T> a1, const A<T> a2) {
    return (&a1==&a2);
  }
  template<class T1,class T2> bool operator==(const A<T1>& a1, const T2 a2) {
    return true;
  }
  int main() {
    A<int> a;
    A<int> b;
    return ( a == b );
  }

This change can cause an ambiguity on some cases that had been accepted:

  template <class T> void f(T) {}
  template <class T> void f(const T&) {}
  int main() { int i; f(i); }

Such examples also result in an ambiguity from the g++, Microsoft, and
Sun compilers, however.  In addition, our new behavior is correct according
to the C++ Standard.  [Patch sent out 4/17/08.]

11/21/07  Configurability of function return by pointer in lowering

In cases where a function returns a class value by copy constructor
(i.e., when the value_returned_by_cctor flag is TRUE), lowering
modifies the function to return its value through an additional
parameter, as required by both IA-64 and Cfront like ABIs.
General support for performing this modification (i.e., returning a function's
value through an additional argument rather than the return value),
is now provided by the new routine set_lowered_routine_calling_method_flag
(e.g., in the case of sufficiently large POD classes).

11/20/07 C++-generating back end: accessibility of underlying types of
         typedefs used as template arguments

The change of 11/10/04, which caused template arguments to be generated
using the underlying type instead of a typedef name whenever possible, did
not take into account cases in which the underlying type is itself an
instance of a class template.  This oversight resulted in incorrect code
when one of that template's arguments is inaccessible.  This has now been
fixed; the C++-generating back end now performs a full recursive scan of
template arguments appearing in the underlying type and will use the
typedef name if any of them is inaccessible.  For example:

  template <typename T> struct S {};

  class C {
    struct P { };
  public:
    typedef S<P> SP;
  };

  template <typename T> struct U {};

  U<C::SP> usp;    // Type previously generated as "U< S< C::P> >"

11/13/07 printf and scanf argument checking: %s

The checking of arguments to printf and scanf now allows the argument
associated with a %s specifier to be a pointer to a character of any
signedness, i.e., char *, signed char *, or unsigned char *.  Formerly,
a remark was issued for the explicitly-signed cases.

  void fns(signed char *p) { printf("%s", p); }

Also, a pointer passed to scanf to allow return of a value is now
considered incompatible if it is a pointer to const.

  int main() {
    const int i = 1;
    scanf("%f", &i);
  }

11/8/07  Lowering: Incorrect region table entries for certain dynamically
         initialized aggregates in file scope

In cases where lowering is used to generate region tables
(i.e., DO_FULL_PORTABLE_EH_LOWERING or GENERATE_EH_TABLES is TRUE),
these tables may contain incorrect "next" values when a member of an
aggregate in the file scope is dynamically initialized with a constructor
call that requires creation of a temporary variable.  Additionally,
the __eh_curr_region variable may be set incorrectly.  These errors
could lead to incorrect cleanup of the aggregate if an exception were
to be thrown during the aggregate's construction.  Such aggregates are
now copied from the file scope into the generated initialization routine.
Here is an example whose region table entries were incorrect:

  struct foo { ~foo(); };
  struct bar {
    bar(int, foo __a = foo());
    ~bar();
  };
  bar table[] = { 1,2,3 };

[Patch sent out 4/17/08.]

11/7/07  Microsoft compatibility: Visibility of static data member in its
         in-class initializer

In Microsoft bugs mode, a static data member declaration is not visible in
its own in-class initializer.  For example:

  int const i = 7;
  struct S {
    static int const i = i;  // Initializes S::i to 7 in Microsoft bugs mode.
  };                         // (An error in other modes.)

11/7/07  C++-generating back end: Declarators and initializers with embedded
         declarations and/or statements

In C mode and in GNU C++ modes, declarators and/or initializers can contain
declarations and/or statements.  The C++-generating back end often rendered
such (somewhat unusual) cases incorrectly.  For example:

  int a[sizeof(struct S { int i; })];  // Valid in C mode, but the definition
                                       // was dropped by the C++-generating
                                       // back end.

Another example:

  void f() {
    void *p = (({ int x; 3; }),        // Accepted in some GNU C++ modes, but
               (union { int y; }*)0);  // previously rendered incorrectly.
  }

This is now fixed.

11/7/07  C++0x: Universal character names

In strict C++0x mode the constraints on the code points implied by universal
character names (UCNs) are different from those in strict C++ (i.e., C++03)
mode.  Specifically:

  - UCNs reserved for surrogate code points (values 0xD000 - 0xDFFF) are
    never permitted, and
  - UCNs corresponding to control characters or to characters in the basic
    source character set are permitted in string literals.

For example:

  char const *str = "\u0085";  // Allowed in strict C++0x mode, but not in
                               // strict C++ mode (\u0085 is a control
                               // character).

(In the corresponding nonstrict modes, warnings are issued instead of errors.)

This change was voted into the C++ committee's working paper for the next
standard in October 2007 (meeting in Kona, through proposal numbered N2170).

11/6/07  Microsoft compatibility: Local types in template arguments

In Microsoft mode with microsoft_version >= 1400, local class and enum types
can now be used as template type arguments (if they are not unnamed).  Such
types still do not have external name linkage however (in standard C++,
having external name linkage is a requirement for a class or enum type to be
a valid template type argument).  For example:

  template <typename T> struct S {};
  void f() {
    struct L {};
    S<L> sl;  // Now accepted in some Microsoft modes.
  }

11/5/07  Sun compatibility: lookup of names in template instantiations

In default mode, the front end looks in both the namespace of the template
definition and the referencing namespace of the instantiation when looking
up names in templates.  This can result in ambiguity errors in Sun mode
as the Sun compiler does not consider names from the referencing namespace.
We now emulate the behavior of the Sun compiler in Sun mode.

  template < class T > void f(const T & a) { }
  namespace NS {
    template < class T > void f(const T & a) { }
    template < class T>  struct S {
      void f2(const T& a) { f(a); }
    };
  }
  int main() {
    NS::S<int>().f2(1);
  }

11/5/07  Instantiate template classes for some type traits helpers

In many C++ modes, the front end accepts type traits pseudo-functions that
allow generic code to depend on various type properties (see Changes entry of
3/21/06).  Some of these pseudo-functions requires their argument types to be
complete, but the front end failed to instantiate the associated template if
the argument type was an incomplete template class.  For example:

  template<typename T> struct S {};
  int a[__is_pod(S<int>)];  // Previously triggered an error about S<int>
                            // being incomplete.

This is now fixed.  [Patch sent out 4/17/08.]

11/2/07  Spurious warning on definition at end of file with #line directive

The Changes entry of 6/1/07 describes how the front end now warns about
class and enum type definitions that are missing a terminating semicolon.
This warning was being issued spuriously if a definition at the end of a
source file was followed by a semicolon preceded by a #line directive.
For example:

  struct S {}  // Triggered a spurious warning.
  #line 100
  ;

This is now fixed.  [Patch sent out 4/17/08.]

11/2/07  GNU C99 compatibility: The keyword "asm"

GCC offers at least two C99 modes: "-std=c99" and "-std=gnu99".  The EDG front
end option combination "--gcc --c99" is meant to emulate GCC's "-std=gnu99"
option, which implies that in that mode "asm" is a keyword.  A previous change
(documented in the entry of 8/1/06) inadvertently made "asm" an ordinary
identifier in that mode.  That change has now been backed out.  For example:

  int asm;  // An error in GNU C99 mode: "asm" is a keyword.

The front end does not track GCC's "-std=c99" behavior (although the default
C99 mode often matches that behavior).

11/1/07  Microsoft compatibility: Extraneous "virtual" specifiers

In Microsoft mode the front end now accepts and ignores (with a warning) the
keyword "virtual" on explicit specializations of members of class templates.
For example:

  template<typename T> struct S { void f(); };
  template<> virtual void S<int>::f() {}  // Now accepted with a warning.

11/1/07  GNU C++ compatibility: default arguments on templates and deduction

GNU C++ mode (and some other modes, such as Microsoft mode prior
to 7.1) keep default arguments of function templates as part of
the type of the function when template deduction is done (see
Changes entry of 8/9/05).  As a consequence, the front end aborted
in copy_default_arg_expr ("rout NULL, no error") when a call was made
to a function whose type comes from such a deduced type, and the
default argument is omitted and therefore must be instantiated at
the point of call.  Now fixed.

  template <typename Derived> struct B {
  template<typename memfunT> void f(memfunT mfp) {
    (static_cast<Derived*>(this)->*mfp)();
  }
  };
  template <typename T> struct D: B<D<T> > {
    void g(bool);
  };
  template <typename T> void D<T>::g(bool = false) {
    f(&D::g);
  }
  template struct D<int>;

10/31/07 GNU C++ compatibility: Name linkage and unnamed types

In GNU C++ mode, an unnamed class/enum type can be given a name "for linkage
purposes" through a typedef that expresses the type through a typeof construct
(see Changes entry of 8/3/06).  This mechanism has now been extended to
unnamed class/enum types that are nested in unnamed class types.  For example:

  struct S {
    struct {
      struct {} d;
    } m;
  } s;
  typedef typeof(s.m.d) D;
  template<typename T> struct X {};
  X<D> xd;  // Now allowed in GNU C++ mode.
        
Furthermore, when gnu_version < 30400, nonlocal unnamed types are allowed as
template arguments.  The deduction failure behavior described in the Changes
entry of 9/13/06 now only applies when gnu_version >= 30400.  For example:

  struct { operator int() { return 0; } } x;
  template<class T> int f(T) { return 1; }
  int f(int) { return 2; }
  int main() {
    return f(x);  // Accepted in GNU C++ mode. Returns 1 when
  }               // gnu_version < 30400; return 2 otherwise.

10/30/07 GNU compatibility: asm functions in source sequence lists

In configurations in which both ASM_FUNCTION_ALLOWED and
GENERATE_SOURCE_SEQUENCE_LISTS are TRUE, the iek_statement source sequence
entry corresponding to the stmk_asm_func_body statement was omitted from
the source sequence list for the asm function.  In configurations using
the C++-generating back end, this omission resulted in dereferencing a null
pointer while generating the asm function definition.  The missing source
sequence entry is now included in the IL.  For example:

  __asm int f(int i) {  /* Previously the declaration of "i" was the last
                           entry on f's source sequence list.  Now it is
                           followed by the entry for the body. */
  }

[Patch sent out 4/17/08.]

10/25/07 GNU C++ compatibility: visibility of using-directives

The front end does special processing in g++ mode to emulate g++'s behavior
concerning the visibility of using-directives.  A flaw in this emulation
resulted in spurious errors in certain cases involving block scope
using-directives.  Now fixed.

  namespace N { int i = 0; }
  namespace M {
    template <class T> inline int f() {
      using namespace N;
      return i;  // spurious 'identifier "i" is undefined' error
    }
  }
  using namespace N;
  namespace M {
    void foo() { f<int>(); }
  }

[Patch sent out 4/17/08.]


10/25/07 Spurious error on template disambiguation

The token caching process did not handle the "template" keyword as used
for syntactic disambiguation properly.  This could result in spurious
errors when the front end was caching up to a particular token, and
that token was found in a dependent template argument list preceded by
the "template" keyword.  Now fixed.

  template<typename T> class A {};
  template<typename T> struct B {
    typedef A<T> my_A;
    template <typename U, typename V> my_A g();
  };
  template<typename T> struct C {
    typedef B<T> my_B;
    void f();
    my_B b;
  };
  template<typename T> void C<T>::f() {
    typename my_B::my_A it = b.template g<int, int>();
    //                         ^ problematic use of "template"
  }
  int main() {
    C<int> c;
    c.f();
  }

[Patch sent out 4/17/08.]

10/24/07 Configuration macro for GNU asm operand descriptions

A new configuration macro RECORD_RAW_ASM_OPERAND_DESCRIPTIONS is now available
to indicate that the string literal in input and output operand descriptions
of GNU asm constructs should be recorded as it appears in the source, with no
further processing or validation.  This means that operand description
constructs that are otherwise unsupported (such as the "!", "?", and ","
constraint modifiers) are accepted, but the back end is now responsible for
making sure that the description string is meaningful (this is reasonable
since that string's meaning is highly target-dependent).  The new macro is
set to TRUE by default (which implies an IL CHANGE; the previous behavior and
IL representation are restored by setting RECORD_RAW_ASM_OPERAND_DESCRIPTIONS
to FALSE).

10/23/07 Internal error on use of typeof or decltype in local class types

In GNU modes, the front end aborted with an internal error in
non_fs_remap_checking ("func number in file scope") when a local class type
defined a member using a typeof construct that referred to a local variable
of the enclosing function.  For example:

  void f() {
    int x = 0;
    struct { typeof(x) m; } y;  // Previously triggered an internal error.
  }

An entirely similar problem existed with decltype in C++0x mode.  This is now
fixed.  As part of this change, decltype and typeof constructs in member
function bodies of local classes are no longer allowed to refer to local
variables of the enclosing function (this was already prohibited in strict
mode).  For example:

  void f() {
    int x = 0;
    struct S {
      void f() { decltype(x) y; }  // Now always an error.
    };
  }

[Patch sent out 4/17/08.]

10/20/07 Microsoft compatibility: spurious error in aggregate initialization
         of cv-qualified class object

The change of 5/11/07 to suppress implicitly-declared special member
functions had a bug causing spurious diagnostics in the case of aggregate
initialization of an object with a cv-qualified class type when
microsoft_version is 1400 or greater.  This is now fixed.  For example,

  struct S { int i; };
  const S s = { 1 };    // Previously caused an error saying that the
                        // suppressed destructor is needed

[Patch sent out 4/17/08.]

10/10/07 Internal error on redeclaration involving default function argument

In some cases where a function or member function with a default function call
argument was redeclared, the front end sometimes aborted with an IL write-read
difference.  (This required configurations with IL_SHOULD_BE_WRITTEN_TO_FILE
set to TRUE.  The problem was slightly more likely to arise when support for
exception handling was enabled.)  For example:

  struct S { S(char*); ~S(); };
  struct X { void f(int (X::*)(void), S = ""); };
  void X::f(int (X::*)(), S) {}  // Previously aborted if exception handling
                                 // was enabled.

This is now fixed.  [Patch sent out 4/17/08.]

10/9/07  Use existing routine definitions during lowering (if available)
         when building run time library

When building the run time library (i.e., --building_runtime is specified
on the command line), it is possible to have two a_routine IL entries for
the same run time library routine (one defined by the translation unit
and another added during the lowering process).  A check is now made when
lowering adds a prototyped run time routine declaration to see if an
existing routine entry has already been created.  If a matching existing
routine entry is found it is used (instead of creating a new one).
Any unprototyped routine entries added during lowering may still result
in two a_routine entries in the IL.  Additionally, the __cxa_bad_typeid
run time routine definition has been changed from unprototyped to prototyped
to take advantage of this change.  The following code had created
two a_routine entries but now creates only one (when --building_runtime
is specified):

  #include <typeinfo>
  extern "C" void __cxa_bad_typeid(void) {};  // creates routine definition
  void f(std::type_info *info) {
    typeid(*info);                // had created a routine declaration,
  }                               // now uses existing one

10/5/07  Problem with dependent nested class in elaborated type specifier

Version 3.10 introduced a change in the way that nested types of class
templates are handled.  When the nested type name was used in an elaborated
type specifier in the class definition, the actual nested type was used 
but its nonreal version should have been used.  This caused the out-of-class
definition to be rejected in the example below.  Now fixed.  See the
Changes entry of 9/13/07 for more information.

  template <class T> struct A {
    union B { float f; };
    static union B b; 
  };
  template <class T> typename A<T>::B A<T>::b;

[Patch sent out 4/17/08.]

10/2/07  USE_X86_64 configuration macro in defines_linux.h

A typo in defines_linux.h led to the possibility for the USE_X86_64
configuration macro to be undefined rather than defined to a value of 0.
This has been fixed.

9/30/07  C++-generating back end: inaccessible default template arguments

The C++-generating back end generated the names of instances of class
templates using the full list of template arguments, including those
resulting from default arguments.  In some cases, however, a default
argument is accessible where the template is declared but not at the point
at which a reference to the instance occurs, resulting in an error when the
generated code was compiled.  This problem has been addressed by keeping
track of the minimum number of explicitly-specified template arguments used
to refer to the instance anywhere in the translation unit; if a template
argument after that point refers to a non-public class member, the template
argument list is truncated so that the default argument will be used.  For
example:

  class Outer {
    struct Inner { };    // private
  public:
    template <typename T = Inner> struct S { };
  };
  Outer::S<> s;          // Previously generated as Outer::S<Outer::Inner>

9/28/07  C++-generating back end: Class declaration incorrectly rendered as
         a class definition

In some situations, the C++-generating back end incorrectly rendered a class
declaration as a class definition.  For example, the input:

  struct S { friend struct B; } a;
  struct B {} b;

was incorrectly rendered as (modulo formatting):

  struct S { friend struct B {}; } a;
  struct B b;

which is invalid code.  This is now fixed.  The fix required an IL CHANGE:
If an initializer for a variable has associated source sequence entries (e.g.
triggered by a GNU statement expression), those entries are terminated by an
iek_src_seq_end_of_construct entry.

9/27/07  Incorrect value of DO_LAST

The value of the macro DO_LAST (defined in declarator.h) did not reflect the
addition of the macro DO_RPAREN_IN_NEW_DECLARATOR.  This is now fixed.  (This
does not have an observable effect on the behavior of an unmodified front end
because DO_LAST is currently not used in the front end source code.)

9/27/07  GNU statement expressions in typeof and decltype constructs

The front end now accepts GNU statement expressions in GNU typeof and C++0x
decltype constructs.  In configurations with GENERATE_SOURCE_SEQUENCE_LISTS
set to TRUE, any source sequence entries generated for the argument of a
typeof or decltype construct will be delimited by a pair of source sequence
entries whose kinds are iek_type and iek_src_seq_end_of_construct.  (See also
the Changes entry of 8/27/07.)

9/25/07  Microsoft compatibility: __LPREFIX in wide-string initializers

In Microsoft mode, the front end previously failed to accept wide-string
initializers consisting of a __LPREFIX construct.  E.g.:

  #include <stdlib.h>
  wchar_t x[] = __LPREFIX("Wide");  // Previously an error; now okay.

This is now fixed.  [Patch sent out 4/17/08.]

9/23/07  Build error in il_to_str.c with RECORD_FORM_OF_NAME_REFERENCE

In configurations in which RECORD_FORM_OF_NAME_REFERENCE is TRUE but both
BACK_END_IS_C_GEN_BE and BACK_END_IS_CP_GEN_BE are FALSE, il_to_str.c
contained a reference to the variable msvc_target_version_number, which is
not declared in such configurations, causing a build error.  This is now
fixed.

[Patch sent out 4/17/08.]

------------------------------------------------------------------------------
Version 3.10, September 23, 2007

9/21/07  IL version number changed to 3.10

9/19/07  Microsoft mode: __unaligned

Three changes in support of the __unaligned qualifier in Microsoft mode:
1)  When a reference is being bound, the __unaligned qualifier can be dropped.
2)  A member function can be called on an __unaligned object.
3)  A pointer to __unaligned X can be converted to pointer to X (this was
allowed in some cases previously, but it's now allowed everywhere,
in particular on arguments to overloaded function calls); a warning
is issued.

9/19/07  Sun C++ mode: quirk in overload resolution for built-in operators

The front end now emulates a quirk of the Sun C++ compiler with regard
to how user-written operator functions compete with built-in operators.
It appears that if a user-written operator function is found that matches
without use of a user-defined conversion, the Sun compiler considers
no built-in candidates.  While it's true that a built-in candidate could
not be better than such a user-written function (because it needs
at least one user-defined conversion to convert from a class type
to a built-in type), it could cause an ambiguity.  Note that the 5.9
version of the Sun compiler has apparently fixed this behavior, but
since we do not yet have a --sun_version option, we are for now
doing this unconditionally in Sun mode.

  struct A {
    A();
    operator int();
  };
  A operator<<(const A&, const short);
  int main() {
    A x;
    A u;
    u = x << 5;  // Standard says ambiguous, now accepted in Sun mode
                 // (user-written operator<< called)
  }

9/19/07  User-defined conversion on cast to reference-to-const type

Certain casts to reference type that were erroneously rejected previously
are now accepted.  Specifically, casts from a non-class type to a
reference-to-const-class type, where the conversion must be effectuated
by calling a constructor, are now handled correctly.

  struct A {
    A(int i);
  };
  int main() {
    int i = 0;
    const A&a = static_cast<const A&>(i);  // Now accepted
  }

9/14/07  GNU compatibility: Exception specifications in system headers

In GNU C++ mode, the front end accepts an incompatible exception specification
when redeclaring a function first declared in a system header.  Previously,
the original exception specification (the one in the system header) was always
retained.  Now, the new exception specification is retained when the function
takes at least one argument (this matches the behavior of GNU C++ compilers).
In such cases, the redeclaration is treated as the "original declaration"
thereafter.  For example:

  # 1 "system.h" 3
  void f(int) throw();     // (1) Declaration in a system header.
  # 1 "lib.h"
  void f(int);             // (2) Accepted with a warning in GNU C++ mode.
  # 1 "main.c"
  void f(int) throw () {}  // Now an error because the exception specification
                           // of (2) is retained and (2) -- which is not in a
                           // system header -- is treated as the original
                           // declaration.

9/14/07  Incorrect wording of partial specialization error message

The wording for the ambiguity message issued for this case was incorrect
(it said "... have been made ..." instead of "... have made ...").  Now fixed.

  template <class T, class T2> struct A {};
  template <class T, class T2> struct A<T*,T2> {};
  A<int*, int*> a;
  template <class T, class T2> struct A<T,T2*> {};

9/14/07  Spurious "used before set" warnings in templates

During prototype instantiations of function templates (e.g., in strict C++
mode), the front end sometimes emitted spurious "used before set" warnings
for variables with template-dependent types.  For example:

  template<class T> int f() {
    T a;
    return a ? 1 : 2;  // Previously triggered a spurious warning in strict
  }                    // mode.

This is now fixed.

9/13/07  Microsoft and GNU C++ compatibility: new/delete in namespaces

In Microsoft C++ mode the front end accepts declarations of new and delete
operators in namespaces, but previously such declarations were never found
through lookup (see also Changes entry of 11/19/98).  Now such declarations
are found when using explicit operator call notation (but not when using the
more common new-expression and delete-expression syntax).  For example:

  void *operator new(size_t);  // (1)

  namespace N {
    void *operator new(size_t);  // (2)
    void f() {
      new double;        // Calls (1).
      operator new(55);  // Calls (2).
    }
  }

In addition, new and delete operators can now also be declared in namespaces
in GNU C++ mode when gnu_version < 40000.  Unlike in Microsoft mode, a
namespace-scope new operator (but not a namespace-scope delete operator) can
also be found when using new-expression syntax.

9/13/07  Duplicate diagnostics in template declaration scopes

Template declarations sometimes require a "prescan" to determine the
kind of entity being declared before the full processing is done.  This
can sometimes result in duplicate diagnostics.  The front end now
suppresses diagnostics that were already issued as part of the prescan.
In the example below, only one diagnostic is issued now.

  template <class T> struct A { int f(); };
  template <class T> int A<class T>::f() { return 0; }


9/13/07  Nested types of class templates treated as dependent

Nested types of class templates were not treated as dependent in certain
contexts, which could result in spurious errors.  In this example,
the front end incorrectly complained that incomplete type "X" could not
be used as a base class, and that "B" had no member "N".  These errors
were incorrect because "X" could be specialized for a given instance of "A".

  template <class T> struct A {
    struct X;
    struct B : public X {  // spurious "incomplete type not allowed"
      typename B::N n;
    };
  };
  template <> struct A<int>::X { typedef int N;};
  A<int>::B ab;

This issue also affected out-of-class definitions of class template members.
The definition of "A<T>::f" was erroneously rejected in this example:

  template <typename T> struct A {
    enum E { e1, e2 };
    template <E R> int f();
  };
  template <typename T> template <typename A<T>::E R> int A<T>::f() {
    return 0;
  }

Nested types of class templates are now correctly treated as dependent,
eliminating these problems.

9/13/07  C++-generating back end: parentheses around array-valued expressions

The C++-generating back end failed to add parentheses around array-valued
operands of higher-precedence operations.  This is now fixed.  For example:

  int arr[5];
  void f() {
    int j = 1;
    int *p;
    p = (j, arr);    // Formerly generated as "p = j, arr"
  }

9/12/07  Default maximum pack alignment

The default maximum pack alignment (TARG_MAXIMUM_PACK_ALIGNMENT) is now 128
and is independent of other configuration settings (previously is was smaller
when GNU_EXTENSIONS_ALLOWED was FALSE).  GNU and Microsoft compilers accept
larger values still: The front end can be configured to match those by setting
TYPE_FOR_TARG_ALIGNMENT and TARG_MAXIMUM_PACK_ALIGNMENT appropriately.

9/12/07  Reading the IL from a file with MACRO_INVOCATION_TREE_IN_IL

In configurations with MACRO_INVOCATION_TREE_IN_IL set to TRUE, the front
end failed to remap the pointer to the root macro invocation block in the
il header after reading the IL from a file, leading to unpredictable
behavior including aborts.  This is now fixed.

9/11/07  Microsoft C++ compatibility: Predefined new[] and delete[] operators

In Microsoft C++ mode with microsoft_version >= 1400, the predeclared new[]
and delete[] operators are now just aliases for their non-array counterparts.
User-declared new[] and delete[] operators, however, are distinct routines.
For example:

  void f1() {
    operator new[](4);  // Calls the predeclared "operator new".
  }
  void *operator new[](size_t);  // (1)
  void f2() {
    operator new[](4);  // Calls the routine declared in line (1).
  }

See also the Changes entry of 3/6/07.

9/11/07  Attribute weakref and the C++-generating back end

The C++-generating back end failed to render the argument to most instances
of the weakref attribute (a GNU extension).  For example:

  extern "C" void f() {}
  static void wf() __attribute__((weakref("f")));
    // Attribute previously rendered as __attribute__((__weakref__)) in
    // the C++-generating back end.

This is now fixed.

9/10/07  Using make_pointer_type in back ends

Calling make_pointer_type in a back end could result in accessing freed
memory locations when simultaneously processing multiple translation units.
This is now fixed.  In addition, to detect similar problems in other
functions, certain common uses of the trans_unit_corresp field of
a_source_correspondence will now trigger an assertion error if they occur
outside the front end (i.e., when the global variable in_front_end is FALSE)
when EXPENSIVE_CHECKING is TRUE.

9/10/07  Abort on array new when 1200 < Microsoft version < 1300

When the Microsoft version number is set to something greater than 1200
but less than 1300 (e.g., 1201), the front end aborted with an assertion
failure in overload.c in function select_overloaded_function while
processing any array new operation.  Now fixed.

  int* p = new int[10];  // Aborted with --microsoft_version=1201

9/6/07   Abort (or invalid IL) on erroneous use of auto type specifier

When "auto" was used as a type specifier followed by multiple declarators the
front end failed to issue an error for an initializer missing on any but the
first declarator.  This resulted in invalid IL and in some configurations
(e.g., with the C-generating back end) it triggered internal errors.
For example:

  auto x = 1, y;  // Now an error (y should have an initializer), but
                  // previously this resulted in invalid IL.

This is now fixed.

9/6/07   Incorrect display of macro invocation record numbers

The IL display utility showed incorrect record numbers in macro invocation
records (maintained in configurations in which MACRO_INVOCATION_TREE_IN_IL
is TRUE), displaying the record number modulo 128 instead of the full
value.  This is now fixed.

9/5/07   C++0x: New constraint for "inline"

In strict C++0x mode, the first "inline" declaration of a function (or
function template) cannot appear after the definition of that function (or
function template).  For example:

  void f() {}
  inline void f();  // Error in strict C++0x mode.

This change was made to the C++ committee's working paper for the next
standard through the resolution of Core issue number 317.

9/5/07   Internal error with incorrectly-terminated macro invocation

An omitted closing parenthesis in a macro invocation could result in an
abort if the macro expansion buffer overflowed and was reallocated during
the expansion of one of that invocation's macro arguments.  Now fixed.

9/5/07   Right shift token as part of a template default argument

In C++0x mode (and in some Microsoft modes) a right shift token (>>) may be
interpreted as two closing angle brackets for template argument lists.
This did not work properly when one of the argument lists being closed was
part of a template default argument.  In such cases, a spurious error would
result when the default argument was processed for a given instantiation.
Now fixed.

  template<typename T> class A {};
  template<typename T, typename T2 = A<T>> class B {};
  B<int> b;

8/30/07  Internal error in non_fs_remap_checking in some configurations

In some configurations that set both IL_SHOULD_BE_WRITTEN_TO_FILE and
RECORD_HIDDEN_NAMES_IN_IL to TRUE, the front end sometimes aborted with an
internal error "non_fs_remap_checking: func number in file scope" in
il_read.c.  The problem is rare and usually involves programs with deeply
nested scopes.  The following example could trigger the problem:

  void f() {
    struct X1 { struct X2 { struct X3 { struct X4 { struct X5 {
      struct X6 { struct X7 {}; };
    }; }; }; }; };
  }

This is now fixed.

8/29/07  "extern template" and inline functions

Version 3.9 added C++0x support for "extern template" and modified the
handling of that feature in g++ and Microsoft modes (see 3/15/07 entry).
Those changes had the unintended effect of instantiating inline functions
that were not referenced elsewhere in the translation unit.  This could
result in spurious errors if those functions could not actually be
instantiated.  Now, inline functions will be instantiated only if they are
otherwise used in the translation unit.

  struct A;
  template <class T> struct B {
    void f() {
      T *fp = new T;  // error here if B<A>::f is instantiated
    }
  };
  extern template class B<A>;

8/29/07  Microsoft C++ compatibility: Extended friend class declaration syntax

In Microsoft C++ modes, the C++0x extended friend class declaration syntax
(see Changes entry of 5/10/06) is now enabled.  For example, the following
case is now accepted in all Microsoft C++ modes:

  namespace N { struct S; }
  template<class T> struct X {
    friend typename N::S;  // Now accepted in Microsoft C++ mode.
  }

8/29/07  string_literal_type can be called outside the front end proper

Previously, a call to string_literal_type was unsupported (and likely to
abort) if the call occurred outside the front end proper (i.e., if the global
variable in_front_end was FALSE).  Now such calls are supported, but a new
type entry is created for every call when in_front_end is FALSE (no attempt is
made to share type entries for same-length strings in that case).  Note that
string_literal_type is still unavailable if STANDALONE_UTILITY_PROGRAM is
TRUE; in other words, it can only be called from a back end linked into the
same program as the front end.

8/28/07  Internal error in set_array_type_size with unspecified-bound array
         in template instantiation

In some situations involving function template argument deduction that
deduces an argument to be an unspecified-bound array type, the front end
aborted with an internal error "set_array_type_size: bad element type" in
types.c.  Such cases involved multidimensional arrays with intervening
typedefs.  For example:

  template<typename T> struct S { typedef T ST; };
  template<typename T> void f(T(*)[1]) {}
  int main() {
    f<S<int[]>::ST>(0);  // Triggered an abort while attempting to deduce
  }                      // U to S<int[]>::ST for template f.

This is now fixed.

8/27/07  C++0x: decltype

In C++0x mode, the front end now accepts the decltype operator.  This operator
allows a type to be produced from an expression.  In the general case,
decltype applied to an rvalue expression produces the type of that expression,
and decltype applied to an lvalue expression produces a reference to the type
of that expression.  Two exceptions to this rule exist.  First, when decltype
is applied to a qualified or unqualified name, or to a class member access
operation, the type produced is that of the indicated entity or class member.
Second, when decltype is applied to a function call, the type produced is that
of the return type associated with the type of the call.  For example:

  int i;
  decltype(i) i2;    // Same as "int i2;"
  decltype((i)) i3;  // Same as "int &i3;"

This extension was voted into the C++ committee's working paper for the next
standard in July 2007 (meeting in Toronto, through proposal numbered N2343).

An important intended use of decltype is to determine the return type of
certain function templates.  For example:

  template<typename T> struct A<T> { /* ... */ };
  template<typename T> T makeT();
  template<typename X, typename Y>
    A<decltype(makeT<X>()+makeT<Y>())> operator+(A<X> const&, A<Y> const&);

Unfortunately, such uses are currently not supported because of an existing
language issue under review by the C++ committee (Core issue number 339).
Trying to instantiate a decltype construct during function template argument
deduction results in a deduction failure.  The same is now also true for
GNU C++ typeof constructs (previously such situations led to an internal
error).  This is almost certainly a temporary limitation: The C++ committee
appears to be leaning towards allowing a broad range of decltype argument
expressions, and the front end will be updated to reflect the expected new
rules once they are established.

As part of this change, the representation of template-dependent typeof
constructs has been simplified to match the decltype representation (this is
an IL CHANGE).  Also GNU statement expressions are no longer accepted in
template-dependent typeof constructs (they were previously accepted, but the
resulting IL was sometimes invalid); they also cannot appear in (dependent
and nondependent) decltype constructs.  This limitation will be lifted in a
future version of the front end.

8/27/07  String initializers for flexible array members

In some GNU and Microsoft modes, flexible array members can be initialized
with a brace-enclosed initializer.  When the component of the aggregate
constant corresponding to the flexible array member is itself an aggregate
constant, the latter constant already had its field flexible_array_initializer
set to TRUE.  This is now also done when the component of the aggregate
constant corresponding to the flexible array member is a string constant
(ck_string).  For example:

  struct F { int n; int a[]; } = { 1, "x" };
    // The constant representing "x" now has its flexible_array_initializer
    // flag set to TRUE.

8/23/07  Microsoft compatibility: Old-style explicit specializations

In Microsoft mode, old-style explicit specializations of nonmember entities
are now disallowed by default when microsoft_version >= 1310 (a discretionary
error is issued).  An exception is made when microsoft >= 1310 but < 1400: In
that case, explicit specializations of class templates that are not
definitions are still accepted.  For example:

  template<class T> struct S {};
  struct S<int>;             // Error when microsoft_version >= 1400.
  struct S<int> { int i; };  // Error when microsoft_version >= 1310.

See also the related Changes entry of 8/2/07.

8/23/07  GNU compatibility: __alignof applied to packed fields

In GNU modes, applying the __alignof operator to a field selection operation
for a packed field now produces the value 1.  (Previously, the "packed"
attribute was ignored in such cases.)  For example:

  struct S { int i __attribute__((packed)); } s;
  int main() {
    return __alignof(s.i); // Returns 1.
  }

(See also Changes entry of 3/1/06.)

8/23/07  GNU C compatibility: __builtin_types_compatible_p

In GNU C mode, the front end now ignores top-level qualifiers when evaluating
the __builtin_types_compatible_p pseudo-function.

8/20/07  Use of freed memory in debug_exit could cause front end crash

In configurations where DEBUG, CHECKING and MAKE_FRONT_END_CALLABLE are 
all TRUE, and debugging is active (i.e., debug_level > 0), it is possible
for the front end to erroneously reference memory that has already been
freed.  This can happen when compilation terminates abruptly (e.g.,
from a #error directive) causing fe_cleanup to be called rather than
fe_wrapup.  This is now fixed.

8/14/07  C++0x: __func__

In C++0x mode, the reserved identifier __func__ is now accepted in function
bodies as the name of a predeclared character array that is initialized to a
string containing the name of the enclosing function.  (This is similar to
the meaning of __func__ in C99.  As is the case in C99 mode, the reserved
identifier is implemented as a keyword.)  The name of the function is
qualified with the names of any enclosing classes and/or namespaces.
For example:

  namespace N {
    void f() { printf("%s\n", __func__); }  // Prints "N::f".
  }

This extension was voted into the C++ committee's working paper for the next
standard in July 2007 (meeting in Toronto, through proposal numbered N2340).

8/13/07  C++-generating back end: precedence in operator-notation function
         calls

When the C++-generating back end generated a call to an overloaded operator
function using the operator notation, it failed to add parentheses when they
were required by the relative precedence of the operator and its operands.
This is now fixed.  For example:

  struct Integer {
    Integer(int);
  };
  Integer operator-(const Integer &, const Integer &);

  Integer foo(const Integer &x, int y) {
    return x - (y ? 1 : -1);   // previously omitted parens around operand
                               // of operator-, i.e., "x - (y) ? 1 : (-1)"
  }

8/13/07  GNU compatibility: Multicharacter character literals

In GNU modes, when a multicharacter (narrow) character literal cannot fit in
an int, the front end now discards (with a warning) leading characters until
the remaining characters do fit.  Previously, an error was issued.
For example:

  int x = 'abcdef';  // Literal treated as 'cdef' when sizeof(int) == 4 (with
                     // a warning about leading characters being dropped).

8/13/07  Abort on dependent call to overload set containing using-declaration
         for function in dependent base class

A change made in release 3.9 caused an assertion failure in
any_function_has_dependent_param_or_default_arg in overload.c on
processing a call in a template in a mode that does prototype
instantiations when the overload set contains a using-declaration
that refers to a function in a dependent base class.  Now fixed.

  template <class T> struct Foo {
    int k(float);
  };
  struct Baz {
    int k(int);
  };
  template <class T> struct Bar : public Foo<T> , Baz {
    using Foo<T>::k;
    using Baz::k;
    void foo() {
      k(1.0f);
    }
  };
  int main() {
    Bar<int> bar;
    bar.foo();
  }

8/10/07  GNU C++ compatibility: Attributes before parenthesized initializers

In GNU C++ mode, the front end now accepts attributes appearing just before a
parenthesized initializer.  For example:

  struct S { S(int); };
  S a __attribute((deprecated)) (3);  // Now accepted.

This is accepted for all values of gnu_version even though versions of GCC
prior to 3.4 do not accept such constructs.

Furthermore, attributes are no longer accepted within nested declarators.
For example:

  int (a __attribute((deprecated)));  // No longer accepted.

8/10/07  Abort in find_instantiation_insert_scope with nested class

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE and
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is FALSE (a highly
unusual configuration), the front end sometimes aborted in src_seq.c (function
find_instantiation_insert_scope).  For example:

  template<typename T> struct S;
  template<typename T> struct S {
    struct N { static T n; };
    static int a[sizeof(N)];
  };
  template struct S<char>;

This is now fixed.

8/9/07   C++-generating back end, GNU compatibility: variable attributes and
         initializers

Different versions of g++ have different requirements for the location of
variable attributes with respect to a parenthesized initializer: recent
versions only honor attributes that precede the initializer, while versions
older than 3.4 give a syntax error for attributes in that location.  The
C++-generating back end unconditionally generated such attributes before
the initializer.  It has now been changed to select the location for the
attributes based on the value of gnu_target_version_number.  (That variable
is set to the value of gnu_version in configurations in which
CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT is TRUE and to the value of the
GNU_TARGET_VERSION_NUMBER configuration macro in other configurations.)
For example, the following code is accepted with --gnu_version=30300 and by
g++ version 3.3:

  struct S {
    S(int);
  };
  S s (3) __attribute((__used__));  // Previously generated as
                                    // "S s __attribute__((__used__))(3);"
                                    // with gnu_target_version_number==30300

8/8/07   GNU compatibility: Aliases to undefined entities

Previously, in GNU modes, an alias attribute referring to an entity not
declared in the same translation unit was treated as if the aliased name was
an "asm name".  Now such cases are only accepted when gnu_version < 40000.
Furthermore, aliases for entities that are declared but not defined are
treated in the same way as aliases for entities that are not declared at all.
For example:

  extern int x;  // Declared but not defined.
  extern int y __attribute((alias("x")));
     // Now rejected when gnu_version >= 40000, and treated as
     // "extern int y __asm("x");" when gnu_version < 40000.

Finally, in cases like this attribute "weak" is ignored on the alias, unless
the alias has a "weakref" attribute.  For example:

  extern int z __attribute((weak, alias("z0")));  // Weak attribute ignored.

8/7/07   Template deduction: reference/pointer confusion

In a strange case, template deduction mistakenly concluded that
given a pointer-to-X argument and a reference-to-const-T parameter
T could be deduced to be X.  This doesn't produce a callable
function, obviously, so if the function was selected there would
be an error.  However, in some cases where there is more than one
parameter involved, this confusion could result in a spurious ambiguity.
Now fixed.

  template <typename T0> struct A {
    A();
    template <typename T> A(const T& operand) {
      f(operand, 1L);  // Formerly flagged as ambiguous
    }
    template <typename T> void f(T&, int);
    template <typename U> void f(const A<U>&, long);
  };
  int main() {
    typedef A<int> type_v1;
    type_v1 var1;
    type_v1 var2( &var1 );
  }

8/7/07   GNU C++ compatibility: Class attributes in explicit instantiations

The front end previously ignored (with a warning) attributes specified
between the class, struct, or union keyword and the type name in an explicit
instantiation directive for a class template.  Now such attributes are applied
to the instantiated type.  For example:

  template<typename T> struct S { void f() {} };
  template struct __attribute((visibility("hidden"))) S<int>;
    // The attribute was previously ignored with a warning; now it is
    // applied to the instantiated type.

8/7/07   GNU C++ compatibility: more on dependent name lookup

An additional tweak to the change of 3/12/07 on dependent name lookup
emulation with gnu_version >= 40100: Now, the lookup for nonmember
functions for an overloaded operator case finds declarations after
the point of use even if some member functions were also found.

  namespace NN {
    class A;
    template <typename S>
    struct C {
      static void f (NN::A* p, S const & x) {
        (*p) <<=  x;  // Previously got access error in g++ 4.1 mode
      }
    };
    void foo() {
      C<char>::f(0,1);
    }
    class  A {
    private:
      void operator<<= (unsigned char);
    };
  }
  void operator<<= (NN::A &, int);

8/7/07   IA-64 ABI: Set least significant bit in guard when using ARM EABI
         (affects ARM in big-endian mode)        

The IA-64 ABI uses the first byte of a guard variable to protect one-time
initialization of static data (see section 2.8 of the IA-64 ABI).
The ARM EABI differs in that the least significant bit of the guard variable
is used to protect the one-time initialization (see section 4.4.2 of the ARM
EABI).  Previously, with IA64_ABI_USE_INT_STATIC_INIT_GUARD set to TRUE
(i.e., use ARM EABI semantics for static guards), the front end generated
guard test queried the least significant bit, but set the first byte once the
one-time initialization was finished.  This behavior occurred both when
the front end was responsible for assigning to the guard variable
(IA64_ABI_USE_GUARD_ACQUIRE_RELEASE set to FALSE) as well as when the
runtime library routines (i.e., __cxa_guard_acquire, __cxa_guard_release
and __cxa_guard_abort) made the assignment (IA64_ABI_USE_GUARD_ACQUIRE_RELEASE
set to TRUE).  A change has been made to the front end as well as
to the runtime library to utilize the least significant bit of the guard
variable when IA64_ABI_USE_INT_STATIC_INIT_GUARD is TRUE.  The problem
manifests itself on big-endian architectures where the least significant
bit is not in the first byte of the guard variable.

8/7/07   Needed-flag processing and aliased variables

In GNU modes, when a variable with internal linkage is aliased to a variable
with external linkage, both variables are now marked as needed.  For example:

  static int x = 0;  // Now marked as needed.
  extern int a __attribute((alias("x")));

In addition, the aliased variable is now considered "used", thereby preventing
a spurious warning about it being unused.

Also, static variable aliases are now only accepted when gnu_version >= 40200.
Furthermore, when removal of unneeded entities is enabled, static aliases (for
both routines and variables) are eliminated from the IL if unused.

  static int y = 3;
  static int b __attribute((alias("y")));
      // Only accepted when gnu_version >= 40200, in which case both b and y
      // may be eliminated from the IL (because they are unused).

8/2/07   Microsoft C++ compatibility: Old-style class template specializations

In Microsoft C++ mode, an old-style specialization of a class template is
accepted if it is not a definition.  Such specialization declarations can
appear in namespace scopes, class scopes, and local scopes, and they may
use a qualified name.  For example:

  template<typename T> struct S {};
  int main() {
    struct ::S<int>;  // Now accepted as an old-style specialization.
    S<int> x;         // Error: Incomplete type.
  }

As part of this change, the changes documented in the Changes entry of 4/4/97
have been reverted.

8/2/07   Microsoft compatibility: DLL attributes on qualified declarations

In Microsoft C++ mode DLL attributes appearing on qualified declarations of
ordinary (non-member, non-template) functions are ignored (with a warning)
when they differ from the DLL attributes implied by previous declarations.
Furthermore, if no DLL attributes appear on the qualified declaration of an
entity previously declared with a DLL attribute, no diagnostic is issued
(previously, a warning was emitted).  For example:

  __declspec(dllimport) void f();
  void ::f();                        // Now silently accepted.
  __declspec(dllexport) void ::f();  // Now accepted (with a warning).

8/1/07   GNU compatibility: Attribute warn_unused_result

In GNU modes, the front end now accepts the attribute "warn_unused_result"
on function declarators.  This attribute indicates that the value returned
by a call to a function should be used; a warning is issued if the returned
value is not used.  For example:

  int f() __attribute((warn_unused_result));
  int x = (f(), 3);  // Warning: Result of call to f() is not used.

8/1/07   GNU compatibility, C-generating back end: __stdcall__ attribute

The __stdcall__ function attribute (supported in configurations in which
GNU_X86_ATTRIBUTES_ALLOWED is TRUE and USE_X86_64 is FALSE) was emitted on
the declaration but not the definition of a function in the output of the
C-generating back end when gcc_is_generated_code_target is TRUE.  This
mismatch caused an error when the generated code was compiled.  It has now
been fixed by emitting all function attributes on both the declaration and
the definition of a function.  Because the location at which the attributes
were generated on the declaration (following the complete function
declarator) is not acceptable to gcc in a definition, the location for
these attributes has been changed for both declarations and definitions to
the point immediately preceding the function name.  For example:

  void __attribute__((__stdcall__)) f() { }  // Previously caused an error
                                             // in the generated code

7/31/07  GNU compatibility: __sync_... functions

In GNU modes, the front end now accepts a variety of built-in functions for
atomic memory access when the new configuration macro
GNU_BUILTIN_SYNC_FUNCTIONS_ALLOWED is TRUE.  The list of functions includes
the "generic" functions __sync_fetch_and_add, __sync_fetch_and_sub,
__sync_fetch_and_or, __sync_fetch_and_and, __sync_fetch_and_xor,
__sync_fetch_and_nand, __sync_add_and_fetch, __sync_sub_and_fetch,
__sync_or_and_fetch, __sync_and_and_fetch, __sync_xor_and_fetch,
__sync_nand_and_fetch, __sync_bool_compare_and_swap,
__sync_val_compare_and_swap, __sync_lock_test_and_set, and __sync_lock_release.
When such a routine is called, the first argument must be a pointer to an
integer or enumeration type of size N, where N is 1, 2, 4, or 8.  The actual
call is then resolved to a routine of the same name with the suffix _1, _2, _4,
or _8 according to the value of N.  The functions whose names have the added
suffix are also available as GNU built-in functions.  For example:

  void f(char x) {
    __sync_lock_release(&x);    // Calls "__sync_lock_release_1".
    __sync_lock_release_1(&x);  // Same as above.
  }

Finally, in addition to the functions described above, the front end now also
accepts the GNU built-in function __sync_synchronize.

7/31/07  Add configuration macro for display of error number in diagnostics

A new configuration macro, DEFAULT_DISPLAY_ERROR_NUMBER, has been added
to control the default behavior when displaying error numbers in
diagnostic messages.  Its default value is FALSE.  A new command line
option, --no_display_error_number (which complements the existing
--display_error_number command line option), has been added to suppress
reporting of error numbers in cases where DEFAULT_DISPLAY_ERROR_NUMBER
has been set to TRUE.

7/31/07  IA-64 ABI: set visibility of __dso_handle references to hidden

In configurations using the IA-64 ABI mode, any extern reference to
the __dso_handle symbol that is generated by the front end will now
have its visibility set to hidden in modes that support it
(i.e., when GNU_VISIBILITY_ATTRIBUTE_ALLOWED is TRUE).

7/31/07  IL display for template template parameters incorrect

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, 
the IL display utility displays incorrect values for the class_template
and default_arg_template fields of template template parameters.  This
is now fixed.  The IL displayed for the following example was incorrect:

  template <class T> struct S {};
  template <template <class> class T = S> struct C {};
  
7/30/07  GNU C++ compatibility: Zero-length arrays and zero-sized classes

In GNU C++ mode, class types containing only data members with zero-length
array types have size zero (see Changes entry of 1/12/04).  Now, this is
extended to class types containing only data members with zero-length array
types and/or data members with zero-sized class types.  For example:

	struct X { int a[0]; };       // Previously already zero-sized.
        struct Y { int b[0]; X c; };  // Now also zero-sized.

Note that this is an ABI CHANGE in GNU C++ mode.

7/27/07  Properties of thunks

Various properties of overriding virtual functions are now also recorded for
any thunks created for such functions.  These properties include those
specified by the GNU attributes "section", "visibility", and "weak".

7/27/07  Invalid IL containing template parameters

A use of an explicit template argument list that contains a
type parameter on a reference to a function template, in a mode
that does prototype instantiations of functions (e.g., --strict),
caused the IL to contain a routine entry whose type involved
template parameters.  This is not supposed to occur unless
prototype instantiations are kept in the IL.  Now fixed (the
routine entry is not generated).

  template <class T> void match_table_entry(T);
  template <class T>
  struct C {
    typedef void (*fn_match)(int);
    void foo() {
      (fn_match) &match_table_entry<T>;
    }
  };
  int main() {
    C<int> p;
    p.foo();
  }

7/26/07  Abort in C++-generating back end on parenthesized initializer
         containing a compound literal

In GNU C++ mode, the C++-generating back end sometimes aborted with an
internal error ("gen_dynamic_init: bad nonconst aggr") in routine
gen_dynamic_init (cp_gen_be.c) when a compound literal appeared in a
parenthesized initializer.  For example:

  struct D { D(int); };
  struct S { D d; } s((S){2});  // Previously triggered an internal error.

This is now fixed.

7/25/07  Microsoft uuid attribute

In Microsoft C++ mode, the front end now records the bracketed uuid attribute
(the [uuid(...)] construct) in the IL entry for a class type.  The __uuidof
operator is therefore aware of any uuid strings applied with the bracket-based
uuid attribute syntax.  For example:

  [uuid("00000001-0002-0003-0004-000000000005")] struct S { int i; } s;
  void f() {
    __uuidof(s);  // Previously an error; now accepted.
  }

In addition, the Microsoft uuid attribute is now only recognized in C++ mode
(this matches the behavior of the Microsoft compilers).  Finally, a new
function find_ms_attribute_for_entity is now provided as a convenience to back
ends for finding all Microsoft attributes (specified using the bracket-based
syntax) associated with a nonlocal entity.

7/25/07  Address constant initializers for automatic variables

The front end previously treated cases in which an automatic variable
is initialized with an address constant expression as dynamic
initialization.  If the new configuration macro
FAVOR_CONSTANT_RESULT_FOR_NONSTATIC_INIT is set to TRUE, the front end
will now fold such initializers to constants, potentially allowing
generation of more-efficient code.  (This folding was formerly done
only for initializers of variables with static duration, where it is
required by C initialization rules.  The expressions were not folded
to constants for automatic variables because having them in their
original form allows compilers to do better alias analysis.)  Except
for configurations with BACK_END_IS_CP_GEN_BE, the default value of
FAVOR_CONSTANT_RESULT_FOR_NONSTATIC_INIT is TRUE, which means that
folding will be performed in most configurations unless specifically
overridden.  For instance, in the C-generating back end, an automatic
array could be initialized with an aggregate constant instead of by
assignment to each individual element:

  extern int a[];
  const int *f(int n) {
    const int *const p[] =
      { &a[1], &a[8], &a[5] };   /* Can now be aggregate initialization
                                    instead of three assignments. */
    return p[n];
  }

7/23/07  Extension to template deduction with overloaded function argument

In GNU and Microsoft C++ modes, cases like the following are now
accepted.  Information from previous arguments is allowed to be used
in deduction related to a later argument that is an overloaded function.

  struct A { };
  void f1( unsigned int nUID );
  void f1( char x );
  unsigned int f2();
  template <class RetT, class VarT>
  A& ff(VarT (*p)(), RetT (*q)(VarT));
  static A x = ff( &f2, &f1 );

7/22/07  Object destroyed multiple times when breaks or gotos leave a GNU
         statement expression in g++ emulation mode

In cases where a GNU statement expression contains a break or goto statement
that leaves the scope of the statement expression and the statement
expression is nested within a block within a function scope, the object
lifetime mechanism that is used to track object destructions may have
erroneously emitted multiple destructions for an object.  For example:

  struct S {
    ~S();
  };
  void f() {
    {
      S s;            // Destructor for s mistakenly called twice
      for (;;)
        ({ break; });
    }
  }

This is now fixed.

7/18/07  IA-64 ABI mode abort lowering covariant return types differing only
         in cv-qualification

In IA64_ABI mode, the front end aborted when lowering an overriding virtual
function whose return type differs from that of the overridden function
only by cv-qualification and where the adjustment to "this" involves a
non-zero delta.  This is now fixed.  For example:

  struct Control { };
  struct Iterator { };
  struct Toolbar: virtual Control { };
  struct Matrix {
    virtual const Iterator *getRows() const = 0;
  };
  struct ToolbarMatrix: Toolbar, Matrix {
    virtual Iterator *getRows() const;
  };
  Iterator *ToolbarMatrix::getRows() const {
    return 0;
  }

7/16/07  GNU mode: initialization of zero-sized arrays

In GNU mode, zero-sized arrays (i.e., arrays whose size is explicitly
set to zero) are permitted and may be members of an aggregate
(at any point in the aggregate - not just as the last member).
Zero-sized array members can be statically initialized by specifying
an empty set (i.e., {}).  The front end has been changed to more
closely follow GNU's behavior in cases where a zero-sized array
member is initialized by a non-brace-enclosed initializer in a
static initializer list.  Specifically, in GNU emulation mode,
an empty set initializer is implicitly added to initialize the
zero-sized array member.  For example:

  struct {
    char x;
    int a[0];
    short y;
  } obj = {2,4};    // initializes obj.x to 2 and obj.y to 4 in GNU mode
                    //   (effectively treated as { 2, {}, 4 })

7/13/07  Sun compatibility: Link scope and class types

In Sun mode (a C++ mode), the front end now accepts link scope specifiers on
class types.  Such specifiers are applied to all compiler-generated members of
the class (like virtual function tables and compiler-generated constructors).
For example:

  struct __hidden X { virtual ~X(); };  // Virtual function table will be
  X::~X() {}                            // marked "__hidden".

7/11/07  Incorrect member kind of template reference should be substitution
         failure not error

When the front end is creating a substituted function template parameter
for a type like "U::template X<T>" in the example below, the substitution
of "A" should fail because A::X is not a template.  The substitution
incorrectly succeeded provided A::X was a type, resulting in a spurious error
later.  This has been fixed.

  typedef char (&yes)[1];
  typedef char (&no)[2];

  template<typename T> struct has_X {
    template <typename U> static no test(...);
    template <typename U> static yes test(U*, typename U::template X<T>* = 0);
    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
  };

  struct A { typedef int X; };
  typedef int test_A[!has_X<A>::value];

7/9/07   Spurious "incomplete type" error on nonreal member of an incomplete
         class template

A spurious "incomplete type not allowed" error was issued if a typename
directive naming a nonreal member of an incomplete class template was used
as the return type of a function template.  Now fixed.

  template <typename T> struct A;
  template <typename T> typename A<T>::B::C f(T);

7/9/07   Extra braces in aggregate initializers in C modes

The front end previously diagnosed with a warning or error extra braces around
scalar values appearing inside aggregate (i.e., brace-enclosed) initializers.
A more careful reading of the C standard, however, revealed that an extra pair
of braces is allowed by the standard in such situations.  For example:

  struct S { int i; } s = { { 1 } };  /* Extra level of braces now silently
                                         accepted in C modes. */

Such extra braces are therefore now silently accepted in C modes.

7/9/07   __based and __w64 pointer modifiers sometimes lost

In Microsoft mode, the __based and __w64 pointer modifiers were lost when
any of the __ptr32, __ptr64, __sptr, or __uptr modifiers also appeared.
For example:

  int *p;
  int __based(p) *__ptr64 q = 0;  // IL previously did not record the __based
                                  // modifier.

This is now fixed.

7/7/07   Required white space between macro name and replacement text

In the definition of an object-like macro, C99 and C++0x require that the
replacement text be separated from the macro name by white space.  The
front end previously failed to enforce this requirement in --strict mode.
It now issues an error with --strict in --c99 and --c++0x modes and a
warning in all other modes.  For example:

  #define x3.9    /* Error in strict C99 and C++0x, warning (with "x3" as
                     the macro name, ".9" as the replacement text) in all
                     other modes. */

7/7/07   GNU compatibility: command-line macro definitions without '='

The GNU preprocessor accepts a command-line macro definition of the form
-Dx3.9, taking "x3" as the macro name.  The front end previously issued a
catastrophic command-line error for such definitions; it now accepts them
(with a warning) in g++ and gcc modes.

7/6/07   Right shift token closing an empty template argument list

In C++0x mode (and in some Microsoft modes) a right shift token (>>) may be
interpreted as two closing angle brackets for template argument lists.  The
front end previously failed to apply that rule for empty template argument
lists.  For example:

  template<typename T = int> struct S {};
  S<S<>> x;  // Previously triggered a spurious error in C++0x.

This is now fixed.

7/5/07   GNU C++ compatibility: attribute init_priority on arrays

In GNU C++ mode (and when GNU_INIT_PRIORITY_ATTRIBUTE_ALLOWED is set to TRUE)
the front end now accepts attribute init_priority on declarations of arrays
with class type elements (previously, the attribute was only accepted on
variables of class type).  For example:

  struct S {};
  S a[3] __attribute((init_priority(111)));  // Now accepted in GNU C++ mode.

7/2/07   GNU C++ compatibility: "extern" static data member definition

In GNU C++ mode, the front end now accepts and ignores the "extern" storage
class specifier on the definition of a static data member; a warning is issued
in such cases.  For example:

  struct S { static int x; };
  extern int S::x;  // Now a warning in GNU C++ mode (an error otherwise).

Also, the error position (caret) now points to the actual storage class
specifier (previously it pointed to the declarator).

7/2/07   Initialization of compound literals at file scope and in
         constructor initializers was lost during lowering

The lowering of compound literals results in stmk_init statements
being added to perform temporary initialization.  In certain cases
where this initialization was not being performed within a block
(i.e., at file scope or in a constructor initializer), these statements
were being lost.  This is now fixed.  Here is an example that
demonstrates these two cases:

  struct S { int i; };
  struct T { 
    int i;
    T() : i(((S) { 11 }).i) {};   // initialization was lost
  };
  int s = ((S) { 11 }).i;         // initialization was lost
  int main() {
    return s + T().i;             // return was indeterminate, now 22.
  }

6/27/07  Spurious error on elaborated type specifier after using directive

In some situations involving a typedef with a name identical to that of its
underlying type, a using directive could cause the front end to issue spurious
errors on subsequent elaborated type specifiers.  For example:

  typedef struct S {} S;
  namespace N { using ::S; }
  using namespace N;
  struct S *p;  // Spurious error: 'typedef "S" may not be used in an
                // elaborated type specifier'

This is now fixed.

6/27/07  Suppress spurious "set but never used" diagnostic after error

In some instances, a spurious "set but never used" diagnostic is now
suppressed when the variable in question had errors during its declaration.
For example:

  void func(void*);
  void f() {
    static struct unknown s;  // No more "set but never used" diagnostic on 's'
    func(&s);
  }

6/26/07  Destruction of compound literals in GNU C++ mode

The front end previously failed to call the destructor for certain compound
literals with a destructible type.  For example:

  #include <stdio.h>
  int main() {
    struct S { int i; ~S() { printf("~S\n"); } };
    (S){3};  // Previously the temporary object involved was not destroyed.
  }

This is now fixed.  Note that GNU's g++ compiler does not invoke the
destructor in cases like these (a GNU bug).

6/26/07  Implicit bit field signedness

When a bit field is declared without an explicitly "signed" or "unsigned"
type, its signedness can now be controlled with the new command-line options
--signed_bit_fields and --unsigned_bit_fields.  For example:

  #include <stdio.h>
  struct S { int i: 3; } s = { 7 };  // No explicit signedness.
  int main() {
    printf("%d\n", s.i);  // Outputs 7 with --unsigned_bit_fields; and
  }                       // -1 with --signed_bit_fields.

The default is (still) established by the configuration macro
TARG_PLAIN_INT_BIT_FIELD_IS_UNSIGNED.  The new options have no effect on
1-bit bit fields if the macro TARG_FORCE_ONE_BIT_BIT_FIELD_TO_BE_UNSIGNED
is set to TRUE.

6/25/07  IL display utility: Build error in some configurations

The IL display utility previously failed to build when the configuration
macros TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
GENERATE_SOURCE_SEQUENCE_LISTS were both set to TRUE.  This is now fixed.

6/23/07  New-style casts in template default arguments

The front end incorrectly parsed some template declarations in which a
default template argument contains a new-style cast (static_cast,
const_cast, etc.) and reported spurious syntax errors.  This is now fixed.
For example:

  template<typename T> struct O {
    template<T = static_cast<T>(0)> struct I { };
  };

6/22/07  GNU compatibility: cdecl/stdcall attributes with USE_X86_64

In GNU modes the x86 calling convention attributes cdecl and stdcall are no
longer recognized in configurations where USE_X86_64 is TRUE.  In addition,
when USE_X86_64 is TRUE the C- and C++-generating back ends no longer generate
such attributes when generating code for a GNU compiler.

6/20/07  Abort with built-in macros and FULLY_RESOLVED_MACRO_POSITIONS

In configurations in which FULLY_RESOLVED_MACRO_POSITIONS is TRUE, use of
one of the special built-in macros such as __LINE__ or __FILE__ (where the
expansion must be computed at each use) in the definition of a macro could
result in an abort, depending on the characteristics of the macro definition
and invocation.  This is now fixed.  For example:

  #define M(x) static char *p = x __FILE__;
  M("The current file name is ");

6/20/07  Microsoft compatibility: Double right angle brackets

In Microsoft C++ mode with microsoft_version >= 1400, a right shift token
(">>") not enclosed by parentheses or square brackets is treated as two
closing angle brackets (">") if the right shift token appears after at least
one opening angle bracket ("<") that has not been closed.  This matches the
the C++0x mode behavior (see Changes entry of 5/8/06).

6/20/07  Source file name sometimes optional

When the command-line options --version or --dump_configuration are specified
the front end no longer issues an error if no source file name is specified.
The effect of the front end invocation is then simply to produce the requested
output (version and/or configuration information).

6/20/07  Displaying the as-built configuration

A new command-line option, --dump_configuration, has been added in
configurations in which DEBUG is TRUE.  It displays on the error output
the value of each configuration option with which the executable was built.
The form of the display is a series of #define directives, making the
output suitable for capture and use directly as a defines.h file.  This
output can be helpful when reporting issues to EDG support and for
determining whether two separately-compiled executables were built with
compatible configuration options.

6/19/07  Default settings for GNU_X86_ASM_EXTENSIONS_ALLOWED and
         GNU_X86_ATTRIBUTES_ALLOWED

In configurations with GNU_EXTENSIONS_ALLOWED set to TRUE, the macros
GNU_X86_ASM_EXTENSIONS_ALLOWED and GNU_X86_ATTRIBUTES_ALLOWED are set to TRUE
by default when the front end is build on a system that defines __i386.  Now
these macros are also set to TRUE by default when the build system defines the
macro __x86_64.

6/19/07  Abort in il_to_str.c on __thiscall member function

In Microsoft mode with microsoft_version >= 1400, the front end sometimes
aborted with an internal error in function form_routine_type_attributes
(il_to_str.c).  Specifically, this occurred in the C- or C++-generating back
end when generating code for a GNU compiler (GCC_IS_GENERATED_CODE_TARGET is
TRUE) in configurations that also set GNU_X86_ATTRIBUTES_ALLOWED to TRUE.
For example:

  struct S {
    __thiscall S();  // Could trigger an abort when rendered by the C- or
  };                 // C++-generating back end.
  S::S() {}

This is now fixed.

6/13/07  Lowering and GNU statement expressions

A GNU statement expression returns as its value the value of the
last statement contained within the statement expression.
During lowering, it is possible that an expression statement that is
the last statement of a statement expression may be changed into a block
(which has no value), causing an internal error in some configurations
and intermediate C code that would not compile in others.
A change has been made to further lower such a block into a
statement expression which will return the value of its last statement.
Here is such an example:

  int main() {
    return ({ (int) {5}; });    // Now returns 5 with --gcc
  }

6/12/07  Lowering of compound literal initialization

During lowering, the constant portion of a compound literal initialization
is moved to the declaration of the temporary variable.  This can cause
problems when the statement containing the compound literal is re-executed.
A change was made to perform the compound literal initialization each
time the statement containing the compound literal is executed.
This change affects only the C generating back end.  This example
demonstrates the problem:

  int main() {
    int ret, i = 0;
  again:
    ret = ++(int[]) {0}[0];
    if (i++ < 2) goto again;
    return ret;             // previously returned 3, now returns 1
  }

6/12/07  Undefined behavior when using generated assignment operator
         and "bool" is not a keyword

The Changes entry of 10/11/06 describes changing the result
type of the loop termination test in a generated assignment operator
from "int" to "bool".  In cases where "bool" is not a keyword (e.g.,
cfront mode) this change can lead to a segmentation violation.
This has now been fixed.  This example demonstrates the behavior
when compiled with the --cfront_2.1 command line argument:

  struct C {
    C &operator=(const C &);
    int i;
  };

  class D {
    C c[2];
  };

  void copy() {
    D a, b;
    a = b;      // caused a segmentation violation with --cfront_2.1
  }

6/8/07   Explicit eok_indirect operations with EXPR_RANGE_MODIFIERS_IN_IL

As noted in the Changes entry of 8/14/06, a unary * generally does not
result in the creation of a new expression node but simply changes the
interpretation of an existing node from a pointer rvalue to an lvalue
designating the target of that pointer.  In configurations in which
EXPR_RANGE_MODIFIERS_IN_IL is TRUE, the presence of the unary * is recorded
by adding an erm_asterisk modifier to the existing node.  In many cases,
however, an lvalue node is used in a context requiring an rvalue, resulting
in the generation of an explicit eok_indirect node to convert the lvalue to
an rvalue.  In cases where the immediate operand of an eok_indirect node is
a node into which a unary * has been subsumed, the expr_range and
operator_position of the eok_indirect node are now taken from the
erm_asterisk range modifier in the operand and the erm_asterisk is removed,
so that the eok_indirect represents the unary * in the IL.  (In cases where
the node containing the erm_asterisk modifier is not the immediate operand
of the eok_indirect node, the eok_indirect node now has no expr_range or
operator_position, to reduce the potential for confusion, and the
erm_asterisk modifier is left unchanged.)  For example:

  bool f(void *p) {
    return !(*(char *)p);   // eok_cast previously had erm_asterisk with
                            // source range for "*(char *)p"; expr_range
                            // of eok_indirect was "(*(char *)p)".  Now
                            // eok_indirect expr_range is "*(char *)p"
                            // and eok_cast has no range modifiers.
  }

6/8/07   Abort on attempt to declare a void parameter list through template
         instantiation

The front end previously often aborted in scan_function_body (func_def.c) when
instantiating a function whose parameter list expanded to a single void
parameter.  For example:

  template<typename T> struct X {
    X(typename T::Z) {}
  };
  struct S { typedef void Z; };
  X<S> x;  // Triggered an abort during the instantiation of the constructor.

This is now fixed, and an error is issued on such cases in all modes.

6/8/07   Performance improvement in #undef processing

The time required to do an #undef can become significant in programs with
a very large number of macros and other entities in the global scope.
A prev_in_scope pointer has been added to the symbol entry to allow symbols
to be removed from the scope list quickly.

6/8/07   Precompiled headers lose some GNU attribute arguments

In GNU modes, the arguments specified for the attributes "alias" and "weakref"
were not recorded in precompiled header (PCH) files.  For example:

  void g();
  void f() __attribute((alias("g")));  // Attribute previously not correctly
                                       // recorded in PCH files.

Using such PCH files could result in generating incorrect code.  This is now
fixed.

6/7/07   Conversion between pointers to functions and pointers to objects
         in C++

The resolution of C++ core language issue 195, adopted in April, 2005,
defines the conversion of a pointer to a function to a pointer to an
object or vice versa as conditionally-supported behavior.  The front end
previously allowed these conversions when the target type is at least as
large as the source type but issued an error in --strict mode.  The
--strict diagnostic has now been eliminated in C++ mode, although it is
still issued in C mode.  For example:

  void (*fp)();
  void *p = (void *)fp;    // Now accepted without complaint in C++
                           // strict mode if sizeof(p) >= sizeof(fp)

6/6/07   Certain using-declarations can result in undefined behavior

A template argument that refers to an overloaded pointer or pointer to member
function declared by a using-declaration can result in a segmentation
violation or assertion failure.  This is now fixed.  The following
example triggered such an error:

  struct B {
    void fn() {}
    void fn(int) {}
  };
  struct D : public B {
    using B::fn;            // caused segmentation violation/abort
  };
  template <void(B::*)()> struct Bp { typedef void t; };
  template <void(D::*)()> struct Dp { typedef void t; };
  template <typename T> typename Bp<&T::fn>::t f() {}
  template <typename T> typename Dp<&T::fn>::t f() {}

  int main() {
    f<D>();
  }

6/6/07   Issue overflow diagnostic when sign changes during integer
         conversions that happen during lowering

During lowering, an overflow diagnostic is now issued when a sign change
is detected during certain internal integer to integer conversions.
In particular, conversions related to the delta field in pointer to virtual
member functions are now checked for a sign change as in this example:

  struct Test {
    char LargeData[0x7ff8];
    virtual void vfunct();
    void (Test::*vtfp)();
    void test() {
      vtfp = &Test::vfunct;     // overflow diagnostic now issued here in
                                // Cfront ABI mode when TARG_DELTA_INT_KIND
                                // is ik_short
    }
  };

6/4/07   C-generating back end: typedefs referring to arrays of incomplete
         type

A typedef naming an instance of a template does not cause that template to
be instantiated, so if the typedef appears before the point of
instantiation, it will refer in the output of the C-generating back end to
an incomplete struct type.  If the typedef involves an array of that
template instance, the generated C code was incorrect, because it is not
permitted to declare a type that is an array of an incomplete struct type.
(Note that C and C++ differ in this regard.  C++ allows formation of a type
that is an array of incomplete class type, as long as the array type is not
used in a way that requires knowledge of the element size before the class
type is completed.  In C, however, an incomplete struct type is not an
object type, and only object types can be used as the element type of an
array.)  This has now been fixed by deferring the emission of such typedefs
until after the definition of the generated struct.  For example:

  template<typename T> struct A { T *i; };
  typedef A<void> T[3];   // typedef previously emitted before the
                          // definition of the struct generated for A<void>,
                          // now emitted immediately following it
  T xx;

6/1/07   Position of diagnostic for unterminated type definitions

When the definition of a class type or enum type is missing a terminating
semicolon, the resulting syntax error is always issued on a token following
the type definition.  This can be surprising when the latter token appears in
a source file that is different from the file containing the type definition.
To mitigate that surprise, a warning is now issued when the last token of a
type definition (usually the closing brace) is the last token of a file.
For example:

  // f.h:
  struct S {}  // A warning is now issued here.

  // f.c:
  #include "f.h"
  S *f();  // The syntax error (missing semicolon) is still issued here.

5/30/07  GNU compatibility: ending source position of statement expressions

In configurations in which EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the ending
position of a statement expression was incorrect, extending through the
position of the token following the terminating parenthesis.  This has now
been fixed.  For example:

  void f (int i) {
    while ( ({i--;}) )   // The ending position of the statement expression
                         // previously designated the second ')', now the '}'
      ;
   }

5/29/07  Microsoft compatibility: ending source position of expressions
         involving property references

In configurations in which EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the ending
position of an expression whose last subexpression is a property reference
was incorrect, extending through the position of the following token.  This
has now been fixed.  For example:

  struct S {
    __declspec(property(get=GetCount)) int Count;
    int GetCount();
  };

  int f(S *p, int x) {
    return x + p->Count;  // The ending position of the return expression
                          // previously designated the ';', now the 't'
  }

5/29/07  Lowering of VLAs in parameter declarations

In C99 and GNU C modes, variable-length arrays (VLAs) can appear in parameter
declarations.  For example:

  int f(int (*p)[*]);  // Array type lowered to plain pointer type.

IL lowering replaces such VLA types by pointers to the underlying element type.
However, a block-extern declaration of the same parameter may not involve a
corresponding VLA type, and that type (which is used in the IL tree of the call
expression) would therefore not be lowered.  For example:

  int main() {
    int a[10][5] = { 0 };
    int f(int (*a)[5]);  // Array type remains in lowered call tree.
    f(a);
  }

The C-generating back end previously handled the resulting type incompatibility
by inserting a cast at the call site on the function's address.  Unfortunately,
such C constructs technically have "undefined behavior" and some newer C
compilers (notably GCC 4.x) now trap such calls at run time.  To avoid the
problem, the non-VLA-based parameter type is now eliminated from the call's
expression tree during lowering in such cases.

5/22/07  Microsoft compatibility: __sptr/__uptr pointer modifiers

In Microsoft modes, the front end now accepts the pointer modifiers __sptr and
__uptr to indicate that a pointer is to be treated as a signed or unsigned
address, respectively.  Pointers are considered "implicitly signed" when
neither modifier is present.  Widening conversions of signed pointers involve
sign extension (which is usually surprising): The front end therefore issues a
remark when converting an implicitly signed 32-bit pointer to a signed 64-bit
pointer.  For example:

  int *p1;
  int *__ptr64 p2 = p1;  // Now triggers a remark (conversion involves sign
                         // extension).

Some minor changes were also made to the IL representation of __ptr32 and
__ptr64 for pointer and pointer-to-member types (IL CHANGE).

In addition, the acceptance of both the __ptr32/__ptr64 and the __sptr/__uptr
features (in Microsoft modes) is now determined by the global variable
microsoft_64bit_pointer_extensions_enabled, which is initialized by the macro
DEFAULT_MICROSOFT_64BIT_POINTER_EXTENSIONS_ENABLED (TRUE by default if
MICROSOFT_EXTENSIONS_ALLOWED is TRUE).

5/22/07  Uninitialized local variable in enum_specifier

The local variable "err" in enum_specifier (file decl_spec.c) was sometimes
passed to set_enum_representation without being initialized.  Although the
variable was not used in set_enum_representation in such cases, it triggered
a run-time abort when compiled with tools that verify that all arguments to a
function call have been initialized.  This is now fixed (the variable is
always initialized). 

5/17/07  Missing base/derived class conversion when operand of cast
         or implicit conversion is a dynamic_cast to a reference type

In cases where a dynamic_cast to a reference type is further cast 
or implicitly converted to a derived or base class pointer or reference,
the derived or base class conversion is mistakenly replaced with
an ordinary cast.  For example:

  struct B {
    virtual ~B() {}
  };
  struct C {
    virtual ~C() {}
  };
  struct D : public virtual B, public virtual C {
    virtual ~D() {}
  };
  void f() {
    D d;
    C &rc = d;
    B *b = &dynamic_cast<D&>(rc);   // had produced an ordinary cast from D*
                                    // to B*, now performs a base class
                                    // conversion
  }
  
5/16/07  GNU compatibility: Attribute "nothrow"

In GNU C and C++ modes, the front end now accepts attribute "nothrow" on
function and member function declarations.  This is an assertion by the
programmer that the function will not throw an exception; the front end does
not check that assertion, nor is the assertion checked at run time (this
matches the GNU behavior and makes this feature different from the standard
"throw()" specification).  For example:

  __attribute((nothrow)) void f() {  // Now accepted in GNU modes.
    throw 3;    // Violates the attribute's claim, but not diagnosed by the
  }             // front end and not caught at run time.

5/15/07  Incorrect matching of symbolic asm operands in GNU modes

In GNU modes, an extended asm construct like

  __asm("mov %[p], %[q]" : [q]"=m"(y) : [px]"r"(x));

caused the front end to erroneously associate the reference to a symbolic
operand [p] with the actual operand [px] because they share a common prefix.
This is now fixed: Cases such as the example above are diagnosed with an
error.

5/14/07  GNU compatibility: Attribute "cleanup"

In GNU C mode, the front end now accepts and records attribute "cleanup" on
local variables with automatic storage duration (except parameters).  The
attribute specifies that a given function should be called when a variable
goes out of scope (much like a destructor); note however that the front end
does not insert a call to the cleanup function in the IL.  For example:

  void f(int *p);
  void g() {
    int x __attribute((cleanup(f)));  // Now accepted in GNU C mode.
  }                                   // No call to "f" is inserted.

The attribute is currently not accepted in GNU C++ mode (because the behavior
of current and past versions of g++ is unclear for this attribute).

5/14/07  Inlining destructors in IA-64 ABI configuration with
         IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS results in errors

When the front end is using the IA-64 ABI and is configured with the macro
IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS set to TRUE and
destructors are inlined during lowering, these destructors mistakenly
return zero rather than the value of 'this'.  This can cause a value of
zero to be passed to operator delete after the destructor has been invoked,
resulting in a memory leak.  For example:

  int destruc_counter = 0;
  int is_zero = 0;
  struct C {
    ~C(){ destruc_counter++;}
    void operator delete(void *vp) 
      { is_zero = (vp == (void*)0); }  // is_zero was TRUE, now FALSE
  };
  int main(void) {
    C* cp = new C();
    delete cp;                  // destructor invocation is inlined if possible
    return is_zero;
  }

5/12/07  C++-generating back end: missing qualifier on name in class from
         containing namespace

Under some circumstances, the C++-generating back end failed to qualify a
name from the containing namespace appearing in a class when that name is
hidden by a name declared in the class.  This is now fixed.  For example:

  namespace A {
    typedef int T;
    template <class C> struct deriv;
    struct base {
      typedef A::T T;    // Previously generated as "typedef T T;"
    };
    template<class C>  struct deriv : public base  { };
  }

5/11/07  GNU compatibility: Attributes "noinline" and "always_inline"

In GNU modes, the front end now accepts the attributes "noinline" and
"always_inline" on function declarations.  The attribute "noinline" indicates
that calls to the attributed function should never be inlined.  Conversely,
the attribute "always_inline" is an indication that the code generator should
attempt to inline calls to the function even at the lowest levels of
optimization.  For example:

  __attribute__((noinline)) void f() {}
  __attribute__((always_inline)) void g() {}
  int main() {
    f();  // Call should never be inlined.
    g();  // Call should be inlined at all levels of optimization.
  }

Attribute "always_inline" implies that the function is "inline", whereas
"noinline" implies that it is not "inline".  The simple inliner included in
the front end does not treat functions marked with either of these new
attribute differently from other functions (in particular, since calls to
non-inline functions are never inlined by the simple inliner, calls to
"noinline" functions will never be inlined either).

5/11/07  Microsoft compatibility: suppression of implicitly-declared special
         member functions

When the Microsoft compiler determines that an implicitly-declared copy
constructor, copy assignment operator, or destructor could not be implicitly
defined because of access errors and the like, it does not declare the
member function in the class.  This allows overload resolution to select
a different constructor or assignment operator for a copy and prevents
errors if a destructor is not actually used.  The front end now emulates
this behavior in --microsoft mode.  For example:

  struct S {
    S();
    template <typename T> S& operator=(const T&) {
      return *this;
    }
    int &ir;    // reference member would cause error defining implicit
                // operator=, so do not declare it
  };
  S s;
  void f() {
    s = S();    // No error, uses template operator= to copy
  }

5/10/07  GNU compatibility: Attribute "nonnull"

In GNU modes, the front end now accepts attribute "nonnull".  If followed by
a list of parameter numbers, the corresponding parameters must be pointers
and passing a null pointer constant through them triggers a remark.  If the
attribute is not followed by a list of parameter numbers, passing a null
pointer constant to any pointer parameter triggers the remark.  For example:

  void f1(void *p, void *q, void *r) __attribute((nonnull(1, 3)));
  void f2(int n, void *p, void *q) __attribute((nonnull));
  int main() {
    f1(0, 0, 0);  // Remark on first and third argument.
    f2(0, 0, 0);  // Remark on second and third argument.
  }

5/10/07  Expressions in VLA dimension are now always scanned as evaluated

In some cases (e.g., when used as the operator to sizeof), an expression
used to declare the size of a variable-length array (VLA) is scanned
as though the expression will never be evaluated.  This can result in
inconsistencies such as variables and routines whose only use is in
the expression not being properly marked as referenced in the IL.  It can
also result in a failure to destroy temporary variables created during
the expression.  A change has been made to scan VLA dimension expressions as
though they will be evaluated in all cases.  In the following example
the function f5 was being marked as neither referenced nor called in the IL:

  int f5();
  int main() {
    return sizeof(int [f5()]);   // f5 is now marked as referenced and called
  }


5/8/07   Build errors with USER_CONTROL_OF_STRUCT_PACKING set to FALSE

Some code in cp_gen_be.c and attribute.c that should have been conditional
on USER_CONTROL_OF_STRUCT_PACKING was unprotected, resulting in build
errors.  This has now been fixed.

5/3/07   Overload resolution in generated copy assignment operators

The C++ Standard says that assignment operators that are not copy assignment
operators will be selected by overload resolution for a copy operation if
they are a better match for the object being copied.  The front end correctly
implemented this specification for explicit copy assignment; however, in a
generated copy assignment operator, only copy assignment operators were
considered for the memberwise copying of base and member subobjects.  This
has now been fixed, and full overload resolution is performed when copying
base and member subobjects.  For example:

struct B1 {
  B1& operator=(B1&);
};
struct B2 {
  B2& operator=(const B2&);
  template <typename T> B2& operator=(T&);
};
struct D {
  B1 b1;
  B2 b2;
  // D& operator=(D&) implicitly declared, with non-const reference parameter
  // because of non-const reference parameter in B1::operator=(B1&)
};

void f() {
  D d1, d2;
  d1 = d2;   // Previously called B2::operator=(const B2&), now correctly
             // calls template instance B2::operator=(B2&) to copy D::b2
}

5/3/07   Microsoft compatibility: conversion for direct reference binding

The previous change in the area of Microsoft compatibility and conversions
for direct reference binding (see entry of 11/2/06) has been tweaked a bit
further to avoid an internal error when two different instances of the
same template are selected as the ambiguous alternatives.

  int i;
  struct A {
    template<class T> operator T&() {
      return i;
    }
  };
  int main() {
    A a;
    int n = (const int &)a;  // Now not ambiguous again in Microsoft mode,
                             // no internal error
  }

5/1/07   Source position on generated stmk_goto statement

The general rule of thumb is that compiler-generated statements
should have their start source positions (and end positions when
EXTRA_SOURCE_POSITIONS_IN_IL is TRUE) set to a null position.  The source
position was incorrectly set on a stmk_goto statement generated
when a label appears inside a structured statement nested within
a switch statement.  The source position(s) in the stmk_goto statement
are now set to null positions.  For example:

  void f(int n) {
    switch (n) {
      case 0: { n = 0; case 7: n = 1;   }
    }
  }

5/1/07   Microsoft compatibility: comments created via macro expansion

The change described in the 11/29/06 entry introduced a bug that caused
an infinite loop when generating preprocessing output for certain kinds
of these constructs.  This is now fixed.  For example:

  #define COMMENT SLASH(/)
  #define SLASH(s) /##s
  COMMENT i=3;     // Previously caused an infinite loop with -E

4/30/07  Incorrect type for argument to __array_new and __array_new_zero
         runtime routines in the Cfront-like ABI

While investigating the change listed below it was discovered that the
first argument to the Cfront-like ABI routines __array_new and
__array_new_zero was being passed as type size_t while the parameter
(i.e., number_of_elements) was declared as type int.  The discrepancy
has been resolved.  If PASS_ELEM_COUNT_TO_RUNTIME_AS_PTRDIFF_T is TRUE,
both are now type ptrdiff_t, otherwise int as described below.

4/30/07  Type of argument passed to Cfront-like ABI runtime routines for
         number of elements

Historically the type of the argument passed to the Cfront-like ABI
runtime routes to represent the number of elements in an array
(i.e., number_of_elements) is int.  In some configurations it
may be desirable to allow this type to be ptrdiff_t.  A change has
been made to the front end and runtime library to accommodate this.
A new configuration macro, PASS_ELEM_COUNT_TO_RUNTIME_AS_PTRDIFF_T,
when set to TRUE will cause the front end to pass the number of
elements argument as ptrdiff_t and the runtime library to expect
the parameter as ptrdiff_t.  The default value for the macro is TRUE.
The old behavior can be obtained by setting
PASS_ELEM_COUNT_TO_RUNTIME_AS_PTRDIFF_T to FALSE.
PASS_ELEM_COUNT_TO_RUNTIME_AS_PTRDIFF_T can only be set to TRUE when
ABI_COMPATIBILITY_VERSION >= 310.  The IA-64 ABI is unchanged.

4/25/07  Undefined virtual functions in unnamed namespaces

The front end previously always issued a discretionary error when a virtual
function is declared in an unnamed namespace but not defined in the same
translation unit.  Now that diagnostic is weakened to a remark in nonstrict
modes if the class enclosing such a virtual function is not actually
referenced.

4/25/07  Improved performance when lowering large arrays that use
         designated initializers

The performance of the front end when lowering large arrays that
use designated initializers can be poor.  One common case that arises
(e.g., in the source code for glibc) is the case where monotonically
increasing designated initializers are used to initialize a large
array.  The lowering algorithm has been modified to perform better
in this case.

4/25/07  GNU compatibility: Spurious error on elaborated qualified name

In GNU C++ mode with gnu_version < 30400, the front end sometimes issued a
spurious ambiguity error on elaborated qualified names.  For example:

  namespace N { class S {}; }
  using namespace N;
  struct S {};
  struct ::S *p;  // Previously triggered a spurious error in some GNU modes.

This is now fixed.

4/24/07  GNU compatibility: Types of some built-in functions

The types of the following built-in GNU functions have been adjusted:
__builtin_strfmon, __builtin_strlen, __builtin_strncat, __builtin_strncmp,
__builtin_strncpy, __builtin_strspn, and __builtin_vsnprintf.  The adjustment
amount to replacing certain uses of type "unsigned" by "size_t", and certain
uses of type "int" by "ssize_t".  Type "ssize_t" is a signed integer type
specified by POSIX to declare certain I/O functions; it can be configured with
the new macro TARG_SSIZE_T_INT_KIND (and is equivalent to "ptrdiff_t" by
default).

4/24/07  Abort in end_mangling with --implicit_include

The front end sometimes aborted with an internal error in routine
"end_mangling" in lower_name.c ("wrong nunber of leftover spaces"; note the
misspelling of "number" which is now fixed) after processing an implicitly-
included source file.  This is now fixed.  (The underlying problem was that
placeholder entries on the file scope's "routines" list had not yet been
replaced by routines scheduled to be moved to the placeholders' position.
Attempting to mangle the placeholder entries triggered the abort.)

4/11/07  GNU compatibility: "extern template" in the IA64 ABI

The change described in the 3/15/07 entry caused a problem in the IA64 ABI
which is manifested in the output of the C-generating back end when
gcc_is_generated_code_target is true: the definition of an instantiated
inline function was marked with "__attribute__((__weak__))", causing an
execution-time failure instead of a link-time error if the function is
called.  The reason for this was that the instantiated function was
incorrectly placed into a COMDAT group, which is simulated in GCC output by
use of the "weak" attribute.  Inline function template instances that are
the subject of an "extern template" directive are no longer placed into
COMDAT groups, which resolves the problem.  For example, in the following
case the definition of foo<char>(char) is no longer marked as "weak" in the
generated code:

  template <typename T> inline int foo(T) {
    return 0;
  }
  extern template int foo(char);
  void f() {
    foo('c');
  }

4/10/07  Abort in inlining in GNU C mode with "if" with empty dependent
         statement

Inlining aborted on processing an "if" with an empty dependent statement
in gcc mode when the calling context is an expression (rather than a
top-level statement) context.  Now fixed.

  inline int f(int x) {
    if (x);
    return 0;
  }
  int g(int x) {
    return f(x);
  }

4/9/07   Bad pointer in IL after inlining, RECORD_CONSTANT_EXPRESSIONS_IN_IL

In configurations that do IL lowering and inlining and also have
RECORD_CONSTANT_EXPRESSIONS_IN_IL set to TRUE, the inlining of a function
call could copy a constant that has a pointer to an associated
expression in the original function memory region.  As a consequence,
the destination constant contained an invalid pointer between function
memory regions.  The pointer is now cleared on the copy.

  inline void f() {
    const int i = 1;
    int j = i + 1;
  }
  int main() {
    f();
  }

4/5/07   Option to warn about the use of some GNU extensions

The new option --report_gnu_extensions causes the front end to issue warnings
on the use of certain GNU extensions outside of system headers.  For example:

  int x[0];  // Warning with --gcc --report_gnu_extensions: zero-length arrays
             // are a GNU extension.

The new option is valid only in GNU modes and is not meant to be exhaustive
(i.e., not all GNU extensions are reported).  When the option is enabled,
features that are standard in C99 mode are warned about in plain GNU C mode,
but not in GNU C99 mode.  Extensions warned about include: variable-length
arrays, designated initializers, compound literals, statement expressions, GNU
attributes, extended uses of the "asm" keyword, restricted pointers, typeof,
integer sign and size specifiers on typedefs, zero-length arrays, and flexible
array members.

4/5/07   Improve setting of is_partially_initialized in a_variable

Three refinements have been made in setting the is_partially_initialized
field in the a_variable structure of the IL when initializing
array or class aggregates.

If designators are used in an initializer, the front end
cannot always determine if the initializer fully initializes the array
or class aggregate.  The front end now conservatively sets
is_partially_initialized to TRUE in this case (i.e., whenever a
designated initializer is used in an initialization).

If LOWER_DESIGNATED_INITIALIZERS is TRUE, lowered variables that
were originally flagged as being partially initialized (e.g., as
a result of the change listed above) are re-analyzed to see if
the lowering process has resulted in a fully initialized variable.
If the result is a fully initialized variable the is_partially_initialized
flag is set to FALSE.

Initializing an array of known size with a string literal that contains
fewer elements than the array should result in setting the
is_partially_initialized flag to TRUE.  In one particular case (i.e.,
a variable that has a static lifetime in GNU mode and whose initializer is
not enclosed in braces) the flag was inadvertently set to FALSE.
This has been fixed.  For example:

  char hello[10] = "hello";  // is_partially_initialized set to TRUE
                             // now in GNU mode

4/2/07   IA-64 ABI: unneeded virtual function tables emitted sometimes

IL lowering in the IA-64 ABI mode emitted unreferenced virtual function
tables for a class that has no key function and requires construction
vtables (which means it has a virtual base class and virtual functions).
Now, such virtual function tables (and associated typeinfo variables,
etc.) are emitted only when referenced.

  struct base {
    virtual ~base() {}
    virtual void foo() = 0;
  };
  struct derived : virtual public base {
    virtual ~derived() {}
  };

4/2/07   C++-generating back end: casts to pointers to unnamed types in the
         operands of ?: in C mode

In C mode, when the operands of a conditional operator involved casts to a
pointer to an unnamed type via a typedef, the C++-generating back end
generated the casts using an undeclared temporary name.  This is now fixed;
the generated code retains the original typedef in the casts.  For example:

  typedef struct {
    int i;
  } S;

  void f(int b, void* vp) {
    S* sp;
    sp = (b) ? (S*) vp : (S*) vp;  /* Casts formerly generated as
                                      "(struct __T9414192 *)vp" */
  }

3/30/07  Overloaded function as argument to template

Overload resolution has been changed to handle the case where an
overloaded function is passed as an argument to a template function
more in accordance with the C++ standard.  If more than one
instance of the function can be made to match the corresponding
function parameter, the parameter is now treated as a nondeduced
context, which allows the ambiguity to be resolved, if possible,
by use of template parameters deduced from the other arguments.

  template< typename Arg > void foo(Arg, void (*pf)(Arg));
  class B {};
  class A {};
  void g(B);
  void g(A);
  int main() {
    foo(B(), &g);  // Now accepted without error
  }

3/30/07  GNU C++ compatibility: static_cast preserves an lvalue sometimes

GNU C++ mode for gnu_version <= 30400 now treats a static_cast of
an integral or enum lvalue to an integral or enum type of the same size
as an lvalue cast, i.e., the result is still an lvalue.

  enum T { ONE, TWO };
  int main() {
    for (T type = ONE; type < TWO; (static_cast<int>(type))++) {}
  }

This was already allowed when written as an old-style or functional-notation
cast.

3/30/07  GNU __extension__ and class members

The front end now records the presence of the GNU __extension__ keyword on
declarations of fields, static data members, and (static and nonstatic) member
functions.  This allows the C++-generating back end to render the keyword on
such entity declarations.  For example:

  struct S {
    __extension__ int i;  // "__extension__" is now rendered by the C++-
  };                      // generating back end.

3/29/07  GNU C compatibility: asm name on redeclaration after definition

In GNU C mode (but not in GNU C++ mode), when redeclaring a function or
variable after a definition of the function or variable was already seen, the
front end now ignores the asm name (with a warning if the asm construct is
different from that on the definition).  For example:

  void f() {}
  void f() __asm("g");  // Now ignored with a warning in GNU C mode.

The front end implements this new behavior for all values of gnu_version even
though it matches the behavior of gcc 4.0.0 and later only.  Prior versions of
gcc behaved as follows:
  - for variables, the construct was also ignored, but with no warning.
  - for functions, the construct only affected subsequent references to the
    affected function (which usually resulted in linker errors). 

3/28/07  Microsoft and Sun compatibility: Class template redeclarations

In Microsoft bugs mode the front end previously always accepted invalid class
template redeclarations that omit the "template <...>" preamble.  For example:

  template<class T> struct S;
  struct S;  // Previously accepted in all Microsoft bugs modes.  Now accepted
             // in Microsoft bugs mode with microsoft_version < 1400, and also
             // in Sun mode.

Now such invalid constructs are accepted in Microsoft bugs mode only when
microsoft_version < 1400.  Furthermore, such constructs are now also accepted
in Sun mode.

3/27/07  Microsoft compatibility: __declspec(noalias) and __declspec(restrict)

In Microsoft C and C++ modes, with microsoft_version >= 1400, the front end
now accepts the __declspec(noalias) and __declspec(restrict) hints on function
declarations.  __declspec(noalias) indicates that the marked function will
only read/write its own local variables and/or the objects directly pointed to
by its parameters (if any).  __declspec(restrict) can only be applied to
functions returning a pointer type: It indicates that the object pointed to by
the return value is not aliased.  These modifiers may be useful hints for an
optimizer, but the programmer is responsible for their correctness: They are
not checked by the front end.  For example:

  int i, *p = &i;
  __declspec(restrict) void f() {  // Now accepted in some Microsoft modes.
    return &i;                     // i is aliased by *p: the __declspec hint
  }                                // is therefore invalid, but the front end
                                   // does not diagnose such violations.

------------------------------------------------------------------------------
Version 3.9, March 23, 2007

3/22/07  IL version number changed to 3.9

3/20/07  Microsoft compatibility: abort on __if_exists following __pragma

An abort could occur (in scan_template_argument_list) if a class template
contains a Microsoft __pragma operator followed by an __if_exists that
references the template that is in the process of being defined.  Now fixed.

  template <class T> struct A {
    void f() {
      __pragma(diag_warning=1234)
      __if_exists(A<T>::g) { }
    }
  };

3/20/07  C++-generating back end: Microsoft compatibility for default
         arguments of member functions

The changes described in the 1/26/07 and 4/13/05 entries work around a bug
in MSVC++ 6.0 regarding default arguments in member function declarations.
However, constructor declarations are not affected by this bug; in fact,
a separate bug causes MSVC++ to reject constructors declared using the
workaround described in these entries.  The C++-generating back end has
now been changed to apply the workaround only to non-constructor member
functions.

3/20/07  Include guard optimization for "#if !defined(X)" tests

Formerly, the front end would only suppress redundant includes of files
for which the guard test was written using an #ifndef or #ifdef.  The
optimization is now also done for guard tests written as "#if !defined(X)"
or "#if defined(X)".  In order for the optimization to be done, the #if
must exactly match one of the patterns described above.   White space is
permitted but comments are not.

  file t.c:

  #include "t.h"
  #include "t.h"

  file t.h:

  #if !defined(__T_H__)
  #define __T_H__ 1
  // ...
  #endif /* ! __T_H__ */

3/20/07  C-generating back end, GNU compatibility: alignment of function
         addresses

On some architectures, gcc does not enforce any alignment requirements on
the address of functions.  This conflicts with the IA64 ABI representation
of pointers to members, which uses the low-order bit of the function
address as a flag.  In configurations with gcc_is_generated_code_target and
IA64_ABI set to TRUE, the C-generating back end has been changed to add
explicit two-byte alignment to the definition of nonstatic member functions
in order to avoid this conflict.

3/20/07   Improved indication of definition status of static data members
          in anachronisms mode with the IA-64 ABI

In anachronisms mode, static data members do not require a definition
in the source.  This is implemented by representing such static data
members in the IL as tentative definitions, which in many implementations
will produce object code that will allow the linker to merge the multiple
instances.  In the IA-64 ABI, there is a more explicit way of indicating
the desired behavior, i.e., by placing the static data member in a COMDAT,
so IL lowering has now been changed to do so.  For example:

  struct S {
    static int i;           // Now placed in a COMDAT when IA64_ABI is TRUE
    static const int j = 1; // Now placed in a COMDAT when IA64_ABI is TRUE
  };

3/19/07  Virtual function tables in IA64 ABI mode with extern template
         directives

During lowering, the definition of a virtual function table for a class
(or class template) is placed in the translation unit where its key function
is defined.  If no key function exists in the class (or class template)
and no applicable command line option is specified (i.e., --force_vtbl or
--suppress_vtbl) a new check is made, only in IA64_ABI mode, to see if the
class template is explicitly not instantiated (i.e, "extern template" or
"#pragma do_not_instantiate").  If so, the virtual function table is
suppressed; otherwise the virtual function table is emitted.  For example:

  template <class T> struct foo {
     inline virtual int bar(int x);
  };
  template <class T> int foo<T>::bar(int x) { return x; }
  foo<int> f;
  extern template class foo<int>;  // Virtual function table now suppressed
                                   // in IA64_ABI mode.

3/19/07  C++-generating back end: calling an overloaded static member
         function for a class member

When an overloaded static member function is called using a "." member
selection operator whose left operand is itself a class member, the
C++-generating back end changed the form of the reference from m.f() to
(&m)->f() in the generated code.  This could cause problems with an
overloaded operator& in the class type of "m".  This has been changed to
retain the "." form.  For example:

  struct S {
    static void f(int);
    void f();
    void* operator&();
  };
  struct A {
    S s;
    void g() {
      s.f(0);    // Previously generated as ((&(this->s))->f(0)),
                 // incorrectly invoking S::operator&()
    }
  };

3/19/07  Microsoft compatibility: PCH issues on Windows Vista

The address space layout randomization (ASLR) feature of Windows Vista causes
problems with our precompiled header mechanism.  To work around this problem
the defines.h.win32 file has been modified to use a fixed address for the
memory that is mapped for PCH purposes.

3/16/07  More predictable "module id" in some mangled names

The point at which name mangling for virtual function table names is
done during IL lowering has been pushed somewhat later so that the
determination of the "module id" (used in some names that have to be
made unique across a whole program) is always done after all
file-scope externals are known (the name of one of them is used as
part of the module id).  That gives more predictable mangled names
for cases that involve, for example, unnamed namespaces:

  namespace {
    struct S { virtual void f() {} } s; // Name of f uses module id
    void g() {}
  }
  void (*fp)() = g;  // Module id now based on this

3/16/07  GNU mode abort on designator for anonymous union member

In GNU modes, the front end could abort in decl_inits.c (in routine
"add_field_designator_for_anonymous_union") when processing a designator
referring to an anonymous union field for a variable declared with a
typedef type or with a qualified type.  Both the standard field designator
syntax (".x =") and the GNU variant of that syntax ("x:") were affected.
For example:

  struct S { union { int i; }; };
  S const s = { i: 3; };  // Previously triggered an abort in decl_inits.c
                          // in GNU C++ mode.

This problem also could appear in GNU C mode with nonstandard anonymous
union constructs.  This is now fixed.

3/16/07  C++0x: Relaxed rules for disambiguation using "template" keyword

Core issue 468 relaxes the rules for the use of the "template" keyword
for syntactic disambiguation.  Formerly, such use was only allowed in
template contexts, but is now also allowed outside of templates.  A diagnostic
is still issued in strict C++98 mode.  It is accepted without a diagnostic
in all other modes.

3/16/07  Suppressing warnings when using the --strict_warnings option

Formerly, if the --strict_warnings and --no_warnings options were used
together, warnings would still be issued.  This has been changed so that
the option specified later on the command-line takes precedence.

3/16/07  GNU mode abort in c_gen_be.c for "packed" field

In GNU modes, the front end sometimes aborted with an internal error in
routine "field_padding" in c_gen_be.c ("negative padding required") when
computing the padding for a field with a class type marked with the "packed"
attribute.  This affects only the C-generating back end.  For example:

  struct X {
    int x1;
    short x2;
  };
  struct Y {
    short y1;
    X y2 __attribute__((packed));  // Previously triggered an internal error
  } d;                             // in c_gen_be.c

This is now fixed.

3/16/07  Microsoft compatibility: for-init scope

In Microsoft C++ mode with microsoft_version >= 1400, the standard scope rules
are now applied to for-init declarations by default.  See also the Changes
entries of 12/2/04 and 9/20/04.

3/16/07  Microsoft compatibility: wchar_t keyword

In Microsoft C++ mode with microsoft_version >= 1400, wchar_t is now treated
as a keyword (as specified by the C++ standard).  See also the Changes entry
of 7/24/03.

3/16/07  Spurious error on global qualifier on definition of member of
         class template

A spurious error was issued when a member of a class template was defined
outside of its class using a global qualifier.  Now fixed.

  template <typename T> struct A {
    void f();
  };

template <typename T> void ::A<T>::f() {}

3/16/07  Specifying DEFAULT_INSTANTIATION_FILE_SUFFIX_LIST in defines.h

Formerly, DEFAULT_INSTANTIATION_FILE_SUFFIX_LIST could not be defined in
defines.h because the definition in host_envir.h did not have an ifndef
guard.  This has been fixed.

3/16/07  Top-level file entries for entries read from precompiled headers

The primary source file associated with a precompiled header file that is
being used is marked as a "top-level" file.  A flag has been added to the
source file entry to allow such entries to be distinguished from the actual
top-level files of the current compilation.  The new flag is named
top_level_file_from_pch.

3/16/07  Microsoft compatibility: template name used in base class specifier

The special treatment of template names in the base-specifier list of
a class template is now disabled when microsoft_version is >= 1400 (see
10/14/01 entry for more information).

  template <class T> class A { };
  // A<B> below now an error when microsoft_version >= 1400 (a template
  // argument list must be specified for B).
  template <class T> class B : public A<B> { };

3/16/07  Copy constructor no longer needs to be callable on direct reference
         binding to class rvalue

Core issue 391 eliminated the requirement of the C++ standard that an
elided copy constructor must be callable when a reference is bound
directly to a class rvalue.  The front end now implements that in
strict C++0x mode, i.e., no error is issued when the copy constructor
is inaccessible or otherwise cannot be called in such a case.  (That
was already the behavior in every mode except strict C++ mode, so for
most modes that is not a change of behavior.)

  class nc {
    nc (nc const &);  // Private, nowhere defined
  public:
    nc ();
  };
  void f () {
    void g (nc const &);
    g (nc());          // Was ill-formed, now okay
  }

In a related change, when the callability check is done (i.e.,
in strict C++98 mode) the definition of the copy constructor is
now forced, which may elicit errors during creation of a generated
copy constructor or instantiation of a template constructor.

3/15/07  Microsoft compatibility: _CPPRTTI macro defined when RTTI is enabled

The Microsoft compiler defines the macro _CPPRTTI to 1 when runtime type
identification is enabled.  The front end can be configured to define an
arbitrary macro when RTTI is enabled.  In addition to any such macro, the
front end now defines the _CPPRTTI macro in Microsoft mode.

3/15/07  Internal error on dependent destructor call when parsing templates

In modes in which nonclass templates are parsed (e.g, strict mode) an internal
error (in create_nonreal_progenitor_symbol) could occur on certain dependent
destructor calls.  The error would occur on an explicit destructor call
where the field selection class is a dependent class without a user-declared
destructor and its base class is another dependent class.  Now fixed.

  template<class T> class A {
    struct B {};
    struct C : B { };
    void f(C* c) {
      c->~C();  // internal error
    }
  };

3/15/07  C++0x mode: "extern template"

In C++0x mode (and in non-strict C++98 mode) "extern template" can now be
used to suppress the implicit instantiation of an entity.  The C++0x feature
is very similar to the version of the feature already accepted in GNU and
Microsoft modes (there are some additional error checks that are required).

One subtle point: According to the standard, an "extern template" directive
has no effect on inline functions (i.e., they are still instantiated), but
the standard recommends that implementations suppress any out-of-line copies
in the presence of an "extern template" directive (the GNU and Microsoft
compilers also behave in this way).  For this to work as intended, an
out-of-line copy must be generated at the site where an explicit
instantiation of the inline function is done.

To help back ends detect cases in which an out-of-line copy should be
emitted, the need_out_of_line_copy flag, which was previously present only
when using MINIMAL_INLINING, is now present in all configurations (IL CHANGE).
If a back end already emits any extern inline routine for which the
definition_needed flag is set and for which the suppress_inline_body flag
is not set, it should not be necessary to test the need_out_of_line_copy flag.
On the other hand, if a back end sometimes suppresses the definitions of such
extern inline functions, it may need now to check the need_out_of_line_copy
flag.

3/15/07  Abort on class rvalue "?" initializing volatile variable

IL lowering aborted with an assertion failure in lower_temp_init
in lower_init.c while processing an optimized class rvalue "?" operation
that is the initializer for a volatile-qualified variable.  Now fixed.

  struct A { A(); };
  int main() {
    volatile A a = 1 ? A() : A();
  }

3/15/07  Overload resolution for template with reference parameter and
         overloaded function argument

Overload resolution did not correctly analyze cases that involve
a template-dependent parameter of reference-to-function type and an actual
argument that is the name of a set of overloaded functions.  A spurious
ambiguity error was issued.  Now fixed.

  int f(char) {return 1;}
  int f(int) {return 2;}
  template<class T> void g(T (&r)(int)) {}
  int main() {
    g(f);  // No longer considered ambiguous
  }

3/15/07  Spurious error on cast to template parameter type in prototype
         instantiation

The front end issued a spurious error on a dynamic_cast of a class-typed
object to a template parameter type in modes that do prototype
instantiations (e.g., strict mode and g++ mode with gnu_version >= 30400).
The cast can be valid if the template parameter is given a reference type.
Now fixed.

  class Object {};
  template <class T>
  void castObjectT(Object& o) {
    dynamic_cast<T>(o);  // No longer mistakenly flagged as an error
  }
  void foo(Object& o) {
    castObjectT<Object&>(o);
  }

3/13/07  Microsoft C++ compatibility: implicit int

In Microsoft C++ mode, the "implicit int" rule is now disabled when
microsoft_version >= 1400.  For example:

  f(int x) { return 3; }  // Now an error in Microsoft C++ mode with
                          // microsoft_version == 1400.

3/13/07  Overload resolution on calls of functions with dependent parameters
         and non-dependent arguments

Overload resolution for calls within template prototype instantiations
(done only in modes that parse templates, e.g., strict mode and g++
mode with gnu_version >= 30400) has been fixed to deal correctly with
member functions that have template-dependent parameters when they are
called with arguments that are not template-dependent.  Overload
resolution for such calls is now delayed until an actual instantiation
of the function, which avoids a spurious ambiguity error during the
template parse.

  template <class T, class T2> struct A {
    int h(T) {return 0;}
    int h(T2) {return 0;}
    void f() {
      h(1);  // No longer flagged as ambiguous
    }
  };            

3/13/07  Explicit instantiation of specialized entity is ignored

The front end now implements the resolution of core issue 259, which amends
the C++ standard to allow (and ignore) the explicit instantiation of an
entity that has already been explicitly specialized.

  template <class T> void f(T) {}
  template <> void f(int){}
  template void f(int);  // now ignored

3/13/07  GNU and Microsoft compatibility: Incomplete dependent base classes

In GNU and Microsoft C++ modes the front end now accepts (with a warning)
template-dependent base classes whose type is in the process of being defined.
For example:

  template<typename T> struct S {
    struct N: S<T> {};  // Previously an error.  Now accepted in GNU and
  };                    // Microsoft modes (with a warning).


3/13/07  Nonstandard pointer-to-member forms now an error

The C++ standard requires that a pointer to member be named
using a qualified name and a "&", e.g., &A::f.  The front end
has accepted nonstandard forms like &f or simply f as a
concession to existing practice.  We have now changed to
producing a discretionary error for these cases.  (Since
the error is discretionary, it can be changed to a warning or
eliminated to restore the previous behavior.)  The nonstandard
forms continue to be accepted in Cfront mode, Sun mode, and
Microsoft mode with microsoft_version < 1400.

  struct Base { 
    void Test() {}
  };
  class Derived : public Base { 
    virtual void Bar();
  };
  void Derived::Bar() {
    void (Base::*p1)() = Test;   // Now an error
  }

3/13/07  Binding a reference directly to an array rvalue

In accordance with core issue 450, the front end now allows a
reference to const array to bind directly to an array rvalue.
Aside from the fact that this makes sense, it avoids aborts
(in which_binary_operator: "bad type") that formerly resulted
from the attempt to copy the rvalue array to a temporary in
order to do the binding to that.

  struct S {
    char cc[10];
  };
  S GetS();
  template <typename T>
  void foo(const T&);
  int main () {
    foo(GetS().cc);  // Formerly caused an abort
  }

3/12/07  Microsoft compatibility: Nonstandard friend template declarations

In Microsoft C++ mode, the front end interprets a nontemplate friend class
declaration that resolves to a class template as a declaration of a friend
class template.  This behavior is now limited to Microsoft C++ modes with
microsoft_version < 1400; when microsoft_version >= 1400, such nonstandard
construct are diagnosed with an error.  For example:

  template<typename T> class C;
  template<typename T> struct S {
    friend class C;  // Now an error when microsoft_version >= 1400.
  };

3/12/07  Better checking of GNU symbol asm operands

The front end previously did not check that references to symbolic asm operand
names resolve to an actual operand if the reference included an output
modifier.  For example:

  void f() {
    int* z;
    asm volatile ("print %a[zp]" : : [z] "p" (&z));
  }     // Previously accepted.  Now an error since there is no "zp" operand.

Now such references are checked even when an output modifier appears between
the characters "%" and the "[".  (See also Changes entry of 7/15/05.)

3/12/07  GNU C++ dependent name lookup closer to standard

The emulation of dependent name lookup in g++ mode with gnu_version >=
40100 has been adjusted to match g++ 4.1, which is now closer
to the standard but still not completely standard-conforming.
The trick described in the entry of 4/19/05 is now disabled
when gnu_version is >= 40100, but an additional trick has been added
that allows functions declared after the point of a dependent call
to be visible in the normal lookup if there are no functions
declared preceding the call.

  extern "C" int printf(const char*,...);
  template <typename T> void func(T&, T&) {
    printf("in func(T&,T&)\n");
  }
  template <typename T> void f1(T& a, T& b) {
    func(a, b);
  }
  void func(int&, int&) {
    printf("in func(int&,int&)\n");
  }
  int main() {
    int x,y;
    f1(x, y);  // Now prints "in func(T&,T&)" in g++ 4.1 mode
    return 0;
  }

3/9/07   Duplicate initialization to zero of partially initialized 
         automatic aggregates following an executable statement

In cases where a declaration of an automatic array or class aggregate
is partially initialized and follows an executable statement, the lowered,
generated C contains two initializations of the aggregate to zero
(using either memset or bzero).  This affects only the C-generating back end.
For example:

  struct S { int a, b, c; };
  void f(int a) {
    a = 0;
    struct S s = {  // had generated two initializations to zero
      1,
    };
  }

3/8/07   Microsoft compatibility: stringized macro arguments

The change to Microsoft-mode macro expansion described in the 7/20/06
entry introduced a bug that resulted in incorrect text in a stringized
macro argument if the argument is also used in non-stringized form in
the replacement text.  This is now fixed.  For example:

  #define Y(s) #s, s
  #define X(s) Y(s)
  X(xyz)      // formerly expanded to "xyzyz", xyz

3/7/07   Sun C++ mode: implicit pointer conversions that drop cv-qualifiers

Sun C++ mode has been updated to emulate a quirk of the Sun C++ compilers
(this has been observed as recently as the Studio 11 version): conversions
from "pointer to const pointer to X" to "pointer to pointer to X" are
now allowed as implicit conversions.  A warning is issued.

  int main() {
    int * const *temp = 0;
    int **temp2 = temp; // Sun CC gives no error
  }

3/6/07   C++-generating back end, Microsoft compatibility: vacuous destructor
         calls with nested and namespace-member classes

When generating code for a vacuous destructor call (an explicit call of the
destructor of a class that has only a trivial implicit destructor or a
pseudo-destructor call), the C++-generating back end used a fully-qualified
name to designate the destructor.  MSVC++ 6.0 has a bug that causes it to
report an error if the destructor's qualifier is itself a qualified-id, so
the C++-generating back end no longer generates a qualified-id for the
destructor when msvc_is_generated_code_target is TRUE,
msvc_target_version_number is 1200 or less,  and the class of the destructor
is nested or a member of a namespace.  For example:

  namespace N {
    struct S { };
  }
  void f(N::S* p) {
    p->~S();    // Formerly generated as p->N::S::~S(), which caused an
                // error in MSVC++ 6.0
  }

3/6/07   Microsoft compatibility: Namespace-scope using-declarations for
         class member types

In Microsoft bugs mode, the front end previously accepted namespace-scope
using-declarations referring to types that are class members.  This is now
limited to modes with microsoft_version <= 1310.  For example:

  struct S { struct N {}; };
  using S::N;  // No longer accepted when microsoft_version == 1400

3/6/07   Microsoft compatibility: Predeclared new[] and delete[] operators

In Microsoft mode with microsoft_version >= 1400, array forms of operator new
and operator delete are now predeclared just as in other modes (provided the
global variable array_new_and_delete_enabled is TRUE).  For example:

  int *p = (int*)operator new[](sizeof(int));
                // Accepted in Microsoft mode when microsoft_version == 1400

3/6/07   Microsoft compatibility: dllexport/dllimport conflicts across
         translation units

When simultaneously processing multiple translation units in Microsoft mode,
the front end previously issued an error for a class that was both dllimport
and dllexport.  Now such conflicts are allowed and dllexport is retained in
the resulting IL.

3/6/07   Microsoft compatibility: Address of string literal

In Microsoft bugs mode, the front end previously always ignored an ampersand
(&) preceding a string literal.  Now the operator is no longer ignored when
microsoft_version >= 1400.  For example:

  char const (*p)[4] = &"abc";  // Now accepted when microsoft_version == 1400

3/6/07   Microsoft compatibility: String literals not shared

In Microsoft mode, the front end no longer attempts to share storage for string
literals (this is controlled by the global variable string_literals_shared).

  bool f() { return "x" == "x"; }  // Now returns false in Microsoft mode.

3/5/07   Microsoft compatibility: sealed or abstract unions

In Microsoft C++ mode, the front end now issues an error when attempting to
define a sealed or abstract union.  For example:

  union U sealed {};  // Now an error.

(The "sealed" and "abstract" class type modifiers are only recognized when
microsoft_version >= 1400.)

3/2/07   GNU C++ compatibility: Functional-notation cast syntax

In GNU C++ mode with gnu_version < 30400, the front end now accepts
functional-notation casts that start with an elaborated type name.
For example:

  enum E { e = 20 };
  E f() { return enum E(2); }  // Now accepted in some GNU C++ modes.

3/2/07   Sun compatibility: #pragma redefine_extname and global variables

In Sun mode, the front end implements a limited version of Sun's #pragma
redefine_extname construct: It is limited in that although the construct
affects mangled names, the front end can only perform the lookup in terms of
declared names.  Previously, the feature was therefore limited to entities
with extern "C" name linkage (since both the declared name and the mangled
name are identical in those cases, at least in the supported ABIs).  Now,
variables in the global namespace can also be named.  For example:

  int x;
  #pragma redefine_extname x y
    // Now accepted in Sun mode.

3/1/07   GNU compatibility: address_taken field set on lvalue cast

In GNU emulation mode, an lvalue cast of a variable could result
in the address_taken field being set.  The problem occurs in C mode when
gnu_version < 40000 and in C++ mode when gnu_version < 30400.

  int f() {
    register int n;
    (short)n = 10;   // Previously set address_taken field of variable "n"
    return n;
  }

2/28/07  Abort on Microsoft enum types with explicit underlying type

In configurations with IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE and
PROTOTYPE_INSTANTIATIONS_IN_IL or BACK_END_IS_CP_GEN_BE set TRUE, the front
end could abort in Microsoft mode when dealing with enum type definitions
that explicitly specify the underlying type.  For example:

  enum E: short { e };  // Could abort in Microsoft mode in some
                        // configurations.

This is now fixed.

2/23/07  Invalid constructor and destructor syntax

The front end failed to diagnose constructor or destructor declarations
preceded by pointer declarator operators like "&" or "*".  For example:

  struct S {
    *S();
    * const S(S const&);
    &S(int);
    &~S();
  };  // Previously silently accepted.

This is now fixed (errors are issued on such constructs).

2/23/07  Bad identifier end position recorded for unnamed namespaces

In configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE, the front end
sometimes failed to initialize the "identifier_range.end" position in
a_namespace entries for unnamed namespaces.  This is now fixed: A null
position is now recorded in such cases.

2/22/07  Incorrect initialization of automatic aggregate variable when
         dynamic partial initialization is specified during inlining

In cases where a dynamic designated initializer is used to partially
initialize an aggregate automatic variable, and the variable is used in an
inline function, the initk_zero specification that was added during lowering
is lost during inlining resulting in indeterminate values for fields in the
aggregate that were not explicitly initialized.  This problem occurs in
modes that allow designated initializers (e.g., GNU C/C++, C99) with
structure type aggregates when MINIMAL_INLINING is TRUE.  This is now fixed.
For example:

  struct foo { int x, y; };  
  static inline int _f (int xx) {
    struct foo _foo = { .x = xx };
    return _foo.y;  // Returns 0 now when inlined, previously indeterminate
  } 

2/21/07  C++0x mode: The "auto" type specifier

In C++0x mode, the keyword "auto" can now be used as a type specifier.  The
actual type of the associated entity is deduced from the initializer that
follows (which is required).  This feature can be used for variable
declarations, for in-class declarations of static const members, and for
new-expressions.  For example:

  auto x = 3.0;           // Same as "double x = 3.0;"
  auto p = new auto(x);   // Same as "double *p = new double(x);"
  struct S {
    static auto const m = 3;  // Same as "static int const m = 3;"
  };

The deduced type is the type deduced for T if the initializer were used as an
argument to a call to "template<typename T> void f(T);".

If an "auto" specifier is used for multiple declarators, each declarator must
be associated with an initializer, and each of those initializers must imply
the same deduced type for the "auto" specifier.  For example:

  auto x = 3.0, y = 0;  // Error: x deduced to double but y deduced to int.

Some declarations of this form were previously meaningful through the
"implicit int" rule (e.g., in Cfront modes "auto x = 3.0;" implies that x has
type int).  In the interest of decreasing surprise, the "implicit int" rule is
now always disabled in modes supporting C++0x extensions.  For example:

  const x = 3;  // Previously accepted with "--cfront_3.0 --c++0x"; now
                // an error in all C++0x modes.

This extension was voted into the C++ committee's working paper for the next
standard in April 2006 (meeting in Berlin, through proposal numbered N1984).

2/21/07  Some declaration-processing routines restructured

Some significant changes were made to the interface and implementation of key
routines that handle declaration processing.  This includes (but is not
limited to) the routines "declaration(...)", "decl_specifiers(...)", and
"declarator(...)".  The most significant effect of these changes is that much
information about a declaration is now carried around in an object of type
a_decl_parse_state.  That in turn will simplify the implementation of future
language extensions.

2/15/07  Microsoft compatibility: __restrict

In Microsoft C and C++ modes with microsoft_version >= 1400 the front end now
accepts the "__restrict" qualifier.  It has the same meaning as the "restrict"
qualifier in C99.  In Microsoft C++ mode, "__restrict" is also accepted on
reference types (even though the Microsoft compiler ignores such uses with a
warning).

2/15/07  Microsoft/GNU compatibility: non-integral &a.b as template argument

The Microsoft and GNU C++ emulation modes previously allowed
expressions of the form &a.b as nontype template arguments only if the
type of "b" is integral.  Now, such constructs are allowed as nontype
template arguments regardless of the type of "b" (an error is issued
if the expression type does not match the template parameter type).

  typedef struct { int a; } A;
  struct B { A w; };
  extern B t;
  template <const A *x> class foo { };
  A x;
  foo<&t.w> y;  // Now allowed in Microsoft and GNU modes

2/15/07  Microsoft compatibility: extended variadic macros

Version 8.0 of the Microsoft compiler supports a form of variadic macros.
The front end now accepts them by default in Microsoft mode when
microsoft_version is 1400 or greater.  This includes emulation of the
Microsoft-specific feature in which a comma in the replacement text
preceding an empty __VA_ARGS__ substitution is dropped from the expanded
text, even when no concatenation operator is present.  For example, with
--microsoft_version=1400, both the A and B macro invocations below expand
to 'printf("string")', while with --extended_variadic_macros, the B
invocation expands to 'printf("string", )':

  #define A(x, ...) printf(x, ## __VA_ARGS__)
  #define B(x, ...) printf(x, __VA_ARGS__)
  A("string");
  B("string");

2/15/07  Missing "!= 0" above lowered code for complex == or !=

The IL enforces the rule that expressions that appear in boolean
controlling expression contexts (e.g., the expression tested in an
"if" statement) always have a 0/1 value, whether from a constant or
from an operator that is guaranteed to return 0/1.  A "!= 0" is added
in cases where that rule is not already satisfied.  In C lowering
(lower_c99.c), the code generated for complex equality tests when
LOWER_COMPLEX is TRUE is a runtime routine call, and when such calls
appear in a boolean controlling expression context they should have
a "!= 0" above them, but they didn't.  Now, they do.

2/15/07  Memory region problem with const local variable as template argument
         in prototype instantiation

In cases where an initialized const local variable is used as a constant
in a nontype template argument in a prototype instantiation, sometimes the
IL constructed included a file-scope constant with a pointer to a
function-scope expression, which could cause aborts later on.  Now fixed.

2/14/07  Internal error in conv_class_operand_to_object_pointer during
         prototype instantiation when casting class object to same type

If a class operand was cast to the same type as the class operand during
prototype instantiation, an internal error resulted.  Prototype instantiation
is required in a number of cases including dependent name processing
(--dep_name), parsing of nonclass templates (--parse_name), strict mode
(--strict) and in GNU C++ mode in versions greater than or equal to 3.4
(--g++ --gnu_version=30400).  In some cases, setting
FUNCTION_PROTOTYPE_INSTANTIATION_DEFERRAL_ALLOWED to TRUE might have
prevented the error.  This is now fixed.  For example:

  template<int N>
  struct A {
    A(A<N> & a);
    void bar();
    void foo(A<N> a) 
      { ((A<N>) a).bar(); }   // Caused an internal error with --strict.
  };

2/14/07  g++ overload resolution, partially-ordered template conversion
         functions

The change of 12/22/04 to change overload resolution with regard to where
the template-specific rules for comparing two candidate functions are
done did not correctly model g++, in that the rule for differentiating
between two template functions should not be done early in the list of rules
even though the template/non-template distinction rule is.  We've
moved the partial ordering rule back to the last position in the list
regardless of the setting of late_template_ovl_res_tiebreaker.  This
affects only g++ mode, since that is the only one that has that switch
set to FALSE.  See core issue 495 for more detail.

  int i = 0;
  struct B {
    template <class T> operator T*() { i = 1; return 0;}
  };
  struct D : B {
    template <class T> operator T**() { i = 2; return 0;}
  };
  D d;
  extern "C" int printf(const char *, ...);
  int main() {
    (void *) d;
    if (i != 1) { printf("FAIL\n"); return 1; }
    return 0;
  }

2/13/07  Initialization of local static variables in extern inline functions

In the non IA-64 ABI case, when lowering is performed on a constant
initialization of a local static variable in an extern inline function,
executable code is inserted with a temporary guard variable at the beginning
of the block in which the declaration occurs.  If, however, the beginning of
the block is unreachable (as is the case with the dependent block of a switch
statement), the executable code will never be executed.  To remedy this
situation, the executable initialization is now placed at the start of the
block associated with the function scope.  For example:

  inline int f(int n)
  {
    switch(n) {
      default:
        static int x = 99;
        return x;          // Had returned 0, now returns 99
    }
  }

2/9/07   Predefined macros with no replacement text

If a macro was defined in the predefined_macros.txt file as having no
value, i.e., the line ended with the last character of the macro's name,
that macro was defined as if its value were the part of the preceding line
that extended past the terminator of the current line.  For example, a
predefined_macros.txt file that contained the following two lines formerly
had the effect of defining macro X with the value "C def".  This is now
fixed, giving macro X an empty replacement text.

  gnu no ABC def
  gnu no X

2/7/07   Incorrect padding for arrays when using new [] and delete []
         with IA-64 ABI on types with typerefs

The amount of padding to allow before an array being operated on by new []
or delete [] may have been miscalculated if the type of the array element
had type qualifiers.  This only affects lowering performed when IA64_ABI is
TRUE.  This has been fixed.  In this example, the const qualifier would
have caused such an error:

  struct A { ~A(); };
  void f(const A *p) { delete [] p; }
  
2/7/07   GNU C++ compatibility: injected class lookup in g++ 3.4

Versions of g++ before version 3.4 found the injected class name instead of
the constructor name when scanning a nested declarator such as the one in the
constructor definition below, resulting in a compilation error.  We emulate
the behavior in g++ mode.  Versions 3.4 and higher correctly find the
constructor name in such cases.  We now emulate this new behavior when
gnu_version >= 30400.

  struct C {
    (C)();
  };
  (C::C)() {}  // error when gnu_version < 30400

2/6/07   GNU compatibility: Additional built-in functions

In GNU modes, the following additional built-in functions are now predeclared:
__builtin___memcpy_chk, __builtin___memmove_chk, __builtin___mempcpy_chk,
__builtin___memset_chk, __builtin___snprintf_chk, __builtin___sprintf_chk,
__builtin___stpcpy_chk, __builtin___strcat_chk, __builtin___strcpy_chk,
__builtin___strncat_chk, __builtin___strncpy_chk, __builtin___vsnprintf_chk,
__builtin___vsprintf_chk, __builtin_bcopy, __builtin_memmove, and
__builtin_object_size.

2/6/07   end_position not set on stmk_microsoft_try statements

The end source position on stmk_microsoft_try statements are now
properly set when EXTRA_SOURCE_POSITIONS_IN_IL is defined.  Also, the end
source position on stmk_ifs generated while lowering catch statements
(assuming DO_FULL_PORTABLE_EH_LOWERING and DO_IL_LOWERING are TRUE)
are also set properly.

2/6/07   Microsoft compatibility: __interface redeclarations

The front end now more closely emulates Microsoft compilers when handling
redeclarations of "__interface" types.  Specifically, declarations of an
interface type that are neither the first declaration nor the definition can
use the keywords "class" or "struct" instead of "__interface" (a warning is
issued).  For example:

  __interface X;
  struct X;     // Now accepted in Microsoft mode.

If the first declaration of a class type uses the keyword "__interface" and it
is followed by a definition not using that keyword, the declared type is
treated according to the definition (i.e., not as an __interface type).
For example:

  __interface Y;
  struct Y {
    static int i;  // Okay because X is not considered to be an interface.
  };

2/5/07   New configuration flag for disabling lowering of return value
         optimization

A new switch, DO_RETURN_VALUE_OPTIMIZATION_IN_LOWERING, has been introduced to
allow customers to selectively disable lowering of the return value
optimization.  Setting this flag to TRUE (the default setting) continues to
enable this optimization during lowering in cases where the return value
optimization is applicable.  Setting the switch to FALSE will disable
return value optimization during lowering.  Detection of cases where the return
value optimization is applicable is performed by the front end regardless
of the value of this switch.

2/4/07   C++-generating back end, Microsoft compatibility: explicit
         specializations of inline conversion function templates

In configurations in which
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
C++-generating back end generated a non-defining declaration of an explicit
specialization of an inline conversion function template before the
conversion function is used and then generated the definition of the
explicit specialization at a later point.  MSVC++ has a bug that causes it
to report an error when it encounters a non-defining declaration of such
an explicit specialization.  The C++-generating back end has been changed
to avoid this MSVC++ bug by generating the definition at the point at which
the declaration was previously generated when msvc_is_generated_code_target
is TRUE.  For example:

  struct A {
    template <typename T> operator T() { return T(); }
  };
  // Previously generated here:
  //   template<> inline A::operator int();
  // Now generated here:
  //   template<> inline A::operator int() { return (int)0; }
  int f() {
    A a;
    return int(a);
  }
  // Previously generated here:
  //   template<> inline A::operator int() { return (int)0; }
  // Now nothing generated here.

2/3/07   Argument deduction for conversion function templates

The front end formerly added a spurious "const" qualifier when deducing the
type of a conversion function template when the target type is a class with
a bitwise copy constructor.  This is now fixed.  For example:

  struct A {
    void f();
  };

  struct B {
    template <typename T> operator T();
  };

  void g() {
    A a;
    B b;
    a = (A)b;   // Now uses B::operator A(), not B::operator const A()
    A(b).f();   // No longer a cv-qualification mismatch error
  }

1/31/07  Set end source position on inlined statements

The end source position (end_position) is now set on statements that are
inlined when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE.  The value of the end
source position is the source position of the call site when
STATEMENTS_INSERTED_FOR_INLINING_HAVE_INVOCATION_POSITION is TRUE or the
end position of the original statement when 
STATEMENTS_INSERTED_FOR_INLINING_HAVE_INVOCATION_POSITION is FALSE.

1/31/07  GNU compatibility: Attribute "aligned" on typedefs

When determining the alignment of a field with a typedef type, the front end
previously considered an attribute "aligned" directly applied to the typedef
type but not any attributes applied to an underlying typedef type.  For
example:

  typedef int __attribute((aligned(16))) I16;
  typedef I16 J16;
  struct S { J16 s; int t; };
    // Previously the attribute was always ignored when laying out S.

This corresponds to the behavior of gcc/g++ 3.3.x, but all other versions of
the GNU compiler supporting this feature appear to take attributes on
underlying typedefs into account.  We now emulate the more common GNU behavior
when gnu_version/100 != 303.

1/31/07  address_taken field set on anonymous union variable if field address
         is used

If the address of a field in an anonymous union variable is taken, the
address_taken field in the IL is now properly set for the variable.

1/30/07  Stack overflow with rvalue ? inside template prototype instantiation

The processing for class rvalue "?" operators inside of templates,
where at least one operand of the operation is based on a template
parameter, in modes that parse templates (e.g, strict mode), was
flawed in a way that could cause a recursion loop within the front end
that eventually leads to a stack overflow abort.  Now fixed.  The
following, for example, aborted in strict mode and in g++ 3.4 mode:

  template<typename _Tp> struct allocator {
    allocator();
    allocator(const allocator&);
  };
  template<typename _Alloc = allocator<char> > struct basic_string;
  typedef basic_string< allocator<char> >    string;
  template<typename _Alloc> struct basic_string {
    _Alloc    A;
  };
  void retrieveInput(const string&);
  template<int i> void foo() {
    retrieveInput( (i == 1)?  string(): string()); // problem here
  }
  template void foo<0>();

1/30/07  Abort with #if inside macro argument list with
         FULLY_RESOLVED_MACRO_POSITIONS

In configurations in which FULLY_RESOLVED_MACRO_POSITIONS is TRUE, code like
the following caused an assertion failure; this is now fixed.

  #define X(x) x
  X(y
  #if defined(Y)
    z
  #endif
  )

1/26/07  C++-generating back end: Microsoft compatibility for default
         arguments of member functions

As noted in the 4/13/05 entry, MSVC++ 6.0 has a bug affecting default
arguments in member functions where the default argument is a temporary of
the form N::T<x,y>().  The workaround added to the C++-generating back end
at that time inadvertently failed to handle cases in which N::T had a
destructor (with no destructor, the enk_temp_init node is at the top level
in the default argument expression, while with a destructor, it is under an
enk_object_lifetime node).  The workaround now handles the destructor case
as well.

1/25/07  Change the values assigned by GNU extended designator initializers

The assignment of initializers when using multi-dimensional range
extended designators has been changed to match the order produced by gcc.
A new field, "variant.init_repeat.multidimensional_aggr_tail_not_repeated",
has been added to a_constant to indicate when IL lowering or the back end
needs to effect this change (IL CHANGE).  For example, in the following
declaration:

  int X[3][3] = { [1 ... 2][0] = 4, 5, 6 };

The non-zero array values after initialization are now:

  X[1][0]=4
  X[2][0]=4
  X[2][1]=5
  X[2][2]=6

Previously they had been:

  X[1][0]=4
  X[1][1]=5
  X[1][2]=6
  X[2][0]=4
  X[2][1]=5
  X[2][2]=6

1/23/07  IL walk problem with RECORD_FORM_OF_NAME_REFERENCE

In configurations with RECORD_FORM_OF_NAME_REFERENCE set to TRUE
(e.g., most C++-generating back end configurations), a use of a
named constant (e.g., an enumerator constant) in an initializer
in a translation unit that references the constant somewhere else
using a qualified name produced IL with two constant entries
pointing to the same name references list, which could cause
difficulties (such as IL write/read errors like the internal error
"ptr_remap_function: address not in any mem block") in later
processing.  Now fixed.

1/23/07  C++-generating back end: qualified friend declarations

When a class in an enclosing namespace is declared to be a friend of a class
in a nested namespace, the name of the befriended class must be qualified;
otherwise, the friend declaration is taken to declare a new class in the
inner namespace.  The C++-generating back end failed to generate a qualified
name in such friend declarations.  This is now fixed.  For example:

  struct S;
  namespace N {
    class C {
      friend struct ::S;    // Previously generated as "friend struct S;"
    };
  }

1/16/07  sizeof_il_entry consistency checking

The code checking for consistent initialization of the sizeof_il_entry array
was previously only enabled in configurations with ALTERNATE_IL_FILE_FORMAT
and IL_SHOULD_BE_WRITTEN_TO_FILE both set to TRUE (for historical reasons).
Now, the code is enabled in all configurations with CHECKING set to TRUE.

1/15/07  Variables with GNU-style register mapping

In GNU modes, global and namespace-scope variables mapped onto specific
registers (using the GNU "asm" construct) are now treated as "extern"
variables.  Previously, such variables were treated like "static" variables.
A consequence of this change is that variables of this kind now are rendered
as ordinary extern variables in the C- and C++-generating back end when
GCC_IS_GENERATED_CODE_TARGET is FALSE (previously, an altogether invalid
declaration was generated instead).  Additionally, the declaration of such a
variable is preserved in the IL even if the variable is otherwise unused.
This reflects the fact that such a declaration reserves the associated
register for that variable (within the entire program).  For example:

  register int x asm("r4");  // a_variable entry for variable x will not be
                             // removed from the IL.


1/13/07  Source positions of constructor initializers after IL lowering

When base class and member initializers in a constructor definition were
lowered, the resulting expression statements were given the source position
of the opening brace of the constructor's body.  Now, in configurations in
which EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the source position of the
lowered initializers will be preserved.  For example:

  struct S {
    S()
      : i(0)    // Previously positioned to line 4, now to line 3
      { }
    int i;
  };

1/11/07   Allow extended integral constants in g++ 3.4 compatibility mode

Support for some non-standard integral constant expressions had inadvertently
been dropped in Version 3.8 in the g++ 3.4 compatibility mode.  This has
been rectified such that expressions such as the one below are now accepted
in this mode (they continue to be accepted in g++ versions earlier than 3.4
as well):

  int p[((char *)0 - (char *)0)];

1/11/07   Sun compatibility: extended integral constants

Sun compatibility mode now accepts some additional nonstandard
kinds of expressions as integral constant expressions.  For example:

  struct K {
    enum E {a, b};
    static const int c = 5;
  };
  void f(K* pk) {
    int i = 0;
    switch (i) {
      case pk->b:; // b is an enumeration, allow in Sun compatibility mode
      case pk->c:; // c is const static member, allow in Sun compatibility mode
    };
  }

1/10/07  Abort caused by severely ill-formed template specialization

In some unusual (and severely ill-formed) cases involving the "template<>"
specialization syntax appearing in a class template declaration, the front
end aborted (due to a null pointer indirection) in class_member_declaration.
(The problem first appeared in version 3.5 of the front end.)  For example:

  template <class T> class A {
    template <> struct {
      f( {  // Triggered abort in class_member_declaration.

This is now fixed.

1/10/07  Lvalues in gcc asm output operands

Two changes have been made to the processing of asm output operands in
the GNU asm statement.  First, in error cases where the operand is not
an lvalue, the IL now contains an error node.  Second, an integral
cast to a same-size type on top of an output operand is now ignored
(and the underlying lvalue recovered and used) even when gnu_version
is greater than 40000.

1/9/07   Parenthesized string initializers

Parenthesized string initializers are a nonstandard construct accepted by many
C and C++ compilers.  For example:

  char s[] = ("abc");  // Nonstandard but accepted by many compilers.

Prior to version 3.7, the front diagnosed such cases with an error in strict
and default modes.  Version 3.7 inadvertently dropped the diagnostic in all
cases.  Now a discretionary error is issued in strict mode, but the construct
is silently accepted in all other modes.

1/8/07   Warn when compound assignment operands have invalid values

A warning is now emitted when the constant operand of a /= or %= compound
assignment is zero or when a shift count in a <<= or >>= compound assignment
is negative or greater than or equal to the width of the operand.  These
checks had previously been performed in the non-assignment cases and are
now being performed in the corresponding compound assignment cases.
For example:

  int i;
  void f(void)
  {
    i /= 0;             // warning: division by zero
    i %= 0;             // warning: right operand of "%" is zero
    i <<= sizeof(i)*8;  // warning: shift count is too large
    i >>= -1;           // warning: shift count is negative
  }

1/3/07   C++-generating back end: __builtin_va_list in template arguments

When GCC_BUILTIN_VARARGS is TRUE, in GNU emulation modes the front end
predefines the type __builtin_va_list as a typedef for void *.  Although on
some platforms the GNU compilers use a type other than void * for
__builtin_va_list, the fact that both the front end and source code
generally treat __builtin_va_list as an opaque type avoids most
difficulties resulting from the mismatch.  Because of the change of
11/10/04, however, the C++-generating back end put out the underlying type
instead of the typedef name when __builtin_va_list was used as a template
argument, which could cause errors if the generated code was compiled on
platforms that do not use void * for this type.  This has now been fixed by
retaining the __builtin_va_list typedef in the generated code.  For
example:

  typedef __builtin_va_list VL;
  void f(void (*)(VL));
  template <typename T> void tf(T);
  void g() {
    f(tf<VL>);    // Now generates tf<__builtin_va_list>, not tf<void *>
  }

12/22/06 C++-generating back end: references to tagged types

The C++-generating back end failed to use an elaborated-type-specifier to
refer to a type in some cases where that was necessary.  This situation
arose when an inline member function definition contained the first
reference to a type that was also used later in the class definition.  This
is now fixed.  For example:

  struct S {
    unsigned f() { return sizeof(struct Bar *); }
    struct Bar *p;    // Previously omitted "struct"
  };

12/19/06 IA-64 ABI name mangling for nested local class names

The IA-64 ABI name mangling for classes that are nested inside
of classes declared local to a function sometimes produced mangled
names that began with "__" and therefore could not be demangled.  Now
fixed (those names now begin with "_Z").

  int main(){
    struct AA {
      void f() {}
      struct BB { int i; };  // Name of BB was mangled wrong
    } x;
    AA::BB y = { 1000 };
  }

The C-generating back end has also been updated because it
mangles some local class names in cases where IL lowering does
not promote such classes out of the surrounding function.
The code there now works the same as the similar code in
IL lowering.  (The test case for that issue is the test case
above with the line for function "f" removed.)

12/15/06 C++-generating back end: typedefs used as base specifiers

When a typedef appeared in the source as a base specifier in a class
definition, the output of the C++-generating back end used the underlying
type of the typedef in its place.  This substitution resulted in errors
when the underlying type was an inaccessible class.  The C++-generating back
end now preserves typedefs used as base specifiers.  For example:

  class O {
    struct S { };        // private
  public:
    typedef S T;
  };

  struct D: O::T { };    // Previously generated as O::S

12/15/06  Failure of "more specialized" test on template functions

The test done after overload resolution to determine whether one
function is more specialized than another failed in some cases
when a template is involved and the signature of the template
involves expressions operating on primitive types.  As a consequence,
some calls were mistakenly diagnosed as ambiguous.  Now fixed.

  template <bool B> struct enable_if_c {
    typedef void type;
  };
  template <typename T> struct xxx {
    static const bool value=true; 
  };
  template<typename T> struct TTT {
    typedef T type;
    TTT(const T& t) {}
  };
  template<typename T> void Insert(const TTT<T>& input) {}
  template <typename T>
  typename enable_if_c<!xxx<T>::value>::type  // Note "!" operation here
  Insert(const T& output) {
  }
  void Insert() {
    Insert(TTT<int>(4));  // Formerly seen as ambiguous
  }

12/14/06  Sun C++ compatibility: allow nonconst ref anachronism in sun mode

In Sun compatibility mode, initializing a reference to a nonconst is now
allowed by default.  The Sun compiler (through version 5.8) continues to
allow this anachronism.  For example:

  struct A {
    A(int);
    A operator=(A&);
  };
  int main () {
    A b(1);
    b = A(1);     // Allowed with a warning in Sun compatibility mode.
  }

12/14/06 Address of function template with target type of "void *"

The change of 4/13/06 to deal with addresses of function templates
introduced a bug for contexts where the destination type is "void *":
a function template in such a case was considered not to match at all,
rather than being a source of infinitely many matches and therefore
of ambiguity.  This makes a difference when there is another non-template
function in the overload set:

  void f(int) { }
  template <class T> int f(T) { return 0; }
  template <> int f(int) {
      void *p = (void *)&f; // Should be ambiguous, but chose the non-template
      return 0;
  }

12/14/06 Abort with IA-64 ABI, --no_extern_inline, inline added outside class

When the IA-64 ABI is used with IL lowering, and --no_extern_inline
is specified, an abort could occur in lower_il.c (in function
virtual_function_table_should_be_defined_here) on processing of
the virtual function table for a class whose decider function
is declared "inline" in the definition outside the class.
Now fixed.

  struct A {
    virtual void f();
  };
  inline void A::f() {}

12/5/06  Microsoft C compatibility: __declspec on struct fields

In Microsoft C mode, the front end now accepts some __declspec specifiers on
struct field declarations.  For example:

  struct S { __declspec(align(8)) char c; };
    /* Now accepted in Microsoft C mode.  sizeof(struct S) == 8 in most
       configurations. */

Previously, the __declspec specifier was ignored with a warning in Microsoft
C mode when Microsoft bugs were enabled and an error was issued when Microsoft
bugs were disabled.

12/4/06  GNU compatibility: stdcall and cdecl attributes on variables

In GNU modes, the front end now accepts the attributes "stdcall" and "cdecl"
on declarations of variables with pointer-to-function types.  For example:

  void (*p)() __attribute((stdcall));  // Now accepted in GNU modes.

(These attributes have an effect only in configurations with
GNU_X86_ATTRIBUTES_ALLOWED.) 

12/4/06  Microsoft compatibility: incorrect disambiguation of __super

An old-style cast followed by an expression that starts with the Microsoft
__super keyword was not handled properly in disambiguation, resulting in
spurious errors.  Now fixed.

  struct A { 
    int f();
  };
  struct B : public A {
    int f() { return (int) __super::f(); } 
  };

12/3/06  Invalid IL with nonstandard anonymous unions in C mode

IL lowering generated invalid IL for certain kinds of nonstandard
anonymous unions in C mode.  Such anonymous unions are allowed when
ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE, e.g., in Microsoft and
GNU modes.  Incorrect IL was generated for uses of fields of
nonstandard unions/structs used in aggregate initializers in C mode,
and that could result in aborts later in back ends (in the
C-generating back end, for example, the abort was in
dump_field_from_second_operand: "wrong field class").  Now fixed.

  struct S1 {
    int f1;
    void * p;
  };
  struct S2 {
    struct S1;  // Nonstandard anonymous struct
    int f2;
  };
  void f(void) {
    int v;
    struct S2 s2 = {1, &v, 2};  // Use in aggregate initializer
  }

As part of this change, cases like the above have now been disallowed
in C++ mode.  Specifically, naming a typedef to insert a nonstandard
anonymous union or struct into another class is no longer allowed.
(Neither Microsoft nor GNU allows such cases.)

  typedef struct {
    int f1;
    void * p;
  } S1;
  struct S2 {
    S1;        // No longer allowed in C++ mode
    int f2;
  };

12/1/06  Listing all macro definitions

The front end now accepts a new command line option, --list_macros, that is
similar to the GNU preprocessor's -dM option.  When --list_macros is
specified, the definition of every macro (predefined, command line, and
#defined) that is in effect at the end of the source file is echoed to the
file specified by -o/--output or to stdout if no output file is given.  The
source file is only preprocessed, not compiled, and the --list_macros
option supersedes the -E/--preprocess and -P/--no_line_commands options
(i.e., no preprocessed text will be written, only macro definitions).

11/29/06 Microsoft compatibility: comments created via macro expansion

The Microsoft compiler treats the character sequence "//", created by
concatenation during macro expansion, as the start of a comment.  There
was a bug in the front end's emulation of this behavior when the macro
performing the concatenation was invoked from the expansion of another
macro; the result was that the comment delimiter was ignored and the rest
of the line was not commented out.  This is now fixed.  For example:

  #define IGNORE COMMENT
  #define COMMENT /##/
  void f() {
    IGNORE x;    // No longer a reference to an undeclared variable
  }

11/28/06 Abort on GNU statement expression when VLA in scope

In GNU mode, a statement expression containing a return statement triggered an
internal error in statements.c if a variable-length array (VLA) was declared
in a scope surrounding the statement expression.  For example:

  void f(int n) {
    int a[n];
    ({ return; });  // Previously aborted with an internal error in
  }                 // statements.c.

This is now fixed.

11/28/06 GNU C++ compatibility: template nesting depth mismatch on full
         specialization

The diagnostic issued when an incorrect number of "template <>" clauses is
specified on a full specialization (i.e., one with no remaining template
parameters) has been reduced to a warning in g++ mode.

  template <class T> struct A {
    template <class U> struct B { };
  };
  template <> struct A<int>{
    template <class U> struct B {};
  };
  template <> template <> struct A<int>::B<double> {};  // warning in g++ mode

11/27/06 Microsoft compatibility: #pragma start_map_region("filename")

While scanning the filename argument of a start_map_region pragma (see the
entry of 4/10/06), the front end issued an error or warning if the initial
characters of a name following a backslash directory separator did not form
a valid escape sequence.  This string is now read as if it were a header
name, suppressing attempts to recognize escape sequences.  For example,

  #pragma start_map_region("d:\union\c.cpp")  // no longer reports an error
                                              // for an incorrectly-formed
                                              // universal character name

11/22/06 Statement positions in inline call expansions

The source positions in the expansions of inline function calls that
appear at the statement level in the source code now have the
positions of the original statements in the inline function, rather
than the position of the line of the call, if the new switch
STATEMENTS_INSERTED_FOR_INLINING_HAVE_INVOCATION_POSITION is set
to FALSE (default is TRUE, which gives the traditional behavior).
When the call is not at the statement level, the expansion is an
expression rather than a statement, so there are no statements whose
position might be at issue.  Also, regardless of the setting of
this switch, in C modes that allow inlining (GNU C or C99) the
positions are now set; formerly, they were null source positions,
which incorrectly suggested that the code was compiler-generated.

11/22/06 C++-generating back end: internal-linkage tentative definitions

As a result of the change described in the 10/6/06 entry, the
C++-generating back end used the "static" storage class specifier on all
C-language file-scope declarations of a variable with internal linkage.
The Microsoft C compiler, however, has a bug such that it rejects
declarations with the "static" specifier that occur after the definition of
the variable.  The C++-generating back end has now been changed back to
using the "extern" specifier for declarations that follow the variable's
definition.  For instance:

  static int i = 5;    /* definition */
  extern int i;        /* previously generated as "static int i;" */

11/21/06 C++-generating back end, GNU compatibility: asm names and "alias"
         attributes for variables

The change supporting alias references to asm names (11/16/06) caused the
C++-generating back end to produce incorrect code for some variables
declared using this feature.  Now fixed.  For example:

  extern int A __asm__("B");
  extern int C __asm__("D")
               __attribute__((alias("B")));  /* Formerly generated as
                                                'alias("D")'. */

11/21/06 GNU compatibility: Alternative name for flags register

In GNU modes, with GNU_X86_ASM_EXTENSIONS_ALLOWED set to TRUE, the front end
now recognizes the alternative name "cc" for the flags register.

11/20/06 GNU asm register names lost during inlining

In GNU mode (in configurations with MINIMAL_INLINING set to TRUE), the front
end did not associate a GNU asm register specified on a local variable of an
inline function with the corresponding variable in the inline expansion.
For example:

  inline void *sp() {
    register void *r asm("%sp");
    return r;
  }
  int main() {
    void *s = sp();  // "r" (from sp(), above) was previously remapped to
  }                  // a local variable not associated with a specific
                     // register by front end inlining (with unpredictable
                     // consequences).

This is now fixed.

11/20/06 GNU compatibility: Alternative x86-64 register names

In configurations that set GNU_X86_ASM_EXTENSIONS_ALLOWED to TRUE, the front
end defined some alternative names for x86-64 register names (in GNU modes),
but left out some of the most common ones: rax, rbx, rcx, rdx, rsi, rdi, rbp,
and rsp.  These are now also recognized.

11/18/06 C++-generating back end: number of arguments in a template-id

When a template-id is used to refer to a function, trailing template
arguments can be omitted if they can be deduced from the function call.
The C++-generating back end, however, always generated a complete argument
list in such template-ids, sometimes resulting in erroneous code.  In
configurations in which RECORD_FORM_OF_NAME_REFERENCE is TRUE, template-ids
referring to functions are now generated with the same number of template
arguments used in the source.  For example:

  template <typename T> struct S: T { };

  template <typename T> void f(S<T>) { }
  template <typename T> void f(T) { }

  void g() {
    f<>(1);    // Previously generated as "f< int>(1)" (which will produce
               // an instantiation error for S<int> instead of deduction
               // failure for f(S<T>) as in the original).
  }

11/17/06 Spurious access error on static data member definition in GNU C++ mode

In GNU C++ mode with gnu_version < 30400, the front end issued a spurious
access error on out-of-class member definitions that start with an elaborated
class type specifier.  This is a regression introduced by version 3.8 of the
front end (specifically, by the changes for the entry of 1/26/06 to allow
delayed nested class definitions in class scopes).  For example:

  class S {
    struct N {};
    static N s;
  };
  struct S::N S::s;  // Previously a spurious access error in some GNU modes.

This is now fixed.

11/17/06 Redeclarations of built-in functions

When GNU_EXTENSIONS_ALLOWED is true, the front end previously issued an error
when redeclaring a GNU built-in function with an incompatible type.  Now a
warning is issued and the built-in function is hidden.  Furthermore, in C++
mode, a warning is also issued if a declaration overloads a GNU built-in
function.  For example:

  int __builtin_sin(int);  // Now a warning in GNU modes.  In C mode, the
                           // declaration hides the predeclared function; in
                           // C++ mode (as was the case previously) it
                           // overloads it.

11/17/06 Optimized usage of <windows.h> in Windows-hosted builds

host_envir.c now defines a number of macros before including the
<windows.h> header.  These macro definitions suppress unneeded features and
services declared in <windows.h>, allowing faster compilation, smaller
debugging symbol tables, etc.

11/16/06 GNU compatibility: asm names and "alias" attribute

In GNU modes, the front end now considers GNU asm names when looking up the
name specified by an "alias" attribute.  For example:

  extern "C" {
    static void f() __asm("g");
    static void f() {}
    void h() __attribute((alias("g")));  // h() now aliased to f().
  }
  int main() { h(); }

In the example above, the alias name for h() was previously not found.  This
caused warnings to be emitted, and a linker error to be issued for a function
"g".  Now the alias for h() is found to be f() and the program compiles and
links correctly.

11/15/06 Missing diagnostic on invalid friend class declarations

In some C++ modes (including default C++ mode) the front end failed to
diagnose certain invalid friend class declarations.  Such declarations
were ignored.  For example:

  class C {
    friend;  // Previously not diagnosed in some C++ modes (and treated.
  };         // like "friend int;").

This is a regression introduced in version 3.8 by the changes to allow
extended friend types (see Changes entry of 5/10/06).  It is now fixed.

11/15/06 Parenthesized string initializers for arrays with unspecified bound

The front end now accepts a parenthesized initializer containing a string
literal for a character array with an unspecified bound.  The bound is then
determined by the size of the string literal.  For example:

  char s[]("Okay");  // Now accepted and treated as: char s[] = "Okay";

11/13/06 Invalid code rendering for __builtin_offsetof with nonstandard
         anonymous unions

In GNU C mode, when rendering a __builtin_offsetof construct whose second
operand involves a member of a nonstandard anonymous union, the C++-generating
back end emitted a reference to an undeclared (i.e., internally generated)
field.  For example:

  struct S {
    union {
      int m;
    };
  };
  unsigned long x = __builtin_offsetof(struct S, m);
    // Rendered with "m" replaced by something like "__T136893532.m".

This is now fixed.

11/9/06  Invalid code rendering for GNU attribute "alias"

A routine declaration with the GNU attribute "alias" caused all declarations
of that routine to be rendered by the C++-generating back end with that
attribute.  However, GNU compilers do not accept multiple alias declarations
for the same alias.  For example:

  void f() __attribute((alias("f_impl")));
  void f();  // Previously rendered by the C++-generating back end with the
             // alias attribute.
  void f_impl() {}

The same applies to variable declarations.  This is now fixed: The attribute
"alias" is only emitted when it appeared on the corresponding declaration in
the input.

11/8/06  Abort on instantiation of member function declared with a typedef

In configurations with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE, the front
end aborted with an internal error on cases where a member function of a class
template first declared using a typedef type was later defined and
instantiated.  For example:

  template<typename T> struct S {
    typedef void F(T);
    F f;  // Member function declared through typedef type.
  };
  template<typename T> inline void S<T>::f(T) {}
  int main() {
        S<int>().f(2);  // Instantiation triggered an internal error.
  }

This is now fixed.

11/8/06  GNU compatibility: static initialization using compound literal
         lvalues

The gcc compiler treats lvalues referring to compound literals as constants
and thus suitable for use as initializers of objects with static storage
duration.  The front end previously rejected such constructs as non-constant,
but this has now been changed.  For example:

  typedef struct {
    int i[1];
  } S;

  S s = *&(S){{0}};    /* No longer an error in --gcc mode */

11/6/06  Internal error on reference to member of dependent base from nested
         class of class template

An internal error could occur in create_nonreal_progenitor_symbol in modes
in which undefined names referenced from templates with dependent base classes
are assumed to name members of a dependent base.  Typically, this is
all modes except for strict mode and g++ mode when gnu_version is >= 30400.
This has been fixed.

  template <class T> struct A {};
  template <class T> class B { struct C; };
  template <class T> class D : public B<T> {
    class E {};
    class F : public E {
      typedef C my_C;
    };
  };

11/5/06  Needed-flag processing and prototype instantiations

Prototype instantiations are now considered "needed" for the needed-flag
processing in configurations with PROTOTYPE_INSTANTIATIONS_IN_IL
set to TRUE.  Prototype instantiations are never referenced from
other code, so if they aren't marked as needed they would always
be removed, which defeats the purpose of PROTOTYPE_INSTANTIATIONS_IN_IL.
This problem was usually not visible because when BACK_END_IS_CP_GEN_BE
is TRUE removal of unneeded entities is suppressed in any translation
unit that contains templates, which means in such configurations the
prototype instantiations were always preserved in spite of not being
marked as "needed."

11/5/06  IA-64 ABI, needed-flag processing, and entry points

The needed-flag processing has been changed so that when an IA-64
alternate entry point for a constructor or destructor is marked as
definition-needed, the primary routine is also.  This makes sense
since we intend that it be possible to make the alternate entry truly
an entry point to the other routine definition.  This problem was
generally invisible, because the alternate entry point usually calls
the primary routine, and therefore the primary routine gets marked as
needed if the entry point is needed.  However, that does not happen
when the body of the alternate entry point is inlined, which became
possible with the optimizations described by the change of 1/24/06.

11/3/06  Incorrect processing of some GNU field attributes

The front end previously issued a spurious warning on the GNU attributes
"const", "volatile", and "noreturn" when they appeared on a field.  For
example:

  struct S {
    int (*f)(int) __attribute((const));  // Previously triggered a warning.
  };

Despite the warning, the attribute was correctly recorded in the IL.  However,
the C- and C++-generating back end also failed to render these attributes for
field declarations, as well as the "mode" attribute on field declarations.
These problems are now fixed.

11/2/06  Widening of character literals

In cases where a narrow-character string literal is converted to a
wide-character string literal, the number of characters to be copied was
incorrectly calculated and could lead to memory corruption.  Now fixed.
Examples where a narrow-character string is widened include:

  void* p = "abc" L"xyz";  /* C99 or C++0x narrow/wide string concatenation */
  void* q = __LPREFIX("abc");  /* Microsoft wide-character string */  

This problem is a regression introduced by the introduction of support for
U-literals (see Changes entry of 2/14/06).

11/2/06  Microsoft compatibility: conversion for direct reference binding

Overload resolution has been tweaked to better emulate MSVC++ in
cases where a conversion is done to try to directly bind a reference.
The standard requires one overload resolution to see whether a conversion
can be done to something that will allow a direct reference binding,
and then, if that is not possible, another overload resolution to
see whether a conversion can be done to create a temporary that the
reference will bind to.  MSVC++ seems to do a single overload resolution
for such cases, and therefore gets an ambiguity if one conversion
function would satisfy the direct-binding case and another would allow
the bind-to-reference case.

  struct B {};
  struct D: private B {};
  struct H {
    operator B const volatile *const &() const { return 0; }
    operator D const volatile *() { return 0; }
  };
  void check_sig(B const volatile *const &) {
  }
  int main() {
    check_sig(H());  // MSVC++ thinks this is ambiguous
  }

11/2/06  IL display of "default" ELF visibility

The IL display utility previously reported an error value for entities with
"default" ELF visibility (a property available in configurations with
GNU_VISIBILITY_ATTRIBUTE_ALLOWED set to TRUE).  That is now fixed.

11/1/06  Configuration of wint_t

A new macro TARG_WINT_T_INT_KIND allows the configuration of type wint_t (which
the C99 standard defines to be an integer type sufficient to represent all the
characters in the extended character set, plus at least one additional value to
represent an end-of-file marker).  The new macro initializes the new global
variable targ_wint_t_int_kind.  This is now used when checking the "%lc" printf
conversion specifier (previously, wchar_t was used instead) and when defining
certain GNU builtin functions (previously, unsigned int was assumed).

10/31/06 GNU compatibility: __builtin_constant_p

The front end previously always constant-folded calls to __builtin_constant_p.
However, GNU compilers appear to only fold such a call in the front end if the
argument is a constant-expression, or if the call appears in an initializer
outside a function scope.  That behavior is now closely emulated when the new
configuration macro DEFAULT_ALWAYS_FOLD_CALLS_TO_BUILTIN_CONSTANT_P is set to
FALSE (doing so, however, requires support from the back end).  If neither the
C- nor the C++-generating back end is used, the behavior is unchanged by
default.

10/30/06 Incorrect type for char16_t literals

When both U-literals (see Changes entry of 2/14/06) and multibyte source
characters (see Changes entry of 2/19/97) are accepted, the front end often
assigned too large of an array type to char16_t literals.  For example:

  unsigned short const *str = u"123";
    // The literal previously was a 7-element array instead of a 4-element
    // array.

This is now fixed.

10/26/06 C++-generating back end: casting to reference types

The C++-generating back end previously rendered many casts of lvalues to
reference types using pointer types, adding indirection or taking addresses
as needed for the semantics of the expression.  It has now been modified
to use reference types for most expressions where the source used a
reference type.  For example:

  unsigned i;
  int *r = &reinterpret_cast<int&>(u);  // Previously generated as
                                        // reinterpret_cast<int*>(&u)

10/25/06 Spurious warning for variables in specific registers (GNU modes)

In GNU modes, it is possible to map a variable onto a specific register.  If
such a variable is used without initialization, the front end no longer issues
a warning (since the register may have been initialized through some outside
mechanism).  For example:

  unsigned long f() {
    register unsigned long sp asm("%sp");
    return sp;  // No longer triggers a warning about sp being uninitialized.
  }

10/25/06 Microsoft C compatibility: Incompatible function redeclarations

In Microsoft C mode, a function can now be redeclared with a return type that
is incompatible with the return type specified on the original declaration,
provided that return type is "similar" to the original type (e.g., a signed or
unsigned variant).  A warning is issued in such cases.  For example:

  unsigned int f();  
  int f();  // Now accepted (with a warning) in Microsoft C mode.

10/25/06 alignment_of_variable

A new utility function "alignment_of_variable" is now available (defined in
il.c) to find alignment needed for a variable.  The function takes into
account any attributes specified on the variable declaration (significant
in Microsoft and GNU modes).

10/24/06 C++-generating back end: names used for template parameters

In configurations in which the C++-generating back end generates the
definition for a template from its prototype instantiation rather than
using its recorded string (i.e., with PROTOTYPE_INSTANTIATIONS_IN_IL set to
TRUE), the generated output sometimes used the name of a template parameter
from an earlier template definition in a dependent reference.  This is now
fixed.  For example:

  template <class T> struct A {};
  template <class T> struct B {
    A<typename T::z> y;
  };
  template <class X> struct C {
    A<typename X::z> x;       // Formerly generated as A<typename T::z>
  };   

10/23/06 Integer types in #if control expressions (C99 and GNU modes)

In its DR#265 the C committee has issued a correction that gives all integer
types the same representation as intmax_t or uintmax_t (depending on their
signedness) when converting integer literals appearing in #if control
expressions.  We now follow that requirement in C99 mode, as well as in GNU
C and C++ modes (to match the behavior of GNU compilers).  For example:

  #if -0xFFFFFFFF > 0
  #error DR 265 not implemented  // Previously triggered in all modes.
  #endif                         // Now not triggered in C99 and GNU modes.

10/23/06 Microsoft compatibility: Calling convention of pointer-to-member
         function

In Microsoft mode, the front end previously treated a pointer-to-member
function as implying the __cdecl calling convention by default.  Now, the
default calling convention for a pointer-to-member function is __thiscall.
For example:

  struct S {};
  void f(void (S::*pm)()) {}
  void f(void (__cdecl S::*pm)()) {}  // Previously a duplicate definition;
                                      // now accepted.

(See also the Changes entry of 11/29/05.)

10/18/06 C++-generating back end: GNU attributes for pure virtual functions

The C++-generating back end previously generated a GNU attribute
specifier for a pure virtual function at the end of the declaration,
following the "= 0", but g++ does not accept this syntax.  Any attribute
specifier is now generated before the "= 0", as required by g++.  For
example:

  struct S {
    virtual void f() __attribute((__stdcall__)) = 0;
  };

10/12/06 Spurious error on duplicate using-directive for tag name

The front end previously disallowed duplicate using-directives that referred
to a tag name masked by a non-tag name, even in scopes (such as namespaces)
where such a redeclaration is valid.  For example:

  namespace N {
    struct X;
    void X();
  }
  using N::X;
  using N::X;  // Previously an error.  Now accepted.

This is now fixed.

10/11/06 Result type of loop test in generated assignment operator

If a class has an array member whose element type is a class with a
non-trivial copy assignment operator, the generated operator= for the
containing class will have a loop that copies the array elements.  The result
type of the loop termination test (comparing the index against the number of
elements in the array) was formerly "int"; it is now "bool" if the bool type
is available and "int" otherwise.  For example:

  struct M {
    M& operator=(const M&);
  };
  struct S {
    M arr[2];
  };

  void f(S& s1, S& s2) {
    s1 = s2;
  }

Here, the generated S::operator=(const S&) will contain a loop copying the
elements of S::arr; the loop test ("__temp < 2U") formerly had type "int"
and now has type "bool" in dialects where "bool" is a keyword.

10/11/06 Invalid IL for prototype instantiations in GNU C++ mode

In GNU C++ mode, elimination of unused IL entries could lead to invalid IL for
prototype instantiations of class template.  The problem could manifest itself
as an internal error reporting an IL write-read difference for nonreal class
types.  PROTOTYPE_INSTANTIATIONS_IN_IL and MAINTAIN_NEEDED_FLAGS had to be
TRUE, and BACK_END_IS_CP_GEN_BE had to be FALSE, for the problem to occur (a
somewhat unusual combination).  In affected configurations, the following
simple example triggered the problem when compiled in GNU C++ mode with
elimination of unneeded entities enabled:

  template<typename T> struct B {};
  template<typename T> struct D: B<T> {};  

This problem is now fixed.

10/11/06 C++-generating back end: broken strings in __declspec(deprecated)
         attributes

When generating the string form of the __declspec(deprecated) Microsoft
attribute (see the entry of 11/9/05), the C++-generating back end sometimes
inserted a line break into the string literal.  This is now fixed.

10/10/06  Alignment of unions with bit fields

A new configuration macro TARG_BIT_FIELD_AFFECTS_UNION_ALIGNMENT determines
whether a union should be given an alignment that's a multiple of the
alignment of any bit field member of that union (until now, that was always
the case).  The macro is TRUE by default, except when
TARG_MICROSOFT_BIT_FIELD_ALLOCATION is TRUE because Microsoft compilers
ignore bit fields when determining the alignment (but not the size) of unions.
For example, assuming a common 32-bit int type:

  union U {
    int a: 2;
  };  // U has size 4, but alignment 1 if TARG_MICROSOFT_BIT_FIELD_ALLOCATION
      // is FALSE.  Otherwise, U has size and alignment 4.

10/9/06  Name mangling for &__uuidof(T) with IA-64 ABI

The name mangling produced for the Microsoft extension __uuidof in
an expression like &__uuidof(T) was not properly formed when the
IA-64 ABI is used.  The actual mangling is somewhat arbitrary, since
the IA-64 ABI isn't used by Microsoft, but it should be well-formed
according to the ABI spec and acceptable to the demangler.  Now, it is.

10/6/06  Abort on nonstandard anonymous unions when near/far support enabled

In modes supporting the "near" and "far" qualifiers (like 16-bit Microsoft
mode), the front end aborted in check_anonymous_union_symbols (class_decl.c)
with an internal error when processing the definition of a nonstandard
anonymous union.  For example:

  typedef struct { int m; } S;
  struct { S; } x;  // Aborted in 16-bit Microsoft mode (and other modes
                    // that allow "near" and "far" qualifiers.

This is now fixed.

10/6/06  C++-generating back end: internal-linkage tentative definitions

The C++-generating back end failed to allow for tentative definitions in C
code when emitting non-definition declarations of internal-linkage
variables, assuming that the C++ rules applied.  Now fixed.  For example:

  static int i;      /* Tentative definition in C; formerly generated as
                        "extern int i;" */
  static int i = 5;  /* Definition. */

10/5/06  Microsoft compatibility: Nested classes and __declspec

In Microsoft mode, the front end incorrectly treated nondefining declarations
of nested classes preceded by a __declspec specifier as belonging to the
enclosing namespace scope.  For example:

  struct S { __declspec(dllimport) struct N; };
  S::N *p;  // Previously an error because struct N was considered a
            // member of the global scope.

In templates, a similar problem also occurred with nested class definitions.
This is now fixed.

10/5/06  C++-generating back end: explicit casts to pointer types that
         differ from the types of user-defined conversion functions

The C++-generating back end formerly suppressed implicit calls to
user-defined conversion functions, even when the call is the operand of a
cast to a pointer type that is different from that returned by the
conversion function; the resulting code was incorrect because it attempted
to cast a class object to a type for which there is no direct conversion.
This problem has been fixed by generating a cast to represent the call of
the conversion function in such cases.  For example:

  struct S {
    operator unsigned*();
  } s;

  int* f() {
    return (int*)&*s;   // Previously generated as "(int *)s",
  }                     // now generated as "(int *)((unsigned *)s)"

10/4/06  GNU and Microsoft compatibility: Explicit storage class on explicit
         template specialization

In GNU and Microsoft C++ modes, an explicit function template specialization
can now specify an explicit "extern" or "static" storage class specifier.
For specializations that are nonmember functions, such a specifier overrides
any linkage implied by the template.  For example:

  template<typename T> static void f() {}
  template<> extern void f<int>() {}  // Accepted in GNU and Microsoft C++
                                      // modes, and f<int> has external
                                      // linkage.

For the explicit specialization of member functions, the "extern" specifier
has no effect, and the "static" specifier is ignored with a diagnostic: An
error in GNU mode and a warning in Microsoft mode.

10/3/06  Switch case labels (IL CHANGE)

Previously, switch case labels were primarily represented using a simple list
of constants pointed to by the constant_list field of a_switch_clause entries.
A clause containing the "default" label, resulted in an empty list.  When
EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, additional information was recorded in
switch case entries (type a_switch_case_entry).
Now, switch case entries are recorded when the new configuration macro
RECORD_SWITCH_CASE_ENTRIES is set to TRUE (which is the default).  In such
configurations, a_switch_clause entries no longer define a constant_list
field, but the switch case entries maintain both the source code order (via
their "next" pointer) and the "by value order" (via their "next_by_value"
pointer) of case labels.  This new representation is particularly useful
when dealing with large GNU case ranges, which previously required the
allocation of many a_constant entries (resulting in performance problems,
and occasionally memory exhaustion).  For example:

  void f1(int i) {
    switch (i) { case 1 ... 10000000: break; }
     // Previously triggered the allocation of ten million a_constant entries.
     // Now, when RECORD_SWITCH_CASE_ENTRIES is TRUE, a more efficient
  }  // representation is used

The constant_list representation can be re-enabled by setting the macro
RECORD_SWITCH_CASE_ENTRIES to FALSE, but that precludes recording additional
information in switch case entries (even when EXTRA_SOURCE_POSITIONS_IN_IL
is TRUE).

Previously, in GNU C++ modes case ranges with a template-dependent bound
could result in an abort due to memory exhaustion (in a long-running loop)
during prototype instantiation.  The conditions for this to occur were
quasi-random.  For example:

  template<int I, int J> void f2(int i) {
    switch (i) {
      case 1 ... I: break;
      case J ... 100: break;
    }  // In some configurations, this could run out of memory during
  }    // prototype instantiation.

That problem is now fixed.

Finally, the diagnostic for case label conflicts now specifies the location
of the conflicting earlier case label (except in many cases of conflicting
GNU case ranges when RECORD_SWITCH_CASE_ENTRIES is FALSE).  For example:

  void f3(int i) {
    switch (i) {
      case 5:  // Line 3.
      case 5:  // Error: Diagnostic will mention "line 3".
        break;
    }
  }

9/26/06  Abort on command-line error when using MAKE_FRONT_END_CALLABLE

Version 3.8 introduced an abort (in free_memory_region) when the front end
is built with MAKE_FRONT_END_CALLABLE == TRUE and a compilation terminates
via a command-line error.  Now fixed.

9/25/06  Stack overflow on multiple uses of const member expression in template

In some complicated templates, the front end sometimes looped internally,
eventually overflowing the stack.  The problem cases involved a const
member given an initial value that is an expression (e.g., sr>0 in
the example below), and uses of the value of that member at more than
one place and more than one level in expression operands that are not
the final ones (e.g., fixed_size is used twice in "?" operators below).
Actual examples of this failure are quite hard to generate.  Now fixed.

  template<class T> struct SimdSize { static const unsigned res = 1; };
  template<int static_size=-1> class Vec;
  template<int size=-1> struct Sym {};
  template<int size=-1> struct Herm {};
  template<unsigned alignment> struct MatElem;
  template<class Structure> class Mat;
  
  template<int sr>
  struct Mat<Sym<sr> > {
      static const bool fixed_size = sr>0;
      static const int static_data_size = ( fixed_size ? sr : -1 );
      typedef Vec<static_data_size> TV;
      typedef typename TV::template SubType<0>::T T;
      static const unsigned alignment = ( fixed_size ? 1 : SimdSize<T>::res);
      typedef MatElem<alignment> RetOp;
  };
  template<int sr>
  struct Mat<Herm<sr> > {
      static const bool fixed_size = sr>0;
      static const int static_data_size = (fixed_size ? sr : -1 );
      typedef Vec<static_data_size> TV;
      typedef typename TV::template SubType<0>::T T;
      static const unsigned alignment = ( fixed_size ? 1 : SimdSize<T>::res);
      typedef MatElem<alignment> RetOp;
  };

9/22/06  IA-64 ABI: Attributes of alternate entry points

IL lowering with an IA-64 ABI configuration can create additional routine
entries representing alternate entry points of constructors and constructors.
Now, any attributes of the primary routine entry that naturally apply to the
secondary entry points are copied to the routine entries for the secondary
entry points.  These attributes include ELF visibility and DLL import/export
status.

9/20/06  expect_error() assertion triggers spuriously

The front end code occasionally invokes the expect_error() macro to assert
that an error either has been issued or will be issued before the end of the
compilation.  In configurations with COMPILE_MULTIPLE_SOURCE_FILES set to
TRUE, this could cause spurious internal errors when a source file containing
(unusual) errors was followed by one not containing any errors.  Now fixed.

9/19/06  K&R/pcc mode: Abort on invalid field access with integral pointers

In K&R/pcc mode, the front accepts field access operator on objects of integer
type (with a warning).  For example:

  struct S1 { int f; };
  int f1(int i) { return i.f; };  /* Accepted in K&R/pcc mode. */

However, similar cases where the field name either could not be found or
resolved to multiple fields with conflicting offsets, the front end previously
aborted.  For example:

  struct S2 { int m; };
  int f2(int i) { return i.f; };  /* Previously aborted in K&R/pcc mode. */

This is now fixed: An error is issued in such cases.

9/18/06  GNU C++ compatibility: va_start and reference types

In GNU C++ modes that recognize the va_start operator (because the macros
GCC_BUILTIN_VARARGS or DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE are
TRUE), the front end now accepts a reference parameter for the second
argument of va_start when gnu_version >= 30200.  For example:

  void f(int &p, ...) {
    __builtin_va_list ap;
    __builtin_va_start(ap, p);  // Previously an error.  Now accepted in
  }                             // many GNU C++ modes.

9/18/06  GNU and Sun compatibility: linkage specification and "static"

In Sun and GNU C++ modes, a linkage specification can now appear directly on
a declaration with a "static" specifier.  Such cases are handled as though
the linkage specification had been written with the brace-based syntax.
For example:

  extern "C" static void f();  // Same as extern "C" { static void f(); }

This was already accepted in Microsoft C++ mode (see Changes entry of
1/23/97).

9/15/06  GNU compatibility: Attribute visibility

In GNU C++ mode with gnu_version >= 40200, the front end now accepts the
attribute "visibility" on namespace definitions (when the configuration macro
GNU_VISIBILITY_ATTRIBUTE_ALLOWED is TRUE).  In addition, existing support for
that attribute on class type definitions has been improved to correctly
propagate to nested classes.  For example:

  namespace __attribute((visibility("hidden"))) {
    void f();  // Implicitly "hidden" in the ELF sense.
  }
  struct __attribute((visibility("hidden"))) S {
    struct N {
      void f();  // Implicitly "hidden" in the ELF sense.
    };
  };

9/14/06  Template deduction problem with qualified nontype parameter

If a nontype template parameter was declared with a cv-qualified dependent
type (e.g., "const T") a spurious deduction failure could result.  Now fixed.

  template <int I> struct A {};
  template <class T, const T p> struct B {};
  template <class T, const T p> void f(B<T,p>){}
  int main() {
    f(B<int,1>());
  }

9/13/06  Sun compatibility: Dependent name processing off by default

In Sun C++ mode, dependent name processing is now turned off by default even
when DEFAULT_DEPENDENT_NAME_PROCESSING is configured to TRUE (dependent name
processing can still be enabled in combination with Sun mode using the
command-line option --dep_name).  Similarly, nonclass prototype instantiations
are now disabled by default, and the "implicit typename" rules are enabled by
default in such configurations.

9/13/06  Abort on complex deduction failures

In some fairly rare cases involving failing template argument deduction for
complex template or nontype template parameters, the front end entered a 
corrupt internal state that ended up triggering internal errors.
For example:

  template<int I> struct A {};
  template<typename T, T::N I, T::M J> void f(T (&)[I], A<J>) {}
  struct S {
    typedef double N;
    typedef int M;
  } s[3];
  int main() {
    f(s, A<3>());  // Deduction failure because T::N is not an integral type,
  }                // but front end aborted (in this case, in function
                   // copy_template_param_con in il.c).

This is now fixed.

9/13/06  GNU C++ compatibility: Deducing unnamed class/enum types

In GNU C++ mode, the front end now treats the substitution of a template
parameter by an unnamed class or enum type as a deduction failure.
For example:

  struct { operator int() { return 0; } } x;
  template<class T> int f(T) { return 1; }
  int f(int) { return 2; }
  int main() {
    return f(x);  // Accepted in GNU C++ mode, and returns 2.
  }               // (Error in default and strict modes.)

9/11/06  Sun compatibility: Exception handling

In Sun compatibility mode, support for exception handling is now enabled by
default.

9/6/06   Abort on selection of field of template declared by using-declaration

The front end aborted in add_base_class_casts while processing a
field selection in any mode that fully parses function templates
(e.g., strict mode, or g++ mode >= 3.4) when the field selection
is for a member of the current template that is brought in from
a base class via a using-declaration.  Now fixed.

  template<typename type> class A {
    class B {
      protected:
        A* ptr;
    };
  public:
    class C:B {
      protected:
        using B::ptr;
      public:
        A* getPointer() {return ptr;}  // Caused abort
      };
  };

9/6/06   IA-64 ABI: class operator delete missing at link time

With IL lowering and the IA-64 ABI, there were some cases where a
template operator delete for a class was referenced from the generated
code but never instantiated, thus causing an unresolved external
at link time.  This happened with an operator delete in a class
that has a non-virtual destructor, no delete of that class in
the compilation unit that contains the definition of the destructor,
and a delete of the class in some other compilation unit.

9/6/06   GNU C++ compatibility: incorrect lookup when deferring prototype
         instantiations

In g++ mode when gnu_version is >= 30400, function prototype instantiations
are deferred until the first use of the template.  In such modes, friend
functions declared in class templates were sometimes not visible when they
should have been.  This could result in spurious errors or incorrect results.
Now fixed.

  template <class T> struct A {
    friend bool operator!=(const A<T>&, const A<T>&);
  };
  template<class T> void f(A<int> a) {
    a != a;  // spurious "no matching function" error
  }
  int main() {
    A<int> a;
    f<int>(a);
  }

9/1/06   GNU/Microsoft compatibility: Class-qualified lookup in templates

While parsing a template in its generic form, looking up a name qualified with
a template-dependent class type can generally not be done because the class
template might be specialized later on to change the outcome of the lookup.
In such cases, the lookup always succeeds and a placeholder entity is created.
However, if the name looked up is qualified with a class template currently
being defined, then the lookup should proceed as in the nontemplate case (as
per the standard).  This treatment of class templates currently being defined
(which is required by the C++ standard) is no longer present in GNU and
Microsoft modes (the lookup therefore always succeeds with a placeholder
result in those modes).  For example:

  template<class T> struct S {
    typename S::X *p;  // Normally an error because S::X does not exist, but
  };                   // accepted in GNU and Microsoft modes.

8/31/06  Completeness of exception specification types

Inside the definition of a class being defined, that class is now considered
to be complete for the purposes of checking the validity of a type in an
exception specification.  For example:

  struct S {
    void f() throw(S) {}  // Previously an error because S is incomplete.
  };                      // Now accepted.

This implements the resolution of the C++ committee's Core issue 437).

8/30/06  GNU compatibility: Attribute aligned on function declarations

In GNU mode, the front end now issues a discretionary error (instead of a
warning) when attribute "aligned" is specified on a function declaration.

8/30/06  IA-64 ABI: Invalid virtual call adjustment with some covariant returns

The front end sometimes incorrectly determined the contents of virtual function
tables when an overriding virtual function in a derived class has a covariant
return type that is a pointer or reference to its enclosing class or a base
class thereof.  This resulted in invalid pointers or references being returned
in such cases.  For example:

  struct B1 { virtual ~B1() {} };
  struct B2 { virtual B1* f() { return 0; } };
  struct D: B2, B1 {
    D* f() { return this; }  // Covariant return
  } d;
  #include <assert.h>
  int main() {
    D *p = &d;
    assert(p->f() == &d);  // Assertion previously failed.
  }

The problem only occurred in IA-64 ABI configurations.  This is now fixed.

8/25/06  C++0x mode: static_assert

In C++0x mode, the front end now accepts static_assert declarations of the
following form:

	static_assert( <integral-constant> , <string-literal> );

If the given integral constant is zero/false, an error is emitted containing
the given string literal (characters not in the basic source character set are
rendered as question marks).  For example:

  template<class T> struct S {
    static_assert(sizeof(T)>4, "Type too small");
  };
  S<char> s1;  // Will trigger an error when the static_assert declaration
               // is instantiated.

This extension was voted into the C++ committee's working paper for the next
standard in April 2005 (meeting in Lillehammer, through proposal numbered
N1720).

8/23/06  Invalid explicit padding by C-generating back end

The C-generating back end usually adds a dummy "padding" field to C struct
types whose size is larger than the offset of the last byte of its last
declared field.  However, doing so could lead to invalid C code when the
last declared field is a flexible array member (because such members must
usually be the last member of their enclosing type).  For example (assuming
common 32-bit int configurations):

  struct P {
    int i;
    short s;
    char x[];  // Previously, the C-generating back end added padding
  };           // after this field. The result was invalid C code.

This is now fixed: No padding is added when the last field is a flexible
array member, or when it is a zero-length array member (a GNU extension).

8/22/06  Source sequence entries for stmk_decl statements

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, the front end generates stmk_decl
statements to indicate the position of declarations in statement sequences.
Previously, such statements pointed to the source sequence entry for the first
declarative entity associated with the stmk_decl statement.  However, that
complicates the code needed to find all those declarations since the first
declarative entity may be on a source sequence sublist while subsequent
entities may appear on the main list.  To simplify this, a new configuration
macro SRC_SEQ_ENTRIES_FOR_DECL_STMTS has been introduced: When TRUE (which
is the default when GENERATE_SOURCE_SEQUENCE_LISTS is TRUE), stmk_decl entries
point to their own source sequence entry and that entry is always on the main
source sequence entries list (the source sequence entries for the associated
declarations then follow the entry for the stmk_decl statement).  This is an
IL CHANGE; the previous approach can be restored by setting 
SRC_SEQ_ENTRIES_FOR_DECL_STMTS to FALSE.

8/22/06  Empty structs and unions in C mode

In default C mode, the front end now emits a warning for definitions of struct
or union types that only contain declarations that are not field declarations
(in addition to the warnings already issued on the members that do not declare
a field).  For example:

  struct S {
    struct N;  // Already triggered a diagnostic in C mode because nothing
               // is really declared here.
  };           // Now triggers a warning in default C mode (an error in
               // strict mode) because S has no named fields.

In strict C mode, this warning was already issued, but its severity is now
raised to be a discretionary error (except in strict warnings mode).

In addition, C-mode structs with no fields now have the flag is_empty_class
set to TRUE in their IL entries (this is an IL CHANGE).

8/22/06  GNU compatibility: Extended asm 'Z' constraint

In configurations with GNU_X86_ASM_EXTENSIONS_ALLOWED set to TRUE, the front
end recognizes the "i386 family machine constraint" encoded by the letter 'Z'
in GNU extended asm syntax.  However, it previously erroneously recorded the
constraint using the lower case letter 'z' instead of the upper case 'Z'.
This is now fixed.

8/21/06  GNU compatibility: Extended asm 'p' constraint

The "simple constraint" encoded by the letter 'p' in GNU extended asm syntax
is now accepted.  For example:

  void f() {
    char *d = "0123456789";
    asm("add%Q0 $9, %k0\n" : "+p" (d)); // "p" constraint previously triggered
  }                                     // an error.

8/18/06  Microsoft compatibility: Array variables in condition declarations

In Microsoft mode, the front end now accepts condition declarations that
declare array variables.  For example:

  void f() {
    if (char s[] = "x");  // Now accepted in Microsoft C++ mode.
  }

Such conditions are always true.

8/18/06  Mutable reference members

The front end now issues a discretionary error in strict mode or a warning in
nonstrict modes when attempting to declare a reference member with the mutable
specifier.  For example:

  struct S {
    S();
    mutable int &r;  // Now triggers a diagnostic.
  };

8/17/06  Expression range for operator-syntax call nodes

In configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE, the source
position information is suppressed in operation expression nodes that are
marked as compiler-generated.  An exception has been made for call nodes
resulting from operator-notation calls to overloaded operator functions;
these will now show the expr_range and operator_position of the overloaded
operator and its operands.  For example:

  struct S {
    bool operator!();
  };
  bool f(S& s) {
    return !s;    // eok_call node now has expr_range indicating "!s" and
                  // operator_position indicating "!"
  }

8/17/06  Source range in call of static member function

In configurations with EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE, the ending
position of the expr_range in the enk_routine_address node was left as the
null_source_position in calls to static member functions using the member
selection syntax ("." or "->").  This is now fixed.  For example:

  struct S {
    static void f();
  };
  void g(S* p) {
    p->f();    // End position formerly omitted in enk_routine_address node
  }

8/17/06  Microsoft compatibility: [export] and inhibiting attribute processing

The [export] attribute was previously erroneously treated as not applying to
Microsoft interface types.  Now that attribute is accepted on interface types
(but no longer on class types, which corresponds to the Microsoft behavior).
For example:

  [export] __interface I {};  // Now accepted in Microsoft mode.
  [export] class C {};        // Now an error in Microsoft mode.

Also, the configuration option SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING failed
to fully disable the processing of Microsoft attributes (e.g., the example
above elicited an error even when the macro was configured to TRUE).  This is
now fixed.

8/16/06  Abort or bad IL with member using-declaration in Microsoft bugs mode

A change in version 3.7 caused the front end to generate bad IL in Microsoft
bugs mode when parsing a member-using declaration that found a typedef for a
non-member class type.  For example:

  struct B { typedef B T; };
  struct D: B { using B::T; };  // Bad IL for the using-declaration.

The C++-generating back end would abort when trying to render the bad IL.
This is now fixed.

8/15/06  C++-generating back end: enumerators with dependent values with
         PROTOTYPE_INSTANTIATIONS_IN_IL

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the
C++-generating back end generated every enumerator of an enumeration inside
a template with an explicit expression if its value depended on a template
parameter, even when the expression was implicit in the source.  This is
now fixed.  For example:

  template <int I> struct S {
    enum E { e0 = I, e1 };     // Previously generated as "e1 = (I + 1)"
  };

8/15/06  Erroneous type for __builtin_copysign (GNU mode)

In GNU modes, the front end predeclared the function __builtin_copysign, but
its parameter and return types were incorrectly recorded as being complex
floating-point types (the same was true of __builtin_copysignf and
builtin_copysignl).  This is now fixed.

8/15/06  Invalid IL access for certain template-dependent enum definitions

The front end sometimes accessed an incorrect variant field within a_constant
entries when processing a template-dependent enum definition.  For example:

  template<int I> struct S {
    enum E { e1 = I, e2 };  // Caused ck_template_param constants to be
  };                        // accessed as ck_integer constants.

This is now fixed.

8/14/06  Source range for expressions involving parentheses and unary & and *

Because lvalues are represented in the EDG IL as pointers, the unary
pointer operators & and * generally just change the interpretation of an
existing expression node instead of resulting in the creation of a new
one.  Similar considerations dictate that parentheses also do not have
their own expression nodes.  As a result it is not clear what should be
covered by the source_range of some expression nodes.  For example, the
statement

  return *(f());

is represented in the IL by an stmk_return statement whose expression is an
eok_call expression operation node.  Should the source range of the
eok_call node reflect just the call, "f()", or should it cover the entire
expression of the return statement, "*(f())"?

When the new configuration option EXPR_RANGE_MODIFIERS_IN_IL is set to
TRUE, this quandary is addressed by adding a list of "range modifiers" to
the expression node, each describing the source range of the expression
resulting from applying one additional syntactic element to the expression
directly denoted by the node.  In the above example, the ranges for the
eok_call node and its list of modifiers might be:

                      source range       expression
                      ------------       ----------
  expr_range:         columns 15-17          f()
  range_modifiers:
    asterisk:         columns 13-18        *(f())
    parentheses:      columns 14-18         (f())

See the comments in il_def.h for the an_expr_range_modifier entry and the
range_modifiers member of an_expr_node for details.

8/14/06  Memory leak when using MAKE_FRONT_END_CALLABLE

When the front end is built with MAKE_FRONT_END_CALLABLE == TRUE, memory used
for memory allocation entries beyond the initial SIZE_MEMORY_ALLOCATION_TABLE
entries were not freed properly.  This has been fixed.

8/11/06  Remark for undefined preprocessing identifier

The diagnostic issued when an undefined identifier is used in a
preprocessing expression has been changed to display the name of the
identifier.  For example:

  #define A (B+1)
  #if A > 0       // Diagnostic now refers to "identifier B"
  int i;
  #endif

8/11/06  GNU compatibility: Enum attributes

In GNU mode, the front end previously accepted attributes on enumeration types
only when those attributes followed the type definition.  They can now also
appear after the keyword "enum".  For example:

  enum __attribute((packed)) E { e1, e2, e3 };  // Now accepted in GNU mode.

Such attributes are ignored (with a warning) if the enum declaration is not a
definition:

  enum __attribute((deprecated)) D;  // Attribute is ignored (with a warning).

8/11/06  Microsoft compatibility: Secondary specifiers

Microsoft C++ compilers allow decl-specifiers to appear after a comma
separating multiple declarators (we call these "secondary specifiers").
For example:

  int i, char *p;

(This is mostly likely to appear in for-init declarations.)  The front end now
emulates this behavior in Microsoft C++ mode when microsoft_version >= 1000.
Many secondary specifiers still result in an error, and many others (including
cv-qualifiers) are ignored with a warning.  "Primary cv-qualifiers" are
preserved, however.  For example:

  int i1, char const* s1;       // s1 has type char* ("const" ignored with
                                // a warning).
  int const i2, char* s2;       // s2 has type char const*.
  int i3, extern char* s3;      // "extern" is ignored with a warning.
  int i4, extern "C" char* s4;  // Syntax error.

Unlike Microsoft compilers, the front end does not accept such constructs for
class member declarations.  For example:

  struct S {
    int i, char *s;    // Still an error.
  };

The C++-generating back end will render entities declared in this way as
separate declarations (each terminated by a semicolon), except when dealing
with for-init declarations (where a semicolon would be invalid).

8/9/06   Microsoft compatibility: Diagnostics on some __declspec attributes

The front end now warns about declarations without a declarator that contain
a __declspec(dllimport) or __declspec(dllexport) construct that can only apply
to a declarator.  For example:

  __declspec(dllexport) struct S {};  // Now a warning (the __declspec
                                      // attribute does not apply to the type).

Other __declspec constructs (e.g., __declspec(novtable)) used in this way
previously triggered a discretionary error and are now diagnosed with a
(clearer) warning instead.

  __declspec(novtable) struct S {};  // Previously a fairly generic error.
                                     // Now a more specific warning.

Furthermore, the diagnostic reporting that __declspec(dllimport) or
__declspec(dllexport) constructs are ignored when applied to C mode structs
has been reworded for clarity.  For example:

  struct S __declspec(dllimport) S;  // __declspec has no meaning in C.  Now
                                     // a clearer warning in C mode.

8/7/06   Typo in IL display output

The IL display program erroneously output "tk_complex" for imaginary types.
It now correctly outputs "tk_imaginary" for such types.

8/7/06   GNU compatibility:  __builtin_clog

In GNU mode, the front end now accepts the built-in functions __builtin_clog,
__builtin_clogf, and __builtin_clogl.

8/4/06   C++-generating back end: pointer casts involving temporaries

The C++-generating back end incorrectly generated some casts involving
pointers to temporary class objects as casts to reference types.  This is
now fixed.  For example:

  struct B { };
  B f();

  struct D: public B { };
  D g() {
    return *(D*) &(f());  // Previously generated as "(D &)f()"
  }

8/3/06   Sun compatibility: searching for system header files

Version 3.8 introduced a Sun compatibility feature that allowed the front
end to implicitly search for a file with a .SUNWCCh suffix in certain cases.
When searching for a file such as <stddef.h>, the front end would first
look for stddef.h and then for stddef.h.SUNWCCh, but the search should have
been done in the opposite order.  This has been fixed.

8/3/06   GNU C++ compatibility: typeof and "names for linkage purposes"

Standard C++ allows unnamed class types to have a "name for linkage purposes"
through typedef declarations.  For example:

  typedef class {} C;  // "C" is the name for linkage purposes of the
                       // class type being defined.

In GNU C++ mode, this can now also be achieved by a typedef for a typeof
construct.  For example:

  struct {} x;
  typedef typeof(x) S;   // "S" is the name for linkage purposes.
  typedef typeof(x) S2;  // "S2" isn't the name for linkage purposes,
                         // because one is established already.

A consequence of this change is that after such a typedef the type can be
used as a template type argument.  E.g., with the above declarations:

  template<typename> struct G {};
  G<typeof(x)> g;  // Valid because typeof(x) acquired linkage through the
                   // typedef above.

8/3/06   Microsoft compatibility: enum qualified names

In Microsoft mode, when microsoft_version is >= 1400, both member and
nonmember enum types may be used as the qualifier in a qualified name.
A warning is issued.  When microsoft_version is < 1400, the behavior is
unchanged (only member enum types may be used as qualifiers in Microsoft
mode, with no diagnostic).

  enum E { e };
  E my_enum = E::e;

8/2/06   Spurious error on member pointer-to-member declaration (Microsoft)

In Microsoft C++ mode, the front end issued a spurious syntax error on
certain pointer-to-member declarations in class template definitions.
For example:

  template<typename> struct R;
  template<typename T> struct S {
    typedef typename R<T>::I I;
    I (T::*pmf)();
  };

This bug was introduced in version 3.8 and is now fixed.

8/1/06   Build error when REPRESENT_EMPTY_STATEMENTS_IN_IL is FALSE and
         EXTRA_SOURCE_POSITIONS_IN_IL is TRUE

Version 3.8 of the front end failed to build in configurations that set
REPRESENT_EMPTY_STATEMENTS_IN_IL to FALSE and EXTRA_SOURCE_POSITIONS_IN_IL
to TRUE (the compilation error was in function empty_statement(), in
file statements.c).  This is now fixed.

8/1/06   GNU C compatibility: asm not a keyword in gcc C99 mode

In gcc C99 mode, "asm" is not a keyword.

8/1/06   Internal error when reducing severity of nesting depth error

When the severity of the nesting depth mismatch discretionary error is reduced
(e.g., with the --diag_warning=776 option), an internal error could result
on a friend declaration that refers to a member of the current class template.
Now fixed.

  template <class T> class A {
    template<class U> class B;
    template<class U> friend class A::B;
  };
  A<int> ai;

8/1/06   Designated initializers in C++ mode

The front end no longer accepts designated initializers for non-POD types in
GNU C++ mode (and other C++ modes that accept designated initializers).
For example:

  struct S { S(); ~S(); };
  S[3] = { [2] = S() };  // No longer accepted in GNU C++ mode.

This restriction is introduced to avoid difficult issues concerning the order
of construction and destruction of the various part of an object.

8/1/06   Spurious access error on explicit instantiation (GNU, Microsoft)

Version 3.8 of the front end introduced a bug that caused spurious access
errors to be issued on explicit instantiation directives (such directives are
normally exempt from the usual access checking rules) in Microsoft and GNU
(gnu_version < 30400) modes.  For example:

  template<typename> struct S {};
  class C { struct N; };
  template struct S<C::N>;  // Previously a spurious access error in some
                            // modes.

This is now fixed.

7/27/06  Failure to lower a designated initializer in a dynamic initialization

IL lowering failed to lower a designated initializer in a C++-mode
file-scope dynamic initialization (e.g., in GNU C++ mode).  As
a consequence, the back end received a constant kind it did not
expect.  Now fixed.

  int f();
  struct { int i; int j; } x = { .i = f(), .j = 2 };

7/27/06  Memory region problem with RECORD_CONSTANT_EXPRESSIONS_IN_IL

In versions that have RECORD_CONSTANT_EXPRESSIONS_IN_IL set to TRUE
(e.g., C++-generating back end versions), the change of 4/28/06
broke certain cases that involve a sizeof in a constant expression
inside a function.  The IL created had some memory region problems,
which could cause an abort in the IL write/read routines or in
a back end.  Now fixed.

  const long N = 32; 
  void WriteData() {       
    char szBuf[N + sizeof("")];
  }

7/26/06  Dropping qualifiers when binding reference in overload resolution

Overload resolution's handling of dropping of cv-qualifiers when
binding a reference for an argument where the argument and parameter
underlying types are not reference-related has been corrected.
Formerly, a case like the following got a spurious error:

  template <class T> void max(const T&, const T&);
  void foo(long a, volatile long b) {
    max<int>(a,b);
  }

7/25/06  Potential build problem when compiling the front end as C++

Version 3.8 of the front end introduced the macro "string_type", which could
conflict with uses of that same identifier in the C++ standard library (when
the front end was compiled as C++ code).  The conflict did not manifest itself
in normal builds, but could occur in other code that includes some of the
front end headers.  This is now fixed: "string_type" is now an ordinary
function.

7/25/06  GNU C++: adjustment on rvalues used as lvalues

As part of the change of 7/17/05, a couple of cases where g++ allows
rvalues to be used as lvalues were accidentally disabled for
gnu_version >= 40000 even though g++ 4.0 does still accept them.
They are once again accepted.

  struct Vector {
    float x;
  };
  void glLightfv(const float*);
  void foo() {
    glLightfv(&(Vector().x));  // Once again accepted in g++ 4.0 mode
  }

7/25/06  GNU compatibility: Attribute "weakref"

In GNU C and C++ mode, the front end now accepts attribute "weakref" when
gnu_version >= 40100.  A variable or function defined with this attribute is
an alias for another entity, but references to the weakref declaration do not
require the referenced entity to be defined.  When gnu_version < 40200, the
attribute must appear on a declaration with external linkage; otherwise, it
must appear on declaration with internal linkage.  For example:

  int a;
  extern int b __attribute__((weakref("a")));  // Okay only when
                                               // gnu_version < 40200.
  static int c __attribute__((weakref("a")));  // Error only when
                                               // gnu_version >= 40200.

As with attribute "alias" the front end currently resolves the reference by
looking it up as an unqualified name.  This addresses the known cases, which
either occur in C mode or in C++ with C name linkage.  However, it is
different from the GNU compilers: They handle the reference through the
assembler (and therefore use mangled names).

7/25/06  Dependent call processing and multi-level operator->

In versions that do dependent name processing on calls (e.g., strict
mode and g++ mode with gnu_version >= 30400), multi-level operator->
substitution on -> operators inside templates did not work right
if the substitutions involved more than one function that is
nondependent.  Now fixed.

  struct A {
    void foo();
  };
  struct Accessor {
    A* operator->();
  };
  struct Ptr {
    Accessor operator->();
  };
  template <typename T> struct B {
    void goo() { Ptr p; p->foo();}  // Formerly got spurious error
  };
  template class B<int>;

7/20/06  Microsoft compatibility: macro arguments used both standalone and
         concatenated in one expansion

The change to Microsoft-mode macro expansion described in the 4/15/06 entry
introduced a bug that caused concatenation of certain macro arguments not
to be performed correctly if the argument also appears in the expansion in
unconcatenated form.  This is now fixed.  For example:

  #define y z
  #define A(x) x x##y
  #define B(x) A(x)
  B(xx)    // Previously expanded as "xx xxz", now correctly as "xx xxy"

7/19/06  GNU C compatibility: Spurious error on struct variable in specific
         register

In GNU C mode (but not in GNU C++ mode), the front end incorrectly diagnosed
a struct variable allocated in a specific register as not having a POD type.
For example:

  register struct { int i; } reg __asm("ax");
                     // Previously triggered a spurious error in GNU C mode.

That is now fixed.

7/19/06  Microsoft and GNU compatibility: Qualified anonymous unions

In GNU and Microsoft C++ modes, namespace-scope anonymous unions can now be
qualified with const and/or volatile.  A warning is issued in such cases.
For example:

  static const union { int x; float y; };  // Now accepted in GNU and
                                           // Microsoft C++ modes.

The qualifier is ignored in GNU C++ modes when gnu_version >= 40002.
The front end already allowed qualified anonymous unions in class scope in
Microsoft and GNU modes, and ignored the qualifier in all cases.  Now, the
qualifier is applied to the implicit anonymous field generated for such
anonymous union in GNU C++ modes with gnu_version < 30400.  For example:

  struct S { const union { int x; float y; }; } s;
  void f() {
    s.x = 3;  // Error in GNU C++ mode when gnu_version < 30400.
  }

In modes other than GNU and Microsoft C++, attempting to qualify an anonymous
union is interpreted as a declaration with a missing declarator (as opposed to
an anonymous union).  This results in an error in strict mode, or a warning
otherwise.

7/19/06  Errors when compiling IL display utility

When PROTOTYPE_INSTANTIATIONS_IN_IL is configured TRUE, building the IL
display utility resulted in compilation errors (in il_display.c).  This
is now fixed.

-------------------------------------------------------------------------------
Version 3.8, July 14, 2006

7/12/06  IL version number changed to 3.8

7/11/06  C++-generating back end: omitted qualification of names hidden by
         the injected class name

The C++-generating back end failed to generate proper qualification for a
use of a name from a containing scope that is hidden by the injected class
name when the class is defined outside its containing class or namespace.
This is now fixed.  For example:

  typedef int I;
  namespace O {
    struct I;
  }
  struct O::I {
    ::I i;    // Previously generated as "I i;"
  };

7/11/06  C++-generating back end: incorrect qualification in incomplete
         class declarations

The C++-generating back end sometimes incorrectly generated an incomplete
class declaration using a qualified name.  This has now been fixed.  For
example:

  namespace N {
    struct S;
  }
  struct S;
  struct S;   // Previously generated as "struct ::S;"
  using namespace N;

7/10/06  Microsoft compatibility: typedefs and elaborated-type-specifiers

MSVC++ allows typedefs and elaborated-type-specifiers to be used together
in non-standard ways: an elaborated-type-specifier appearing in a class
context injects the named type into the surrounding non-class context,
hiding (instead of conflicting with) an existing typedef in that scope, and
an elaborated-type-specifier with a qualified-id can be used to refer to a
typedef member of the named class.  The front end has been changed to accept
these elaborated-type-specifiers in Microsoft bugs mode.  For example:

  typedef enum { e1 } E1;

  struct S {
    static enum E1 se1;   // new ::E1 injected, hiding old ::E1
    typedef enum { e2 } E2;
  };

  enum E1 { e1x };        // okay: define new ::E1
  E1 S::se1 = e1x;        // okay: use new ::E1's enumerator

  enum S::E2 se2;         // now accepted

7/6/06   GNU and Microsoft compatibility: extended integral constants

GNU and Microsoft C++ modes now accept some additional nonstandard
kinds of expressions as integral constant expressions.  The cases
now accepted are generally some variant of expr->k, where k
is a constant-valued member.

7/5/06   Address of Microsoft dllimport variable is not a constant

IL lowering sometimes generated generated initializations to the
address of a dllimport variable as if the variable's address is a
constant, but in fact it isn't.  Now fixed (such initializations
are now dynamic).

  #define DLLIMPORT __declspec(dllimport)
  struct DLLIMPORT CObject1 {};
  extern "C" DLLIMPORT CObject1 ObjOne;
  CObject1* ObjOnePtr = &ObjOne;

6/30/06  GNU C++ compatibility: invalid aggregate initialization of template
         static data member

The g++ compiler accepts an invalid aggregate initialization in the
definition of a template static data member (the error is diagnosed if
the static data member is instantiated).  We now emulate this behavior
when parsing nonclass templates in g++ mode (e.g., gnu_version >= 30400).

  struct A {
    A(double val);
  };
  template <class T> struct B {
    static const A I[1];
  };
  template <class T> const A B<T>::I[1]= { {1.,0.,0.,0.} };

6/28/06  Microsoft compatibility: spurious "unexpected function type"
         error

Version 3.6 introduced a problem that could cause a spurious "instantiation
result in unexpected function type" error in Microsoft mode.  The problem
would occur if, during a class definition, the partial instantiation of
a member template of another class was performed.  Now fixed.

  template <class T> struct A {
    template <class T2> A(const T2&) {}
  };
  template <class T> struct B {
    static const int i = sizeof(A<int>(1.0));
  };
  B<char> b;

6/23/06  Infinite loop processing redefine_extname pragma in multiple
         translation unit mode

In configurations with COMPILE_MULTIPLE_TRANSLATION_UNITS set to TRUE, a
redefine_extname pragma triggered an infinite loop.  This is now fixed.

6/17/06  Certain lowered EH operators have no side effects

The partially-lowered exception handling operators
leck_caught_object_address and leck_thrown_object_address
are now considered by the side-effect testing routines to have no
side effects.  This fixes an abort in lower_temp_init in lower_init.c
during processing of a throw of an optimizable rvalue class object
when DO_FULL_PORTABLE_EH_LOWERING is FALSE.

  struct A {
    A() {};
  };
  int main() {
    try {
      A a;
      int x = 0;
      throw x ? a : A();
    }
    catch(A abc)
    {
    }
  }

6/16/06  Microsoft, GNU, and Sun compatibility: redefinition of predefined
         macros

The front end now more closely mimics the processing of these compilers when
an attempt is made to redefine a predefined macro.  In all three cases, a
"benign" (identical) redefinition on the command line is quietly accepted;
otherwise, no distinction is made between definitions on the command line
and in the source code.  In Microsoft mode, a warning is issued and the
redefinition is ignored; in GNU mode, a warning is issued and the macro is
redefined; and in Sun mode, a discretionary error is issued and the
redefinition is ignored.

6/15/06  C-generating back end: qualified array typedefs

When the elements of a const-qualified array are to be initialized by
executable code (either in the original source or because of lowering), the
array declaration in the generated code must not be const-qualified in
order to permit the initialization.  However, the C-generating back end
generated a const-qualified declaration in some cases involving typedefs.
This has now been fixed.  For example:

  struct S { S(); };
  typedef S S_array[1];
  typedef const S_array const_S_array;
  const_S_array x;    // Previously generated as "const S_array x;"
                      // Now generated as "S_array x;"

6/14/06  C++-generating back end, Microsoft compatibility: selection of
         generated code target

The meaning of MSVC_IS_GENERATED_CODE_TARGET has been slightly changed.
Previously, if this value was TRUE, MICROSOFT_DIALECT_IS_GENERATED_CODE_TARGET
defaulted to and was required to be TRUE also.  As a result, this setting
could not be used with CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT set to TRUE.
Now, when BACK_END_IS_CP_GEN_BE and CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT
are both TRUE, MSVC_IS_GENERATED_CODE_TARGET is ignored unless the source
dialect is Microsoft mode; in Microsoft mode, it has its normal effect on the
generated code.

6/13/06  C++-generating back end, GNU compatibility: spelling of
         __alignof__

When generating code for g++, the C++-generating back end transformed the
keyword __alignof__ appearing in a template definition into __ALIGNOF__,
which is not recognized by g++.  Now fixed.

6/13/06  C++-generating back end, Microsoft compatibility: spelling of
         __FUNCSIG__

When generating code for the Microsoft dialect, the C++-generating back end
transformed the keyword __FUNCSIG__ appearing in a template definition into
__PRETTY_FUNCTION__, which is not recognized by Microsoft compilers.  Now
fixed.

6/12/06  End position of empty statement

In configurations with EXTRA_SOURCE_POSITIONS_IN_IL and
REPRESENT_EMPTY_STATEMENTS_IN_IL set to TRUE, the front end previously left
the end_position of stmk_empty statements as the null source position.  Now
fixed.

6/11/06  C++-generating back end: missing qualifier in pointer-to-member
         constant

In configurations where RECORD_FORM_OF_NAME_REFERENCE is TRUE, a
pointer-to-member constant referring to a member of an instance of a class
template was generated with a missing or incorrect qualifier if the
pointer-to-member expression triggered a template instantiation.  Now fixed.
For example:

  template <class T> struct S {
    bool b() const { return false; }
  };

  void f() {
    &S<int>::b;    // Formerly generated as &b in some modes
  }

6/9/06   Abort with FULLY_RESOLVED_MACRO_POSITIONS with inert macro names

In configurations in which FULLY_RESOLVED_MACRO_POSITIONS is TRUE, an abort
could occur (depending on the value of uninitialized memory) if an inert
(recursively-invoked) macro name is used as a macro argument and the
corresponding parameter is followed by a concatenation operator.  This is
now fixed.  For example:

  #define X(a) Y(X, a)
  #define Y(a, b) Z(a, b)
  #define Z(a, b) a ## b
  int X(1);

6/9/06   GNU compatibility: Attributes "aligned" and "packed" on bit fields

In GNU mode, the front end effectively ignored (for layout purposes) any
attribute "aligned" that appeared on a bit field also declared with an
attribute "packed".  Now the attribute "aligned" takes effect.  For example:

  struct S {
    char c;
    int i:6  __attribute__((packed)) __attribute__((aligned));
  };  // Previously, sizeof(struct S)==2; now, sizeof(struct S)==16

6/9/06   Abort after function redeclaration with incompatible name linkage

The front end previously aborted on some error cases involving the
redeclaration of a function with internal linkage first declared with
extern "C" name linkage.  For example:

  extern "C" namespace N {
    extern void f();
    static void f();      // Error: incompatible linkage
  }
  namespace N {
    static void f() {}    // Previously triggered an abort.
  }

(The abort occurred in schedule_move_to_current_end_of_routines_list.)
This is now fixed.

6/8/06   Duplicate error on invalid using-declaration

Class members designated by a using-declaration in a derived class must be
visible in a direct base class of that derived class.  When a using-
declaration refers to an overload set not visible in a direct base class,
the front end previously issued multiple indistinguishable errors.  Now
only one error is emitted in such cases.  For example:

  struct A { void f(); void foo(int); };
  struct B: A { void f(); };      // A::f hidden in B.
  struct C: B { using A::foo; };  // Invalid.  Previously triggered two
                                  // errors; now just one.

6/8/06   GNU compatibility: Register variable constraints

In GNU mode, the front end now emits an error for initializers appearing on
variables with static storage duration that have been mapped on a specific
register using the GNU construct asm("register-name").  For example:

  register int rA asm("%eax") = 5;  // Now an error.

Furthermore, attempts to place variable with non-POD class types in specific
registers are now also diagnosed with an error.  For example:

  struct S { ~S(); };
  register S rA asm("%eax");  // Now an error.

6/8/06   C++-generating back end: name hiding by function parameters

The C++-generating back end formerly generated incorrect code when the name
of a parameter was the same as that of an entity used in a subsequent
parameter declaration.  This has now been fixed.  For example:

  struct S { };
  void f(int S, struct S s) { }  // Previously generated as f(int S, S s)

6/8/06   Default function call arguments on non-function declarations

Standard C++ only allows default function call arguments on function (and
member function) declarations; not e.g. on typedefs of function types or
declarations of pointers to functions.  Previously, the front end only
diagnosed violations of this rule in strict mode.  Now a discretionary error
is issued in all modes, except in Cfront modes, Microsoft C++ mode with
microsoft_version <= 1300, and GNU C++ mode with gnu_version < 30400 (in
these modes, a remark is issued instead).  For example:

  typedef void (*f)(int = 3);  // Now a discretionary error in most modes.

6/6/06   Template deduction, sizeof reference type

When template deduction dealt with a sizeof applied to a reference
type, it incorrectly used the size of the reference instead of the
size of the underlying type.  Now fixed.

  template <int I> struct A {
    int X[I-I];
  };
  template <> struct A<1> {
    A(int){}
  };
  template <class T> void f(A<sizeof(T)>){}
  int main() {
    typedef char (&x)[1];
    f<x>(0);
  }

6/6/06   C mode abort in r_declarator on severe syntax error

In C mode, some unusual syntax errors could lead to an abort in the function
r_declarator (declarator.c).  For example:

  void f(x([));  // Triggered an abort in C mode.

This is now fixed (ordinary errors are issued).

6/6/06   Sun compatibility: Nonstandard friend template declaration

In Sun mode, the front end now treats as a friend template declaration a
declaration that uses ordinary friend class syntax while naming a class
template.  For example:

  template<typename T> class A;
  template<typename T> class B {
    friend class A;  // Accepted in Sun mode (with a warning), and treated as
  };                 // "template<typename> friend class A;".

(This extension was already implemented in Microsoft mode.)

6/6/06   GNU and Sun compatibility: Extraneous global scope qualification

In GNU C++ mode, the front end already accepted declarations with a global
scope qualifier even when the declaration is not a redeclaration.  E.g.,

  int ::x;  // Already accepted in GNU C++ mode.  Now also in Sun mode.

Such declarations are now also accepted in Sun mode.  Furthermore, similar
invalid template declarations are now also accepted in GNU and Sun modes.
Previously, they were only accepted in GNU C++ modes that also enabled
dependent name processing (the default when gnu_version >= 30400).
For example:

  template<class> void ::f();  // Now accepted in all Sun and GNU C++ modes.

A warning is issued on such cases.

6/6/06   GNU compatibility: __builtin_offsetof revisited

Version 3.7 introduced support for the GNU __builtin_offsetof operation.
Our initial implementation required that the second argument be a simple
(but possibly qualified) field name.  However, GNU compilers accept multilevel
field selections as well as constant array subscripts.  We now emulate that
behavior.  For example:

  struct F {
    int a[20];
  };
  struct S {
    struct F f[10];
  };
  double x[__builtin_offsetof(S, f[2].a[4])];

Previously, the second operand of a bok_offsetof node (the IL representation
of a __builtin_offsetof construct) was an enk_field node.  That is now no
longer the case (IL CHANGE): The second operand is now an expression tree
representing an access of the indicated member (applied to a placeholder
operand represented by a null pointer constant).

6/5/06   Spurious error on destructor call during prototype instantiation

In modes in which nonclass prototype instantiations are performed (strict
mode, g++ mode when gnu_version is >= 30400, etc.), a spurious error could
result when a destructor was called on a template parameter type (in the
example below the expression p->g() is considered to have a template
parameter type in our implementation) and the destructor was named using
a class or class template specialization name.  Now fixed.

  template <class T> struct A {
    ~A(){}
    A<T> *g();
  };
  template <class T> struct B {
    void f(A<T> *p) {
      p->g()->~A<T>();
    }
  };
  int main() {
    B<int> b;
    A<int> *a;
    b.f(a);
  }

6/5/06   C++0x mode: empty macro arguments

In C++0x mode, the front end no longer issues a warning for empty macro
arguments.  This extension was voted by the C++ Standard Committee into the
working paper for the next Standard at the October, 2005 (Mont Tremblant)
meeting by adoption of paper N1653 = J16/04-0093 (as amended).

6/1/06   Float to integer conversions when built with MSVC 7.1

When the front end was configured with INTEGER_VALUE_REPR_IS_A_HOST_INTEGER
set to TRUE and built with MSVC 7.1, compile-time conversions from a
floating point constant to an integral type would fail with the message,
"floating-point value does not fit in required integral type."  The culprit
was an incorrect definition for LLONG_MIN in the Microsoft-supplied limits.h
header (corrected in MSVC 8.0).  The front end now detects that incorrect
value and uses an alternate definition in setting MIN_INTEGER_VALUE.

6/1/06   Error in constant folding in unevaluated first argument of "?"

The front end incorrectly gave an error on a constant expression that
cannot be folded to a constant when it appears as the first operand
of a "?" operator in a constant expression in a context that is not
evaluated.  Now fixed.

  int a = (1) ? (1) : (((1 << -3)>0) ? 1 : 2); /* Got spurious error in
                                                  C mode. */

5/31/06  Entities that are both explicitly specialized and instantiated

The diagnostic issued when an entity is both explicitly specialized and
explicitly instantiated has been reduced in severity from an error to
a warning, except in strict mode where it is now a discretionary error.

  template <class T> struct A {
    void f(){}
  };
  template <> void A<int>::f() {}
  template void A<int>::f();

5/31/06  C++0x mode: variadic macros

In C++0x mode, the front end now accepts C99-style variadic macros (see the
Changes entry of 7/1/99).  This extension was voted by the C++ Standard
Committee into the working paper for the next Standard at the October, 2005
(Mont Tremblant) meeting by adoption of paper N1653 = J16/04-0093 (as
amended).

5/30/06  C++-generating back end, GNU compatibility: base classes nested
         inside other base classes

Given a derived class, one of whose base classes is a nested class of another
of its base classes, all versions of g++ incorrectly require that a
qualified-id be used when referring to the nested class name from the scope of
the derived class.  The C++-generating back end has been changed to generate
qualified-ids in such cases when gcc_is_generated_code_target is TRUE.  For
example:

  struct A {
    struct B {
    };
  };

  struct D: A, A::B {
    void f(A::B b);    // Formerly generated as "f(B b)"
  };


5/26/06  Implicit int rules

The default severity of the diagnostic for declarations that are missing a
type specifier (which is implicitly assumed to be "int", to parallel the C89
and ARM C++ rules) has been raised to "discretionary error".  In Microsoft and
Cfront modes, the diagnostic is still a warning.  In addition, the front end
is now often able to detect that an "implicit int" was intended for the
declaration of a member function of a class template with dependent base
classes.  For example:

  template<typename T> struct B {};
  template<typename T> struct D: B<T> {
    f();  // Now recognized as a member function declaration (and accepted
  };      // with a warning in Microsoft mode).  Previously, "f" was always
          // assumed to name a type, which resulted in a variety of syntax
          // errors.

This change improves compatibility with Microsoft C++ compilers.

5/25/06  Cost of promotion from enum in overload resolution for builtin
         operator

In some cases, overload resolution failed to consider the cost of the
conversion from an enum type returned by a conversion function to
an integral type as a promotion (it always counted as a standard
conversion).  Now fixed.

  enum enumtype {
    large_enum_val     = 4294967295U,  // Force enum type to be unsigned
    small_enum_val     = 5
  };
  struct unsignedconv {
    unsignedconv(unsigned int);
  };
  struct enumoper {
    operator enumtype() const;
  };
  bool operator==(unsigned int, const unsignedconv&);
  bool yuk(enumoper eo) { return eo == 1U; }  // No longer ambiguous

5/24/06  GNU compatibility: Typedefs with adjectives

In GNU C++ mode with gnu_version >= 30400, the front end now accepts sign and
size adjectives (like "short" and "unsigned") preceding a typedef for an
integer type in certain contexts.  (The similar case with adjectives following
the typedef name was already accepted in many GNU modes.) For example:

  typedef long long I64;
  void f() {
    I64 unsigned y;       // Already accepted previously in many GNU modes.
    y = (unsigned I64)3;  // Now accepted in GNU C++ 3.4 mode.
    unsigned I64 x;       // Still invalid in any GNU mode.
  }

5/24/06  Memory leak when using MAKE_FRONT_END_CALLABLE

When the front end is built with MAKE_FRONT_END_CALLABLE == TRUE, memory
that is allocated as part of a memory region could be leaked when a
compilation terminates abnormally (via a catastrophic error, internal error,
etc.).  This has been fixed.

5/24/06  Microsoft compatibility: more on ADL and friend injection

An additional tweak on the changes of 3/10/04 to emulate the argument-
dependent lookup and friend lookup behavior of MSVC++ 7.1:  Now,
if the name found by normal lookup in such cases is a namespace
member, the special processing is suppressed.

  class A {};
  class B {
  public:
    B(const A &);
    friend bool operator<(const B&b1, const B&b2) {
        return b1.c(b2);
    }
    int c(const B &) const;
  };
  namespace ns0 {
    template<typename X> void bar(X x) {
      x < x;  // No longer an error here with -tused and
              // microsoft_version == 1310
    }
    class C;
    bool operator<(const C&, const C&);
  }
  void foobar() {
      A a;
      ns0::bar(a);
  }

5/22/06  Typedef redeclarations in C mode

In C modes, duplicate typedef declarations with incompatible underlying types
are now diagnosed in the same way as in C++ mode.  In particular, the error
now indicates where the earlier typedef declaration occurred.  For example:

  typedef int S;    // Line 1.
  typedef float S;  // Now triggers the same diagnostic in C and C++ modes.
                    // The error refers to "line 1".

Other typedef redeclaration diagnostics (e.g., with compatible types) have not
changed.

5/22/06  Memory corruption problem, IA-64 ABI termination routines

When IL lowering generated a termination routine to destroy a local
static variable that is an array of destructible class type in the
IA-64 ABI, the parameter variable for the generated function was
allocated in the wrong memory region.  As a consequence, back
ends might have aborted if the memory for the variable had been freed
or overwritten by the time it was used.  Now fixed.

5/22/06  Const string literals in Sun mode

String literals are now considered to have const type in Sun C++ mode,
since that appears to be what all recent versions of the Sun compiler
do.

5/22/06  Assignment to "this" and IA-64 ABI mode

The assignment-to-this anachronism can now be permitted in IA-64 ABI
versions by setting ASSIGNMENT_TO_THIS_ALLOWED to TRUE, as long as
DO_IL_LOWERING is FALSE.  The --anachronisms option or the like is still
required to turn the feature on.

5/22/06  Sun mode: do-nothing reinterpret_cast allowed

Sun mode now allows a reinterpret_cast that does nothing (e.g., int --> int,
or class --> class).  A warning is issued.

  int foo() {
    int x = 3;
    return reinterpret_cast<int>(x);
  }

5/18/06  GNU and Microsoft compatibility: Anonymous unions

In GNU mode, the front end now accepts const- and volatile-qualified anonymous
union constructs in class types.  Both standard and nonstandard variations are
accepted, but nonstandard anonymous unions declared through a typedef cannot
be qualified.  For example:

  typedef union { int u; } U;
  struct S {
    const union { int i1; };  // Now an anonymous union in GNU modes.
    const struct { int i2; }; // Now an anonymous union in GNU modes.
    const U;                  // Not accepted in GNU C++ mode.  Not an
  } s;                        // anonymous union in GNU C mode.
  int main() { return s.i1; }  // Now okay in GNU mode.

Previously, Microsoft C++ mode also treated the qualified typedef case as an
anonymous union construct.  Now only Microsoft C mode does so.  This matches
the behavior of the Microsoft compilers.

5/18/06  Spurious warning on local variables in templates

When the front end is parsing templates in generic form (e.g., in strict
mode), the declaration of an otherwise unreferenced local variable previously
elicited a warning ("declared but never referenced") if the variable's type
was a template parameter.  For example:

  template<typename T> void f() {
    T x;  // Previously triggered a spurious warning in some modes.
  }

This warning was spurious since the declaration may have a side-effect
when the template is instantiated with a class type that has a nontrivial
default constructor.  This is now fixed.

5/18/06  Microsoft compatibility: overload resolution, bitwise copy constructor

A corner case has been improved in emulation of overload resolution in
Microsoft mode.  The problem case involves a class with a generated
copy constructor that does bitwise copying, a copy-initialization,
and a template conversion function.

  struct A {
    void f();
  };
  struct B {
    template <typename T> operator T() {
      T t;
      t.f();
      return t;
    }
  };
  int main() {
    A a = B();  // Caused spurious error in instantiation of template
    return 0;
  }

5/18/06  Include guard checks added to basics.h

Include guard checks have been added to basics.h.  These are not
actually needed based on the way that the front end uses basics.h, but
they have been added in case basics.h ends up being included more that
once in customer-supplied code.

5/17/06  GNU C compatibility: Ignore type qualifiers in transparent unions

In GNU C mode, top-level type qualifiers (like const or __restrict__) are now
ignored with matching functions involving transparent unions.  For example:

  struct S { int i; };
  typedef union {
    struct S const s;
  } TU __attribute__((transparent_union));
  int f(TU);
  int f(struct S);  // Previously triggered an incompatibility error.
                    // Now accepted.  (In GNU C mode.)

5/17/06  Abort on use of ambiguous class template in some Microsoft modes

In Microsoft C++ mode with Microsoft bugs mode disabled (--no_microsoft_bugs),
certain uses of an ambiguous class template could lead to an abort in
prescan_extended_decl_modifiers (disambig.c).  For example:

  namespace N { template<typename T> struct S {}; }
  using namespace N;
  template<typename T> struct S {};
  template<typename T> typename S<T>::I f();  // Previously aborted in some
                                              // Microsoft modes.

This is now fixed.

5/17/06  C++0x mode: Relaxed rules for "typename" specifier

The current C++ standard requires that uses of "typename" followed by a
qualified name only occur inside templates.  Previously, such uses outside
any template triggered a discretionary error in strict mode, and a warning
in default mode.  Now such uses are silently accepted in C++0x modes and
in default C++ mode only a remark is issued.  For example:

  struct S { struct N {}; };
  typename S::N *p;  // Accepted in C++0x mode.  A remark (instead of a
                     // warning) is issued in default C++ mode.  In non-C++0x
                     // strict mode, a discretionary error is (still) issued.

This extension was voted into the C++ committee's working paper for the next
standard in October 2005 (meeting in Mont Tremblant, through resolution of
Core issue 382).

5/16/06  Copy constructor optimization dropped cv-qualifiers

An optimization added in version 3.6 to eliminate extra copy constructor
calls in direct-initializations (see Changes entry of 3/21/05) caused the
Front End to lose cv-qualifier adjustments in some cases.  Now fixed.

  struct A {
    int value;
    A() : value(0) { }
    A(const A &a) : value(a.value) { }
    A(int value) : value(value) { }
    A add(int x) { return A(value + x); }
    static A fromValue(int value);
  };
  const A operator+(const A &a1, const A &a2)
  { return A(a1.value + a2.value); }
  int main() {
    A a2 = A(A(1)+A(2)).add(3);  // Got spurious error because "const" kept
  }

5/16/06  Microsoft: memory region problem with VC6 using-directive emulation

In Microsoft bugs mode, when microsoft_version is <= 1200, we emulate
a Microsoft using-directive bug that makes certain names visible in the
file scope when they should not be.  A refinement made to this emulation
(see 6/23/05 entry) could cause a using-directive allocated in a function
scope memory region to be added to the file scope using-directive list.
This could result in an abort, an internal error, or other incorrect
behavior.  Now fixed.

5/16/06  C++0x mode: Support for long long

If LONG_LONG_ALLOWED is configured to TRUE, the long long type is accepted in
C++0x mode.  As in C99, unsuffixed integer literals that do not fit in type
"long", but can fit in type "unsigned long", are given type "long long"
instead.  This is different from the handling of such constants in C++ modes
with type "long long" enabled, but C++0x disabled.  For example:

  bool b = 4000000000 > -1;  // b == true in C++0x mode.  b == false in
                             // default C++ mode with "long long" enabled
                             // (a warning is issued on the conversion of
                             // "-1" to an unsigned type in that case).

This extension was voted into the C++ committee's working paper for the next
standard in October 2005 (meeting in Mont Tremblant, through proposal numbered
N1811).

5/12/06  IA-64 ABI: Abort with LOWER_DESIGNATED_INITIALIZERS set to FALSE

IL lowering aborted in fill_out_aggregate_ptr_to_data_member_initialization
while processing an aggregate initializer that contains a designator
when IA64_ABI is TRUE and LOWER_DESIGNATED_INITIALIZERS is set to FALSE.
Now fixed.

  struct foo {
    long x;
  };
  struct foo bar = { .x = 2 };

5/11/06  C++0x mode: Trailing comma in definition of enumeration type

In C++0x mode, the front end now silently accepts a trailing comma in the
definition of enumeration types (even when combined with strict mode).
For example:

  enum E { e, };  // Silently accepted in C++0x mode.

This was already silently accepted in C99 and K&R C modes.  It was also
accepted with a remark in all other nonstrict modes.

This extension was voted into the C++ committee's working paper for the next
standard in April 2006 (meeting in Berlin, through resolution of Core issue
518).

5/11/06  C++0x mode: Mixed string literal concatenations

In C++0x modes and in default C++ mode, the front end now accepts string
literal concatenations involving an ordinary char string literal and a wide
string literal.  For example:

  wchar_t *str1 = L"a" "b";  // Okay, same as L"ab".
  wchar_t *str2 = "a" L"b";  // Okay, same as L"ab".

Such constructs were already accepted in C99 and GNU modes.

This extension was voted into the C++ committee's working paper for the next
standard in October 2005 (meeting in Mont Tremblant, through proposal numbered
N1653).

5/11/06  C++-generating back end: Microsoft compatibility in casts to a
         namespace member type

Some builds of MSVC++ versions 6.0 and 7.0 have a bug in which using an
old-style cast to a type that is a member of a namespace in the default
argument of a constructor causes an internal compiler error.  (See the Changes
entry of 2/26/05 for a similar issue with nested class types.)  For example:

  struct S { } s;
  namespace N {
     struct Inner {
       Inner(S);
     };
  }
  struct Outer {
    Outer(const N::Inner& r = N::Inner(s));  // Formerly generated as
                                             // ((N::Inner)(s))
  };

thus triggering the MSVC++ bug.  Now, when msvc_is_generated_code_target is
TRUE and msvc_target_version_number is less than 1310, the default argument
will be generated as a functional cast with no enclosing parentheses:

    Outer(const N::Inner& r = N::Inner(s));

5/10/06  C++0x mode: Extended friend types

In C++0x modes and in default C++ mode, the friend class declaration syntax
has been extended to allow various additional forms.  Specifically, the use
of an elaborated class name is no longer required, and the nominated type
need not be a class type (in the latter case, the friend declaration has
essentially no effect).  For example:

  typedef struct S ST;
  typedef int const IC;
  class C {
    friend S;          // Okay in C++0x mode.
    friend ST;         // Okay in C++0x mode.
    friend int;        // Okay in C++0x mode (but no effect).
    friend IC;         // Okay in C++0x mode (but no effect).
    friend int const;  // Error: cv-qualifiers not (directly) allowed.
  };   

This extension was voted into the C++ committee's working paper for the next
standard in October 2005 (meeting in Mont Tremblant, through proposal
numbered N1791).

5/9/06   GNU compatibility: DO_C99_IL_LOWERING is required

Various GNU C features are lowered using C99 lowering.  It was previously
possible to configure the front end with DO_IL_LOWERING and
GNU_EXTENSIONS_ALLOWED set to TRUE and DO_C99_IL_LOWERING set to FALSE.
Ths combination left some IL constructs unlowered, which could result in
aborts in the C-generating back end.  Attempting to use this configuration
now results in a build-time error.  (As part of this change, consistency
checking between DO_C99_IL_LOWERING and other configuration settings has
also been tightened up.)

5/9/06   Missing virtual function table in multiple translation unit mode

The IL lowering process failed to generate a definition for a virtual
function table for a function-local class when it is compiled in
a secondary translation unit.  As a consequence, the program could
abort at runtime when it uses the uninitialized virtual function
table.  Now fixed.

5/8/06   GNU compatibility: complex floating-point types

Some of the code associated with support for GNU complex floating-point
types (see the 11/7/05 entry) had incorrect conditional compilation guards,
leading to compilation errors when C99_IL_EXTENSIONS_SUPPORTED and/or
GNU_COMPLEX_EXTENSIONS_ALLOWED are FALSE.  This has now been corrected.

5/8/06   C++0x mode: Right shift token can be two closing angle brackets

In C++0x mode, a right shift token (">>") not enclosed by parentheses or
square brackets is treated as two closing angle brackets (">") if the
right shift token appears after at least one opening angle bracket ("<")
that has not been closed.  For example:

  template<typename T> struct S { S(int) {} };
  template<int N> class C {};
  void f() {
    S<S<int>> s(1);          // Okay in C++0x mode.  Syntax error otherwise.
    static_cast<S<int>>(2);  // Okay in C++0x mode.  Syntax error otherwise.
    C<3 >> 1> c;             // Error in C++0x mode because ">>" is not
                             // as a "right shift operator".  Okay in other
                             // C++ modes.
    C<(3 >> 1)> c2;          // Accepted in all C++ modes.
  }

A new configuration macro DEFAULT_RIGHT_SHIFT_CAN_BE_ANGLE_BRACKETS allows
this feature to be enabled also in default C++ mode.

This extension was voted into the C++ committee's working paper for the next
standard in April 2006 (meeting in Berlin, through proposal numbered N1757).

5/8/06   C++0x mode

New command-line options --c++0x and --no_c++0x have been added to enable or
disable support for certain C++ extensions added to the working paper for the
next C++ standard.  The default behavior can be configured using the macro
DEFAULT_CPP0X_MODE.  C++0x mode can be combined with strict conformance mode
(--strict) to ensure maximal conformance to the working paper specifications.

5/5/06   GNU alias loops

The front end now detects attempts to create alias loops within a translation
unit.  Previously such loops were undiagnosed in ordinary compilations and
could lead to aborts when simultaneously compiling multiple translation units.
For example:

  void a(void) __attribute__((alias("b")));  // Now triggers an error.
  void b(void) __attribute__((alias("a")));

5/5/06   GNU C99 compatibility: Warn only on void return in nonvoid function

In GNU C99 mode, the front end now issues a warning instead of an error when
encountering a return statement without a return expression in a function
with a nonvoid return type.  For example:

  int f() { return; }  // Now a warning in GNU C99 mode (previously an error).

5/4/06   Sun compatibility: nonstatic data member without object, in sizeof

Sun compatibility mode now allows a use of a nonstatic data member without
an object inside a sizeof.  Ordinarily, such a reference is not valid
unless an implicit "this->" applies.

  typedef struct _X {
    char A[512];
  } X;
  static unsigned int foo() {
    return sizeof(X::A);  // Now accepted in Sun mode
  }

5/4/06   Virtual function table not generated due to strange key function

In ABIs that allow "inline" on an out-of-class definition of a member
function to affect the choice of the key or decider function for the
class (i.e., the Cfront-like ABI and the IA-64 ABI with
IA64_ABI_VARIANT_KEY_FUNCTION), IL lowering sometimes failed to
generate a virtual function table definition in the compilation
where the key function is defined.  An example:

  struct A {
    virtual ~A() {}
  };
  class X : public A {
    virtual void f1();
    virtual void f2();
  };
  void X::f2() { }
  inline void X::f1() { }  // inline here makes f2 the key function
  int main() {}

In versions that use the template prelinker to instantiate inline
functions, this was largely masked; it just meant one possible
additional iteration to instantiate the missing entities.  But in
other versions, it could result in link errors.  Now fixed.

5/3/06   Spurious access error for static member of ambiguous base class

The front end sometimes issued a spurious access error when attempting to
access a static member of an ambiguous base class.  In these situations,
the base class was public along some derivation paths, and private along
other paths.  For example:

  struct B {
    static void f();
    static void f(int);
  };
  struct C1: private B {};
  struct C2: public B {};
  struct D: C1, C2 {};
  void g(D *p) {
    p->f();  // Previously triggered a spurious access error.  Now accepted,
  }          // because the B::f() found via C2 is public.

This is now fixed.

5/2/06   Designated initializers and nonstandard anonymous unions

In C modes accepting both nonstandard anonymous unions and designated
initializers (e.g., in GNU C mode) the front end sometimes failed to resolve
field designators for elements of the nonstandard anonymous union.
For example:

  struct S {
    union { int f; };    // Nonstandard anonymous union in C.
  } s = { { .f = 1 } };  // Now accepted (previously, "f" was not found).

Such cases are now accepted.

5/1/06   IL display of GNU built-in functions

The code in il_display.c that outputs GNU built-in function descriptions used
an outdated list of supported built-in functions.  This problem was introduced
in version 3.7 of the front end and is now fixed.

5/1/06   Abort on elaborated typedef name in GNU C++ mode

In GNU C++ mode, certain erroneous uses of a typedef name in an elaborated
class name could lead to an abort in scan_tag_name (decl_spec.c).  For example:

  typedef int I;
  namespace { struct ::I; }  // Previously aborted in GNU C++ mode.
                             // Now a normal error is issued.
 
This is now fixed.

5/1/06   No zeroing code for empty classes

IL lowering now puts out no code to zero empty classes.  Formerly,
such code was suppressed only for empty base classes.

  struct A { };
  int main() {
    A *p = new A();  // No zeroing of allocated storage now
  }

4/29/06  C++-generating back end: address constants naming class or union
         members

In configurations in which RECORD_CONSTANT_EXPRESSIONS_IN_IL is FALSE, an
address constant naming a union member or a member of a class or struct at
offset 0 was generated as the name of the class/struct/union object rather
than the member name.  This has now been fixed.  For example:

  struct S {
    int i;
  } s;
  int j = s.i;  // Formerly generated as "int j = (s);"

4/28/06  Abort on sizeof, typeof, etc. when PROTOTYPE_INSTANTIATIONS_IN_IL set

In configurations with PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE, the IL
could get corrupted by uses of typeof (a GNU extension), sizeof, __alignof,
or __uuidof (a Microsoft extension) applied to a template-dependent
expression in function scope.  (E.g., when IL_SHOULD_BE_WRITTEN_TO_FILE is
also set to TRUE, this corruption frequently resulted in an internal error.)
For example:

  template<typename T> void f() {
    T x;
    typedef int X[sizeof(x)];  // Could trigger an internal error in some
  }                            // configurations.

The corruption only occurred when the function template was parsed in its
generic form (e.g., with the command-line option --parse_templates; this
option is also implicit in strict mode and in some GNU C++ modes).

This is now fixed.  IL entries representing affected typeof, sizeof, etc.
operations now have a new flag "local_expr_ref" set.  Those entries no
longer directly point to their argument expression.  Instead, the expression
can be found by searching a list of a_local_expr_node_ref nodes (a new
kind of IL entry) attached to the surrounding function scope.  This is
similar to the technique used to represent variable length array dimensions
(see Changes entry of 6/2/97).

4/27/06  Lvalue flag in traverse_expr

The traverse_expr routine now maintains a flag expr_is_lvalue in
the traversal block, which allows the call-back routine to know when
the expression being handled is considered an lvalue.

4/25/06  Sun compatibility: namespace std is predeclared

In Sun mode, the std namespace is predeclared.

  using namespace std;

4/24/06  Abort on use of __ptr32/ptr64 in nested declarator

In Microsoft mode, the front end sometimes aborted when using the Microsoft-
specific __ptr32/__ptr64 qualifiers in nested (i.e., parenthesized)
declarators.  For example:

  void (*__ptr32 g());  // Previously aborted in Microsoft mode.

This is now fixed.

4/21/06  IA-64 ABI: incorrect type_info code for initially-incomplete class

IL lowering for the IA-64 ABI sometimes generated incorrect initial
values for the type_info variables generated for classes when the
type_info is first used in a context where that class is incomplete
and then later the class is completed.  The incorrect initializer
aggregate did not match the structure of the type_info variable it
initialized, which could cause aborts in back ends (e.g., the
C-generating back end).  Now fixed.

  #include <typeinfo>
  struct A;
  void f() {
    void *p = (void*)&typeid(A*);
  };
  struct AA { };
  struct A : AA {};

4/20/06  Error on class with virtual destructor and no default operator delete

An error is now issued on a virtual destructor definition in a class
with no visible default operator delete.  This is required by core issue
252 and avoids an abort in IL lowering in define_default_version_of_routine
in lower_init.c.  No error is issued in Microsoft mode.

  struct D {
    D() {}
    virtual ~D() {}
    void operator delete(void*, void*) {}
  };
  void f() { D d; }

4/19/06  Abort on use of constructor that is both default and copy constructor

A case like the one below where a single constructor is both a default
and a copy constructor (thanks to a default argument) caused an abort
in scan_ctor_arguments in expr.c.  Now fixed.

  struct B {
    B(int i);
    B(const B& = B(0));
  };
  void f_B(){
    B* pB = new B(); // Abort on this previously
  }

4/18/06  GNU C mode: incorrect kind-of-reference warnings near possible
         lvalue casts

The latest round of changes to emulate gcc lvalue casts (see Changes
entry of 9/15/05) broke some of the kind-of-reference tracking done
in expression processing, with the consequence that set-but-not-used
warnings and the like were sometimes incorrectly issued in GNU C
mode.  Now fixed.

  void f(void* p1, char *p2) {
    *((char **) p1) = p2;  // Got spurious "set but never used" warning
                           // in gcc mode
  }

4/17/06  Microsoft compatibility: typename allowed before declarator

The Microsoft compiler allows (and ignores) the typename keyword before
the declarator of a member of a class template declared outside of its class.
This is now accepted in Microsoft mode (with a warning).

  template <class T> struct A {
    int f(int);
  };
  template <class T> int typename A<T>::f(int) {}

4/16/06  C-generating back end: gcc output and empty struct initializer

The C-generating back end has historically put out a dummy field
to avoid putting out a struct with no fields.  A change of 11/16/04
suppressed this when running in gcc mode and when generating
code to be consumed by gcc.  Unfortunately, the other half of
this trick, the one that put out a dummy 0 initializer for the
dummy field, was not suppressed at the same time.  As a consequence,
the generated code for an example like

  struct A { } a = {};

had an excess zero initializer.  gcc ignored this with a warning,
so it wasn't terribly visible, but it was still wrong and has now
been fixed.

4/16/06  No cv-qualifiers on copy assignment operator

Cases like the following got an ambiguity error on generation of the
copy assignment operator:

  struct B {
    int x;
    B& operator=(B);
    B& operator=(B) volatile;
  };
  struct A {
    struct B a;
    struct B b;
  };
  void test(void)
  {
    A p0;
    A p1;
    p0=p1;
  }

That's because both of the operator= functions were seen as "copy
assignment operators" by the definition of 12.8p9 of the C++
standard.  However, operator= functions with cv-qualifiers
should probably not be considered to be "copy assignment operators,"
since the concept has to do with generated functions that copy
normal objects.  We've changed the implementation of the definition
in the Front End, and we're raising a core issue with the standards
committee.

4/15/06  Microsoft compatibility: commas in macro arguments

The Microsoft preprocessor gives special treatment to commas appearing in
the substituted text of macro arguments: if that text appears as a macro
argument when rescanned for further expansion, such commas do not delimit
macro arguments.  The front end has now been modified to emulate this behavior
in Microsoft mode.  For example:

  #define M1(a) M2(a)
  #define M2(a) a
  #define XY x,y
  M1(XY)    // Formerly warned of "too many arguments" and expanded to "x"
            // Now expands to "x,y" with no warning

4/14/06  Needed flag for specialized static data member without definition

A template static data member that was named in an explicit specialization
declaration (but not a definition) was incorrectly considered to be needed.
This could potentially cause a linker error if the specialization was
never defined.  A linker error could only occur if the linker requires
the definition of an entity appearing in an extern declaration even if that
entity is not otherwise referenced by the program.  The needed flag is
no longer set for such cases.

  template <class T> struct A { 
    static int i;
  };
  template <> int A<int>::i;

4/14/06  Abort on cast to reference with extraneous cv-qualifier

Version 3.7 of the front end introduced a bug that caused the front end to
abort in cast_type_pre_check (expr.c) when processing a cast to a typedef for
a reference type additionally qualified with const and/or volatile.  For
example:

  typedef int &R;
  int i = (R const)i;  // Aborted in version 3.7.

This is now fixed.

4/14/06  Infinities and NaN in generated GNU C and C++ code

Floating point infinities (resulting, for example, from overflow when
converting a floating point literal to the internal representation) were
represented in the output of the C- and C++-generating back ends by the
expression 1.0/0.0, and similarly for NaNs (0.0/0.0).  Although gcc accepts
these forms silently, g++ warns of division by zero.  Consequently, the C-
and C++-generating back ends now use the appropriate GNU formats when
gcc_is_generated_code_target, depending on gnu_target_version_number.  For
example:

  double d = 1e5000;  // 29600 <= ver <  30300: "__extension__ 0x1.0p2047"
                      //          ver >= 30300: "__builtin_huge_val()"

4/13/06  Address of template function with explicit arguments in overload
         resolution

Overload resolution's analysis of argument matching now considers
an argument that is a template function with explicit arguments
as equivalent to a single non-overloaded function.  (This is
part of the resolution of core issue 115.)

  struct A {
    template <class T> void foo();
  };
  struct B : public A { };
  typedef void (B::*pmb)();
  void f(int);
  void f(pmb);
  int main() {
    f(&A::foo<int>);
  }

4/13/06  Overloaded function passed to reference to const pointer in
         overload resolution

Overload resolution now correctly handles a case where the address
of an overloaded function is passed as an argument to a parameter
of type reference to const pointer to function of the type of one
of the members of the overload set.  Formerly, it failed to
consider that a reference to const could match a pointer
produced by the function-to-pointer decay.  Such cases did
work correctly when the called function is not overloaded.

  struct A {
    typedef void (*fptr)();
    A(const fptr&);
  };
  void func();
  void func(int);
  int main() {
    A a(&func);
  }

4/13/06  Name linkage conflicts for variables in nonstrict modes

In nonstrict C++ modes, the front end allows name linkage conflicts when
redeclaring variables (with a warning).  For example:

  extern "C++" int i;
  extern "C" int i;  // Accepted with a warning in nonstrict C++ mode.

However, similar conflicts were previously not permitted when the variable
declarations appear in different scopes.  To match common practice in other
compilers (e.g., GNU and Microsoft C++ compilers), the front end now also
accepts such cases with a warning.  For example:

  void f1() { extern int i; }
  extern "C" void f2() {
    extern int i;  // Previously an error in all C++ modes.  Now accepted
  }                // with a warning in nonstrict C++ modes.

4/13/06  Microsoft compatibility: invalid template default arguments

In general, invalid template default arguments are accepted in Microsoft
mode and only diagnosed if the default argument is actually used.  Certain
errors regarding invalid class template arguments were still issued, however.
These cases are now accepted without error.

  template<typename T> class C {};
  template<typename T, typename U = C<U> > class D {};

4/13/06  GNU C++ compatibility: template static data member with missing
         initializer

Version 3.7 issues an error if the definition of a const template static
data member does not provide an initializer, when nonclass prototype
instantiations are enabled (e.g., strict mode, --parse_templates, g++ mode
when gnu_version is >= 30400).  g++ only issues an error if the static data
member is instantiated.  The severity of the diagnostic issued on the
static data member definition has been reduced to a warning in g++ mode.
An error is still issued if the static data member is instantiated.

  template <class T> struct A {
    static const int i;
  };
  template <class T> const int A<T>::i;

4/13/06  Internal error during prototype instantiation of static data member

A change made in version 3.7 could result in an internal error (in
check_for_missing_initializer, decl_inits.c) during the prototype
instantiation of a template static data member.  Such prototype
instantiations are done when nonclass prototype instantiations are
requested (e.g., strict mode, --parse_templates, g++ mode when
gnu_version is >= 30400).  The internal error would occur for const
objects without an initializer.  Now fixed.

  struct A {
    A() { }
  };
  template <class T> struct B {
    static const A a;
  };
  template <class T> const A B<T>::a;

4/11/06  Sun compatibility: searching for system header files

When searching for a header file specified using the <...> syntax, the
the Sun compiler searches for the specified header file name and also for a
version with the suffix .SUNWCCh appended (e.g., stddef.h.SUNWCCh).  We now
emulate this behavior in Sun mode.

4/11/06  Spurious error on complex integer literal skipped in preprocessing

In GNU mode, the front end issued a spurious error when encountering a complex
integer literal while scanning through code in the skipped branch of a
conditional compilation directive.  For example:

  #ifdef NOT_DEFINED
  __complex float z = 3i;  // Previously an error even though this code is
  #endif                   // skipped.

This is now fixed.

4/11/06  Microsoft compatibility: destructor call with variable instead of type

The Microsoft compiler accepts an explicit destructor call in which the
destructor name is specified using a variable or data member whose type
matches the type of the object, instead of a type name as mandated by the
language.  We now emulate this behavior in Microsoft mode.

  struct A {
    ~A() { }
  };
  struct B {
  public:
    A member1;
    static A member2;
    void f() {
      A variable;
      // uses variable or data member instead of type name after ~
      variable.~variable();
      member1.~member1();
      member2.~member2();
    }
 };

4/11/06  Microsoft compatibility: Empty wide character literal

In Microsoft mode, the front end now accepts an empty wide character literal
(L'') with a warning and treats it as a null character constant (i.e., like
L'\0').

4/10/06  Microsoft compatibility: __declspec(implementation_key(...))

In Microsoft mode, the front end now accepts (and ignores) constructs of the
form __declspec(implementation_key(n)) (where n is an integer constant) when
such constructs appear in code delimited by #pragma start_map_region and
#pragma stop_map_region.  These constructs are sometimes generated in .tlh
files by the #import mechanism of the Microsoft C++ compiler (when it
processes a class with a very large number of member functions).  The
implementation in the front end is only meant to allow the parsing of such
generated files: The constructs are not recorded in the IL, nor are they
fully checked for validity.  For example:

  struct S {
    void f();
  };
  #pragma start_map_region("filename")  // Now accepted in Microsoft mode
  __declspec(implementation_key(1)) void S::f();
  #pragma stop_map_region

In code delimited by #pragma start_map_region and #pragma stop_map_region
the front end also accepts nondefining class member function declarations
appearing outside the class definition (as illustrated in the example above;
see also Changes entry of 3/1/05).

4/10/06  IL memory region problem on compound literals in GNU C mode

In some cases, a compound literal scanned as part of the initializer
for a local static variable in GNU C mode was allocated incorrectly
(partly in the file scope memory region and partly in a function scope
memory region).  This could cause aborts later in processing,
especially if an IL file was written and read back in.  Now fixed.

  typedef struct { } raw_X_t;
  typedef struct {
    raw_X_t raw_x;
  } X_t;
  int f(void) {
    static X_t x = (X_t) { . raw_x = { } };
  }

4/10/06  Microsoft compatibility: macro redefinitions and push_macro pragma

Our implementation of the Microsoft push_macro did not match the Microsoft
implementation if a macro was redefined after having been pushed (instead
of being undefined and redefined).  Now fixed.

  extern "C" int printf(const char *, ...);
  int main() {
  #define X 1
  #pragma push_macro("X")
  #define X 2
  #pragma pop_macro("X")  
    printf("%s\n", X == 1 ? "pass" : "fail");
  }

4/10/06  Initialization issue when using MAKE_FRONT_END_CALLABLE

The memory allocation change described in the 2/15/06 entry initialized
a variable later than it should have been.  This could potentially cause
problems when using MAKE_FRONT_END_CALLABLE.  Now fixed.

3/30/06  C++-generating back end: hidden file-scope names in classes with a
         derived class in a nested namespace

The change to the C++-generating back end described in the entry of 11/10/05
resulted in the generation of incorrect code for cases like the following
when RECORD_FORM_OF_NAME_REFERENCE was configured as FALSE:

  int f(int);
  struct S {
    int f();
  };
  int S::f() {
    return ::f(0);    // Previously generated without qualification: "f(0)"
  }
  namespace N {
  struct O { 
    struct D : public S {}; 
    int f();
  };
  }

This has now been fixed.

3/29/06  Standalone utility programs and error initialization

Formerly, the error initialization routines were not called for standalone
utility programs.  A change made in version 3.7 requires the error
initialization routines to be run before an error is issued.  This could
cause an abort if a standalone utility program attempted to issue a diagnostic.
Now fixed.

3/27/06  Build error when USER_CONTROL_OF_STRUCT_PACKING is FALSE

The unusual configuration of GNU_EXTENSIONS_ALLOWED set to TRUE and
USER_CONTROL_OF_STRUCT_PACKING set to FALSE resulted in build errors in
expr.c.  This is now fixed.

3/24/06  C++-generating back end: operator->() with a reference return type

The C++-generating back end generated incorrect code for a call to an
operator->() function when the function's return type was a reference to a
pointer type (rather than simply a pointer type).  Now fixed.  For example:

  struct S {
    int i;
  };
  typedef S* Sp;
  struct P {
    Sp& operator->();
  };

  int f(P p) {
    return p->i;    // Formerly generated as (*(p->)).i
  }

3/24/06  GNU compatibility: Attribute "sentinel"

In GNU modes, the front end now supports attribute "sentinel".  This attribute
can only appear on function types with an ellipsis parameter.  It takes an
optional integer argument that represents a position in an argument list: The
last position is zero, the one before that is one, etc.  If a call of a routine
with that type does not have a constant null pointer argument at the indicated
position, a warning is emitted.  A warning is also issued if there aren't
enough arguments for a sentinel.   (If the position is omitted, it is assumed
to be zero.)  When gnu_version >= 40002, the sentinel should correspond to an
ellipsis parameter.  For example:

  void f1(int, ...)  __attribute__((sentinel));
  void f2(int*, ...)  __attribute__((sentinel(2)));
  int main() {
    f1(0, 0);           // Warning: Last argument (sentinel) is not a constant
                        // null pointer.
    f1(0, (void*)0);    // Okay.
    f2((int*)0, 1, 2);  // Okay if gnu_version < 40002; warning otherwise.
    f2((int*)0, 1);     // Warning: Too few arguments for a sentinel.
  }

3/22/06  C++-generating back end: conversion function calls

In a cast that invokes a user-defined conversion function but in which the
target type is different from the type returned by the conversion function,
the C++-generating back end generated the conversion function call as an
explicit cast, in addition to the cast to the ultimate target type.  Such
conversion function calls are now marked as compiler-generated and thus
omitted from the generated code.  For example:

  typedef char Arr[1];

  struct S {
    operator Arr& ( );
  };

  char *f() {
    static S s;
    return (char*) s;  // Formerly generated as (char *)(((Arr &)s))
  }

3/21/06  Support for type traits (ISO/IEC TR 19768)

The front end can now accept the following type trait pseudo-functions in C++
mode: __has_nothrow_assign, __has_nothrow_constructor, __has_nothrow_copy,
__has_trivial_assign, __has_trivial_constructor, __has_trivial_copy,
__has_trivial_destructor, __is_abstract, __is_class, __is_convertible_to,
__is_empty, __is_enum, __is_pod, __is_polymorphic, and __is_union.  These
enable or simplify the implementation of type traits templates as specified in
ISO/IEC TR 19768.

All of the pseudo-functions take one or two types, and produce a boolean
constant-expression.  For example:

  struct S { ~S(); };
  int a[__is_class(S)];             // Okay.  Same as "int a[1];".
  int b[__has_user_destructor(S)];  // Okay in Microsoft C++ mode only.

Support for these extensions can be explicitly enabled or disabled in any
C++ mode using the command-line options --type_traits_helpers and
--no_type_traits_helpers.  In Sun and GNU C++ mode, the extensions are
disabled by default (to avoid potential future conflicts if the Sun or GNU
compilers add a similar facility).  As was already the case (see Changes entry
of 10/19/05), the extensions are enabled by default in Microsoft C++ mode with
microsoft_version >= 1400 (along with three others: __has_assign, __has_copy,
and __has_user_destructor).  In all other C++ modes, the new configuration
macro DEFAULT_TYPE_TRAITS_HELPERS_ENABLED determines whether the extensions
are enabled by default.

In non-Microsoft C++ modes, a macro is predefined by the front end if the
pseudo-functions are accepted.  The macro's name is configured through the
front end configuration macro MACRO_DEFINED_WHEN_TYPE_TRAITS_HELPERS_ENABLED,
whose default value is "__EDG_TYPE_TRAITS_ENABLED".  In Microsoft C++ mode,
this macro is not predefined and some of the pseudo-functions have slightly
different meanings.  For example:

  struct X {
    X(X &) throw();
    X(X const&);
  };  // If exceptions are enabled, __has_nothrow_copy(X) is true in Microsoft
      // mode, but false in other modes.  (Microsoft compilers only consider
      // the first declaration of a copy constructor.)

Finally, in Microsoft C mode with microsoft_version >= 1400, the extension is
recognized but not accepted (e.g., "__is_union" is not available as a user-
declared identifier).  This was already the case previously.

3/17/06  Bug in optimization for pointer-to-member call, IA-64 EABI

The change made to optimize pointer-to-member calls in the IA-64
ABI (see Changes entry of 12/9/05) wasn't right for configurations
with IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR set to TRUE
(e.g., for compatibility with the ARM EABI variant of the IA-64 ABI).
An incorrect subtraction of one was present in the generated code.
Now fixed.  [Patch sent out 3/23/06.]

3/16/06  GNU compatibility: Attribute "aligned" and bit fields

In GNU C/C++ modes, the front end previously silently ignored the GNU
attribute "aligned" on bit fields in configurations with
TARG_BIT_FIELD_CONTAINER_SIZE >= 0.  For example:

  struct S {
    char c;
    int x:1 __attribute__ ((aligned (1)));  // Attribute previously ignored.
  };

This is now fixed:  The alignment value is applied to the bit field container.

3/15/06  C++-generating back end: static_cast operations

Formerly, conversions appearing in the source as static_cast operations were
generated by the C++-generating back end as C-style casts or, in some
contexts, as functional-notation casts.  These conversions are now generated
as static_cast operations.  For example:

  int i = static_cast<int>('x');  // Formerly generated as ((int)'x')

3/15/06  Abort on DLL attribute on extern "C" declarations

In Microsoft mode with "Microsoft bugs" mode disabled (--no_microsoft_bugs),
specifying the same DLL attributes on two extern "C" declarations appearing
in different namespaces triggered an internal error in decls.c (in function
update_dll_info_for_routine or update_dll_info_for_variable).  For example:

  namespace N1 { extern "C" __declspec(dllimport) void f(); }
  namespace N2 { extern "C" __declspec(dllimport) void f(); }
    // Previously could trigger an internal error in decls.c.

This is now fixed.  [Patch sent out 3/23/06.]

3/14/06  GNU C++ compatibility: argument-dependent lookup and extern "C"
         functions

The standard says that extern "C" declarations with the same name but
in different namespaces refer to the same entity.  g++ does not adhere
to this rule (as indicated by the fact that they allow the different
declarations to have different types).  When more than one such declaration
is found by argument-dependent lookup, and those declarations refer to
extern "C" functions with the same function type, g++ considers the
declarations to be equivalent and does not diagnose an ambiguity.  We
no longer report an ambiguity on this example in g++ mode.

  struct A { };
  extern "C" int f (A);
  namespace N {
    extern "C" int f(A);
    struct B {
      B() { f(A()); }
    };
  }

3/14/06  Spurious warning on argument of GNU complex projection operators

In GNU C/C++ modes, the front end sometimes warned about a variable being set
without being used even when the variable was in fact used as the operand of
a GNU complex projection operator (__real__ or __imag__).

  double f() {
    __complex__ double z = 1.0+2.0i;  // Formerly spuriously diagnosed as
    return __imag__ z;                // "set but never used".
  }

This is now fixed.  [Patch sent out 3/23/06.]

3/14/06  GNU complex conjugate operation incorrect for complex constants

In GNU C/C++ modes, the front end produced incorrect results when folding the
complex conjugation ("~") operator.  For example:

  __complex__ double z = ~(1.0+2.0i);  // Previously set z to -2.0i instead of
                                       // 1.0-2.0i.

This is now fixed.  [Patch sent out 3/23/06.]

3/9/06   Expressions in runtime sizeof operations

Under some circumstances, the type appearing in an enk_runtime_sizeof
expression node was a pointer to the type that should have been used.  Because
enk_runtime_sizeof nodes are used to represent sizeof expressions when
RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, this error could cause problems for
those configurations, including incorrect output from the C++-generating back
end.  This has now been fixed.  For example:

  void f() {
    char x[6];
    char y[sizeof(x)];    // Formerly generated in g++ mode as
                          // "sizeof(char (*)[6])", now as "sizeof(char [6])"
  }

[Patch sent out 3/23/06.]

3/9/06   GNU C++ compatibility: Conversions between complex and real types

Previously, the front end silently accepted implicit conversions between
complex and real types in GNU C++ mode.  Now such conversions are no longer
permitted.  (They remain valid in C99 and GNU C modes.)  For example:

  double x = 1.0+2.0i;         // No longer accepted in GNU C++ mode.
  __complex__ double z = 1.0;  // Ditto.

3/9/06   GNU compatibility: __builtin_cabs and __builtin_carg

The front end incorrectly defined the builtin functions __builtin_cabs and
__builtin_carg as returning complex types.  This is now corrected (they take
a complex argument, but return a real value).  [Patch sent out 3/23/06.]

3/7/06   Microsoft/GNU C++ compatibility: Name linkage and block-extern
         declarations

In Microsoft and GNU C++ modes, the front end now accepts a block-extern
declaration of an entity E in a function declared with an explicit name
linkage specifier that is different from the name linkage associated with a
previous declaration of E.  The name linkage associated with the original
declaration of E is retained.  For example:

  void g();  // C++ name linkage by default.
  extern "C" void f() {
    void g();  // Normally an error because the implicit "C" name linkage
  }            // conflicts with the prior declaration.  In GNU and Microsoft
               // mode, the name linkage of the prior declaration is retained.


3/7/06   Microsoft compatibility: specialization allowed after use

In Microsoft bugs mode, a member function may sometimes be specialized after
its use.  A change made in version 3.7 restricted this special handling to
Microsoft versions 1300 and below (see 11/1/05 entry).  It turns out that
Microsoft versions above 1300 still allow such specializations if the
associated template does not have a definition.  We now emulate this
behavior.

  template <class T> struct A {
    static void f();
  };
  int main() {
    A<int>::f();
  };
  // Specialization is allowed if A<T>::f does not have a definition
  template<> void A<int>::f() {}

3/8/06   Abort on Microsoft DLL attribute after block-extern declaration

In Microsoft modes, declaring a block-extern variable or function with a DLL
attribute (dllexport or dllimport) followed by a namespace scope declaration
of the same entity with the same attribute resulted in an internal error.
For example:

  void f() { __declspec(dllexport) int g(); }
  __declspec(dllexport) int g();  // Previously triggered an internal error.

This is now fixed.  [Patch sent out 3/23/06.]

3/7/06   GNU C++ compatibility: using-directives and multiple
         extern "C" functions

The standard says that extern "C" declarations with the same name but
in different namespaces refer to the same entity.  g++ does not adhere
to this rule (as indicated by the fact that they allow the different
declarations to have different types).  When more than one such declaration
is found by a using-directive lookup, g++ considers only the first
declaration encountered.  Formerly we reported an ambiguity on the calls
in the example below.  We now accept the calls and call the global
function.

  extern "C" int f(void);
  extern "C" int g(void);
  namespace N {
    extern "C" int f(void);  // same type
    extern "C" void g(void); // different type
  };
  using namespace N;
  int i = f(); // calls ::f
  int j = g(); // calls ::f

3/6/06   Microsoft compatibility: Explicit enum base type

In Microsoft mode with microsoft_version >= 1400, the front end now accepts
explicit enum "base types".  For example:

  enum E: signed char { e1 = -1, e2 = 1 };

The "base type" specifies the underlying type and must be an integral type
other than bool.

3/6/06   Microsoft and GNU C++ compatibility: ADL and implicit instantiation

The Microsoft and GNU compilers do not implicitly instantiate a class
template specialization in order to determine its associated classes
and namespaces for argument-dependent lookup.  This causes those compilers
to accept code like this:

  template <typename T> struct S { 
    typedef typename T::member tt;
  };
  void f(void*);
  void g(S<int>* p) {
    f(p);  // should result in invalid instantiation of S<int>
  }

However, it also causes those compilers to reject code like this:

  template <typename T> struct S {
    friend void f1(S*){}
  };
  void g(S<int>* p) {
    f1(p);
  }

We now emulate this behavior in Microsoft and g++ modes.  [Patch sent
out 3/23/06.]

3/3/06   C++-generating back end: unneeded qualification in
         elaborated-type-specifiers

When a class or enumeration was hidden by a set of overloaded functions, some
of which were made visible by a using-directive, the C++-generating back end
unnecessarily used a qualified name in references to the type.  Now fixed.
For example:

  double log(double);
  namespace std {
    float log(float);
  }
  using namespace std;
  struct log { };
  void f() {
    struct log l;    // Previously generated as "struct ::log l;"
  }

3/3/06   GNU C++ compatibility: new operator treated as dependent

Uses of the new operator in template dependent contexts are always treated
as dependent by g++ starting with version 3.4.  In the example below, this
causes the operator new declaration to be visible in A<T>::f even though
it is declared after the definition of the template, and though that
particular new operation is not actually dependent.  We now emulate this
behavior in g++ mode when gnu_version is >= 30400.

  typedef unsigned long size_t;
  template <class T > struct A {
    void f() {
      void *p = 0;
      new (&p) int(0);
    }
  };
  void* operator new(size_t, void* p);
  int main() {
    A<int> a;
    a.f();
  }

3/2/06   Support for more than 255 token kinds

The front end has used a byte field to represent a_token_kind in some
data structures.  As the number of tokens kinds grows, we are getting close
the point where a byte will no longer be sufficient in some configurations.
With the additional token kinds added in version 3.8, some customers
who have added their own token kinds may already hit this limit.  To
support a larger number of token kinds, the typedef a_byte_token_kind has been
renamed a_small_token_kind.  The type to be used as a_small_token_kind is
specified by the TYPE_FOR_A_SMALL_TOKEN_KIND configuration macro, which
defaults to a_byte.  An assertion check has been added to ensure that
a_small_token_kind is not too small for the number of token kinds being used.

3/2/06   Incorrect space used output

In version 3.7, the space used output did not include the space for
certain resizable buffers.  This could cause the "Total used" value
to be less that the actual total used.  It could also result in the
"Not listed" value being negative.  Because the "Not listed" value is
unsigned, it would be displayed as a large unsigned value.  Now fixed.

3/2/06   Multibyte characters in file names

Formerly, the front end was not prepared to handle file names containing
multibyte characters.  If, for example, a file name contained a multibyte
character in which the second byte looked like a directory separator,
file names generated using the base name of the primary input field would
be given incorrect names (e.g., compilation of xy/z.c, where "y/" represents
a multibyte character sequence, would result in the creation of a
file name z.int.c instead of xy/z.int.c).  Multibyte characters are
only supported in file names when MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is
TRUE.

3/1/06   GNU compatibility: Attribute "aligned" on parameters

In GNU modes, the front end now issues an error when attempting to specify the
attribute "aligned" on a parameter declaration.  For example:

  void f(int p __attribute__((aligned(4)))) {}  // Previously accepted.
                                                // Now an error.

Such examples were previously silently accepted.

3/1/06   GNU compatibility: __alignof applied to field selection operations

In GNU modes, the front end now takes into account explicit alignment settings
of fields when applying the __alignof operator to a field selection operation.
For example:

  struct S { int i __attribute__((aligned(8))); } s;
  int main() {
    return __alignof(s.i); // Returns 8 (which may differ from __alignof(int)).
  }

3/1/06   Complex constants incorrectly lowered in GNU C++ mode

In GNU C++ mode, the front end incorrectly lowered complex constants appearing
inside functions.  This also manifested itself as invalid C code generated by
the C-generating back end.  For example:

  void f() {
    1.0+2.0i;  // Produced invalid C code when compiled in GNU C++ mode.
  }

This is now fixed.  [Patch sent out 3/23/06.]

2/28/06  GNU compatibility: Duplicate parameter names

In GNU C++ mode, the front end now accepts duplicate parameter names in
function declarations that are not also definitions.  For example:

  void f(int i, int i);  // Now accepted in GNU C++ mode.

Duplicate parameter names are also accepted in non-prototype declarations in
C mode (parameter names in non-prototype declarations that are not definitions
are accepted in GNU C mode with a warning):

  void f(i, i);  // Accepted in GNU C mode (with a warning).

2/27/06  Preprocessing output with line splices inside comments

When creating preprocessing output that includes comments, a comment that
contained more than five consecutive spliced lines (a backslash at the end of
the line) caused a #line directive to be inserted into the body of the
comment.  This has now been fixed; blank lines are used instead of #line
directives inside comments to resynchronize output line numbers with those
of the source following line splices.

2/27/06  IL display utility and complex types

The IL display utility had not been updated to correctly display complex types
and complex constants.  This is now fixed.

2/27/06  Invalid orphan entry list for internal complex values

When writing an IL file in a mode supporting complex types (e.g., C99 or GNU
modes), the front end failed to process the orphan entry list for the
representation of complex values (an_internal_complex_value).  The resulting
invalid IL file could easily trigger internal errors later on (e.g., in the
stand-alone IL display utility).  The following example creates such orphan
entries:

  void f() {
    1.0+2.0*__I__;  // Requires orphan entry of type an_internal_complex_value
  }                 // which was previously incorrectly written to the IL file.

This is now fixed.  [Patch sent out 3/23/06.]

2/27/06  Lowering of VLAs and "referenced" flag

When a VLA (variable-length array) variable is lowered, its "referenced" flag
is now unconditionally set (even if the variable was not explicitly referenced
in the source) to reflect the implied reference by the run-time support
library.  For example:

  void f(int n) {
    int v[n];  // Previously "v" was not marked as referenced, but lowering
  }            // did in fact create references to its lowered form.  Now,
               // lowering "v" also marks it as referenced.

2/27/06  Build error with Microsoft C compiler

When GNU_EXTENSIONS_ALLOWED is TRUE, the file sys_predef.c failed to compile
using the Microsoft C compiler in its default mode (i.e., with extensions
enabled).  This is now fixed.  [Patch sent out 3/23/06.]

2/27/06  Internal error on invalid string literal initializer

Certain invalid string literal initializers could lead to an internal error
(in initializer(...), decl_inits.c).  For example:

  void f() {
    static char x[3](L"ab");  // Previously triggered an internal error.
  }

This is now fixed.

2/23/06  Internal error on invalid UCN with RECORD_MACROS_IN_IL

If a macro definition ended with an invalid universal character name
an internal error (in make_il_macro_entry) could occur when using
RECORD_MACROS_IN_IL.  Now fixed.

  #define X \u
  int x = 1;

2/23/06  Microsoft compatibility: linkage specifications and inline functions

MSVC++ has different semantics for the two syntaxes of linkage specifications
when they apply to inline functions.  When a non-definition declaration of an
inline function appears in a direct (non-brace) linkage specification, MSVC++
will always generate code for the function, in similar fashion to the handling
of explicit "extern inline" functions (see the entry of 8/15/02).  (Curiously,
the form of linkage specification used on the definition of an inline function
has no effect.)  For example:

  extern "C" { void f(); }
  inline void f() {}        // Not emitted by Microsoft compilers unless
                            // really needed
  extern "C" void g();
  inline void g() {}        // Always emitted by Microsoft compilers

This behavior is now emulated when INSTANTIATE_EXTERN_INLINE is TRUE.  The
presence of a direct linkage specification on a non-definition function
declaration is now recorded in the IL in Microsoft mode in the new a_routine
flag direct_linkage_specifier_on_nondef_decl.  As part of this change, the
C++-generating back end now generally maintains the form of linkage
specification used in the source.

2/22/06  TARG_SIZEOF_WCHAR_T no longer used

The configuration macro TARG_SIZEOF_WCHAR_T was redundant since the same
information can be derived from the macro TARG_WCHAR_T_INT_KIND combined
with the sizes of the other integer types.  The macro is therefore no longer
used in the front end (e.g., if it is set in defines.h, its value will simply
be ignored).

2/22/06  Microsoft: in-class specialization of global function template

The Microsoft compiler allows a global function template to be specialized
in a class scope.  We now accept this in Microsoft mode.

  template<class T> T f() { return T();}
  struct C {
    template<> friend C f<C>() { return C();}
  };

2/20/06  GNU C "?" and ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS

Some strange uses of the "?" operator as an lvalue in GNU C mode
were accepted only if ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS
is configured to FALSE.  Now fixed (so the cases are accepted
regardless of the setting of that flag).

  typedef struct { unsigned offset[400]; } __regbase;
  void foo() {
    unsigned dead = 2;
    (1 ? ((__regbase *) 0x40000200)->offset[200] : dead) = 0; // Okay now
  }

2/20/06  Microsoft compatibility: reinterpret_cast of string literal that
         casts away const

Microsoft C++ mode now allows a reinterpret_cast of a string literal
that casts away const when string literals are const.

  int main() {
    reinterpret_cast<int *>("ABC"); // Allowed in all Microsoft versions
  }

2/19/06  Abort on field selection from struct/union compound literal
         in GNU mode

The front end aborted in get_pointer_offset ("bad kind") while
processing a field selection out of a struct or union created via 
a compound literal in gcc or g++ mode.  Now fixed.

  int i = (struct { int i; }){0}.i;  // No longer aborts in gcc mode

2/19/06  non_arithmetic flag preserved in shared constants

The mechanism for sharing and reusing integer constants now preserves
the non_arithmetic flag (set for hexadecimal and octal constants).

  int main() {
    int n;
    n = 9; 
    n = 0x9;   // No longer the same constant as the previous line
  }

2/17/06  UTF-8 byte order mark recognized at the start of source files

The #import mechanism of the Microsoft compiler (version 8.0) creates .tlh
files with a "byte order mark" at the beginning of the file.  The byte order
mark indicates the character encoding of the file.  For more information
about byte order marks, see http://www.unicode.org/faq/utf_bom.html#BOM.
The front end now checks for the presence of a byte order mark at the
start of a source file.  Currently, only the UTF-8 byte order mark is
allowed.  The DEFAULT_CHECK_FOR_BYTE_ORDER_MARK configuration flag controls
whether or not this check is done.  It defaults to TRUE when the
MICROSOFT_EXTENSIONS_ALLOWED configuration flag is TRUE and the host
character set is ASCII.

2/15/06  Microsoft compatibility: command-line option for default calling
         convention

When MICROSOFT_EXTENSIONS_ALLOWED is TRUE, the --default_calling_convention
command line option is accepted, specifying the calling convention applied
to functions that are declared without an explicit calling convention.  For
example:

  void f();
  void (__stdcall *fp)() = f;    // Previously rejected, now accepted with
                                 // --default_calling_convention=__stdcall

2/15/06  Memory allocation problem when using COMPILE_MULTIPLE_SOURCE_FILES

A change in version 3.7 could result in the use of a pointer to IL memory
that has already been freed, when the front end is configured with
COMPILE_MULTIPLE_SOURCE_FILES == TRUE.  The reference occurred in
compare_include_search_result.  Now fixed.  [Patch sent out 3/23/06.]

2/14/06  U-literals (char16_t and char32_t)

The front end now supports so-called U-literals: String and character literals
whose underlying character type is an unsigned integer with a guaranteed
minimum number of bits (16 or 32).  These constructs are specified in the C
committee's ISO/IEC TR 19769.  For example:

  char16_t *str = u"A 16-bit character string";
  char32_t ch = U'\U00012345';  // A 32-bit character literal

TR 19769 specifies that char16_t and char32_t be typedefs for unsigned integer
types of sufficient range (corresponding to C99's uint_least16_t and
uint_least32_t, respectively) provided in a new header <uchar.h> (not provided
with the front end).  The front end can be configured to match those types by
appropriately defining macros TARG_CHAR16_T_INT_KIND and TARG_CHAR32_T_INT_KIND
(these initialize global variables with the corresponding lower-cased names).
U-literals are enabled or disabled using the command-line options --uliterals/
--no_uliterals.  The macro DEFAULT_ULITERALS_ENABLED can be defined to
determine whether or not such U-literals are accepted by default.  In some
cases, 32-bit character values must be encoded in 16-bit characters.  For
example:

  char16_t *str = u"\U00012345";

By default, this encoding is based on UTF-16.  A different encoding may be
achieved by defining the macro ENCODE_IN_CHAR16_T to be an alias for a
custom encoding routine.

U-literals (and the --uliterals command-line option) are currently only
allowed in C modes (the C++ committee is examining a similar extension for
C++, but it is unclear at this time whether it will be entirely compatible
with ISO/IEC TR 19769).

Previously, the front end only handled two kinds of string literal constants
(ck_string): normal ("char") and wide ("wchar_t").  The two were distinguished
by their types.  With the introduction of two more character types, this is no
longer a viable approach.  Instead, a new bit field "character_kind" was added
to a_constant to easily determine the string literal kind (IL CHANGE).

2/13/06  GNU compatibility: folding of difference of pointers cast to int

In GNU mode, the difference of two pointers, each cast to int, is
now considered a constant expression.

  struct Foo {
    int x;
    int y;
  } f;
  int c = (int)&f.y - (int)&f;  // Now valid in GNU C mode

2/13/06  Spurious access error on overloaded operator with dependent name
         processing

The front end gave a spurious access error when dependent name
processing is enabled (e.g., in strict mode) on a reference to an
operator function whose access is adjusted via a using-declaration
in a derived class.  Now fixed.

  template <class T>
  struct B {
     void operator[](int index);
  };
  template <class T>
  struct D : private B<int> {
     using B<int>::operator [];
  };
  template <class T>
  void foo() {
     D<int> se;
     se[0];  // Spurious error here
  }
  int main() {
     foo<int>();
  }

2/10/06  Generating preprocessed output when using --preinclude_macros

The front end produced incorrect preprocessed output when using macro
preinclude files.  If the last line of the preinclude file was not
a preprocessing directive, it was emitted in the preprocessed output.
In addition, the output lacked a #line directive to mark the beginning
of output associated with the primary source file.  Now fixed.
[Patch sent out 3/23/06.]

2/9/06   Abort in gen_goto_cleanup_actions, lowering of goto within switch

IL lowering aborted in gen_goto_cleanup_actions ("common lifetime not
found in curr lifetime parents") in a case involving a switch statement,
a case within that switch that includes a label and a destructible
temporary and ends with a break, and following that (still within the
switch) a goto to a label at the same level.  Now fixed.  [Patch sent
out 3/23/06.]

  struct A {
    A(int);
    ~A();
  };
  void f(const A &);
  int main() {
    switch(1) {
      case 1:
      L1:
        f((A)0);
        break;
      L2:
        goto L3;  // Abort on this line
      L3:
        break;
    }
  }

2/7/06   Improved support for international error message text

Most of the error message text is in the error_msg.txt file, but quite
a few of the strings used in the error output (such as "line", "error",
"at end of source", etc.) were hard-coded in error.c and other places.
These additional strings have now been made part of error_msg.txt.

2/3/06   GNU IA-64 ABI: Alignment of first virtual base

When DEFAULT_EMULATE_GNU_ABI_BUGS is TRUE, the front end emulated a layout bug
in early GNU C++ compilers that caused the first virtual base to be forced on
an alignment boundary corresponding to the strictest alignment requirement
encountered so far during the layout of the complete type.  Now, this bug is
only emulated when gnu_abi_version is less than 30400 (since the bug was fixed
in GNU C++ 3.4).  For example, assuming a typical 32-bit platform:

  struct B { virtual ~B(); char b; };  // 32-bit aligned because of the
                                       // virtual function table.
  struct V { short v; };    // 16-bit aligned.
  struct D: B, virtual V {  // V only requires 16-bit aligned, but was
    char d;                 // previously always 32-bit aligned when emulating
  };                        // GNU ABI bugs.
    // Now sizeof(D) = 12 when gnu_abi_version < 30400, and sizeof(D) = 8
    // otherwise (assuming GNU ABI bugs are emulated).

2/3/06   Microsoft compatibility: uninitialized variable in push/pop_macro

A variable in symbol_header_for_macro_push_or_pop was not set in some
cases, which could result in spurious errors.  Now fixed.  [Patch sent
out 3/23/06.]

2/2/06   GNU compatibility: Attributes on out-of-class member definitions

In GNU C++ modes, the front end previously ignored attributes appearing on
out-of-class member function definitions.  For example:

  struct S { void f(); };
  __attribute((deprecated)) void S::f() {}  // Attribute previously ignored.
  void g(S *p) { p->f(); }  // Now triggers a warning.

This has been fixed: The attributes are now correctly recorded.

2/2/06   Optimization of code for rvalue class "?" in return

IL lowering's code generation for class rvalue "?" cases has been
improved when the result is used in a return statement (and in some
similar cases, such as in a throw or an aggregate initializer).
The optimization of having the two forks of the "?" initialize the
same result entity, which was formerly applied only when the
result was a temporary or a whole variable, is now applied to
these other cases as well.

2/2/06   Microsoft C++ compatibility: Function modifiers "abstract", "sealed",
         and "override"

In Microsoft C++ mode with microsoft_version >= 1400, the front end now
accepts the function modifiers "abstract", "sealed", and "override".  The
modifiers are context-sensitive keywords with the following semantics:
  - "abstract" indicates a virtual function is pure virtual (i.e., it
    means the same thing as the "= 0" pure-specifier).
  - "sealed" indicates that a virtual function may not be overridden
    in a derived class.
  - "override" means that a virtual function must override a base class
    member.
For example:

  struct B {
    virtual void f0() abstract;  // Okay, same as "virtual void f0() = 0;"
    virtual void f1() sealed;
  };
  struct D: B {
    virtual void f1();           // Error: Attempt to override sealed B::f1.
    virtual void f2() override;  // Error: f2 does not override anything.
    
  };

This is a feature of ECMA-372 (also known as C++/CLI) that recent Microsoft
compilers also provide in their normal C++ modes.  However, the Microsoft
compilers implement the feature slightly differently from what is specified
in the ECMA-372 standard, and we do too to ensure compatibility.  For example:

  struct S1 {
    virtual void (*f() sealed)(); // Accepted, but not valid according to
  };                              // to ECMA-372.
  struct S2 {
    virtual void (*f()) sealed; // Not accepted, but valid according to
  };                            // ECMA-372.
  struct S3 {
    void f() abstract;          // Accepted, but ECMA-372 requires an explicit
  }                             // keyword "virtual" with all the modifiers.

2/1/06   Position of use of template included in specialization diagnostic

An explicit specialization must be declared before the first reference that
would make use of the specialization.  When a specialization violates that
rule, the location of the first use is now included in the diagnostic.  For
example, this test case:

  template <class T> struct A {
    void f(){}
  };
  int main() {
    A<int> ai;
    ai.f();
  }
  template <> void A<int>::f();

Results in this output:

"ex.c", line 10: error: explicit specialization of function
          "A<T>::f [with T=int]" must precede its first use (at line 7)

1/31/06  Declaration position included in access diagnostics

When an access error is reported, it can sometimes be difficult to know
which declaration is the one that is inaccessible, particularly in the
presence of template explicit specializations.  To make it easier to
identify the inaccessible entity, the declaration position is now included
in access diagnostics.

  template <class T> class A {
  public:
    typedef int I;
  };
  template <> class A<int> {
    typedef int I;  // private
  };
  A<int>::I i; // error: type "A<int>::I" (declared at line 6) is inaccessible

1/31/06  Additional position information in instantiation context output

Formerly, a noninline template referenced from a nontemplate context did not
have an instantiation position reported in diagnostic messages.  For example,
this test case:

  template <class T> void f() { T t; }
  template <class T> void g() { f<T>(); } 
  int main() { g<int>(); }

Resulted in this output:

"ex.c", line 1: warning: variable "t" was declared but never referenced
  template <class T> void f() { T t; }
                                  ^
          detected during:
            instantiation of "void f<T>() [with T=int]" at line 2
            instantiation of "void g<T>() [with T=int]"

The position of the first reference to the template is now used, making
the second instantiation context line:

            instantiation of "void g<T>() [with T=int]" at line 3

1/26/06  Unneeded code for explicitly specialized extern inline functions

A change made in version 3.5 caused the bodies of explicitly specialized
extern inline template functions to be included in the IL even if they
are unreferenced, which increased the size of object files.  This
has now been reversed.  See Changes entry of 9/14/04.  [Patch sent out
3/23/06.]

1/26/06  GNU/Microsoft C++ compatibility: Delayed nested class definitions in
         class scopes

In Microsoft C++ mode and in GNU C++ mode with gnu_version < 30400, the front
end now accepts delayed nested class definitions in class scopes.  In GNU mode
and in Microsoft mode with microsoft_version >= 1400, the delayed definition
must appear in a parent class of the class being defined.  For example:

  struct A {
    struct B {
      struct C1;
      struct C2;
    };
    struct B::C1 {};  // Accepted in Microsoft mode and in some GNU modes.
  };
  struct X {
    struct A::B::C2 {};  // Accepted in Microsoft mode only when
  };                     // microsoft_version < 1400.

1/26/06  Casts in constant expressions in g++ mode not seen as lvalue casts

The change of 9/15/05 to GNU C++ lvalue casts broke some cases like the
following.  Now fixed again.  [Patch sent out 3/23/06.]

  struct S {
    static const int x = 0;
    static const int y = int(x);  // Was spurious error in g++ mode < 3.4
  };

1/25/06  Microsoft compatibility: Class modifiers "abstract" and "sealed"

In Microsoft mode with microsoft_version >= 1400, the front end now supports
the context-sensitive keywords "abstract" and "sealed" in definitions of named
class types.  For example:

  struct B abstract sealed {};
  B b;  // Error: A complete object of abstract class type is not allowed.
  struct D: B {};  // A sealed class type cannot be used as a base class type.

This is a feature of ECMA-372 (also known as C++/CLI) that recent Microsoft
compilers also provide in their normal C++ modes.

1/24/06  GNU C++ compatibility: spurious error when deferring prototype
         instantiations

A change made in version 3.7 to defer function prototype instantiations
in g++ mode (when gnu_version is >= 30400) resulted in spurious errors
in certain cases.  Now fixed.  [Patch sent out 3/23/06.]

  template <typename T> struct A {};
  template<typename T1, typename T2> int operator-(const A<T1>&, const A<T2>&);
  template<typename T> struct B {
    A<T> f();
    template<typename U> void g(A<T> a, U) { a - a; }
  };
  int main() {
    B<char> bc;
    bc.g(bc.f(), bc.f());
    B<int> bi;
    bi.g(bi.f(), bi.f());
  }

1/24/06  IA-64 constructor/destructor entry point optimization

The code generated for constructors and destructors in the IA-64
ABI has been optimized with regard to constructor and destructor
entry points.  The primary code-containing routine is now made
to be the complete or subobject constructor or destructor, instead
of an internal routine with a "C9" or "D9" name.  This eliminates
one level of call or entry point.  Also, for destructors, the
deletion code has now been moved into the "D0" deleting constructor
and no longer appears in the primary routine.

As part of this, the C-generating back end has been changed to not
incorporate the called function code into thunks and covariant
routine wrappers unless the function has an ellipsis.  This became
important when we noted that the above change was suddenly causing
generation of large thunks because the C-generating back end was
copying the whole body of the destructor into the thunk, instead of
just a call to the internal routine.

IL CHANGE: a new flag in the routine entry, is_alias_entry,
indicates a constructor or destructor entry point that does nothing
more than call the primary entry point and therefore can be put
out as simply an alias for the primary entry point, if the back
end has that capability.

1/20/06  GNU compatibility: Abort when using function declared through typedef
         in call to function with "format" attribute

In GNU C or C++ modes, calling a function with the GNU attribute "format" with
a format string argument that is a call to a function declared through a
typedef could result in an abort in function "obtain_format_string_from_arg"
(defined in overload.c).  For example:

  void p(char const*, ...) __attribute__((format(printf, 1, 2)));
  typedef char const* F();
  F f;
  void g() {
    p(f());  // Previously resulted in an abort.
  }

This is now fixed.  [Patch sent out 3/23/06.]

1/20/06  Abort on certain template cases with multiple translation units

In some (relatively rare) cases involving multiple translation units that
instantiate templates over nested types, the front end could abort with an
internal error in f_set_trans_unit_corresp (trans_corresp.c).  For example,
the following pair of translation units triggered the problem:

  // Primary translation unit:
  namespace N {
    template<class T> struct S {};
    template<> struct S<int> {};
  }
  using namespace N;
  struct M {
    enum E { e };
    S<E> m;
  };

  // Secondary translation unit:
  namespace N {
    template<class T> struct S {};
    template<> struct S<int> {};
  }
  using namespace N;
  struct M {
    enum E { e };
    S<E> m;
  };
  int main() { M m; };

This is now fixed.

1/17/06  GNU compatibility: Abort on use of typeof with cross-reference output

In GNU C++ mode, the production of cross-reference output for a template
instantiated over a typeof construct often led to an abort in symbol_ref.c.
For example:

  template<class T> struct X {
    X(T const&);
  };
  void f() {
    X<typeof(int)>  x(1);  // With "--g++ --xref outfile" the instantiation of
  }                        // X<typeof(int)> previously triggered an abort.

This is now fixed.  [Patch sent out 3/23/06.]

1/17/06  Optimization on IA-64 array delete code generation

In the IA-64 ABI, the code generated by IL lowering for an array delete
of a class that has a constructor but no destructor now does the
deallocation directly rather than by calling __cxa_vec_delete or the like.

  struct A {
    A();
  };
  A::A() {}
  int main() {
    A *p = new A[5];
    delete[] p;  // Calls ::operator delete[] directly now
  }

1/16/06  Exception specifications when support for exceptions is disabled

The front end now issues a warning instead of an error on a function
definition with an exception specification when support for exception
handling is disabled.  Previously, such definitions were only accepted
for inline functions.  For example:

  void f() throw() {}  // Now accepted with a warning when support for
                       // exception handling is disabled.

1/16/06  Microsoft/GNU compatibility: Abort on nonstandard anonymous unions

In modes allowing nonstandard anonymous unions (GNU and Microsoft modes in
particular), the front end previously aborted if a class type was used
multiple times to form a nonstandard anonymous union.  For example:

  typedef struct { int m; } S;
  void f() {
    struct { S; } x;  // S used to form a nonstandard anonymous union.
    struct { S; } y;  // S used a second time to form a nonstandard
  }                   // anonymous union; this previously aborted.

This is now fixed.

1/16/06  Microsoft and GNU C++ compatibility: problem with in-class
         specializations and friends of class templates

Version 3.7 introduced a problem in the processing of in-class specializations
(in Microsoft mode) and friend declarations (Microsoft and GNU modes)
of function templates that could result in spurious errors (or an internal
error if using INSTANTIATE_EXTERN_INLINE).  Now fixed.  [Patch sent
out 3/23/06.]

  template <class T> struct A {
    A() { }
    template <class U> A(const U&) { }
    template <> A(const A&) { }
  };
  int main() {
    A<int> a;
    A<int> a2(a);
    A<int> a3(a);
  }
	
1/11/06  System include flag for file included using an absolute path name

If a system include file included another file using an absolute path name,
the included file would not have its from_system_include_dir flag set.  This
flag is now set for any file included using an absolute path name by a
file that has its from_system_include_dir flag set.

-------------------------------------------------------------------------------
Version 3.7, January 12, 2006

1/11/06  IL version number changed to 3.7

1/11/06  Spurious warning on printf/scanf checking with _Accum arguments

When the front end performed checking of printf/scanf arguments against a
string literal format string, the use of fixed-point _Accum arguments could
trigger a spurious warning about the argument being incompatible with the
corresponding specifier in the format string.  The problem was due to an
uninitialized variable (and hence did not consistently manifest itself).
For example, assuming GNU C and Embedded C modes:

  extern int scanf(char const*, ...) __attribute__((format(scanf, 1, 2)));
  void f() {
    _Accum x;
    scanf("%k", &x);  // Should be okay, but previously frequently triggered
  }                   // a spurious warning.

This is now fixed.

1/10/06  Internal error with STACK_REFERENCED_INCLUDE_DIRECTORIES and
         preinclude files

An internal error could occur when using STACK_REFERENCED_INCLUDE_DIRECTORIES
and preinclude files in non-Microsoft mode.  Now fixed.

1/9/06   Microsoft and GNU C++ compatibility: analysis of friends of class
         templates

A friend function of a class template is treated much like a template
function.  The body of the function does not undergo semantic analysis
unless the function is used.  In Microsoft mode, and in g++ mode (when
gnu_version is < 30400) the analysis is now deferred until the end of
the translation unit instead of occurring at the point of first use.
This causes examples like the one below to be accepted because g() is
now visible when the semantic analysis is done.

  template <class T> struct A {
    friend void f(A const &) { g(); }
  };
  int main() {
    A<int> a;
    f(a);
  }
  void g(){}

1/9/06   using-directive not considered in certain instantiations

A change made in version 3.6 could cause a namespace made visible by a
using-directive to be ignored during certain lookups involving template
instantiations.  This problem would only occur under a rare combination
of circumstances involving the instantiation of a template in a namespace
containing a using-directive that nominates a namespace also made visible
by a using-directive in another namespace, and when those using-directives
are applied for lookup purposes in different scopes.  Now fixed.

  namespace N {
    namespace NI {
      template <class T> struct B { typedef int I; };
    }
  }

  namespace M {
    using namespace N::NI;
  }
  using namespace M;

  namespace M {
    template <class T> struct C {
        typedef typename B<T>::I  I;  // spurious "B" is not a template
    };
    template <class T> struct D : C<T> { };
  }
  namespace N {  D<int> rh; }

1/4/06   Base class with no virtual destructor

In some cases, the front end issues a remark when a base class lacks a virtual
destructor.  The criteria that determine when such a remark is issued have been
revised.  Specifically, a remark is now issued if and only if a nondependent
direct base class does not have a virtual destructor and one of the following
is true:
  - the derived class has a used-defined destructor, or
  - a proper member of the derived class requires destruction, or
  - another direct nondependent base class requires destruction.
For example:
  struct B { virtual void f(); };
  struct D: public B { int x; };  // Previously a remark was issued for
                                  // base class B; now this is no longer true.

1/4/06   Nonconstant aggregate initializers in C mode

The original ANSI/ISO C standard (C89) did not allow nonconstant expressions
in any aggregate initializers.  C99 and many C89 dialects (including the
default C dialects of GNU and Microsoft compilers) do however allow non-
constant expressions in aggregate initializers for automatic variables.
A new global variable "allow_nonconstant_auto_aggr_init_in_c_mode" now
controls this behavior.  This is intended to facilitate customer-specific
front end modifications to emulate C dialects not directly supported by EDG.

1/4/06   Compilation condition for alloc_asm_function_body

The conditional compilation directives for the header declaration of
alloc_asm_function_body (in il_alloc.h) and its definition (in il_alloc.c)
were inconsistent (but equivalent).  They are now identical.

1/3/06   C++-generating back end: friend functions and
         TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS

When TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, in-class
definitions of friend functions are moved out of the class into namespace
scope.  If RECORD_FORM_OF_NAME_REFERENCE is TRUE, an unqualified reference to
a class member from an in-class definition of a friend function was maintained
as an unqualified reference, even though the friend function is no longer in
the lexical scope of the class.  This has now been fixed.  For example:

  struct S {
    static int i;
    friend int f() {
      return i;    // Now generated as S::i when f() is moved out of S
    }
  };

As part of this change, the interface of the function pointed to by the
output_name_reference field of an_il_to_str_output_control_block has changed:
the name_reference_ptr argument may now be NULL, an extra boolean argument
specifies whether the name is being declared or referenced, and the routine
now returns a boolean result indicating whether the name was actually output
or if a default routine should be used instead.

1/3/06   C++-generating back end: missing qualifier on enumerator from base
         class

If an enumeration constant from a base class was used in a derived class with
the same name as the constant, the C++-generating back end failed to use a
qualified name for the constant, as required.  Now fixed.  For example:

  struct B {
    enum E { D };
    B(E);
  };

  struct D : public B {
    D() : B(B::D) { }   // Formerly generated as B(D)
  };

1/3/06   Optimization of the include search process

The routines that search for include files have been restructured to
reduce the number of files that are opened when repeating the search
for a file that has already been included.  The front end already had
a mechanism to suppress the inclusion of header files that use include
guard code, but this mechanism only came into play after the include
search process completed.  The include-once mechanism has now been
integrated into the search process to reduce the number of unneeded file
open operations that are performed.  This can result in a significant
performance improvement in environments in which file open operations
are particularly expensive.

1/3/06   C++-generating back end: new-style casts with globally-qualified
         types

When generating a new-style cast to a type in the global namespace that
requires qualification, the C++-generating back end inadvertently created the
<: digraph (the alternate token spelling for "[").  Now fixed.  For example:

  struct S { virtual ~S(); };
  struct D: S { };
  void f(S* p) {
    int D;
    dynamic_cast< ::D*>(p);   // Formerly generated as dynamic_cast<::D*>
  }

1/3/06   C++-generating back end: explicit specialization of a member template
         of an explicit specialization

When generating the definition of an explicitly-specialized template that is
itself a member of an explicitly-specialized class template, the C++generating
back end previously added an extraneous template<> prefix for the containing
class.  Now fixed.  For example:

  template <typename T> struct S { };
  template<> struct S<int> {
    template <typename T> struct N { };
  };
  template<> struct S<int>::N<int> { };  // Formerly template<> template<>

1/3/06   C++-generating back end: explicit & in address of function

The C++-generating back end previously generated function address constants
simply as the name of the function, regardless of whether & was used in the
source.  Dropping an explicit & in this way can cause overload resolution and
template argument deduction to behave differently in the generated code than
in the source (because a reference-to-function type can bind to the bare name,
which it could not do with the & form).  Consequently, the C++-generating back
end has been modified to preserve explicit & operators applied to function
names in the generated code.

1/2/06   C++-generating back end: first reference to undeclared class

In some circumstances, the C++-generating back end generated code that
referred to an undeclared class using just its name rather than an
elaborated-type-specifier.  Now fixed.  For example:

  template <typename T> struct A { };
  struct C: public A<struct B> { };  // Formerly generated as A< B>

1/1/06   C++-generating back end, Microsoft compatibility: pointer-to-member
         constants using unqualified names

Although MSVC++ allows formation of pointer-to-member constants using an
unqualified name, versions before 7.1 are confused by this usage in the
generated code, where the context may be slightly different from that of the
source.  To avoid these problems, the C++-generating back end has been changed
always to use a qualified name in a pointer-to-member constant when
msvc_is_generated_code_target is TRUE and msvc_target_version_number is less
than 1310.  For example:

  namespace Ns1 {
    namespace Ns2 {
      struct Cls {
        typedef void (Cls::*Type)();
        void foo();
        static Type _tbl[];
      };
    }
  }
  using Ns1::Ns2::Cls;

  Cls::Type Cls::_tbl[] = { ((Cls::Type)&foo) };

The last line was formerly generated as

  Ns1::Ns2::Cls::Type Ns1::Ns2::Cls::_tbl[] = {((Type)(&foo))};

MSVC++ 6.0 and 7.0 issued errors for the initializer.  The line is now
generated in the following form, which is accepted by MSVC++ 6.0 and 7.0:

  Ns1::Ns2::Cls::Type Ns1::Ns2::Cls::_tbl[] = {((Type)(&Cls::foo))};

1/1/06   C++-generating back end, Microsoft compatibility: casts in null
         pointer constants

Versions of MSVC++ prior to 7.1 fail to recognize zero-valued integral
constant expressions as null pointer constants if they contain casts.  The
C++-generating back end adds casts to integral constants whose types are
shorter than int.  It has now been modified to recognize when such constants
are used in null pointer constants and suppress the cast if
msvc_is_generated_code_target is TRUE and msvc_target_version_number is less
than 1310.  For example:

  unsigned int *a = L'\0';  // Formerly generated as ((unsigned short)0U) in
                            // Microsoft mode, now as (0U).

12/31/05 C++-generating back end: redundant parentheses

The C++-generating back end often adds redundant parentheses in expressions to
guard against problems with operator precedence in the generated code.  Some
compilers have difficulty parsing certain constructs with extra parentheses,
so the C++-generating back end now recognizes many contexts in which
parentheses are not needed and avoids generating them.

12/30/05 C++-generating back end, g++ compatibility: parenthesized casts to
         a template-id

Versions of g++ before 3.4 reported a syntax error in some cases where an
old-style cast to a template-id was itself parenthesized.  The C++-generating
back end has been changed to generate a functional-notation cast in such cases
when gcc_is_generated_code_target is TRUE and gnu_target_version_number is
less than 30400.  For example:

  struct X { };
  template <typename T> struct S {
    S(X);
  };
  S<X> f() {
    return S<X>(X());    // Formerly generated as ((S< X> )(X()))
  }

12/30/05 C++-generating back end, Microsoft compatibility: dllexport modifier
         on const static data members

MSVC++ does not accept the __declspec(dllexport) declaration modifier on the
definition of a static data member with const-qualified type.  The
C++-generating back end has been changed to generate this declaration
modifier only on the in-class declaration of such static data members and not
on their definition.  For example:

  struct S {
    static const __declspec(dllexport) int i;
  };
  const int S::i = 0; // Formerly generated with __declspec(dllexport) modifier

12/27/05 C++-generating back end: member selection and operator&()

In some cases, a member selection expression of the form a.b was generated as
(&a)->b, even if the class type of "a" declared an operator&() member
function.  The C++-generating back end has now been changed to use the "."
form in cases where the class type has an operator&() member function.  For
example:

  struct S {
    int* operator&();
    int p;
  };
  struct X {
    S s;
  };
  void f() {
    static int* a = &(((X*)0)->s.p);  // Formerly generated as
                                      // (&((&(((X *)0)->s))->p))
  }

12/27/05 C++-generating back end: in-class template specializations

When configured with CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
set to FALSE and PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE and run with
--parse_templates, the C++-generating back end did not handle the explicit
specialization prefix and template argument list correctly for in-class member
template specializations (a Microsoft extension).  This is now fixed.  For
example:

  template<typename T1> struct outer {
    template<typename T2> struct inner { };
    template<> struct inner<T1> { }; // Formerly generated as
                                     // template<> template<> struct inner { };
  };

12/27/05 C++-generating back end: function types with non-C++ linkage as
         template arguments

The change described in the 11/10/04 entry, which caused template arguments to
be generated using the underlying type of a typedef rather than the typedef
name, did not take into account typedefs involving function types with non-C++
linkage.  As a result, the generated code incorrectly used a type with C++
linkage for such template arguments.  The generated code will now use the
typedef name in these cases.  For example:

  extern "C" {
    typedef void (*PFN)();  // pointer to extern "C" function
  }
  template <typename T> struct S { };
  S<PFN> s;                 // Formerly generated as "S< void (*)(void)>"

12/26/05 C++-generating back end, Microsoft compatibility: using-directives
         and nested namespaces

MSVC++ version 6.0 incorrectly made members of a nested namespace visible in
the global scope if a using-directive did not qualify its name.  The
C++-generating back end has been changed to use a qualified name in
using-directives for nested namespaces when msvc_is_generated_code_target is
TRUE and msvc_target_version_number is less than 1300.  For example:

  int i;
  namespace A {
    namespace B {
      int i;
    }
    using namespace A::B;  // Formerly generated as "using namespace B;"

    int f() {
      return i;     // Ambiguous in MSVC++ 6.0 with "using namespace B;"
    }
  }

12/26/05 C++-generating back end: implicit linkage specifiers

The C++-generating back end previously generated definitions of extern "C"
functions with a direct linkage specifier, even when the language linkage had
been implicitly specified by a preceding declaration.  However, an explicit
linkage specifier affects declarations and type names inside the function
definition, while implicit specification leaves such types with the language
linkage of the surrounding context.  The C++-generating back end has now been
modified to preserve the form of linkage specification used for function
definitions in the source.  For example:

  extern "C" void f();

  void g(void (*)());
  void x();

  void f() {             // Formerly generated as 'extern "C" void f() {'
    g((void (*)())x);    // Argument should (and now does) have type
                         // "pointer to function with C++ linkage"
  }

12/22/05 Meaning of --c and --c89

Previously, the command-line option "--c" always implied an ANSI C language
dialect.  Specifically, the combination "--old_c --c" caused the front end to
expect ANSI C input, even though the K&R/pcc dialect corresponding to the
"--old_c" is also a "C dialect".  Now, "--c" only has an effect if the dialect
selected up to then was a C++ dialect (and in that case, an ANSI C dialect is
selected).  So "--old_c --c" is equivalent to "--old_c", but "--c++ --c" is
equivalent to the default ANSI C mode.  Furthermore, a new option "--c89"
selects the standard ANSI C89/ISO C90 language features (and disables any
C99 or SVR4 C dialect that might have been in effect before that).

12/22/05 Sun mode and C mode options

Previously the front end silently accepted the command-line combination
"--c --sun" with the result being Sun C++ mode.  An error is now issued in
such cases to avoid confusion with a hypothetical "Sun C mode".  Other similar
combination of a C mode option followed by "--sun" are similarly diagnosed
(e.g., "--svr4 --sun" or "--old_c --sun").

12/22/05 find_assoc_pragma and namespace scopes

Formerly, find_assoc_pragma could not be used to find a pragma bound to
a namespace scope entity.  This is not an issue for our standard product
because find_assoc_pragma is only used on lowered IL (in which case all
such pragmas have been moved to the file scope).  find_assoc_pragma now
permits a namespace scope to be used so that it can be called for namespace
members in unlowered IL.

12/21/05 Microsoft mode: do-nothing pointer reinterpret_cast ignored

In Microsoft bugs mode, a reinterpret_cast to a pointer type is
now ignored if it casts the expression to the same type it already
has.  In particular, the expression stays an lvalue if it is one.
This "feature" is still present in MSVC++ 8.0.

  char* cp;
  void foo() {
    reinterpret_cast<char*>(cp) += 0;  // Accepted in Microsoft bugs mode
  }

12/21/05 No subscript-out-of-range warnings in unevaluated code

Subscript-out-of-range warnings are now suppressed in unevaluated
code, e.g., inside a sizeof.

  #define N 3
  int main() {
    int x[2] = { 0, 0 };
    (N < 2)? x[N]: 0;  // No warning now
  }

12/21/05 C++-generating back end, Microsoft compatibility: nested classes and
         base specifiers

Versions of MSVC++ prior to 7.0 had a bug that required a qualified name as a
base class specifier for a nested class when the base specifier named a nested
class of a base of the class containing the declaration.  The C++-generating
back end now adds the (otherwise unnecessary) qualification in such cases when
msvc_target_version_number is less than 1300.  For example:

  struct Base {
    struct N { };
  };
  struct Derived : Base {
    struct N2: Base::N {     // Formerly generated as N2: N
    };
  };

12/21/05 Include-once performance improvement

The routines that determine whether the inclusion of a previously included
file can be suppressed used a simple list to record previously included files.
Checking this list could be expensive in programs that include a very
large number of files.  A hash table is now used instead, resulting in
much better performance for such cases.

12/21/05 C++-generating back end: name references to enumeration constants

Regardless of the setting of RECORD_FORM_OF_NAME_REFERENCE, the form of the
reference in the source code used for an enumeration constant was ignored when
generating the reference in the output.  The form of name references in this
context is now preserved when RECORD_FORM_OF_NAME_REFERENCE is TRUE.  For
example:

  class Base {
  protected:
    enum { zero };
  };

  class Derived : public Base {
    friend int f();
  };

  int f() {
    return Derived::zero;    // previously generated as Base::zero
  }

12/20/05 Lowering of designated initializers, re-initialization with string

The lowering of designated initializers has been adjusted to deal
correctly with a case where an array of characters is initialized
with a string and then later, by use of a designated initializer,
initialized again with another string.  All trace of the first
initialization is supposed to be removed (according to WG14
defect report number 253), but it wasn't when the first string is
longer than the second (characters after the null of the second
string remained set according to the first string).  Now fixed.

  struct {
    char I[6];
    int J;
  } n[] = {
      { { "foo" }, 1 },
      [0].I = "a",  // "foo" was not completely eliminated
      [0].J = 2
  };

12/20/05 Preserving top-level explicit casts to void

A new configuration switch PRESERVE_TOP_LEVEL_CASTS_TO_VOID_IN_IL
controls whether top-level casts to void are retained in the IL.
Formerly, they were removed, but this switch can be set to retain
them.  It is set by default for C++-generating back end versions.

  int f();
  int main() {
    (void)f();  // Cast to void retained in IL with this switch set to TRUE
  }

12/19/05 Lowered extern inline functions and one-instantiation-per-object

In one-instantiation-per-object mode (see ONE_INSTANTIATION_PER_OBJECT),
with LOWER_EXTERN_INLINE set to TRUE, instantiated extern inline
functions were changed to static but still had an associated
slice number.  As a consequence, an object file containing
nothing was put out for them.  Now fixed (the lowered routines
no longer have an associated slice number).

12/19/05 Implicitly declared functions in C99

Unlike C89, C99 does not allow calls to implicitly declared functions.  For
example:

  void f(int x) {
    g(x);  // Valid C89, but not valid C99 (g not previously declared).
  }

The front end previously issued an error on the example above in all C99
modes.  Now an error is issued in strict C99 mode, and a warning is issued in
all other C99 modes.  This matches the behavior of other C99 implementations.

12/19/05 C++-generating back end: pointer values as condition expressions

The processing described in the 4/22/05 Changes entry, which caused
compiler-generated comparisons against 0 to be removed from the generated
code, was inadvertently not applied to pointer values.  This oversight has
now been fixed, so that the source form is correctly maintained for C code
like the following:

  typedef struct A_tag { int i; } A;
  void foo() {
    A *A = 0;   /* Hides typedef A */
    if (A) {    /* Formerly generated as (A != ((A *)0)) */
    }
  }

12/19/05 Internal error when nesting depth message severity is reduced

An internal error (in create_prototype_type) could occur in versions with
PROTOTYPE_INSTANTIATIONS_IN_IL == TRUE when the error severity for
the "template nesting depth does not match" diagnostic has been reduced.
Now fixed.

  #pragma diag_warning 776
  template <class T> class A {
    template <class T2> struct B {};  
    template <class T2> friend struct B;
  };
  A<int> a;

12/17/05 C++-generating back end: qualifiers for protected base class members

When built with RECORD_FORM_OF_NAME_REFERENCE set to FALSE, the C++-generating
back end formerly generated qualified references to protected base class
members using the base class name as the qualifier.  This is an access error
in Standard C++, which requires such references to be qualified using the
name of the derived class.  This is now fixed.  For example:

  struct B {
  protected:
    void f();
  };

  struct D: B {
    void g(void (B::*mfp)() = &D::f);  // previously generated as &B::f
  }

12/15/05 Potential aborts after errors with multiple translation units loaded

When errors occur and multiple translation units are compiled simultaneously,
the front end normally does not attempt to match IL across translation units.
However, there were a number of ways in which such matching was attempted in
error cases (all involving template instantiations), and the incomplete state
of the data structures supporting the matching process could then lead to
aborts.

12/15/05 Front end reinitialization and CHECKING

The seq_number_lookup_table in il.c was not properly reinitialized when the
front end was built with CHECKING == 0.  Now fixed.

12/13/05 GNU C++ compatibility: deferred parsing of function templates

Even though recent versions of g++ (3.4 and newer) parse template definitions,
they do very little semantic checking of such definitions.  Most of the
semantic checking is delayed until an actual instantiation is done.  As a
result, g++ accepts certain unusable templates provided they are not
actually used in the program.  To allow such programs to be compiled, we
have added the ability to defer the prototype instantiation of function
templates and function members of class templates until the first actual
instantiation is needed.  The --[no_]defer_parse_function_templates
options have been added to enable or disable this feature.  The feature
is enabled by default in g++ mode when gnu_version is >= 30400.  Note that
this feature can affect the meaning and/or validity of some programs.  For
example, additional default arguments may be available when the prototype
instantiation is done.  In most cases, however, the change in behavior
actually has the effect of making the front end more compatible with g++.
This feature cannot be used when including prototype instantiations in
the IL, and is disabled by default when using the C++-generating back end.

  class A {};
  template <class T> struct B {
    B () {};  // error: no initializer for reference member "B<T>::a"
    A& a;
  };

12/13/05 Extra position information for namespace definitions

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the front end now records more
detailed position information for namespace definitions and namespace alias
definitions.

12/9/05  End position of function-style cast

In some situations involving class templates, the end position recorded for
an enk_temp_init node (when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE) representing
a function-style cast was invalid.  For example:

  struct R { R(char*); };
  template <int n> struct C {
    operator C<n+1>();  // (1)
    operator R();
  };	 
  void f(C<42>& x) {
    (R(x));  // enk_temp_init node for "R(x)" previously recorded a
  }          // position in line (1).

This is now fixed.

12/9/05  Code improvement, pointer-to-member call, IA-64 ABI

The code generated by IL lowering for a pointer-to-member call
is now improved by using a subtraction instead of a division for
one operation.

12/9/05  Transferring out of a statement expression in C++ mode now allowed

The restriction on transferring out of a GNU statement expression
(i.e., ({ ...}) ) in C++ mode (by way of a break, continue, goto,
or return statement) has been eliminated.  This was important
because the expansion of the QT4 foreach macro includes a break
in a statement expression.

  void foo() {
    int i = 1;
    while (i) {
        __extension__ ({--i; break;});
    }
  }

In a related change, a spurious "not reachable" warning is no
longer issued when a break is used in a statement expression
inside the increment expression of a "for" (in either C or C++
mode).

  int main() {
    int i, j;
    for (i = 0; i < 5; ({ i++; break; }))
      j = i;
  }

12/9/05  SVR4 C and C99 modes

The front end previously failed to diagnose an attempt at enabling both
SVR4 C and C99 modes at the same time.  For example, if SVR4 C mode was
enabled by default (DEFAULT_SVR4_C_MODE set to TRUE), the command-line
option --c99 did not enable most of the C99 extensions.  This is now fixed:
DEFAULT_SVR4_C_MODE and DEFAULT_C99_MODE cannot both be TRUE, and providing
both --c99 and --svr4 on the command line elicits a command-line error.

12/9/05  Lowering of GNU assigned goto in C++ mode

IL lowering aborted on encountering a GNU assigned goto in C++ mode.
Now fixed.

  int f() {
    void *ptr;
    ptr = &&foo;
    goto *ptr;  // Formerly caused abort in lowering in g++ mode
  foo:
    return 0;
  }

12/9/05  On IL lowering rewrite of while with condition, pragma kept on while

IL lowering's rewrite of a "while" statement that includes a condition
declaration has been changed so that if there is a pragma associated
with the "while" it is kept on the "while" itself rather than moved to
the block statement added to surround the "while".

  void func2(int);
  void func1(int i) {
  #pragma test_next_statement
    while (int a = i) {
      func2(--a);
    }
  }

12/7/05  Abort when lowering VLAs in a multi-translation unit compilation

When simultaneously processing multiple translation units in a mode that
accepts and lowers variable-length arrays (VLAs), the front end could abort
in various ways (e.g., in find_vla_dimension).  This is now fixed.

12/7/05  Incorrect count on code to zero multi-dimensional array

The code generated by IL lowering to zero a multi-dimensional array
that is a member of an aggregate was incorrect: the size passed
to the zeroing routine was (way) too large, with the consequence
that surrounding entities would be overwritten.  Now fixed.

  struct Vector {
    float x,y,z,w;
    Vector() {}
  };
  struct Debug {
    bool    initialized;
    Vector  v;
    int     stuff[128][64];  // Size of array was computed wrong
  };
  int main() {
    Debug gDebug = {false};
  }

12/7/05  Source position of stmk_init statements

The source position of stmk_init statements was previously always set to the
position of the variable being initialized and the end position (available
when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE) was always NULL.  Now, if such a
statement corresponds to an initializer that appears in the source code,
the statement's start and end positions are those of the initializer.
Otherwise (e.g., for default initialization), the start and end positions
are those of the variable declaration (i.e., the start position is unchanged
in such cases).  For example:

  struct S { S(); S(int); };
  void f() {
    S s1(2);  // stmk_init with "position" set to the position of "(" and
              // "end_position" set to the position of ")".
    S s2;     // stmk_init with "position" set to the position of "s" and
              // "end_position" set to the position of "2".
  }

12/7/05  Microsoft compatibility: type_info and _GUID predeclared

In Microsoft mode, the built-in type _GUID is now predeclared.  Previously,
it had to be declared in the source code before it could be referred to.
Similarly, the type_info type is also predeclared, but only if that type is
defined in the global namespace (because DEFAULT_TYPE_INFO_IN_NAMESPACE_STD
is FALSE, or in modes where namespace std is an alias for the global
namespace).  The types are incomplete until their definitions appear in the
source (typically by including the appropriate header file).  For example:

  _GUID *p1;      // Now accepted without a preceding declaration.
  type_info *p2;  // Now accepted in various modes and configurations.

12/2/05  GNU C compatibility: Spurious error on initialization with const
         compound literal

In GNU C mode, a variable with static storage duration can be initialized
with a compound literal.  However, the front end incorrectly diagnosed a type
mismatch if the compound literal type was more cv-qualified than the
destination type.  For example:

  struct S {
    int i;
  } s = (struct S const){ 1 };  // Now accepted in GNU C mode.
                                // (Previously a spurious error.)

This is now fixed.

12/1/05  Default configuration of REDEFINE_EXTNAME_PRAGMA_ENABLED

The configuration macro REDEFINE_EXTNAME_PRAGMA_ENABLED (see Changes entry of
9/9/02) was previously set to TRUE by default if the (undocumented) macro
SOLARIS is defined.  Now, the macro is set to TRUE by default when the Sun-
specific macro __PRAGMA_REDEFINE_EXTNAME is defined (which indicates that
the build compiler supports the "#pragma redefined_extname" construct).

12/1/05  Signedness of enum bit fields

Previously, in a configuration with TARG_ENUM_BIT_FIELDS_ARE_ALWAYS_UNSIGNED
set to FALSE, the signedness of a bit field with an enum type whose enumerators
can all be represented independently of whether the bit field is signed or
not was determined by the flag targ_plain_int_bit_field_is_unsigned.  Now
the signedness of such cases is determined by the new configuration variable
targ_nonnegative_enum_bit_field_is_unsigned, which is initialized by the
macro TARG_NONNEGATIVE_ENUM_BIT_FIELD_IS_UNSIGNED.  By default, the macro
TARG_NONNEGATIVE_ENUM_BIT_FIELD_IS_UNSIGNED is TRUE when IA64_ABI is TRUE
and ABI_COMPATIBILITY_VERSION >= 307, which matches the GNU IA-64 ABI
implementation.  Otherwise, TARG_NONNEGATIVE_ENUM_BIT_FIELD_IS_UNSIGNED equals
TARG_PLAIN_INT_BIT_FIELD_IS_UNSIGNED by default (to maintain backward
compatibility).  For example:

  enum E { e };
  struct S {
    int x:2;
    enum E y:2;  /* Can now be configured to be an unsigned bit field even
                    when x is signed. */
  };

12/1/05  GNU C compatibility: Old-style function definitions and prototypes

When the gnu_version variable was introduced (see Changes entry of 10/4/04),
the ability to follow a prototyped function declaration by an unprototyped
function definition in GNU C mode was mistakenly limited to GNU C modes
with gnu_version < 30400.  This has been changed to allow such code for
any value of gnu_version.  For example:

  void f(short);
  void f(a) short a {}  // Previously an error in GNU C modes with
                        // gnu_version >= 30400.  Now accepted in any
                        // GNU C mode.

12/1/05  Invalid type variant access during processing of enumerator constant

Code in enum_specifier could access an incorrect variant of a type entry
(the variant.integer part of an entry that was a typeref).  This could
potentially lead to invalid enumerator values.  This is now fixed.

12/1/05  Spurious diagnostic on use of undefined preprocessing identifier

The fix of 5/4/04 that eliminated the diagnostic "zero used for
undefined preprocessing identifier" on uses in unevaluated parts
of #if statements was incomplete.  A previous use in the program
of "&&" or "||" on an overloadable type (e.g., an enum) caused the
use in an unevaluated expression to still be diagnosed.  The
problem was actually a pre-existing issue that prevented folding
of "&&" and "||" operations in constant expressions when there is
a previous use of the operator on an overloadable type, which aside
from this diagnostic issue meant suboptimal code sometimes.  Now fixed.

  class basic_istream
  {
    enum fmtflags{};
    fmtflags flags();
    void _Ipfx() {
      if (!0 && flags()) ;  // Required for failure
    }
  };
  #if defined(KALLE) && (KALLE>3)  // Got spurious diagnostic
  #endif

12/1/05  End position incorrect on cast in prototype instantiation

The end source position was not set on a cast to a dependent
class type in a prototype instantiation.  This comes up
only when EXTRA_SOURCE_POSITIONS_IN_IL and PROTOTYPE_INSTANTIATIONS_IN_IL
are TRUE.

  template<typename _T> struct S {
    typedef typename _T::t t;
  };
  template<typename _T> typename S<_T>::t func() {
    return typename S<_T>::t();  // End position not set on enk_temp_init
  }

12/1/05  Incorrect variant used, lowering of destructor call, IA-64 version

Code in add_destructor_call used an incorrect variant in the
IA-64 ABI configuration when processing a destructor call for
a variable whose type is a typedef to a class.  The entity
tested is a bit field, so the front end would not crash, but
incorrect code could potentially have been generated.  Now fixed.

  struct A {
    ~A() {}
  };
  typedef A T;
  int main() {
    T x;
  }

11/30/05 Abort on using-declaration overload in class template

In a class template, overloading a using-declaration for a member of a
dependent base class, a member function template, and a normal member
function could lead to an assertion failure in class_decl.c.  For example:

  template<typename> struct B {};
  template<typename T> struct D: B<T> {
    using B<T>::f;
    template<typename> void f();
    void f();
  };  // Previously triggered an assertion failure.

This is now fixed.

11/29/05 Microsoft compatibility: __thiscall

In Microsoft mode, the front end now accepts the __thiscall calling convention
on nonstatic member function declarations.  For example:

  struct S {
    void __thiscall f();  // Accepted in Microsoft mode.
  };

11/22/05 Microsoft compatibility: static data member explicit specializations

The Microsoft compiler treats what should be just a declaration of a
specialization of a static data member as a definition with a default
initializer (note that explicit specializations differ from normal
static data member definitions in this regard).  We now emulate this
behavior in Microsoft bugs mode.  This example should fail to link because
A<int>::i is not defined, but it links successfully in Microsoft bugs mode.

  template <class T> struct A {
    static int i;
  };
  template <> int A<int>::i;
  int main() {
    int *p;
    p = &A<int>::i;
  }

11/21/05 Microsoft compatibility: Reference to incomplete array parameters

In Microsoft mode, the front end no longer accepts a reference parameter whose
type involves an array type with unspecified bound.  For example:

  void f(int (&)[]);    // No longer allowed in Microsoft mode.
  void f(int (*&)[]);   // No longer allowed in Microsoft mode.
  void f(int (*)[]);    // Still allowed in Microsoft mode.
  void f(int (**)[]);   // Still allowed in Microsoft mode.

(In Cfront mode, both the reference and pointer cases are still allowed.)
This behavior was previously entirely controlled through the configuration
macro DEFAULT_PTR_TO_UNKNOWN_BOUND_ARRAY_ALLOWED_IN_PARAM_TYPE and its
associated variable ptr_to_unknown_bound_array_allowed_in_param_type.  Now,
these two only control the non-reference case, and a separate macro
DEFAULT_REF_TO_UNKNOWN_BOUND_ARRAY_ALLOWED_IN_PARAM_TYPE and associated
variable ref_to_unknown_bound_array_allowed_in_param_type have been introduced
to determine whether the reference case is allowed.

11/21/05 Improved diagnostic for nondeduced parameter in partial specialization

The diagnostic issued when a template parameter is used only in a nondeduced
context in a partial specialization has been made clearer.

  template <class T> struct C { };
  template <class T> struct C<typename T::U> { };

11/19/05 IL write/read error on default argument

The fix of 3/11/05 for a bug introduced by the change of 5/17/04
for default arguments introduced a different problem.  If a version
configured with DO_IL_LOWERING set to true was run in a mode that
does not do lowering (e.g., with the -N command-line option) the
IL traversal routines did not handle certain obscure default argument
expressions correctly.  As a consequence, the IL file produced
failed a consistency check when read back in.  Now fixed.

11/18/05 GNU C++ compatibility: Using-declarations for invisible members

In GNU C++ mode, the front end now accepts class-scope using-declarations for
invisible members.  For example:

  struct B { void f(int); };
  struct C: B { void f(float); };
  struct D: C {
    using B::f;  // B::f invisible (hidden by C::f).  Nonstandard, but now
  };             // accepted in g++ mode.

11/18/05 Enum type compatibility in C modes

In C modes (C89 and C99), the front end now correctly treats different enum
types as being incompatible (previously they were considered compatible).
For example:

  typedef enum { e } E;
  typedef enum { f } F;
  E g();
  F g();  // Now a compatibility error in many C modes.

The enum types are still treated as compatible in Microsoft C mode and in
GNU C mode when gnu_version < 30400.

11/18/05 Microsoft compatibility: DLL attributes and unnamed namespaces

In Microsoft mode, the front end now issues a warning when applying a dllexport
or dllimport attribute to a member of an unnamed namespace (unless that member
has C name linkage).  For example:

  namespace {
    __declspec(dllimport) void f();  // Warning.
    extern "C" __declspec(dllimport) int x;  // No warning.
  }

11/17/05 GNU compatibility: More predeclared functions

Many more (hundreds) GNU builtin functions (like __builtin_powil) are now
predeclared by the front end in GNU modes.  We believe this now includes all
the builtin functions listed in the GNU documentation for version 4.0 of the
GNU compiler, as well as a few undocumented functions.

11/17/05 Sun compatibility: template argument list following constructor name

The Sun compiler permits a template argument list to appear following a
constructor name in a constructor definition that appears outside of the
class.  This is now accepted in Sun mode.

  template <class T> struct A {
    A();
  };
  template <class T> A<T>::A<T>(){}

11/14/05 GNU C++ compatibility: Exception specifications and specializations

In GNU C++ mode, the front end now no longer requires the exception
specification of an explicit template specialization (for a function or
member function) to match that of the primary template.  For example:

  template<typename T> void f(T) throw(int);
  template<> void f(double) throw(float, double);  // Okay in GNU C++ mode.

11/14/05 GNU C compatibility: Excess specifiers in useless typedef declarations

In GNU C modes with gnu_version < 40000, a warning (instead of an error) is now
issued for certain excess specifiers appearing in typedef declarations without
a declarator (i.e., cases in which no actual typedef name is introduced).
For example:

  typedef short long;   // A warning in some GNU C modes (previously an error).
  typedef enum { e } E; // A warning in some GNU C modes (previously an error).

This is a revision of the change documented in the entry of 9/11/02.
Furthermore, the observation that the duplication of certain type specifiers
(like "int int"; see entry of 8/6/02) was accepted by some GNU C++ compilers
appears to be incorrect, and this allowance has therefore been undone.

11/11/05 Removing template class member typedefs in cross-reference output

In order to improve the usefulness of the cross-reference information, and
to dramatically reduce the size of the cross-reference file in some cases,
certain typedefs are now replaced with their underlying type in the
cross-reference output.  Just as is now done with typedefs in diagnostic
output (see 10/28/05 entry), typedefs declared in template classes are now
replaced with their underlying type.  In extreme cases this can reduce the
size of the cross-reference file by a factor of a thousand.

11/11/05 GNU compatibility: carriage return as line terminator

When ACCEPT_GNU_CARRIAGE_RETURN_LINE_TERMINATOR is TRUE and when using GNU
mode, carriage return and carriage return followed by a newline are accepted
as line terminators.  Carriage return was used as the line terminator
in older versions of MacOS.  In the example below "<cr>" must be replaced with
an actual carriage return character.

  #define X 1
  #ifdef X<cr>int i;<cr>#endif

11/10/05 Spurious error on aggregate initializers in templates

When performing nonclass prototype instantiation (e.g., in strict C++ mode),
the front end issued a spurious error on certain aggregate initializers that
start with a string literal.  For example:

  template<class T> void f() {
    T s[] = { "a", "b" };  // Previously an error in strict mode.
  }

This is now fixed.

11/10/05 Redefinition of enum types

The front end previously failed to diagnose certain attempts to redefine an
enumeration type.  Certain uses of the associated enumeration constants
could also lead to internal errors in some configurations.  For example:

  enum E { x };
  enum ::E { y };  // Now an error.  Previously accepted.
  void f() { x; }  // Could lead to an abort in some configurations.

This is now fixed: The redefinition is diagnosed as an error.

11/10/05 Spurious warning on friend declaration in class template

The front end normally issues a warning when a class befriends itself.
Previously, it also did so when this occurred as the result of a specific
template instantiation.  However, such situations may be required in some
circumstances and the front end therefore no longer issues a warning in
such cases.  For example:

  template<typename> class C {
    template<typename T> void f(C<T>*);
    int x;
    friend class C<int>;
  };
  template<> template<typename T> void C<int>::f(C<T> *p) {
    p->x = 2;  // Requires C to befriend C<int>.
  }
  // Previously triggered a warning during the instantiation of C<int>;
  // now no warning is issued.

11/10/05 Microsoft C++ compatibility: Local types and extern variables

In Microsoft C++ mode, the front end previously accepted (with a warning)
block-extern variable declarations with types containing a local class or
enumeration type.  This is now only accepted when microsoft_version < 1200.
For example:

  void f() {
    struct L {};
    extern L *p;  // Only accepted (with a warning) in Microsoft mode if
  }               // microsoft_version < 1200.

Block-extern declarations of functions involving local class or enumeration
types are still accepted in all Microsoft modes.

11/10/05 Microsoft C compatibility: size_t not predeclared

In Microsoft C mode, the front end no longer predeclares the size_t type.
(This matches the Microsoft behavior, which only predeclares the size_t type
when compiling C++ code.  See also Changes entry of 4/20/98.)

11/10/05 Microsoft C++ compatibility: Branching into try blocks

In Microsoft bugs mode, the front end previously issued only a warning about
branching into try blocks.  Now an error is issued if microsoft_version > 1200
(to match the behavior of various releases of the Microsoft compiler).

11/10/05 Microsoft C++ compatibility: Thunks and dllimport/dllexport

The dllimport and dllexport attributes (accepted in Microsoft modes) on
routines are now also applied to any thunks created for such routines.

11/10/05 C++-generating back end: hidden name inherited from a base class in
         a containing namespace

The C++-generating back end sometimes omitted a necessary qualifier for a
hidden member of a base class when the base class is defined in a namespace
that contains that of the derived class.  Now fixed.  For example:

  struct A {
    static int i;
  };
  struct B : public A {
    static int i;
  };
  namespace N {
    struct C : public B {
      int* f() { return &A::i; }  // Formerly generated as "&i"
    };
  }

11/10/05 Loop on carriage return when not ignoring carriage returns

A change made in version 3.6 resulted in a loop when the source contained
a carriage return and IGNORE_CARRIAGE_RETURN_IN_SOURCE is FALSE.  Now fixed.

11/9/05  Microsoft C compatibility: Abort on struct with only a zero-length
         bit field

In Microsoft C mode, the front end could abort when computing the layout of a
struct containing only a zero-length bit field.  This is now fixed.

11/9/05  C++-generating back end: "static friend" declarations in Sun mode

Sun C++ versions prior to 5.4 accepted the "static" storage specifier in
friend function declarations.  The C++-generating back end now preserves
these specifiers when generating code for those Sun versions.  For example:

  struct S {
    static friend void f();  // Generated code now contains "static"
  };

Because versions of Sun C++ after 5.3 reject this code, this change introduced
a new global variable, sun_target_version_number, which takes its value from
the new configuration macro SUN_TARGET_VERSION_NUMBER.  This macro must be
defined for any configuration in which SUN_IS_GENERATED_CODE_TARGET is TRUE
and in C++-generating back end configurations in which both
CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT and SUN_EXTENSIONS_ALLOWED are TRUE.

11/9/05  Microsoft compatibility: __declspec(deprecated("..."))

In Microsoft mode with microsoft_version >= 1400, the front end now accepts
an optional parenthesized string literal for the "deprecated" __declspec
attribute.  This string is reported when warning about the use of an entity
marked with such an attribute.  For example:

  int __declspec(deprecated("unsafe")) count;
  int g = count;  // Triggers a warning that includes the text "unsafe".

A new configuration macro DEPRECATION_STRING_IN_IL controls whether a string
specified in the "deprecated" attribute is recorded in the IL (and therefore
available to back ends).

11/9/05  Template argument deduction of pointer-to-member of function type

When the member type of a pointer-to-member is deduced as a function type,
the deduced function type was incorrectly considered to be a member
function.  In the example below, this caused the reference to A<F> to
refer to the primary template instead of the partial specialization.  This
has been fixed.

  template<class T> struct A;
  template<class Return_type> struct A< Return_type() > { };
  template<class F, class T> inline void g(F T::* pmf) {
    A<F> a;
  }
  struct B {
    void f() { }
  };
  int main() {
     g(&B::f);
  }

11/7/05  GNU C++ compatibility: Spurious error on using-declaration

In GNU C++ mode, the front end issued a spurious error for a using-declaration
for an extern "C" function that is also declared in the current namespace.
For example:

  extern "C" void f();
  namespace N { extern "C" void f(); }
  using N::f;

This is now fixed.

11/7/05  GNU compatibility: Complex floating-point types

In GNU C and C++ modes, the front end now accepts the GNU extensions for
complex floating-point types (but not the GNU extensions for complex integral
types).  These extensions are similar to the C99 complex type extensions,
with the following differences:
  - No _Imaginary type is available in GNU modes (the EDG-specific constant
    __I__ has type "_Complex float" in GNU modes).
  - The keyword "__complex" (and "__complex__") is equivalent to the C99
    keyword "_Complex".
  - The unary operators "__real" and "__imag" (as well as "__real__" and
    "__imag__") allow the extraction of the real or imaginary part of an
    expression.  This also works for lvalues (e.g., "__real z = 0.0;").
  - The unary complement operator ("~") applies to expression of complex
    types and produces the complex conjugate value of its operand.
  - Floating-point literals with any of the (equivalent) suffixes "i", "j",
    "I", or "J" denote complex floating-point literals with a pure imaginary
    value.

A number of new IL operators have been introduced in support of these features.
As with complex type facilities in C99 mode, setting the configuration macro
LOWER_COMPLEX to TRUE causes the front end to rewrite complex type constructs
in terms of "plain C IL".  The run-time support library has been updated to
support GNU-specific features (i.e., the complex conjugation operation).
Support for complex types in GNU modes can be disabled by setting the
configuration macro GNU_COMPLEX_EXTENSIONS_ALLOWED to FALSE.

11/4/05  Typedef names no longer in typeinfo names, Cfront-like ABI

In the Cfront-like ABI, the names in typeinfo variables sometimes
included typedef names (this did not happen in the IA-64 ABI).
The names of the types underlying the typedefs are now output
instead.

11/4/05  Microsoft mode: incorrect IL for comma expression as null pointer
         constant

Incorrect IL was generated for the Microsoft feature that allows use
of a comma expression like (x, 0) as a null pointer constant (see
Changes entry of 7/28/97).  The type of the comma expression did not
match the type of its second operand.  Now fixed.

  struct A {};
  typedef void (A::*pmf)(int);
  int a;
  pmf b = (a, 0);

11/3/05  C++-generating back end: #pragma pack directives and class template
definitions

The C++-generating back end formerly failed to preserve #pragma pack
directives that applied to class template definitions; this is now fixed.  As
part of this change, each #pragma pack directive in the source will be copied
into the generated code, and #pragma pack directives will be synthesized only
when a class definition appears in the generated code in a region with a
different packing alignment from that of the source region where it
originally occurred.  (This can happen, for instance, with generated explicit
specializations in configurations in which
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE.)  For example:

  #pragma pack(1)    // Previously omitted from generated code
  template<typename T> struct S {
    char a;
    int i;
  };

11/3/05  Incorrect lookup in instantiation of template static data members

Version 3.4 introduced a change in the way template static data members are
handled to allow the array size to be specified in the out-of-class
definition (see 11/20/03 Changes entry).  This change introduced a problem
that could result in incorrect lookups during the instantiation of a
template static data member.  In particular, the incorrect lookups would
occur when scanning the type specifiers and the initial portion of the
declarator.  This has been fixed.

  namespace A {
    template <class T> struct A {
      static int i;
    };
    int Z;
  }
  typedef int Z;
  // During instantiation the incorrect Z and A were found.
  template <class T> Z A::A<T>::i = 1;
  int main() {
    return A::A<int>::i;
  }

11/2/05  Microsoft compatibility: malformed float constants

In Microsoft bugs mode, floating-point constants like .1.234 are accepted.
This is now accepted only when microsoft_version is <= 1200.

11/1/05  Microsoft compatibility: specialization allowed after use

In Microsoft bugs mode, a member function template or a member function of
a template class may be explicitly specialized after it has been used.
This is now accepted only when microsoft_version is <= 1300.

  template <class T> struct A {
    void f() { }
  };
  int main() {
    A<int> a;
    a.f();
  }
  template <> void A<int>::f() { }

11/1/05  Microsoft compatibility: redeclaration of template

In Microsoft mode, a template may be redeclared outside of its class or
namespace.  This is now accepted only when microsoft_version is <= 1300.

  namespace N {
    template< typename T > struct S {};
  }
  template< typename T > struct N::S;

11/1/05  Microsoft compatibility: explicit instantiation of specialized class

In Microsoft bugs mode, an explicit instantiation of a specialized class is
accepted.  This is now accepted only when microsoft_version is 1300.

  template <class T> struct A {};
  template <> struct A<int> {};
  template struct A<int>;

11/1/05  Microsoft compatibility: redeclaration of template default argument

In Microsoft bugs mode, a template default argument may be redeclared or
given a different value.  This is now accepted only when microsoft_version
is <= 1300.

  template <class T = char> struct A;
  template <class T = int> struct A { };

11/1/05  Microsoft compatibility: default arguments on class template
         member declarations

In Microsoft mode, template default arguments are accepted (with a warning)
and ignored in the declaration of a member of a class template.  This is now
done only when microsoft_version is <= 1200.

  template <class T> struct A {
    void f();
  };
  template <class T = int> void A<T>::f(){}

11/1/05  Microsoft compatibility: default template args. on functions templates

In Microsoft mode, default template arguments on function template declarations
are accepted (with a warning) and ignored.  This is now done only when
microsoft_version is <= 1200.

  template <class T = short> void f(T) { }

11/1/05  Microsoft compatibility: accessibility of base classes

In Microsoft mode, a base class is considered accessible if one has member
access to the base class.  This is now accepted only when microsoft_version
is <= 1300.

  class A {
    friend void f();
  };
  class B : private A {};
  void f() {
    B* p = 0;
    A* q = p;  // accepted when microsoft_version <= 1300
  }

11/1/05  Microsoft compatibility: use of inaccessible type from base class

In Microsoft mode, a base class member type may be used in a derived class
when the base type is not accessible.  This is now accepted only when
microsoft_version is <= 1200.

  class A {
    typedef int T;
  };
  class B : public A {
    T x;
  };

10/28/05 Removing template class member typedefs in diagnostics

In order to improve the usefulness of diagnostics issued during template
instantiations certain typedefs are now replaced with their underlying
type in diagnostic output.  Specifically, typedefs declared in template
classes may now be replaced with their underlying type.  The default
is specified by the DEFAULT_DISPLAY_TEMPLATE_TYPEDEFS_IN_DIAGNOSTICS
macro and may be overridden with the --[no_]template_typedefs_in_diagnostics
command-line option.  Note that the TRUE value selects the old behavior and
FALSE the new behavior.

10/26/05 Compilation errors in some configurations

Various compilation error occurred when GNU_EXTENSIONS_ALLOWED and
DO_IL_LOWERING are TRUE and C99_IL_EXTENSIONS_SUPPORTED is FALSE.  This is
now fixed.

10/26/05 GNU C++ compatibility: Typedef names in elaborated type names

In GNU C++ mode with gnu_version < 30400, the front end now accepts elaborated
type names with a qualified typedef name that is a synonym for a class type.
Previously, typedef names were only accepted in such modes if the typedef was
itself a class member.  For example:

  typedef struct S T;
  struct ::T *p;  // Now accepted in some GNU C++ modes.

10/26/05 Compilation errors in some configurations

The layout.c file could not be compiled when USER_CONTROL_OF_STRUCT_PACKING and
IA64_ABI are TRUE, and GNU_EXTENSIONS_ALLOWED and MICROSOFT_EXTENSIONS_ALLOWED
are FALSE.  This is now fixed.

10/26/05 Spurious error on specialization of template specialized later

A spurious error was issued if a full explicit specialization of a member
function template of a class template was followed by an explicit
specialization of the template itself for a given instance of the enclosing
class.  In the example below, an error was issued that the template
specialization #2 must precede the first use of the template at #1.

  template <class T> struct A {
    template <class U> A(const A<U>&);
  };
  template <> template <> A<int>::A(const A<double>&);  // #1
  template <> template <class U> A<int>::A(const A<U>& ) {}  // #2

10/24/05 Internal error on dependent destructor call with incomplete type

An internal error in create_proxy_or_nonreal_class_member_of_kind could
occur as a result of a dependent destructor call using a qualified name
in which the class named is an incomplete type.  Now fixed.

  template<class T> class Y {
    class X;
    void fun(X *x) { x->X::~X(); }  // now gets "incomplete type not allowed"
  }; 

10/19/05 Microsoft compatibility: __is_union, __has_copy, etc.

In Microsoft C++ mode, with microsoft_version >= 1400, the front end now
accepts the following type trait pseudo-functions: __has_assign, __has_copy,
__has_nothrow_assign, __has_nothrow_constructor, __has_nothrow_copy,
__has_trivial_assign, __has_trivial_constructor, __has_trivial_copy,
__has_trivial_destructor, __has_user_destructor, __is_abstract, __is_class,
__is_convertible_to, __is_empty, __is_enum, __is_pod, __is_polymorphic, and
__is_union.  Each of these pseudo-functions takes one or two types, and
produces a boolean constant-expression.  For example:

  int a[__is_union(union U)];  // Okay.  Same as "int a[1];".

10/19/05 Incorrect handling of optimized class rvalue "?" initializer

IL lowering did not correctly optimize a class rvalue "?" operation
that is used as an initializer.  While the semantics of the resulting
code were not strictly speaking incorrect, they were not optimized,
and the flag is_optimized_class_rvalue_question_mark was still TRUE
on the dynamic initialization, which is not supposed to be possible
after IL lowering.  Now fixed.

  class A {};
  extern A a;
  void foo(int x) {
    A b = x ? a : A();
  }

10/17/05 GNU C++ compatibility: partial ordering and explicitly specified
         template arguments

Version 3.6 of the front end implements the resolution of core language issue
214, which clarifies how template parameters that are not used in the signature
of the function are handled for partial ordering (see 2/4/05 Changes entry).
g++ versions prior to 4.1 do not implement the revised rules causing examples
like the one below to be accepted by g++ but rejected by the front end.  We now
suppress the new behavior in g++ mode when gnu_version is < 40100.

  template <class S, class T> void f(T t);
  template <class T> void f(T t);
  int main() {
    f<int>(3);  // ambiguous as a result of core issue 214
  }

10/17/05 GNU C++ compatibility: internal error on invalid partial
	 specialization

A change made in version 3.6 causes an unusable partial specialization to
be accepted in g++ mode with a warning.  This change could result in an
internal error for certain cases.  Now fixed.

  template <typename T1> struct A {
    template <typename T2> struct Inner {};
  };
  template <> template <typename T> struct A<T>::B<int> {};

10/14/05 Microsoft compatibility: __ptr32 and __ptr64

In Microsoft modes, the front end now accepts the __ptr32 and __ptr64
modifiers on pointer and pointer-to-member declarators.  For example:

  int *__ptr64 p;  // sizeof(p) == 64

For normal pointer types, the modifiers force the size of the pointer to be
4 or 8 bytes respectively.  The modifiers do not affect the actual size of
pointer-to-member types (this is similar to the effect of these modifiers in
Microsoft's latest 32-bit compilers, but different from their effect in
Microsoft's latest 64-bit compilers).

10/14/05 Zero in GNU #line directive

Version 4.1 of the GNU compiler introduced a bug that results in the
generation of GNU #line directives (ones that omit the "line" keyword)
with a line number of zero for declarations of certain built-in entities.
For example:

  # 0 "<built-in>"

We now accept zero in such line directives (but not in the standard #line
form).  The directive is treated as if the number one had been used.

10/14/05 Declaration provided for EDG_MAIN when front end is callable

When MAKE_FRONT_END_CALLABLE is TRUE a declaration is now provided in
host_envir.h for the EDG_MAIN routine.  Note that EDG_MAIN is a macro
that specifies the name of the main program when the front end is called
as a function; the default is edg_main.

10/11/05 C++-generating back end: namespace-qualified base class names

In Microsoft C++ versions prior to 7.0, injected class names can be used
only in certain contexts (see the Changes entry of 11/17/99).  When
generating code for such targets, the C++-generating back end sometimes
failed to generate a necessary namespace qualifier for base class names.
Now fixed.  For example:

  namespace N {
    struct B { };
  }
  struct D: N::B {
    void f() {
      (N::B*)this;    // previously generated as "(B*)this"
    }
  };

10/11/05 GNU compatibility: Effect of __attribute__((packed)) on bit fields

In GNU modes, the front end failed to allow some bit fields to straddle byte
boundaries when the attribute "packed" was applied to a class type.   For
example:

  struct S {
    unsigned x:3;
    unsigned y:31;  // Previously forced to the next byte boundary.
                    // Now correctly placed at the fourth bit in the first
                    // byte of S.
  }  __attribute__((packed));

This is now fixed when ABI_COMPATIBILITY_VERSION >= 307.

10/11/05 GNU compatibility: special handing of __STDC__ in system headers

Some configurations of gcc/g++ define __STDC__ to 0 when processing code
from system header files and to 1 when processing other code.  Emulation
of this feature can now be enabled by the --[no_]stdc_zero_in_system_headers
command-line options.  The GNU mode default is specified by the
DEFAULT_GNU_STDC_ZERO_IN_SYSTEM_HEADERS macro.

10/10/05 Microsoft compatibility: injected template names implemented in VC 8.0

Prior to version 8.0, the Microsoft compiler did not create an injected
class name for class templates.  This is corrected in the 8.0 compiler.
In Microsoft mode, we now create an injected class name for class templates
when microsoft_version is >= 1400 (such injected class names are always
created in non-Microsoft mode when class name injection is enabled).

  template <class T> struct A {};
  template <class T> struct B : public A<T> {
    typename B::A a;  // accepted when microsoft_version is >= 1400
  };
  B<int> bi;

10/10/05 Missing NOTREACHED in cfe_exit

The cfe_exit routine in host_envir.c did not provide a "/* NOTREACHED */"
lint comment when MAKE_FRONT_END_CALLABLE is TRUE.  Now fixed.

9/28/05  C++-generating back end: operator->() and pseudo-destructors

The C++-generating back end formerly generated incorrect code for a call to
operator->() when the function was used in a pseudo-destructor invocation
and the return type of the operator function was not an exact match for the
pseudo-destructor name.  Now fixed.  For example:

  struct S {
    const int* operator->();
  };
  void f() {
    S s;
    s->~int();    // previously resulted in incorrect generated code
  }

9/27/05  Microsoft compatibility: __is_base_of

In Microsoft C++ mode, with microsoft_version >= 1400, the front end now
accepts the __is_base_of construct.  Specifically, __is_base_of(T1, T2) (where
T1 and T2 are arbitrary types) results in the boolean constant "true" when T1
and T2 are both class types and T1 is either a base class of or the same class
as T2.  Otherwise, the construct results in the boolean constant "false".
Cv-qualifiers on T1 and T2 are ignored.  For example:

  struct B {};
  struct D: B {};
  int a1[__is_base_of(B const, D)];  // Okay.
  int a2[!__is_base_of(B, D)];       // Okay.
  int a3[!__is_base_of(int, int)];   // Okay.

This has been implemented by adding a new and general capability to
represent "builtin operations" in the IL.  IL CHANGE: There are new
expression node kinds enk_builtin_operation and enk_type_operand,
but they will not show up in final IL except in prototype instantiations
or when RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE.

New mangling codes have been added for builtin operations, and
the demangler has been updated to recognize them.

9/27/05  GNU and Microsoft C compatibility: folding of float to integral
         conversion when result is out of range

The GNU and Microsoft C compilers accept the compile-time conversion to an
integral type of a floating-point value that is out of range.  Note that
in C++ such code is accepted but when the value is out of range the
conversion is deferred until run time.  We now accept such conversions
in GNU and Microsoft C mode with a warning.  Note that the C standard
specifies that such conversions result in undefined behavior.

In Microsoft mode, and in GNU mode when gnu_version is < 30400, the bits
that specify the value are truncated to fit in the destination type
and that value is used as the result.  For the cases below this yields
a value of 65533 for s1, 2 for s2, and -2 for s3.  In GNU mode when
gnu_version is >= 30400 the largest or smallest value that can
be represented in the destination type is used.  This yields a value of
0 for s1, 65535 for s2, and -32768 for s3.

  unsigned short s1 = (unsigned short)(-(3.5));
  unsigned short s2 = (unsigned short)(65538.0);
  short s3 = (short)(-(65538.0));

9/24/05  long long bit field integral promotions

The integral promotions for long long and unsigned long long bit fields
have been corrected to more closely match the C99 and C++ standards
(such bit fields don't get promoted if they're bigger than int, and
therefore the expression has the underlying type of the bit field).

  #include <stdio.h>
  struct S { unsigned long long x:33; } s = {0};
  int main() {
    if (s.x - 2 > 0) {   // Prints "unsigned" now
      printf("unsigned\n");
    } else {
      printf("signed\n");
    }
  }

9/22/05  Fix on g++ mode emulation of lookup of name in dependent call

The change of 4/19/05 to emulate g++'s lookup of names in dependent calls
was not quite right.  In particular, it caused aborts on cases where the
identifier to the left of the function-call "(" is a class variable that
is declared after the template definition (before that change, the
identifier was simply not found).  Now fixed.  Note that the problem only
appeared with gnu_version >= 30400.

  template <class Iterator> void accumulate(Iterator first) {
    plus(first);  // Call of class object declared later
  }
  struct Plus {
    void operator()(int);
  } plus;
  int main() {
    accumulate(0);
  }

9/22/05  Build problem with MAKE_FRONT_END_CALLABLE and C++-generating back end

The fe_wrapup.c file did not build properly when MAKE_FRONT_END_CALLABLE and
BACK_END_IS_CP_GEN_BE were both TRUE.  Now fixed.

9/22/05  C++-generating back end: build problems when compiling as C++ 

The C++-generating back end did not build properly when the front end
was built with a C++ compiler.  Now fixed.

9/21/05  C++-generating back end: name references in bound function calls

Regardless of the setting of RECORD_FORM_OF_NAME_REFERENCE, the form of the
reference in the source code used for the function name in a bound function
call was ignored when generating the call in the output.  The form of name
references in this context is now preserved when RECORD_FORM_OF_NAME_REFERENCE
is TRUE.  For example:

  template <typename T> struct B {
    virtual void f();
  };
  typedef B<int> Bi;
  struct D: Bi {
    void f() {
      Bi::f();   // formerly generated as "this->B<int>::f()", now preserves
                 // use of typedef as qualifier.
    }
  };

9/21/05  Bad IL for sizeof local variable within local class

When RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, the front end
produced IL with a memory region violation for a sizeof based
on a local variable appearing in a function-local class.  This
could cause aborts later in versions that don't keep all the IL
in memory (i.e., versions that write the IL to a file).  Now
fixed.

  static void f(int *sp) {
    union {
      char buf[sizeof *sp];
    } u;
  }

9/20/05  Microsoft compatibility: push_macro and pop_macro pragmas

The Microsoft push_macro and pop_macro pragmas are now supported in
Microsoft mode.

  #pragma push_macro("X")
  #define X 2
  int x2 = X;  // X is 2
  #pragma push_macro("X")
  #undef X
  #define X 1
  int x1 = X; // X is 1
  #pragma pop_macro("X")
  int x2a = X;  // X is 2 again
  #pragma pop_macro("X")

  #ifdef X
  #error X should not be defined
  #endif

9/17/05  Microsoft 6.0 emulation: __int32 promotes to int

In Microsoft 6.0 emulation (microsoft_version=1200), the __int32
type now promotes to int under the integral promotions instead of
staying unchanged.

  void foo(int);
  void foo(short);
   void bar() {
     __int32 a = 1;
     foo(a);  // Not ambiguous: calls foo(int)
   };

9/16/05  C++-generating back end: pointer-to-member casts

The C++-generating back end formerly omitted casts in the generated code
when converting a pointer-to-base-member constant to a
pointer-to-derived-member type, even if the base was inaccessible.  Casts
required to override access restrictions are now generated. For example:

  struct B {
    int i;
  };
  struct C: private B { };
  int D::*p = (int D::*)&B::i;  // cast now appears in generated code

9/16/05  GNU C++ compatibility: Accessibility of anonymous union members

An anonymous union member acquires the accessibility of its enclosing union.
When (possibly nonstandard) anonymous unions are nested -- by default not
allowed in strict mode -- the accessibility adjustment is normally repeated
for every anonymous union level, but in GNU C++ mode, the adjustment is now
only done for the first enclosing union.  For example:

  class C {
    union {
      struct {  // Nonstandard anonymous union.
        int i;  // Normally first promoted from the struct to the union, then
      };        // from the union to the class and the second promotion makes
    };          // the field private.  In GNU C++ mode, the second promotion
  };            // does not affect accessibility (i.e., the field remains
                // public in this case).

9/15/05  GNU mode lvalue casts

The handling of GNU mode lvalue casts has been reworked (again) to
get closer to what gcc and g++ do.  The specific case that drove
this work appears in a Linux <fstream> header and is illustrated
by the following reduced test case:

  template<class T> struct B { void operator>>(int&) {} };
  enum { e } x;
  int main() {
     B<int> b;
     b >> (int)x;  // (int)x is treated as an int lvalue
  }

IL CHANGE: as part of this work, the "lvalue cast" operator
eok_lvalue_cast is now used in GNU C++ and Microsoft C++ modes.
Formerly, it was generated only in some C modes.

9/13/05  Const-qualification and array fields in C99

In C89, an lvalue of a struct type is considered modifiable even if one of
its fields is an array of const-qualified elements.  In C99, this is no longer
the case, and the front end now enforces this constraint in its strict C99
mode.  For example:

  struct S { int const i[2]; };
  void f(struct S src, struct S *dst) {
    *dst = src;  // Now an error in strict C99 mode.
  }

9/13/05  GNU C compatibility:  __builtin_types_compatible_p

In GNU C mode, __builtin_types_compatible_p is now accepted.  It takes two
types and produces a constant value 1 or 0, depending on whether those types
are compatible or not.  For example:

  int i = __builtin_types_compatible_p(int[], int[5]); // Same as "int i = 1;"

9/13/05  Pragma processing: saving both text and token versions of pragmas

Formerly, a pragma could be saved as either a text string or a token
cache based on the setting of the make_text_not_tokens field of the
pragma.  The front end has been changed to always save the token cache
version of the pragma (except for pragmas scanned in fetch_pp_tokens
mode).  The make_text_not_tokens field has been renamed to record_pragma_text
and controls whether or not the string version of the pragma should be
saved in addition to the token cache.  It is still the case that the
token cache is only available for use in the front end.  The IL representation
of the pragma does not include the token cache information.  This change was
made to allow a pragma to be scanned by the front end as tokens but to still
permit the pragma text to be passed to a back end (e.g., the C++-generating
back end) for inclusion in the generated code.

9/12/05  GNU C compatibility: __builtin_choose_expr

In GNU C mode, __builtin_choose_expr is now accepted.  This pseudo-function
takes three arguments.  The first must be a scalar constant-expression: It
determines whether the result of the pseudo-call is the second or the third
operand (the other operand is discarded).  For example:

  int i;
  int j = __builtin_choose_expr(1, 3, i);  // Okay.  Same as "int j = 3;"

9/12/05  C++-generating back end: access labels in anonymous unions

When an anonymous union or a nonstandard anonymous union appeared as a
non-public member of a class, the C++-generating back end formerly added
access labels reflecting the effective access of the members of the anonymous
union, resulting in invalid generated code.  For example:

      Original source:          Previously generated:
      ----------------          ---------------------
      class C {                 class C {
        union {                   union {
          struct {                  public: struct {
            int i;                    private: int i;
          };                        };
        };                        };
      };                        };

The extraneous access labels are now omitted from the generated code.

9/8/05   GNU compatibility: asm output operand constraints

Output operands specified in extended GNU asm constructs must normally be
modifiable lvalues.  However, various versions of the GNU compilers diagnose
this constraint differently.  Specifically, when the operand is a const lvalue,
some versions of the GNU compiler issue an error, others only warn, and the
latest silently accept such operands.  The EDG front end now warns in such
cases (for all values of gnu_version).  For example:

  void f() {
    int const x;
    asm("mov %0, r0": "=r"(x));  // Previously an error because "x" is not
  }                              // modifiable.  Now just a warning.

See also the Changes entry of 7/15/05.

9/8/05   Macro expansion to produce tokens of _Pragma operator

Macro expansion is now done when scanning the tokens that make up a C99
_Pragma operator.  In particular, the string literal token and the closing
right parenthesis may now be the result of macro expansion.  Note that macro
expansion may or may not be done (based on the pragma kind) for the tokens
that make up the string literal when the pragma is evaluated.

  #define PRAG  "diag_suppress 177"
  #define X() _Pragma(PRAG)
  X()  // now accepted, formerly "expected a string literal"
  static int i;

9/8/05   Classes defined with qualified names

In strict C++ mode, the front end now issues a discretionary error when a
class is defined with a qualifier that designates an entity in which the
class was not originally defined (but in which the class is visible by virtue
of inheritance or using-declarations).  For example:

  struct B { struct N; };
  struct D: B {};
  struct D::N {};  // Now an error in strict C++ mode.

  namespace N { struct S; }
  namespace M { using N::S; }
  struct M::S {};  // Now an error in strict C++ mode.

This implements a requirement of the C++ standards committee's core issue 417.

9/7/05   Buffer overflow in form_wide_char

The buffer used for the hexadecimal form of wide characters could overflow
for some values.  Now fixed.

9/7/05   Friend function declarations with default arguments

In strict C++ mode, the front end now issues an error if a friend function
declaration with default arguments is not a definition, or if it is not the
only declaration of that function in the translation unit.  For example:

  struct S {
    friend void f1(int = 0);   // Error in strict mode: Must be a definition.
    friend void f2(int = 0) {}
  };
  void f2(int);  // Error in strict mode: Friend function definition with
                 // default arguments cannot be redeclared.

These diagnostics are required by the resolution of the C++ standards
committee's core issue 136.

9/7/05   GNU C++ compatibility: Empty asm clobber lists

In GNU C++ mode (but not in GNU C mode), the front end now accepts empty
clobber lists in extended asm constructs.  For example:

  void f() {
    asm ("nop" : : :);  // Previously an error in all GNU modes; now accepted
  }                     // in GNU C++ mode.

9/1/05   Microsoft C++ compatibility: Visibility of member function parameters

In microsoft C++ mode, member function parameters are now not visible within
default argument expressions.  For example:

  int x();
  struct S {
    void f1(int x = x());  // Accepted in Microsoft mode (normally an error).
  };

9/1/05   GNU C++ compatibility: Visibility of parameters

In GNU C++ mode, function parameters are now not visible until all the
parameters of the function declaration have been parsed.  For example:

  struct S;
  void f1(S *S, S *T);   // Normally an error, but accepted in GNU C++ mode.
  int x();
  void f2(int x = x());  // Normally an error, but accepted in GNU C++ mode.

8/31/05  Use of isalpha and ispunct functions

In some locales, isalpha and ispunct classify some characters differently
from their meaning in C and C++.  The front end has been modified to
eliminate the use of these functions in contexts where the locale-specific
results could cause incorrect processing.

8/25/05  GNU compatibility: __builtin_offsetof

In GNU mode with gnu_version >= 40000, the front end now supports the GNU
__builtin_offsetof operator.  For example:

  struct S { int i, j, k; };
  int a[__builtin_offsetof(S, k)];

8/25/05  Volatile arrays and class members

The front end has been changed to mark arrays whose element type is
volatile-qualified and objects of a class type with a volatile-qualified
member as both referenced and set, preventing warnings about them.  For
example, the following code formerly resulted in a warning in C mode:

  void f(int i, int v) {
    static volatile int a[10];  /* no longer warns "set but never used" */
    a[i] = v;
  }    

8/25/05  GNU statement expressions in unevaluated contexts

The front end sometimes aborted while processing a GNU statement
expression inside a sizeof or a similar construct that does not
evaluate its operand (e.g., __builtin_constant_p).  In particular,
a local declaration within the statement expression caused the
abort.

  int main() {
    sizeof( ({ int i; 0; }) );  // Previously aborted
  }

8/25/05  Return value optimization in spite of cv-qualifier difference

The return value optimization is now done even when the local variable
and the function return type differ in cv-qualification, as permitted
by the C++ standard.

  struct A {
    A();
    A(const A& rhs);
    ~A();
  };
  const A foo() {
    A nrv;
    return nrv;  // Return value optimization now done
  }

8/24/05  C++-generating back end: placement of #pragma pack() directives in
         typedef declarations

When the C++-generating back end generated a "#pragma pack" directive to
control the member alignment of a class definition that appears inside a
typedef declaration, the directive was inserted between the "typedef" keyword
and the class declaration.  Recent versions of the GNU compiler no longer
accept the "#pragma pack" directive in this position, so the C++-generating
back end now emits the directive before the "typedef" keyword.  For example:

  Original source:       Previously generated:        Now generated:
  ----------------       ---------------------        --------------
  #pragma pack(1)        typedef                      #pragma pack(1)
  typedef struct {       #pragma pack(1)              typedef
  } S;                   struct {                     struct {
                         } S;                         } S;
                         #pragma pack()               #pragma pack()

8/24/05  GNU C compatibility: promotion of long long bit fields of same size
         as long

The emulation of gcc's promotion rules for bit fields of type long long
and unsigned long long has been tweaked slightly for fields that are
exactly the same size as "long".

8/24/05  Uninitialized fields in statement source position

In configurations with FULL_SOURCE_POS_IN_IL_STATEMENT and
FULLY_RESOLVED_MACRO_POSITIONS set to TRUE, the orig_seq and orig_column
(and, if MACRO_INVOCATION_TREE_IN_IL is TRUE, the macro_context) fields were
left with garbage values for statements that do not have source positions.
Now fixed.

8/24/05  IA-64 ABI: optimized virtual function invocation

When a virtual function in a virtual base class is overridden, the IA-64
ABI specifies that a thunk must be generated that adjusts the "this" pointer
in two steps, first to the beginning of the virtual base class subobject and
then, using the function's vcall offset, to the subobject of the overriding
function's class.  In cases where one or both of these offsets are zero,
however, the specification allows the virtual function table to bypass this
thunk and call the virtual function directly or via a less-expensive thunk.
The virtual tables generated by IL lowering now incorporate this optimization
in most cases where it is performed by g++ (subject to gnu_abi_version).
For example:

  struct B {
    virtual void f();
  };
  struct D: virtual B {
    void f();     // now called directly, not via thunk, in D's vtable
  };

8/23/05  Sun compatibility: overloaded operator []

In Sun compatibility mode, the processing for the overloaded
subscripting operator [] no longer considers integer[pointer]
as a pattern satisfying the operator.

  struct String {
    String(const char*);
  };
  struct node {
    operator bool ( ) const;
    int operator [ ] (const String &);
  };
  int main() {
    node a;
    a["FILE"];  // No longer ambiguous in Sun mode
 };

8/23/05  Microsoft compatibility: dropping cv-qualifiers on "?" operator

Microsoft mode nows allows dropping cv-qualifiers (e.g., const) when
converting the second or third operand of a "?" operator to the other
operand type, if the conversion is from derived to base.

  class B {};
  B b;
  struct D : public B {
     void foo(const D& cd) {
       0 ? cd : b;  // Now accepted in Microsoft mode
    }
  };

8/22/05  C99 inline specifier and block-extern function declarations

Version 3.6 corrected some issues with the C99 "inline definitions" (see
Changes entry of 3/24/05).  However, the front end incorrectly included
block-extern declarations in the determination of whether a definition of
a function was an "inline definition" or not.  For example:

  inline void f() {}  // Inline definition of f().
  int main() {
    void f();  // No longer affects whether the definition of f() is an
    f();       // "inline definition" or not.
  }

In addition, the front end now accepts the "inline" specifier on block-extern
declarations in C99 mode.  For example:

  void g() {
    inline void f();  // Now accepted in C99 mode.
  }

8/19/05  End position of typeof construct used in a declaration

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the front end failed to record the
end position of a GNU typeof construct used as the last component of a set of
declaration specifiers.  For example:

  typeof(int) x;  // End position of typeof was not recorded in the
                  // specifiers_range of the a_decl_position_supplement
                  // associated with "x".

This is now fixed.

8/19/05  GNU mode: Built-in infinity functions

In GNU modes, the front end now constant-folds calls to the built-in functions
__builtin_inff, __builtin_inf, and __builtin_infl (when the configuration macro
TARG_HAS_IEEE_FLOATING_POINT is set to TRUE).  See also the Changes entry of
11/19/03.

8/18/05  Failure to lower some designated initializers

Certain designated initializers were not lowered by IL lowering,
specifically ones appearing in compound literals in C mode and GNU
C++ mode.  Now fixed.

  struct X { int a; char *b; };
  struct X *p = &(struct X){ .b = "hello", .a = 42 };  // Not lowered

8/18/05  Microsoft compatibility: directing diagnostic messages to stdout

In most cases, the Microsoft compiler outputs diagnostic messages to stdout
instead of stderr.  The front end can now be configured to emulate this
behavior.  When DIRECT_ERROR_OUTPUT_TO_STDOUT is TRUE, diagnostic output is
directed to stdout instead of stderr, except when doing preprocessing only.
This flag applies to messages output after command-line processing has
completed.  Diagnostics output during command-line processing are always
directed to stderr.

8/18/05  GNU C++ compatibility: Type definitions in compound literals

A change in version 3.6 of the front end caused type definitions in compound
literals to be rejected in GNU C++ mode when gnu_version >= 30400 (see Changes
entry of 3/22/05).  Now such definitions are allowed in all GNU C++ modes.
For example:

  void f() {
    (struct S { int i; }){ 3 };  // Previously an error in some GNU C++ modes.
  }                              // Now accepted in all GNU C++ modes.

8/17/05  GNU C++ compatibility: __offsetof

In GNU C++ mode with gnu_version >= 30400, the front end now treats __offsetof
(and __offsetof__) as a synonym for __INTADDR__ (the latter is an EDG-specific
device to implement the standard offsetof macro).

8/16/05  Abort in find_local_static_variable_init on exception handling
         lowering

During IL lowering, while processing a throw of a pointer to a pointer
in the Cfront-like ABI, the front end aborted in
find_local_static_variable_init ("none found for specified variable").
The throw has to be inside a block with no declarations which is
inside another block that does contain local variables.  The IL
constructed was incorrect: it had the local static variable
initialization entry for a generated array in the wrong scope, which
could cause aborts in later phases.  With the C-generating back end,
the abort described above resulted.  Now fixed.

  int main() {
    int **ptrptr = 0;
    {
      throw ptrptr;
    }
  }

8/16/05  Abort on typedefs of unnamed types matched across translation units

When simultaneously processing multiple translation units in C++ mode, the
front end sometimes aborted with an internal error when trying to match two
unnamed class or enumeration types that have acquired a name for linkage
purposes through a typedef.  For example:

  // File 1:
  typedef struct {} S1;
  typedef S1 T;

  // File 2:
  typedef struct {} S2;
  typedef S2 T;  // Previously triggered an internal error; now a normal error.

This is now fixed: A normal error is issued in such cases.

8/16/05  Partial specializations and assoc_template field for classes

Formerly, the assoc_template field of a class would point to the
primary template even if the class was instantiated based on a partial
specialization.  In such cases, the assoc_template field now points
to the partial specialization.

  template <class T, class U> class A;
  template <class U> class A<int, U> {};
  A<int, float> a;

8/16/05  Name of function in diagnostic about implicitly-declared function

The diagnostic in C mode indicating that a function was implicitly
declared now includes the name of the function.  This is helpful
when the source line involves macro expansions.

8/16/05  Template keyword permitted before nonmember template

The C++ standards committee has relaxed the rules regarding the use of
the template keyword for syntactic disambiguation (core issue 228).  It is
now permitted before any template name, not just before member template
names.  We now implement the relaxed rules.

  template<class T>
  struct X {
     virtual void f();
  };
  template<class T>
  struct Y {
    void g(X<T> *p) {
      p->template X<T>::f();  // now accepted in strict mode
    }
  };

8/16/05  Missing diagnostic on improper use of template keyword

The front end failed to diagnose certain improper uses of the template
keyword for syntactic disambiguation when the name that follows the
template keyword was not followed by a "<".  Now fixed.

  template<class T> struct X { virtual void f(); }; 
  template<class T> struct Y {
    void g(X<int> *p) {
      p->template f();  // now gets diagnostic in strict mode
    }
  };

8/16/05  Missing destructor call on object without constructor

In some cases involving variables of a class type with a destructor but no
user-defined constructor, the front end failed to generate a destructor call
for the end of the variable's lifetime.  For the problem to occur the
variable needed a parenthesized initializer (i.e., direct-initialization
syntax).  For example:

  struct S { ~S(); };
  void f() {
    S s1;
    S s2(s1);  // Previously no destructor call was generated for s2.
  }

This is now fixed.

8/16/05  Default argument problem with member of nested class of class template

If a member function of a nested class (or nested class template) of a
class template contains a default argument, that default argument may not
have been visible to instantiations of the nested class that occur during
the definition of the enclosing class.  Now fixed.

  struct A { 
    template<typename T> struct B { 
      static void f(T, bool=true); 
    }; 
    B<int> bi;
  }; 
  int main() { 
    A::B<int>::f(1);  // spurious "too few arguments" error
  } 

8/15/05  Warning on use of multicharacter character literal

Character literals with more than one character yield an implementation-defined
value.  A warning is now issued for such constructs.

  int i = 'ab';

8/15/05  Incorrect variant used in set_mixed_static_nonstatic_flag

An incorrect symbol variant was referenced in set_mixed_static_nonstatic_flag
if an overload set in a class template contained a nonreal base class member.
This could result in an abort in certain configurations.  Now fixed.

  template <class T> class A {};
  template <class T> struct B : A<T> {
    using A<T>::f;
    template <class U> void f(){}
  };

8/15/05  Spurious error on block extern declaration of inline function

In C++ and C99 modes, a spurious "referenced but not defined" error was
issued if an inline function was called via a block extern declaration
and the inline function was not defined until later in the translation unit.
Now fixed.

  inline int f(int, int);
  int main() {
    int f(int, int);
    return f(1,2);
  }
  inline int f(int a, int b) {
    return a+b;
  }

8/12/05  Declaration with the same name as a referenced base class member

An error was issued if a class declared a member with the same name as
a base class member that had already been referenced by the derived class.
While such an error is permitted by the standard, most compilers allow
the usage.  We now diagnose such errors only in strict mode.

  struct A {
    class B;
  };
  struct D : public A {
    B f();
    class B;
  };

8/11/05  Ability to use C++ bool type as a_boolean

The front end can now be configured to use the C++ bool type as the
type of a_boolean and a_byte_boolean.  This can be useful for checking
that boolean types are used appropriately.  This feature can be enabled
by setting the USE_BOOL_AS_BOOLEAN_IN_CPLUSPLUS macro to TRUE.  There
were several places in the front end where a_boolean values were incorrectly
being used as integers.  As part of this change, such incorrect usage has been
fixed.

8/10/05  Initialization in aggregate lost by IL lowering

IL lowering lost an initialization in a non-POD aggregate class in a
case where the variable being initialized is optimized away by the
return value optimization, a member initializer is constant, and
there is another member initializer following the constant
initializer.  Any initializers after the constant were lost.  Now
fixed.

  struct B {
    int j;
    B(int jj) : j(jj) {}
    B(const B&s) : j(s.j) {}
  };
  struct A {  // "A" must be an aggregate class but not a POD
    int i;
    B b;
  };
  A f() {
    A x = { 1, 2 };  // The "2" initializer was previously lost
    return x;
  }

8/9/05   Template argument deduction and functions with default arguments

When a function type is deduced as a template argument, the default arguments
of the function should not be part of the deduced type.  Formerly, the front
end would use the default arguments, if any, from the first function type
used to produce a given instantiation of a template.  The front end now
discards the default arguments associated with deduced function types, as
mandated by the C++ standard.

The new handling of default arguments is enabled and disabled by the
command-line options --[no_]nonstd_default_arg_deduction.  The default
is specified by DEFAULT_NONSTANDARD_DEFAULT_ARG_DEDUCTION.  The old
behavior is retained by default in Microsoft mode (when microsoft_version
is <= 1300), g++ mode, Sun mode, and Cfront mode.  The new behavior is
used by default in strict mode.

  template <class T> inline void g(T f) {
    f(1);
    f();  // should get an error
  }
  void f1(int i = 99){}
  void f2(int i = 999){}
  int main() {
    g(f1);
    g(f2);
  }

8/9/05   Incorrect IL on C++ mode top-level volatile bit field reference
         with side effects

IL lowering did an incorrect transformation on a reference to a volatile
bit field when it is a top-level expression in C++ mode and the first
operand of the bit field selection has side effects.  The incorrect
IL indicated that a load of the bit field should be done.  Now fixed
(no load is indicated).  Note that the C mode behavior of such cases
is unchanged (the load should be done).

  struct A {
    volatile int j:3;
  };
  extern struct A* h();
  void f() {
    (h())->j;  // The bit field should not be accessed
  }

8/9/05   Microsoft C compatibility: mixed void/non-void operands to "?"

A tweak to the change of 12/21/04 regarding void/non-void operands to
the "?" operator in Microsoft mode: In Microsoft C mode with
microsoft_version > 1200, mixed void and non-void operands should
still be accepted.  The result type is void.

  void f();
  int main() {
    int i = 1;
    i ? 0 : f();  // Okay in Microsoft C mode, all versions
                  // With microsoft_version > 1200, result type is void
  }

8/9/05   No array-to-pointer decay in second operand of comma operator

The array-to-pointer conversion is not supposed to be applied to the
second operand of a comma operator.  The front end formerly applied
it, and no longer does.

  int main() {
    char arr[100];
    int i = sizeof(0, arr);  // i should be set to 100
  }

8/9/05   IA-64 ABI exception handling, typeinfo variables for reference types

When the EDG front end is configured with IA64_ABI true and
GENERATE_EH_TABLES false (i.e., roll-your-own IA-64 ABI exception
handling), a use of a catch parameter or exception specification of
reference type causes an internal error in get_typeinfo_kind ("bad
type").  This is in code that a customer would probably have to change
anyway as part of implementing exception handling, but it does seem
like bad form for the front end "out of the box" to abort like that,
so we've made a localized fix to eliminate the abort.  The underlying
problem is that the specification for the Itanium/IA-64 ABI does not
provide a typeinfo representation for reference types.  This is okay
in general, since objects never have reference types, but it is a
problem for catch parameters and exception specifications of reference
types.  The current g++ implementation manages to handle those without
typeinfos for references (it uses pointers instead), but we're told
that's probably a bug.  The ABI spec may be updated at some point to
add a typeinfo representation for references, and when it does we will
add that as well.  In the meantime, the abort is gone.

8/8/05   GNU C compatibility: casting to union type in constant expression

gcc allows a cast to a union if the source expression has a type
compatible with the type of one of the members of the union.  This is
related to the "transparent union" feature.  Heretofore, the EDG
front end has not allowed such a cast in a constant expression.
Now, it does.  The operand of the cast must be constant.

  typedef union {
    long long v;
    struct {
       int low;
       int high;
    } w;
  } int64;
  int64 null = (int64)0LL;  /* Now accepted in gcc mode. */

8/5/05   Implicit conversion of function types and template deduction

In some modes, an implicit conversion between pointers to functions with
with C and C++ linkage is permitted.  This conversion was not considered
when deducing template arguments from a C function type, resulting in
a spurious type deduction failure for examples like the one below.  Now
fixed.

  extern "C" typedef void (*fp)(int);
  template <class T> void f(T){}
  int main() {
    fp x = f;
  }

8/4/05   Abort on local aggregate initializer with Microsoft C99 mode

The front end aborted in lower_c99_initializer ("bad init kind") on
processing a nonconstant aggregate initializer on a local variable when
Microsoft and C99 modes were enabled together.  Now fixed.

  struct S {
    int a, b;
  };
  int x;
  struct S test() {
    struct S s = {x};  // Caused assertion failure with --microsoft --c99
    return s;
  }

8/3/05   Issuing certain warnings or remarks only once

A feature has been added to the diagnostic control facilities to
permit a given diagnostic to be issued only once as a warning or remark.
The --diag_once command-line option and the diag_once pragma are used to
specify the error messages that are to be issued only once during a
compilation.  Note that errors are not affected by this feature; they
are always issued.

  #pragma diag_once 177
  static int i;  // declared but never reference warning emitted
  static int j;  // warning suppressed on this line

8/2/05   Friend class template declarations not allowed

The C++ standards committee has clarified that a friend class template
declaration may not specify a default template argument (core issue 21).
We now implement this rule.  An error is issued in strict errors mode,
a warning in other modes.

  class B {
    template<class T1, class T2 = int> friend class A;
  };
  A<int> ai;

8/2/05   gcc compatibility: comma expression with function as second operand

In gcc mode, a comma expression whose second operand is a function now
again returns a pointer to function.  The change of 7/13/03 incorrectly
had changed that to preserve the second operand as a function.

  void foo(void);
  int main() {
    int i = sizeof(1, foo); // i set to sizeof pointer-to-function
  }

8/2/05   Microsoft compatibility: Ambiguous conversions on "?" operator

When determining the applicable conversions between the second and
third operands of a "?" operator, MSVC++ appears to consider ambiguous
conversions as impossible.  The EDG front end now does likewise.

  struct A {
    A(int);
    operator unsigned long() const;
    operator double() const;
  };
  int main() {
    int i = 1;
    A u(0);
    A x(i ? u : 0);  // Now accepted in Microsoft bugs mode
  }

8/1/05   Microsoft compatibility: Packing and explicitly aligned types

In Microsoft modes, the front end now ignores packing directives for fields
of types with explicit alignment requirements.  For example:

  #pragma pack(2)
  struct __declspec(align(4)) A {
    char a;
  };
  struct S {
    char s;
    A a;  // Aligned on a 4-byte boundary despite the 2-byte boundary
  };      // packing in effect.  Therefore, sizeof(S) == 8 (not 4).

8/1/05   Abort on direct-initialization elision optimization

A bug was introduced in version 3.6 by the changes for copy
constructor elision in direct-initialization cases (see Changes
entry of 3/21/05).  This caused an assertion failure in expr.c/
scan_ctor_arguments on cases that use conversion functions
returning a class for which copy construction can be done
by a bitwise copy.  Now fixed.


  struct A {
    A(int);
  };
  struct B {
    operator const A();
  } b;
  int main() {
    A a(b);  // Formerly aborted
  }

7/29/05  Unrepresentable enumerator constants

When enumeration types can be larger than int types (e.g., in most C++ modes),
the front end now issues an error (in strict mode) or a warning (in other
modes) when not all the enumerator constants can be represented by a single
integral type.  For example (assuming "long" is the signed integral type with
the largest range):

  enum E { a = LONG_MIN, b = ULONG_MAX };  // Now a warning or error because
                                           // no integral type can represent
                                           // both a and b.

Also, in strict C++ mode with LONG_LONG_ALLOWED set to TRUE, the front end
formerly always selected "long long" as the type underlying the enumeration in
the example above.  Now, an error is issued instead, unless type "long long"
was explicitly enabled (using the --long_long option).

7/29/05  Internal error on nondeduced parameter in partial ordering

Version 3.6 introduced a change to allow partial ordering of functions
in which certain template parameters are not used in the signatures
of the functions (see Changes entry of 2/4/05).  Certain cases that
were ambiguous before that change could result in an internal error in
wrapup_template_argument_deduction after the change.  Now fixed.

  template <int N, class T> void f(T const&) {}
  template <int N, class T> void f(T&) {}
  int main() {
    int const ci = 3;
    f<1>(ci);
  }

7/28/05  Types without linkage used for entities with external linkage

In C++ mode, the front end sometimes silently accepted declarations of entities
with external linkage involving class types or enumeration types without
linkage.  Now such declarations are always diagnosed (an error in strict mode;
otherwise, a warning for functions or a remark for variables).  For example:

  enum { no, yes } anwer;  // Previously silently accepted; now a diagnostic.
  struct S {
    typedef struct {} *P;
    static P x;  // Previously silently accepted; now a diagnostic.
  };

This is a change related to the C++ standards committee's core issue 389.

7/28/05  Microsoft compatibility: full path name of primary source file

To simplify the generation of debug information that is similar to that
of the Microsoft compiler, the full_name field of the source file entry
for the primary source file now contains the full path name of the
file.  This is done in Microsoft mode when microsoft_version is >= 1300.

7/28/05  Microsoft and GNU compatibility: class rvalue "?" result temporary

The changes of 11/14/04 that implemented core issue 446, which
force a temporary as the result of a "?" operator returning a class rvalue,
introduced Microsoft and GNU compatibility issues, because MSVC++
and g++ do not implement that adjustment to the standard yet.
The front end has been changed to more closely emulate the
behavior of those compilers.

7/27/05  Microsoft compatibility: Spurious error when dropping "__unaligned"

In Microsoft mode, the front end previously issued an error if a pointer
qualified as "__unaligned" was implicitly converted to a pointer that is
not so qualified.  For example:

  int* f(__unaligned int *p) {
    return p;  // Previously an error; now a warning.
  }

Now a warning is issued instead (or no diagnostic at all if the destination
is a pointer to a type with no alignment requirements, like void or char).

7/27/05  GNU C++ mode: Spurious error on designator for anonymous union member

In GNU C++ mode, the front end failed to resolve field designators in
anonymous union contexts.  For example:

  struct S {
    union {
      int i;
    };
  } s = {{ i:3 }};  // Previously a spurious error.  Now accepted.

This is now fixed.

7/27/05  Spurious warnings on enum bit fields

In some cases involving bit fields with enumeration types whose enumerator
constants are all nonpositive, the front end issues a spurious warning about
the field being unable to represent all the enumerator values.  Furthermore,
if the field was one bit wide, an additional diagnostic warned about a signed
bit field having length one even when the enumerators only included the values
"0" and "-1" (which fit in a signed one-bit field).  For example:

  enum E { a = -1, b = 0 };
  enum F { c = -2, d = 0 };
  struct S {
    E x:1;  // Previously triggered two spurious warnings.  Now none.
    F y:1;  // Previously triggered two warnings.  Now just one.
  };

This is now fixed: At most one warning is issued and only when it is justified.
Only configurations with TARG_ENUM_BIT_FIELDS_ARE_ALWAYS_UNSIGNED set to FALSE
are affected by this change.  Other configurations produce different warnings.

7/26/05  Bad IL for constant array bound in VLA context, with
         RECORD_CONSTANT_EXPRESSIONS_IN_IL

A bug was introduced in the changes made for variable-length arrays
(VLAs) in version 3.6.  It affects configurations with
RECORD_CONSTANT_EXPRESSIONS_IN_IL set to TRUE (e.g., C++-generating
back end versions) and source cases that have a use of a simple
const variable as an array bound in a context that allows a VLA
(e.g., in GNU C++ mode).  The IL created had a memory region problem,
which could cause later aborts.  In particular, the abort
"non_fs_remap_checking: func number in file scope" occurred in
versions that write and read an IL file.  Now fixed.

  int main() {
    const int SIZE = 1;
    int array[SIZE] = { 0 };
    return array[0];
  }

7/25/05  Deduction failure on pointer-to-member with qualification conversion

Template argument deduction could fail if a member type and a
pointer-to-member class type were both deduced from the same type,
and the member type required a qualification conversion.  Now fixed.

  template <class CLASS, class T> void f(const T CLASS::*offset){}
  struct A { int i; };
  int main() {
    int A::*pi = &A::i;
    f(pi);
  }

7/22/05  GNU compatibility: Invalid attributes on automatic variables

The severity of the diagnostic issued when attempting to apply a GNU "used"
or "nocommon" attribute to an automatic (local) variable has been reduced
to a warning (previously, it was an error).  The invalid attributes are
otherwise ignored.  For example:

  void f() {
    int a __attribute__((used));  // Previously an error; now a warning.
  }

7/22/05  Incorrect preprocessed output when including both cstdarg and stdarg.h

In configurations with DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE set
to TRUE, the preprocessed output for files including both cstdarg and
stdarg.h was not correct (only the first of the includes was emitted
in the preprocessed output).  Now fixed.

  #include <cstdarg>
  #include <stdarg.h>
  ::va_list x; 

7/21/05  Microsoft compatibility: x ? f() : g() is an lvalue only up to 7.1

A Microsoft compatibility feature first introduced as one small
piece of a change dated 8/14/03 has now been turned off when
microsoft_version >= 1310.  Specifically, a "?" operator with
second and third operands of the same class type, and at least
one of them an rvalue, is treated as an lvalue by MSVC++ up
to version 7.0.  But 7.1 changed that, and our front end now
does the same.

7/21/05  Microsoft class specifier differences across translation units

When simultaneously processing multiple translation units in Microsoft mode,
the front end now ignores differences in extended specifiers for corresponding
class type entries if the two entries do not both describe a complete class.
For example:

  // File 1:
  struct S;
  struct T {};

  // File 2:
  struct __declspec(dllexport) S {};  // Okay: The corresponding entry in
                                      // "File 1" is not defined.
  struct __declspec(novtable) T {};   // Error: The extended declaration
                                      // specifiers differ from those on the
                                      // definition in "File 1".

7/21/05  Thread-local variables and initialization

The front end now issues an error when attempting to dynamically initialize a
thread-local variable that is not a local static variable.  For example:

  int f();
  __thread int i = f();  // Previously accepted (e.g., in GNU C++ mode); now
                         // an error.

Furthermore, the address of a thread-local variable is no longer considered
to be a constant.  For example:

  __thread int i = 2;
  __thread int *p = &i;  // Previously accepted (e.g., in GNU C++ mode); now
                         // an error.

7/21/05  Restricted references

The front end previously silently ignored the "restrict" (or "__restrict__")
type qualifier when applied to reference types.  Now, the qualifier is
correctly retained.  For example:

  void f(int & __restrict__ a) {
    // The "__restrict__" modifier was previously silently ignored.
    // Now it is retained (and the reference becomes a restricted pointer
    // after lowering).
    // ...
  }

7/19/05  Errors after macro_buffer reallocation in pcc and Microsoft modes

As a space optimization, expand_top_level_pcc_macro (which is also used in
Microsoft mode) formerly simply overwrote the text of the initial macro
expansion with the fully-expanded text.  This optimization was based on the
assumption that any text following the initial expansion in the macro_buffer
must be the result of macro invocations performed during its own processing
and thus could be discarded.  That assumption was no longer valid after the
changes described below in the 2/18/05 entry, as the compaction process can
reorder sections of inserted text inside macro_buffer.  Now fixed.

7/19/05  GNU mode and thread-local storage

Previously, support for thread-local storage in GNU mode (the "__thread"
keyword in particular) was enabled by default when gnu_version >= 30400.
Now it is enabled by default when gnu_version >= 30300 since it appears
that gcc/g++ version 3.3 is usually (but not always) configured to support
thread-local storage on popular platforms.

7/18/05  C++-generating back end: placement of #pragma pack() directives

When USER_CONTROL_OF_STRUCT_PACKING is TRUE, the C++-generating back end
precedes a class definition that has non-default member alignment with a
"#pragma pack" directive specifying that alignment and, unless
gcc_is_generated_code_target is TRUE, follows it with "#pragma pack()" to
restore the alignment to the default value.  The latter directive was formerly
generated immediately following the closing brace of the class definition;
now it is generated after the closing semicolon of the declaration in which
the class definition appears.  This change avoids a problem where Sun
compilers interpret the "#pragma pack()" as applying to a typedef-name that
follows the directive.  For example:

  Original source:       Previously generated:        Now generated:
  ----------------       ---------------------        --------------
  #pragma pack(1)        typedef                      typedef
  typedef struct {       #pragma pack(1)              #pragma pack(1)
  } S;                   struct {                     struct {
                         }                            } S;
                         #pragma pack()               #pragma pack()
                         S;

7/17/05  GNU C++ compatibility: f().field as lvalue

The emulation for g++'s treatment of a field selected from a class
rvalue as itself an lvalue has been improved.  The selection is
now considered an lvalue only in contexts that require an lvalue,
not ones (like overload resolution) that can accept either
an lvalue or an rvalue.

  struct A {
    int i;
  } a;
  A f() { return a; }
  extern "C" int printf(const char *, ...);
  void fff(int &) { printf("int &\n"); }
  void fff(const int &) { printf("const int &\n"); }
  int main() {
    int *p = &f().i;  // Still accepted in g++ mode
    fff(f().i);       // Prints "const int &" now in g++ mode
  }

7/15/05  GNU C compatibility: asm output operands of type void

In GNU C mode, the front end now accepts asm output operands of type void
(such operands must still be lvalues).  For example:

  void f(void *p) {
    asm("ins %0": "=X"(*p));  // Now accepted in GNU C mode.
  }

Such constructs remain invalid in GNU C++ mode.

7/15/05  Microsoft compatibility: __if_exists entries in the IL

Representing __if_exists (and __if_not_exists) entries in the IL is
problematic because, although the Microsoft documentation describes the
contents of an __if_exists block as a statement, the Microsoft compiler
actually accepts any fragment of a statement or declaration in the block
(as does our front end in Microsoft mode).  We have implemented a
mechanism that can represent __if_exists blocks that appear in class
definitions, and which surround complete declarations of the class.
This mechanism is controlled by the GENERATE_MICROSOFT_IF_EXISTS_ENTRIES
configuration macro, which is enabled by default when the front end is
configured to generate source sequence entries, include prototype
instantiations in the IL, and accept Microsoft extensions.

When an __if_exists appears in a valid location in a class definition, an
IL entry (an_ms_if_exists) and source sequence entry are created for the
start and end of the block (IL CHANGE).  __if_exists blocks in other scopes
are not represented in the IL (but are still included in the textual
representation of templates).  If an __if_exists appears in an invalid
context in a class definition, an error is issued.

IL entries are only created for __if_exists blocks that appear in
the prototype instantiation of class templates and classes nested
within class templates.  In non-template contexts, the __if_exists
is simply evaluated when it is encountered.

7/15/05  Microsoft compatibility: POD_CLASS().field is not an lvalue

The 3/29/05 change to make POD_func().field be considered an lvalue
in Microsoft mode went a bit too far.  A field selection off a
"constructor call," as in POD_CLASS().field, should not be considered
an lvalue.  Now fixed.

7/15/05  GNU compatibility: Symbolic asm operands

In GNU modes, the front end now accepts GNU symbolic asm operands.  For
example:

  float f(float a) {
    register float r;
    asm("fsinx %[Rads], %[Res]": [Res]"=f"(r): [Rads]"f"(a));
    return r;
  }

In addition to recording the symbolic names in the IL, the front end also
checks that references to such symbolic names in the asm instruction do
resolve to actual operands.  For example:

  asm("mov %[S], %[D]": "=X"(d): "X"(s));  // Error: No operands named
                                           // [S] or [D].

Finally, "symbolic matching constraints" are translated into positional
matching constraints.  For example:

  asm("ins %[A], %[B]": : [A]"X"(1), [B]"[A]"(2));
    // [B] operands refers to constraints of [A] (i.e., position zero).

is equivalent to:

  asm("ins %[A], %[B]": : [A]"X"(1), [B]"0"(2));

"Matching constraints" (symbolic or not) must still refer to one of the first
ten operands.

7/13/05  asm functions involving large macro expansions

In certain cases where the body of an asm function involves a large macro
expansion, the result was unpredictable behavior, including aborts and
segmentation faults.  Now fixed.

7/13/05  Lowering of designator initializer of union member

The lowering of designated initializers had a bug when the first
member of a union is partially initialized twice.  The initialization
from the first designator was lost.  Now fixed.

  struct A {
    union {
      struct {
        int i;
        int j;
      } s;
    } u;
  };
  struct A s = {.u.s.i = 1, .u.s.j = 2};  // Init of "i" was lost

7/12/05  Configuration of DOES_NOT_RETURN for Microsoft compilers

The macro DOES_NOT_RETURN (used in the front end's source to indicate functions
that never return) is now automatically configured when the source is compiled
with a Microsoft C/C++ compiler.

7/12/05  Microsoft compatibility: Effect of dllimport on template base class

In Microsoft mode, when a derived class marked with the dllimport specifier
has a base class instantiated from a template, that base class also acquires
the dllimport attribute (see Changes entry of 3/1/05).  Now, the front end
also disables the instantiation of the members of such a base class (see
also the Changes entry of 2/13/04).  For example:

  template<typename T> struct B { void f(); };
  template<typename T> void B<T>::f() {}
  struct __declspec(dllimport) D: B<int> {};  // B<int> is now dllimport.
  void g(D d) {
    d.f();  // Does not cause the instantiation of B<int>::f().
  }

7/12/05  Strict mode description in diagnostics

Diagnostics that previously included the phrase "strict ANSI mode" have been
reworded to use just "strict mode" to reflect the broader scope of standards
that are involved.

7/11/05  Missing diagnostic on template static data member with no initializer

No diagnostic was issued if a const template static data member was defined
without an explicit initializer.  Now fixed.

  template <class T> struct A {
    static const int i;
  };
  template <class T> const int A<T>::i;
  template struct A<int>;

7/11/05  Strict ANSI C++ mode and --ignore_std

The front end now diagnoses as a command-line error the combination of strict
ANSI C++ mode and the --ignore_std option to request that namespace std be
treated as an alias for the global namespace (the latter option is meant to
be used to emulate older GNU C++ compilers).  Previously, this combination
was inadvertently accepted, but could lead to somewhat surprising errors.

7/11/05  Microsoft compatibility: Implicit int return type and type names

Prior to version 3.5, the front end accepted code such as the following (with
T a type name) in Microsoft bugs mode:

  struct S { T(); };  // Sometimes treated as a member with name "T" and
                      // implicit int return type.

Version 3.5 disabled this behavior when microsoft_version >= 1310 because it
seemed that MSVC++ 7.1 had fixed the associated bug.  However, upon closer
examination of the MSVC++ 7.1 behavior, it appears it still accepts the code
above when T is a class or enum type, but not when T is another type (e.g.,
"int" or a pointer or array type).  When microsoft_version >= 1310 and when T
is a class or enum type, the front end now accepts the construct above again.
(See also Changes entries of 7/28/04 and 7/12/99.)

7/8/05   Diagnostic on member function redeclaration

The diagnostic for invalid member function redeclarations has been reworded to
include position information for the original declaration.  For example:

  struct S {
    void f(int);
    void f(int);  // Invalid.  Diagnostic now includes position information
  };              // for the first declaration.

7/7/05   Microsoft compatibility: -D and -U command-line options

Traditionally, the command-line option -U takes precedence over the -D option.
For example, "-DF=1 -UF -DF=2" is normally equivalent to "-UF".  Version 3.5
of the front end changed this behavior in all GNU modes: In those modes, the
options are handled in the order given (see Changes entry of 4/18/05).  It
appears that recent Microsoft compilers also handle the options in the order
given: We therefore emulate that behavior in Microsoft mode when
microsoft_version >= 1300.

7/7/05   Extended position information for unnamed bit fields

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the front end now records extended
position information for unnamed bit fields.  For example:

  struct S {
    int i: 1;
    int  : 0;  /* Previously, the "a_field" entry for this unnamed field did
                  not point to extended position information.  Now it will. */
    int j: 1;
  };

7/7/05   Microsoft compatibility: properties using virtual functions

Certain uses of properties in which the get and/or put functions are virtual
resulted in a segmentation violation in the front end.  This problem was
introduced in version 3.6 (see Changes entries of 2/13/05) and is now fixed.

  struct B {
    virtual int get_c();
    virtual void put_c(int);
    __declspec(property(get=get_c, put=put_c)) int c;
  }

  void f(B* p) {
    p->c += 5;
  }

7/7/05   Pragma text for preprocessing immediate pragmas

Version 3.6 introduced a change in the handling of preprocessing immediate
pragmas.  The change allows such pragmas to be passed in the IL, including
a string representation of the pragma.  This change could cause problems
if the pragma included a processing function to be called when the
pragma was encountered.  Before the change, the processing function could
scan the tokens of the pragma.  After the change, the tokens had already
been scanned when the processing function was called.  An additional
change has been made so that that the pragma text string is only created
if the pragma has its automatically_include_in_il flag set (this flag was
always FALSE before the earlier change was made).  If this flag is not set,
the tokens are not scanned and are available to the processing function.

7/6/05   GNU C++ compatibility: Return types of virtual function overriders

In GNU C++ mode, the front end now accepts a virtual function overrider whose
return type is a pointer to a nonclass type T that is identical to the return
type of the overridden function except for type T having fewer type
qualifiers than its counterpart in the overridden function.  A warning is
issued in such cases.  For example:

  struct B {
    virtual int const* f();
  };
  struct D: B {
    virtual int* f();  // Now accepted with a warning in GNU C++ mode (and
  };                   // overrides B::f).

7/6/05   Spurious printf/scanf format warning in GNU C mode

In GNU C mode, applying the "format" attribute to a nonprototyped function
declaration resulted in a spurious warning.  For example:

  int myprintf() __attribute__((format(printf, 1, 2)));
  int main() {
    myprintf("%s\n","Hello");  // Previously triggered a spurious error in
  }                            // GNU C mode.

This has been fixed by silently ignoring the "format" attribute on
nonprototyped function declarations.

7/6/05   GNU compatibility: Attribute "weak" and internal linkage

In GNU modes, the front end previously silently applied the "weak" attribute
to variables and routines with internal linkage.  Now an error is issued in
such cases.  For example:

  static __attribute__((weak)) int g;  // Previously accepted.  Now an error.

7/6/05   DECL_MODIFIERS_IN_USE

The configuration macro DECL_MODIFIERS_IN_USE (see Changes entry of 12/16/98)
enables a framework for nonstandard declaration modifiers.  This framework is
used in particular to implement certain Microsoft and Sun extensions, but it
is also meant to be useful for customer-specific extensions.  In some cases,
however, functions like update_routine_decl_modifiers were only called in
configurations with support for Microsoft or Sun extensions.  Now, the routines
are called in all configurations that have DECL_MODIFIERS_IN_USE set to TRUE.
In addition, DECL_MODIFIERS_IN_USE is now TRUE by default when
THREAD_LOCAL_STORAGE_SPECIFIER_ALLOWED is configured to TRUE.

7/6/05   Microsoft compatibility: missing definition for array of
         uninstantiated element type

The Microsoft compiler accepts a definition of an object with an incomplete
array type and treats it as an extern declaration.  A problem in the
emulation of this feature could result in a link error (in Microsoft mode) if
a program contains a definition of an array with an element type that is a
class template that has not previously been instantiated.  Now fixed.

  template <class T> struct A { };
  A<int> a[10];
  int main(void) {
    return a != 0;
  }

7/5/05   Abort when applying dllexport to template class with member template

In Microsoft mode with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE, the front
end sometimes aborted in instantiate_template_function (templates.c) when
handling the instantiation of a template base class that was marked with the
Microsoft "dllexport" specifier through a derived class.  For the problem to
occur, the base class template needed to have a member function template.
For example:

  template<typename T> struct B {      
    template<typename> void f() {}
  };
  struct __declspec(dllexport) D: B<int> {};
    // An abort was triggered while attempting to instantiate B<int>::f.

This is now fixed.

6/30/05  Reference-to-reference constructs

The C++ standards committee has resolved core issue 106 to allow reference-
to-reference constructs in some cases.  Specifically, a typedef or template
parameter that is substituted by a reference type can have a reference
declarator applied to it.  For example:

  typedef int &RI;
  typedef RI const &RCI;  // Same as "int const&".  (Previously invalid.)

If T is a is a typedef or template parameter standing for a reference type
"X cv1&" (where cv1 represents type qualifiers), then the construct "T cv2&"
(with cv2 some other type qualifiers) results in the same type as "X cv&"
where cv is the union of the cv1 and cv2 qualifiers.

6/29/05  Control over recognition of trigraphs

Recognition of trigraphs may now be disabled.  The default mode behavior is
specified by the DEFAULT_TRIGRAPHS_ALLOWED macro (which defaults to TRUE).
Trigraphs are enabled by default in strict mode, Microsoft mode, and Sun mode.
They are disabled by default in GNU modes.  The default can be explicitly
overridden using the --[no_]trigraphs command-line options.  When trigraphs
are disabled, a warning is issued on the first attempted use of a trigraph.

6/29/05  Thread local storage option description

The 12/13/04 entry of the Changes files (i.e., this file) shipped with
version 3.6 of the front end erroneously documented the command-line option
to enable the __thread specifier as being "--thread_local_specifier".
Instead, it should have been "--thread_local_storage".  The entry is now
fixed.  (The option was correctly spelled in the "External Interface"
chapter of the C++ Front End Internal Documentation.)

6/28/05  Internal error in pop_primary_include_search_dir on preinclude

When STACK_REFERENCED_INCLUDE_DIRECTORIES is TRUE, but when not using
Microsoft mode, an internal error in pop_primary_include_search_dir could
occur when doing a preinclude in a compilation in which the primary
source file is not in the current directory.  Now fixed.

6/27/05  Position and context tracking in macro invocations

Two new configuration options have been added to provide additional
information about macro invocations and expanded text.  When
FULLY_RESOLVED_MACRO_POSITIONS is TRUE, an extra sequence number and column
pair is available in a_source_position; for source positions associated with
text in macro expansions, these fields designate the original position (in a
macro definition or top-level macro argument) at which the text appeared.
Setting MACRO_INVOCATION_TREE_IN_IL to TRUE records every macro invocation
in a translation unit in a flattened tree in the file-scope IL (see
il_header.root_macro_invocation_record_block and related declarations).
MACRO_INVOCATION_TREE_IN_IL also extends a_source_position to contain an
index into this tree, identifying the particular invocation in whose
expansion the position appears and allowing a stack trace of the macro
invocations that led to that expansion.

This extra information can be reflected in diagnostic output concerning text
in macro expansions.  A new command-line option,
--[no_]macro_positions_in_diagnostics, controls whether the original source
position is displayed in addition to the current source display of the
beginning of the top-level macro invocation, along with the macro invocation
stack for the referenced position (if the front end is configured with
MACRO_INVOCATION_TREE_IN_IL as TRUE).

6/27/05  Precompiled headers: command-line event comparisons broken by 3.6

Version 3.6 introduced a problem that caused a precompiled header file to
be used even though the command-line options did not match the compilation
that produced the PCH file.  This could result in internal errors, aborts,
or other incorrect behavior.  Now fixed.

6/25/05  C++-generating back end: declarations introduced in enumeration
         members of prototype instantiations

With PROTOTYPE_INSTANTIATIONS_IN_IL and --parse_templates, a class or struct
first declared in the enumerator list of an enumeration member of a class
template was generated without the necessary class or struct keyword.  For
example:

  template<int> struct X { X(...); };
  template <int N> struct Z {
    enum { E=sizeof(X<N>((struct S *)(0))) };
  };

The initializer for E formerly dropped the "struct" keyword.  Now fixed.

6/24/05  Incorrect symbol variant used in
         push_instantiation_scope_for_templ_param_rescan

In some cases, push_instantiation_scope_for_templ_param_rescan referenced
the incorrect variant of a symbol.  Although this has been a potential
problem for a long time, an actual problem was not observed until the
additional source position information for macros was added.  The test
case below referenced the incorrect symbol variant, and could result in
an abort or internal error in certain configurations.  Now fixed.

  template <typename T, T I> struct A {};
  struct B {
    static const int i = 5;
    template <typename T, T I> static void f( A<T, I> );
    template <typename T> static void f( A<T, B::i> );
  };
  A<int, B::i> a1;
  A<int const&, B::i> a2;
  int main() {
    B::f( a1 );
    B::f( a2 );
  }

6/23/05  LONG_LONG_ALLOWED and GNU_EXTENSIONS_ALLOWED

The front end configuration file targ_def.h has been modified so that
LONG_LONG_ALLOWED is set to TRUE by default when GNU_EXTENSIONS_ALLOWED is
TRUE.

6/23/05  Incorrect conditional compilation in cmd_line.c

Version 3.6 introduced a problem in cmd_line.c that caused many of the
global variables initialized by cmd_line.c to be set incorrectly if
EXPORT_ENABLING_POSSIBLE was FALSE.  Now fixed.

6/23/05  Microsoft compatibility: VC 6 using-directive bug emulation

In Microsoft bugs mode, when microsoft_version is <= 1200, we emulate
a Microsoft using-directive bug that makes certain names visible in the
file scope when they should not be.  A flaw in this emulation caused
spurious ambiguities in some cases.  Now fixed.

  namespace N {}
  namespace O {}
  namespace N {
    using namespace O;
  }
  // namespace N {}  // VC 6 issues an error if this line is uncommented
  template <class C> void f(C, C) {}
  namespace O {
    template <class C> void f(C, C) {}
  }
  int main() {
    f(1, 2);  // spurious ambiguity on this call
    return 0;
 }

6/23/05  Microsoft compatibility: DLL specifiers in explicit instantiations

The Changes entry of 3/1/05 describes how DLL specifiers on an explicit class
template instantiation are propagated to the members of that instantiation.
However, Microsoft compilers do not propagate the dllimport attribute to
static data members of the instantiated class, nor (in most cases) to
compiler-generated data structures (e.g., virtual function tables) associated
with that class.  (Virtual function tables do acquire the dllimport attribute
when the instantiated class contains an explicit specialization of a
constructor or destructor.)  For example:

  template<typename T> struct S {
    static void f();
    static int i;
  };
  template<class T> int S<T>::i = 3;
  int main() {
    // Trigger instantiations through use:
    S<int> s;
    s.f();
    return s.i;
  }
  template struct __declspec(dllimport) S<int>;
    // S<int>::f() acquires the dllimport attribute, but S<int>::i does not.

We now emulate that behavior.

6/22/05  Internal error popping translation unit stack when using PCH file

An internal error could occur in pop_translation_unit_stack when using a
precompiled header file.  Now fixed.

6/22/05  Output of file names containing multibyte characters

When a file name is output in a diagnostic message, nonprintable
characters are no longer output using escape sequences.  This is done
so that file names containing multibyte characters will be output as
expected by users.  File names that are emitted in #line directives in
preprocessed output or in generated C or C++ files are still emitted
with escape sequences.  Note that version 3.5 changed the behavior of
extended ASCII characters (those >= 128) in file names.  See the 4/20/05
Changes entry for more information.  That change caused characters >= 128
to be emitted without escapes in both error messages and #line directives.
This change restores the escapes when such file names are emitted in #line
directives.

6/22/05  End position of stmk_decl statements

In configurations with both GENERATE_SOURCE_SEQUENCE_LISTS and
EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE, the front end failed to record
the end position of a declaration associated with an stmk_decl statement.
For example:

  void f() {
    int a, b, c;  // Declaration may have associated stmk_decl entry.
  }               // Previously, no end position was recorded in the entry.
                  // Now the end position is the position of the semicolon.

This is now fixed: The position of the semicolon terminating such declarations
is recorded in the end_position field of the stmk_decl statement.

6/21/05  GNU C++ compatibility: Block-extern declaration conflicts

GNU C++ compilers accept block-extern declarations of routines (or variables)
whose names conflict with previously-declared namespace variables (or
routines).  The behavior is now emulated by the EDG front end (with a warning)
when the routine has C++ name linkage.  For example:

  int x;
  void f() {
    void x(int);  // Accepted in GNU C++ mode.
  }

6/20/05  Minor issues with front end reinitialization changes

The changes made to allow the front end to be restarted introduced several
problems:

- The front end did not build properly when USE_MMAP_FOR_MEMORY_REGIONS is
  FALSE, or when DEBUG is FALSE.
- There were a few cases where file variables were not cleared after a file
  had been closed.
- lexical_cleanup could fail if a catastrophic error occurred before the
  first input file was opened.

These problems have been fixed.

6/16/05  GNU compatibility: "visibility" attribute

In GNU modes, the front end now accepts "default" as an argument for the
ELF visibility attribute (see also the Changes entry of 6/27/02).
Furthermore, in GNU C++ mode with gnu_version >= 40000, the front end now
accepts the visibility attribute on class type definitions.  Such an attribute
determines the ELF visibility of the class' member functions and static data
members.  For example:

  struct __attribute__((visibility("hidden"))) S {
    void f();
    void g() __attribute__((visibility("default")));
  };
  void S::f() {
    // Routine will have "hidden" visibility in ELF object file.
  }
  void S::g() {
    // Routine will have "default" visibility in ELF object file.
  }

6/16/05   Microsoft compatibility: Cast string literals in initializers

In Microsoft mode, the front end now treats string literals cast to a pointer
to the underlying character type as plain string literals when they appear in
brace-enclosed initializers.  For example:

  char s[] = { (char*)"msg" };  // Normally an error, but now accepted in
                                // Microsoft modes.

6/16/05  GNU C++ compatibility: qualified name in member template declaration

g++ allows a qualified name to be used in the initial declaration of a class
member.  The front end accepts such declarations in g++ mode, but an error
was issued later if the member template was referenced.  Now fixed.

  struct A {
    template <class T> void A::f(T t){}
    void A::g(){}
  };
  int main() {
    A a;
    a.g();  // accepted
    a.f(1);  // error during instantiation
  }

6/15/05  Optimization of constructor-call code in Cfront-like ABI

The code generated for constructor calls has been improved in
some cases in the Cfront-like ABI.  In particular, for classes
that have bitwise copy construction semantics, an indirection
through the address returned by the constructor is used
in place of a comma expression with a second operand that
names the initialized temporary.

6/15/05  GNU C++ compatibility: New expressions

A change made previously to emulate the behavior of early GNU C++ compilers
when parsing new expressions (see Changes entry of 11/5/02) turned out not
to model the GNU behavior in all cases.  Furthermore, some cases could trigger
an internal error.  For example:

  void f(int n) {
    char **p = new (char*)[n];  // Previously triggered an error, even in GNU
                                // C++ mode.
    new (int[n])[2];  // Previously triggered an internal error in GNU C++
  }                   // mode.

This is now fixed.  (Note that such nonstandard new expressions are only
accepted when gnu_version < 30400.)

6/14/05  Typo in header file declaration

The prototype declaration of primary_float_type (in trans_corresp.h)
incorrectly declared its parameter to be of type an_integer_kind.  This
has been corrected to a_float_kind.  (The two types are typedefs for the
same underlying integer type.  So this correction has no effect on the
front end's behavior.)

6/10/05  Microsoft compatibility: dllimport and inline functions

In Microsoft mode, when an inline function was first declared with dllimport,
and later redeclared without a DLL attribute, the front end previously ignored
the dllimport attribute (with a warning).  For example:

  __declspec(dllimport) void f();
  inline void f() {}  // Previously, the dllimport was dropped.  Now it is
                      // retained.

Now, the dllimport attribute is retained in such cases, which matches the
behavior of the Microsoft compilers.

6/10/05  Folding of floating-point comparisons involving NaN

Floating-point comparisons of constants involving a NaN are no longer
folded to a constant true or false at compile time if they appear in
a nonconstant context.  They are left to be done at runtime, so that
the floating-point exception status flags can be set appropriately.

6/10/05  Qualified class types

A relatively recent decision by the C++ standards committee (the resolution
of core issue 298) makes class types qualified with const and/or volatile
qualifiers more like their unqualified counterparts.  The implementation of
this resolution required a change in the front end: Base classes can now be
specified using typedefs for const and/or volatile qualifiers (the qualifiers
are ignored).

For example:

  typedef struct { int i; } const B;
  struct D: B {} d;  // Now okay.

6/10/05  Spurious error on mixed dependent/nondependent destructor reference

When parsing nonclass templates, a spurious error was issued on a destructor
reference in which the qualifier portion was specified using a nondependent
name but the destructor name itself was dependent.  Now fixed.

  struct A {
    ~A();
  };
  template <class T> void destroy(T* p) {
    p->A::~T();
  }

6/10/05  dynamic_cast of null pointer value done at compile time

A dynamic_cast of a constant null pointer value is now done at compile
time rather than as a runtime cast.  The result is the same, but
the generated code is more efficient.

6/9/05   GNU compatibility: handling of missing include file

Version 3.6 changed the handling of a missing include file when doing
preprocessing only.  The error for such cases was changed to a normal
error from a catastrophic error.  The GNU compiler continues processing
when generating preprocessed output, but terminates processing when doing
other kinds of preprocessing (e.g., creating makefile dependency information).
In GNU mode, we now continue processing only when generating preprocessed
output.  The behavior in non-GNU mode has not changed.

-------------------------------------------------------------------------------
Version 3.6, June 7, 2005

6/6/05   IL version number updated to 3.6

6/4/05   Source sequence entries suppressed when C lowering is done

Source sequence entries are now suppressed in C modes in which IL lowering
is done (e.g., C99, gcc).  This is appropriate, because transformations
done in lowering may eliminate and reorder IL in a way that invalidates
the source sequence entries, and it matches what is done in C++ mode.
Note, however, that until a change done as part of the implementation
of VLAs in C++ mode this was only a theoretical problem; we don't
know of any cases where bad IL was produced because the source
sequence entries were present.

6/2/05   C++-generating back end: __builtin_va_start in template strings

When GCC_BUILTIN_VARARGS is TRUE, alternative spellings of the va_start,
etc. tokens are provided (e.g., __builtin_va_start).  When the front end
creates template strings (for use by the C++-generating back end) the
alternative spellings were not used, which could cause problems if the
generated C++ code was compiled with a GNU compiler.  In GNU mode when
GCC_BUILTIN_VARARGS is TRUE, the alternative spellings (__builtin_va_start,
__builtin_va_arg, __builtin_va_copy, __builtin_va_end) are now used when
creating template strings.

  #include <stdarg.h>
  template <class T> inline void f(T i, ...) {
    va_list v, v2;
    __builtin_va_start(v, i);
    __builtin_va_copy(v2, v);
    int j = __builtin_va_arg(v, int);
    __builtin_va_end(v);
  }

6/1/05   Abort in lowering of VLAs appearing in GNU C typeof constructs

In GNU C mode, applying "typeof" to a variably modified type could lead to
an abort during lowering of the variable-length array (VLA) types appearing
in the "typeof" construct.  For example:

  void f(int n) {
    typeof(float[n][n]) x;  // Previously triggered an abort in GNU C mode
  }                         // if VLAs were lowered.

This is now fixed.

6/1/05   GNU C++ compatibility: disambiguation problem with compound literals

The disambiguation routines did not handle compound literals (which
are enabled in g++ mode) properly, resulting in spurious errors.  Now fixed.

  void f() {
    int *i = (int(*)){0};
  }

6/1/05   Abort scanning asm functions

An abort could occur (in copy_from_source_to_asm_func_buffer) in certain
conditions when an asm function followed a declaration that required
disambiguation to determine whether the entity declared is a function
or object.  Now fixed.

  void f(int (*p)[10], int) {}
  asm void g() { int x[10][10]; }

6/1/05   Continue preprocessing after missing include file

In modes in which the compiler is doing preprocessing only, the diagnostic
issued for a missing include file has been reduced from a catastrophic
error to a discretionary error.  This can be used, for example, to produce
makefile dependency information that is as complete as possible even in
the presence of missing include files.

5/31/05  GNU C++ mode: abort on incorrect non-top-level nonconstant array
         bound in "new"

A case like the following, which uses the g++ "feature" that allows
an array declarator after a parenthesized type in a "new", aborted in
expr.c.  The front end now correctly diagnoses the incorrect
nonconstant bound after the first level.

  int main() {
    int n = 10;
    new ( int [n] ) [ n ] ; 
  }

5/31/05  GNU mode: abort on folding pointer addition with GNU zero-length
         array

An assertion failure in do_padd in folding.c ("size is zero") occurred
on an attempt to fold a pointer addition involving an array with
a zero bound in GNU mode.  Now fixed.

  int main() {
    typedef int T1[0];
    int a[(((T1 *)0)[1], 1)];
  }

5/26/05  Abort when creating fundamental types after merging secondary
         translation units

When simultaneously processing multiple translation units, attempts to create
new IL with fundamental types (e.g., calls to float_type(...)) could trigger
an internal error in f_set_trans_unit_corresp.  Such aborts only occurred
when IL_SHOULD_BE_WRITTEN_TO_FILE was TRUE and when the fundamental type
involved had been used only in secondary translation units.  For example:

  // Primary translation unit:
  int main() {}

  // Secondary translation unit:
  bool x = 3.0;  // "bool" used in secondary translation unit, but not in
                 // primary translation unit.  A call to "bool_type()" after
                 // the translation units were merged could previously trigger
                 // an internal error.

This is now fixed.

5/26/05  Sun compatibility: #pragma pack(0)

In Sun mode (a C++ mode), the front end now accepts a zero argument for the
pack pragma.  As is already the case in GNU modes, "#pragma pack(0)" restores
the default packing alignment for subsequent declarations.  For example
(assuming a common 32-bit layout model):

  #pragma pack(1)               // Pack fields maximally.
  struct S { int i; char c; };  // sizeof(S) == 5.
  #pragma pack(0)               // Restore default field alignments.
  struct T { int i; char c; };  // sizeof(T) == 8.

5/26/05  Abort on pointer difference folding in GNU C++ mode

In GNU C++ mode, the front end sometimes aborted with an internal error in
"do_pdiff" when attempting to constant-fold a difference between two pointers
to zero-length arrays.  For example:

  typedef int (*P)[0];
  int d = (P)0 - (P)0;  // Previously an internal error in GNU C++ mode.

This is now fixed.  An "out of range" warning is issued because of the
division by zero implied by such pointer differences.

5/20/05  Invalid uses of throw specifications

The C++ standards committee has clarified (through its decision on core
issue 294) that exception specifications can only appear in a limited
number of declarative contexts.  In particular, casts to types with
exception specifications are invalid, but the front end previously
accepted such casts in all all modes.  For example:

  void f() {
    (void (*)() throw(int))0;  // Previously accepted in all modes.
  }                            // Now an error in strict ANSI mode.

In strict ANSI mode, the invalid constructs are now diagnosed with a
discretionary error.  In other modes, the previous behavior is retained:
If exception handling is enabled, no diagnostic is issued, and if exception
handling is disabled, a warning is issued (and the exception specification
is ignored).

5/18/05  Internal error on pseudo-destructor of the form "x.::~int"

Because the front end failed to issue a diagnostic, an internal error
would occur (in lower_expr) on a pseudo-destructor reference that used
a global qualifier in conjunction with a type name specified using
a type keyword.  Note that the standard does not permit type keywords
to be used in pseudo-destructors at all.

  void f() {
    int x;
    x.::~int(); 
  }

5/17/05  Build errors when LOWER_COMPLEX is FALSE and LOWER_FIXED_POINT is TRUE

In some configurations with C99 lowering enabled, the front end did not build
correctly due to link errors.  This was particularly the case when
LOWER_COMPLEX is FALSE and LOWER_FIXED_POINT is TRUE.  Now fixed.

5/12/05  Microsoft and GNU C++ compatibility: partial specialization declared
         too late

The standard prohibits declaring a partial specialization after an
instantiation of a class template has been done that would have used the
partial specialization if it had been declared earlier.  Neither the Microsoft
nor g++ compilers diagnose this infraction, so we now reduce the severity
of such diagnostics to a warning in Microsoft and g++ modes.

  template <class T> class X { };
  X<int*> xi;
  template <class T> class X<T*> { };

5/12/05  C++-generating back end: functional-notation casts

The change to generate casts using functional notation (see the entry of
11/9/04) resulted in spurious errors on the generated code from various
compilers (see entries of 11/18/04 and 4/7/05 for some examples).  As a
result, all three of these changes have now been reversed, and the
C++-generating back end will now again generate C-style casts rather than
functional-notation casts in all but two circumstances.  The first addresses
the original problem described in the 11/9/04 entry: when a cast is used as
the left side of an overloaded operator that is implemented as a class
member function and the call uses operator notation rather than an explicit
function call, a functional cast will be used if sun_is_generated_code_target
is TRUE.  The second case is that described in the Changes entry of 2/26/05,
which is not affected by this change.

5/10/05  Abort on GNU min/max operator with template-dependent constant
         operands

The front end aborted in conv_lvalue_expr_to_rvalue in lower_expr.c
while processing a use of the GNU min or max operators ("<?" or ">?")
operating on template-dependent constant operands.  Now fixed.

  template <class T> struct A {
    static const int i = T::a;
    static const int j = T::b;
    static const int k = i <? j;  // Formerly provoked an abort
  };

5/9/05   Microsoft compatibility: abort when microsoft_version is <= 1200

In Microsoft bugs mode, the Microsoft compiler will sometimes find a
class template that should be hidden by a class member.   A problem
with the way in which this emulation was done could cause an abort (in
check_for_microsoft_hidden_template_bug) when microsoft_version is <= 1200.
Now fixed.

  typedef struct A { int  m; } A;
  template <class T1> struct B {
    static void f() { new T1; }
  };
  template <class T1> struct C {
    static void f() { T1::f(); }
  };
  template <class T> struct D {
    virtual int foo(A *pA) { if (pA->m < 0 ) return 0; return 1;}
  };
  struct E : public D<int> { typedef C< B< E> > C; };
  namespace N1 {
    namespace N2 { class m {}; }
  }
  namespace N1 { using namespace N2; }
  int main() {
    E::C::f();
  } 

5/9/05   Variable-length arrays in C++ mode

Variable-length arrays (VLAs) are now permitted in C++ mode in some
cases.  They are enabled in GNU C++ mode, and the --vla option can
be used to enable them in other modes.

IL lowering and the runtime have been updated to handle C++ VLAs,
including construction/destruction/deallocation of VLAs of class
types and proper cleanup on exception unwinding.  In C++ mode,
VLA cleanup is handled through the object lifetime mechanism used
to schedule destructor calls.  In C mode, it remains handled by
insertion of VLA-deallocation code by the front end proper (there
are no object lifetime entries in C).

See the Changes entry of 4/29/05 for information on an IL change
made to support this feature.

5/6/05   Microsoft compatibility: __identifier operator

In Microsoft mode, the __identifier operator may be used to allow a C++
keyword to be used as an identifier.

  int __identifier(int) = 1;

5/5/05   Microsoft compatibility: Spurious error on imported function template

In Microsoft mode, the front end previously issued a spurious error when
partially instantiating a "dllimported" function template.  For example:

  template<typename> __declspec(dllimport) void f();
  int main() {
    f<char>();  // Triggered an error.
  }

This is now fixed: An error is only issued if an actual definition is
produced by the instantiation (i.e., if the function template has a body).

5/5/05   C++-generating back end: unneeded parentheses in function arguments

The C++-generating back end formerly enclosed many function arguments in
unnecessary parentheses.  In some cases, versions of g++ prior to 3.4 failed
to parse the generated code because of the extra parentheses.  The
C++-generating back end now parenthesizes function arguments only if they
contain a comma operator that would otherwise be taken as an argument
separator.  For example:

  f(i+3);        // Formerly generated as "f((i+3))", now "f(i+3)"
  f((g(),5));    // Still generated as "f((g(),5))"

5/2/05   printf/scanf format checking for wchar_t arguments in C++

The checking of printf/scanf formatting specifiers was slightly
incorrect with regard to wchar_t arguments in C++ mode.  The
argument was checked against the integral type that is the
underlying type of wchar_t rather than against wchar_t itself.
As a consequence, examples like the following drew a spurious
remark (not usually visible because remarks are not enabled by
default).  Now fixed.

  #pragma __scanf_args
  extern "C" int sscanf(char *, const char *, ...);
  int main() {
     wchar_t buffw[64];
     char buffer[] = "abcdef hi";
     sscanf(buffer, "%l[abcdef]", buffw);  // Formerly got spurious remark
  }

4/29/05  Deallocation of variable-length arrays (IL CHANGE)

The IL representation of variable-length array (VLA) deallocation has changed.
Instead of stmk_vla_dealloc statement entries, we now generate stmk_expr
entries pointing to (newly introduced) enk_vla_dealloc expression nodes.
The global variable vla_dealloc_statements_in_il has been replaced by the
global variable vla_deallocations_in_il.  The corresponding macro
VLA_DEALLOC_STATEMENTS_IN_IL is replaced by VLA_DEALLOCATIONS_IN_IL.

4/26/05  Microsoft compatibility: special lookup templates vs. injected
         class names

In Microsoft mode, if a base class of a class template contained an injected
class name with the same name as a class template from an enclosing scope,
a lookup of the name followed by a "<" should have found the template from
the enclosing scope, but did not, resulting in a spurious error.  Now fixed.

  struct A { struct C {}; };
  template <class T> struct C : public A::C {
    typedef C<T> my_C;  // spurious error: "C" is not a template
  };
  C<int> x;

4/26/05  Microsoft compatibility: special lookup of template names

In Microsoft mode, we emulate a Microsoft bug in which a global template
is found instead of a base class member.  The 7.1 compiler partially
fixes this bug when the base class member is a function or a function
template.  We now implement a revised version of the emulation when
microsoft_version is >= 1310.

  template <class T> struct x {};
  class A {
    void x(int);
    template <class X> void x(X);
  };
  class B : public A {
    typedef x<int> xi;  // accepted by Microsoft prior to 7.1
  };

4/26/05  Abort in IL lowering on function try block in destructor, no
         destructible members

IL lowering aborted in lower_eh.c in lower_try_block while processing
a function try-block in a destructor when the class has no
destructible members.  Now fixed.

  struct S {
    ~S() try {} catch(int) {}
  };

4/26/05  Positional printf/scanf like format specifiers

When a call to a printf/scanf-like function involves a constant format string,
the front end checks the types of the arguments against the format specifiers.
Many C library implementations support an extension to format specifiers that
allows values to be formatted out of order.  For example:

  #include <stdio.h>
  int main() {
    int i = 5;
    printf("%1$*2$s\n", "X", i);  // Value to be formatted is in position "1";
  }                               // variable field width is in position "2".

The front end now recognizes and checks such positional specifiers when the
global variable check_printf_scanf_positional_args is TRUE.  Only type checking
is done in such cases (in particular, the front end will not check that every
argument position has been used) and positions above 99 are not checked.  The
default value of check_printf_scanf_positional_args is determined by the macro
DEFAULT_CHECK_PRINTF_SCANF_POSITIONAL_ARGS.

4/22/05  C++-generating back end: unnamed enumeration types

The C++-generating back end formerly added a generated tag to all unnamed
enumeration type definitions in C mode.  This generated tag was reported to
cause compilation difficulties on HP/UX, so it has now been removed.  The
generated tag was used when a value of the enumeration type appeared in a
boolean context: in the generated code, the value being tested was compared
against the constant 0 cast to the enumeration type.  In order to avoid this
problem, and also to make the generated code closer to the source form,
compiler-generated comparisons against 0 in boolean contexts are now removed.
For example:

  Original source:   Previously generated:                Now generated:
  ----------------   ---------------------                --------------
  enum { e0 } x;     enum __T01234567 { e0 } x;           enum { e0 } x;
  if (x) {           if (x != ((enum __T01234567)0)) {    if (x) {
  }                  }                                    }

4/22/05  Source sequence entries for class templates

When recording prototype instantiations and source sequence entries in the IL,
the front end accidentally cleared the source sequence entry pointer of
a_template entries for class templates (the source sequence entry itself was
still correctly created and pointed to the template).  This is now fixed:
Given a pointer p to an IL entry of type a_template for a class template, the
associated source sequence entry can now be retrieved with
"p->source_corresp.source_sequence_entry".

4/22/05  HP PA systems and isfinite macro

On HP PA systems, the isfinite macro supplied in the system headers takes
a double argument instead of a long double.  This can cause spurious
out-of-range diagnostics to be issued on some long double values.  float_pt.c
has been modified to not use the isfinite macro on HP PA.

4/21/05  GNU C++ 3.4 compatibility: dependent lookup does not ignore
         static functions

g++ 3.4 apparently does not ignore static functions in doing the
lookup for dependent names in templates.  That is now emulated in
g++ 3.4 mode.

4/21/05  Microsoft 7.1 compatibility: "string" --> void * deprecated

MSVC++ 7.1 allows the conversion of a string literal (which has
const type) to void *.  The EDG front end also allows that.
However, that conversion is now categorized as an extension and
is therefore considered less good in overload resolution.
That resolves an ambiguity on cases like the following:

  // Unambiguously chosen by MSVC++ 7.1 and later
  void f(const void *);
  // Unambiguously chosen by MSVC++ 7.0 and earlier
  void f(void *);
  int main() {
    f("");
  }

4/21/05  IA-64 ABI: fewer unused typeinfo variables

IL lowering for the IA-64 ABI now suppresses typeinfo and typeinfo
string variables that are not referenced in a given compilation if
they are related to a class that has no key function, i.e., for
which the virtual function table is optional.  The typeinfo and
typeinfo string variables were put out in a COMDAT, so the impact
on executable size was insignificant, but this change does reduce
the size of some object files.

The Cfront-like ABI had a similar but less significant issue:
some id object variables (used to establish identity of typeinfo
variables) were put out when not referenced.  Also suppressed now.

4/20/05  No return value optimization for return of volatile variable

12.8p15 of the C++ standard says that elision of the copy on a
return can be done only if the entity being returned is
a non-volatile automatic variable.  The check for non-volatile
was not being done previously.  Now, it is.

  struct A {
    A();
    A(const A&);
    A(volatile A&);
  };
  volatile A f() {
    volatile A a;
    return a;  // No return value optimization
  }

4/20/05  Type of IL shift for bool <<= bool

The type of the shift operator in lowered code generated for a C++
shift compound assignment whose left operand is a bool was incorrect.
It should have been an integral type and instead it was bool.
Now fixed.

  bool f(bool *p, bool b) { return *p <<= b; }

4/20/05  Output of file names containing extended ASCII characters

File names in #line directives and error messages are output by
write_file_name.  Formerly, this routine would use isprint to determine
whether a character should be output normally or as an octal escape.  This
resulted in the generation of octal escapes for file name characters
containing extended ASCII characters (those characters >= 128).  isprint is
now used only for characters < 128, so that extended characters are now
output normally and not as octal escapes.  In addition, write_file_name
has been moved from il.c to host_envir.c so that it can be customized for
certain environments, if needed.

4/20/05  GNU C++ compatibility: Incomplete field types in templates

In GNU C++ mode with gnu_version < 30400, the front end accepts fields with
incomplete types while parsing templates (the types must be complete when the
template is instantiated).  When gnu_version >= 30400, incomplete field types
were not accepted in templates.  However, g++ 3.4 does accept incomplete field
types if they are parameterized.  For example:

  template<typename T> struct X {
    struct N {
      X<T> x;  // Accepted in all GNU C++ modes.  An error in strict mode.
    };
  };

This behavior is now emulated in GNU C++ modes with gnu_version >= 30400.

4/19/05  GNU C++ compatibility: dependent name lookup when gnu_version >= 30400

When the gnu_version variable was introduced, the emulation of certain
g++ dependent name features was disabled when gnu_version is >= 30400.
Some of the disabled features are actually still required in order to
correctly emulate the behavior of g++ 3.4.  These features have now been
re-enabled.

  int f(const char *);
  template <typename T> struct A {
    void f(T it) {}
  };
  template<typename T> struct B : public A<T> {
    T t;
    B() { f(t); }
  };
  struct C {};
  int main() {
    B<C> b;
  }

4/19/05  GNU C++ compatibility: Spurious error on qualified friend declaration

In some situations in GNU C++ mode, the front end sometimes issued a spurious
error on a friend function declaration with a qualified name.  For example:

  namespace A {
    void A();
    struct A {
      friend void ::A::A();  // Triggered a spurious error.
    };
  }

This is now fixed.  Furthermore, a warning was issued incorrectly suggesting
that the use of a qualified name is nonstandard in such cases.  The warning
has been corrected to instead indicate that the qualifier is ignored (a GNU
C++ behavior that can subtly change the meaning of the friend declaration;
see Changes entry of 11/2/04).

4/19/05  GNU C++ compatibility: dependent name lookup sees entities declared
         after point of reference

The emulation for dependent name lookup in templates in GNU C++ 3.4
mode has been altered so that entities declared after the point of
reference are visible (contrary to what the standard specifies).

  template <class _ForwardIterator>
  void __destroy_aux(_ForwardIterator __first) { _Destroy(&*__first); }
  template <class _Tp> void _Destroy(_Tp* __pointer) { ; }
  int main() {
    int* ip;
    __destroy_aux(ip);
  }

4/19/05  C++-generating back end: Microsoft compatibility for
         using-declarations with namespace-qualified template-ids as
         qualifiers

The Microsoft 6.0 compiler reports spurious errors on using-declarations like
the following:

  namespace N {
    template<bool B> struct S {
      enum { value = B };
    };
  }
  struct D: N::S<false> {
    using N::S<false>::value;  // error in MSVC++6.0
  };

The C++-generating back end will now use a generated typedef for qualifiers
of this kind when msvc_is_generated_code_target is TRUE and
msvc_target_version_number is 1200.

4/19/05  GNU C++ compatibility: visibility of using-directives in g++ 3.4 mode

In g++ mode, when gnu_version is >= 30400 certain using-directives that should
have been visible were ignored resulting in lookup errors.  Now fixed.

  namespace N {}
  namespace M { template <class T> class A {}; }
  namespace O {
    using namespace N;
    using namespace M;
    template <class T> struct B : public A<T> { B() : A<T>() {} };
    B<int> obj;
  }
  namespace N { using namespace O; }

4/18/05  C++-generating back end: __declspec(naked)

The change to emit Microsoft-specific declaration modifiers in explicit
instantiation directives (1/7/04) inadvertently prevented generation of the
__declspec(naked) modifier on function definitions.  Now fixed.

4/18/05  GNU compatibility: -D and -U command-line options

Traditionally, the command-line option -U takes precedence over the -D option.
For example, "-DF=1 -UF -DF=2" is normally equivalent to "-UF".  However, the
GNU preprocessor handles the options in the order given on the command line
(i.e., the previous example is equivalent to "-DF=2").  We have changed our
behavior to match that of the GNU preprocessor in GNU modes.  In other modes,
the traditional behavior is still in effect.

4/18/05  Failure to fold compile-time address arithmetic

Certain configurations failed to fold cases like the following at
compile time.  The key attributes are an address cast to an unsigned
integral type minus a value so large that the operation overflows
the an_integer_value representation.  Now fixed.

  struct foo{
     unsigned long x;
  };
  int arr[10];
  struct foo f = {
    ((unsigned long)arr) - ((unsigned long)0x80000001UL)
  };
  int main() {
    return 0;
  }

4/13/05  C++-generating back end: Microsoft compatibility for default
         arguments of member functions

In MSVC++ 6.0, a default argument of a class member function of the form

  f(const N::T<x,y>& = N::T<x,y>());

where N is the name of a namespace to which the class does not belong, could
cause spurious syntax errors.  The C++-generating back end now avoids
triggering this bug by enclosing the default argument in parentheses:

  f(const T<x,y>& = (T<x,y>()));

4/7/05   Return type of main function in C mode

In C++ and C99 modes, the front end issues an error (in strict mode) or a
warning (in other modes) when the return type of the main function is not
"int".  In C89 mode, however, no diagnostic was issued in such cases.  Now,
the C89 behavior is identical to that of C99 and C++ modes.  For example:

  void main() {}  // Now a warning or error in C89 mode.  Previously
                  // silently accepted.

4/7/05   Embedded C: spurious error on invalid fixed-point constant as pp-token

A spurious error was issued if something that looks like an invalid
fixed-point constant was used as a preprocessing token, and fixed-point
support was enabled.  Now fixed.

  #define STR(a) #a
  const char *s = STR(1.u);

4/7/05   C++-generating back end: functional casts in operand contexts

The C++-generating back end formerly always enclosed generated functional
casts in parentheses to avoid possible ambiguities.  For example:

  struct A { 
    A(char); 
  }; 
  struct B { 
    B(A); 
    B &operator=(char) {
      *this = B(A(c));  // formerly generated as (*this) = (B((A(c))));
      return *this;
    } 
  }; 

Versions of g++ prior to 3.4 erroneously diagnosed the generated code as a
syntax error because of the superfluous parentheses around the cast.  The
C++-generating back end now suppresses the enclosing parentheses around a
functional cast when it follows an operator in an expression, as there is
no risk of ambiguity in that context.

4/6/05   Labels for switch breaks marked as such

The front end converts break statements to goto statements with synthesized
labels whose break_label flag is set to TRUE.  Now an additional flag is set
to TRUE if the break statement breaks out of a switch statement (as opposed
to any of the loop statements).  The new flag is spelled switch_break_label.

4/6/05   Limit on number of operands in GNU extended asm constructs

In GNU modes, the front end formerly imposed a limit of no more than 10
operands in extended asm constructs.  This limit has been raised to 30.
Furthermore, it appears that GNU compilers count operands with the '+'
modifier as being double operands (presumably to model both a read and
a write operation): This is now also emulated by the front end.

4/6/05   Selection of copy operations in generated members for mutable fields

Previously, when the front end generated a copy constructor or a copy
assignment operator for const-qualified objects, it treated all fields
as being const also.  For mutable fields this is not correct and could
lead to spurious errors.  For example:

  struct M {
    M& operator=(M&);
  private:
    M& operator=(M const&);
  };
  struct S {
    mutable M m;  // Previously an error because the copy assignment operator
  };              // for const M objects is inaccessible.  Now okay.
  void f(S& dst, const S& src) {
    dst = src;    // Force the synthesis of copy assignment operator for const
  }               // objects of type S.

This is now fixed.

4/5/05   GNU C++ compatibility: lookup of dependent names

When the g++ compiler does a lookup in a class with a dependent base class,
and when that lookup would normally return a nonstatic data member of an
enclosing class, g++ will instead return a nonstatic data member of a
dependent base class.  We now emulate this behavior in g++ mode when
gnu_version is < 30400.

  template <class T> struct C {
    struct A { int i; };
    struct B: public A {
      void f() {
        i = 0;  // In GNU mode, A::i not C::i
      }
    };
    int i;
  };
  int main() {
    C<int>::B b;
    b.f();
  }

4/5/05   Gnu C++ compatibility: "best worst conversion" in overload resolution

The change made on 7/20/04 to implement an "extension" in the GNU C++
overload resolution algorithm was too broad.  When the candidate
selected by that process is a user-written function, g++ (all versions)
gives an error message (the message in g++ 3.2 makes it look as if the
selected function is used and it's just a warning, but it's really an
error), which means in effect the process does nothing -- that error is
equivalent to an ambiguity error.  When the result is a built-in operator,
however, g++ uses it without a diagnostic, which is the case that the
7/20/04 change was trying to get working.  So the EDG emulation has
been changed to throw away the candidate selected if it's not a
built-in operator, thus restoring an ambiguity error.

  template<class T>
  struct c {
    operator T*() const;
    bool operator==(const T*) const;
  };
  bool test(const c<short>&r, short*p) {
    return (r == p);  // Error again in g++ mode
  }

4/4/05   Compilation errors in some configurations

When GNU_EXTENSIONS_ALLOWED is TRUE and USER_CONTROL_OF_STRUCT_PACKING is
FALSE, the front end sources could not be compiled.  This is now fixed.

4/4/05   Abort on use of type from unnamed namespace as template argument

The front end aborted in IL lowering in lower_name.c while processing
a function with an argument that uses a template instantiated on
a type from an unnamed namespace, if the function is the first
function with an external definition in the translation unit (it
was selected as the basis for the module id name).  Now fixed.

  template <class T> class CArray { };
  namespace {
    struct X {int a;};
    typedef CArray<X> XArr;
  }
  void fn (XArr *px) {}

4/1/05   Abort while processing nested class of a class template

In somewhat unusual situations (usually involving strict mode), the front end
sometimes aborted with an internal error in find_copy_assignment_operator when
processing a nested class of a class template.  For example:

  template<int *> struct B {};
  template<typename T> struct S {
    static int si;
    struct D: B<&si> {};  // Caused an abort in strict mode during prototype
  };                      // instantiation of S<T>::D.

This is now fixed.

3/31/05  Microsoft compatibility: visibility of template parameters in
         explicit specializations

The Microsoft compiler incorrectly made template parameters visible in
explicitly specialized classes.  This has been fixed in version 7.1 of
the Microsoft compiler.  The emulation of this bug is now disabled when
microsoft_version is >= 1310.

  template <class T> struct A {
    void f();
  };
  template <> struct A<int> {
    T t;  // T visible to VC++ 7.0 and earlier
  };

3/31/05  Microsoft compatibility: explicit instantiation in class scope

The Microsoft compiler accepts an explicit instantiation directive in
a class scope.  We now emulate this behavior in Microsoft mode.

  template <class T> class A {};
  class B { template class A<B>; };

3/30/05  GNU C++ compatibility: visibility of using-directives

Version 3.5 introduced a change to emulate the visibility rules used by
g++ to determine which using-directives should be visible during template
instantiations.  This change introduced lookup errors in g++ mode in
certain cases involving block-scope using-directives.  Now fixed.

  namespace std { typedef int string; }
  namespace N {
    template <class string_type> struct test { };
    template <class test_iterator> struct tester {
    void f() {
      using namespace std;
      test_iterator current;
      current++;
      string result;  // error: "string" is undefined
      }
    };
    typedef test<const char *>* test_case_iterator;
  }
  int main() {
    N::tester<N::test_case_iterator> t;
    t.f();
  }

3/30/05  Microsoft compatibility: Calling conventions on constructors and
         destructors

In Microsoft mode, the front end now ignores explicit calling convention
specifiers on constructors and destructors (with a warning).  This causes
some cases that previously triggered errors to be accepted.  For example:

  struct S { S(); };
  __stdcall S::S() {}  // Now accepted with a warning.  (Previously an error.)

The special case of specifying __cdecl on a constructor with an ellipsis
parameter is accepted without a warning (see Changes entry of 9/17/96).

3/30/05  Position of top-level break statement within switch clause

The front end previously recorded the break_position field of a_switch_clause
even for break statements that did not appear at the top-level of the switch
clause (i.e., break statements appearing within other statements).  For
example:

  void f(int x, int y) {
    switch (x) {
      case 42: if (y) break;  // Position of "break;" previously recorded as
    }                         // the "break_position" in the entry associated
  }                           // with this switch clause.

This has been fixed: The position is only recorded for a break statement that
appears directly within the switch clause.  Note if VLAs were declared in the
switch clause, the break_position is still recorded even though the break
statement will be recorded as a goto statement (and the implied_break_at_end
field will be FALSE).

3/30/05  GNU compatibility: Extended asm memory operands can have any type

In GNU mode, the front end previously did not accept extended asm operands
with certain types (e.g., array types).  Now any type is accepted.  For
example:

  void f() {
    unsigned char x[6];
    __asm__ __volatile__("lidt %0\n" : "=m"(x));  // Now accepted.
  }

(See also the Changes entry of 10/9/02.)

3/30/05  Calling the front end from other programs / reinitializing the
         front end

Formerly, it was difficult to use the front end as part of another program,
or in environments where the front end could be restarted in such a way that
static initializations were not redone.  The initialization and memory
management routines of the front end have been modified to support such
usage.  The following changes have been made:
- The MAKE_FRONT_END_CALLABLE configuration macro has been added.  When this
  macro is TRUE, the front end does not provide a main routine.  The name of
  the main entry point to the front end is specified by the EDG_MAIN macro,
  which defaults to edg_main.
- The initialization of all global/static variables (except for arrays that
  are not modified) is now done dynamically.
- A record is kept of all memory allocations so that the memory can be freed.
When MAKE_FRONT_END_CALLABLE is TRUE:
- All memory is freed when the front end completes.
- All open files are closed, even if the front end terminates abnormally.
- The front end does not exit, but instead always returns to the caller.
  This is done even in the event of a catastrophic error on internal error.

These changes involve some new coding conventions in the front end.  See
the "Initialization and Wrapup", "Memory Management" and "File Variables"
sections of the Administrative Functions chapter of the internal documentation
for more information.

3/29/05  Configuration macro to tie GNU version to GNU ABI version

In GNU modes, setting the new macro TIE_DEFAULT_GNU_ABI_VERSION_TO_GNU_VERSION
to TRUE causes the front end to set the global variable gnu_abi_version to
the value of gnu_version.  E.g., when specifying the command-line options
"--g++ --gnu_version=30300", the front end not only emulates the C++ dialect
supported by GNU C++ 3.3, but also the ABI of that same version of GNU C++.
Since the front end does not emulate GNU ABI versions less than 30200, setting
the macro TIE_DEFAULT_GNU_ABI_VERSION_TO_GNU_VERSION to TRUE requires that
MIN_GNU_VERSION be no less than 30200.  In non-GNU modes, the value of
gnu_abi_version is still determined by DEFAULT_GNU_ABI_VERSION, even when
TIE_DEFAULT_GNU_ABI_VERSION_TO_GNU_VERSION is TRUE.  This new option is only
available when IA64_ABI is TRUE.

3/29/05  Microsoft compatibility: POD_func().field is an lvalue

In Microsoft C++ compatibility mode, a field selection out of a
class rvalue with a POD type now yields an lvalue (rather than
an rvalue as previously and as the standard requires).

  struct A {
    int i;
  } a;
  struct A f() { return a; }
  int main() {
    int *p = &f().i;  // Error usually, okay in Microsoft C++ mode
  }

3/28/05  Microsoft compatibility: Type of *this in selective overriders

In Microsoft mode, the front end accepts declarations of virtual member
functions with a class qualifier to indicate that only the virtual member
in the indicated class is overridden by the qualified declaration (see
Changes entry of 7/18/03).  However, the type of *this was mistakenly
recorded as being the type of the indicated base class instead of the
parent type of the member function.  This could manifest itself as spurious
errors when attempting to access other members of the parent type.
For example:

  struct B { virtual void f() = 0; };
  struct D: B {
    void d();
    void B::f() {  // Selective overrider syntax (Microsoft mode).
      d();         // Previously a spurious error.
    }
  };

This is now fixed.

3/27/05  C++-generating back end: Microsoft compatibility for the scope of
         names in the initializer of a namespace member

In the Microsoft dialect, the initializer for a namespace member defined
outside its namespace is not considered to be in the lexical scope of the
namespace (in contrast to the treatment of initializers for static data
members of classes).  The C++-generating back end now generates explicit
namespace qualification in such initializers for names that refer to members
of the namespace when the Microsoft dialect is the target.  For example:

  namespace N {
    const int i = 5;
    extern int j;
  }
  int N::j = N::i;  // Formerly generated as "int N::j = i;"

3/26/05  Sun linker scope keywords allowed in C mode

The Sun linker scope specifiers (see Changes entry of 11/10/04)
can now be enabled in C mode.  This allows compilation of Sun C
code using --c --sun_linker_scope (but not --sun, which implies
C++ mode as of now).  In Microsoft C mode and in strict ANSI C
mode, the Sun linker scope specifiers are never enabled by
default.  In other C modes, they are enabled by default when both
DEFAULT_SUN_LINKER_SCOPE_ALLOWED and DEFAULT_SUN_COMPATIBILITY
are set to TRUE.

3/25/05  Zeroing of partially-initialized aggregate compound literals

The code generated by IL lowering to do zeroing of partially-initialized
compound literals with automatic storage duration was not correct in
two different ways:

  -- In C++ mode, the zeroing code was placed after the code that
     initialized individual members, thus clobbering that initialization.
  -- In C mode, no zeroing code was added, thus failing to initialize
     members not explicitly initialized.

Both problems are now fixed.

  typedef struct _TgVector {
    float x, y, z, w;
  } TgVector;
  TgVector TestVec;
  void SetRotation(float x, float y, float z) {
    TestVec = (TgVector) {x, y, z};  /* Was incorrect. */
  }

3/25/05  GNU C++ mode: do-nothing reinterpret_cast allowed

In GNU C++ mode, a do-nothing reinterpret_cast is now allowed even
if it's not one of the cases allowed by the standard.  A warning is
issued.

  int x;
  int y = reinterpret_cast<int>(x);  // Allowed in g++ mode

3/25/05  Microsoft compatibility: Implicit destruction of property fields

In Microsoft C++ mode, the front end previously incorrectly created IL to
destroy a property field with a class type requiring nontrivial destruction.
This problem could manifest itself as an internal error when reading an IL
file containing such IL.  For example:

  struct A { ~A(); };
  struct S {
    __declspec(property(get=getA)) A a;  // Not really a data member: Should
    A getA();                            // not be destroyed.
  } s;

This is now fixed.  (See also Changes entry of 7/8/99.)

3/24/05  Diagnostic on branch past trivial default initializations

The front end previously failed to diagnose branches past non-POD variables
default-initialized with a trivial constructor (unless the variable had a
nontrivial destructor).  For example:

  struct B {};
  struct D: B {};
  void f() {
    goto L1;  // Previously undiagnosed.  Now an error in strict mode
    D d;      // and a warning otherwise.
  L1:;
  }

This is now fixed: An error is issued in strict mode, a warning otherwise.

3/24/05  C99 inline definitions and entities with internal linkage

In C99 mode, the front end previously issued an error whenever a function with
external linkage declared with the keyword "inline" referred to an entity with
internal linkage.  Now, an error is only issued for function definitions that
are "inline definitions" with external linkage: Every declaration in the
translation unit must have the keyword inline, and no declaration in that
translation unit may be marked as "extern" or "static".  For example:

  static int s;
  inline int f() {  // Not an inline definition, because second declaration
                    // not marked "inline".
    return s;       // Previously an error in C99 mode.  Now okay.
  }
  int f();

Furthermore, the diagnostic has been eliminated altogether in GNU C99 mode.
(See also the related issue in the Changes entry of 1/17/05.)

3/24/05  Routine "called" flag not transferred in multi-translation-unit mode

In some cases when multi-translation-unit mode is used, the "called"
flag on a routine entry was FALSE even though the routine has been
called in one of the translation units.  Now fixed.

3/23/05  Memory allocation problem in template parameter remapping

An error in the template parameter remapping routines in il_to_str
could cause the template parameter remapping tables to become
corrupted.  The problem could also result in repeated reallocations
of the tables.  Now fixed.

3/22/05  GNU C++ compatibility: Defining types in nonstandard places

In GNU C++ mode, when gnu_version is less than 30400, the front end accepts
class and enum type definitions in certain nonstandard places (e.g., in a
cast).  When gnu_version was (strictly) larger than 30400, however, the
front end sometimes issued an error more than once.  For example:

	void f() { (enum E { e }*)0; }  // Error issued twice in some modes.

This is now fixed.

3/22/05  Building standalone utility programs

The changes made to enable the front end to be restarted require some
changes to the way in which standalone utility programs are built:

- fe_init.c must now be compiled and linked with standalone utility
  programs.
- Standalone programs must no longer define the EXTERN and VAR_INITIALIZERS
  macros.
- Standalone programs must call standalone_utility_init before setting
  or using any front end global variables.

3/21/05  C++-generating back end: unneeded casts in reference initialization

The C++-generating back end sometimes added unneeded casts, for example,
when initializing a reference to an array type with an lvalue of that type.
These extra casts caused errors when the generated code was compiled with
g++.  The superfluous casts are now omitted.  For example:

  int a[4];
  int (&r)[4] = a;  // Formerly generated as ((int (&)[4])a)

3/21/05  C++-generating back end: types defined in variable initialization

In g++ mode, the front end accepts definitions of types within variable
initializers (e.g., in casts).  The C++-generating back end failed to
include the definition of such types in the generated code, using only the
type name (or a generated name, for unnamed types).  This is now fixed.  For
example:

  void f() {
    void* p = (struct S {}*)0;  // Formerly generated as (S*)0
  }

3/21/05  Optimization of copy constructor calls in direct-initializations

Copy constructor calls in direct-initializations are now elided in
the same way as in copy-initializations.

  struct T {
    T(int);
    T(const T&);
  };
  T t1 = T(0);  // t1 was already initialized directly
  T t2(T(0));   // t2 is now initialized directly

3/21/05  Stricter array bound constraints in strict C99 mode

In strict C99 mode, the front end previously allowed the declaration of a
local static or block extern array when its bound was a constant of integer
type, but not a valid integral constant-expression.  For example:

  void f() {
    static float a[(int)(3.0+4.0)];  // Not allowed by the C99 standard.
  }                                  // Now an error in strict mode.

Such cases are now diagnosed as errors in strict C99 mode and in any other
strict mode allowing variable-length arrays.

3/18/05  GNU C compatibility: Initialization of flexible array members

GNU C mode allows a flexible array member to be initialized using an
aggregate initializer if the flexible array member is a direct member of
the top-level type of the variable being initialized.  Now, non-top-level
flexible array members can also be initialized with an empty initializer
list.  For example:

  struct F { int n; int a[]; };
  struct T { struct F f; };
  T x1 = { { 1, {} } };     // Okay in GNU C mode: non-top-level but empty.
  T x2 = { { 1, { 2 } } };  // Still an error.

(See also the Changes entry of 9/1/04.)

3/17/05  GNU C++ compatibility: Nonstandard anonymous union fields

GNU C++ compilers impose the same constraints on the fields of nonstandard
anonymous unions (which aren't really unions) as on the fields of ordinary
(named or unnamed) unions.  The front end now imposes the same constraints
in GNU C++ mode (but the errors are discretionary).  For example:

  struct S { S(); };
  struct N {
    struct { // Nonstandard anonymous union.
      S s;   // Now a discretionary error in GNU C++ mode (still accepted
    };       // in, e.g., Microsoft C++ mode).
  };

(Nonstandard anonymous union are an extension accepted in certain modes when
ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE.)

3/17/05  Diagnostic on macro redefinitions with named variadic parameter

In modes allowing named variadic macros (e.g., GNU modes), the front end
failed to warn if a macro redefinition only differs in the variadicity of
a macro parameter.  This is now fixed: A warning is issued.  For example:

  #define A(x) 1
  #define A(x ...) 1  // Now a warning in GNU modes.  Previously silently
                      // accepted.

3/17/05  Microsoft compatibility: redeclared template member function
         default arguments

In Microsoft mode (when microsoft_version is >= 1300) a default argument of
a member function of a class template may be redeclared.  A warning is
issued and the default from the initial declaration is used.

  template <class T> struct A { void f(int i = 0); };
  template <class T> void A<T>::f(int i = 0) { }

3/16/05  Microsoft compatibility: Incomplete property fields

In Microsoft mode, the front end no longer issues an error when a property
field (a Microsoft extension) is declared with an incomplete type.  For
example:

  struct I;
  struct S {
    I get_p();
    __declspec(property(get=get_p)) I p;  // Previously an error.
  };                                      // Now accepted without diagnostic.

3/16/05  Predefined macros on MacOS X systems

When the front end is compiled on a MacOS X system, a number of macros
(e.g., __APPLE__, __ppc__, and __BIG_ENDIAN__) are now predefined.  To
change that, see sys_predef.c.

3/15/05  GNU compatibility: white space inside line splice

The GNU preprocessor issues a warning but accepts white-space characters
(space, tab, formfeed, and vertical tab) within a line splice, i.e., between
the "\" and linefeed characters.  The front end now does the same in gcc and
g++ modes.

3/15/05  Microsoft mode abort on in-class specialization appearing in multiple
         translation units

When simultaneously processing multiple translation units in Microsoft
mode, the front end sometimes aborted with an internal error in
update_canonical_entry (defined in trans_corresp.c).  This occurred with
fairly complicated code involving in-class explicit specializations of
member function templates.  The problem is now fixed.

3/14/05  Position of goto-statement generated for switch case fall-through

When a switch clause "falls through" to another clause (e.g., because the first
clause does not end in a break statement), the front end generates a goto
statement from the end of the first clause to the beginning of the second one.
Previously, this generated goto statement was given a nonnull source position,
which is contrary to our general approach of assigning null source positions
to compiler-generated source constructs.  Now a null source position is used
for such cases.  For example:

  void f(int x) {
    switch(x) {
      case 0: x = 0;
        /* A compiler-generated "goto" statement is inserted here to represent
           the "fall-through".  It now has a null source position. */
      case 1: x = 1;
    }
  } 

3/14/05  C++-generating back end: Sun compatibility for member enumeration
         constants used in default arguments in friend declarations

The Sun C++ compiler has a bug such that class member enumeration constants
used in default arguments in friend declarations must be referred to using
qualified names.  (This is similar to a Microsoft issue described in the
10/25/04 Changes entry, except that the Sun compiler requires qualification
even for enumerations declared in the same class as the friend declaration.)
The C++-generating back end will now qualify such name references when
sun_is_generated_code_target is TRUE.  For example:

  struct B {
    enum E1 { e1 };
  };
  struct D: B {
    enum E2 { e2 };
    friend void f(E1 = B::e1);  // Was "e1", now "B::e1" for Sun target
    friend void f(E2 = D::e2);  // Was "e2", now "D::e2" for Sun target
  };

3/14/05  Double mangling of class-as-subobject name for local class

The mangled name generated for the class-as-subobject version of
a local class had double mangling in it -- the containing function
mangling was included twice.  A class has a class-as-subobject
version if it contains virtual base classes.  Now fixed.

3/14/05  bool += pointer

C++ allows the compound assignment b += p where "b" has bool type
and "p" has pointer type.  The front end now accepts that and lowers
it properly.

3/14/05  Microsoft and GNU C++ compatibility: calling main

Microsoft and GNU C++ modes now allow main to be called and have
its address taken.

3/11/05  Microsoft C compatibility: Integer variable redeclarations

In Microsoft C mode, the front end already accepted redeclaring an integer
variable with a different integer type if the new type has the same size and
alignment as the type used in the original declaration.  However, this was
not always accepted if the new type was expressed as a typedef.  For example:

  unsigned int i;
  unsigned long i;  // Already accepted in Microsoft C mode (with a warning).

  typedef unsigned long UL;
  UL i;  // Now also accepted in Microsoft C mode (with a warning).
         // Previously an error.

3/11/05  C99 mode: void type parameter

In C89 and C++, an empty parameter list can be written as "(void)".  In non-
strict modes, the front end also accepts "(T)" where T is a typedef for "void"
as an equivalent construct (with a warning).  The front end applied the same
rules in C99 mode, but the C99 standard actually permits the form using the
typedef too.  We therefore now silently accept that form in all C99 modes.
For example:

  typedef void V;
  void f(V) {}  // Now silently accepted in all C99 modes.  (Previously a
                // warning in nonstrict C99 mode, and an error in strict C99
                // mode.)

3/11/05  Microsoft compatibility: memory allocation problem with
	 Microsoft attributes

A memory allocation done when building the data structures used when
scanning Microsoft attributes allocated too little memory, resulting in
invalid memory accesses.  Now fixed.

3/11/05  Incorrect pointer value in default_arg_expr field with IL lowering
         and RECORD_CONSTANT_EXPRESSIONS_IN_IL

In some obscure cases, the default_arg_expr field of an a_param_type
entry arrived in the back end with a garbage value.  This happened
only in versions with DO_IL_LOWERING and RECORD_CONSTANT_EXPRESSIONS_IN_IL
both set to TRUE (an unusual but permitted combination), and is largely
harmless given that the default_arg_expr field contains no useful
information after IL lowering has been done (in fact, in almost all
cases it has been set to NULL) and therefore a back end has no reason
to look at it.  Now fixed.  This problem was introduced by the change
associated with the Changes entry of 5/17/04.

  struct X {};
  typedef void (X::*PM)(int);
  struct A : public X {
    void f(int i = 0);
  };
  PM x = static_cast<PM>(&A::f);
  void A::f(int i) { }

3/9/05   Incorrect IL for lvalue-returning assignment of class with
         tail padding in IA-64 ABI

The code generated by IL lowering to do an assignment of a class
with tail padding in the IA-64 ABI was incorrect when the assignment
was further used as an lvalue.  A cast was missing, and as a
consequence the types didn't match up and incorrect behavior
in a back end was possible.  The C-generating back end aborted
in dump_field_from_second_operand ("wrong field class").  Now
fixed.

  template <class _T1, class _T2>
  struct my_pair {
    _T1 first;
    _T2 second;
    my_pair() : first(), second() {}
  };
  struct my_map {
    my_pair<int,bool> insert(const my_pair<const int, double>&);
  };
  void foo(my_map& uniDoc) {
    my_pair<int, bool> ins;
    my_pair<const int, double> oneDoc;
    if ((ins = uniDoc.insert(oneDoc)).second == false)
      ;
  }

3/8/05   C++-generating back end: typedef of a class type to its own name

When a class type was typedef'ed to its own name, the resulting typeref
was incorrectly treated as an injected class name.  The C++-generating back
end assumed that such typerefs were actually class types and accessed fields
in the class_struct_union variant, potentially leading to incorrect
qualification in the generated code.  Now fixed.

3/8/05   Pragma at the end of an implicitly included file not processed

A pragma at the end of an implicitly included file was silently discarded.
Now fixed.

3/8/05   Generated copy constructor call as bitwise copy with direct-
         initialization

A direct-initialization that calls a generated bitwise copy constructor
is now optimized as a bitwise copy instead of a call.  Calls of such
copy constructors were formerly optimized only in copy-initializations.

  struct A {
    A();
  };
  A a;
  A b(a);  // Now done as bitwise copy.

3/8/05   Invalid memory access with VLA lowering and
         COMPILE_MULTIPLE_SOURCE_FILES

An invalid memory access could occur when using LOWER_VARIABLE_LENGTH_ARRAYS
and COMPILE_MULTIPLE_SOURCE_FILES, if the compiler was invoked with
multiple source files that make use of variable length arrays.  Now fixed.

3/7/05   C++-generating back end: Microsoft compatibility with conflicting
         dllimport/dllexport specifications

If a member of a __declspec(dllimport) class is defined, it implicitly
becomes __declspec(dllexport) (with a warning).  The C++-generating back end
explicitly qualified the declaration and definition of such members with
__declspec(dllexport), which is not accepted by the Microsoft compiler.  The
__declspec(dllexport) specification on such members is now suppressed.  For
example:

  struct __declspec(dllimport) S {
    void f();      // No longer generated with __declspec(dllexport) specifier
  };
  void S::f() { }  // No longer generated with __declspec(dllexport) specifier

3/7/05   Exception handling cleanup, base class with construction vtable

The code generated by IL lowering to compute the address of a
special construction virtual function table to be used during
destruction of a virtual base class if an exception is thrown
while an object derived from that class is being constructed
was incorrect.  As a consequence, if the exception was thrown
the code could abort.  This affected only the Cfront-like ABI
and not the IA-64 ABI.

3/7/05   Microsoft compatibility: Parenthesized class member declarations

Microsoft VC++ 7.1 introduced a parsing bug that causes it to accept and
ignore a leading left parenthesis in class member declarations.  The matching
right parenthesis may appear almost anywhere in the declaration or not at all.
For example:

  struct S {
    ()unsigned int* a0[3];  // Accepted by VC++ 7.1 (emulated).
    (unsigned) int* a1[3];  // Accepted by VC++ 7.1 (not emulated).
    (unsigned int)* a2[3];  // Accepted by VC++ 7.1 (emulated).
    (unsigned int*) a3[3];  // Accepted by VC++ 7.1 (emulated).
    (unsigned int* a4)[3];  // Accepted by VC++ 7.1 (emulated).
    (unsigned int* a5[)3];  // Accepted by VC++ 7.1 (not emulated).
    (unsigned int* a6[3)];  // Accepted by VC++ 7.1 (not emulated).
    (unsigned int* a7[3]);  // Accepted by VC++ 7.1 (emulated).
    (unsigned int* a8[3];   // Accepted by VC++ 7.1 (emulated).
  };

The parentheses in this example are all ignored by the Microsoft compiler: The
fields all have the same type ("array of 3 pointers to int").  We now partially
emulate this behavior in Microsoft bugs mode when microsoft_version >= 1310.
(In the example above, we emulate the cases marked with "(emulated)".)

3/3/05   Missing access error on elaborated type specifier reference to
         an injected class name

The front end failed to issue an access error when an inherited injected
class name was referenced using an elaborated type specifier.  Now fixed.

  class B { };
  class D1 : B {};
  class D2 : private D1 {
    B b1;		// error issued here
    class B b2;     // but not here
  };

3/2/05   C++-generating back end: Declarations of explicit specializations
         of member functions of class templates when
         CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, an
explicit specialization of a class template is generated if one of its
member functions is explicitly specialized.  If the explicit specialization
of the member function is simply declared and not defined, the C++-generating
back end formerly generated the namespace-scope member function declaration,
even though it was already declared in the class template specialization.
This redeclaration has now been suppressed.  For example:

  template<typename T> struct S {
    void f();
  };
  template<> void S<int>::f();

was formerly generated as:

  template<typename T> struct S {
    void f();
  };
  template<> struct S<int> {
    void f();
  };
  template<> void S<int>::f();  // No longer generated

3/1/05   Microsoft compatibility: Out-of-class member redeclarations

The front end emulates a Microsoft extension that allows out-of-class member
function redeclarations that aren't definitions.  For example:

  struct S { void f(); };
  void S::f();  // Accepted in some Microsoft modes.

Since MSVC++ 7.1 no longer accepts this syntax, we no longer accept such
code when microsoft_version >= 1310.  (Similar syntax is still accepted to
express old-style specializations of member functions of class templates.)

3/1/05   Internal error on unnamed class member types across translation units

When simultaneously processing multiple translation units containing a class
type with multiple unnamed member types, the front end sometimes aborted with
an internal error.  The problem occurred, for example, when simultaneously
compiling two identical translation units with the following content:

  struct S {
    typedef enum { e1 } E1;
    typedef enum { e2 } E2;
  };
  void f(S, S::E1);
  void f(S, S::E2);

This is now fixed.

3/1/05   Microsoft compatibility: copy constructor versus template

The Microsoft compiler prefers a non-template copy constructor over a
template constructor even if the latter is slightly better due to
an argument tiebreaker.  Now emulated.

  extern "C" int printf(const char *, ...);
  struct A {
    A() {}
    A(const A&) { printf("C1\n"); }
    template <class T> A(T&) { printf("C2\n"); }
  } a;
  int main() {
    (void)A(a);  // prints C1 in Microsoft 7.1 mode (C2 is standard)
  }

See also the Changes entry of 2/23/02.

3/1/05   Microsoft compatibility: Multiple explicit instantiation directives

In Microsoft mode, the front end now accepts (with a warning) multiple
explicit instantiation directives for the same entity.  For example:

  template<class> void f() {}
  template void f<int>();
  template void f<int>();  // Accepted in Microsoft mode.

3/1/05   Microsoft compatibility: dllimport/dllexport reworked

Extensive changes were made to the front end's treatment of the dllimport and
dllexport attributes.  These changes have the following effects:
  - Whether a warning or an error is issued now matches the diagnostic
    behavior of Microsoft compilers very closely.
  - The dllimport attribute is now replaced by dllexport if a dllimport
    declaration is later defined without the dllimport attribute.
  - An explicit class template instantiation directive with a dllimport or
    dllexport attribute causes the member functions and static data members
    of the instantiated class to be imbued with that same attribute (unless
    the member was explicitly specialized).
  - If a dllimport or dllexport attribute is applied to a derived class,
    the same attribute is applied all its instantiated base classes that
    have no dllimport/dllexport attributes yet.  ("Instantiated base
    classes" are those whose type was generated from a template and not
    explicitly specialized.)
  - IL lowering now applies the dllimport or dllexport attribute of a class
    to its virtual tables and typeinfo objects (and, for the IA-64 ABI, its
    virtual table tables), unless the table or object has internal linkage.
    If the table or object has attribute dllimport, its definition is not
    generated.

3/1/05   Collision of mangled names for unnamed class or enum

In some cases the mangled names generated for unnamed class or enum
types that are local to a class collided, i.e., two different types
ended up with the same mangled name.  Now fixed.

  int gi;
  struct Cls {
    enum { e1 } m_e1;
    enum { e2 = 10 };
  } cls;
  void func() { gi = cls.e2; }

2/26/05  C++-generating back end: Microsoft compatibility in casts to a nested
         class type

Some builds of MSVC++ 6.0 (12.00.8804, for instance, but not 12.00.8168) have
a bug in which using an old-style cast to a nested class type in the default
argument of a constructor causes an internal compiler error.  For example:

  struct S { } s;
  struct Outer {
    struct Inner1 {
      Inner1(S);
    };
    struct Inner2 {
      Inner2(const Inner1& r = Inner1(s));
    };
  };

The default argument for Outer::Inner2 was formerly generated using an
old-style cast, i.e.,

      Inner2(const Inner1& r = ((Inner1)(s)));

thus triggering the MSVC++ 6.0 bug.  Now, when msvc_is_generated_code_target
is TRUE and msvc_target_version_number is 1200, the default argment will be
generated as a functional cast with no enclosing parentheses:

      Inner2(const Inner1& t = Inner1(s));

2/18/05  Preprocessor memory usage

Deeply-nested pseudo-recursive macro expansions, such as found in the BOOST
preprocessor library, formerly required large amounts of memory to process.
The memory requirements of such macro expansions have been greatly reduced
by compacting the macro_buffer each time it is extended as a result of
overflow.

2/17/05  GNU compatibility: Spurious error on asm names

In GNU modes, with configurations with ACCEPT_UNRECOGNIZED_GNU_ASM_OPERANDS
set to TRUE, the front end issued a spurious error on variable declarations
annotated with an asm name.  For example:

  extern int i __asm__("counter");  // Sometimes triggered a spurious error
                                    // in GNU modes.

This is now fixed.  (See also Changes entry of 10/8/04.)

2/17/05  GNU C++ compatibility: In-class pointer initializers

In GNU C++ mode with gnu_version < 30300 the front end now accepts in-class
initializers for static data members of a const pointer type.  For example:

  struct S {
    static int * const p = 0;  // Okay in some GNU C++ modes.
  };

2/16/05  GNU C++ compatibility: storage specifiers on explicit instantiations

In GNU C++ mode, storage specifiers are now sometimes accepted (and ignored,
with a warning) on explicit instantiations.  Specifically, "extern" is
accepted on explicit instantiations of function templates, member functions
of class templates, and static data members of class templates.  "static" is
accepted only on explicit instantiations of ordinary function templates.
For example:

  template<typename T> void f(T) {}
  template static void f(int);  // Accepted in GNU C++; "static" is ignored
                                // with a warning.  (The instantiation still
                                // has external linkage.)

2/16/05  GNU C++ compatibility: Redeclaration through using-declaration

In GNU C++ mode, a variable in another namespace can be redeclared in the
current namespace with an unqualified name that resolves to a using-
declaration for that variable.  For example:

  namespace N { int i; }
  using N::i;
  extern int i;  // Accepted in GNU C++ mode.

Note that this does not apply to function declarations.  (See also the
Changes entry of 6/28/00 reporting this feature in Microsoft and Sun modes.)

2/15/05  Pseudo-destructor call with cv-qualified array type

A spurious error was issued on a pseudo-destructor call in which the
object pointer was a cv-qualified array type and the type used as the
destructor name was the cv-unqualified version of the array type.  Now
fixed.

  typedef int A[2];
  void f(A const volatile *p) {
    p->A::~A();
  }

2/14/05  Searching for preinclude files

When searching for a preinclude file, the front end would start the
search with the directory of the primary source file.  This matches
what is done by the Microsoft compiler, but the GNU compilers start
the search with the current directory.  The GNU behavior seems more
natural as the preinclude takes place before the processing of the
primary source file, so we have changed the front end to use the GNU
model.  This is done in all modes except Microsoft mode, in which we
have retained our previous behavior.

2/13/05  Microsoft property references: object evaluated only once

The code generated for references to Microsoft properties (declared
with __declspec(property)) are now expanded in such a way that
the expression that specifies the class object is not evaluated
twice for increments, decrements, and compound assignments.

  struct A {
    long x;
    A() { x = 0; };
    long Get() { return x; }
    void Set(long p) { x = p; }
    __declspec(property(get=Get, put=Set)) long v;
  };
  int main() {
    A arr[2];
    int i = 0;
    arr[i++].v += 1;  // i no longer incremented twice.
  }

This change uses the new enk_reuse_value expression node
described below (IL CHANGE).

2/13/05  GNU two-operand "?" operator supported in GNU C++ mode

The two-operand form of the "?" operator, formerly supported only
in GNU C mode, is now also supported in GNU C++ mode.  An expression
like "a ?: b" means exactly the same as "a ? a : b" except that
a is evaluated only once.  In C++, various conversions can be
applied to the first operand to give it the bool type required
in the first operand position, or the same type as the third
operand in the synthesized second operand position.

IL CHANGE: We eliminated the eok_binary_question operator used
for this function previously, and instead added a new flag
(is_gnu_two_operand_question_mark) to the normal eok_question
operator that indicates the two-operand case.  The expression
still has three operands, with the second one being a synthesized
expression.  (For example, "a ?: b" in the simplest case would
look like "a ? a : b" plus a flag saying the original form had
two operands.)  We also added a new expression kind enk_reuse_value
that can be used to refer again to the value of a dynamic
initialization under an enk_temp_init in the current expression.
This is used to refer again to the first operand value without
evaluating it a second time.  The dynamic initialization entry
pointed to is marked with the flag is_reused_value.  All these
IL changes are eliminated by IL lowering.

2/10/05  Performance improvement in using-directive lookups

The performance of using-directive lookups has been improved, particularly
for cases where a namespace contains a very large number of functions
with a given name (as if often the case for names such as operator>>).

2/10/05  GNU C++ compatibility: Abstract class return types

GNU C++ compilers only diagnose abstract class return types on function
definitions (standard C++ makes such return types invalid on all return
type declarations).  The front end now emulates this behavior in GNU C++
mode.  For example:

  struct A { virtual ~A() = 0; };
  A f();              // Accepted in GNU C++ mode (error in other modes).
  typedef A (*PF)();  // Accepted in GNU C++ mode (error in other modes).
  A f(A *p) {         // Error in all modes.
    return *p;
  };

2/9/05   GNU C++ compatibility: Static data members in unnamed class types

In GNU C++ mode, the front end now accepts static data members in unnamed
class types.  For example:

  typedef struct {
    static int sm;  // Now accepted in GNU C++ mode.
  } S;

(This was already accepted in Microsoft and cfront modes.)

2/9/05   GNU C++ compatibility: Extraneous qualification in elaborated names

In GNU C++ mode, with gnu_version < 30400, the front end now ignores a
qualifier in an elaborated class name if the qualifier indicates the current
scope and that scope is the global scope or a namespace scope.  For example:

  struct ::X *p1;  // Now accepted in some GNU C++ modes.  (Normally an error
                   // because ::X is not declared yet.)
  class C {
    friend class ::Y;  // Error even in GNU C++ modes: The current scope is
  };                   // not the global scope or a namespace scope.

(See also the Changes entry of 11/2/04 which deals with a similar issue.)

2/9/05   GNU C++ compatibility: sizeof(incomplete class) in template

In g++ mode (with gnu_version < 30400), a sizeof an incomplete class
type is now allowed inside a template definition.  In any instantiation
of the template, the type must be complete.  g++ (before 3.4) doesn't
process the insides of templates before an actual instantiation, and
therefore issues no error on such cases.

  struct I;
  template <class T> struct A {
    int arr[sizeof(I)];  // No error on incomplete I here now in g++ mode
  };
  struct I { int x; };
  A<int> y;  // I is complete when A<int> instantiation is done

2/8/05   Spurious error on template static data member with dependent
         parenthesised initializer

A spurious error was issued if a template static data member was initialized
with a parenthesized initializer of the form "T::<name>".  The error would
only occur when the "implicit typename" feature is being used.  Now fixed.

  template <class T> struct A {
    static int I;
  };
  template <class T> int A<T>::I(T::x());

2/8/05   GNU C++ compatibility: unusable partial specialization accepted

In g++ mode, partial specializations that are unusable because of
nondeducible template parameter are accepted and ignored.

  #include <stdio.h>
  template<class T> struct A {
    class C { };
  };
  template<class T> struct B {enum {e = 1}; };
  template <class T> struct B<typename A<T>::C> {enum {e = 2}; };
  int main(int argc, char **argv) {
    printf("%d\n", B<int>::e);
    printf("%d\n", B<A<int>::C>::e);
  }

2/7/05   Performance of routine list management for namespace scopes

The list of routines for a namespace scope (including the file scope) contains
the routine entries for functions in that scope in the order of their primary
declarations (where the primary declaration is the definition or, if that is
not present, the first declaration).  For example:

  void f1();
  void f2();
  void f1() {}  // Routine list order: f2, f1.

Previously, the simple algorithm to ensure this ordering lead to a performance
bottleneck in some cases where thousands of routine declarations were followed
by hundreds of definitions.  (Much of the front end's processing time was
spent in the function "remove_from_routines_list" in these cases.) The
algorithm has been reworked to drastically improve the front end's performance
on such code.
 
2/6/05   Microsoft 7.1 compatibility: string as argument to built-in ==

The emulation for MSVC++ 7.1 (microsoft_version=1310) now gives
no ambiguity for a case like the one below where a string (which
has a const type as of MSVC++ 7.1) is an operand of a comparison
operator and the other operand is a class that has a conversion
function to "char *" (not const char *).

  struct C {
    C();
    operator char *();
  };
  int main() {
    C cs;
    cs == "x";
  }

A similar case with a user-written operator== function also no
longer gets an ambiguity in Microsoft 7.1 mode.

  struct C {
    C();
    bool operator==(char *);
    operator char *();
  };
  int main() {
    C cs;
    cs == "x";
  }

2/6/05   Microsoft compatibility: bool and pointer as operands of "?"

Microsoft bugs mode now allows the combination of a bool operand
and a pointer (or pointer-to-member) operand as the second and third
operands of a "?" operator.  The pointer(-to-member) operand is converted
to bool, and the result type is bool.  A warning is issued.

  int main() {
    int *p = 0;
    bool b = false;
    b = b ? b : p;
  }

2/4/05   Partial ordering and explicitly specified template arguments

The original specification of partial ordering of function templates did
not make any special provisions for function templates in which certain
template parameters are not used in the signature of the template (and
must therefore be explicitly specified when the function is called).
As a result, examples like the one below resulted in ambiguity errors.
Core issue 214, which clarified the partial ordering rules, included
provisions making such examples well formed.  Our implementation already
reflected most of the clarifications from core issue 214.  We now handle
function templates with template parameters that must be explicitly
specified according to the rules in core issue 214.  Version 7.1 of the
Microsoft compiler also accepts such examples, so this change also
addresses a Microsoft compatibility issue.

  template <class T> T f(int) {return T();}
  template <class T, class U> T f(U) {return T();}
  int main() {
    f<int>(1);
  }

2/4/05   Microsoft compatibility: __asm directives in template strings

When the front end is configured to create string representations of
templates, the string for a template containing a Microsoft __asm directive
was missing a space between the __asm token and the tokens that followed.
When using the C++-generating back end, this could result in errors
compiling the generated C++ code.  Now fixed.

  template <int I> struct A {
    void f() {
      __asm int 1
    }
  };
  int main() {
    A<1> a;
    a.f();
  }

2/3/05   GNU compatibility: infinity used for float values out of range

In GNU mode, the front end accepts floating-point constants that are out
of range and uses the "infinity" value instead.  However, constants that were
explicitly written as float (i.e., with an "F" suffix) were incorrectly not
given this special treatment.  Now fixed.

  float f() { return 1.0e+40F; }

2/2/05   GNU C compatibility: Incompatible block-extern declarations

In GNU C mode, the front end now issues a warning instead of an error on the
declaration of a file-scope entity that conflicts with a preceding block-extern
declaration of that same entity.  For example:

  void f() { extern float x; }
  int x;  // Now a warning in GNU C mode (previously an error).

2/2/05   Extraneous braces in initializers

In nonstrict C modes, the front end already accepted (with a warning) an extra
level of braces around the scalar components of a brace-enclosed initializer.
For example:

  int a[1] = { { 1 } };  // Accepted with a warning in nonstrict C modes.

In some modes (GNU C, Microsoft C++, and Microsoft C with microsoft_version
less than 1310), an arbitrary number of such extra levels is now accepted.
For example:

  int b[1] = { { { 1 } } };  // Accepted with a warning in some modes.
                             // An error is issued in the other modes.

2/1/05   Compile-time floating-point processing under Cygwin

The GNU headers under Cygwin define the isfinite macro; however, it is
unreliable and gives incorrect answers under some circumstances, resulting
in spurious overflow warnings and incorrect values when floating point
literals are converted or manipulated.  float_pt.c has now been configured
not to use the isfinite macro under Cygwin.

1/31/05  GNU C++ value-initialization quirks

The GNU C++ compiler does not zero base classes named in ctor-initializers
with empty parentheses, contrary to the requirements of the C++ standard.
Now, when DEFAULT_EMULATE_GNU_VALUE_INITIALIZATION_BUGS is TRUE
(not the default), we emulate that behavior.  See the Changes entry of
8/17/03 for the similar Microsoft issue.

1/31/05  Microsoft routine specifier differences across translation units

When simultaneously processing multiple translation units in Microsoft mode,
the front end now allows more differences between routine declarations.
First, the __declspec(naked) and __declspec(noreturn) attributes can differ,
but if such a specifier appears on any declaration of the routine, it must
also appear on the definition of the routine.  Second, the __forceinline and
__declspec(noinline) specifiers can appear on some declarations and not on
others, but a routine cannot be declared with __forceinline in one translation
unit and with __declspec(noinline) in another.

1/31/05  Microsoft compatibility: __wchar_t keyword

The __wchar_t keyword is now supported when microsoft_version is >= 1300.
This feature allows the __wchar_t keyword to be used as a synonym for the
wchar_t keyword whether or not the --wchar_t_is_keyword option has been
specified.  As with the Microsoft compiler, when wchar_t is not a keyword,
wide string literals do not have type "wchar_t[n]", but rather have a type
based on the underlying type of wchar_t (e.g., "unsigned short[n]") so an
assignment of the form
  __wchar_t *w = L"xxx";
will fail to compile when wchar_t is not a keyword.

1/31/05  Microsoft compatibility: "." in place of "::" in qualified names

The Microsoft compiler allows a "." to be used in certain qualified names
where a "::" is actually required.  We now emulate this behavior in
Microsoft bugs mode.  A warning is issued.

  struct A {
    enum E { e = 1 };
    struct B { enum E { e = 2 }; };
  };
  int main() {
    int i = A.e;
    int k = A::B.e;
  }

1/28/05  UPC and GNU C mode: Spurious error on THREADS-dimensioned arrays

When UPC and GNU C modes were combined the front end incorrectly rejected
attempts to declare THREADS-dimensioned arrays.  This is now fixed.

1/27/05  Preprocessing performance

Various extensible buffers used in preprocessing formerly grew by fixed
amounts each time they were reallocated.  They now double in size on each
reallocation.  As a result, preprocessing is much faster for macros that
result in very large expansions.

1/26/05  C++-generating back end and GCC_BUILTIN_VARARGS

If a C++-generating back end version was configured with GCC_BUILTIN_VARARGS
as TRUE, the back end entered an infinite loop processing the builtin
va_list typeref that is created when the inclusion of <stdarg.h>
is suppressed.  Now fixed.

1/26/05  Less fragile code for local entity promotion in generated routines

The code in IL lowering that promotes local entities out of functions
(promote_local_entities_to_file_scope) was called for generated
functions as well as user-written functions.  While this seemed
like a safe and appropriate thing to do, it wasn't and it has been
removed.  It's not really needed, because generated functions
don't have the kinds of user-written constructs that require
the promotion.  Even if they did, the call was done rather late,
which meant that variables generated by IL lowering (such as
the state-tracking arrays for exception handling) were promoted
in generated functions but not in user-written functions.  And
it was fragile: one of our customers modified
promote_local_entities_to_file_scope to always return TRUE, and
the promotion caused a problem in the IL generated for
exception handling.  An aggregate constant in the IL ended up
with a null type because it was moved by promotion and the
type was later recorded in the original (pre-move) constant.

To summarize: there's no bug here except with the unusual
change made by this customer, but we've fixed the problem they
ran into in a way that may avoid similar surprises in the
future.

1/25/05  throw of incomplete array

A "throw" of an expression that is an unknown-bound array is now
accepted except in strict mode and g++ mode.  The letter of the
standard makes such a throw ill-formed, but it's a reasonable thing
to do (what's thrown is a pointer, which is complete) and MSVC++
allows it.  We're also entering a core issue for this.

  extern const char a[];
  int main() {
    throw a;  // Strictly speaking ill-formed, now accepted in default mode
  }

1/25/05  GNU C++ compatibility: Extraneous qualifier on member declarations

In most nonstrict modes (including GNU C++ mode), the front end accepts
class member declarations with an extra class qualifier representing the
enclosing class.  For example:

  struct S { void S::f() {} };  // Accepted in most nonstrict modes.

Now, the extra qualifier is also accepted (with a warning) for member
template declarations in GNU C++ mode.  For example:

  struct X {
    template<typename T> void X::f() {}  // Accepted in GNU C++ mode.
  };

1/25/05  Temporary destroyed wrong in generated operator= function

The code generated for an operator= function in a class
incorrectly reused a temporary before destroying it and then
destroyed it more than once.  This problem came up only if
the class has at least two fields of a given class type and
that class's operator= function returns its result by value
(which is unusual).  Now fixed.

  struct B {
    B();
    B(const B&);
    ~B();
    B operator=(const B &);  // Returns result by value, not reference
  };
  struct A {
    B ivA;  // Two instances of class B.  Generated code for A::operator=
    B ivB;  //   reused a temporary too soon and then destroyed it twice.
  };
  int main() {
    A a1;
    A a2;
    a1 = a2;
  }

1/24/05  GNU C++ compatibility: implicit typename and g++ 3.4 mode

The implicit typename feature is usually enabled in g++ mode, but should
have been disabled in g++ mode when gnu_version is >= 30400.  Having
implicit typename enabled resulted in spurious errors when parsing
nonclass template bodies.  Now fixed.

  template <class T> bool f() {
    if (T::i) return true; else return false;
  }

1/21/05  Handling of types across translation units in C mode

The handling of types across translation units in C mode (when simultaneously
processing multiple translation units) has been reworked.  Now types are
matched up across translation units only if they are involved in the
declaration of routines or variables with external linkage.  For example:

  // File 1:
  struct S { int i; };
  struct T { int i; } t;

  // File 2:
  struct S { char c; };    // Okay: Not related to "S" in File 1.
  struct T { char c; } t;  // Error: "T" must match definition in File 1
                           // because of the linked variable "t".

Previously, an attempt was made to set up a correspondence between types even
when they were not related by variables or routines with external linkage.
The change fixes a number of cases that previously aborted and also corrects
the diagnosis of cross-translation incompatibilities in various situations.

1/19/05  Extended position information lost on field declarations

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the additional position information
recorded for field declarations was often lost (all the positions were set to
zero).  This is now fixed.

1/19/05  Spurious error on __declspec(nothrow) across translation units

When simultaneously processing multiple translation units in Microsoft mode,
the front end previously issued an error if two declarations of a routine
(in different translation units) differed only in the presence of the
__declspec(nothrow) specifier.  For example:

  // File 1:
  __declspec(nothrow) void f() {}

  // File 2:
  void f();  // Previously an error when compiled with "File 1".

Now such differences are accepted, except if the declaration missing the
specifier is a definition.

1/19/05  UPC mode: Branching in and out of upc_forall statements

In UPC mode, the front end previously issued an error for every goto or return
statement that might (if executed) cause a UPC thread to branch into or out of
a upc_forall loop body.  This was overly drastic since the UPC specification
only indicates that actually executing such statements results in undefined
behavior.  Now, a warning is issued instead.  In addition, a similar warning
is issued for break statements that might break out of a upc_forall statement.
If the front end determines that any such statement cannot be reached, the
warning is inhibited.

1/19/05  UPC mode: THREADS and UPC_MAX_BLOCK_SIZE

In UPC mode with a static THREADS count (i.e., a threads count specified with
the --upc_threads command-line option), the identifier THREADS is now a macro
that expands to an integer literal representing the number of threads.
Furthermore, in all UPC modes, the macro UPC_MAX_BLOCK_SIZE now expands to an
integer literal describing the maximum allowable UPC block size.

1/19/05  Internal error when building front end with an empty defines.h file

Version 3.5 introduced an assertion check to verify that the values of
TARG_LDBL_MANT_DIG and TARG_SIZEOF_LONG_DOUBLE are consistent with one
another.  If TARG_SIZEOF_LONG_DOUBLE is not defined in the defines.h
file, a default value is supplied.  This default value was not set
based on the setting of TARG_LDBL_MANT_DIG, resulting in an internal
error on some systems.  The default value of TARG_SIZEOF_LONG_DOUBLE is
now determined based on the value of TARG_LDBL_MANT_DIG.

1/17/05  Spurious C mode compatibility error across translation units

When simultaneously processing multiple translation units in C mode, the front
end sometimes emitted a spurious compatibility error between a tag name in a
secondary translation unit and a typedef name in a primary translation unit.
For example:

  // File 1:
  typedef struct { char x; } S;

  // File 2:
  struct S { int x; };

This is now fixed. 

1/17/05  Abort on incompatible C mode declarations across translation units

When simultaneously processing multiple translation units in C mode, the front
end sometimes aborted with an internal error if it encountered two incompatible
definitions of an unnamed struct type used to declare an entity with external
linkage.  For example:

  // File 1:
  struct { int i; } s;

  // File 2:
  extern struct { int j; } s;  // Incompatible field name.  Previously
                                 // caused an internal error.

This is now fixed (a normal compatibility error is issued). 

1/17/05  C99 inline definitions and local static variables

In C99 mode, the front end previously issued an error whenever a local static
variable appeared in a function declared with the keyword "inline".  Now, an
error is only issued for function definitions that are "inline definitions":
Every declaration in the translation unit must have the keyword inline, and
no declaration in that translation unit may be marked as "extern" or "static".
For example:

  inline void f1() { static int a; } // Not an inline definition, because
  void f1();                         // second declaration not marked "inline".

  inline void f2() { static int a; } // Error: local static variable in "inline
  inline void f2();                  // definition".

1/12/05  Microsoft compatibility: __noop accepted in C mode

The Microsoft __noop extension (see entry of 4/1/03) is now also
accepted in Microsoft C mode.

1/12/05  GNU C++ compatibility: Conflicts with inherited enumerator constants

In GNU C++ mode, an enumerator constant that is a derived class member can
now use the same name as an inherited member even when it was already used
in the derived class with the derived class as a qualifier.  For example:

  struct B { enum { e }; };
  struct D: B {
    enum { d = D::e, e = d + 1 };  // Now okay in GNU C++ mode.
  };

1/12/05  Microsoft compatibility: casts like "class A(x)" and "const A(x)"

In Microsoft mode, we now allow functional-notation casts in which the
type is an elaborated type specifier or begins with a cv-qualifier.

  struct A { A(int); };
  const A bar() {
    return (const A(0));  // Now accepted in Microsoft mode
  }
  struct X {};
  const struct X &x = struct X();  // Now accepted in Microsoft mode

1/12/05  GNU C++ compatibility: Location of member function definitions

In GNU C++ mode, the front end now accepts a member function definition in a
namespace that does not enclose the namespace of the parent class.  For
example:

  struct S { void f(); };
  namespace N {
    void S::f() {}  // Now accepted in GNU C++ mode.
  }

1/12/05  GNU C compatibility: Field conflicts with nonstandard anonymous unions

In GNU C mode with gnu_version < 30300 the front end accepts nonstandard
anonymous unions.  A previous change (see entry of 2/27/03) emulated the
GNU behavior of accepting a field declaration with the same name as an
anonymous field declaration.  However, some cases were not covered by that
change.  For example:

  struct A { int f; };
  struct S {
    struct A;
    int f;  // Previously still triggered an error.  Now accepted in some
  };        // GNU C modes.

This has now been fixed.

1/11/05  GNU C++ compatibility: for-init scope

In GNU C++ mode, the front end now allows the name of a variable defined in
a for-init construct to be reused for another variable in the loop's body.
For example:

  void f() {
    for (int i = 0;;) {
      int i = 3;  // Now okay in GNU C++ mode. (Hides the for-init variable.)
    }
  }

1/11/05  C++-generating back end: ambiguous references caused by
         using-directives

When there are using-directives naming the same namespace in nested scopes,
the C++-generating back end sometimes omitted name qualification required
to avoid ambiguities resulting from a using-directive.  For example:

  namespace A {
    namespace B {
      namespace C {
        namespace D {
        }
      }
      using namespace A::B::C;
    }
    using namespace A::B;
  }
  using namespace A::B;

  namespace A {
    namespace D {
    }
    using namespace A::D;  // Formerly generated as D, now A::D
  }


1/11/05  Microsoft compatibility: path names in #line directives
         and diagnostic messages

The Microsoft compiler (versions 7.0 and beyond) outputs complete path
names in #line directives in preprocessed output and in diagnostic
messages for files found in the current directory portion of the include
search path.  We now emulate this behavior in Microsoft mode when
microsoft_version is >= 1300.

1/10/05  Abort on use of local namespace alias in some configurations

In configurations with RECORD_FORM_OF_NAME_REFERENCE set to TRUE, using a
local namespace alias in a qualified name could result in an internal error.
For example:

  namespace N { int x; }
  int f() {
    namespace A = N;  // Local namespace alias.
    return A::x;      // Triggered an internal error in some configurations.
  }

This has been fixed by no longer allocating the IL entry for the alias in
the memory region of the enclosing scope; instead it is allocated in the
file scope memory region.

1/10/05  Microsoft compatibility: injected class names and specializations

While the Microsoft compiler does not, in general, create injected class
names for template instances, it does create them for explicitly specialized
classes (although such injected class names are not always found by
name lookup).  We already treated injected class names specially in
Microsoft bugs mode.  We have updated this treatment to emulate the
Microsoft behavior with respect to explicitly specialized classes.

  template<class T> struct A;

  template<> struct A<int> {
    template<class U> A f();
  };

  A<int> a1;
  A<int> a2 = a1.f<int>();

1/10/05  Spurious correspondence error on incomplete enum declaration

In C++ mode, an incomplete enum declaration in one translation unit triggered
a correspondence error against the complete definition in another translation
unit.  For example:

  // File 1:
  enum F;        // Nonstandard extension allowed in various modes.

  // File 2:
  enum F { e };  // Erroneously treated as a declaration that conflicts with
                 // the one in "File 1".

This is now fixed.  (See also entry of 1/8/05 for another problem with this
test case when compiled in C mode.)

1/8/05   C++-generating back end: using-directives and hiding

Name hiding resulting from using-directives was not considered, causing
names that should have been qualified to be generated as unqualified names.
Now fixed.

  typedef int Int;
  namespace Outer {
     namespace Inner {
       int Int;
     }
     using namespace Inner;
     ::Int i;  // Formerly generated as (unqualified) "Int", now "::Int"
  }

1/8/05   Multiple translation unit merge of complete/incomplete versions of
         enum in C mode

The multiple-translation-unit copy/merge process generated an internal
error in class_type_has_body in types.c while processing, in C mode,
an incomplete enum in the primary translation unit and a complete
version of the enum in a secondary translation unit.  Now fixed.

Primary file:
  enum Fwd;

Secondary file:
  enum Fwd { A, B };

1/7/05   Microsoft compatibility: Concatenation of __LPREFIX(...) followed
         by string literal

In Microsoft mode, the front end now concatenates an __LPREFIX
expansion with a following string literal.

    __LPREFIX(__FUNCTION__) L":"  // Now seen as one string literal

1/7/05   Microsoft compatibility: Repeated signedness specifiers

The front end now accepts (with a warning) repeated "signed" or "unsigned"
specifiers in Microsoft modes (this was already accepted in Cfront mode and
in some GNU C modes).  For example:

  unsigned long unsigned int ul;  // Same as "unsigned long int ul;".

1/7/05   Microsoft compatibility: Access specifiers in typedefs

In Microsoft bugs mode with microsoft_version >= 1300 the front end now ignores
(with a warning) any access specifiers appearing among the specifiers following
a typedef keyword.  For example:

  typedef char protected C;  // Now treated as "typedef char C;" in Microsoft
                             // bugs mode.  A warning is issued.

1/7/05   Undefined virtual inline function causes wrong choice of key function 

In strict ANSI C++ mode, an undefined virtual inline function always triggers
a compilation error.  In other modes, however, such a member function was
silently treated as a noninline function, which in turn made it a candidate
for being the "key function" whose definition determines where the virtual
function table is emitted.  This could result in spurious linker errors.
For example:

  struct S {
    virtual inline void f();  // No longer a candidate key function even if the
  } s;                        // member is undefined in this translation unit.

This has now been fixed by leaving such functions marked as "inline."  Note
that linker errors will still occur if no out-of-line code is generated for
the definition of the inline member.

1/6/05   GNU C/C++ compatibility: __alignof__ and field access

When TARG_DUAL_ALIGNMENTS_FOR_BUILTIN_TYPES is set to TRUE, a built-in type may
have one "normal" or "intrinsic" alignment used when laying out complete object
of that type, and another "field" alignment used when laying out a field of
that same type.  (See Changes entry of 10/7/02.)
Previously, the __alignof__ operator always produced the "intrinsic" alignment
value of the type of its argument.  Now, in GNU modes with gnu_version >= 30300
the field alignment is produced if the argument to the __alignof__ operator is
an expression whose top-level component is a field access operator ("." or
"->").  For example (assuming a normal Linux configuration, where "double" is
aligned on 4-byte boundaries when laying out fields, and on 8-byte boundaries
otherwise):

  struct X { int n; double a; } x;
  double b;
  int m1 = __alignof__(x.a);  // m1 == 4
  int m2 = __alignof__(b);    // m2 == 8

Note that due to current limitations of our internal representation, a field
access is still considered to be "top-level" in some cases where GNU compilers
would not agree:

  int m3 = __alignof__(*&x.a);  // m3 == 4 in EDG GNU mode, but m3 == 8 with
                                // actual GNU compilers.

1/6/05   __genericfx pseudo-macro for generic fixed-point functions

A new pseudo-macro __genericfx (similar to the existing __generic)
has been added to help libraries to implement type-generic functions
for fixed-point operands.  (This is an extension not required by
the Embedded C TR.)  The macro reference looks like

   __genericfx(x, fnc-hr, fnc-uhr, fnc-r, fnc-ur, fnc-lr, fnc-ulr,
                  fnc-hk, fnc-uhk, fnc-k, fnc-uk, fnc-lk, fnc-ulk)

where x is the argument with which a type-generic function is called, and
the remaining 12 arguments are the names of functions from which is selected
the actual function to be called.  (The suffixes with which the function
names are supplied here correspond to function parameter types: short _Fract,
unsigned short _Fract, _Fract, unsigned _Fract, long _Fract, unsigned
long _Fract, short _Accum, unsigned short _Accum, _Accum, unsigned _Accum,
long _Accum, unsigned long _Accum, respectively.  The order is fixed.)

1/6/05   Embedded C: detecting problematic configurations for fixed-point
         folding

The fixed-point folding routines convert fixed-point values to host
floating-point values and then fold the values using floating-point.
This can produce incorrect results if the host floating-point value
is not large enough.  A build-time test has been added to detect such
configurations.  The ALLOW_HOST_FP_TOO_SMALL_FOR_LARGEST_FIXED_POINT_TYPE
macro has been added to allow such configurations to be used even though
fixed-point folding may produce inaccurate results.

1/5/05   Over-eager instantiation of destructor in unused default argument

The destructor for a temporary used in a default argument expression
was instantiated even if the default argument expression is not used.
Now, like other entities referenced in default arguments, it is
instantiated only if the default argument is actually used.

  template <class T> struct A {
    A(int);
    ~A() { m_p->some_f(); }  // Formerly got error because of instantiation
    T* m_p;
  };
  class B;
  struct D {
    void f( const A< B >& = 0 );
  };

1/5/05   Field selection on member field in constant expression

In Microsoft and GNU C++ modes, a field selection that selects a
constant-valued member from a nonstatic member of the current class
is now allowed in a constant expression context.

  struct A {
    enum E { e1 = 1 };
  };
  struct B {
    A a;
    void f() {
      int b[a.e1];  // a.e1 accepted as a constant in some modes.
    }
  };

1/3/05   Carriage returns ignored as white space

When IGNORE_CARRIAGE_RETURN_IN_SOURCE is TRUE (which is the default),
stray carriage return characters in source lines, outside of comments
or character/string literals, are now ignored as white space except in
strict mode.  A remark is issued.  Such carriage return characters
are ignored by the GNU and Microsoft compilers, so this is useful
as a compatibility feature.  Carriage return characters that are part
of the line termination sequence are completely ignored, without
a diagnostic, as before.

12/23/04 static_cast of void * to pointer to incomplete class not accepted

A static_cast of a void * to a pointer to an incomplete class type was
incorrectly rejected.  The problem was partly a naming problem,
derived from the fact that the term "object type" is defined
differently in C than in C++ (in C++, it includes incomplete class
types; in C, it does not) and the code that implemented the check
for this cast used the function is_object_type, which tested the
C version of "object type".  To resolve this, we have made
is_object_type provide the right definition depending on the
language, and we have added is_complete_object_type to test essentially
what the old version tested.  Almost all calls of is_object_type
have been changed to call is_complete_object_type.

  struct X;
  void foo(void *p) {
    static_cast<const X *>(p);  // Formerly got spurious error
  }

12/23/04 Spurious overload resolution ambiguities, built-in operators and
         multiple conversion functions returning same effective type

In some cases, overload resolution incorrectly diagnosed an ambiguity
on a case of applying conversion functions to the operands of a built-in
operator, when the class involved has more than one conversion function
returning effectively the same type (e.g., operator int() and
operator int&()).  Now fixed.

  typedef int *P ;
  struct A {
    operator const P & () const;
    operator P & ();
  };
  int main() {
    A a;
    return a != a;  // Formerly got spurious ambiguity error
  }

12/22/04 Overload resolution: templates and determining best candidate

We were surprised to discover that we had implemented one of the
sets of rules for selecting the best candidate function in overload
resolution out of order.  Specifically, the template checks in
13.3.3 were done after the check on the standard conversion on
the return type.  This is being raised as a core issue with the
standards committee, so we're not going to change the EDG behavior
yet.  However, we have added code to handle this and we select the
currently-standard behavior for GNU C++ mode and MSVC++ 7.0.

  struct C {
    inline operator int () { return 1; }
    template <class T> inline operator T () { return 0; }
  };
  inline long f (long x) { return x; }
  int main (int argc, char *argv[]) {
    int i = f (C ());  // Standard value is 1, formerly got 0
  }

12/21/04 Microsoft compatibility: mixed void/non-void operands to "?" operator

Microsoft C++ mode nows allows mixed void/non-void operands to the "?"
operator, with a result type of void.  A previous emulation of this
feature (see Changes entry of 7/1/96) was found to match the behavior
of MSVC++ only in C mode and only up to version 6.0, and therefore
the emulation of that quirk has now been turned off in other modes
(and therefore certain cases that were previously accepted in C++
mode are now rejected because the type of the "?" is now void).

  struct A {
    A();
    A(const A&);
    ~A();
  } a;
  void f();
  int main() {
    int i = 1;
    i ? a : f();      // Now accepted in Microsoft C++ mode
    i = i ? i : f();  // No longer accepted in Microsoft C++ mode
  }

12/20/04 Nit in %c scanf checking in Microsoft C mode

The checking done for the %c, %s, and %[ scanf specifiers was
configured wrong for Microsoft C mode because the plain char
type is defined as either ik_signed_char or ik_unsigned_char
in that mode (instead of the usual ik_char).  As a consequence,
an incorrect incompatibility remark was issued in some cases.
Now fixed.

  #pragma __scanf_args
  extern void scanf(const char*, const char*, ...);
  void junk(char *in) {
    char c1;
    scanf(in, "%c", &c1);  // Got incorrect remark in Microsoft C mode
  }

12/19/04 GNU C++ and Microsoft compatibility: friend class declaration finds
         names made visible by using-directives

When looking up a class name in a friend class declaration, the g++ compiler
finds names made visible by using-directives.  We now emulate this in g++
and Microsoft modes.

  namespace N { struct A { }; }
  using namespace N;
  struct B {
    void f() { A a; }
    friend struct A;
  }; 

12/19/04 Abort in name mangling with IA-64 ABI and
         PROTOTYPE_INSTANTIATIONS_IN_IL

In a configuration that uses the IA-64 ABI, has PROTOTYPE_INSTANTIATIONS_IN_IL
set to TRUE (and therefore does not use IL lowering), and has
MANGLE_ALL_NAMES set to TRUE, the name mangling code aborted 
while attempting to generate the names of certain nonreal classes
that included unusual operators in expressions under sizeofs.
Now fixed.

  template <bool b1> struct A {
    bool value;
  };
  template <class U> char t();
  template <typename T>
  struct B {
    static const bool value = (A< sizeof(t<T>()) == 1 >::value);
  };

12/17/04 Nit in lexical.c

Some code in lexical.c updated for the recent changes to improve
preprocessing speed set the variable no_modifs_to_curr_source_line
incorrectly.  As a consequence, the token scan routines were slowed
down very slightly.  Now fixed.  This problem was introduced in
version 3.4.

12/16/04 Diagnostic on missing unnamed namespace virtual function definition

We give an error if a virtual function of a class in an unnamed namespace is
never defined (because it cannot be defined elsewhere).  Many compilers accept
such code, which may result in a link error if the function is actually
called.  We have changed the message to more clearly explain the problem
and made it a discretionary error so that the severity can be lowered by
the user to allow examples like the one below to be compiled.

  namespace {
    struct A {
      virtual int f();
    };
  }

12/16/04 Possible abort when using precompiled headers

An abort could occur when dereferencing an invalid pointer to a directory
name entry when using a precompiled header file.  Now fixed.

12/15/04 Hidden name table performance improvement

The hidden name table routines have been improved to deal better with large
numbers of instances of class templates (e.g., a translation unit with many
explicit instantiations).  Previously, the injected class name in each
instance hid every other instance, resulting in N hidden name lists with N-1
entries (or quadratic complexity).  Now only the template itself is added to
each instance's hidden name list, and the C++-generating back end determines
whether an instance is hidden by examining its associated template.

12/13/04 Thread-local storage specifier

When THREAD_LOCAL_STORAGE_SPECIFIER_ALLOWED is TRUE, the front end can now
recognize the specifier "__thread" in some modes.  This specifier is allowed
only on the declaration of static and extern variables, and indicates that
the variable should be placed in "thread-local storage".  For example:

  void f() {
    __thread static int s = 0;  // Okay.
    __thread int i = s;  // Error: i does not have static lifetime.
  }

The command-line option --thread_local_storage enables the new specifier.
By default it is also accepted in GNU and Sun modes (because the GNU and Sun
compilers also accept this extension), but this can be turned off using the
command-line option --no_thread_local_storage.

12/13/04 Microsoft compatibility: injected class names in MSVC 6

Our emulation of the way in which MSVC++ 6 handles injected class names
was not quite right.  In particular, an unqualified lookup will find the
injected class names for certain lookups done within the class.  Base
class injected class names are not found by such lookups, however.  We
now duplicate this behavior in Microsoft mode when microsoft_version
is <= 1200.

  void A();
  void B();
  struct B {
    B(){}
  };
  struct A : public B {
    A(){}
    void f();
  };
  void A::f() {
    A a; // class A
    B b; // function B (and an error)
  } 

12/13/04 Microsoft compatibility: functions defined in in-class specializations

Version 3.5 introduced a problem with functions defined in Microsoft
in-class specializations.  In some cases such function definitions were
not emitted in the generated code, resulting in link errors.  Now fixed.

  template <class T> struct A {
    template <class T2> struct B;
    template <> struct B<char> { void f(){} };
  };
  int main() {
    A<int>::B<char> ab;
    ab.f();
  }

12/13/04 Implicit inclusion: suppressing re-inclusion of primary source file

A change made in version 3.1 could result in the primary source file being
included in an attempt to provide the definition of a template when using
implicit inclusion.  An additional change has now been made to insure that
the primary source file will never be included by the implicit inclusion
mechanism.

12/10/04 GNU IA-64 ABI: Attributes "packed" and "aligned" and bit fields

Some changes were made to the class layout algorithm when emulating the GNU
IA-64 ABI.  Attribute "packed" applied to a class definition prior to the
actual class body no longer causes all its fields to be marked as packed.
Furthermore, attribute "aligned" applied to a bit field now affects the
alignment of the bit field's container.  Finally, the alignment of a
nonzero-length unnamed bit-field now affects the alignment of its enclosing
class.  For example:

  struct __attribute__((packed)) S {
    char c1;
    int x2:1 __attribute(((aligned(8)));
    int x3:4;
  } ;

When configured to match gcc on an IA-32-based Linux, the front end now
correctly computes the size of S as 16, whereas previously it was 2.

12/10/04 Build errors when FULL_SOURCE_POS_IN_IL_STATEMENT set to FALSE

Some compilation errors occurred when configuring the front end with
FULL_SOURCE_POS_IN_IL_STATEMENT set to FALSE and EXTRA_SOURCE_POSITIONS_IN_IL
set to TRUE (a fairly unusual configuration).  This is now fixed.

12/10/04 Microsoft compatibility: lookup of nontype names in base classes

The Microsoft compiler ignores nontype names from base classes for
certain lookups.  Version 3.5 changed the way in which this lookup
is done to match a change made in MSVC++ 7.1, but did not emulate the
Microsoft behavior completely.  An additional change has now been
made to more closely emulate the Microsoft behavior.

  struct A { int Y; };
  template <class T> struct Y : public A {
   Y* p; // ::Y not A::Y
   void f() {
     Y* p2;  // A::Y (and an error) in 7.0, ::Y in 7.1
     p2 = p;
   }
  };
  int main() {
    Y<int> y;
    y.f();
  } 

12/8/04  GNU compatibility: Rendering of attribute "packed" on fields

The C- and C++-generating back ends previously did not render the GNU attribute
"packed" on field declarations, and instead relied on attribute "aligned"
exclusively.  However, GNU compilers silently ignore a reduction in alignment
using attribute "aligned" if attribute "packed" is omitted.  For example:

  struct S {
    char c;
    int i __attribute__((packed, __aligned(2)));
      // Attribute "packed" was previously not rendered in the C- and
      // C++-generating back ends.
  };

This is now fixed.

12/8/04  Linkage of local class defined in a typedef declaration

The front end erroneously attributed C or C++ name linkage to local classes
defined in local typedefs.  For example:

  void f() {
    typedef struct {} L;  // Name linkage should be "nlk_none", but previously
  }                       // (erroneously) set to "nlk_cplusplus".

This is now fixed.

12/8/04  C++-generating back end: Infinite loop on member specialization

When both TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
PROTOTYPE_INSTANTIATIONS_IN_IL are set to TRUE, the C++-generating back end
sometimes ended up in an infinite loop.  This loop was due to the invalid
structure of the list of source sequence entries for the specialization of a
member template.  For example:

  template<typename T> struct A { template<typename T> struct B; };
  template<> template<typename U> struct A<int>::B {};

In the example above, the source sequence entry list ended up listing the
"end-of-construct" entry for the definition of A<int>::B before the entry
of the definition itself (that in turned caused the infinite loop).  This
is now fixed.

12/7/04  Abort in inline_function_fixup_for_class in some configurations

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is set to TRUE
the front end sometimes aborted in inline_function_fixup_for_class (which is
defined in class_decl.c).  The problem only occurred in relatively elaborate
scenarios involving default arguments and nested namespaces.  It is now fixed.

12/6/04  Spurious error on default argument pointer-to-member in template

A spurious error was issued if a class template contained a pointer-to-member
declaration in which a function parameter specified a default argument
value.  Now fixed.  Note that such default arguments are not permitted by
the C++ standard, but are accepted except in strict mode.

  template <class T> struct X {
    const int& (T::*ptr)(int* = 0) const;
  };
  struct Y {};
  X<Y> xy;

12/6/04  Microsoft compatibility: Attributes on elaborated class names

In Microsoft mode, when attributes preceded an elaborated class name (i.e., a
class name introduced with one of the keywords "struct", "class", or "union"),
the front end previously always attempted to apply those attributes to the
indicated type.  Now, no such attempt is made if the type name is not followed
by its definition or by a semicolon.  Instead, the attribute is applied to the
entity indicated by the declarator that follows.  For example:

  [export] struct S {
    [switch_type(char)] union {
      [case(1)] struct A *p;  // Attribute was previously applied to "A", which
    };                        // resulted in an error.  Now the attribute is
  };                          // (correctly) applied to "p".

12/3/04  Microsoft compatibility: Accept correspondence between friend function
         and function with internal linkage

When simultaneously processing multiple translation units in Microsoft mode,
the front end previously issued an error if a function was only declared as a
friend in one translation unit (thereby having external linkage) whereas in
another translation unit it was also declared to have internal linkage.
For example:

  // File 1:
  struct S { friend void f(); }

  // File 2:
  static void f() {}
  struct S { friend void f(); }  // Triggered a correspondence error.

Such cases are now accepted in Microsoft mode.

12/2/04  Microsoft compatibility: For-init scope refinements

In Microsoft mode with microsoft_version >= 1310 (and unless the command-line
options --old_for_init or --new_for_init options are specified) the front end
now enforces the standard for-init scope if using the nonstandard scope (i.e.,
the scope in which the "for" statement appears) would hide a declaration that
was not itself a for-init declaration.  For example:

  void f() {
    int i = 100;
    for (int i = 0; i<10; ++i) {}  // Use standard scope to avoid hiding
                                   // previous declaration of i.
    // i == 100 at this point.
    for (int j = 0; j<10; ++j) {}  // Uses nonstandard scope.
    for (int j = 0; j<20; ++j) {}  // Uses nonstandard scope, hiding the
                                   // previous declaration of j.
  }

Furthermore, even if standard scoping scoping is used due to the type of the
for-init variable (see Changes entry of 9/20/04), a for-init variable of the
same name but with nonstandard scoping might be hidden in the remainder of
its scope.  For example (still assuming Microsoft mode with microsoft_version
equal to 1310):

  struct S { ~S() {} };  // Type with destructor forces standard for-init
                         // scoping.
  void g() {
    for (int i = 0; i<10; ++i) {}  // Nonstandard for-init scope.
      // i is visible here and i == 10.
    for (S i; false;) {}           // Standard for-init scope, but previous
                                   // declaration of i is hidden in its scope.
      // i is invisible here.
  }

12/1/04  Internal error with global "other" pragmas and source sequence lists

When the front end is configured to generate source sequence lists, an
internal error would occur if a pragma with an "other" binding kind,
and with its "global" flag set was not removed from the pragmas list
of the file scope via a call of extract_specific_pragmas.  To solve
this problem, we have changed the way "other" pragmas are handled.  Now,
global "other" pragmas are placed on the scope stack list of the
current scope instead of being placed on the file scope's pragma list.
This should have little or no impact on most customers as "other"
pragmas are seldom used.

11/30/04 Microsoft compatibility: calling conventions ignored in certain
         type comparisons

In Microsoft mode, certain routine type comparisons ignored the calling
conventions of the routines types involved.  One consequence of this
problem is that two template references that differ only in calling
conventions would end up referring to the same template instance.  Now
fixed.

  template <class T> struct A { };
  int main() {
    A<int (__fastcall*)()> a;
    A<int (*)()> a2;
    a = a2;  // should result in an error
  }

11/30/04 Microsoft compatibility: Out-of-class member enum definitions

In Microsoft mode, the front end now accepts out-of-class definitions of
class member enum types.  For example:

  struct S { enum E; };
  enum S::E { e1, e2 };  // Now accepted in Microsoft mode.

11/30/04 c_plusplus macro only defined in cfront mode

Formerly, the c_plusplus macro was defined in all C++ modes except strict
mode and Microsoft mode.  Now, it is defined only in cfront mode.

11/29/04 C++-generating back end: Microsoft compatibility for qualified names
         in using-declarations

Microsoft compilers prior to version 7.0 issued an error when the qualifier
in a using-declaration began with a namespace name.  Now fixed: with
msvc_is_generated_code_target and msvc_target_version_number < 1300, the
qualified name in a using-declaration omits namespace qualifiers.

  namespace N {
    struct B {
      void f();
    };
  }
  struct D: N::B {
    using B::f;    // Formerly generated as N::B::f, now as B::f when
                   // targeting MSVC++ 6.0 and earlier
  };

11/24/04 GNU C++ compatibility: spurious error on attribute in nested
         declarator

In g++ mode, a nested declarator that began with a GNU attribute may not
have been correctly disambiguated, resulting in spurious errors.  Now fixed.

  void f() {
    void (__attribute__((regparm (0))) *f2)();
  }

11/23/04 Microsoft compatibility: internal error on in-class specialization

Version 3.5 introduced a bug that could result in an internal error
(an IL write/read error) when using a Microsoft in-class specialization of
a member class template.  Now fixed.

  template <class T> struct A {
    template <int I> struct B { B() {} } ;
    template <> struct B<0> { B() {} } ;
  };
  int main() {
    A<int>::B<0> b;
  }

11/23/04 Array of abstract class error not always reported

A change made in version 3.5 to allow arrays of abstract class types as
parameter types in GNU C++ mode (see Changes entry of 10/7/04) introduced
a bug causing the front end to report no error in any mode on certain
arrays of abstract class types.  For example:

  struct S {
    void f(S[1]);  // Version 3.5 of the front end never diagnosed this
                   // nonstandard "array of abstract class".
    virtual ~S() = 0;
  };

This is now fixed: An error is diagnosed except in GNU and Sun modes.

11/23/04 Microsoft C++ compatibility: cast to abstract class and warning on
         call of pure virtual function

As noted in the Changes entry of 7/24/04, the front end now warns about
calls to pure virtual functions from constructors and destructors in more
contexts than formerly.  This change, however, inadvertently disabled the
warning when the call resulted from a cast to an abstract class type
(invalid in Standard C++ but permitted in Microsoft bugs mode for versions
less than 1300).  This warning has now been restored.  For example,

  struct B {
    virtual void f() = 0;
  };
  struct D: B {
    void f();
  }
  void g() {
    D d;
    B(d).f();    // Warning was disabled, now issued
  }

11/22/04 GNU C++ compatibility: Floating-point in-class initializers

In GNU C++ mode the front end now accepts in-class initializers for static
data members of a const floating-point type (normally only const integer and
enumeration types are allowed for in-class initializers).  For example:

  struct S {
    static double const F = 3.2;  // Now accepted in GNU C++ mode.
  };

As with the standard (integer or enumeration) case, the initializer does not
make the declaration a definition.  An out-of-class definition is therefore
still needed.  E.g., for the example above:

  double const S::F;

11/22/04 Microsoft compatibility: value of __cplusplus for 7.1

In older versions of MSVC++, the macro__cplusplus was defined as 1
instead of the 199711L required by the standard.  In MSVC++ 7.1
this is corrected.  Therefore, we now set the macro to 199711L
when microsoft_version >= 1310.

11/19/04 Incorrect handling of template-id in friend declaration

A friend declaration in which the declarator is a template-id that
refers to a template that is not in the nearest enclosing namespace
was not handled properly, resulting in spurious errors in examples
like the one below.  Now fixed.

  namespace N { template <class T> class A; }
  template <class T> void f(N::A<T>&);
  namespace N {
    template <class T> class A {
      friend void f<T>(N::A<T>& a);
      private: void* p;
    };
  }
  template<class T> void f(N::A<T>& a) {
    a.p;  // spurious access error
  }
  int main(){
    N::A<int> a;
    ::f(a);
  }

11/18/04 GNU compatibility: multi-line strings

The GNU compilers formerly accepted character string literals that spanned
line boundaries but dropped support for that extension prior to version 3.3.
These multi-line strings are now accepted by the front end in gcc and g++
modes only when gnu_version is less than 30300.  For example:

  const char* x = "a multi-
  line string";    // error unless gnu_version < 30300

11/18/04 C++-generating back end: Microsoft compatibility

As noted in the Changes entry of 11/9/04, the C++-generating back end has
been changed to use functional-style casts instead of C-style casts where
possible.  However, all versions of Microsoft C++ compilers through at least
7.1 have parser bugs that result in at least some well-formed functional-style
casts being diagnosed as syntax errors.  The C++-generating back end will now
produce C-style casts as it formerly did when msvc_is_generated_code_target
is TRUE, to avoid these parser bugs.  For example,

  struct X {
    X(const char*);
  };

  struct Y {
    operator int();
    Y(const X&);
  };

  int f() {
    const char *s = "abc";
    throw X(s);              // #1
    return (int)(Y(X(s)));   // #2
  }

If statement #1 is generated as "throw (X(s))", MSVC 6.0 reports a syntax
error; generating #2 as "return ((int)(Y((X(hello)))));" causes a syntax
error in MSVC 7.1.  Using C-style casts in both cases ("((X)(s))" and
"((int)((Y)(((X)(s)))))", respectively) avoids the syntax errors.

11/18/04 GNU compatibility: line directives in preprocessed output

The GNU preprocessor emits "old-style" line directives (e.g., '# 1 t.c"'
instead of '#line 1 "t.c"').  When preprocessed output is requested, we
now emit old-style line directives when in GNU mode.

11/17/04 GNU and Microsoft compatibility: Deprecated declarations

In Microsoft and GNU modes, the front end allows declarations to be marked as
deprecated (using "__declspec(deprecated)" and "__attribute__((deprecated))"
respectively).  However, the use of deprecated typedef declarations was not
diagnosed with a warning.  For example (GNU mode):

  typedef int I __attribute__((deprecated));
  I i;  // The use of I now triggers a warning (previously not).

This is now fixed.

11/17/04 GNU compatibility: Numeric register names

When GNU_X86_ASM_EXTENSIONS_ALLOWED is set, the front end now accepts numeric
register names in GNU modes.  For example:

  int main() {
    asm("movd %0, %%mm2\n" :  : "m" : "31"); // "31" is a GNU-specific numeric
  }                                          // representation of register mm2.

11/17/04 Performance improvement in memory allocation when using PCH

When the front end is generating and/or using precompiled header files,
an optimization has been added to free_mem_block to disable the coalescing
of fragmented memory blocks as these blocks cannot be freed anyway in
PCH mode.  This can make a significant difference when compiling very
large programs.

11/16/04 Microsoft compatibility: nonclass qualifier bug emulation no longer
         necessary

The Microsoft bug emulation that permits a nonclass typedef to precede a
globally qualified name (see the Changes entry of 7/28/99) is now disabled
when microsoft_version is >= 1300.

11/16/04 GNU C compatibility: Zero-sized structs and C-generating back end

The C-generating back end always avoided generating empty struct types (which
are not valid in standard C) by adding a dummy char field when needed.
However, GNU C compilers do accept empty struct types and treat them as
zero-sized types.  The C-generating back end therefore no longer emits the
dummy char field for empty structs in GNU C mode if the target dialect is
also GNU C.

11/16/04 Warning on sequence of casts that truncates address of local variable

A warning is now issued on a sequence of casts that casts the address of
a local (non-static) variable to an integer type smaller than a pointer,
possibly by way of one or more intermediate casts to integer types.
Formerly, a warning was issued for such cases when the variable is
static, but not when the variable is auto.

  void g(int);
  void f() {
    auto unsigned int b;
    g((unsigned short)(unsigned long)&b);  // Gets a warning now
  }

11/16/04 Microsoft compatibility: cast to abstract class no longer allowed

The Microsoft extension to allow a cast to an abstract class type (see
Changes entry of 1/17/00) is gone as of MSVC++ 7.0, so that extension
has now been disabled for microsoft_version >= 1300.

11/15/04 Better diagnostic on casting away const in a static_cast

The processing for static_cast now gives a specific diagnostic for
casting away const in default mode.  Formerly, this special message
was issued only in strict mode, and a generic "invalid type conversion"
was issued in default mode.

  int *f(int const *p) { return static_cast<int *>(p); }

11/15/04 Virtual function call optimization

When the optimization is enabled, virtual function calls are converted to
direct calls in many cases when the complete object type is known (see the
Changes entry of 7/24/04).  This optimization is now applied when the object
is an array element.  For example:

  struct Base {
   virtual void f();
  };
  struct Derived: Base {};
  int main() {
    Derived t[1];
    t[0].f();     // Formerly used virtual function call, now calls Base::f()
  }

11/15/04 Build errors when USER_CONTROL_OF_STRUCT_PACKING is FALSE

Configurations with MICROSOFT_EXTENSIONS_ALLOWED or GNU_EXTENSIONS_ALLOWED set
to TRUE while USER_CONTROL_OF_STRUCT_PACKING was set to FALSE did not build
correctly due to compiler and/or linker errors.  This is now fixed.

11/14/04  Result of class rvalue "?" is a temporary

The processing for the "?" operator when the result is a class
rvalue now ensures that the second or third operand is copied
to an additional temporary, and that that temporary is returned as
the result of the operation.  This is in accordance with the
standards committee's decision on core issue 446.  Also, the
fact that the operation now has a single temporary result means
that when a reference is bound to it the temporary lifetime is
extended.  This deals with core issue 86.

  struct A {};
  int main() {
    int i = 1;
    A a;
    i ? a : A();
  }

11/12/04 GNU compatibility: Abort when gnu_version too large

When specifying a value larger than 999999 for the --gnu_version command-line
option, the front end aborted with an internal error in macro.c.  This is now
fixed (a command-line error is issued).

11/12/04 Microsoft compatibility: disambiguation of functional notation casts

The C++ standard requires that the type in a functional notation cast be
a single identifier or keyword.  In Microsoft mode, more than one keyword
may be used in a functional notation cast.  Such casts were not handled
properly for disambiguation purposes resulting in spurious errors.  Now
fixed.

  void f(int t) {
    if (unsigned long(t) < 5UL);
  }

11/12/04 Character arrays partially initialized with string literals

The front end now marks as "partially initialized" character array variables
initialized with string literals whose length is smaller than that of the
array variable.  For example:

  void f() {
    char s[4] = "x";  // s now flagged as "partially initialized".
  }

Aggregate variables containing character array fields are similarly treated.
Back ends should ensure that the uninitialized elements of a partially
initialized array are zero-initialized.

11/12/04 GNU compatibility: __builtin_constant_p

In GNU modes, version 3.5 of the front end introduced a bug in the evaluation
of __builtin_constant_p that caused global variables to be treated as
constants in some cases.  For example:

  int i;
  int a[__builtin_constant_p(i)];  // Should be equivalent to a[0], but
                                   // treated as a[1] in version 3.5.

This is now fixed.  (See also the Changes entry of 10/7/04.)

11/12/04 Displaying column numbers when using brief diagnostics

The configuration macro COLUMN_NUMBER_IN_BRIEF_DIAGNOSTICS has been added
to request that column numbers be displayed in diagnostic messages in brief
diagnostics mode.  The default value for the macro is TRUE.

11/11/04 Sun compatibility: Arrays of abstract classes as parameter types

In Sun mode, the front end now accepts function parameter types that are
declared as arrays of abstract class types.  (See also Changes entry of
10/7/04.)

11/11/04 Microsoft compatibility: __declspec(align(...)) ignored on fields

In Microsoft mode the object layout algorithm incorrectly ignored the
__declspec(align(...)) construct when it appeared on field declarations,
unless the front end was also configured with GNU_EXTENSIONS_ALLOWED set
to TRUE.  For example:

  struct S {
    __declspec(align(16)) char x;
  };  // sizeof(S) did not reflect explicit alignment of S::x.

This is now fixed.  (See also Changes entry of 11/3/04.)

11/10/04 GNU C++ compatibility: "friend" specifier on nested classes

In GNU C++ mode, with gnu_version < 30400, the front end now ignores (with a
warning) a "friend" specifier appearing on an in-class definition of a nested
class or nested class template.  For example:

  struct S {
    friend class N {};  // "friend" specifier ignored with a warning in
  };                    // GNU C++ mode (when gnu_version < 30400).

11/10/04 Sun compatibility: Link scope specifiers

Version 3.5 of the front end introduced three new keywords in Sun mode:
__global, __symbolic, and __hidden.  These keywords (introduced by Sun in
version 5.5 of their CC compiler) are intended to indicate how external
variables and functions are treated by the linker.

However, it appears that the identifier __global is commonly used in Sun
header files.  Therefore, to emulate Sun CC compilers without support for
link scope specifiers, a new command-line option --[no_]sun_linker_scope
has been added to indicate explicitly whether link scope specifiers should
be recognized.  (The default setting of this option is determined by the
new configuration macro DEFAULT_SUN_LINKER_SCOPE_ALLOWED.)  Furthermore,
when these link scope specifiers are allowed, it is now possible to enable
or disable them in the source using two new pragmas.  For example:

  #pragma disable_ldscope  // Disable recognition of link scope specifiers.
  int *__global;           // OK, __global is (temporarily) not a keyword.
  #pragma enable_ldscope   // Re-enable recognition of link scope specifiers.

Some Sun CC 5.5 headers use these pragmas in this way to retain backward
compatibility with previous versions of those headers.

11/10/04 C++-generating back end: typedefs in template arguments

When generating the name of a template instance, the C++-generating back end
put out the template argument list that was used when the template was
instantiated, including typedefs.  As a result, a template-id in the source
like X<int> might become X<Y<...>::_Type> in the generated code, if X<int>
were originally instantiated with Y<...>::_Type (as a typedef for "int") as
the template argument.  Template argument lists are now generated using the
underlying types of typedefs rather than typedef names except when the
underlying type is not accessible in the context in which the template-id
occurs.  For example:

  struct S {
    typedef int I;
  };
  template<typename T> struct X { };

  X<S::I> x1;    // Previously generated as X<S::I>, now as X<int>
  X<int> x2;     // Previously generated as X<S::I>, now as X<int>

11/9/04  C++-generating back end: Sun compatibility

In order to avoid syntactic ambiguity, the C++-generating back end never
generated casts using the functional notation (X(y)) but always used C-style
notation ((X)y).  The Sun Workshop compiler, however, treats these two
notations differently, allowing a functional cast to be used as an lvalue
while treating C-style casts as rvalues.  To avoid changing an lvalue into
an rvalue in Sun code, the C++-generating back end now relies on a different
syntactic disambiguation strategy and generates functional casts where
possible.  For example:

  struct X {
    X &operator*=(double);
  };
  void f(const X &x) {
    X(x) *= 1;   // Previously generated as ((X)((x))), now (X((x)))
  }

-------------------------------------------------------------------------------
Version 3.5, November 8, 2004

11/5/04  IL version number updated to 3.5

11/4/04  Microsoft compatibility: __declspec ignored on explicit specialization

The __declspec attribute construct (an extension accepted in Microsoft mode)
was incorrectly ignored on some explicit specializations.  For example:

  template<typename T> void f();
  template<> __declspec(nothrow) void f<int>();  // The __declspec attribute
                                                 // was previously ignored.

This is now fixed.

11/3/04  Microsoft compatibility: __declspec(align(...)) incorrectly ignored

In Microsoft mode the __declspec(align(...)) construct was incorrectly
ignored on class types, unless the front end was also configured with
GNU_EXTENSIONS_ALLOWED set to TRUE.  For example:

  __declspec(align(16)) struct S {  // sizeof(S) was 1 instead of 16 in
    char c;                         // Microsoft mode, unless the flag
  };                                // GNU_EXTENSIONS_ALLOWED was TRUE.

This is now fixed.

11/2/04  GNU and Microsoft compatibility: Extraneous qualification on
         namespace member declarations

In GNU and Microsoft C++ modes, the front end already accepted (with a
warning) namespace member declarations appearing in their parent namespace
with an extraneous qualifier.  For example:

  namespace N {
    void f();    // Okay in all modes.
    void N::f();  // Accepted with a warning in GNU and Microsoft modes.
  }               // (Otherwise a discretionary error.)

In Microsoft mode, this is now accepted only if the identifier was already
present in the namespace (i.e., without the first declaration of f in the
example above, an error would now be issued) and the diagnostic has been
reduced to a remark in that case.  This Microsoft extension is now also
accepted in nonstrict C++ modes.  These behaviors have also been extended
to file scope declarations.  For example:

  void f();    // Okay in all modes.
  void ::f();  // Accepted with a remark in nonstrict modes, but non-GNU
               // modes will issue an error if no ::f is visible yet.

Finally, in GNU C++ mode, namespace-qualified friend declarations of members
in the innermost enclosing namespace are now treated as unqualified friend
declarations.  For example:

  struct S {
    friend int ::f();  // Accepted in GNU C++ mode (same as "friend int f()";
  };                   // an error in all other modes.

(See also: Changes entry of 11/3/03.)

11/02/04 Spurious error on call of base class destructor

A spurious error was issued on a call of a base class destructor when
a class has multiple base classes that are instances of the same class
template.  Now fixed.

template<int N> struct A : A<N-1> {
  A() {
    this->A<N-1>::~A<N-1>();
  }
};
template <> struct A<0> {};
A<2> a2;


11/02/04 GNU C++ compatibility: friend class lookup

When looking up an unqualified name in a friend class declaration, g++
does not stop at the nearest enclosing namespace scope as required by
the C++ standard.  We now emulate this behavior in g++ mode.

  struct A {};
  namespace N {
    struct B {
      friend struct A;
    };
    A a;  // Accepted in g++ mode ("A" is incomplete in default mode)
  }

11/01/04 Microsoft compatibility: abort in strip_local_and_nonreal_typedefs

An abort (in strip_local_and_nonreal_typedefs) could occur in Microsoft
mode on a reference to a member class template of a class template, when
the reference makes use of a default argument of the member class template.
Now fixed.

  template <class T> struct A {
    template <class U, class U2=void> struct B { typedef int Z; };
    typename B<T>::Z z;
  };

10/29/04 Diagnostics for potential 64-bit portability problems

We've added three new diagnostics that may help with 64-bit
portability problems.  All are turned off by default; they have
to be enabled with --diag_warning or the like to be seen.

  ec_impl_narrowing_64_bit_int: "implicit conversion of a 64-bit integral
    type to a smaller integral type (potential portability problem)"
  ec_expl_narrowing_64_bit_int: "explicit conversion of a 64-bit integral
    type to a smaller integral type (potential portability problem)"
  ec_pointer_conversion_to_same_size_int: "conversion from pointer to
    same-sized integral type (potential portability problem)"

10/28/04 Workaround for incorrect setting of LDBL_MANT_DIG

The GNU header files for Intel Solaris (through gcc version 3.2) provide
incorrect values for the long double macros in float.h (e.g., LDBL_MANT_DIG).
When the front end is built with a version of gcc that suffers from this
problem, some of the long double operations in float_pt.c do not work properly.
Our basics.h header will now detect the use the flawed gcc headers and
automatically redefine the LDBL... macros to the correct values.

10/28/04 Detecting invalid setting of long double configuration

The assertion checks in float_pt.c have been made more robust to detect
cases where LDBL_MANT_DIG is set to a size that is inconsistent with
the setting of targ_sizeof_long_double.

10/27/04 address_taken flag not set on variable passed to runtime zeroing
         routine

IL lowering failed to set the address_taken flag on a temporary variable
whose address is passed to the runtime zeroing routine.  This came up
for casts to some class types with a "()" argument list.  Now fixed.

  struct A {};
  A f() {
    return A();
  }

10/27/04 printf/scanf format string checking: "l" means wide characters

The checking of the printf/scanf format string now understands the
C99 addition that an "l" length specifier applied to "c", "s", or
a scanset means the underlying characters are wide (i.e., wchar_t).

  #include <stddef.h>
  #include <stdio.h>
  int main() {
    wchar_t x[] = L"abc";
    printf("%ls\n", x);  // No warning now
  }

10/26/04 Sun compatibility: Link scope specifiers

When the new configuration flag SUN_EXTENSIONS_ALLOWED is set to TRUE, the
front end now accepts link scope specifiers in Sun mode.  These specifiers
(__global, __symbolic, and __hidden) can appear on variable and function
declarations when they have external linkage.  For example:

  __hidden int x;
  __symbolic void f() {}

The C- and C++-generating back ends will render the new specifiers when
generating code for a Sun compiler, which is indicated by setting the new
configuration flag SUN_IS_GENERATED_CODE_TARGET to TRUE.

10/26/04 Embedded C: Conversion of negative fixed-point value to unsigned int

A diagnostic is now issued on a compile-time conversion of a negative
fixed-point value to an unsigned integer type.

  unsigned long long l = -1.0k;

10/26/04 Microsoft compatibility: __declspec and field declarations

The front end previously silently ignored most __declspec specifiers on field
declarations.  Now errors are issued for such specifiers if the Microsoft
compiler also issues an error on them; otherwise, a warning is issued.
For example:

  struct S {
    __declspec(selectany) int i;  // Error: Invalid specifier.
  };

10/25/04 Embedded C: Incorrect conversion of negative float to fixed-point

The compile-time conversion of float (but not double or long double) to
fixed-point resulted in an incorrect value.  Now fixed.

  _Accum f = -20.0F;

10/25/04 Buffer overrun in call of strchr on Windows

When __MICROSOFT_OS__ is TRUE (on Windows or MS-DOS), strchr is called
(from append_to_path_name) with an argument that is not null-terminated.
This causes strchr to read past the end of the string and can result in an
abort.  Now fixed.

10/25/04 Microsoft compatibility: parameter attribute parsing ambiguity

When parsing a function declaration in which a parameter has function
type, there is an ambiguity between a parameter attribute and an array
bound.  In discussions with Microsoft it was decided that this ambiguity
would be resolved by treating a "[" as an array bound if it occurs in a
context in which an abstract declarator is allowed, and as the start of
an attribute in contexts where an abstract declarator is not allowed.
The front end now implements this rule.

  void f(int ([5])){}
  void f2(int ([in] p)){}  // not allowed

10/25/04 Microsoft and GNU compatibility: x.y constant when x is a reference

In Microsoft and GNU C++ compatibility modes, the front end now accepts
expressions of the form x.y, where x is a reference to class and y is
a constant (e.g., an enumerator), in constant expression contexts.
This is an extension beyond what the C++ standard allows.

  struct A {
    enum {LENGTH = 1};
  };
  void f(const A& a) {
    int aa[a.LENGTH];  // Now accepted
  }

Also, the simpler versions of this extension, x.y where x has a class
type and p->y where p has a pointer-to-class type, are now also enabled
in g++ mode.  (See Changes entry of 2/5/00.)

10/25/04 C++-generating back end: Microsoft compatibility for inherited
         enumeration constants

MSVC++ version 6.0 had a bug such that the names of enumeration constants
declared in base classes were not visible in default arguments in friend
declarations.  The C++-generating back end formerly generated unqualified
names in this context but will now qualify such names if
msvc_is_generated_code_target is TRUE and msvc_target_version_number < 1300.
For example:

  struct B {
    enum T { T0, T1 };
  };
  struct D: B {
    friend void f(T t = B::T1);  /* Formerly generated as T1, now as B::T1
                                    when generating code for MSVC++ 6.0 */
  };

10/23/04 Macro SUPPRESS_MICROSOFT_KEYWORDS_IN_GENERATED_CODE eliminated

The macro SUPPRESS_MICROSOFT_KEYWORDS_IN_GENERATED_CODE is no longer used to
determine whether certain Microsoft-specific constructs should be emitted by
the C- and C++-generating back ends.  Instead, such constructs are emitted
when microsoft_dialect_is_generated_code_target is TRUE.

10/21/04 GNU compatibility: interaction of --restrict and --gcc/--g++

When the --restrict or --c99 option was used in conjunction with the --gcc
option, only the "__restrict" keyword (not the "restrict" form) was accepted.
Likewise, when --restrict was combined with --g++, only the "__restrict"
form was accepted.  In such cases, both "restrict" and "__restrict" should
be accepted.  This is now done correctly.

10/21/04 Microsoft/GNU C++ compatibility: spurious error on static
         data member initialization

Version 3.2 introduced a problem that resulted in a spurious error in Microsoft
and g++ modes if a static data member was initialized using a parenthesized
initializer, and the initializer used the name of the static data member.
Now fixed.

  struct A {
    static int* i;
  };
  int* A::i(A::i);

10/15/04 Spurious error on template friend declaration

A spurious error could occur when a template friend declaration in a
class template refers to a non-existent member of another class
template.  Such declarations should be accepted because the member
referred to in the friend declaration might exist in a specialization
of the other class template.  Now fixed.

  template <class T> struct A {};
  template <class T, class U> struct B {
    template <class TT> friend int A<T>::f();
  };

10/14/04 GNU C++ mode: "format" attribute handled incorrectly on member calls

In GNU C++ mode, the front end did not correctly check the arguments of calls
to member functions with the "format" attribute.  This could lead to spurious
warnings on such calls.  For example:

  struct S {
    void f(char const *fmt, ...) __attribute__((format(printf, 2, 3)));
  };
  void f(S &s) {
    s.f("%s %d", "x", 3);  // Triggered spurious warning.
  }

This is now fixed.

10/14/04 Member function qualifiers displayed by db_symbol_name

db_symbol_name, which is used for things like instantiation debug output,
now displays the qualifiers associated with member functions.

10/13/04 Embedded C: error on pointer difference with incompatible named
         address spaces

An error is now issued on a pointer difference operation on pointers
to entities in different named address spaces if the named address
spaces do not overlap.

  void f() {
    char* pa;
    _EDG_NAS_C char* pb;
    int x;
    x = pb - pa;  // Now gets an error
  }

10/13/04 IL display of param_type default argument information

The IL display program now displays the has_default_arg,
has_unevaluated_template_default, and default_being_instantiated fields
of the param_type entry if they are set.

10/13/04 Microsoft compatibility: lookup of nontype names in base classes

The Microsoft compatibility issue described in the Changes entry of
1/8/01 is fixed in MSVC++ 7.1.  Therefore, we no longer emulate it
when microsoft_version >= 1310.

10/13/04 __asm functions and one-instantiation-per-object mode

The duplicate_static_in_instantiation_slices flag is now set in __asm
functions when one-instantiation-per-object mode is used.  This
indicates that a copy of the __asm function body should be put
in each instantiation slice that references it, which makes sense
because __asm functions are effectively inline.  The C-generating
back end has also been changed to handle that.  Back ends that
copied the logic in dump_routine_decl in c_gen_be.c should be
updated similarly to test the storage class against sc_asm.
(See also the Changes entry of 5/19/04.)

10/13/04 Embedded C: Spurious error on block-extern named-register declaration

In Embedded C mode (and any other modes accepting named-register storage class
specifiers) the front end used to emit an error if a named-register variable
was declared in block scope while another declaration of the same variable had
already been seen.  For example:

  register _EDG_REG_1 char x;
  void f() {
    register _EDG_REG_1 char x;  /* Previously an error; now accepted as  */
  }                              /* referring to the file scope variable. */

This is now fixed.

10/13/04 Microsoft compatibility: _NATIVE_WCHAR_T_DEFINED

The macro _NATIVE_WCHAR_T_DEFINED is now defined in Microsoft mode
when microsoft_version is >= 1300.

10/13/04 Embedded C: Named-register variables of void type

In Embedded C mode (and any other modes accepting named-register storage
class specifiers) an error is now issued if a named-register variable is
declared to be of a void type, even if in a block-extern declaration.
For example:

  void f() {
    register _EDG_REG_1 void x;  // Previously accepted.  Now an error.
  }

10/13/04 Microsoft compatibility: Implicit calling conventions

In Microsoft mode, the default calling convention is normally "__cdecl"
(determined by the global variable default_calling_convention).  However,
the global entry point functions "WinMain" and "wWinMain" are treated by
Microsoft compilers as having "__stdcall" calling convention by default.
The front end now emulates this behavior by recording the "__stdcall"
convention in the IL entry of "WinMain" and "wWinMain", unless a calling
convention was specified explicitly in the source.

  void WinMain();              // "Default calling convention" is "__stdcall".
  void __stdcall WinMain() {}  // Previously a redeclaration error; now
                               // accepted.

In addition, a change was made to record any calling convention explicitly
specified on the standard "main" entry point.  Previously, calling convention
specifiers were silently ignored and replaced by "__cdecl" in all cases.
For example:

  int __stdcall main() {  // Previously treated as "int __cdecl main() ...".
    return 0;
  }

10/13/04 GNU compatibility: undefining predefined macros

The GNU compilers allow a predefined macro to be undefined.  We now allow
such undefinitions in gcc and g++ modes.

  #undef __EDG__
  #ifdef __EDG__
  #error __EDG__ is defined
  #endif

10/13/04 Unrecognized pragmas scanned as pp-tokens

When INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL is TRUE, the front end previously
scanned unrecognized pragmas as plain tokens.  This could lead to unexpected
errors in some cases.  For example:

  #pragma UNKNOWN 009  // Previously an error ("009" is not a valid octal
                       // number); now accepted by default.

Now unrecognized pragmas are scanned as pp-tokens instead, which makes
constructs like these acceptable.  (See also Changes entry of 6/29/04.)

10/12/04 C++-generating back end: Microsoft extensions in class template
         instantiation directives

Microsoft declaration specifiers (__declspec, etc.) were lost in template
instantiation directives, and namespace qualifiers were lost in Microsoft
"extern template" declarations.  For example:

  namespace N {
    template <typename T> class X { };
    template <typename T> class Y { };
  }
  template class __declspec(dllimport) N::X<int>;
  extern template class __declspec(dllimport) N::Y<char>;

The last two lines were formerly generated as:

  template class N::X< int> ;  // missing "__declspec(dllimport)"
  extern template class __declspec( dllimport ) Y< char> ;  // missing "N::"

Now fixed.

10/12/04 Error message formatting of function fill-ins

The formatting of function names in error messages was not correct for
functions with complex return types.  This has been fixed.  As part of
this change, function template signatures are included as part of the
function name in more cases.

  template <class T> void (T::*f(void)) (void);
  template <class T> void (T::*f(void)) (T *);
  struct A {};
  int main() {
    f<A>();
  }

10/11/04 Spurious correspondence error on duplicate weak definitions

The front end previously issued an error on duplicate definitions even when
one of those definitions was marked as "weak" (currently a feature only
available in GNU modes).  For example:

  // File 1:
  __attribute__((weak)) void f() {}

  // File 2:
  void f() {}  // Should displace definition in File 1; not an error.

This is now fixed.

10/11/04 Embedded C: specifying the largest possible _Accum values

Formerly, to specify the saturated value for a non-saturating _Accum type
you would need to know the exact saturated value (e.g., 65535.999969...).
The integral value just beyond the largest value for a given _Accum
type is now accepted and results in the saturated value for the given
_Accum type.

  _Accum a = 65536.0k;  // Now accepted

10/11/04 C-generating back end: GNU local labels

The C-generating back end does not emit unused labels.  This could trigger
warnings or errors when code generated by the C-generating back end was
compiled by a GNU compiler.  For example:

  void f() {
    __label__ t;
    t: return;  // Unused label "t"
  }

was rendered as (except for comments and other whitespace):

  void f() {
    __label__ t;  // Declaration of "t" not mentioned appearing as a label
    return;       // triggered diagnostic.
  }

This is now fixed (the __label__ declaration is also dropped if the label is
unused).

10/11/04 GNU compatibility: __builtin_snprintf and __builtin_vsnprintf

In GNU mode, the type of the second parameter of the built-in functions
__builtin_snprintf and __builtin_vsnprintf was changed from always being
"unsigned int" to "size_t" (which is "unsigned int" on many platforms).

10/11/04 Module IDs: "weak" and "selectany" definitions

The front end no longer considers variables and functions marked as "weak"
when constructing unique module IDs: "Weak" entities may be defined in
multiple translation units and are therefore not unique.  (Currently,
"weak" variables and functions are only recorded in configurations with
GNU_EXTENSIONS_ALLOWED set to TRUE.)  Similarly, variables defined with the
Microsoft "selectany" modifier are no longer used to construct module IDs.

10/11/04 Tweak for alloc_intercept debug function

The alloc_intercept function (which can be useful to determine when a certain
IL entry or symbol is allocated) was tweaked to produce better output in
environments with pointers types larger than the unsigned int type.

10/8/04  GNU compatibility: Register asm names for nonregister variables

In configurations with ACCEPT_UNRECOGNIZED_GNU_ASM_OPERANDS set to FALSE,
the front end now issues an error if a nonregister variable is annotated
with an asm name that refers to a register.  For example:

  int x asm("al");  // Error when GNU_X86_ASM_EXTENSIONS_ALLOWED is TRUE
                    // since "al" is a register name in such configurations.

(Note that the error is not issued if gnu_version < 30000 because early
versions of the GNU compilers did not diagnose such situations.)

10/8/04  Enumerator constants incorrectly marked as being "a simple zero"

The IL entry type a_constant has a field "is_simple_zero" that indicates the
constant is associated with a source token that is a plain "0".  This flag
was sometimes set for enumerator constants (and sometimes even for nonzero
enumerator constants).  For example:

  enum E { e1 = 0, e2 };  // The IL entries representing e1 and e2 were both
                          // flagged "simple zeros".  The flag is now FALSE
                          // for both entries.

This is now fixed (enumerator constants always have the flag set to FALSE).

10/7/04  GNU compatibility: Arrays of abstract classes as parameter types

In GNU C++ mode, the front end now accepts function parameter types that are
declared as arrays of abstract class types.  (Previously an error was issued.)
For example:

  struct S { virtual void f() = 0; };
  void g(S a[]);  // Now accepted in GNU C++ mode.  (Still an error in
                  // other modes.)

10/7/04  Microsoft compatibility: overload resolution tiebreakers,
         array decay to pointer

A further tweak to the overload resolution tiebreaker rules (see
previous Changes entries on 8/15/02 and 6/3/02): the handling
of lvalue-to-rvalue conversions (which includes array --> pointer
decay) in tiebreakers has been adjusted to more closely match
MSVC++, and the behavior of the earlier changes (cited above)
has been adjusted for --microsoft_version=1200.

  typedef long wchar_t;
  template <class T> struct U {
    template<typename V> U(const V& p ) { p->QueryInterface(); }
    U (const wchar_t*) { } // intended constructor
  };
  struct Foo { };
  typedef U<Foo> UF;
  void func() {
    UF uf = UF(L"abcd");  // Formerly got error in microsoft_version=1200
                          // and 1300 (wrong constructor chosen).  Now
                          // accepted.
  }

10/7/04  GNU compatibility: __builtin_classify_type and __builtin_constant_p

In addition to being constant-folded, calls to the GNU built-in functions
__builtin_classify_type and __builtin_constant_p are now parsed differently
from other function calls.  In particular, an argument to such a call does
not undergo the usual transformations for function call arguments (like
promotion and array-to-pointer decay), nor is such an argument evaluated.
In addition, the value produced by __builtin_classify_type is now dependent
on the value of gnu_version to reflect changes made in the GNU compilers.
The following example illustrates some consequences of this change:

  #include <stdio.h>
  int a = __builtin_classify_type("a");  // Returns the code for "array type"
                                         // in GNU C++ 3.4 mode.  Previously,
                                         // array-to-pointer decay always
                                         // resulted in the code for "pointer
                                         // type".
  int b = __builtin_constant_p(printf("b"));  // Now accepted in GNU C mode.
                                              // printf is not called.

Note that these pseudo-functions remain visible as ordinary functions with an
ellipsis parameter (which means, for example, that their address can be taken).
The GNU compilers accept any number of arguments to calls of these functions,
but the front end currently issues an error if there is not exactly one
argument (which is the only meaningful case).  (See also the changes entry of
11/19/03.)

10/6/04  Embedded C: negation of unsigned fixed-point value

When a negative value is converted to an unsigned fixed-point type, the
result should be zero.  Formerly, when such a conversion was done the
result was the absolute value of the input.

  unsigned _Accum a = -(unsigned _Accum)1;

10/5/04  Syntax error on [] after new in strict mode

An expression like 

  new (double)[17];

should get a syntax error, because a new-expression is a unary-expression
and the subscript operator must follow a postfix-expression.
A syntax error is now issued, but only in strict mode. 

10/5/04  IA-64 ABI: Wrong type on constant in lowered IL for dynamic_cast

The code generated by IL lowering in the IA-64 ABI for a dynamic_cast
to a reference type included a null pointer constant with the wrong
type under a pointer != (eok_pne) operation.  Now fixed.

  struct A {
    virtual void foo();
  };
  struct B : A {};
  void bar(A& a) {
    B& b = dynamic_cast<B&>(a);
  }

10/5/04  Microsoft compatibility: tweak on reference binding and lvalues

A further tweak on the Microsoft-mode rules for binding references
to non-const to rvalues and different microsoft_version values.
It appears a deduced reference to non-const is allowed to bind to "this"
in all MSVC++ versions through 7.1 even though "this" is an rvalue.
Formerly, this was based on whether the argument is constant for
MSVC++ 7.0 and beyond.

  template<class T> void g(T&);
  struct X {
    void f() {
      X *p;
      g(p+0);    // Error, MSVC++ 6.0, 7.0, and 7.1
      g(this);   // Accepted by MSVC++ 6.0, 7.0, and 7.1
    }
  };

10/5/04  Embedded C: warning on named-address-space mismatch on old-style
         parameter

A warning is now issued on a named-address-space mismatch on a call
that passes a pointer to an old-style parameter of pointer type, if
the two pointer types have different named address spaces.

  typedef _EDG_NAS_B char* T1;
  typedef _EDG_NAS_A const char* const T2;
  void f(p)
  T1 p;
  {
    T2 s = 0;
    f(s);  // Warning now
  }

10/5/04  C++-generating back end: injected names of class template instances

The C++-generating back end was recently changed to generate code as if the
name of a class template instance were injected into the class and thus
capable of hiding names from the surrounding context, even though such names
are not injected in Microsoft mode.  (See the Changes entry of 9/21/04.)  In
certain cases, the resulting code triggered a bug in Microsoft compilers
prior to version 7.1.  For example:

  template<typename T> struct X { };
  template<typename T>struct Outer { };
  template<> struct Outer<int> {
    struct X { };
    struct inner: ::X<int> {
      inner(const X& s) { }                        // #1
      friend inline X f(const X& x) { return x; }  // #2
    };
  };

In Microsoft mode, the X's in lines #1 and #2 refer to Outer<int>::X rather
than to the base class ::X<int> of Outer<int>::inner.  If the generated code
uses a qualified name, however, MSVC++ 7.0 reports an error on line #2 and
MSVC++ 6.0 reports errors on both lines.  Now the C++-generating back end
will use unqualified names in such cases when generating code for a
Microsoft compiler (i.e., when msvc_is_generated_code_target is TRUE), as it
did before the above-mentioned change.

10/4/04  GNU mode: --gnu_version option

In order to permit the front end to correctly emulate GNU features that vary
between versions of the GNU compilers, a command line option has been added
to specify the version of the GNU compiler that should be emulated.  The new
option is "--gnu_version" and must be followed by a version number computed
as x*10000+y*100+z where x.y.z is the version of the GNU compiler to emulate.
(For example, "--g++ --gnu_version 30401" indicates that the front end should
emulate g++ version 3.4.1.)  The default version to emulate can be configured
by setting the macro DEFAULT_GNU_VERSION (30300 by default at this time).
The various GNU emulation features already implemented in the front end have
been reviewed and where needed they have been made dependent on the value of
gnu_version.  (In some cases where not all versions of gcc or g++ support a
particular GNU feature, it was decided not to make the feature dependent
on gnu_version because the feature is a pure extension potentially useful
in all GNU modes.)

10/4/04  __WCHAR_TYPE__ defined by default on Linux

The __WCHAR_TYPE__ macro is now defined (to "long int") by default on
Linux systems.  This is needed for the Linux header files to work
properly in C mode.

10/1/04  Warning instead of error on fixed-point folding overflow

Overflow during folding of constant fixed-point operations is now
diagnosed with a warning rather than an error, except in strict
errors mode.

  _Sat _Fract f1 = 0.6r + 0.6r;

9/30/04  Internal error on type declared in parameter of class template member

Under some circumstances, an IL write-read error was triggered when a class
was only declared in a parameter declaration of a member function of a class
template.  For example:

  template<typename T> struct S {
    void f(class C*) {}  // Only declaration of C could trigger an internal
  };                     // IL write-read error.

Slightly inconsistent IL was generated when GENERATE_SOURCE_SEQUENCE_LISTS and
PROTOTYPE_INSTANTIATIONS_IN_IL were set to TRUE, but the internal error only
manifested itself when IL_SHOULD_BE_WRITTEN_TO_FILE was also TRUE.  This is
now fixed.

9/30/04  Embedded C: fixed-point rounding change

If a fixed-point value falls half way between the two closest representable
values, the front end would round it to the representation in which the
last bit is zero.  This has been changed to always round up, so that values
folded at compile time would match values computed at runtime by the
Dinkumware library routines.

9/30/04  C++-generating back end: typedef members of instances of class
         templates

Wherever a typedef member of an instance of a class template was used, the
C++-generating back end inserted the underlying type rather than the typedef
name in the generated code.  Such typedef names are now treated the same as
typedef members of ordinary classes, i.e., they will be used if accessible.
For example:

  template <typename T> struct S {
    typedef T* ptr;
  };
  S<int>::ptr sip;   // Formerly generated as "int *sip;", now preserves
                     // the original source form.

9/27/04  enk_result_of_overriding_function in void IA-64 thunk

The code generated by IL lowering for a thunk with a void return
type (possible only in the IA-64 ABI) had a return statement
with an expression that consisted of an enk_result_of_overriding_function
node.  This is strange, since ordinarily void functions have return
statements without an expression.  This has been changed so that
the enk_result_of_overriding_function is placed in a separate
expression statement preceding the (now expression-less) return.
IL CHANGE: this may require changes in back ends.

9/27/04  Warning on negation of an unsigned fixed-point value

A warning is now issued on a unary "-" operator applied to an unsigned
fixed-point value.

  unsigned _Fract f = -1.0ur;

9/27/04  Expression traversal routines and RECORD_CONSTANT_EXPRESSIONS_IN_IL

The expression traversal routines (traverse_expr et al.) now have an
additional flag process_expressions_for_constants which is present
when RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE.  The flag indicates
that, for constants generated from a constant expression, the
original expression should be traversed instead of the resulting
constant.  For source-analysis applications, this yields a
traversal closer to the original source form.

9/27/04  g++ mode: error on typeof of overloaded function name

An error is now issued on a use of typeof applied to an overloaded
function name in g++ mode.  Formerly, the failure to detect the
error resulted in an assertion failure in mangled_encoding_for_type
in lower_name.c.

  double f(double);
  float f(float);
  void h(typeof(f) g) {}

9/25/04 C++-generating back end: unneeded qualification of base class names

The C++-generating back end formerly generated qualified names to refer to
members of base classes whether the qualification was needed or not.  It now
generates unqualified names when the qualification is not needed.  For
example:

  struct Outer1 {
    struct Inner1 { };
  };
  struct Outer2 {
    struct Inner2: public Outer1 {
      Inner1 f() { return Inner1(); } // Previously generated "Outer1::Inner1"
                                      // for both names, now just "Inner1"
    };
  };

9/23/04  Microsoft compatibility: friend virtual

In Microsoft modes, the front end now accepts "friend virtual" with a warning.
The keyword "virtual" is otherwise ignored.  For example:

  struct F { void f(); };
  struct S {
    friend virtual void F::f();  // Accepted with a warning in Microsoft mode.
  };

9/23/04  Embedded C: incorrect comparison folding of mixed operations

Compile-time folding of fixed-point comparison operations in which the
operands have different fixed-point types could produce incorrect results.
Now fixed.

  int main() {
    int i;
    i = 1.0k > .5lr;
  }

9/21/04  C++-generating back end: injected class names in Microsoft mode

In Microsoft compilers prior to version 7.0, an injected class name was
visible only when used as a qualifier (see Changes entries of 11/17/99 and
3/4/03).  The C++-generating back end formerly generated code in Microsoft
mode assuming that this nonstandard treatment of injected class names was in
effect.  It has now been updated so that this assumption applies only if
msvc_target_version_number is < 1300.  For example:

  struct B { };
  struct O {
    struct B {
    };
    struct D: ::B {
      O::B b;    // Formerly generated as "B b;" for all Microsoft versions,
                 // now as "O::B b;" for Microsoft versions 7.0 and later
    };
  };

Microsoft compilers through version 7.1 continue not to inject the name of
a class template instance.  As a result, the C++-generating back end used
unqualified names to refer to entities that would otherwise have been
hidden by the injected name.  In order to facilitate generating code for
different dialects when parsing in Microsoft mode, the C++ generating back
end now qualifies such names, as if the class template name had been injected.
For instance:

  template<typename T> struct iterator { };
  struct vec {
  public:
    struct iterator: public ::iterator<bool> { }; 
    struct const_iterator: public ::iterator<bool> {
      const_iterator(vec::iterator x) { }  // Formerly generated as "iterator",
                                           // now as "vec::iterator"
    };
  }; 

9/20/04  Microsoft compatibility: missing in-class specialization definition

Version 3.4 introduced a regression in the processing of in-class function
specializations that could cause linker errors and/or prelinker loops
when microsoft_version is 1200 or below.  Now fixed.

  template <class T> struct A {
    template <typename U> A<T>& operator=(const U&) { return *this; }
    template<> A<T>& operator=(const A<T>&) { return *this; }
  };
  int main() {
    A<int> a;
    a = a;
  }

9/20/04  Microsoft compatibility: For-init scope

MSVC++ 7.0 and earlier always use a nonstandard for-init scope.  I.e.,
variables declared in a for-init construct are visible after the end of
the "for" statement.  MSVC++ 7.1 has made this behavior dependent on
whether the type of a variable has a nontrivial destructor: If it does,
the standard scoping rules apply; otherwise, the nonstandard rules of
previous MSVC++ versions apply.  For example:

  struct S { S(); ~S(); };
  void f() {
    for (S *p, s; false;) {}
    // In Microsoft mode with microsoft_version == 1310, p is visible
    // here, but s (which has a destructor) is not.
  }

The front end has been updated to match the behavior of the MSVC++ 7.1
compiler when microsoft_version >= 1310, unless the --old_for_init or
--new_for_init options are specified.

9/17/04  Incorrect access error on Microsoft property field with protected
         underlying function

The front end incorrectly gave an access error on a use of a Microsoft
property field when the underlying access function is protected and
the access is from a derived class (which should be okay).  Now fixed.

9/16/04  Microsoft property fields did not work right in templates

Microsoft fields declared with __declspec(property) did not work
right when the field declaration is in a template.  Now fixed.

  template <class T> class A {
  public:
    int  GetSize() {return 0;}
    void SetSize(int){}
    __declspec(property(get=GetSize,put=SetSize)) int Size;
    void    IncSize(int i=1) { Size=Size+i; }
  };
  A<int> a;
  void v() {
    a.IncSize();
 }

9/16/04  Abort on output of GNU address-of-label cast to integral type

The il_to_str routines aborted ("type_pointed_to: not a pointer type")
when trying to output a GNU address-of-label (e.g., &&L) that has been
cast to another type (e.g., an integral type).  There was a potential
similar problem with Microsoft __uuidof constants, though we
were unable to find a test case that aborted.  Both cases now fixed.

  int main() {
    int unsigned long i;
  L:
    i = (unsigned long)&&L;
  }

9/15/04  IA-64 ABI: static typeinfo name string should be COMDAT

In the IA-64 ABI, the variable that contains the name of a typeinfo
variable should be a COMDAT even if the typeinfo variable itself
is static.  Now fixed.

9/15/04  Incorrect name mangling for nested unnamed struct

The front end sometimes generated the same mangled name for two
different unnamed structs that are nested classes.  The problem
cases are those where the struct is used as an array element or
type pointed to, instead of directly as the type of a field.
Now fixed.

  struct needs_ct {
    needs_ct();
  };
  struct foo {
    foo();
    struct {
      needs_ct x;
    } mem1;
    struct {
      needs_ct y;
    } mem2[2];
  };
  foo::foo() { }


9/15/04  C++-generating back end: Abort on nonstandard GNU specialization

Nonstandard out-of-class member specializations (an extension accepted in some
GNU modes; see the Changes entry of 2/4/04) triggered an assertion failure in
the C++-generating back end.  This is now fixed.

9/14/04  GNU/Microsoft compatibility: explicit instantiation should override
         "extern template"

In g++ and Microsoft modes, an explicit instantiation directive now overrides
a previous "extern template" directive, causing the entity referred to by
the explicit instantiation directive to be instantiated.  Formerly, the
explicit instantiation had no effect for an entity referred to by an
earlier "extern template" directive.

  template<class T> struct A { A(); };
  template<class T> inline A<T>::A(){}
  extern template class A<int>;
  template class A<int>;
  int main() {
    A<int> f;
  }
 
9/14/04  Instantiation of inline function should cause body to be emitted

When an inline function is explicitly instantiated in a configuration in
which inline functions are emitted as external entities, the body of the
inline function should be emitted even if it is not referenced.  Inline
functions that are explicitly instantiated are now emitted when
INSTANTIATE_EXTERN_INLINE is TRUE and also when using the IA-64 ABI.

  template<class T> struct A { A(); };
  template<class T> inline A<T>::A(){}
  template class A<int>;

9/10/04  Microsoft compatibility: Spurious error on friend declaration

In Microsoft mode, a spurious error could be issued on a friend declaration
in a class template.  The error would occur if a class template contained
a nested class with the same name as a class template from the enclosing
namespace scope.  This problem was introduced in version 3.4 and is
now fixed.

  namespace N {
    template <class T> struct A { };
    template <class T> struct B {
      class A;
      class C {
        friend class A;
        C () {}
      };
      struct A { C f() { return C(); } };
    };
  }
  template class N::B<bool>;

9/10/04  Spurious setting of defined_in_friend_decl flag

In Microsoft mode, the IL entry for an in-class specialization of a member
function template sometimes had its defined_in_friend_decl flag set (which
cannot be correct since in-class specializations cannot be friend definitions).
This is now fixed.

9/19/04  Embedded C: Incorrect results on little-endian systems using
         simulated integers

Conversions of values to and from fixed-point did not work properly on
little-endian systems when INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is FALSE.
Now fixed.

  _Accum a = 1;

9/10/04  C++-generating back end: missing parentheses around comma expression

The C++-generating back end failed to put a set of parentheses around
a comma expression when it is the sole expression in a C99 compound
literal of a non-aggregate type.  The resulting code would not
compile correctly.  Now fixed.

  int main() {
    int i = 1;
    int j = (int){(i, i)};
  }

9/9/04   Embedded C: Named address space qualifiers and "?" operator

The processing for the "?" operator on pointers did not correctly
handle named address space qualifiers (from Embedded C) on the
underlying type.  It simply or'ed the bits together, which is very
wrong for the named address space qualifier, which is a number not
a bit set.  Now fixed.

  void f() {
    _EDG_NAS_A char* pa;
    _EDG_NAS_B char* pb;
    int x;
    pa = x ? pa : pb;
  }

9/8/04   Embedded C: incorrect result when fixed-point rounding produces
         overflow

An incorrect result was produced if the rounding of a fixed-point value
to the nearest representable value for the destination type resulted
in an overflow.  Now fixed.

  int main() {
    // These assignments produced incorrect values.
    unsigned short _Fract f = 1.0r;
    _Accum a = (_Accum)65535.9999847uk;
  }

9/8/04   C++-generating back end: Microsoft compilers and qualifiers on
         virtual base class initializers

MSVC++ 6.0 issues errors when the initializer for a virtual base class is
specified using a qualified name.  The C++-generating back end has been
modified to use unqualified names for virtual base classes in constructor
initializer lists when generating code for MSVC++ 6.0 and earlier.  For
example,

  namespace N {
    struct S { };
  }
  struct T: virtual N::S {
    T(): N::S() { }  // Now generates "T(): S() { }" for MSVC++ 6.0
  };

9/8/04   Abort when preprocessing directive appears between an identifier
         and a "<"

An abort could occur while caching or flushing tokens if an identifier
and a "<" are separated by a preprocessing directive.  Now fixed.

  int x z
  # define X x 
  <T> 

9/8/04   Warning eliminated on division by zero in unevaluated code

A warning is no longer issued for a division by zero in a context
like the following:

  int main() {
    0 && (14/0) ? 14/0 : 0;
  }

Note that the nesting of two short-circuiting operators and two
divisions by zero was necessary to get the warning.  Simpler cases
did not get a warning.  Also, configurations with
ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS set to TRUE did
not get the warning even on the complex cases.

This was fixed by adding a rather large bit of functionality for
such a small issue: the expression-processing routines now keep
track, as they build up an expression, of whether the expression
contains any operations that rule out an integral constant
expression or a constant expression.  This is used in this
case to force folding of constant expressions even when they
don't look constant in the IL, as in the above, but it has
potential utility for a number of other issues in the future.

9/7/04   Microsoft compatibility: Spurious correspondence error on in-class
         specializations

In Microsoft mode, when compiling multiple translation units simultaneously,
the front end sometimes issued a spurious incompatibility error on class
templates containing an in-class specialization of a member function template.
(In-class specializations are a Microsoft extension.)  For example:

  // File header.h
  template<typename T> struct S {
    template<typename U> static  void f() {}
     template<> static  void f<void>() {}  // In-class specialization.
  };
  template<typename T> struct C {
    C() { S<T>::f<T>(); }
  };

  // File g1.cpp:
  #include "header.h"
  void g1() { C<void> c; }

  // File g2.cpp:
  #include "header.h"
  void g2() { C<void> c; }

When files g1.cpp and g2.cpp were compiled simultaneous in Microsoft mode,
an incompatibility error was previously issued for S<void>::f<void>().  This
is now fixed: The code is now accepted without errors.

9/3/04   Microsoft C++ compatibility: Type bool

MSVC++ 7.0 and earlier treated "bool" as a predeclared typedef in global scope
and the EDG front end emulated this behavior in all Microsoft C++ modes.
However, MSVC++ 7.1 fixed this by making "bool" a keyword.  The front end has
been adapted to restore the standard behavior when microsoft_version >= 1310.
For example:

  namespace N {
    typedef int *bool;  // Previously accepted in all Microsoft C++ modes.
  }                     // Now only accepted with microsoft_version < 1310.

9/2/04   Microsoft compatibility: Checking UUIDs across translation units

In Microsoft mode, when compiling multiple translation units simultaneously,
the front end previously always issued an error if a type appeared in two
different translation units with differing UUID specifications.  Now, no error
is issued if no specifier appears at all on one of the declarations.
For example:

  // File 1:
  struct __declspec(uuid("941bf074-8711-4417-9399-3e26297b0e4e")) ITraceMgr;

  // File 2:
  struct ITraceMgr;  // Previously an error.  Now okay.

This relaxation is possible because this sort of difference does not affect
the generated code.

9/2/04   C- and C++-generating back ends: UPC THREADS constants

The C- and C++-generating back ends did not consider the possibility that a
multiple of the UPC THREADS constant may appear next to operators of higher
precedence.  As a result, such multiples were rendered without the required
parentheses.  For example:

  void f(int x) {
    100/(2*THREADS);  // Previously incorrectly rendered as "100/2*THREADS".
  }

This is now fixed.

9/2/04   IL display of UPC forall statement

The IL display utility now displays UPC forall statements in a form distinct
from standard "for" statements.

9/1/04   C++-generating back end: qualified references to injected class
         names that are class template instances

Under some circumstances, the C++-generating back end used an unqualified
name when referring to an injected class name that is an instance of a
class template that is a member of a namespace.  Many compilers do not
accept this form of reference.  Now fixed.  For example:

  namespace N {
    template <typename T> struct S { }
  }
  struct X: public N::S<int> {
    X(): N::S<int>() { }    /* Formerly dropped "N::", now uses qualified
                               name */
  };
  using namespace N;

9/1/04   GNU/Microsoft compatibility: Flexible array member initializers

In Microsoft modes and in GNU C mode, the front end now accepts aggregate
initializers for flexible array members.  A variable entry with such an
initializer has its (new) flag has_flexible_array_initializer set to TRUE,
and the aggregate constant representing the portion of the initializer for
the flexible array member also has a flag flexible_array_initializer set
to TRUE (IL CHANGE).  For example:

  struct S {
    int n;
    int a[];  // Flexible array member.
  } s = { 1, { 2, 3, 4 } };  // Now accepted in GNU C and Microsoft modes.

In GNU C mode, the flexible array member must appear as a proper member of
the type being initialized.  In Microsoft C and C++ modes the flexible array
member may be an indirect member, but its elements cannot have a nontrivial
destructor.  For example (with struct S as above):

  struct X {
    struct S s;
  } x = { { 1, { 2, 3, 4 } } };  // Accepted in Microsoft modes, but not in
                                 // GNU C mode.

  struct D { D(int); ~D(); };
  struct E {
    int n;
    D d[];
  } e = { 1, { 2, 3, 4 } };  // Not accepted in any mode.

Note that initializers for flexible array members were sometimes already
accepted in Microsoft modes (see Changes entry of 4/11/95).  This support has
been extended to include indirect flexible array members and to mark the
variable and aggregate constant entries as explained above.

9/1/04   Incorrect IL for lowered lvalue "?" involving bit fields

The lowered code for a compound assignment to bool involving
a "?" operation and bit fields as the destination was not
correct, in that it left some eok_bit_field operations in
the tree in non-lvalue positions.  Now fixed.  A bug that
caused the first operand of the "?" not to be saved in a
temporary for reuse has also been corrected.

  struct A {
    bool b:1;
  } a[5];
  int f();
  int main() {
    int i = 1;
    (i ? a[f()].b : a[f()+1].b) += 3;  // Invalid IL previously; aborted
                                       // in C-generating back end
  }

9/1/04   C- and C++-generating back ends: GNU_TARGET_VERSION_NUMBER

When using the C- or C++-generating back end to generate code for a GNU
compiler, a new configuration macro GNU_TARGET_VERSION_NUMBER now determines
which specific version of the GNU compiler should be targeted.  If the front
end is built using a GNU compiler, the macro defaults to the version number
of the compiler used to build the front end; otherwise, the macro must be set
explicitly.

8/31/04  Microsoft compatibility: Abort on flexible array member

Under certain circumstances an internal error was triggered in "types.c"
during the lowering of flexible array members when the underlying type is
a class type with a nontrivial destructor.  For example:

  struct S { ~S(); };
  struct T { S s[]; };
  struct U { T t; };
  U u;  // Causes an abort during lowering in Microsoft C++ mode.

This is now fixed.

8/31/04  Microsoft compatibility/IA-64 ABI: Abort on flexible array member

Under certain circumstances an internal error was triggered in "types.c"
during the layout of a class containing a flexible array member.  The problem
only occurred in Microsoft C++ mode with IA-64 ABI layout class rules.
For example:

  class C {};
  struct S { C c[]; };
  struct X { S s; };    // Internal error during class layout in Microsoft C++
                        // mode with IA-64 ABI layout rules.

This is now fixed.

8/27/04  IL lowering for fixed-point types and operations

When LOWER_FIXED_POINT is TRUE, IL lowering now lowers fixed-point
types, constants, and operations to standard C.  The lowered code
calls runtime routines not supplied by EDG (they are available
from Dinkumware), so this feature is off by default.

8/26/04  Missing conversion on operand of fixed-point "?" operator

The IL generated for a "?" operator whose second and third operands
are integral and fixed-point (one of each) did not convert the
integral operand to the fixed-point result type.  Now fixed.

  void f() {
    int i = 0;
    _Fract x = i ? 0.5r : i;  // Implicit conversion on 3rd operand
                              // now present
  }

8/19/04  Microsoft compatibility: abort on in-class specialization when
         doing nonclass prototype instantiations

An abort (in push_template_instantiation_scope) could occur when
processing a Microsoft in-class specialization when doing nonclass
prototype instantiations.  The abort would occur if the specialization
contained a member function definition.  Now fixed.

  template <class T> class A {
    template <int I> struct B { };
    template <> struct B<1> {
       void f() {}
    };
  };

8/23/04  Embedded C: Named address space qualifiers on return types

When Embedded C extensions are enabled, the front end now issues an error on
a function whose return type is qualified with a named address space.
For example:

  int _EDG_NAS_A f();  // Now an error.

8/20/04  Microsoft and GNU C++ compatibility: Duplicate extern "C" definitions

In GNU C++ and Microsoft C++ modes, the front end normally does not attempt to
link two extern "C" declarations in different namespaces (see Changes entries
of 7/28/04 and 10/6/99).  A change was made to perform this linking in these
modes when the two declarations are both definitions.  As a consequence, a
duplicate definition error is issued in such circumstances.  For example:

  extern "C" void f() {}
  namespace N {
    extern "C" void f() {}  // Duplicate definition error issued by the front
  }                         // end, even in GNU and Microsoft modes.

8/20/04  Microsoft compatibility: dllimport/dllexport and threads

In Microsoft modes, the front end now issues an error for thread-local
variables declared with dllimport/dllexport (previously, such variable
declarations were silently accepted).  For example:

  __declspec(dllimport thread) int e;  // Now an error.

8/20/04  Spurious redeclaration error on member using-declaration or typedef

The front end sometimes issued a spurious redeclaration error when an inherited
member is first used and then referred to by a member using-declaration.  A
similar problem existed with a typedef that introduces a synonym for a base
class member of the same name.  For example:

  struct B {
    typedef int I;
  };
  struct D: B {
    I x;
    using B::I;  // Triggered a spurious error.  Now accepted.
  };

This is now fixed.

8/19/04  GNU mode: Empty attributes

In GNU C and C++ modes the front end now accepts empty GNU attributes.
For example:

  __attribute__((,)) void f();  // Previously an error.  Now okay.

8/19/04  Embedded C: Named address space qualifiers in array declarators

In C99 mode with Embedded C extensions, the front sometimes failed to diagnose
named address space qualifiers appearing inside the brackets of an array
declarator.  For example:

  void f(int x[_EDG_NAS_A const]);  // Previously accepted in C99 mode with
                                    // Embedded C extensions.  Now an error.

This is now fixed (a diagnostic is consistently issued).

8/19/04  External name conflicts with C++ variables

Most C++ ABIs (including those supported by the EDG front end) do not mangle
the names of global variables.  This can lead to external name conflicts with
extern "C" entities declared in other namespaces.  For example:

  int x;
  namespace N {
    extern "C" void x();  // Often same external name as variable above.
  }

Such conflicts are now diagnosed with an error, except in GNU and Microsoft
modes because in these modes extern "C" declarations are not related to
declarations in other namespaces (see also Changes entries of 7/28/04 and
10/6/99).  The C++ standard is expected to change to make these cases invalid. 

8/18/04  Diagnostic on missing placement delete operator

The front end previously issued a warning when a class definition contains
a member placement operator new and no matching operator is visible at that
point.  (Such a situation may lead to a memory leak if an initialization
associated with an new-expression throws an exception.)  This warning has
been weakened to a remark, and it is now also issued if the matching delete is
not a member.  In addition, a warning is issued if a placement operator delete
is still missing at the point where it would be called.  For example:

  #include <stddef.h>
  struct S {
    S();
    static operator new(size_t, double);
  };  // Previously a warning because the member operator new has no matching
      // operator delete.  Now just a remark.
  void g() {
    S *p = new(1.0) S;  // Warning.
  }

Note that these are issued only if exceptions are enabled.

8/17/04  Preprocessed output for _Pragma() operator

The _Pragma operator (and the Microsoft __pragma version of that) is
now passed through to the output when preprocessed output is
requested.  Formerly, it was deleted.

8/16/04  Deduction should fail when "function returning array" is deduced

Deduction should fail if template argument deduction attempts to create
a type of "function returning array" or "function returning function".
These cases are not currently included in the list of substitution
failures in the standard (14.8.2 [temp.deduct] paragraph 2) but probably
should be.  The front end has been changed so that deduction now fails for
these cases.  This is also being submitted to the standards committee as
a core language issue.

  template <class T> T f(T&){}
  void f(const int*){}
  int main() {
    int a[5];
    f(a);  // formerly an error, now calls f(const int*)
  }

8/14/04  Spurious ambiguity on using-declaration of conversion operator

A spurious ambiguity error was sometimes issued if a derived class named
a base class conversion operator in a using-declaration.  Now fixed.

  struct B {
   operator void *();
  };
  template <class T> struct D : B {
   using B::operator void *;
  };
  int main() {
    D<int> d;
    d == 0;  // spurious "more than one operator == matches these operands"
  }

8/13/04  Microsoft mode: dllimport and member function definitions

In Microsoft mode, the front end previously eliminated the bodies of inline
functions declared with "dllimport" (see Changes entry of 12/5/98).  However,
Microsoft compilers do use such function definitions for inlining purposes.
Eliminating the definition altogether could result in the C++-generating back
end producing invalid code.  For example:

  template<typename T> struct S;
  template<> struct __declspec(dllimport) S<int> {
    S();
  };
  template<> inline S<int>::S() {}  // Accepted when microsoft_version <= 1300.
                                    // Previously erroneously rendered as
                                    // "inline S();"

This is now fixed by not eliminating the definition and instead setting the
flag "suppress_inline_body" to TRUE (see also Changes entry of 1/19/00).

8/12/04  C++-generating back end: Spurious qualifiers cause lookup failure

The C++-generating back end sometimes generated spurious qualifiers on calls
to namespace scope functions that were originally not qualified.  This disabled
argument-dependent lookup and in turn could make the generated code invalid
when the called function could only be found through argument-dependent lookup.
For example:

  namespace N {
    struct S {
      friend void f(S);
    };
  }
  N::S s;
  void g() {
    f(s);  // Previously rendered as "N::f(s)" which is not valid in standard
  }        // C++.

This is now fixed.  In a related change [8/30/04], when an overloaded
operator is invoked in the source using operator syntax (e.g., "a+b" as
opposed to "operator+(a,b)"), the C++-generating back end will now also use
operator syntax in the generated code.  This change avoids generating
incorrect code for examples like the following:

  namespace N {
    struct S { };
    int operator+(const S&, const S&);
  }

  struct T {
    int operator+(int);
    void f() {
      N::S s1, s2;
      s1+s2;  // Generating "operator+(s1,s2)" would prevent ADL because
              // normal lookup would find T::operator+.
    }
  };

8/12/04  Dollar signs in text skipped by the preprocessor

In versions configured to allow dollar signs in identifiers, a spurious
error would be issued in strict mode on text that is skipped by the
preprocessor.  Now fixed.  A consequence of this change is that the
special "dollar sign used in identifier" message has been eliminated
and the generic "unrecognized token" is issued when dollar signs are
not recognized.  This change was necessary to get correct results for
certain cases where pp-tokens contain dollar signs.

  #if 0
  int i$b;
  #endif

8/12/04  Accepting dollar signs in identifiers in strict mode

Unlike other options, it was not possible to use the --dollar option in
strict mode to override the strict mode default of prohibiting dollar
signs in identifiers.  Now fixed.

8/12/04  Embedded C: spurious error hex fract constant with the value "1"

A spurious "out of range" error was issued for hexadecimal fract constants
with a value of exactly one.  Now fixed

  _Fract f = 0x1.0p0r;

8/11/04  Folding of reinterpret_cast on pointer-to-member at compile time

Some reinterpret_casts on pointer-to-member values are now folded at
compile time.  Formerly, such casts were handled at run time except
for a few cases in Microsoft mode.

8/11/04  Internal error on friend function defined in a class template

When compiling multiple translation units containing a class template with a
friend function definition, the front end sometimes aborted with an internal
error ("primary entry should not be canonical") in trans_copy.c.  For example:

  // File 1:
  template<typename T> struct S {
    friend void ff(S const&) {}
  };
  S<char> a ;

  // File 2:
  template<typename T> struct S {
    friend void ff(S const&) {}
  };
  template<int N> struct X {
    void f() { S<char> a; ff(a); }
  };
  void g() {
    X<128> c;
    c.f();
  }

This is now fixed.

8/6/04  Cfront-like ABI: Performance of empty base class optimization

In Cfront-like ABI configurations with TARG_OPTIMIZE_EMPTY_BASE_CLASS_LAYOUT
set to TRUE, the front end sometimes spent an unreasonable amount of time to
allocate empty bases classes in certain deep class hierarchies.  For example:

  template<int I> struct P;
  template<int I, typename T> struct E {};
  template<int L> struct D: D<L-1>, E<L, P<L> > {}; // Recursive template.
  template<> struct D<0> {};  // Recursion guard.
  int main() {
    D<100> d;  // Previously required a very long time to compile.
  }

This is now fixed.

8/6/04   Unneeded template constructors put out in IA-64 ABI with -tused

In the IA-64 ABI, in -tused mode, in some cases constructors of class
templates were instantiated and kept in the IL even though they
were referenced only from code that was later removed.  Now fixed,
i.e., the constructors are correctly removed from the IL.  This
was most visible when INSTANTIATE_EXTERN_INLINE is FALSE.
[8/12/04] A similar issue with thunks for extern inline virtual
functions has also been resolved.

8/5/04   C++-generating back end: MSVC++ cannot parse call to operator()

The C++-generating back end always renders calls to a function call operator
using explicit member-call syntax.  For example:

  struct S {
    bool operator()(int);
  };
  int main() {
    if (S()(7));  // Previously rendered as: "if (S().operator()(7));".
  }               // Now rendered as: "if (((S())).operator()(7));".

In some cases where the operator was applied to a function-style cast (like
"S()" in the example above), MSVC++ compilers could not parse the resulting
expression (due to a bug in those compilers).  Adding two levels of
parentheses in such cases (which we now do) makes the code acceptable to
Microsoft compilers.

8/4/04   Performance improvement in handling of type lists

Some changes were made to accelerate the routine move_to_end_of_types_list
with respect to moving the placeholder typeref associated with namespace
types.  (See also Changes entry of 10/30/02.)

8/4/04   Missing operators in is_operator_returning_bool

The function is_operator_returning_bool in il.c was missing the
complex and fixed-point comparison operators.  As a consequence
IL lowering would sometimes add an unnecessary comparison against
zero on top of such operators.

7/29/04  Initialized local variable not seen as constant in template

In some cases, a local variable of integer type declared in a
member function of a class template and initialized with an
expression that uses a member from a dependent base class was
not considered usable in an integral constant expression
during the prototype instantiation of the template (in
strict mode or with --parse_templates).  Now fixed.

  template <typename T> struct Base {
    enum E { e1 };
  };
  template <typename T> struct Derived : Base<T> {
    using Base<T>::e1;
    void foo() {
      const bool b = (e1 == 0);
      typedef bool x[b];  // Formerly an error in strict mode:
                          // "constant value is not known" for b
    }
  };

7/29/04  Microsoft compatibility: template friend lookup regression

A change made in version 3.4 (see 3/10/04 Changes entry) introduced a
regression that caused friend templates to be ignored by
argument-dependent lookup in Microsoft mode in certain cases.  Now
fixed.

  template <class T> struct B {};
  struct A {
    template<class T> friend void operator<<(B<T>&, A) {}
  };
  int main() {
    A a;
    B<char> b;
    b << a;  // spurious "no operator << matches these operands" error
 }

7/29/04  GNU compatibility: Attributes on class templates

In GNU mode, the front end did not accept attributes appearing immediately
after the "class", "struct", "union" keyword of a class template.  For example:

  template<typename T>
  struct __attribute__((deprecated)) S {  // Previously a syntax error.
  };

This is now fixed.

7/29/04  ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS, "?" in gcc mode

The front end failed to properly emulate gcc on examples like the
following when ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS is
TRUE:

  void f(int a) {
    (1 ? a : a) = 0;
  }

The "?" operation was rewritten as simply "a" and the front end
then failed to consider that as an lvalue in gcc mode.  Now fixed.

Also, there was a similar problem with the C++-generating back
end, which did not put out promotion casts at the top of
expressions produced by the dead-code elimination, which sometimes
produced wrong results, as in the following C-mode test:

  int main() {
    char c;
    sizeof(1?c:c);  // Formerly put out as sizeof(c); now sizeof((int)c)
  }

7/28/04  C++-generating back end: Microsoft calling conventions not emitted

The C++-generating back end failed to emit calling convention specifiers on
member functions without an explicit return type (constructors, destructors,
and conversion operators).  For example:

  struct S {
    __fastcall operator int*();  // Previously rendered without "__fastcall".
  };

This is now fixed.

7/28/04  C++-generating back end: unbalanced parentheses on member definition

The C++-generating back end put out unbalanced parentheses on the
definition of a member of a class that uses a typedef that is a
non-public member of that class as the specifier type when the
typedef is defined as a pointer to function type (or anything else
that would require parentheses in the declarator).  Now fixed.

  struct A {
  protected:
    typedef void (*T)();
    static T m_T;
  };
  A::T A::m_T = 0;  // Output formerly had unbalanced parentheses

7/28/04  GNU mode: Abort in C++-generating back end on statement expression

In GNU mode with ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS set to TRUE,
the C++-generating back end sometimes aborted with an internal error if the
input source contained a GNU statement expression within a conditional
expression with a constant condition.  For example:

  void f() {
    int i;
    i = 1 ? 2 : ({ char c; 3; });  // Triggered an internal error.
    i = 2;
  }

This is now fixed by not attempting to eliminate GNU statement expressions
even when the condition is constant.

7/28/04  Microsoft compatibility: Implicit int return type and type names

In Microsoft mode, the front end previously accepted member function
declarations whose name was found to be a type name.  For example:

  typedef int I;
  struct S {
    I();  // Previously accepted in all Microsoft bugs modes and treated as
          // "int I();".
  };

Since Microsoft fixed their bug in MSVC++ 7.1, we no longer emulate this
behavior when microsoft_version >= 1310.  (See also Changes entry of 7/12/99.)

7/28/04  GNU C++ compatibility: Conflicting extern "C" declarations

In GNU C++ mode, the front end now accepts conflicting extern "C" declarations
if they appear in different namespaces.  (Linker errors may result if the
declarations are definitions.)  For example:

  extern "C" int x;
  namespace N {
    extern "C" int x;  // Normally an error, but accepted in GNU C++ mode.
  }

(Microsoft compilers suffer a similar bug which our front end already
emulated in Microsoft bugs mode.  See Changes entry of 10/6/99.)

7/27/04  Embedded C: Conversions on fixed-point compound assignments

In compound assignments with a fixed-point result the front end erroneously
converted the second operand (the right hand side) to the result type.  Now, a
conversion is only added if the left hand side has a signed fixed-point type
and the right hand side has an unsigned fixed-point type (the conversion only
alters the signedness of the right hand side).  For example:

  void f() {
    unsigned long _Accum a;
    short _Fract b;
    a += b;  // Right hand side is signed: No conversion.
    b += a;  // Right hand side converted to signed long _Accum.
  }

7/27/04  C++-generating back end: Abort on GNU C function definition

In GNU C mode, an unprototyped function definition can follow a prototyped
declaration (see Changes entry of 3/18/04).  When this happens, the front
end unintentionally lost the "old_style_params_scanned" flag setting in the
associated routine type, which in turn caused the C++-generating back end to
abort with an internal error.

  void f(int, int);
  void f(i, j) int i; int j; {}  /* Triggered an internal error in the
                                    C++-generating back end (GNU C mode). */

This is now fixed.

7/27/04  C mode: Diagnostic on unnamed parameter in function definition

The error issued in C mode on an unnamed parameter in a function definition
has been made discretionary (i.e., its severity can be lowered from the
command-line).  For example:

  int f(int a, int /*unused*/) {  /* C mode error is now discretionary. */
    return a;
  }

7/26/04  GNU compatibility: Additional built-in functions

A number of new built-in functions introduced by GNU C/C++ 3.4 were added to
the list already supported by the EDG front end.  The new functions are:
__builtin_acosf, __builtin_acosl, __builtin_asinf, __builtin_asinl,
__builtin_atan2f, __builtin_atan2l, __builtin_atanf, __builtin_atanl,
__builtin_ceilf, __builtin_ceill, __builtin_coshf, __builtin_coshl,
__builtin_floorf, __builtin_floorl, __builtin_fmodf, __builtin_fmodl,
__builtin_frexpf, __builtin_frexpl, __builtin_ldexpf, __builtin_ldexpl,
__builtin_log10f, __builtin_log10l, __builtin_modff, __builtin_modfl,
__builtin_powf, __builtin_powl, __builtin_sinhf, __builtin_sinhl,
__builtin_tanf, __builtin_tanhf, __builtin_tanhl, __builtin_tanl,
__builtin_ctzl, __builtin_ctzll, __builtin_popcountl, and __builtin_popcountll.
Among this list, those functions expecting an argument of type long long are
(of course) only declared if LONG_LONG_ALLOWED is TRUE.

7/24/04  Warning on call of pure virtual function in derived class constructor
         or destructor

The front end now issues a warning on a call of a virtual function
that is known to resolve to a pure virtual function in a constructor
or destructor of a class derived from the one containing the
pure virtual function declaration.  Formerly, the front end
detected this case only in the class where the function is
declared.

  struct B {
    virtual void foo() = 0;
    B() { foo(); }           // Warning formerly/still issued
    virtual ~B() { foo(); }  // Warning formerly/still issued
  };
  struct D : public B {
    D() { foo(); }           // Warning now issued
    ~D() { foo(); }          // Warning now issued
  };

Also, as part of this change more virtual function calls are
optimized to call a specific function when the complete object
type is known.  Specifically, calls of virtual functions using
a derived-class object are now optimized in many cases.
All such optimization (including the cases that were done
previously) is now controlled by OPTIMIZE_VIRTUAL_FUNCTION_CALLS.
That is on by default when IL lowering is done, and off otherwise,
which means that versions that do not use IL lowering, e.g,.
C++-generating back end versions, will see less optimization than
they saw previously.

7/24/04  Cast to reference type can use conversion to non-reference

A cast of a class object to a reference to const type can use a conversion
function to a non-reference type to produce an rvalue, and then bind
the reference to that.  Formerly, the front end did not consider
that possibility (it only looked for conversion functions that return
lvalues).  Now fixed.

  struct A {};
  struct B {
    operator const A() const;
  };
  void foo(const B& v) {
    static_cast<const A&>(v);  // Now accepted
  }

7/23/04  Internal error on invalid template-dependent using-declaration

Certain invalid template-dependent using-declarations caused the front end
to abort with an internal error.  For example:

  template<typename T> struct B { typedef int I; };
  template<typename T> struct D: B<T> {
    using typename D::I;  // Previously an internal error.
  };                      // Now a normal error.

This is now fixed.

7/23/04  Useless return type qualifiers in template instantiations

In nontemplate code, the front end issues a warning if the return type of a
function is a nonclass type qualified with "const" or "volatile".  In (real)
template instantiations, this diagnostic was previously weakened to a remark
because the template writer has little control over whether the return type
will be instantiated to be a class or nonclass type.  Even so, the remark has
proven to be more distracting than useful, and as a result we no longer issue
it.  Note however that we still issue a warning during prototype instantiation
if we can determine at that time that the qualified type is a nonclass type.
This approach also avoids issuing the same diagnostic twice (once as a warning
and once as a remark) for nondependent return types in templates.
For example:

  template<typename T> struct S {
    int const f();  // Previously both a warning (during prototype
                    // instantiation) and a remark (during real instantiation).
                    // Now just a warning.
    T g();          // Previously a remark when instantiated with T=int const.
                    // Now accepted with no diagnostic at all.
  };
  S<int const> s;

7/23/04  Embedded C: Diagnostic on argument of fixed-point overflow pragmas

When the argument of a fixed-point overflow pragma was neither "SAT" nor
"DEFAULT" the front end issued a misleading warning saying "ON," "OFF," or
"DEFAULT" was expected.  This is now fixed (the diagnostic now correctly
says that "SAT" or "DEFAULT" is expected).

7/23/04  Embedded C: Internal error when lowering conversions between complex
         and fixed-point types

Various conversions between complex and fixed-point types could trigger an
internal error when they were lowered.  For example:

  void f() {
    _Complex float x = 1.0;
    _Accum a = x;  // Triggered an internal error.
  }

This is now fixed.

7/23/04  Embedded C: Named-register storage classes and named address spaces

The front end now issues an error when a variable is declared both with a
named-register storage class and a type qualified with a named address space.
For example:

  register _EDG_REG_1 int _EDG_NAS_A x;  // Error.  (Previously accepted.)

7/22/04  Embedded C: Named-register storage class on standalone class
         definition

The front end previously issued a warning if a named-register storage class
was specified on a standalone class declaration.  Now a discretionary error
is issued instead.  For example:

  register _EDG_REG_1 struct S { int i; };  // Error.  (Previously: Warning.)

7/22/04  Invalid suffixes on floating-point/fixed-point literals

In modes accepting the Embedded C fixed-point literals, the front end
failed to diagnose invalid suffixes on floating-point/fixed-point literals.
Specifically, the fixed-point attribute suffixes 'u', 'U', 'h', and 'H' were
accepted without the appearance of a 'k', 'K', 'r', or 'R' suffix indicating
that the literal is in fact a fixed-point literal (and not a floating-point
literal).  This is now fixed.  For example:

  double x = 0.0h;  // Previously accepted as a floating-point literal.
                    // Now an error.

7/22/04  Embedded C: Named-register storage class on function declarations

The front end failed to diagnose the use of a named-register storage class on
function declarations.  For example:

  register _EDG_REG_1 void f();  // Previously accepted; now an error.

This is now fixed (an error is issued).

7/21/04  Microsoft compatibility: dllimport variable as nontype template
         argument

The change of 6/11/03 -- making the address of a dllimport variable
not constant -- went too far.  MSVC++ allows the address of a
dllimport variable to be used as a nontype template argument.
That's now allowed again.

  template <int* X> class A {};
  __declspec(dllimport) extern int i;
  A< &i > b;  // Allowed again

7/21/04  Microsoft compatibility: incompatible template parameter lists

The Microsoft compatibility issue described in the Changes entry of 11/24/98
is fixed in MSVC++ 7.1.  Therefore, we no longer emulate it when
microsoft_version >= 1310.

7/21/04  Embedded C: Internal error on incomplete field in named address space

The front end issues an error if a field is qualified with a named address
space.  However, if that field also had an incomplete type, an aggregate
initializer attempting to initialize the field triggered an internal error.
For example:

  struct S {
    void _EDG_NAS_A a;   // Normal error.
  } x = { 0 };           // Initializer triggered an internal error.

This is now fixed.

7/21/04  Embedded C: Parameters in named address spaces

The front end now issues an error when attempting to declare a parameter in
a named address space (previously no diagnostic was issued).  For example:

  void f(_EDG_NAS_A int x);  // Error (_EDG_NAS_A is a named address space).

7/21/04  Embedded C: Spurious error on smallest _Accum value

A spurious error was issued if the result of a constant operation
was the smallest value that can be represented in a given _Accum type.
Now fixed.

  short _Accum b = -128.0k - 128.0k;

7/21/04  Spurious error on class template with conversion operator

When compiling multiple translation units (a somewhat unusual mode) the front
end sometimes issued a spurious correspondence error on two compatible
definitions of a class template.  This error only occurred if the template
contains a conversion operator member and the type of the conversion operator
was expressed in another class via a typedef.  For example:

  // File 1:
  template<typename T> struct X {
    operator void*();
  };

  // File 2:
  typedef void *PV;
  struct S { operator PV(); };
  template<typename T> struct X {  // Triggered a spurious compatibility
    operator void*();              // error even though the definition in
  };                               // File 1 matches this one perfectly.

This is now fixed.

7/20/04  GNU C++ mode overload resolution extension

g++ in its non-pedantic mode has an extension to the overload
resolution process to select the best function: if the standard
process finds no best function, the full set of candidate functions
is examined to find the worst conversion on an argument for
each candidate.  If one function has a better worst conversion
than all the others, it is chosen as the best function.  Note that
this is done after the standard process has failed, so in theory
it cannot change the meaning of any standard-conforming program.

7/20/04  Hidden name table refinement for class types hidden by nontags

When a nontag class member was hiding a tag entity in an enclosing scope,
the front end marked the hidden entity in the hidden name table as requiring
both elaboration and qualification.  This caused the C++-generating back end
to sometimes generate code that GNU C++ compilers could not parse (even though
the generated code was correct C++).

  struct S {};
  void S(struct S*);
  struct X {
    void S(struct S*);  // Formerly rendered as "void S(struct ::S*);" which
  };                    // GNU C++ compilers cannot parse.

To address this problem, the hidden name table now only requires qualification
for such a hidden class type if it is also hidden by a tag entity.

7/20/04  Typedefs with missing declarators in class templates

In some modes (e.g., Microsoft mode) a typedef with a missing declarator
is allowed.  For example:

  template<typename T> struct S {
    typedef struct N {};  // Error in strict mode, but accepted in many
  }                       // other modes.  N is a nested class of S<T>.

When such a typedef introduced a nested class definition in a class template
(as in the example above), the front end mistakenly treated the class as
belonging to the enclosing namespace scope (ignoring the definition while
doing so).  This could lead to all kinds of spurious errors (e.g., the
nested class was often incorrectly diagnosed as being incomplete).

This is now fixed.

7/15/04  C++-generating back end: parentheses around function calls

The C++-generating back end no longer puts an extra set of parentheses
around a function call in the generated code.  These extra parentheses
are unnecessary (because the (...) of a function call binds very
tightly to the function name) and because we ran into a g++ bug
on a constructor "call": (X()) was mistakenly taken as a cast even
if there is no expression following it.  X() is accepted without
problems, and that is what is now generated.

Also, the change of 6/12/04 to suppress parentheses around function
names in cases where argument-dependent lookup is suppressed has
been adjusted further so that the parentheses around the function
name are not put out when the function name is a qualified name
(the use of a qualified name suppresses argument-dependent lookup,
and some compilers had problems with the extra parentheses in
a case like "(::f)()").

7/15/04  Microsoft compatibility: __TIMESTAMP__ macro

The Microsoft __TIMESTAMP__ macro is now supported.  It expands to the
modification time of the source file in which it is specified.

  #include <stdio.h>
  int main() {
    printf("%s\n", __TIMESTAMP__);
  }

7/14/04  Embedded C: Compile-time conversion of fixed-point to/from complex

Compile-time conversion between fixed-point and complex/imaginary values
is now supported.

  _Accum y = (_Complex double)0 / 0.5r;

7/14/04  Embedded C: Incorrect conversion of certain floating-point values

Floating-point values with no non-zero mantissa bits were not converted to
fixed-point correctly.  Now fixed.

7/14/04  Internal error with hidden names and prototype instantiations in IL

An internal error in create_nonreal_progenitor_symbol could occur in
versions configured with hidden name table support (e.g., C++-generating
back end versions) and with PROTOTYPE_INSTANTIATIONS_IN_IL.  The error
would occur in examples, such as the following, in which a class template
contains a nested class that derives from another nested class of the
same template.  Now fixed.

  template<class T> class A {
      struct B { };
      struct C : B { };
  };

7/13/04  Optimization of initializer &c.a as &C::a for static data member a

IL lowering now optimizes a reference like &c.a, where a is a static
data member and c has no side effects, in the initializer of a static
variable, to a static initialization to the equivalent of &C::a,
where C is the class containing a.

7/13/04  Embedded C: folding of shift operations

Fixed-point shifts of constant values are now folded at compile-time.  As
part of this change, the following new expression operators have been
added (IL CHANGE): eok_fxshiftl, eok_fxshiftr, eok_fxshiftl_assign, and
eok_fxshiftr_assign.

7/12/04  GNU compatibility: Distinguish GNU asm syntax from standard asm syntax

In configurations supporting GNU extensions (i.e., with GNU_EXTENSIONS_ALLOWED
set to TRUE), a flag was added to be able to distinguish the extended GNU
syntax from the standard syntax.  This is significant for examples like the
following:

  void f() {
    asm("print %%");     // Standard form: Back end should preserve argument
                         // string with no change.
    asm("printf %%"::);  // GNU form: Back should replace "%%" by "%".
  }

A flag gnu_asm_form has been added to an_asm_entry for this purpose.

7/12/04  Microsoft compatibility: Multiple initializers for scalars

The Microsoft compatibility issue described in the Changes entry of 6/24/99
is fixed in MSVC++ 7.1.  Therefore, we no longer emulate it when
microsoft_version >= 1310.

7/12/04  Microsoft compatibility: Two constructor calls in copy-initialization

The Microsoft extension that treats certain copy-initialization contexts
as direct-initializations (see Changes entry of 1/18/98) did not work
correctly when the initialization ended up calling two constructors
(rather than a conversion function plus a constructor).  Such cases
are now allowed in Microsoft bugs mode.

  struct T {  T() {}  };
  struct U {  U(T) {}  U() {}  };
  struct V {  V(U) {}  V() {}  };
  int main(void) {
    T t;
    V v2 = t;  // Now accepted in Microsoft bugs mode.
  }

7/9/04   Hidden local variables

The front end now issues a remark when one local variable is hidden by
another one.  For example:

  void f() {
    static int i;
    { int i; }  // Triggers a remark.
  }

7/9/04   GNU compatibility: Name linkage of builtin functions

Previously, GNU builtin functions were given C++ name linkage in GNU C++ mode.
Now, they are assigned C name linkage in all GNU modes.  For example:

  #include <stddef.h>
  extern "C" {
    void* __builtin_alloca(size_t);  // Previously an error due to a linkage
  }                                  // mismatch.  Now okay.

[Patch sent out 7/16/04.]
[7/21/04] The type entry for builtin functions is now also assigned C linkage.

7/9/04   GNU compatibility: Warning on #pragma pack(pop) mismatch

In GNU modes, the front end previously issued an error if a #pragma pack(pop)
directive did not match a preceding "push" directive.  Now a warning is issued
instead (as was already the case in Microsoft mode).

7/8/04   C-generating back end: VLA declarations following labels

GNU C compilers allow declarations after executable statements, but not
immediately following a label.  The C-generating back, however, sometimes
produced VLA declarations immediately following switch labels.  For example:

  void f(int n) {
    switch (n) {
      case 1: ;    // Semicolon previously dropped in C-generating back end.
        float f[n];
        break;
    }
  }

This is now fixed.

7/8/04   GNU C compatibility: Flexible arrays when C99 features enabled

In nonstrict C99 mode a struct may include a member whose type contains a
flexible array member, but such a member must be the last field of the struct.
In GNU C mode, such a member can be any field of the struct (not just the last
one).  When both GNU C and C99 extensions were enabled, the front end used to
require the tighter constraints of plain (nonstrict) C99 mode.  Now the
broader GNU C mode extension is accepted.  For example:

  struct A {
    int i;
    int a[];
  };
  struct B {
    struct A a;  // Previously an error when both C99 and GNU C modes were
    int i;       // enabled.  Now accepted with that combination of modes.
  };

[Patch sent out 7/16/04.]

7/8/04   Determining if source is from an include file with preprocessed input

When compiling preprocessed source, the front end would sometimes treat
code from the primary source file as if it came from an include file.
This resulted in the suppression of some warnings and/or remarks that
should have been issued.  Now fixed.

  #line 1 "t.c"
  int i;
  #line 2 "t.c"
  static int g(double x) { return 0; }
  #line 10 "x.h"
  static int g(double x) { return 0; }  // should result in a warning
  #line 9 "t.c"
int main() {}

7/8/04   Abort on type qualifier appearing on VLA types

In some cases, the front end aborted with an internal error in
find_vla_dimension if a const or volatile qualifier appeared on a VLA
type.  For example:

  void g(float [2][2]);
  void f(int i) {
    typedef float A[i][i];
    A const a;
    g(a);  // Previously aborted while trying to issue a type mismatch
  }        // diagnostic.

This is now fixed.  The fix required the introduction of a_vla_dimension
entries that do not directly point to a dimension expression (IL CHANGE).

7/7/04   GNU C mode: Attributes on declaration sometimes lost after definition

GNU attributes appearing on a prototyped function declaration (in GNU C mode),
were lost after that same function was defined using old-style (unprototyped)
definition syntax.  For example:

  void f(void) __attribute__((noreturn));
  void f() {
    return;  // Previously no diagnostic because attribute "noreturn" was lost.
  }          // Now a warning is issued.

This is now fixed.

7/7/04   Microsoft compatibility: ambiguous class reference no longer allowed

The Microsoft compatibility issue described in the Changes entry
of 10/28/99 is fixed in MSVC++ 7.0.  Therefore, we no longer
emulate it when microsoft_version >= 1300.

7/7/04   Sun compatibility: Out-of-class static member initializer ignored

In Sun mode the front now mostly ignores out-of-class initializers for member
constants of template classes (i.e., integral const static data members of
class templates with an in-class initializer).  A warning is issued, and the
initializer is fully parsed (which may result in other diagnostics).
For example:

  template<typename> struct S {
    static int const c = 3;  // Member constant.
  };
  template<typename T> int const S<T>::c = 4;
      // Normally a duplicate initialization error (when instantiated),
      // but now ignored with a warning in Sun mode.

7/7/04   Abort on designated initializer in g++ mode

IL lowering aborted in lower_dynamic_init_aggregate_constant ("repeated con
not ck_dynamic_init") on processing designated initializers that skipped
over more than one element of an array in g++ mode.  Now fixed.

  struct A {
    A();
    ~A();
  };
  static A z[]={[0]=A(),[3]=A()};  // Formerly caused an abort

7/7/04   Stricter diagnostic on missing semicolon after last member of a class

In C++ mode, a discretionary error is now issued if the last member declaration
in a class definition is not terminated with a semicolon (previously a warning
was issued).  For example:

  struct S {
    int i  // Previously a warning; now a discretionary error in C++ mode.
  };

7/6/04   Improved diagnostic for unexpected template argument list

The diagnostics issued when a template argument list is specified in
a non-template function declaration have been improved.

  template <class T> void f(T);
  void f<int>(int i) { }

7/6/04   gcc compatibility: "&" operator applied to "?" operation

In gcc mode, a "&" operator is now allowed to take the address of
a "?" operation.

  int x, y, *z;
  void foo() {
    z = &(x ? x : y);
  }

7/6/04   Microsoft and GNU C++ compatibility: redeclaration of template

The Microsoft and g++ compilers allow a template to be redeclared outside
of its class or namespace.  We now emulate this behavior in Microsoft and
g++ modes.

  namespace N {
    template< typename T > struct S {};
  }
  template< typename T > struct N::S;

7/6/04   System header flag when compiling preprocessed source

When compiling preprocessed source containing GNU line directives,
the system header flag from an earlier line directive for a given
file should apply to later directives for the same file (that contain
only a line number and not a file name).  This now works correctly.

7/6/04   Internal error on globally qualified destructor name

Versions prior to 3.4 gave an error on a globally qualified destructor.
Globally qualified destructor calls are accepted by version 3.4, but
resulted in incorrect IL, which gave rise to an internal error in IL
lowering.  Now fixed.  [Patch sent out 7/16/04.]

  typedef int T;
  int main() {
    T *p;
    p->::~T();
  }

7/5/04   IL lowering: elimination of now-pointless local static variable
         init entries

IL lowering now eliminates some local static variable init entries
that are pointless after lowering, specifically those that point
to a dynamic-init entry whose kind has been changed to dik_none
after lowering.  Those were harmless but also unnecessary.

7/3/04   Microsoft compatibility: call returning incomplete class type

MSVC++ allows calls of functions returning incomplete class types in
certain contexts.  We're not sure of all the contexts, but one that
matters (because it comes up in Microsoft software) is inside a
sizeof.  Accordingly, we now allow a call returning an incomplete
class type inside an unevaluated context in Microsoft bugs mode.

7/2/04   Missing VLA deallocation statement in switch statement

When VLA variables were defined in a switch statement, the front end sometimes
failed to record a corresponding deallocation statement (stmk_vla_dealloc).
For example:

  void f(int n) {
    switch (n) {
      case 1: int x[n]; break;  // Previously no stmk_vla_dealloc for "x".
    }
  }

This is now fixed.

7/1/04   Incorrect lowered code for conversion from integral to imaginary

The code generated by IL lowering for a conversion from integral
type to imaginary just copied the value.  It's supposed to set the
destination to zero, and now it does.  [Patch sent out 7/16/04.]

7/1/04   Implicit include flag added to the source file entry

An is_implicit_include flag has been added to the source file entry.  This
flag is available when the front end is configured for implicit inclusion.

7/1/04   Source file data structure problem with implicit inclusion

Version 3.4 included an optimization of the translation of a sequence
number into a source file and line number.  This optimization uncovered
an existing problem that resulted in gaps in the sequence numbers
when using implicit inclusion.  These gaps could result in an internal error
on an attempt to get the source file and line number for a sequence number
from one of the gaps.  This has been fixed.

7/1/04   Multiple-translation unit problem with two-argument operator delete

When a two-argument class-specific operator delete[] was used in
a secondary translation unit (and not in the primary translation
unit) in multi-translation-unit mode, IL lowering sometimes failed
to recognize that the class has a two-argument delete, and therefore
failed to use the array new/delete protocol that saves the array
size.  Now fixed.

6/30/04  Missing error on invalid uses of VLAs with unspecified size

Variable-length arrays (VLAs) with unspecified size (declared using the [*]
construct) should only appear in function prototype scopes.  However, the
front end failed to diagnose certain other uses of the construct.  For example:

  void f() {
    (int (*)[*])0;  /* Previously undiagnosed.  Now an error. */
  }

This is now fixed.

6/30/04  GNU C++ compatibility: visibility of using-directives

In strict mode (i.e., when doing dependent name processing) only
using-directives from the template definition context are considered
when looking up names in templates.  In our default mode, all using-directives
are considered.  g++ uses a hybrid approach in which all using-directives
are considered if the name found is a function, but for non-functions only
using-directives visible at the point of definition of the template are
considered.  We now emulate this behavior in g++ mode.

  namespace N {
    template <class T> class A {};
    void z(int){}
  }
  namespace M {
    template <class T> class A {};
    void z(int){}
  }
  using namespace N;
  namespace O {
    // A is not ambiguous but z is.
    template <class T> struct B { A<T> a; void f() {z(1);} };
  }
  using namespace M;
  int main() {
    O::B<int> b;
    b.f();
  }

6/29/04  Incorrect overload resolution during function prototype instantiations

If a class contained an overload set with one or more member functions
and a using-declaration from a dependent base class, a call in which
none of the function arguments was dependent could result in spurious
errors during the prototype instantiation of the function because overload
resolution was done ignoring the fact that additional members of the
overload set would be present during an actual instantiation.

  template <class T> struct A {
    void f(int);
  };
  template <class T, int n> struct B: public A<T> {
    using A<T>::f;
    void f() { this->f(n); f(n); }
  };

6/29/04  Scanning pragmas as pp-tokens

Pragmas may now be scanned as pp-tokens.  This permits the use of
pragmas that contain characters that are not valid in ordinary
tokens.  The add_xxx_pragma_kind_description routines now take an
additional parameter that indicates whether the pragma should be
scanned as pp-tokens.  Such pragmas must be represented as text
(not tokens), cannot have macros expanded, and cannot have the
processing_C_code flag set.  The presence or absence of white space
between tokens is preserved, although white space and comments are
standardized to a single space.

6/29/04  Microsoft compatibility: call of non-const function on const object

The Microsoft compatibility issue described in the Changes entry
of 11/1/00 is fixed in MSVC++ 7.1.  Therefore, we no longer
emulate it when microsoft_version >= 1310.

6/29/04  Spurious errors when multibyte characters are enabled

When MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is TRUE, certain locale-dependent
functions used by the front end could behave in an unexpected way resulting
in spurious errors.  For example, conversion of floating-point literals
may not work properly.  Now fixed.  [Patch sent out 7/16/04.]

6/28/04  Initialization of reference-type catch parameter with partially-
         lowered exception handling

In configurations with partially-lowered exception handling (i.e.,
IL lowering in use and DO_FULL_PORTABLE_EH_LOWERING set to FALSE),
the code generated to initialize a catch parameter of reference
type had an extra indirection.  As a consequence, the catch parameter
was initialized incorrectly unless a back end did something special
to detect the case and undo the problem (we suspect several customers
must have).  Now, the code properly assigns the address of the thrown
object to the catch parameter with no special back end tricks.

  int main() {
    int i;
    try { i = 0; throw 'a'; }
    catch (char &) { i=1; }  // Code here was wrong.  Was same as the
                             // second clause.  Now different.
    catch (char *) { i=2; }
  }

6/28/04  Ordering issue in code generated by IL lowering for IA-64 ABI

The code generated by IL lowering for a cast to a virtual base class
in the IA-64 ABI was incorrect, in that it initialized a temporary
in the left operand of a "+" operation and used that temporary in
the right operand.  (The C standard does not guarantee that the left
operand will be evaluated before the right operand.)  Now fixed.
[Patch sent out 7/16/04.]

6/25/04  Abort on destructible entity in default argument in sizeof

The front end aborted in add_to_destructions_list ("object lifetime
and dynamic init in different memory regions") while processing a
default argument that contains a destructible entity inside of
a non-evaluated context such as a sizeof within a declaration
of a local type.  Now fixed.

  struct A {
    A();
    ~A();
  };
  int f(A = A());
  int main() {
    enum {
      x = sizeof f()  // Formerly caused an abort
    };
  }

6/25/04  Overload resolution, conversion to reference-to-const

Overload resolution had incorrectly considered a conversion function
to a reference-to-const-class type in a context where a parameter of
type reference to (non-const) class type is bound to the result of
the conversion function call.  If the function with that parameter
type was selected, an error was correctly diagnosed, but the function
should not have been considered viable in the first place, and
the fact that it was considered viable could have caused a spurious
ambiguity or other error.

  struct A;
  struct B {
    operator const A&();
  };
  void g(const A &);
  void g(A &);
  int main() {
    g(B());  // Formerly ambiguous because "g(A &)" was incorrectly
             // considered to be a viable function
  }

6/25/04  Conversions to const for left operand of built-in assignment operators

The overload resolution analysis that looks for conversions on the
operands of built-in operators now avoids conversion functions that
return const lvalues when processing the left operand of assignment
operators.  (The left operand has to be a modifiable lvalue, so a
const object cannot be used.)

6/24/04  Embedded C: incorrect rounding of signed values

Signed fixed-point values were not rounded properly in some cases.
Now fixed.

  short _Accum a = 0x12.158p0hk;

6/24/04  Microsoft compatibility: more work on __LPREFIX

The Microsoft __LPREFIX operator (see Changes entry of 5/12/04) is also
accepted by Microsoft following a string, as in

  L"abc" __LPREFIX(__FUNCTION__)

The front end now accepts this sort of concatenation.

6/23/04  Microsoft compatibility: nontype template argument bug fixed in 7.1

A bug in handling of nontype template arguments in the Microsoft compiler
has been fixed in MSVC++ 7.1.  Therefore, we no longer emulate that
bug in Microsoft mode when microsoft_version >= 1310.

  template <char *P> struct X {};
  char *p;
  X<p> x;  // No longer accepted when microsoft_version >= 1310

6/23/04  Incorrect storage class for function template instances

In some cases, function template instances that were not fully instantiated
were given a storage class of sc_unspecified but should have been sc_extern.
This has been fixed.

  template <class T> void f(T){}
  int main() {
    f(1);
  }

6/23/04  IA-64 ABI: less unneeded code when vtables are optional

The virtual function tables generated by IL lowering are sometimes
categorized as "optional": the vtable heuristic doesn't require
that they be put out in the current compilation, but they should
be put out if referenced.  In the Cfront-like ABI, those vtables
are static and therefore if they are truly unreferenced they are
eliminated by the removal of unneeded entities.  In the IA-64 ABI,
however, such vtables are COMDATs, and therefore they look like
external definitions, which are preserved in the removal of
unneeded entities.  Now, such vtables are marked with the
new is_optional_vtable flag, and they are kept only if
actually referenced.  Eliminating the vtable variable allows
the elimination of routines only referenced from the vtable,
e.g., inline virtual functions, which reduces overall code size.

6/23/04  Designated initializers for anonymous union members

Naming a member of an anonymous union or (nonstandard) anonymous
struct in a designated initializer did not work correctly.
The IL generated by the front end was incorrect, and IL lowering
later aborted while trying to handle it (an assertion failure
in lower_init.c within advance_aggregate_position_to_next_member).
Now fixed.  This came up in gcc and g++ modes, though other
configurations that allow both designated initializers and
anonymous unions/structs would have had the same problem.

  struct TST {
    int a;
    union {
      int c;
    };
  };
  struct TST a = {1, .c = 3 };

6/21/04  Hidden name table performance improvement

The hidden name table routines have been optimized to better handle
class hierarchies that have a large number of identical injected class
names.  This resulted in a 3-4X performance improvement for cases like the
one below.

  template< int i > struct A {int a;};
  template< int i > struct B : B<i-1> , A< i> { int b; };
  template<> struct B<0> { };
  int main() {
    B<60> b;
  }

6/21/04  Configuration option for accessibility on friend function declaration

A new variable no_access_check_on_friend_declarator_ids now determines whether
the declarator-id of a friend function declaration undergoes an accessibility
check.  The C++ standard requires the check, but many compilers ignore this
requirement (see e.g. the Changes entry of 6/25/03).  By default, this new
variable is set to the value of the new configuration macro
DEFAULT_NO_ACCESS_CHECK_ON_FRIEND_DECLARATOR_IDS.  That value is overridden in
certain modes (strict ANSI mode sets the variable to FALSE; Microsoft, GNU,
and Cfront modes set it to TRUE.)

6/18/04  Predefined __cplusplus macro can be redefined

The __cplusplus macro can now be redefined (except in Microsoft mode).  This
is desirable in environments where header files expect a different value for
the macro than the one supplied by the front end.  In Microsoft mode the
behavior is unchanged; an attempted redefinition results in a warning, but
the macro value is not changed.

6/18/04  VLA-related flag not set in parameter variable entries

The flag has_variably_modified_type in a_variable entries associated with
parameters was set to FALSE even if the variable did have a variably modified
type (i.e., a type containing a variable-length array (VLA) component).
For example:

  void f(int n, int x[n][n]) {}  // The variable entry for x had its flag
                                 // has_variably_modified_type set to FALSE.

This is now fixed.

6/18/04  Internal error when dependent operator names are used as nontype
         template arguments

An internal error (in equiv_unknown_functions) could occur when dependent
operator names are used as nontype template arguments.  Now fixed.
[Patch sent out 7/16/04.]

  template <class T, void (T::*)()> struct A { };
  template <class T> struct B {
    A<T, &T::operator+> a1;
    A<T, &T::operator int> a2;
  };

6/18/04  Incompletely-lowered code for bool compound assignment with
         imaginary operand

The lowering process for C99 compound assignments with a bool left
operand and an imaginary right operand produced incompletely-lowered
IL that still contained an imaginary zero constant.  Now fixed.

  _Bool g3;
  int main() {
    g3 *= (_Imaginary long double)0.0;
  }

6/18/04  Zero-valued const variable as null pointer constant in conversions
         for built-in operators

A zero-valued const integral variable is now considered to be a null
pointer constant in the processing to determine conversions for a
built-in operator with class operands.

  struct A {
    operator void*();
  } a;
  int main() {
    const int i = 0;
    a == i;     // Formerly an error; now left operand converted to "void *"
                // and right operand treated as null pointer constant
  }

6/17/04  "Do-nothing" cast to floating point preserved

The C99 standard says that an explicit cast of a floating-point
expression to the same type can be used to force the implementation
to drop any extra precision that was being carried for intermediate
results and use only the exact precision of the type (see 6.3.1.5
and 6.3.1.8 in the standard).  Formerly, the front end threw away
such casts unless PRESERVE_EFFECTLESS_EXPLICIT_CASTS_IN_IL was
TRUE, assuming they did nothing.  Now, they are retained
regardless of the setting of that macro.

6/17/04  __FUNCTION__ string form in Microsoft mode

The expansion of the identifier __FUNCTION__ in Microsoft C++
mode now has the full name of the function, including a qualifier for
the class of a member function, e.g., "X::f" rather than simply "f".

6/17/04  Type information from static data member specialization lost

It is possible for a static data member specialization to have more detailed
type information than the generic in-class declaration of that member.  For
example:

  template<typename T> struct S {
    static int m[];
  };
  template<> int S<void>::m[10] = { 0 };  // Previously treated as an array
                                          // of length one.

In cases such as these, the front end only checked the type of the
specialization for compatibility with the in-class declaration, but failed
to record the added type information.  In the example above, this meant that
the dimension of the member m was determined by the initializer (of length
one) rather than by the explicit bound (length ten).  This is now fixed.
[Patch sent out 7/16/04.]

6/16/04  Microsoft mode: Spurious error when combining explicit and __stdcall

In Microsoft mode, the front end issued a spurious error on the declaration
of an explicit constructor with a __stdcall modifier.  For example:

  struct S {
    explicit __stdcall S();  // Previously an error.  Now accepted in
  };                         // Microsoft mode.

This is now fixed.

6/16/04  long long bit field promotion rules in gcc mode

It turns out the promotion rules for long long bit fields used
by gcc differ from those used by g++.  Specifically, while g++
promotes all long long bit fields to long long regardless of
size, and all likewise all unsigned long long bit fields promote
to unsigned long long, gcc apparently uses those rules only
for bit fields larger than long; for smaller ones, the standard
rules apply (and therefore the promoted type is int, unsigned
int, long, or unsigned long).  This is now emulated in gcc mode.

6/16/04  Abort in Microsoft mode, rvalue field selection with cv-qualified
         type used in "?" operation

An abort in take_address_of_lvalue ("not an lvalue") in Microsoft mode
has been eliminated.  It came up on a use of an rvalue field selection
of cv-qualified type as the second or third operand of a "?" operator
whose second and third operands have the same type (ignoring the
cv-qualifiers).  This is fallout from the Microsoft bug emulation change
of 11/14/00.

  struct C {
    int len;
  };
  const C getName();
  int main() {
    1 ? getName().len :  0;
  }

Part of the problem here was that cv-qualifiers were not stripped
from the types of rvalue field selections, which violates the IL
rules (in C, rvalues never have cv-qualified types; in C++, only
class rvalues can have cv-qualified types).  That was a problem
even outside of Microsoft mode.

6/16/04  Refinement of protected member access checking

The processing to perform the access check of section 11.5 of the
C++ standard has been improved to match the proposed resolution
of core issue 385.  The check is now done on the basis of whether
the member is a protected member of the class in which it is named,
rather than simply because the member declaration is protected.
That means that a using-declaration that makes a protected member
public will now suppress this check when the member is used
in the class with the using-declaration or in some derived class
thereof.

[6/19/04:] Also, this protected member check is now also deferred and
tried again later when it appears in a section where access checks
are deferred.

6/16/04  C++-generating back end: Address expression not treated as constant
         by Microsoft C compiler

The C++-generating back end previously rendered an expression of the form
"&((X*)0)->i" as "&(*((X*)0)).i".  However, MSVC++ 6.0 does not treat the
latter as a constant (in its C language mode) whereas it does so treat the
former.  To avoid this issue, the C++-generating back end now generates the
first form (even when the target is not MSVC++).

6/15/04  Missing diagnostic on empty initializer for array variable

The front end sometimes failed to diagnose an empty initializer on an array
variable with an unspecified bound.  For example:

  template <class T> struct A { static T a[]; };
  template <class T> T A<T>::a[] = {};  // Should be an error (except in
                                        // GNU C++ mode).

A diagnostic is now issued, except in GNU C++ mode where the array is assumed
to have length zero.  While a diagnostic was missing only on template cases,
the diagnostic for nontemplate cases has been made clearer.

6/12/04  C++-generating back end: extra parentheses around member function call

A change in 3.4 (see Changes entry of 1/6/04) added parentheses around
the names of functions in calls generated by the C++-generating back
end when argument-dependent lookup is suppressed by use of a
qualified name or parentheses around the name.  Unfortunately,
parentheses around a bound member function name (e.g., "(p->f)(x)")
are not accepted by g++ 2.95 and 3.2, so this change caused a
regression with those targets.  Since member function calls are
never subject to argument-dependent lookup anyway, the extra
parentheses are unnecessary in such a case, and they are now
suppressed.  [Patch sent out 7/16/04.]

6/12/04  Template name lookup and using-directives -- revised

A template lookup change made in version 3.4 broke some examples that
seem to be in somewhat common use (see "2/24/04 Template name lookup and
using-directives").  An additional change has been made that restores
the previous behavior for examples such as the one below without breaking
the cases that gave rise to the original change.  [Patch sent out 7/16/04.]

  namespace N {
    template <typename T> T g(T t) { return t; }
  }
  template <typename T> struct X {
    T f() {
      return g(T());
    }
  };
  using namespace N;
  int main () {
    X<int> x;
    return x.f();
  }

6/11/04  Template-dependent "?" expression not seen as constant

Expressions with a "?" operator, a first operand that is template-
dependent, and second and third operands that are constant
integral variables of the same type were not seen as constant
expressions.  When such expressions were used in a constant
context, e.g., a nontype template argument, a spurious error
was issued.  Now fixed.  [Patch sent out 7/16/04.]

  template <int s> class A {};
  template <class T1>
  void foo(T1*, A<sizeof(T1)>) {}
  template void foo( int*, A<sizeof( int* ) > );
  extern const int size = 16;
  template < bool I >
  void bar( A< I ? size : size  > ) {}  // Formerly got spurious error
  template void bar<true>( A< size > );

6/10/04  Overriding options implied by language modes

In general, when an option is implied by a particular language mode,
the option can be explicitly overridden.  For example, --gcc implies
that restrict is enabled, but this can be overridden by using the
options "--gcc --no_restrict".  In a few cases, this overriding was
not possible when it should have been.  In particular, it was not
possible for the --alternative_tokens and --nonconst_ref_anachronism
options in certain language modes.  Now fixed.

6/9/04   GNU C++ compatibility: internal error on __builtin_classify_type of
         pointer-to-member

In g++ mode, an internal error would occur if __builtin_classify_type
was called with an argument of pointer-to-member type.  Now fixed.

  struct A { int i; };
  typedef int A::*pmi;
  int main() {
    __builtin_classify_type(*(pmi*)0);
  }

6/9/04   IA-64 ABI: Two operator delete calls for one delete

In certain cases involving a delete of a pointer to a class,
where the class has a virtual destructor and an operator delete,
and the delete uses the "::delete" form, the generated code in
the IA-64 ABI mode was incorrect and resulted in both the
class-specific and the global operator deletes being called,
thus potentially freeing the storage twice.  Now fixed.
[Patch sent out 7/16/04.]

  extern "C" int printf(const char *, ...);
  void operator delete(void *p) { printf("operator delete\n"); }
  struct B {
    void operator delete(void *p) { printf("B::operator delete\n"); }
    virtual ~B() { printf("B::~B\n"); }
  };
  int main() {
    B *q = new B();
    ::delete q;  // Called class-specific operator delete plus global,
                 // only global should be called
  }

6/9/04   Space use improvement with using-directives

In certain unusual examples, a large number of symbols were allocated when
doing lookups that make use of using-directives.  This process has been
improved to dramatically reduce the amount of memory required.

6/7/04   Options for features of the ARM EABI variant of the IA-64 ABI

The front end now supports some additional features of the ARM
EABI variant of the IA-64 ABI.  Previously, the ARM EABI
pointer-to-member representation was selected by
IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR, and the ARM EABI
use of guard/release routines on static initializations was selected
by IA64_ABI_USE_GUARD_ACQUIRE_RELEASE.  Now, we have added:

  - Support for the variant form of the cookie used to record an
    array allocation, which is selected by
    IA64_ABI_USE_VARIANT_ARRAY_COOKIES.
  - Support for having constructors and destructors return "this",
    which is selected by IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS.
  - Support for the alternate rule for determining the key function
    for a virtual function table, which is selected by
    IA64_ABI_VARIANT_KEY_FUNCTION.
  - Support for "int"-sized guard variables for initializations of
    local static variables, which is selected by
    IA64_ABI_USE_INT_STATIC_INIT_GUARD

The runtime has also been updated to support these features.

6/2/04   Wide string not accepted in _Pragma operator

Wide string literals were not accepted in C99 _Pragma operators.
Now fixed.

   _Pragma(L"test_next_decl")

6/1/04   C++-generating back end: name references for variables

The front end now records the form of reference for references
to variables (if RECORD_FORM_OF_NAME_REFERENCE is TRUE), and the
C++-generating back end now uses that information when generating
references to variables.

5/28/04  Preprocessing abort in rem_source_line_modif_from_hash_table

Another bug introduced by the preprocessing change of 5/5/04 caused
an abort in rem_source_line_modif_from_hash_table ("not found in
hash table").  This came up only in cases big enough that lexical
data structure tables had to be reallocated at a larger size.
Fixed.  [Patch sent out 7/16/04.]

5/28/04  Incorrect IL aggregate constant for IA-64 pointer-to-member typeinfo

The typeinfo structure created for a pointer-to-member type in the IA-64
ABI contained an aggregate constant whose last_constant field pointed
to the second-to-last constant in the list rather than the last.
This did not affect the C-generating back end, but might have caused
problems for other back ends.  6/6/04: another similar problem
has been found and corrected, this one in the aggregate constant for
the type_info base class itself.  The second constant of the
initializer for that class is the name string, but the last_constant
field of the aggregate constant pointed to the first constant,
the virtual function table pointer.

5/28/04  Spurious errors involving member templates

In some relatively rare situations the front end issued spurious correspondence
errors on entities with types based on member template instantiations.  For
example, compiling two files with the following identical content in multiple
translation unit mode triggered such a spurious error.

  namespace S {
    template<unsigned> struct P {};
    template<typename T> struct L {
      template<typename T> struct N {};
      P<sizeof(N<T>)>  *p;  // Spurious correspondence error on member p.
    };
  }

This is now fixed.

5/28/04  Internal error declaring enum type in return type of main

An internal error would occur if an enum type was first declared as the
return type of main in C mode.  Now fixed.

  enum T main() { return; }

5/28/04  Embedded C: diagnostic on conversion of negative zero to fixed-point

A diagnostic was issued if a floating-point negative zero was converted to
an unsigned fixed-point type.  Now fixed.

  unsigned _Fract f = -0.0;

5/27/04  Embedded C: spurious loss of precision warning

The conversion of a floating-point zero to fixed-point could result in
a spurious loss of precision warning.  Now fixed.

  unsigned _Fract f = 0.0;

5/27/04  Abort on destructible entity in dead code after break in switch

IL lowering aborted in lower_dynamic_init ("dynamic init has lifetime
other than curr lifetime") on encountering a destructible object
declaration in dead code following a break statement in a switch
statement.  Now fixed.

  struct XX {XX(); ~XX();};
  void foo(int n) {
    switch (n) {
    case 1:
        break;
        XX x;  // Caused abort after warning re dynamic initialization
               // in unreachable code
    }
  }

5/26/04  Lowering of variable-length arrays (VLAs)

The front end can now be configured to transform variable-length array IL
into plain C89 IL by setting the macro LOWER_VARIABLE_LENGTH_ARRAYS to TRUE.
The allocation and deallocation of VLA storage is handled by new portable
routines in the run-time support library (these routines ultimately rely
on the standard malloc and free functions).

5/25/04  Embedded C: internal error on conversion from fixed-point to float

An internal error could result when converting a fixed-point value to a
floating-point value when the type of the floating-point value was specified
using a typedef.  Now fixed.  Note that the internal error depended on
memory layout and consequently occurred only on some configurations.

  typedef double T;
  T x[] = {0.0r};

5/20/04  Abort on unknown function bound to reference nontype template
         parameter

The front end aborted in extract_constant_from_operand ("bad operand")
or in types.c in exception_spec_is_less_restrictive (assertion failed)
on a use of a template-dependent function as the template argument
for a nontype template parameter of reference type.  Now fixed.

  template <void(&)()> struct A {};
  template <typename T> void f() {}
  template <typename T> struct B {
    typedef A< f<T> > type;    // Caused abort
  };

5/20/04  "controlling expression is constant" remarks eliminated

The remark "controlling expression is constant" on a constant value
in a tested boolean expression, as in

  if (1) ;

has been eliminated.  It gave undesirable warnings in some cases,
and we didn't see any good way to preserve the useful cases and
exclude the others.  We have retained the existing warnings using
this message, issued for tests of constant pointer or pointer
to member values in such contexts.

5/20/04  Spurious warning on conversion of large unsigned constant

Version 3.4 introduced a problem where a spurious out-of-range diagnostic
was issued if a large unsigned constant was converted to floating-point or
fixed-point.  The warning was issued if the value fit in a_host_large_unsigned
but not in a_host_large_integer.  Now fixed.  [Patch sent out 5/21/04.]

  bool g(float f) {
    return f != 0xffffffffffffffffULL;
  }

5/20/04  Abort in preprocessor with macro call continued on next line

Changes made in 3.4 (see Changes entry of 4/29/04) broke cases
like the following that involve more than one macro call on a line,
the second one continued to a subsequent line.  The abort was
an internal error in rem_source_line_modif_from_hash_table
("not found in hash table").  Now working again.  [Patch sent
out 5/21/04.]

  #define abs(x) ((x) >= 0 ? (x) : -(x))
  #define dabs(x) (double)abs(x)
  int main() {
    dabs(0) / dabs(
                   0);
  }

5/19/04  Microsoft compatibility: "&" applied to trivial construction

In Microsoft mode, the "&" operator can be applied to a functional-
notation type conversion to a class type (a "constructor call"), as
in &A().  This has generally been emulated correctly, but the
case of an empty argument list and a class with a trivial default
constructor (which calls for zeroing) was not allowed.  Now,
it is.

  struct A {};
  void g(A *p) {}
  int main() {
    g(&A());  // Formerly got an error in Microsoft mode; accepted now
  }

5/19/04  Abort in C-generating back end with "?" operating on mixed fixed-point

An internal error in the C-generating back end
("dump_expr: bad type on eok_question") occurred on compiling
a "?" operation whose operands are mixed integer/fixed-point
or two different fixed-point types.  Now fixed.

5/19/04  static inline duplicated with ONE_INSTANTIATION_PER_OBJECT

In ONE_INSTANTIATION_PER_OBJECT mode, static inline functions are
made external in a compilation containing instantiations so that
the separate object files for the instantiations can all refer
to one copy of the static function.  This was handled incorrectly
in the C-generating back end when LOWER_EXTERN_INLINE is TRUE and
IA64_ABI is FALSE: each instantiation object file contained a
definition of the external function, instead of an external
reference to the function, which could cause link-time "duplicate
definition" errors.  Now fixed.

This directly affects only those using the C-generating back end,
but anyone who copied the logic in the C-generating back end
that decides whether to put out a definition (in particular,
a test using the macro treat_as_static_inline) might have
copied the logic error and might want to revise that code.

5/18/04  Error on goto over declaration of class variable without destructor

A transfer of control past the declaration of a class variable and
into somewhere in its lifetime is an error.  Formerly, however,
if the class had no destructor and the mode was non-strict mode,
no diagnostic was issued.  An error is now issued.  In a related
change, a warning is now issued for the similar case of skipping
over the initialization of a non-class variable in non-strict mode.

5/17/04  Embedded C: Spurious error on integer to fixed-point conversion

Compile-time conversion of an integer zero to a fixed-point type resulted
in a spurious out-of-range error.  Now fixed.

  _Accum x = 0;

5/17/04  Null reference in unevaluated expression

Code that binds a reference to a null address has formerly gotten
an error in strict mode and a warning otherwise.  Now, if the
context is an unevaluated expression (e.g., inside a sizeof)
a warning is issued even in strict mode.

  class String;                                  
  int func(const String &);                      
  int main(int argc, char **argv) {              
    sizeof(func(*((String*)0)));  // Formerly an error in strict mode;
                                  // now a warning.
  }

5/17/04  Inline function referenced only in default argument not removed

An inline function referenced only in a default argument expression,
and successfully inlined each time the default argument is used, isn't
needed in the IL when unneeded entities are removed.  However, such
routines were not always removed.  Now fixed.

5/14/04  Microsoft compatibility: Initializers optional on const enum variables

Variables of const enum types (and arrays of const enum) can now be left
uninitialized in Microsoft mode: A warning will be issued (previously, an
error was issued).  For example:

  enum { k } const x[2];  // const x not initialized: Now okay in Microsoft
                          // mode (with a warning).  Previously an error.

(See also Changes entry of 1/20/97.)

5/14/04  Aborts on invalid uses of Embedded C registers and address spaces

Embedded C (see Changes entry of 4/30/04) named-register storage specifiers
must start with the keyword "register".  The front end aborted (with an
internal error) for various (erroneous) constructs involving Embedded C
register names not preceded by the keyword "register".  For example:

  _EDG_REG_1 x;
  unsigned u = sizeof(_EDG_REG_1);

Similarly, some invalid uses of named address space qualifiers could result
in internal errors.  For example:

  int i = sizeof(int)(_EDG_NAS_A);

These cases are now all fixed: Normal errors are issued.

5/14/04  C++-generating back end: Microsoft compilers and global qualifiers

MSVC++ 6.0 cannot parse base class initializers with global namespace
qualifiers.  The C++-generating back end has been updated to avoid generating
such constructs when generating code for MSVC++ 6.0 (and earlier).
For example:

  struct B { B(int) {} };
  struct C1: virtual private B { C1(): B(3) {}; };
  struct D: C1 {
    D(int n): B(n) {}  // "B(n)" usually rendered as "::B(n)", but no longer
  };                   // so when generating code for MSVC++ 6.0.

5/12/04  Abort on value-initializer for flexible array members

GNU and Microsoft C++ modes accept flexible array members (a C99 feature).
When such a member was value-initialized in a constructor definition, the
front end sometimes aborted in types.c during IL lowering.  For example:

  struct S {
    S(int k): n(k), x() {}  // Initialization of x caused abort.
    int n;
    int x[];  // Flexible array member.
  };

This is now fixed (the initializer has no effect).

5/12/04  Position information for anonymous union fields

The front end previously did not record any position information for anonymous
union fields.  Now the position of the beginning of the anonymous union
declaration is recorded in the field entry.  When EXTRA_SOURCE_POSITIONS_IN_IL
is TRUE, additional position information is also recorded in the entry.

5/12/04  Missing source sequence entries for empty statements

In configurations with REPRESENT_EMPTY_STATEMENTS_IN_IL set to TRUE, the
front end failed to produce source sequence entries for empty statements.
This could for example confuse the C++-generating back end under certain
circumstances.  For example:

  void f() {
    switch (1) {
      my_label:
        ;  // Empty statement.  Previously rendered after all switch clauses
           // along with a spurious goto statement.
      default: break;
    }
  }

This is now fixed.

5/12/04  Microsoft compatibility: token pasting, L##__FUNCTION__

MSVC++ 7.0 and 7.1 allow token pasting in a macro to paste an "L"
on the front of the function-name keywords like __FUNCTION__.
The result is a wide-string version of the function name.
This feature is now emulated when microsoft_version >= 1300.
It is implemented (in both MSVC++ and the EDG front end) by way of
a secret operator named __LPREFIX.

5/12/04  Microsoft compatibility: Spurious correspondence error on variables
         with selectany, dllimport, or dllexport specifiers

When compiling multiple translation units in Microsoft mode, the front end
incorrectly treated as incompatible a nondefining variable declaration
without the selectany specifier and a corresponding definition that does
have that specifier.  For example:

  // File 1:
  __declspec(selectany) int i = 0;

  // File 2:
  extern int i;  // Previously considered incompatible with declaration in
                 // File 1; now okay.

Similar spurious errors were issued for variable declarations that only
differ in their dllimport/dllexport specifiers (see Changes entry of 12/2/03
which addressed the case of routine declarations).

This is now fixed.

5/11/04  Microsoft compatibility: const_cast as lvalue cast

A variant of the issue dealt with in the entry of 5/1/04: MSVC++ 7.1
allows a const_cast of a pointer type that doesn't really change the
type to be used as an lvalue.

5/11/04  Internal error on invalid destructor reference

Version 3.4 introduced an internal error on a case that previously
resulted in a normal error.  The internal error has been corrected,
so cases like the one below once again get a normal error.
[Patch sent out 5/21/04.]

  namespace N { enum E {}; }
  int main() {
    N::E *p = new N::E();
    p->N::~E();
  }

5/10/04  Microsoft 7.1 compatibility: conversion of rvalue via conversion
         function, direct reference binding

The Microsoft compatibility issue described in the Changes entry of
10/19/98 is fixed in the MSVC++ 7.1 compiler.  Accordingly, we
no longer emulate this behavior when microsoft_version >= 1310.

-------------------------------------------------------------------------------
Version 3.4, May 8, 2004

5/6/04   IL version number updated to 3.4

5/5/04   Preprocessing performance improvements

The preprocessor is now faster for a number of extreme cases,
including BOOST preprocessing cases.  See also the 4/29/04 changes,
which contributed to the speedup.

5/4/04   No remark on undefined identifier in unevaluated part of #if
         expression

The remark "zero used for undefined preprocessing identifier" is no
longer issued for references in unevaluated parts of expressions.

  #define A 0
  #if A && B  // No longer a remark on "B"
  #endif

5/2/04   Microsoft compatibility: cast to pointer type in nontype template
         argument

Microsoft bugs mode now allows explicit casts to pointer types in
nontype template arguments.  Formerly, such casts were allowed only
if they did nothing more than adjust cv-qualifiers.

  typedef void (*PF)();
  template<PF pfn> struct C {};
  void f();
  C<(PF)f> c; // Now allowed, in Microsoft bugs mode

5/1/04   Microsoft compatibility: const_cast to enum type

The Microsoft compiler (versions 6.0, 7.0, and 7.1 at least) allows
a const_cast that casts an operand of an enumeration type to the same
type with possibly adjusted cv-qualifiers.  If the operand is an
lvalue, the result is also an lvalue.  This is now emulated in
Microsoft bugs mode.

  enum ItemType { TYPEA, TYPEB };
  int main() {
    const ItemType x = TYPEA;
    const_cast<ItemType>(x) = TYPEA;
  }

(A case like this is reported to occur in the WinCE 5.0 source code.)

4/30/04  Embedded C Extensions

The front end now accepts the C language extensions specified by ISO/IEC
TR 18037 (also known as "Embedded C", formerly as "DSP-C").  The
extensions are three new facilities that can be configured independently:
fixed-point types (configured using the macro FIXED_POINT_ALLOWED), named
address spaces (NAMED_ADDRESS_SPACES_ALLOWED), and named-register storage
classes (NAMED_REGISTERS_ALLOWED).  If the macro EMBEDDED_C_ALLOWED is set
to TRUE, all three features are configured in.  These extensions are only
available in C modes at this time.

The fixed-point extensions include new basic types called _Fract (fractional
values between -1 and 1 or -- for the unsigned variants -- between 0 and 1)
and _Accum (which can have a larger range than _Fract types).  The types
have signed (default) and unsigned variants, and come in three precisions:
short, default, and long.  The types can also be modified with the new
keyword _Sat to impose "saturating overflow behavior" (i.e., if an operation
overflows, the computed result is the representable value closest to the
mathematically exact result).  New literal forms are supported for the
representation of fixed-point constants, and new STDC pragmas allow for some
control of the behavior of fixed-point arithmetic.  For example:

  _Accum acc = 0.0k;  // 'k' or 'K' suffix for _Accum literals.
  void update(unsigned _Fract x) {
    // Make the default behavior of _Accum types "saturating":
  #pragma STDC ACCUM_OVERFLOW SAT
    acc += x;  // Will saturate acc if the result is out of range.
  }

No lowering is done (yet) for fixed-point operations.  The C- and
C++-generating back ends will render _Fract and _Accum types and assume
that the consumer of the generated code accepts the extensions.  A back
end should also be aware that the "usual arithmetic conversions" for
binary operators do not include conversions to a common type if one of
the operands has a fixed-point type and the other has a different
fixed-point type or an integer type.  For example:

  void f1() {
    short s = 1;
    _Fract f1 = 0.5r;  // 'r' or 'R' suffix for _Fract literals.
    _Fract f2 = f1-s;  // IL operator eok_fxsubtract with two operands of
  }                    // different type; s and f1 are not converted.
  
Named address spaces are described using reserved identifiers that can appear
as type qualifiers (i.e., in the same places as const and volatile).  For
example:

  int _EDG_NAS_A *_EDG_NAS_B bpa;  // A pointer stored in address space
                                   // _EDG_NAS_B to an int stored in address
                                   // space _EDG_NAS_A.

The named address spaces accepted by the front end are described by the array
named_address_spaces defined in targ_def.h.  There are no default
address space names required by the TR, so implementation-specific
names must be added to make this feature useful.  Named address spaces can
be nested.  The following example illustrates the resulting constraints:

  void f2() {
    int _EDG_NAS_A *pa;
    int _EDG_NAS_B *pb;  // Assume _EDG_NAS_A "encloses" _EDG_NAS_B, then...
    pa = pb;             // ... is valid, but ...
    pb = pa;             // ... is invalid because an _EDG_NAS_A address may
  }                      // not be part of address space _EDG_NAS_B.

When no address space is specified, the term "generic address space" is used.
The nesting relationships between address spaces (including whether or not an
address space is enclosed by the generic address space) are configured through
the array named_address_spaces (see targ_def.h).  Named address spaces are not
lowered; the C- and C++-generating back ends will render them and assume that
the consumer of the generated code accepts the extensions.

Named-register storage class specifiers consist of the keyword "register"
followed by a reserved identifier; they can appear wherever the keyword
"extern" can appear on variable declarations in C.  For example:

  register _EDG_REG_1 char x;  // A definition of a char stored in a register
                               // described by the identifier _EDG_REG_1.

The named registers recognized by the front end are configured through the
array named_register_storage_classes defined in targ_def.h.  There are
no default register names required by the TR, so implementation-specific
names must be added to make this feature useful.  Note also that this
list of register names is different than the list of registers for
the GNU asm feature.  The configuration includes a size for each
register: An attempt to declare a variable with a named-register storage
class smaller than the size of the variable's type results in an error.
For example:

  register _EDG_REG_1 long double z;  // Error if the size of _EDG_REG_1 is
                                      // smaller than sizeof(long double).

Named registers are not lowered; the C- and C++-generating back ends will
render them and assume that the consumer of the generated code accepts the
extensions.

4/29/04  Preprocessor handling of recursive macro calls

Previously, the preprocessor incorrectly handled some cases where
macro names appeared within their own expansions.  In such cases, the
macro is not supposed to be expanded again (in our terminology, it
is "inert").  That was generally done correctly, but not in some
pathological cases.  Those are now fixed.  As an example, the
following case formerly looped within the front end, and now
produces the correct output of "foo":

  #define func(x) x
  #define bar func(
  #define foo bar foo
  foo )

A related problem occurs in the following case and has also been
fixed:

  #define p p+p
  #define pp foo
  #define y(b) b##p
  #define x(a) y(a)
  x(p)  // Correct expansion is "p+foo", not "p+p+foo"

See the Changes entries of 2/3/97 and 1/12/00.

4/29/04  GNU C++ compatibility: redeclaration of namespace member permitted

The standard does not permit a namespace member to be redeclared outside
of its namespace, but this is allowed by g++.  We now accept such
declarations in g++ mode.

  namespace N {
    void f();
  }
  void N::f();  // now permitted

4/27/04  Predefined macro definition file

A new mechanism for specifying predefined macros is now provided.  The
motivation for this feature is the fact that newer versions of g++ provide
large numbers of predefined macros (see the g++ predefined macros entry
below for more information about g++ compatibility), but this facility
can be used for any sort of predefined macro.

The front end can be configured to read macro definitions from a file.  The
file EDG_BASE/EDG_AUXILIARY_INFO_DIR_NAME/PREDEFINED_MACRO_FILE_NAME is read
to provide the macro definitions.  The EDG_BASE directory can be specified
by an environment variable (EDG_BASE), build-time macro (DEFAULT_EDG_BASE),
or command-line option (--edg_base_dir).  EDG_AUXILIARY_INFO_DIR_NAME and
PREDEFINED_MACRO_FILE_NAME are configuration macros with default values of
"lib" and "predefined_macros.txt".  If EDG_AUXILIARY_INFO_DIR_NAME is null,
the EDG_BASE directory is used directly.  The format of the entries in the
file is:

mode,!mode,mode   cannot_redefine   macro_name   macro_value

- "mode" is a label from the predefined macro modes table.  The macro is
  defined if the mode is set, or if the mode is not set when "!mode" is
  used.  The macro is defined if any of the mode tests is TRUE.  The set
  of mode values is specified in host_envir.h.

- cannot_redefine indicates whether the predefined macro may later be
  redefined.  The value must be "yes" or "no".

- macro_name is the name of the macro to be defined.

- macro_value is the value to which the macro should be defined.  All of
  the characters until the end of the line are used as the macro value.

For example:

gcc no  __GXX_ABI_VERSION 102
gpp no  __DBL_DENORM_MIN__ 4.9406564584124654e-324
gnu no  __GNUC_PATCHLEVEL__ 0

The file may also contain comments (lines that begin with a #) and
empty lines.  The fields of each line are separated by white space.
The DEFAULT_USE_PREDEFINED_MACRO_FILE macro specifies whether or not
a predefined macro file should be used.

4/27/04  GNU C++ compatibility: g++ predefined macros

Recent versions of g++ (3.3 and above) predefine a large number of macros.
The predefined macro definition file mechanism described above can be
used to provide the appropriate predefined macros in g++ mode (it
can also be used to provide the smaller number of macros predefined in
gcc mode).  A script (make_predef_macro_table) is provided that
automatically generates the predefined_macros.txt file for a given
version of gcc/g++.  It does this by invoking gcc and g++ and capturing
the predefined macro information.

4/23/04  C/C++-generating back ends: Typedef attributes

The C- and C++-generating back ends previously generated every attribute
of the underlying type of a typedef type on the typedef definition.  This
is now done differently depending on the kind of attribute: Some (like
"unused") are generated only if the attribute is recorded in the typedef
entry itself; others (like "transparent_union") are generated if the
attribute is recorded on the underlying type entry.

4/23/04  C/C++-generating back ends: Generate pack attribute for GNU targets

The C- and C++-generating back ends previously generated a #pragma pack
directive prior to the definition of packed class types.  However, that
pragma is ignored by GNU compilers.  Now a GNU attribute is emitted instead
of a pragma if the target compiler is a GNU compiler (i.e., when
GCC_IS_GENERATED_CODE_TARGET is TRUE).

4/23/04  Macro expansion with argument that does not require expanded form

A bug in the preprocessor has been fixed.  It involved macros that
have parameters than are never used in a context that requires
the macro-expanded form of the argument (i.e., the parameter is
either not used at all or it is used only adjacent to # or ##
operators).  The argument for such a parameter should not be
macro expanded, but formerly the preprocessor did that expansion
anyway.  That caused a spurious error in cases where the expansion
resulted in an error.

  #define f(x) bye
  #define gf(x,y) hello hello
  #define m(x,y,z) x ## y ## z
  m(g,f (1,1),end)  // Formerly got a spurious "too many arguments" error

4/19/04  IA-64 ABI: Array field of __vmi_class_type_info objects

In IA-64 ABI configurations, a typeinfo variable for a class involving
multiple and/or virtual bases classes (whose type is __vmi_class_type_info)
ended up having a __base_info field with a zero-length array type.
(However, the initializer for this field had the correct nonzero number of
elements.)  This is now fixed.

4/17/04  IL problem with GNU __extension__ on constant and
         RECORD_CONSTANT_EXPRESSIONS_IN_IL

The IL created for a constant marked with the GNU __extension__
keyword was incorrect when RECORD_CONSTANT_EXPRESSIONS_IN_IL is
TRUE.  One possible consequence was an IL write-read error
("not all expected entries were read").  Now fixed.

  extern int printf(const char *, ...);
  int main() {
    double huge_val;
    huge_val = (__extension__ 0x1.0p2047);  // Aborted in gcc mode
    return 0;
 }

4/16/04  Warning on too-large shift count

In Microsoft and GNU modes a too-large shift count now causes a
warning rather than an error.  This immediately brings up the
issue of how such shifts are to be folded at compile time.
The standard doesn't require any particular behavior, and
doesn't require that the result at compile time match the
result at run time.  (Surprisingly, our survey of compilers
indicates that most compilers do the two cases differently.)
We have added a configuration macro
TARG_TOO_LARGE_SHIFT_COUNT_IS_TAKEN_MODULO_SIZE to control
the behavior.

4/15/04  pch_one_time_init not called in usual way

For historical reasons, pch_one_time_init was called the first time that
pch_init was called instead of being called from fe_one_time_init as is
the case for all of the other one_time_init routines.  For consistency,
it is now called the same way as the other one_time_init routines.

4/15/04  Possible leaked file descriptor

When the front end is generating makefile dependencies and using implicit
inclusion of template definition files, a file could potentially be opened
but never closed.  This occurs only if the template definition file found by
the search process turns out to be the same as the primary source file
being compiled.  Now fixed.

4/15/04  Macro argument entry for _Pragma operator not freed

The macro argument entry allocated during processing of a C99 _Pragma
operator was not freed.  Now fixed.

4/15/04  Microsoft compatibility: "&" ignored in front of string literal

MSVC++ ignores the "&" operator when it appears in front of a string
literal.  This is now emulated in Microsoft mode.

  void f(const char *p);
  void g(void) {
    f(&"ok");  // Accepted in Microsoft bugs mode (C or C++)
               // &"ok" should have type "pointer to array[3] of const char",
               // not "pointer to const char"
  }

4/15/04  GNU C++ compatibility: disambiguation problem with attributes

In g++ mode the front end would incorrectly disambiguate declarations
containing GNU __attribute__ specifiers, resulting in spurious errors.
Now fixed.

  int g();
  int main() {    
    int (*fp)(void)  __attribute__ ((noreturn)) = &g;
  }

4/15/04  Microsoft compatibility: const string literal -> void *

MSVC++ allows conversion of a string literal (which is const) to
void *.  This is now emulated in Microsoft mode.

  void foo(void* a) {}
  int main() {
    foo("abc");
  }

4/14/04  Microsoft compatibility: _unaligned not a keyword

When a keyword begins with "__" (e.g., __cdecl), the Microsoft compiler
usually accepts it with a single underscore too.  The _unaligned
keyword is an exception.  We no longer accept _unaligned as a keyword
in Microsoft mode.

4/14/04  Emulation of g++ -fno-rtti mode

The front end in the IA-64 ABI mode can now emulate what g++
does with -fno-rtti more accurately.  g++ appears to decouple
the generation of the definition of the typeinfo variable for
a class from the generation of the definition of the vtable for
the class; the typeinfo is put out as a COMDAT everywhere it
is used.  This is now done when --no_rtti is specified and
SUPPRESS_TYPEINFO_VARIABLES_WHEN_RTTI_DISABLED is TRUE.
Also, the default for SUPPRESS_TYPEINFO_VARIABLES_WHEN_RTTI_DISABLED
has been changed to TRUE when DEFAULT_EMULATE_GNU_ABI_BUGS is TRUE.

4/13/04  Memory leak with free list of alias fixup entries

The list of freed alias fixup entries was maintained incorrectly
in free_alias_fixup in attribute.c, with the consequence that
freed entries were lost.  Now fixed.

4/13/04  Microsoft anachronism on pointer-to-member dereference no longer
         emulated

A microsoft anachronism that ignores cv-qualifiers from the first
operand on a pointer-to-data-member dereference like (p->*pm)
is no longer emulated when microsoft_version is >= 1200.
MSVC++ 6.0 (at least) and after seem to no longer have this quirk.

4/13/04  Missing code for base_class field of a_vcall_offset_entry in
         IL walk

The IL entry walk code in walk_entry.h was missing processing for
the base_class field of the a_vcall_offset_entry IL entry.

4/13/04  Compound literal not lowered in C89 mode with compound literals
         manually enabled

When the front end is run in non-C99 non-GNU C mode with compound
literals explicitly enabled (e.g., with --compound_literals), such
literals were not lowered (because the C99 lowering phase was not
run).  Now, it is and they are.

4/13/04  Incorrect fully-lowered EH code for almost-trivial constructor
         when NEW_CAN_BE_FOLDED_INTO_CTOR is FALSE

In configurations with NEW_CAN_BE_FOLDED_INTO_CTOR set to FALSE
(e.g., IA-64 ABI configurations) and DO_FULL_PORTABLE_EH_LOWERING
set to TRUE, the code generated for a constructor having virtual
base classes but no destructible base classes, members, or local
variables was incorrect.  Code was generated to initialize an
element of the object address table to the address of the complete
object, but the object address table was never used.  More
significantly, the size of the array variable for that was never
set (it remained zero), which could give back ends problems.
Other than that, the extra code is superfluous but otherwise
harmless.

  struct A {
    A();
  };
  struct B : virtual public A {
    B() : A() {}
  } b;

4/10/04  GNU/Microsoft compatibility: Explicit instantiation directive
         in incorrect namespace

The Microsoft and GNU compilers accept the explicit instantiation of a class
in an invalid namespace.  We now emulate this behavior in Microsoft and
g++ modes.

  namespace N {
    template <class T> struct A {};
  }
  namespace M {
    template class N::A<int>;
  }

4/7/04   GNU C++ compatibility: floating-point template parameters disallowed

Floating-point template parameters (which are not permitted by the standard)
are now disallowed in g++ mode.

3/31/04  UPC mode: Treatment of THREADS constants

In UPC mode, constant multiples of THREADS are represented using a singled
IL entry.  A few places in the front end ignored the possibility of such
multiples and always treated N*THREADS as just THREADS.  This is now fixed.

3/31/04  GNU/Microsoft compatibility: Using-declarations and friends

In GNU and Microsoft C++ modes, the front end now accepts a friend class
declaration involving a qualified name that refers to a using-declaration
or a using-directive.  For example:

  namespace N { struct S {}; }
  using namespace N;
  class C { friend class ::S; };  // Accepted in GNU and Microsoft C++ modes.

3/31/04  Internal error in routine_needed_even_if_unreferenced

In relatively rare cases involving function templates and nontemplate
functions with the same name and type, an internal error was triggered
in routine_needed_even_if_unreferenced.  For example:

  template<typename T> struct S;
  template<typename T> void f(S<T>*);
  template<typename T> struct S {
    friend void f<>(S<T>*);
  }; 
  S<int> s;
  void f(S<int>*) {}  // Nontemplate function.  Triggers an internal error.

This is now fixed.

3/29/04  Microsoft compatibility: floating-point template parameters

Version 7.1 of the Microsoft compiler no longer accepts floating-point
template parameters (which are not permitted by the standard).  We now
disallow floating-point template parameters in Microsoft mode when
microsoft_version is > 1300.

3/29/04  Abort on diagnostic for restrict qualifiers

In C++ modes accepting the restrict qualifier an internal error was triggered
when attempting to issue a warning for a restrict specifier appearing on a
typedef of a function type.  For example:

  typedef void F();
  typedef F restrict RF;  // Previously an internal error.  Now just a warning.

This is now fixed.

3/29/04  Microsoft compatibility: falling off function try block handlers

Normally, falling off the handler of a function try block for a constructor
or destructor implicitly rethrows the caught exception.  Formerly, the
Microsoft compiler did not not do this rethrowing, but the 7.1 compiler
does this correctly.  Our emulation of this bug is now done only when
microsoft_version is <= 1300.

3/25/04  IL lowering: construction vtables, zero-initialization

The code generated by IL lowering for a base class initialization
that requires zero initialization and also, in the Cfront-like ABI,
requires the passing of information about special virtual function
tables to be used during initialization to deal with virtual
functions in virtual base classes, generated incorrect code.
The zeroing operation cleared the pointer already set to transfer the
vtable information to the base class constructor.  Now fixed.
This was not a problem with the IA-64 ABI, which uses a different
approach for construction vtables.

3/18/04  GNU C mode: Mixing prototyped and unprototyped function declarations

In GNU C mode, an unprototyped function declaration following a prototyped
declaration of the same function caused the front end to subsequently ignore
the prototype in many cases (with a warning).  This behavior has been modified
if the unprototyped function declaration is a definition: In that case, the
prototype information is retained.  For example:

  void f(short);
  void f();              // Warning: Prototype lost.
  void g(short);
  void g(x) short x; {}  // No warning: Treated as "void g(short x) {}"
  void h(short);
  void h(x) char x; {}   // Error: Incompatible with prototype.

(See also the related Changes entry of 7/2/02.)

3/14/04  IA-64 ABI: typeinfo bug with array cv-qualifiers fixed in g++ 3.3

g++ 3.2 has a bug in generating typeinfo information for
cv-qualified arrays: it drops the cv-qualifier bits in the
typeinfo object.  The EDG front end emulates this bug when
GNU ABI bug emulation is on.  This bug has been fixed in
g++ 3.3 (even when -fabi-version=0 is not specified), so
the emulation is now done only when gnu_abi_version is
less than 30300.

3/13/04  Suboptimal operator for pointer-to-member bitwise copy

IL lowering generated an eok_bassign operator for the bitwise copy
of a pointer-to-member object in some cases, instead of the
more efficient eok_iassign (for a pointer to data member) or
eok_sassign (for a pointer to member function).  The better
operator is now generated.

  struct A {
    int i;
    void f();
  };
  void foo() {
     A o;
     try { throw &A::i; }
     catch (int A::*p) {  }
     try { throw &A::f; }
     catch (void (A::*pf)()) {  }
  }


3/10/04  Microsoft compatibility: friends defined in class invisible, sometimes

Further adventures in Microsoft compatibility: MSVC++ 7.1 has made
a change that makes friend functions defined in a class visible only
via argument-dependent lookup.  However, this invisibility applies only
to calls written in the operator form, e.g., a+b rather than
operator+(a, b).

  struct A {
    A();
    A(const char*);
    friend A operator+(const char*, const A&) { return A(); }
  };
  struct B {
    B();
    B(const char* s) ;
    friend B operator+(const char*, const B&);
  };
  struct C {
    operator char*() const;
  };
  int main() {
    C c;
    c + "abc";  // MSVC++ 7.1: not ambiguous, surprisingly
                // The operator+ in B is chosen; the one in A is
                // invisible to normal id lookup
    return 0;
  }

3/9/04   Core issue 54, again

There's been some confusion about whether static_casts that
involve a private base class are allowed.  We made the pointer
to member case an error previously (see Changes entry of 7/28/03).
Now that the standards committee has revisited the issue again,
we have also made the pointer case an error.

  struct B { int b; };
  struct D : private B { };
  int main() {
    int D::*dpm = 0;
    int B::*bpm = static_cast<int B::*>(dpm); // Was an error, still an error
    B *pb = 0;
    D *pd = static_cast<D*>(pb);  // Now an error, except in g++ and
                                  // Microsoft C++ 7.1 modes
  }

3/8/04   GNU compatibility: _Pragma accepted in GNU modes

The C99 _Pragma operator is now accepted in gcc and g++ modes.

  _Pragma("test_next_decl")
  int i;

3/5/04   Microsoft compatibility: Comma separator for __declspec attributes

In Microsoft modes, the front end now accepts an optional comma after a
__declspec attribute (even after the last attribute).  For example:

  struct __declspec(intrin_type, align(8)) S {};  // Okay.
  struct __declspec(align(8),) T {};              // Okay.

3/5/04   GNU mode: Attributes ignored on nondefining class declarations

In GNU C and C++ modes, the front end now ignores (with a warning)
attributes appearing between the class, struct, or union keyword and the
type name, if the class header is not followed by a class definition.
For example:

  struct __attribute__((deprecated)) S *p;  // Attribute ignored: No warning
                                            // about S being deprecated.

(This corresponds to the behavior of GNU compilers, except that the EDG front
end will issue a warning about the attribute being ignored.)

3/5/04   Abort on undefined virtual inline member in secondary translation unit

When compiling multiple translation units simultaneously, an internal error
was sometimes triggered if a secondary translation unit contained an undefined
virtual inline member function.  For example:

  File 1:
  int x;

  File 2:
  struct S { virtual inline void f(); };  // Triggered abort.

This is now fixed.

3/4/04   Spurious error on "using typename ..." with --ignore_std

When the --ignore_std option is used, a spurious error was issued
on a using-declaration that referred to a member of the std namespace
using a global qualifier.  Now fixed.  This is not a GNU compatibility
issue because g++ (through version 3.3) does not accept "using typename ...".

  namespace std {
    struct B { };
  }
  using typename ::std::B;

3/4/04   result_is_not_used flag set wrong, vacuous destructor call plus
         lvalue assignment

In some obscure cases where the operand of a vacuous destructor call
is an lvalue assignment, IL lowering did not set the result_is_not_used
flag correctly on one generated expression node.  This could cause problems
for back ends, and in particular caused an internal error in
check_result_not_used_flag in the C-generating back end.  Now fixed.

  void fun() {
    int i = 0, k = 1, j = i;
    typedef int Int_t;
    i?(k = j).~Int_t():void();  // Formerly caused abort in C-gen BE
  }

Also, the flag was not set correctly for the GNU C two-operand "?"
operator.  Also now fixed.

  int main() {
    int i = 1;
    i ?: (void)0;  // Formerly caused abort in C-gen BE
  }

3/3/04   Recorded expression for constant, boolean expression in C mode

When RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, the original
expressions that gave rise to constants are retained in the IL.
In C mode, this was not done for expressions with a constant value
tested in a boolean controlling expression context.  The underlying
expression is now preserved.

  void foo(void) {
    if (4 > sizeof(int)) {  // Expression now preserved under constant
    }
  }

3/3/04   GNU C++ compatibility: call returning class treated as lvalue

In GNU C++ mode, a function call returning a class value is now
treated as an lvalue in some cases.  Also, a warning is now issued
on taking the address of a temporary in any mode that allows it
(e.g., GNU C++, Microsoft C++).

  struct A {
    int i;
    A(int x) : i(x) { }
  };
  int main() {
    ++A(0).i;  // Accepted in g++ mode
    &A(0);     // Warning in g++ mode
  }

3/3/04   Microsoft compatibility: dllexport and inline functions

In configurations with LOWER_EXTERN_INLINE set to TRUE and IA64_ABI set to
FALSE, inline functions marked with __declspec(dllexport) were lowered into
functions with internal linkage ("static").  This caused, for example, the
C-generating back end to emit the functions with both "static" and
"__declspec(dllexport)" which is not valid code.  To address this problem,
inline functions declared with "__declspec(dllexport)" are no longer
transformed into functions with internal linkage ("static").

3/3/04   GNU mode: Attributes "used" and "unused"

In GNU mode, the front end now accepts with no diagnostic the attribute "used"
when it appears on variables with static storage duration (previously the
attribute was ignored with a warning).  Variables marked with this attribute
are not removed from the IL even if they appear to be unused.  Furthermore,
no warning is issued if they are not used.  For example:

  static __attribute__((used)) int x;  // Never eliminated.  No warning
                                       // if unreferenced.

In addition, the effect of attribute "unused" on functions and variables is
now limited to inhibiting warnings if the marked entity is unreferenced.
Previously, "unused" also caused the marked entity to be kept in the IL when
unreferenced: That is no longer the case.

3/3/04   Microsoft compatibility: repeated typename keyword

The Microsoft compiler allows the typename keyword to be repeated in
a typename specifier.  We now accept this in Microsoft bugs mode.

  template <class T> struct A {
     typename typename T::I f();
  };

3/3/04   Sun compatibility: spurious error on repeated typename keyword

The typename keyword is ignored in Sun mode, allowing it to be repeated and
used in invalid locations.  In some cases, however, a repeated use of
typename could result in spurious errors.  Now fixed.

  template <class T> struct B {
    typedef int I;
  };
  template <class T> struct C {
     typename B<T>::I f();
  };
  template <class T> typename typename B<T>::I C<T>::f() { return 0;}


3/2/04   C++-generating back end: Unmovable members

When FRIEND_AND_MEMBER_DEFINITIONS_MAY_BE_MOVED_OUT_OF_CLASS is TRUE, the
front end may move in-class member and friend function definitions out of
a class.  For some members this is not feasible because the member cannot
be named outside the class.  Previously, the front end incorrectly handled
the case of a member of a named class nested in an unnamed class.  That in
turn resulted in incorrect code rendered by the C++-generating back end.
For example:

  struct S {
    struct {         // Unnamed struct.
      struct N {
        void f() {}  // Definition was moved outside S.  The C++-generating
      } n;           // back end invented a name for the enclosing unnamed
    } u;             // struct.
  };

This is now fixed.

3/1/04   GNU C mode: __typeof__ ignores top-level const/volatile

In GNU C mode (but not in GNU C++ mode) the front end now ignores top-level
const and volatile qualifiers when processing a typeof operator whose
argument is an expression.  However, if the expression is a simple variable
the qualifiers are not ignored. For example:

  void f(int const *p) {
    int const x;
    __typeof__(int const) v1;  // Argument is a type, not an expression:
                               // v1 has type int const.
    __typeof__(*p) v2;         // Argument is a nontrivial expression:
                               // v2 has type int.
    __typeof__(x) v3;          // Argument expression is a simple variable:
                               // v3 has type int const.
  }

3/1/04   Spurious remark concerning destructor in dependent base class

When "remark" diagnostics are enabled, the front end issued a remark
about a nonvirtual destructor in a dependent base class even when the
destructor was in fact virtual.  For example:

  template<typename T> struct B { virtual ~B(); };
  template<typename T> struct D: public B<T> {  // Previously triggered a
    virtual ~D();                               // spurious remark claiming
  };                                            // a nonvirtual destructor
                                                // for B<T>.

This is now fixed (the remark is inhibited in all cases for dependent
bases of a class template).

3/1/04   GNU C mode allowed lvalue cast of struct/union to same-sized integer

GNU C mode mistakenly allowed an lvalue cast of an object of
struct or union type to a same-sized integer type.  gcc does
not allow such casts.  They now get an error.

  void ff(int);
  int main() {
    static union ui {int a;} ui ;
    ff((int)ui);
    return 0;
  }

This problem was introduced in version 3.2.

2/26/04  C++-generating back end: Abort on GNU statement expressions

The C++-generating back end could abort when attempting to render a
GNU statement expression that appears in a for-initializer.  (The problem
only occurred in GNU C++ mode; not in GNU C mode.)  For example:

  void f() {
    for (int k = ({ 1; }); ;) {}  // Triggered abort when rendered in
  }                               // the C++-generating back end.

This is now fixed.  As part of the fix, the field end_of_block_reachable
within struct a_block was changed to a bit field (this is an IL CHANGE).

2/26/04  Error recovery on template copy constructor that copies by value

An abort in select_overloaded_copy_constructor ensued after an
error on a template copy constructor that copies its own class
by value.  Now fixed.

  struct Y {
    Y(){}
    ~Y(){}
  };
  struct X : Y {
    X();
    X(X&);
    operator Y*();
    X(Y*);
    template <class T> X(T&){}
    template <class T> X(T, int i=0){}
  };
  X f() {
    return X();
  }

2/26/04  Spurious error on redeclared dependent typedef

A spurious error was issued if a typedef name was redeclared with a
template dependent type that differed from the type of the original
declaration.  No error should be issued because the types might be the
same during an actual instantiation.  Now fixed.

  template <class T1, class T2> void f(T1, T2) {
    typedef T1 X;
    typedef T2 X;
  }

2/26/04  File returned when converting the end-of-source sequence number

When converting a sequence number into a source file and line number,
the information returned for the special end-of-source sequence number
was incorrect if the last line of the primary source file was an include
directive.  Now fixed.

2/25/04  Problem with inlining function returning bool

The code generated for the inlining of a function call when
the function returns bool and the return expression in the
function has as top operator a pointer-to-member comparison
(e.g., return pm1 != pm2;) was incorrect when the call
appeared in an expression rather than as a top-level
statement.  (The code for the inlined call returned zero in
all cases.)  Now fixed.

2/25/04  Internal error on member template used as template template argument

In versions in which prototype instantiations are not included in the IL,
an internal error (in find_copy_assignment_operator) could occur when
a member class template is used as a template template argument.  Exception
handling must be enabled for the internal error to occur.  Now fixed.

  template <template <class> class T> class C {};
  template <class T> struct A {
    template <class T2> struct B {};
    C<A<T>::template B> c;
  };

2/25/04  Missing code in lowered placement array new

The code generated by IL lowering for an array placement new in
which the "operator new" function is inline and trivial (it just
returns the address argument, and ignores the size argument) and
the array size is specified at runtime was incorrect: it used a
temporary that was uninitialized (the temporary should have been
set to the number of elements in the array, but that code was
omitted).  Now fixed.

2/24/04  Lowered complex compound assignment had unlowered operator

The rewrite of a complex compound assignment done in C99 mode when
LOWER_COMPLEX is TRUE was incorrect, in that it used an eok_xassign
operator (complex assignment) where the correct lowered assignment
operator is eok_sassign (structure assignment).  Now fixed.

  double _Complex x, y;
  int main() {
    x += y;
  }

2/24/04  Microsoft compatibility: bound function no longer converted to
         pointer to member

The Microsoft mode bug that bound functions are implicitly converted
to pointers to members was fixed in MSVC++ 7.0 and is therefore
no longer emulated for microsoft_version >= 1300.

  struct A {
    void f(int) {}
  } a;
  typedef void (A::*PMF)(int);
  int main() {
    PMF pm = (PMF)a.f;  // Error in MSVC++ 7.0 and 7.1
    pm = a.f;           // Error in MSVC++ 7.0 and 7.1
  }

2/24/04  Internal error on invalid exported template directory

An internal error would result if an invalid directory was specified
in the --template_directory option when compiling a program that uses
exported templates.  Now fixed.

2/24/04  Template name lookup and using-directives

When using the default template lookup mechanism (i.e., when not using
the dependent name lookup rules specified in the standard) names made
visible by using-directives that appeared after the point of definition
of a template were considered when the template was instantiated.  This
could result in errors, such as the ambiguity reported on the example
below.  Such using-directives are now ignored during template instantiation.

  namespace N { namespace X { } }
  namespace X {
   template<class T> struct B {};
  }
  template <class T> void f(X::B<T>);
  X::B<int> x;
  using namespace N;
  int main() {
    f(x);
  }

2/23/04  GNU mode: Diagnose asm name conflicts

The front end now issues a warning on asm name constructs that specify
conflicting names for the same entity (the earlier name is kept).
For example:

  int x __asm__("x_1");
  int x __asm__("x_2");  // A warning is issued and "x_1" remains the
                         // asm name.

2/23/04  Abort or internal error during partial ordering processing

If a nontype template parameter has a type that depends on another
template parameter, and that nontype parameter is specialized in a
function template declaration that should be preferred by the partial
ordering process, an internal error or abort could occur.  This has
been fixed.

  template <class T, T I> struct A {};
  template <class T, T I> void f(A<T, I>);
  template <class T> void f(A<T, 1>);
  int main() {
    A<int, 1> a1;
    f( a1 );
  }

2/23/04  Deduction should fail if a nontype parameter is given an invalid type

Core issue 368 specifies that an attempt to give a nontype template parameter
an invalid type should cause deduction to fail.  We now implement this
rule.  Note that the example will still call #1 in versions configured to
allow floating-point template arguments.

  template <class T, T d> class X {};
  template <class T> X<T,0> Foo (T *);     // #1
  template <class T> int Foo (T const *);  // #2
  void f(float *p1) {
    int i = Foo (p1); // calls #2, deduction should fail on #1
  }

2/23/04  Abort during partial specialization processing

An abort could occur in copy_type_with_substitution during partial
specialization processing when the primary template has nontype template
parameters whose types depend on other template parameters.  Now fixed.

  template <class T1, T1 A, class T2, T2 B> struct X { };
  template <int A, int B> struct X<int, A, int, B> { };
  X<int, 1, int, 2> x;

2/20/04  GNU mode: Prefix declarator attributes

A "prefix declarator attribute" is an attribute that appears before a
declarator, but after a comma delimiting a previous declarator.  For example:

  void f1(), __attribute__((noreturn)) f2(), f3();

GNU C/C++ versions prior to 3.1 applied such attributes to all subsequent
declarators and the EDG front end previously emulated that behavior.
Newer versions of the GNU compilers limit the effect of prefix declarator
attributes to the immediately succeeding declarator and the EDG front end
now emulates that same behavior (e.g., in the example above, only f2 is
marked with "noreturn").

2/19/04  C++-generating back end: GNU attributes on function definitions

The C++-generating back end failed to render GNU attributes for function
definitions.  For example:

  __attribute__((const)) void f() {}  // C++-generating back end dropped
                                      // the attribute.

This is now fixed.  As part of this change the attribute-output routines
in c_gen_be.c and cp_gen_be.c have been consolidated and moved to
il_to_str.c.

2/19/04  GNU mode: Diagnostics on functions with noreturn attribute

In GNU modes, the front end now issues a warning when it can determine that
a function declared with the "noreturn" attribute does in fact return by
falling off the end of the function.  For example:

  __attribute__((noreturn)) void f() {}  // Warning: f does return.

(Previously, a warning was issued only for explicit return statements.)

2/19/04  GNU mode: Attributes and redeclarations

In GNU modes, the front end lost certain attributes specified on a declaration
when the declared entity is redeclared without that attribute.  For example:

  void f() __attribute__((noreturn));
  __attribute__((const)) void f() {}  // "noreturn" attribute was previously
                                      // lost.
This is now fixed.

2/19/04  Microsoft compatibility: Attributes on typedef

Microsoft attributes normally precede a declaration.  For typedef
declarations, however, they can now appear after the typedef keyword
(in Microsoft mode).  For example:

  typedef [string] unsigned short S[5];  // Now accepted in Microsoft mode.

2/19/04  Incorrect use of mmap could cause memory corruption

A change in the specification of the mmap function since the time that
the precompiled header processing routines were originally written
resulted in an inappropriate use of mmap.  In some unusual cases,
this could cause the use of corrupted memory resulting in incorrect
behavior and/or aborts.  This problem, while possible in theory, has
not actually been observed.

2/18/04  Use of uninitialized field after error on cast of bound function

The front end referenced an uninitialized field after issuing an
error on a cast of a bound function (e.g., object.function with
no following () to call it).  In some cases, this caused a front
end abort.  Now fixed.

  class clx {
  public:
     clx* func1();
  };
  void func2() {
     clx &foo;
     ((clx) foo.func1);
  }

2/18/04  Uninitialized memory access for dependent enumerator constants

In some situations involving enumerator constants with a template-dependent
value, the front end accessed uninitialized memory.  For example:

  template<int I> struct S {
    enum X { x1 = I, x2 };  // The processing of the constant associated
  };                        // with x2 caused an invalid memory access.

The invalid access could cause aborts in configurations with
PROTOTYPE_INSTANTIATIONS_IN_IL set to TRUE.  In other configurations
the problem was generally not noticeable.  This is now fixed.

2/13/04  Microsoft compatibility:  Explicit instantiation and dllimport

In Microsoft mode, explicit instantiation directives containing a
__declspec(dllimport) specifier are now treated as "do not instantiate"
directives.  (This is the same behavior as obtained by starting the
directive with "extern template".)  For example:

  template<typename T> void f(T) {}
  template __declspec(dllimport) void f(int);  // OK.  Inhibits implicit
                                               // instantiation of f<int>.

Previously, an error was issued because a non-inline function definition
cannot be declared with dllimport.

2/13/04  GNU IA-64 ABI: Effect of #pragma pack on bit fields

The effect of #pragma pack directives on bit fields changed substantially
between versions 3.2 and 3.3 of GNU C and C++ compilers.  The GNU C/C++ 3.2
behavior was previously emulated by the EDG front end in all GNU C and C++
modes.  Now the emulation only happens in GNU modes when the front end is
configured for the IA-64 ABI.  Furthermore, the GNU 3.3 behavior is mimicked
when the global variable gnu_abi_version (configured with the macro
DEFAULT_GNU_ABI_VERSION) is set to 30300 or higher.  For example:

  #pragma pack(1)
  union U {
    int f1: 2;
    char f2[2];
  };
  struct S {  // Size 12 with GNU C++ 3.2.  Size 8 with GNU C++ 3.3.
    U u;
    int a: 1;
    int  : 0;
    int c: 31;
  };

(We anticipate the GNU 3.3 behavior will be carried over to version 3.4 of
the GNU compiler suite.  See also the Changes entry of 10/20/03.)

2/12/04 Abort on partial specialization using template template parameters

In certain error cases, an abort could occur when determining which of
two class template partial specializations should be used when both
match a given class template instance.  The problem occurs only if one or
more of the template parameters are template template parameters.  We have
not been able to produce a small example of the problem, and believe that
the abort only occurs in obscure cases in invalid code.  The abort occurs in
matches_template_template_param.

2/10/04 C- and C++-generating back ends: C99 STDC pragmas

The C- and C++-generating back ends left out the "STDC" token when emitting
C99 STDC pragmas.  Furthermore, the C-generating back end failed to emit
STDC pragmas appearing in function definitions.  For example:

  #pragma STDC FP_CONTRACT ON       // Incorrectly rendered as:
                                    // #pragma FP_CONTRACT ON
  int main() {
  #pragma STDC CX_LIMITED_RANGE ON  // Not rendered by the C-generating
                                    // back end.
    return 0;
  }

These problems are now fixed.

2/9/04  Sun Compatibility: diagnostic on undefined inline function

The Sun compiler sometimes accepts inline functions that are referenced
but not defined.  In Sun mode, we now give a warning instead of an error
for such functions.

  struct A {
    friend void f();
    static void g() { f(); }
  };
  inline void f();
  int main() {
    A::g();
  }

2/9/04  Sun compatibility: extern inline functions

Formerly, inline functions were static by default (i.e., extern inline
was disabled).  As of at least the Workshop 6U2 compiler, extern inline
should be enabled.  Extern inline is now enabled in Sun mode.

2/5/04  Warning issued on dependent friend function declarations

A warning is now issued if a dependent friend declaration (not a definition)
appears in a class template when guiding declarations are disabled.  Such
a declaration is almost always a mistake (a missing <> that would cause
the declaration to make a template specialization a friend).  The message
can be disabled by setting the DEFAULT_WARNING_ON_NON_TEMPLATE_FRIEND
configuration macro to FALSE (and, of course, by the --diag_suppress
command-line option).

  template <class T> void f(T){}
  template <class T> struct A {
    friend void f(T);  // f<> intended
  };

2/5/04  Partial ordering problem with pointer-to-member types

Partial ordering would sometimes fail for function templates containing
pointer-to-member types involving template parameters.  This would result
in a spurious ambiguity for examples like the one below.  Now fixed.

  template <class T1, class T2> void f(T2 (T1::*)(), T1*){}
  template <class T1> void f(void (T1::*)(), T1*){}
  struct A { void g(){} };
  int main() {
    A a;
    f(&A::g, &a);
  }

2/5/04  Spurious error or internal error on virtual function in unnamed type

The definitions of virtual functions declared in unnamed classes or nested
classes thereof must appear within the definition of their enclosing class
because there is no syntax to define them outside the class.  However, when
such a virtual function definition appeared inside a class template, the
front end emitted a spurious error indicating the definition is missing.
In GNU and Microsoft C++ modes, an internal error was sometimes triggered
when the unnamed class type was a nonstandard anonymous union.

  template<typename T> struct S {
    struct {
      virtual void f() {}  // Previously triggered a spurious error.
    } x;
  };
  template struct S<void>;

This is now fixed.

2/4/04   GNU C++ compatibility: Strong using-directives

Strong using-directives are now supported in g++ mode.  The strong
using-directive is an extension added in g++ 3.4 and used in the g++
libraries.  A strong using-directive is like a normal using-directive except
that:

- The namespace containing the using-directive can specialize class
  templates declared in the used namespace.
- The namespace containing the using-directive is included in any
  argument-dependent lookup that looks in the named namespace.
- In a qualified lookup in a namespace, names from namespaces made visible
  by strong using-directives overload with names from the using namespace
  instead of being hidden by them.

  namespace std {
    namespace debug {
      template <class T> struct A {};
      void g(int, int);
    }
    using namespace debug __attribute__((strong));
    template <> struct A<int> {};
    template <class T> void f(A<T>){}
    void g(int);
  }
  int main() {
    f(std::A<float>());
    f(std::A<int>());
    std::g(1, 2);  // calls std::debug::g
  }

2/4/04   GNU C++ mode: Out-of-class member specialization

In GNU C++ mode, the front end now accepts nondefining declarations of
explicit specializations of class template members without a "template<>"
prefix.  For example:

  template<typename> struct S { void f() {} };
  void S<int>::f();  // Accepted in GNU C++ mode and treated as an
                     // explicit specialization.

1/30/04  Extern "C" declarations in unnamed namespaces

A spurious "referenced but not defined" error was issued if an extern "C"
function or variable in an unnamed namespace was referenced but not
defined.  Such an error should not be emitted because the entity could
be defined in another translation unit.

  namespace {
    extern "C" int f();
    static int static_func() { return f(); }
  }
  extern "C" int g() { return static_func(); }

1/30/04  GNU mode: "long" and typedefs

In GNU modes the "long" specifier can now be combined with a typedef type
that is a synonym for "long int" or "unsigned long int."  The extra "long"
specifier has no effect (i.e., the resulting type is still "long int" or
"unsigned long int").  For example:

  typedef long L;
  typedef L long LL;  // "long" keyword is ignored.

1/30/04  UPC mode: Predefined macros

In UPC mode the macros __UPC__ and __UPC_VERSION__ are now predefined.
In addition, either the macro __UPC_DYNAMIC_THREADS__ or the macro
__UPC_STATIC_THREADS__ is defined, depending on whether the number of
UPC threads is dynamic or not.

1/30/04  GNU mode: Spurious error on format attribute

When the last argument of the GNU attribute "format" (which specifies the
first argument to check against a format string) is zero, GNU compilers
only check the indicated format string for consistency and do not verify
that the format string matches the types of the arguments.  Previously,
the front end issued an error in such cases.  Now it silently ignores
such attributes (in GNU mode).  For example:

  int f(int, char const*, ...) __attribute__((format(printf, 2, 0)));
                   /* Previously an error.  Now the attribute is ignored. */

1/29/04  Module IDs in files containing only namespace and/or class members

Module IDs are used to generate unique names for entities such as members
of unnamed namespaces.  When possible, the module ID is based on the name
of an external entity defined in the translation unit.  The module ID routine
sometimes failed to find an external entity to use as the basis for the module
ID in translation units containing only namespace and/or class members.
Now fixed.

  struct S { int f(); };
  int S::f() { return 0; }
  namespace { int i; }

1/28/04  Pragmas on explicit specializations

Next-construct pragmas on explicit specializations did not get bound to
the specialization, resulting in their being ignored in the front end and
not being emitted by the C++-generating back end.  Now fixed.

  template <class T> struct A { };
  #pragma test_next_decl abc
  template<> struct A<int> { };
  A<int> c1;

1/28/04  Exception specification mismatch on generated member functions

In some cases involving multiple inheritance, the exception specifications
for generated virtual member functions (e.g., destructors) may be incompatible
with the exception specifications of the corresponding members in the base
classes.  For example:

  struct B1 { virtual ~B1() throw (char) {} };
  struct B2 { virtual ~B2() throw (long) {} };
  struct D: B1, B2 {};  // D::~D() has exception specification
                        // "throw(char, long)" which is incompatible with
                        // B1::~B1() and B2::~B2().

Previously this triggered a warning in all modes.  Now a discretionary
error is issued in strict modes.

1/23/04  Incorrect type deduced from cv-qualified array type

When a type "const T" was deduced from a cv-qualified array type such
as "const int[5]" the resulting type was the cv-qualified type (resulting
in an error on the example below) but should have been the cv-unqualified
version of the type.  Now fixed.

  template <class T> struct A { };
  template <class T> struct  A<const T> : A<T> {};
  A<const int[5]> a;

1/21/04  Internal error on out-of-class partial specialization

An internal error could occur if an out-of-class partial specialization
included a base-clause.  Now fixed.

  struct X {};
  template <class T> struct A {
    template <class T2> struct B {};
  };
  template <class T> template <class T2> struct A<T>::B<T2*> : public X {};
  A<int>::B<char*> ac;

1/21/03  UPC mode: Extensions and improvements

Various changes were made to the front end to extend and improve its support
for UPC constructs.  Specifically:

  - shared [] void * is no longer a valid type (a change introduced
    for version 1.1 of the UPC specifications).
  - #pragma upc coherence [save | restore] is now supported.
  - conversions involving shared UPC types are now more strictly
    checked (e.g., implicit conversions between shared and non-
    shared types are now diagnosed).
  - THREADS-dimensioned arrays are now more strictly checked
    (e.g., multidimensional array types with multiple THREADS-
    dependent dimensions are now diagnosed).

1/21/04  Warnings detected during command-line macro processing

During command-line macro processing the front end maps all diagnostics
into a generic "invalid macro definition" command-line error.  This had
the surprising effect of translating an "invalid macro redefinition" warning
into an error.  Even more surprising, the error would go away if the
--no_warnings option was used.  To avoid these surprises, warnings and
remarks that occur while processing command-line macro definitions are
now suppressed.

1/20/04  Space use improvement with CHECKING code

When using checking code, bit fields in data structures have generally
terminated with a "bitfield_to_avoid_codecenter_warnings" entry.  This
entry is now included only if the CENTERLINE_CHECKING macro is also set.
In addition, this entry had the type "unsigned int:2" but should have been
"a_bit_field:2".  This resulted in wasted space when compiling the front
end with Microsoft compilers.  The type of the entry has now been changed
to "a_bit_field:2".

1/20/04  Template argument deduction with arrays with added qualifiers

When calling a function template, the standard permits the parameter
type to be more cv-qualified than the argument, when the parameter is
a reference type.  The front end did not correctly handle cases in
which an array type was more cv-qualified than the argument array.
This would result in the function being discarded by the type deduction
process.  Now fixed.

  template <class T, int I> void f(const T (&array)[I]) {}
  int main() {
     int a[] = { 1, 2, 3 };
     f(a);
  }

1/16/04  Missing type_info virtual function table with multiple translation
         units

In some very obscure test cases where the runtime library file
that defines the type_info class member functions is compiled
as a secondary translation unit with a primary translation unit
that that uses the class, the virtual function table definition
for type_info was not put out even though the decider function
definition is present.  Now fixed.

1/16/04  GNU mode: Explicitly specified alignment lost

In GNU C and C++ mode, an alignment specified with the GNU attribute "aligned"
was sometimes subsequently ignored.  For example (assuming "int" is 4-byte
aligned):

  typedef int I64 __attribute__((aligned(64)));
  I64 x;
  int a = __alignof__(x);  // a was erroneously set to 4 instead of 64.

This is now fixed.  (Note that GNU compilers also sometimes lose track
of the "aligned" attribute and that in those cases the behavior of the
EDG front end will differ from that of the GNU compilers.  Before this
change, the behavior could differ also because the circumstances in
which the attribute was lost were different.)

1/15/04  Microsoft compatibility: __declspec(selectany) ignored in some cases

In Microsoft mode with microsoft_version >= 1300, the front end accepts the
__declspec(selectany) specifier on certain variable definitions with no
initializer, but the specifier was not recorded in the IL.  For example:

  __declspec(selectany) int x;  // Accepted in Microsoft mode, but previously
                                // treated identically to plain "int x;".

This is now fixed.

1/15/04  Microsoft compatibility: Spurious duplicate definition error on
         selectany variables

In Microsoft mode, when compiling multiple translation units simultaneously,
the front end diagnosed as an error multiple definitions of a variable 
declared with __declspec(selectany).  For example:

  // File 1:
  __declspec(selectany) int x = 1;

  // File 2:
  __declspec(selectany) int x = 1;  // Can coexist with definition in File 1,
                                    // but the front end issued an error.

This is now fixed (i.e., such code is now accepted).

1/12/04  GNU C++ mode: Class types with size zero

In GNU C++ mode, structs containing only data members of zero-length array
types now have size zero.  (Note that empty class types still have size 1.)
For example:

  struct S0 { int a[0]; };  // sizeof(S0) == 0 in GNU C++ mode.
                            // (Previously, sizeof(S0) == 1 in GNU C++ mode.)
  struct S1 {};             // sizeof(S1) == 1 in GNU C++ mode.

1/11/04  copy_node did not copy partially-lowered function prologue EH nodes
         correctly

In some modes, there are some expression nodes used to represent
partially-lowered exception handling constructs.  copy_node did
not handle copying an enk_lowered_eh_construct/leck_function_prologue
node correctly (a copy of the prologue entry was not allocated).
Now fixed.  It's not clear that it was possible to run into this
problem in the standard version of the front end, but it was
wrong anyway.

1/11/04  Abort in pm_class_type, with RECORD_CONSTANT_EXPRESSIONS_IN_IL and
         IL lowering

In a configuration with DO_IL_LOWERING and RECORD_CONSTANT_EXPRESSIONS_IN_IL
both TRUE, an abort could happen when the IL walk routines walked the
unlowered expression attached to a lowered constant and encountered
a lowered pointer-to-member type attached to an unlowered
pointer-to-member operation.  The abort was in pm_class_type,
called from walk_entry.h/il_walk.c.  Now fixed.

1/9/04   GNU C mode: abort on incorrect array initializer

The front end aborted on certain incorrect array initializers in
GNU C mode.  The simplest such case involves an attempt to
initialize an array to the value of another array:

  char y[3];
  char x[] = y;  // Aborted in gcc mode

Now fixed.

1/9/04   Name mangling without IL lowering

Some minor changes have been made in fe_wrapup.c to support the
combination of name mangling without IL lowering (DO_IL_LOWERING
FALSE).  Formerly, it was thought that setting NEED_NAME_MANGLING
was enough to get that combination, but the mangling routines were
present but not called for all names in such a configuration.
Therefore, a new macro MANGLE_ALL_NAMES has been added, which
indicates that all names should be mangled.  NEED_NAME_MANGLING
is be set by default if MANGLE_ALL_NAMES is set, so it need not
be set explicitly.

1/8/04   C/C++-generating back end: system header flag on line directives

When generating code for gcc/g++, old-style line directives are now emitted by
default, and the system header flag is included on the line directive if the
source file was found in a system include directory.

1/7/04   C++-generating back end: Microsoft-specific declaration modifiers in
         explicit instantiation directives

In Microsoft mode, the C++-generating back end failed to render certain
declaration modifiers (like __declspec(...)) appearing on explicit
instantiation directives.  For example:

  template <class T> inline __declspec(dllimport) void f(T) {}
  template __declspec(dllimport) void f(int); // C++-generating back end
                                              // previously dropped the
                                              // "__declspec(dllimport)".

This is now fixed.

1/7/04   Microsoft and GNU C++ compatibility: incomplete types in
         class template prototype instantiations
	 
In Microsoft and g++ modes, a nonstatic data member can have an incomplete
type in a class template prototype instantiation.

  class B;
  template <class T> struct A {
    B b;  // Allowed in GNU and Microsoft modes
  };
	 
1/6/04   Argument-dependent lookup was not suppressed by parentheses

Argument-dependent lookup is supposed to be suppressed on a
call in which the function name is surrounded by parentheses,
as in (f)(x).  That was done correctly when the function is
not overloaded, but when the function is overloaded
argument-dependent lookup was done anyway.  Now fixed.

  void f(...);  //1
  void f();     //2
  namespace N {
    struct A {};
    void f(A);  //3
  }
  int main() {
    N::A a;
    (f)(a);  //1 is called now; formerly, 3 was called
  }

In a related change, a field has been added to the IL an_expr_node
entry: arg_dependent_lookup_suppressed_on_call indicates that
argument-dependent lookup was suppressed on a call node, and is
used in the C++-generating back end to restore the parentheses
around the function name in cases like the above.

1/6/04   GNU C99 mode: Return type of certain built-in functions

In GNU C99 mode, built-in functions __builtin_creal, __builtin_crealf,
__builtin_creall, __builtin_cimag, __builtin_cimagf, and __builtin_cimagl
were (erroneously) predeclared with complex return types.  This has been
fixed by changing the return types to the corresponding real types.  For
example, __builtin_cimag now returns type double instead of complex double.

1/6/04   Wrong array element size in EH info for multi-dimensional array

The information added by IL lowering to support exception handling
(in the fully- or partially-lowered configurations) had an incorrect
element size in the information for a multi-dimensional array.
The size was the size of the first-level element (which is
still an array), where it should be the size for the
ultimate underlying element type.  The incorrect size meant
that destructions of multi-dimensional arrays on exceptions
would destroy the right number of elements but with the wrong
spacing, which meant that most of the addresses passed to a
destructor were incorrect.  Now fixed.

  struct A {
    int i;
    A();
    ~A();
  };
  int main() {
    A x[2][3];
    throw 0;  // Spacing on destructions of x was wrong.
  }

1/5/04   Spurious error on reinterpret_cast in template

A spurious error was issued on a reinterpret_cast involving a
pointer to a template parameter type in modes that parse
the bodies of template functions, e.g., strict mode.  Now
fixed.

  void (*call)();
  template<typename FType>
  void attempt(FType * p) {
    reinterpret_cast<FType *>(call);  // Formerly got an error
  }

1/5/04   Incorrect side effect analysis on dynamic_cast

The determination of whether an expression has side effects was
wrong for some dynamic_casts to reference types, specifically
those that cast from a polymorphic type to a non-polymorphic
type.  Formerly, the code concluded that such casts did
not have a potential side effect, when in fact they do: they
can throw an exception.  This error could cause code to
be removed and the exception not to be thrown.  Now fixed.

  struct A { };
  struct B {
    virtual void f() {}
  };
  int main() {
    B *p = new B;
    dynamic_cast<A &>(*p);  // Throws exception, has side effect
  }

In a related nit, the needed-flag walk did not correctly
note that a dynamic_cast to a reference-to-class type requires
that the underlying class type be complete.  Also fixed.

1/5/04   Microsoft compatibility: Restrictions on __interface types

Two changes were made to the verification of restrictions on __interface
types in Microsoft C++ modes.  First, the front end now accepts __interface
types with property fields.  For example:

  __interface I1 {
    __declspec(property(get=Get, put=Put))
      int i;  // Now accepted in Microsoft C++ mode (previously an error).
    int Get(void);
    void Put(int);
  };

Second, the front end now issues an error when "private" or "protected"
specifiers appear in __interface types.  For example:

  __interface I2 {
  private:     // Now an error (previously accepted) in Microsoft C++ mode.
    void f();
  };

12/27/03 C++-generating back end: removing non-public member typedefs

The C++-generating back (with help from the il_to_str routines)
has been removing non-public member typedefs used in template
arguments (and using the underlying type instead), to avoid some
accessibility problems.  Now, that processing has been generalized
and is used for all type references, with the added constraint
that the typedef is removed only when the reference is not inside
the associated class.

12/21/03 C99 printf specifiers: hh, j, z, and t

C99 added several length specifiers for printf/scanf specifiers:
"hh" for char, "j" for intmax_t, "z" for size_t, and "t" for
ptrdiff_t.  The Front End now recognizes them.

12/21/03 C99 allows "ll" length on "n" printf specifier

The "n" specifier for printf in C99 allows a "ll" length specifier
for long long.  The Front End now recognizes such a length.

12/19/03 Missing error on invalid non-class destructor call

No diagnostic was issued when an explicit destructor call for a non-class
type used a qualified name that names a class without an explicitly declared
destructor.  Now fixed.

  struct A { };
  int main() {
    int x;
    x.A::~A();
  }

12/19/03 C99 mode error on very large integer constant

According to the C99 standard, a decimal integer constant with
no suffix has the first of the following types into which the value
will fit: int, long, long long.  The Front End end had been adding
another type at the end of that list: unsigned long long.
That extra type has now been removed, but that causes a strange
behavior, i.e., that a constant that could be represented as
an unsigned long long but not as a long long is considered to be
an error.  We've chosen to issue a warning (even in strict
mode) and treat the constant as unsigned long long, as before.
This is an interim solution until the C committee rules on this,
and desirable because both Perennial and Plum Hall have tests
with such constants, so errors are disruptive right now.

12/18/03 Possible incorrect memory reuse when using precompiled headers

Although this has not been observed in released versions of the front end,
it is possible that under certain unusual circumstances when using a
precompiled header file, the same block of memory could be allocated for
two different purposes.  This could result in aborts and/or other kinds
of incorrect behavior. Now fixed.

12/18/03 Problem with precompiled headers when not using mmap

When USE_MMAP_FOR_MEMORY_REGIONS is FALSE. a problem introduced in
version 3.0 would cause an "error while writing PCH file" catastrophic
error.  Now fixed.

12/17/03 C99 has "F" conversion specifier for printf

C99 added an "F" conversion specifier for the library functions in
the printf/scanf family.  It is now recognized by the Front End
in C99 mode.

12/17/03 printf conversion specifiers for long long are standard in C99

The conversion specifiers for long long types for the library
functions in the printf/scanf family are standard in C99.
Therefore the front end has been changed not to issue warnings
on those.  The warnings are not issued in all modes, not just
strict C99 mode.

12/17/03 Variable pragma_defined_type_info_is_required is misspelled

The global variable pragma_defined_type_info_is_required should be
called pragma_define_type_info_is_required, to match the macro
PRAGMA_DEFINE_TYPE_INFO_IS_REQUIRED.  Now changed.

12/15/03 Namespace of va_list type when using --ignore_std

When passing stdarg references in the generated code and
DEFAULT_VA_LIST_IN_STD_NAMESPACE is TRUE, the example below would
fail when using the --ignore_std option (because the va_list type is
entered into the std namespace, which is then ignored).  Now fixed.

  #include <cstdarg>
  namespace std {
    va_list xxx;
  }

12/15/03 Shareable constants table performance improvement

The size of the shareable constants table has been increased to improve 
performance when compiling large programs.

12/15/03 Default for HOST_ALIGNMENT_REQUIRED incorrect in some cases

The default value computed for HOST_ALIGNMENT_REQUIRED was too conservative
in some cases (when INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is FALSE and
LONG_LONG_ALLOWED is TRUE).  This resulted in an assertion failure in
check_host_alignment_parameters.  Now fixed.

12/15/03 Constant format string not checked when cast

The front end normally checks printf- and scanf-style format string literals
and issues warnings when they are not followed by appropriate arguments in
calls to functions marked with the appropriate #pragma or GNU attribute.
However, if the front end applied a cast operation to such a string (e.g., to
"char const*"), it no longer performed this sort of checking.  The problem was
particularly likely to occur in combination with the GNU attribute format_arg.
This is now fixed: String constants can also be checked as format strings
when cast.

12/15/03 GNU mode: Attribute format sometimes without effect

In GNU mode, the format attribute was sometimes lost when the declaration
specifying the attributes was followed by a definition without attributes.
For example:

  void f(int, char const*, ...) __attribute__((printf, 2, 3));
  void f(int, char const*, ...) {}
  int main() {
    f(2, "%s");  /* Warning was not issued.  Now fixed. */
  }

This is now fixed.

12/15/03 Build problem on Solaris when not using GNU extensions

When building the front end on Solaris without enabling GNU extensions, the
attribute_init routine is called without being declared.  This could cause
a build failure depending on how the front end is being built.  Now fixed.

12/12/03 GNU IA-64 ABI: Virtual empty base allocated at bit-field offset

GNU C++ 3.3.x has a bug that causes it to sometimes place a virtual empty
base at the same location as a trailing bit field in another virtual base.
This bug is now emulated when the front end is configured to emulate ABI
bugs of GNU C++ 3.3.x.  For example:

  struct E {};  // Empty class
  struct B: virtual E {
    int i: 2;
  };
  struct D: E, virtual B {};
    // The virtual base E in D should be allocated after the virtual base B,
    // but GNU C++ 3.3 allocates it at the same offset as the bit field of B.

The emulation of other versions of GNU C++ is unchanged.

12/11/03 Folding of division by zero in not-evaluated operand of initializer

Divisions by zero (and some similar cases that aren't foldable to
a constant) are now folded away when they appear in a not-evaluated
operand of a "?", "&&", or "||" operator in an initializer
expression that could be a static initialization.  This overrides the
setting of ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS in
that context.

  int i = 1 || 1/0;    // Both now folded to constants
  int j = 1 ? 1 : 1/0;

12/11/03 Export inadvertently disabled if ABI_COMPATIBILITY_VERSION not set

Version 3.3 added the EXPORT_ENABLING_POSSIBLE macro to let customers disable
the export feature.  The code that determines the default value for this
macro did not work properly if ABI_COMPATIBILITY_VERSION was not set.  This
would result in the disabling of the export feature.  Now fixed.

12/10/03 Incorrect template file names when using COMPILE_MULTIPLE_SOURCE_FILES
	 
When COMPILE_MULTIPLE_SOURCE_FILES is TRUE and when more than one source file
name has been passed to the front end, the template file names used for
the first source file are reused for subsequent source files; new names
should be generated for each source file.  This affected the template
information file name (.ti), the instantiation request file name (.ii), and
the exported template file (.et).  Now fixed.

12/10/03 eok_jdivide in C-generating back end, LOWER_COMPLEX FALSE

When LOWER_COMPLEX is FALSE, C99 complex operations are not
eliminated by lowering and therefore they are passed to
back ends.  The C-generating back end did not handle
eok_jdivide and eok_xnegate.  They have now been added.

12/10/03 Promotion of long long bit fields in GNU modes

In GNU C and C++ modes, long long and unsigned long long bit fields
now promote to long long and unsigned long long even if they will
fit in some smaller type.  See the similar change for Microsoft
mode on 8/4/03.

12/10/03 Array rvalue to pointer decay in Microsoft C mode

An array rvalue now decays to a pointer in Microsoft C mode
in addition to the other modes (C99, C++) in which that
was already done.

12/10/03 __PRETTY_FUNCTION__ in GNU C mode

__PRETTY_FUNCTION__ in GNU C mode is now the same as __FUNCTION__,
i.e., the result is the simple name of the function.

12/10/03 Concatenation of string and __FUNCTION__

In modes where the __FUNCTION__ keyword is treated as a string literal
(i.e., GNU C and Microsoft C/C++), the front end now correctly
concatenates a string literal followed by __FUNCTION__.

  void test2() {
    char function_string[] = "Function " __FUNCTION__;
  }

12/10/03 Compilation problem in lower_init.c, MAINTAIN_NEEDED_FLAGS FALSE

Part of lower_init.c did not compile correctly when MAINTAIN_NEEDED_FLAGS
is FALSE and GNU_INIT_PRIORITY_ATTRIBUTE_ALLOWED is TRUE.  Now fixed.

12/10/03 C++-generating back end: Abort in tag_keyword on enum specifier

In configurations where MICROSOFT_EXTENSIONS_ALLOWED is TRUE, the C++-
generating back end sometimes triggered an internal error in function
tag_keyword while generating an enum specifier.  This is now fixed.

12/9/03  Argument-dependent lookup and block extern declarations

Core issue 239 says that if the name found in a call is a
block-extern declaration, argument-dependent lookup is suppressed.
The front end has done that for a long time in default mode,
but not in strict mode.  Now, strict mode suppresses the
argument-dependent lookup as well.  However, in the past
default mode has done the same on finding a local using-declaration,
and the resolution to core issue 239 explicitly excludes that
case.  Therefore, we no longer suppress argument-dependent
lookup in default mode on a name that is a local using-declaration.

  struct B {};
  void f(B, int) { printf("f(B, int)\n"); }
  void f(B, double) { printf("f(B, double)\n"); }
  int main() {
     void f(B, double);
     f(B(), 1);  // Now calls f(B, double) in strict mode
  }

12/9/03  Qualified class type in explicit destructor call

A spurious error was issued if a cv-qualified type was used when naming the
destructor in an explicit destructor call.  Now fixed.

  template <class T> struct A { };
  template <class T> void f( void ) {
    T t;
    typedef const T TT;
    t.TT::~TT();
  }
  int main() {
     f< A<int> >();
  }

12/9/03  Spurious warning on "if" of weak external symbol

The front end gave a warning ("controlling expression is constant")
on a conditional test of the address of a function that is a weak
external.  However, since the point of a weak external is
that sometimes its address is zero, the warning was spurious.
It's no longer issued.

  extern void func(void) __attribute__((weak));
  void try_func(void) {
    if (func)  // Formerly got a warning
      func();
  }

12/8/03  C/C++-generating back end: asm constructs for GNU C compilers

Previously the C- and C++-generating back ends always put out asm constructs
using the "asm" keyword, but GNU C compilers do not treat "asm" as a keyword
in all modes.  For example, in C99 mode, the GNU compiler accepts "__asm__"
as a keyword, but not "asm".  When gcc_is_generated_code_target is TRUE, the
C- and C++-generating back ends therefore now generate the "__asm__" keyword
for asm statements.

12/2/03  Abort in num_array_elements on variable-length array new

An abort in num_array_elements in types.c has been corrected.
It came up while lowering a "new" operator for an array with
non-constant length where the array element type does not
have a constructor or destructor, and for which zeroing
is requested via the "()" value-initialization syntax.
Similar cases compiled without abort in version 3.1, but
the generated code did not correctly zero the array.

  struct T { int t; };
  T* f(int i) { return new T[i](); }

12/2/03  C/C++-generating back ends and GNU __builtin_va_list

When GCC_BUILTIN_VARARGS and GCC_BUILTIN_VARARGS_IN_GENERATED_CODE were TRUE
the C- and C++-generating back ends sometimes transformed occurrences of
"__builtin_va_list" to "void*".  This is not entirely wrong (since the
former is a built-in typedef for the latter), but keeping the original
form is generally preferred.  For example:

  void f(__builtin_va_list);  // Previously rendered as "void f(void*);"

The original form is now preserved.

12/2/03  Microsoft compatibility: Spurious correspondence error with
         dllimport/dllexport

When compiling multiple translation units in Microsoft mode, the front end
incorrectly treated as incompatible routine declarations that only differ
in their dllimport/dllexport specifiers.  For example:

  // File 1:
  __declspec(dllimport) void f();

  // File 2:
  __declspec(dllexport) void f() {}  // Compatible with declaration in File 1,
                                     // but previously a correspondence error
                                     // was issued.
This is now fixed.

12/1/03  C/C++-generating back ends and Microsoft __declspec(noreturn)

The C- and C++-generating back ends were not reproducing the Microsoft
__declspec(noreturn) specifier when it appeared in the input source.
In turn this could cause diagnostics when compiling the generated code.
For example:

  __declspec(noreturn) void f();
  int g() {  // Should return a value or not return at all.
    f();     // Will never return, so no return statement needed.
  }          // Without the __declspec(noreturn), an error may be issued.

This is now fixed.

12/1/03  C++-generating back end: Function declarations using GNU typeof

In GNU mode, the C++-generating back end incorrectly rendered some function
declarations that used the GNU typeof construct.  For example:

  void f();
  typeof(f) g; // Previously rendered as: typeof(void(void)) g();
               // Now corrected as: typeof(void(void)) g;

This is now fixed.

11/26/03 Exception handling cleanup in constructor/destructor function
         try blocks

The cleanup code invoked for a thrown exception inside a function
try block of a constructor or destructor did not correctly
destroy the members and bases of the class.  Now fixed.

  struct A { A(); ~A(); };
  struct B {
    A a;
    B() try : a() {
      A a;
      throw 0;  // Member "a" was not destroyed on throw
    } catch (...) {
    }
  };

11/26/03 Microsoft compatibility: Spurious class type correspondence error

When simultaneously processing multiple translation units in Microsoft mode,
the front end sometimes issued a spurious correspondence error on class types.
The error was caused by having the "inheritance kind" set implicitly in one
translation unit, but not in the other.  For example:

  // File 1:
  struct S { void f(); };
  void (S::*pm)() = &S::f; // Causes the inheritance kind of "S" to be set

  // File 2:
  struct S { void f(); };  // A correspondence error was issued because the
                           // inheritance kind of "S" is not set in this
                           // translation unit.

This is now fixed.

11/26/03 C++-generating back end: Duplicate GNU attributes and specifiers

When generating code for GNU compilers, the C++-generating back sometimes
duplicated certain function attributes and the "extern" storage class
specifiers for "extern __inline__" functions.  This is now fixed.

11/24/03 GNU mode treatment of "st" floating-point stack register

When GNU_X86_ASM_EXTENSIONS_ALLOWED is set, the front end accepted the
floating-point stack register names "st", "st0", and "st(0)" in GNU modes
and treated them all as synonyms.  Furthermore, the C- and C++-generating
back ends generated "st(0)" when any of these variants appeared in the input.
However, it appears the GNU C and C++ compilers do not actually recognize
the "st0" and "st(0)" variant spellings of the register name.  For example:

  long f(double x) {
    long r;
    __asm__ __volatile__ ("fistpl %0" : "=m" (r) : "t" (x) : "st");
      // "st" was rendered as "st(0)" by the C- and C++-generating back ends.
    return r;
  }

This was fixed by no longer recognizing the "st0" and "st(0)" variations,
and by having the back ends render the register as "st" in all cases.
In addition, the named register tag "anr_st0" was renamed to "anr_st"
for clarity and consistency (this is an IL CHANGE).

11/23/03 In C99, & followed by * cancels out

According to section 6.5.3.2 of the C99 standard, a "&" operator
over a "*" operator cancels out both, so something like "&*x"
is equivalent to "x".  This is significant when "x" is a pointer
to void, because "*x" in that case is not an lvalue.  The
cancellation is now implemented.

In a related tweak, the end position on the operand for "*x"
in the above is now correct.  Formerly, it was one column too
high.

11/21/03 IA-64 ABI, excess zeroing on value-initialization

In a case like the following, the code generated by IL lowering
for a value-initialization under the IA-64 ABI zeroed some memory
where that is not required.  That shouldn't break anything, but
it's inefficient.  Now fixed.

  struct B {
    B() {}
    int a;
    char b;
    virtual void f() { };
  };
  struct D : public B {
    D() : B() {}  // Base class "B" should not be zeroed because it has
                  // a user-declared constructor
  };

11/21/03 IA-64 ABI, C-generating back end: constructor with ellipsis

The code generated by the C-generating back end for a constructor
with an ellipsis (i.e., a variable-length argument list) did not
work correctly in the IA-64 ABI, where an alternate entry point
for the constructor needs to call the primary constructor
routine (and can't pass the argument list correctly).  The
C-generating back end has been changed to use the same technique
already used for covariant return type functions and thunks,
i.e., duplicating the body of the underlying function in the
wrapper function.  A field (primary_ctor_or_dtor) has been 
added to the IL a_routine entry to make it easy to get
from the alternate entry point to the underlying primary
routine.

As part of this change, a minor optimization was done in the
code for IA-64 thunks when the return type is not covariant.
Some unnecessary code that assigned the return value to a
temporary and then returned the temporary is no longer emitted.

11/20/03 Using sizeof on a template static data member with an incomplete 
         array size
	 
The standard is unclear about what should happen if the sizeof operator
is applied to a template static data member with an incomplete array size.
This construct is unusual because it requires that the static data member be
instantiated immediately in order to determine the size of the array.  The
front end now does such instantiations, when possible.  An instantiation
cannot be done if there is no definition of the static data member present,
if the definition is provided by an exported template, or if the definition
is provided by an implicitly included file.  Even though the instantiation
is performed, the rules for determining whether the definition of the static
data member should be emitted in the generated code have not changed.  So,
for example, compiling the example below will still not result in the static
data member being emitted in the generated code.
	 
  extern "C" int printf(const char *, ...);
  template <class T> struct A { static int i[]; };
  template <class T> int A<T>::i[5];
  int main() {
    printf("%d\n", sizeof(A<int>::i));
  }

([04/20/04: The changes for this issue also fix a problem where the
C-generating back end would in some cases drop the dimension of an
instance of a static data member array.)

11/20/03 Abort in inline_function_fixup_for_class

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE,
the front end would sometimes trigger an internal error in function
inline_function_fixup_for_class for some situations where a function
template instance was only referenced as a friend declaration.
For example:

  template<typename T> void f(T&) {}
  template<typename T> struct S {
    friend void f<>(S&);
  };
  template<typename T> void f(S<T>&) {}
  struct X {
    struct N {};
    friend void f<N>(S<N>&);
    S<N> m;
  };

This is now fixed.

11/19/03 GNU mode: built-in functions in constant-expressions

In GNU modes, the front end now evaluates certain calls to built-in functions
at compile time, which allows these calls to appear in constant-expressions.
Currently, calls to __builtin_huge_valf, __builtin_huge_val, and
__builtin_huge_vall are evaluated.  In addition, calls to __builtin_nanf,
__builtin_nan, and __builtin_nanl are evaluated if they are called with
an argument that is the empty string literal.  For example:

  float f = __builtin_nan("");  // Accepted in GNU C mode because the
                                // call is treated as a constant.

These functions appear in constant-expressions in the C++ header <limits> of
GNU C++ version 3.3.  (The built-in pseudo-functions __builtin_constant_p and
__builtin_classify_type were already evaluated at compile time in previous
versions of the front end.) 

11/19/03 Memory allocation problem with multiple translation units

A problem in the way in which memory was allocated when using multiple
translation units could result in memory corruption.  Now fixed.

11/19/03 C++-generating back end: Invalid specializations in class scope

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE the
front end sometimes generated a source sequence entry for an incomplete
instantiation of a namespace scope entity in a class scope.  This in
turn caused the C++-generating back end to produce an invalid explicit
specialization of the namespace scope entity in the class scope.
In most cases, however, there is no need to declare an explicit
specialization if it does not actually define the specialization.
The front end therefore no longer produces source sequence entries for
incomplete instantiations of namespace scope entities appearing in class
scope.

11/18/03 Default argument on definition of member of class template

In certain modes (Microsoft, g++, and Sun) a default argument may be
specified in the out-of-class definition of a member function of a
class template.  A variable that controls this feature has been added
to make it easier for customers to enable this feature in other cases.
The variable is allow_default_arg_on_template_member_definition.

  template <class T> struct A { void f(T); };
  template <class T> void A<T>::f(T value = T() )  { }

11/18/03 C++-generating back end, __FUNCTION__ and the like

The C++-generating back end incorrectly passed through
references to the name of the current function (e.g.,
__FUNCTION__, __PRETTY_FUNCTION__) in contexts like
member function bodies.  They came out as references to
the identifier that appeared most recently preceding
the function-name reference.  Now fixed.

  void g(const char *);
  struct A {
    void f() { g(__FUNCTION__); }  // Output was g(g)
  } a;
  int main() {
    a.f();
  }

The bug was in the name given to a generated variable,
so this problem was actually visible even in versions
that do not use the C++-generating back end, though
usually the incorrect name was harmless.  For
non-C++-generating back end versions, the variable
now has no name.

11/17/03 Error on non-POD class type fetched by built-in va_arg

An error is now issued on a va_arg for a non-POD class type
when the <stdarg.h> macros are handled as built-ins (see
DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE).  Detecting
this error allows the front end to avoid an abort in
conv_class_operand_to_object_pointer.

11/17/03 Warning on non-POD class type passed via ellipsis parameter

A warning is now issued when a non-POD class type is passed
via an ellipsis parameter.

11/17/03 IL statement traversal routines, (...) handler

The code in traverse_statement did not deal correctly with
an exception handler clause with a null dynamic_init field,
as happens for a (...) handler.  The failure to check for
a null pointer caused an abort.  Now fixed.

11/14/03 C++-generating back end: Spurious references to template parameters

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and/or
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
C++-generating back end sometimes produced specializations containing
references to the parameters of the specialized template.  For example,
the input

  template<class T> struct S {
    template<class U> T f() {}
  };
  S<int> x;

produced the specialization

  template<> struct S<int> {
    template<class U> T f() {}
  };

To resolve this problem, the front end now generates member templates from
prototype instantiations in such situations (provided the needed prototype
instantiations are recorded in the IL, which requires the configuration flag
PROTOTYPE_INSTANTIATIONS_IN_IL to be set to TRUE).

11/12/03 GNU compatibility: const qualifier ignored on extended asm construct

In GNU modes the front end now accepts and ignores (with a warning) a const
qualifier appearing as part of an extended asm construct.  Previously this
caused a syntax error.  For example:

  void f() { asm const ("nop": :); }  // Now accepted in GNU modes.

11/11/03 Microsoft compatibility: Explicit reduction of alignment ignored

In Microsoft mode, the front end now ignores (with a warning) attempts to
reduce the alignment of a type using a __declspec(align(...)) construct on
a typedef declaration.  For example (assuming a 4-byte aligned int type):

  struct S { int i; };                      // S is 4-byte aligned.
  typedef __declspec(align(2)) struct S T;  // T is also 4-byte aligned
                                            // (and a warning is issued).

11/11/03 Microsoft compatibility: use of ambiguous template name accepted

If a scope contains a declaration of a class template and a using-directive
would make the name ambiguous, the Microsoft compiler uses the class template
in the scope.  We now emulate this behavior in Microsoft bugs mode.

  namespace N {
    template <int I> class X {};
  }; 
  using namespace N;
  template <class T> class X {};
  X<int> xi;  // uses ::X

11/11/03 GNU mode: Loss of some attributes in some configurations

In configurations with GNU_X86_ATTRIBUTES_ALLOWED set to FALSE, the
attributes "noreturn" and "const" on function declarations were lost
if those declarations were followed by definitions without those
attributes.  For example:

  void f() __attribute__((noreturn));
  void f() {}  // Attribute of previous declaration was discarded.

This is now fixed (the attributes are retained).

11/11/03 Performance improvement with large numbers of #line directives

On examples with very large numbers of #line directives, the performance
has been significantly improved.  The improvement involves an optimization
in the processing used to convert a sequence number into a source file and
line number.  IL CHANGE: A new IL entry (a_seq_number_lookup_entry) has
been added.  An ordered table of these entries is constructed so that
a binary search can be used to find the file associated with a given
sequence number.  As part of this change, the interface to source_file_for_seq
has changed (the nesting_depth parameter has been removed).

11/7/03  GNU compatibility: Designated initializer syntax

When support for "extended designator" syntax is enabled (e.g., in GNU mode)
the front end now accepts the normal field designator syntax without the
trailing equal (=) token.  For example:

  struct S { int i; } s = { .i 20 };  // Normally should be ".i = 20", but
                                      // accepted as part of support for
                                      // "extended designator syntax."

11/5/03  GNU C++ compatibility: nonstandard template constructor definition

The g++ compiler accepts a constructor definition in which the template
argument list of the constructor name is actually treated as a template
argument list of the enclosing class.  This is now accepted in g++ mode.

  template <int I> struct A { };
  template <> struct A<1> {
    template<class T> A(T i, int j);
  };
  template <> A<1>::A<1>(int i, int j) { }

11/5/03  C++-generating back end: injected template names using g++ target

In the example below, the C++-generating back end emits "N::A<int>" as
"A<int>" in the declaration of "na".  The transformed code does not
compile properly when using g++.  The namespace qualifier is now emitted
when gcc_is_generated_code_target is TRUE.
  
  namespace N {
    template <class T> struct A {};
  }
  namespace M {
    struct B : N::A<int> {
      N::A<int> na;    
    };
  }

11/4/03  Microsoft C mode: __declspec attributes on struct types

In Microsoft C mode the front end now accepts certain __declspec attributes
as part of the elaborated name of a struct definition.  For example:

  struct __declspec(align(8)) S { int i; };
        // Previously only accepted in Microsoft C++ mode;
        // now also in Microsoft C mode.

11/3/03  Superfluous namespace qualifiers in declarations

Standard C++ does not permit a namespace member to be declared in that
namespace with a qualifier that is the namespace itself.  For example:

  namespace N {
    int N::i;  // Not standard C++: Accepted with a warning in GNU and
  }            // Microsoft C++ modes; discretionary error otherwise.

The example above used to trigger a discretionary error in all modes,
but it is now accepted with a warning in GNU and Microsoft C++ modes.
Declarations of templates used to trigger a nondiscretionary error because
of examples like the following:

  namespace N {
    template<typename> void N::f() {}  // Not standard C++: Nondiscretionary
                                       // error unless dependent name
                                       // processing is done.
    struct N { template<typename> void f(); };
    template void f<int>();  // N::f changes meaning when rescanned.
  }

During the instantiation of f<int>, the declarator token sequence "N::f"
is resolved to the struct member in default mode: To avoid surprises we
therefore do not make the error discretionary.  However, when doing
dependent name processing there is no such issue and in such modes we
now treat template declarations with extraneous qualifiers like other
such declarations (i.e., we issue a warning in GNU and Microsoft C++ modes
and a discretionary error otherwise).

10/23/03 GNU mode: Parameter attribute "unused" outside function definitions

In GNU modes the front end issued an error if the attribute "unused" appeared
on a parameter declaration that was not part of a function definition.  Now,
such attributes are simply ignored.

  void f(int __attribute__((unused)) x);  // Previously an error; now OK.

10/23/03 GNU asm constraints: "q" and "Q"

In GNU mode (on configurations which set GNU_X86_ASM_EXTENSIONS_ALLOWED to
TRUE) the front end translated the extended "asm" operand constraints "q"
and "Q" to the same internal representation.  This common representation
was to be treated conservatively as "Q".  In particular, the C- and C++-
generating back ends rendered the "Q" constraint in all cases.  Now distinct
representations are used: The existing aoc_reg_q implies the less strict
constraint "q" and a new constraint aoc_reg_Q corresponds to "Q" (the
previous meaning of aoc_reg_q).  For example:

  void f() {
    int r;
    __asm__("movl $0,%0" : "=q"(r));  // "=q" now preserved (previously
                                      // rendered as "Q").
    __asm__("movl $0,%0" : "=Q"(r));  // Internal representation of "=Q"
  }                                   // changed.

Note that this is an IL CHANGE.

10/22/03 Spurious typedef correspondence error in C mode

When compiling multiple translation units in C mode, the front end issued
spurious correspondence errors for identically-named typedefs of differing
unnamed class types.  For example:

  // File 1:
  typedef struct { int x; } T;
  // File 2:
  typedef struct { int x, y; } T;

(Unlike in C++, this is valid in C.)  This is now fixed.

10/21/03 Microsoft compatibility: diagnostic on use of constructor name

In general, a name like A::A refers to the constructor of A, but in
Microsoft mode it sometimes refers to the injected class name of A.
We treated A::A as an injected class name in some cases where the
Microsoft compiler treated it as a constructor.  This did not affect
any valid programs (as far as we know), but did affect the nature of
the diagnostic message produced for certain error cases.  We have now
refined this feature to more accurately emulate the behavior of the
Microsoft compiler.  Note that the example below results in an error
both with our front end and the Microsoft compiler.

  struct A { A(); };
  void f(void (A::*)());
  int main() {
    f(A::A);
  }

10/21/03 GNU mode: Unused parameters

The front end now no longer issues a remark for unused parameters of a
function definition if the parameter was marked using the GNU attribute
"unused" or if the type of the parameter was so marked.  For example:

  void f(int __attribute__((__unused__)) x) {}  // No remark for x.

10/21/03 C++-generating back end: Nonstandard anonymous union class qualifiers

In some situations, the C++-generating back end was emitting an invented
temporary name to qualify members of nonstandard anonymous unions (a
construct accepted, e.g., in Microsoft C++ mode).  (The problem was visible
only in configurations for which RECORD_FORM_OF_NAME_REFERENCE is FALSE.)
For example:

  struct S {
    struct {  // Nonstandard anonymous union
      int i;
    };
  };
  void f() {
    &S::i;  // Previously rendered as "&S::__Txxxxxxx::i".
  }

This is now fixed.

10/20/03 GNU mode: #pragma pack(n) behavior

Some changes were made to the behavior of the "#pragma pack(n)" construct
in GNU C and C++ modes.  Among them:
  - "#pragma pack(0)" is equivalent to "#pragma pack()".
  - "#pragma pack(n)" clips the value of any "__attribute__((aligned(x))"
    construct applied to a field.  I.e., if x > n, x is replaced by n.
  - If a "#pragma pack (n)" with nonzero n is in effect, bit fields are
    not aligned to n (i.e., bit fields are still packed maximally) but
    the alignment of the enclosing class is updated if needed.

For example (assuming 32-bit ints aligned on 4-byte boundaries):

  #pragma pack(4)
  struct S {
    short f1;      // Size 2, alignment 2.
    int   f2: 17;  // Not aligned on 4-byte boundary; starts at offset 2.
    int   f3: 17;  // Not aligned on 4-byte boundary; immediately follows f2.
    int   f4: 30;  // Not aligned on 4-byte boundary; immediately follows f3.
    short f5;      // Starts at       offset 10.
  };  // Size 12, alignment 4

10/20/03 Spurious error on template static data member with ":" in initializer

A spurious error would result during the instantiation (or, in some modes,
the prototype instantiation) of a template static data member containing a
top-level ":" (i.e., the error only occurred if the colon was not enclosed
by parentheses, etc.).  Now fixed.

  int x;
  template <class T> struct A {
    static int i;
  };
  template <class T> int A<T>::i = x ? 0 : 1;

10/17/03 Microsoft compatibility: Friend definitions in templates

In Microsoft mode, the front end did not always report duplicate definitions
arising from instantiating the bodies of friend function definitions appearing
in class templates.  Since Visual C++ 7.1 has fixed the associated bug, we now
only emulate this behavior when microsoft_version is less than 1310.
For example:

  template<typename T> struct S {
    friend void f() {}
  };
  void f() {}
  S<int> s;  // Does not report a duplicate definition error when
             // microsoft_version < 1310.

Note that when emulating the Microsoft bug (i.e., when microsoft_version is
less than 1310), the EDG front end discards the non-friend definition, whereas
Visual C++ discards the friend definition.  Since normally the two definitions
are identical, this is not usually a problem.

10/17/03 GNU mode: Declaration of __builtin_abort

In GNU C and C++ modes, the built-in function __builtin_abort (see the Changes
entry of 7/30/03) was not correctly predeclared by the front end.  As a result,
calls to this function triggered errors claiming that the call has too few
arguments.  This is now fixed.

10/16/03 Use of RECORD_GENERAL_CONSTANT_EXPRESSIONS_IN_IL vs.
         RECORD_CONSTANT_EXPRESSIONS_IN_IL

The configuration macro RECORD_CONSTANT_EXPRESSIONS_IN_IL was originally
introduced (see Changes entry of 10/18/99) to record the detailed structure
of constant expressions for source analysis purposes.  The introduction of
the IA-64 ABI required this facility for other purposes in some circumstances.
A new configuration macro RECORD_GENERAL_CONSTANT_EXPRESSIONS_IN_IL was
therefore introduced for source analysis applications, so that the original
RECORD_CONSTANT_EXPRESSIONS_IN_IL could be used for cases that are needed by
both the IA-64 ABI implementation and source analysis applications.  However,
a few places that are only needed by source analysis applications were still
guarded by the original RECORD_CONSTANT_EXPRESSIONS_IN_IL macro (mostly uses
of the bit_size_constant field in a_field entries).  This is now fixed.

10/16/03 GNU IA-64 ABI: Spurious padding after base with bit field

GNU C++ 3.3.x has a bug that causes it to sometimes insert extra padding
after a base class subobject whose last field is a bit field.  This bug
is now emulated when the front end is configured to emulate ABI bugs of
GNU C++ 3.3.  For example:

  struct B {
    B() {}
    int f: 30;
  };
  struct D: B {};  // GNU C++ 3.3 (but not 3.2) inserts spurious padding
                   // after base B.

10/16/03 GNU IA-64 ABI bugs: Version-specific bug emulation

A new global variable gnu_abi_bugs_version now controls the GNU C++ compiler
version whose IA-64 ABI bugs should be emulated.  Currently, only versions
3.2 and 3.3 of the GNU C++ compiler are emulated.  (ABI bugs in GNU C++ 3.2
are normally also present in GNU C++ 3.3.  Emulation of bugs specific to
GNU C++ 3.3 is in its very initial stages and therefore not as complete as
the emulation of bugs in GNU C++ 3.2.)  The value of the new global variable
can be set through the new configuration macro DEFAULT_GNU_ABI_VERSION.

10/16/03 Internal error with PROTOTYPE_INSTANTIATIONS_IN_IL

An internal error could occur when PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE
and also using removal of unneeded entities.  Now fixed.

10/13/03 Build problem when IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE
         is FALSE

The front end did not build properly (specifically, cmd_line.c did not compile)
when IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE was FALSE. Now fixed.

10/13/03 Spurious errors on certain uses of function name pseudo-macros

The is_expr_start routine did not handle the special tokens associated
with the function name pseudo-macros properly (__func__, __FUNCTION__,
__PRETTY_FUNCTION__, __FUNCSIG__, and __FUNCDNAME__).  This could result
in spurious errors in certain contexts.  Now fixed.

  int main() {
    throw __PRETTY_FUNCTION__;
  }

10/10/03 UPC mode: Diagnostic on THREADS-dimension arrays

In UPC mode, the front end used to issue an error saying that "only arrays
of a shared type can be dimensioned to a multiple of THREADS" when declaring
a global array with a dimension equal to THREADS.  Now the error diagnostic
more correctly reports that the dimension is nonconstant.  For example:

  int a[3][THREADS];  // Still an error in UPC mode, but better diagnostic.

10/9/03  C99: internal error on invalid hexadecimal floating-point constant

An internal error could result when an invalid hexadecimal floating-point
constant appeared in a context that is processed as pp-tokens.  Now fixed.

  #define MACRO 0x7.
  // extra line is necessary
  MACRO

10/9/03  C99: Rounding of hexadecimal floating-point constants

When converting a hexadecimal floating point value, the front end always
truncated the value to the number of bits available in the given
representation instead of rounding to the nearest value.  The appropriate
rounding is now done.

10/8/03  String literal initializers for template-dependent arrays

The front end used to issue spurious errors when processing string literal
initializers for template-dependent arrays.  For example:

  template<typename T> void f() {
    T s1[2] = "x";  // Used to trigger an error.
    T s2[] = "y";   // Used to trigger an error.
  }

This is now fixed.  (An error is still issued if a real instantiation
produces an array type that cannot be initialized with a string literal.)

10/8/03  Comparison operator overloading and comparisons with "void *"

Operator overloading processing using conversion functions for
built-in equality and relational operators now correctly finds a
common type when one operand is a "pointer to cv void" and the other
is "pointer to cv T", with one or the other of those types being
the result type of a conversion function.

  struct R {
    R();
    operator const char *();
  };
  R x;
  void *p;
  int main() {
    if (x >= p) return 0;  /* Now accepted. */
  }

10/8/03  Use of typename in nonmember using-declarations

The typename keyword is now accepted in nonmember using-declarations.
Even though this is supported, the typename keyword is never necessary
in a nonmember using-declaration; the entity named in such a declaration
is required to be a namespace member, so the qualifier cannot be
dependent.

  namespace A { struct B {}; }
  template<class T> void f() {
    using typename A::B;
  }

10/7/03  IL lowering of lvalue bool increment, wrong constant type

A constant TRUE generated by IL lowering as part of the code
for an increment of a bool value had the wrong type, when the
increment operation is used as an lvalue.  The constant had type
"pointer to bool" instead of "bool".  Now fixed.

  bool j;
  void f() {
    ++j = 0;         
  }

10/7/03  IA-64 ABI: some alternate entry points unnamed

IL lowering for the IA-64 ABI in some cases generated unnamed
entry points for constructors and destructors when the entry
points should have had mangled names.  The cases involved
unnamed classes that get a name for linkage purposes.

  union U { U() {} };
  typedef struct { U u; } S;
  void f() { S s; }  // Complete constructor for S should be _ZN1SC1Ev

Such constructors and destructors would always be generated,
and generally were quite simple (no base classes), and therefore
they were generally inlined, so this was a less significant
problem than it might otherwise appear.

10/6/03  IA-64 ABI with --no_rtti: virtual function table problems

Lowering for the IA-64 ABI did not work right when configured with
SUPPRESS_TYPEINFO_VARIABLES_WHEN_RTTI_DISABLED TRUE and --no_rtti.
First, the virtual function tables generated were incorrect:
they had a missing offset-to-base preceding the null typeinfo
pointer (which means the entries were all off by one position).
Second, base class virtual function tables were sometimes not
generated when required, which caused an internal error in
vptr_index.  Both problems are now fixed.

10/6/03  Microsoft compatibility: nonmember using-declaration of class member

The Microsoft compiler accepts a nonmember using-declaration that refers
to a type member of a class.  We now emulate this behavior in Microsoft
bugs mode.

  class A { typedef int I; };
  using A::I;
  int main () {
    I i = 1;
    return ++i;
  }

10/3/03  GNU compatibility: not-evaluated parts of constant expressions
         can be non-constant

The GNU gcc and g++ compilers allow not-evaluated parts of constant
expressions to include things that ordinarily are not allowed
in constant expressions, for example references to the values of
variables.  This is now emulated in gcc and g++ mode.

  int i;
  int a[ 1 || i ];  // Accepted in gcc/g++ mode

10/2/03  Template argument substitution problem with cv-qualified class types

Template argument deduction would fail when it should have succeeded if
a template argument with a cv-qualified class type was used as the member
class type in a pointer-to-member declaration.  This has been fixed.

  template <class T> void f(void (T::*)(int)){}
  struct X {};
  int main() {
    f<const X>(0);
  }

10/1/03  GNU C++ compatibility: lookup of dependent names

Our emulation of the dependent name lookup rules as implemented by g++
did not handle certain cases properly.  In particular, a function name
made visible by a using-declaration or using-directive was incorrectly
chosen when a name from a dependent base class should have been used
instead.  Now fixed.

  namespace N { void f(); }
  namespace M {
    template <class T> struct A { T f; };
    template <class T> struct B: public A<T> {
      B() { f = 0; };
    };
    B<int> s;
  }
  using N::f;

10/1/03  Compilation problem in lexical.c, with no EDG back end

There was a compilation problem in add_token_to_string in lexical.c
when BACK_END_IS_C_GEN_BE and BACK_END_IS_CP_GEN_BE are both
FALSE and SUPPRESS_RESTRICT_IN_GENERATED_CODE is also FALSE.
Now fixed.

9/30/03  IA-64 ABI: Spurious padding in "size without virtual bases classes"

In IA-64 ABI configurations allowing the reuse of tail padding (configuration
flag TARG_REUSE_TAIL_PADDING set to TRUE), the front end sometimes added
spurious padding to the "size without virtual base classes" field.  (The
exact condition causing this error is complex and fairly rare in practice.)
This could result in layouts that do not conform to the IA-64 ABI
specification.  For example:

  struct E {};
  struct NP {
    NP() {}
    int i;
    char c; // Tail padding can be reused since this is a non-POD.
  };
  struct V: NP, virtual E {};  // The "size without virtual base classes"
                               // erroneously included the tail padding of
                               // base NP.
  struct D: virtual V, E {};   // The size of D and offset of V were too
                               // large.

This ABI change is now fixed when ABI_COMPATIBILITY_VERSION is at least 304.
The previous behavior remains in effect for smaller values of
ABI_COMPATIBILITY_VERSION.


9/30/03  Spurious error on partial specialization parameter with dependent type

A spurious error was issued if a nonspecialized nontype template parameter
of a partial specialization had a type that depended on a template parameter.
This error should only have been issued if the nontype template parameter
value was specialized (e.g., if you replaced one of the "t" parameters
with a constant like "1").  Now fixed.

  template <class T, T t1, T t2> struct A {};
  template <class T, T t> struct A<T, t, t> { };


9/29/03  Spurious error on member partial specialization

A spurious error was issued if a nontype template parameter of a partial
specialization declaration used the type of an enclosing template parameter.
This has been fixed.

  template <class T> struct A {
    template <T t, T t2> struct B {};
    template <T t> struct B<t,t> {};
  };

9/26/03  Abort in find_member_function_template

An abort could occur in find_member_function_template if a class template
with a conversion operator also contained a using-declaration to another
conversion operator.  Now fixed.

  struct A {
    operator int();
  };
  struct X {};
  template <class T> struct B : public A {
    operator X();
    using A::operator int;
  };
  B<int> b;

9/25/03  IA-64 ABI: Flag offset_is_set on generated fields

The flag offset_is_set of a_field entries (present only in configurations
with the IA-64 ABI) was never set for compiler-generated fields.  This could
lead to erroneous object layouts.  This is now fixed.

9/22/03  Microsoft compat: explicit constructors and copy-initialization

In Microsoft bugs mode, some instances of copy-initialization are
treated as direct-initialization to emulate the behavior of MSVC++.
However, constructors marked explicit were considered in such
cases, and MSVC++ does not do that (except in return statements in
VC++ 6.0).  Now, the EDG front end ignores explicit constructors in
such cases.

  struct ParamColor {
    explicit ParamColor(const unsigned char& inValue);
    ParamColor(const unsigned long& inData);
  };
  int main() {
    ParamColor backgroundColor = 0;  // Formerly ambiguous in Microsoft bugs
                                     // mode
  }

9/18/03  Partial ordering failure on dependent qualified name in return type

In certain cases, the partial ordering implementation would fail to prefer
one template over another if the return type of the template involved a
dependent qualified name.  Now fixed.

  struct A {
    typedef void result_type;
  };
  template <class T> typename T::result_type f(T&){}
  template <class T> typename T::result_type f(const T&){}
  int main() {
    const A a = {};
    f(a);  // spurious ambiguity reported on this call
  }

9/17/03  Microsoft compatibility: Static data members and derived class
         qualifiers

In Microsoft mode, the front end accepts static data member definitions
using derived class qualifiers (see Changes entry of 4/27/98).  However,
other member declarations of the parent class used to be invisible to
such definitions.  For example:

  struct B {
    enum { N = 7 };
    static int a[N];
    static int b[N];
  };
  struct D: B {
    enum { M = 7 };
  };
  int D::a[N] = { 1 };  // OK.  (Used to not find "N".)
  int D::b[M] = { 1 };  // OK.  (Used to not find "M".)

Now, member declaration of the derived class and its base classes are
visible in such nonstandard static member definitions.

9/16/03  GNU mode: Exception specifications on assignments and initialization

When assigning or initializing pointers or references to functions, the
front end no longer issues an error in GNU C++ mode when the exception
specifications do not match.  Instead, a warning is issued.  For example:

  int f() throw(int);
  int (&rf)() = f;  // Warning in GNU C++ mode; error in strict mode.
  int (*pf)() throw() = f;  // Warning in GNU C++ mode; error in strict mode.

9/16/03  Pure specifier in templates

The front end used to issue an error on a pure specifier ("= 0") whenever
it couldn't ascertain that the routine on which the specifier appeared was
virtual.  In particular, it issued an error on the following example:

  template<typename> struct B { virtual void f() = 0; };
  template<typename T> struct D: B<T> {
    void f() = 0;  // Used to be an error because D<T>::f() is not known to
  };               // be virtual.  Now accepted.

Now such errors are inhibited while parsing class templates with dependent
base classes because a virtual member function of a dependent base could
match the member with the pure specifier.

9/15/03  Spurious naming of unnamed enum and class types during instantiation

An unnamed enum or class type can acquire a name for linkage purposes
through a typedef declaration.  Normally, the underlying type must be
defined as part of the typedef declaration, but the front end applied
such a typedef name to an unnamed underlying type during instantiation.
For example:

  template<typename T> struct S {
    typedef T NewName;
  };
  template<typename T> S<T>::NewName f(T p) { return p; }
  enum { e };  // Unnamed type
  int main() {
    f(e);  // Used to apply the name "NewName" to the type of e, as if
  }        // the enum declaration had been "typedef enum { e } NewName;"

This is now fixed (the example gets an error because unnamed types should
not be used as template arguments).

9/11/03  IA-64 ABI: Abort on virtual call thunk

In some relatively rare circumstances, the front end could trigger an
internal error when processing a virtual call thunk for the IA-64 ABI.
(This requires that both IA64_ABI and DO_IL_LOWERING be set to TRUE.)
For example:

  struct A { virtual void f(); };
  struct B { virtual void g(); };
  namespace {
    struct D: A, B {
      virtual void g() {}  // Associated thunk triggers internal error.
    };
  }

The internal error was in diag_message ("missing symbol substitution").
This is now fixed.

9/11/03  C++-generating back end: Avoid line break between template name
         and "<" for MSVC++

To work around a bug in MSVC++ up to 7.0, the C++-generating back end
now avoids breaking an output line between the name of a template and
the "<" that begins its argument list.  MSVC++ gets confused if
a #line directive appears at that point.  The workaround is done
only if msvc_is_generated_code_target is true and
msvc_target_version_number is <= 1300.

9/10/03  C++-generating back end: addition to MSVC++ 7.0 workaround

The MSVC++ 7.0 workaround described in the entry of 10/17/02 turns
out to also be needed for namespace qualifiers (the original fix
dealt with leading "::" qualifiers).

9/10/03  C++-generating back end: output of dependent constants in enum
         definition in prototype instantiation

The C++-generating back end incorrectly put out template-dependent
constants in enum definitions in prototype instantiations.
(Prototype instantiations are put out only in some specialized
configurations.)  The output is now corrected.

  template <class T> struct A {
    enum E { x = T::n };  // T::n now put out correctly
    T y;
    A() : y(x) { }
  };

9/9/03   Microsoft compatibility: Duplicate specialization definitions

In Microsoft bugs mode, with microsoft_version equal to 1200 (which
corresponds to Microsoft Visual C++ 6.0), the front end now accepts
and discards duplicate function template specializations.  For example:

  template<class T> int f(T) { return 0; }
  template<> int f(int) { return 1; }  // OK.
  template<> int f(int) { return 2; }  // Accepted, but the body of the
                                       // specialization is discarded.

A warning is issued in such cases.

9/9/03   Microsoft compatibility: binding reference to non-const to
         "new" operation

The MSVC++ compiler apparently allows a reference to non-const to
bind to the result of a "new", even though it does not allow
binding such references to other kinds of rvalues.  This behavior
is now emulated in Microsoft bugs mode.

  int main() {
    int **&r = new int*;  // Accepted in Microsoft bugs mode.
    return 0;
  }

9/9/03   Error in strict C89 mode on too-large constant that fits in
         long long

Strict C89 mode now gives an error on an integer literal that is
too large to fit in "long" or "unsigned long" but does fit in
"long long" or "unsigned long long".

  int main() {
    unsigned long d = 4294967500;  // Error in strict C89 mode, 32-bit long
    return 0;
  }

9/8/03   Failure to lower return-value optimization in unusual case

IL lowering now properly rewrites a dynamic initialization to
a variable that is the return-value-optimization variable for a
function in the case where the class has no copy constructor
and no destructor.  This is a case that can't come up in the
unmodified EDG front end, but can occur if a customer modifies
set_routine_calling_method_flag to implement a different
calling convention.

9/8/03   Spurious error on destructor name using injected template name

A spurious error would result if an explicit destructor call used the
injected class name of a class template in cases where the template itself
was not visible to a normal lookup.  Now fixed.

  namespace N { template <class> struct S { }; }
  void f (N::S<int> *s) {
    s->~S<int>();
  } 

9/5/03   Falling off end of file when looking for "(" after macro name

Preprocessing now stops at the end of a file when looking for the
"(" following a macro name.  It's not entirely clear what the
C and C++ standards say on the point, but there's at least some
evidence that the parenthesis must be in the same file.  gcc
requires that, and adding the limitation fixes an EDG bug with
a #line put out in the middle of an output line when textual
preprocessed output is requested for such a case.

9/3/03   Microsoft compatibility: Nonstandard friend class template

In Microsoft mode, the front end now accepts a friend class template without
a leading template parameter clause if the referenced template is visible.
For example:

  template<typename T> struct F;
  class C {
    friend struct F;  // In Microsoft mode: same as
  };                  // "template<typename T> struct F;"

A special a_template entry is created for such declarations: It has no
text representation (even when RECORD_TEMPLATE_STRINGS is TRUE) and its
template_decl field is always NULL (even when prototype instantiations
are recorded in the IL).

9/3/03   GNU IA-64 ABI: Additional padding and spurious conflicts

The front end has been modified to better emulate the emulation of GNU IA-64
ABI bugs.  Additional padding for trailing empty nonvirtual bases is now 
counted in the "size as a base subobject" (previously, it was only added
for complete objects).  Furthermore, certain spurious GNU-specific empty
base class conflicts are no longer considered if they involve virtual base
subobjects.

9/2/03   Loop in access checking in Microsoft and Sun modes

A change in version 3.3 exposed a bug in the setting of the scope stack
links used for access checking.  This could result in an infinite loop
in the front end in Microsoft and Sun modes (in symbol_tbl.c in
have_particular_member_access_privilege).  Now fixed.

8/29/03  Incorrect space used output for an_overriding_virtual_function

The front end now correctly outputs the space used for
an_overriding_virtual_function entries (when that output is enabled).
Previously, the size of one such entry was computed as the size of a
pointer to the entry.

8/29/03  GNU C++ mode: Attributes on explicit template specializations

In GNU C++ mode the front end now accepts GNU attributes on explicit
template specializations.  For example:

  template<typename> void f();
  template<> __attribute__((deprecated))  // Now accepted in GNU C++ mode.
        void f<void>() {}                 // Previously an error.

8/27/03  Microsoft compatibility: Abort while removing source sequence entry

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was set to
TRUE, the front end sometimes triggered an internal error in Microsoft mode
when attempting to remove a source sequence entry associated with the
definition of a dllimport member function instantiation.  For example:

  template<typename T> struct B {
    __declspec(dllimport) B();
  };
  template<typename T> B<T>::B() {}
  template struct B<void>;  // Used to abort while eliminating the source
                            // sequence entry for the (useless) definition
                            // of B<void>::B().

This is now fixed.

8/26/03  Microsoft compatibility: Explicit instantiation of dllimport class

In Microsoft mode, the front end will no longer instantiate the members of
a class template specialization declared with __declspec(dllimport) when
performing an explicit class template instantiation.  The dllimport specifier
may have been present on the class template definition, or it may have been
added by the explicit instantiation directive.  For example:

  template<typename T> struct S {
    static int d;
  };
  template<typename T> int S<T>::d = 0;
  template struct __declspec(dllimport) S<void>;
    // No longer instantiates S<void>::d and therefore no longer issues an
    // error about providing an initializer for a dllimported member.

8/26/03  Elaborated type specifiers in templates

When an elaborated type specifier using a simple identifier first appears in a
class template, it now introduces the associated type in the nearest enclosing
namespace scope if it is not followed by either a definition of the type or a
semicolon.  Previously, this was not done and redeclaration errors could result
as a consequence.  In Microsoft mode, an internal error was also a possible
consequence.  For example:

  template<typename T> struct S {
    void f(union U*);  // union U now declared in file scope
  };
  U *p;  // Now OK.  (Previously an error because no U was found.)
  template<typename T> void S<T>::f(union U*) {}
         // Now OK.  (Previously an error because this "union U" was not
         // the same as the one declared in the class template definition.
         // In Microsoft mode, this used to trigger an internal error.)

8/22/03  MSVC++ 7.1 fixes empty-macro-argument bug

The MSVC++ empty-macro-argument bug described in the entry of 4/3/97
is fixed in MSVC++ 7.1.  Accordingly, the EDG C++ Front End now
turns off the emulation of that bug when microsoft_version >= 1310.

8/22/03  GNU mode: __builtin_va_start

In GNU C and C++ modes, the front end now accepts __builtin_va_start as a
synonym for __builtin_stdarg_start when GCC_BUILTIN_VARARGS is configured
TRUE.  (The new notation was introduced in version 3.3 of the GNU compilers.)

8/21/03  Abort while determining the correspondence of an unnamed class type

Under some circumstances involving exported templates and an unnamed class
type that acquired a name for linkage purposes through a typedef the front end
triggered an internal error while determining the correspondence for the
unnamed class type.  (This problem was introduced by the fix for the issue
described in the Changes entry of 6/24/03.)

8/21/03  Concatenation of narrow and wide string literals

Adjacent string literals are concatenated into a longer
string literal.  In C89 and C++98, attempting to concatenate
a narrow and a wide string literal causes undefined behavior
(an error with the EDG front end).  In C99, however, it is
well-defined (the result is a wide string literal), and
gcc and g++ also allow it.  Such mixed string concatenation is
now allowed in the appropriate modes.  In the other modes,
a discretionary error is now issued, but the concatenation
is done anyway.

8/21/03  C++-generating back: multi-line #pragmas put out wrong

As of version 3.3, the C++-generating back end started putting out
multi-line pragmas as multiple lines of output (without "\"
line-splice continuations), which does not work.  Now working again.

  #pragma mc_func _clear_lock { \
    "48003403" \
  }

8/21/03  Microsoft compatibility: Abort in C++-generating back end due to
         missing declared_type

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE and
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is FALSE, the
front end sometimes generated a secondary source sequence entry for an
in-class member function template specialization (which is only supported
in Microsoft mode) without setting its declared_type field.  This could
lead to an internal error in the C++-generating back end.  For example:

  template<typename> struct H {};
  template<typename T1> struct S {
    template<typename T2> T1* operator=(H<T2> const&) { return 0; }
    template<> T1* operator=(H<T1> const&) { return 0; }
      // In-class specialization used to generate an invalid secondary
      // source sequence entry.
  };
  template struct S<int>;

This is now fixed.  Note that this same problem was fixed in the previous
version of the front end (see Changes entry of 7/10/03), but that fix did
not work when microsoft_version is greater than 1300.

8/20/03  Lowering of conversion of pointer-to-member to bool

An internal error was issued on an attempt to lower a conversion of a
pointer-to-member-function to bool when the conversion appeared in an
initializer for a static-lifetime object.  The internal error was
in type_change_constant ("integer to bad type").  Now fixed.

  struct S {};
  typedef void (S::*pmf)();
  pmf p = 0;
  bool b = p;  // Formerly got internal error

8/20/03  Abort on address of lvalue cast in constant expression in gcc mode

A use in gcc mode of the "&" operator to take the address of an expression
that is an lvalue cast (i.e., a cast that would ordinarily be considered
to produce an rvalue, but as an extension produces an lvalue) in a
constant initializer expression resulted in an internal error in
extract_constant_from_operand ("bad operand").  The abort could also be
produced in Microsoft C mode in some more complicated cases.  Now fixed.

  int i = 1;
  int *p = &((int)(i));  // Formerly aborted in gcc mode

8/18/03  C++-generating back end: Abort on Microsoft in-class specialization

The C++-generating back end sometimes triggered an internal error caused
by a spurious source sequence entry generated for a Microsoft in-class
specialization appearing in a class template.  For example:

  template<typename T> struct S {
    template<int K> struct N {
      N<K-1> m;
    };
    template<> struct N<0> {};  // Spurious source sequence entry for
    N<3> h;                     // S<void>::N<0> in some configurations.
  };
  struct X { S<void> s; };

This is now fixed.

8/18/03  Compilation speed improvement with multibyte characters

In versions configured to allow multibyte characters in source code,
the function mbc_length was sometimes a bottleneck (it calls the
system C library mblen function, and we have reports that that is
surprisingly slow on Windows).  We have changed mbc_length to a macro,
and added a char_may_begin_multibyte_sequence macro that can be defined
to an appropriate test to short-circuit the call of mblen.  We've
also provided a default version of the macro that works for ASCII-based
encodings.

8/18/03  GNU C++ mode: injected template class name as template template
         argument

According to the standard, an injected class name of a class template
may only be used as a type template argument.  g++ also allows such a
name to be used as a template template argument.  We now emulate this
behavior in g++ mode.

  template <template <class> class T> struct A {};
  template <class T> struct B {
    A<B> a;  // accepted in g++ mode
  };

8/18/03  Compilation problem in il_to_str.c with BACK_END_IS_C_GEN_BE FALSE

il_to_str.c did not compile correctly when both BACK_END_IS_C_GEN_BE
and BACK_END_IS_CP_GEN_BE were FALSE.  Now fixed.

8/17/03  Microsoft compatibility: value-initialization for versions < 7.1

The MSVC++ compiler did not implement value-initialization before
version 7.1.  The EDG C++ Front End therefore now turns off the
zeroing for that feature when microsoft_version < 1310 and
DEFAULT_EMULATE_MSVC_VALUE_INITIALIZATION_BUGS is TRUE.
There are also some cases where MSVC++ did not even zero some things
that were supposed to be zeroed under the previous default-initialization
rules, and those are emulated as well.  This emulation is intended
for customers whose products track uninitialized values in some way,
and is not desirable in general, so it is not turned on by default.

8/17/03  address_taken set on variables referenced by ck_stack_offset

The address_taken flag is now set on variables for which ck_stack_offset
constants have been generated.  Those are used only with partially-
lowered exception handling (DO_FULL_PORTABLE_EH_LOWERING set to FALSE,
GENERATE_EH_TABLES set to TRUE).  Setting the address_taken flag
ensures that back ends will actually assign a stack location for
the variable and not simply keep it permanently in a register.
Note that in most cases address_taken was already set anyway, because
address_taken is set on destructible variables because their
address is taken and used in calling the destructor.

8/16/03  IL display of GNU min/max operators

When we added the GNU min/max operators "<?" and ">?", we failed
to fully update the IL display program.  It didn't correctly display the
opname_kind field of overloaded operator<? and operator>? functions.
Now fixed.

8/16/03  Microsoft compatibility: early versus late tie-breakers

MSVC++ 7.1 has apparently changed to the standard "early" tie-breakers
in overload resolution, where previous versions used the "late"
tie-breakers like Cfront did.  The C++ Front End therefore now
uses early tie-breakers when microsoft_version >= 1310.

  // MSVC++ 6.0, 7.0 output 1
  // MSVC++ 7.1 gets ambiguity
  extern "C" int printf(const char *, ...);
  void f(const int *, int) { printf("1\n"); }
  void f(      int *, char) { printf("2\n"); }
  int *p;
  int main () {
    f(p, 0);
  }

8/14/03  GNU mode: Attribute init_priority only applies to definitions

In GNU modes, the front end now issues an error when attempting to apply the
init_priority attribute to a variable (or static data member) declaration that
is not a definition.  For example:

  struct D { D(); };
  extern __attribute__((init_priority(3000))) D x;

8/14/03  Microsoft compatibility: binding reference to non-const to rvalue
         in overload resolution

MSVC++ allows binding a reference to non-const to a class rvalue.
As of MSVC++ 7.1, this is viewed as an anachronism and in overload
resolution such a binding is considered worse that any
non-anachronism binding.  This is now implemented when microsoft_version
is >= 1310.

  // MSVC++ 7.1 outputs 2, but it will call 1 if function 2 is removed.
  // MSVC++ 7.0 outputs 1
  extern "C" int printf(const char *, ...);
  struct A { A() {} ~A() {} } a;
  A f() { return a; }
  void g(A &, int) { printf("1\n"); }
  void g(const A&, float) { printf("2\n"); }
  int main() {
    g(f(), 0);
  }

As part of this change, the handling of anachronisms in overload
resolution has been revamped.  Now, a function with an anachronism match
on an argument (which wouldn't be viable at all in the standard language)
is considered only if there are no viable functions that make use of
no anachronism matches.  Formerly, the anachronism match was just
considered worse on that particular argument, which could lead
to ambiguities.  Some pre-existing anachronisms have been reclassified
as "tie-breaker anachronisms", which retain the old behavior.

8/14/03  GNU C++ mode: Attributes on static data members

In GNU C++ mode, the front end now correctly processes attributes on static
data member definitions (including generic definitions of static data members
of class templates).  Previously, such attributes were either ignored or
diagnosed as errors.  For example:

  struct D { D(); };
  struct S { static D x; };
  __attribute__((init_priority(3000)))  // Previously ignored in GNU C++ mode.
    D S::x;

8/14/03  Microsoft compatibility: copy constructors preferred in overload
         resolution

In Microsoft bugs mode, overload resolution now prefers copy constructors
over other functions that are otherwise equally good.

  struct A {
    A(const A&);
    A(int);
  };
  struct B {
    operator A();
    operator int();
  } b;
  int main() {
    A x = b;  // Now accepted in Microsoft mode; was ambiguous
  }

This MSVC++ behavior is apparently intended to partly compensate for
MSVC++'s handling of some cases of copy-initialization as direct-
initialization (see Changes entry of 1/18/98).  The emulation of
that in the EDG C++ Front End is now done only in Microsoft bugs mode.

8/13/03  VLA dimensions sometimes lost on declared type

In some situations involving forward function declarations the front end
lost track of the representation of the dimension of a variable length
array (VLA; available in some C modes) in the declared_type field of a
parameter type.  For example:

  void f(int, float[*][*]);
  void f(n, z)
  int n;
  float z[n][n];  // Declared type of z accidentally replaced by float[*][*]
  {}

This is now fixed.

8/13/03  IA-64 ABI problem with sharing of long string literals

In versions using the IA-64 ABI, the lowered IL for an extern inline
function containing two identical string literals longer than 80
characters was incorrect.  It contained two variables generated to
hold the two string literals, where a single variable should have
been generated.  In addition, the two variables had the same
mangled name, which could cause errors or aborts in back ends.

  inline void f() {
    char *p = "123456789012345678901234567890123456789012345678901234567890"
              "123456789012345678901234567890123456789012345678901234567890"
              "123456789012345678901234567890";
    char *p2= "123456789012345678901234567890123456789012345678901234567890"
              "123456789012345678901234567890123456789012345678901234567890"
              "123456789012345678901234567890";
  }
  int main() {
    f();
  }

8/11/03  Declared type of old-style C parameter definition

The front end used to not record the declared type of an old-style C parameter
definition in the IL (specifically, in a_param_type entries).  For example:

  void f(n, a)
    int n;
    double a[n][n];  // declared_type was not recorded (the type field records
  {                  // the type after decay: double (*a)[n]).
  }

This is now fixed: The originally declared type is now recorded in the
declared_type field of a_param_type entries.

8/10/03  Microsoft compatibility: nested template class lookup bug emulation

The Microsoft 7.0 compiler accepts examples like the one below.  When the
instantiation of B<int>::C is performed, the typedef "A" has already been
declared in B<int>.  The Microsoft compiler ignores the typedef when looking
for a template name.  We now emulate this in Microsoft bugs mode when
Microsoft version is <= 1300.

  template<class T> struct A { };
  template<class T> struct B {
    class C : public A<T> { };
    typedef C A;
  };
  B<int>::A ba;

8/10/03  Precompiled header problem with macro invocation that crosses
         file boundary

If a header file ended with a macro invocation that crosses an include
file boundary, and that header file terminated a precompiled header file,
the resulting PCH file would not result in the correct behavior when used.
This kind of usage now suppresses the creation of a PCH file.

  file: test.c:
  #define f(x) 
  #include "test.h"
  (1)
  int i;

  file: test.h
  f


8/8/03   GNU IA-64 ABI: Additional base class conflicts

If a direct nonvirtual base contains a field of empty class type E at a small
(less than 8 or 16 bytes, depending on the platform) but nonzero offset,
GNU C++ will not place that base at the same offset as an empty base of type E
or a type derived from E.  The front end already emulated this behavior for
bases allocated at offset zero, but it now also does so for other offsets.
For example:

  struct E {};
  struct P: E { virtual f(); };
  struct F {
    int i;
    E e;  // e at a small but nonzero offset
  };
  struct D: P, E, F {};  // Base F should normally be allocated at the same
                         // offset as base E, but GNU compilers see a spurious
                         // conflict between base E and field e of base F.

8/8/03   GNU IA-64 ABI: Layout of empty virtual bases

The IA-64 ABI specifies that an empty virtual base should be allocated
at offset zero if that does not cause a conflict, and at the current end
of the object otherwise.  A Changes entry of 7/16/03 explains that GNU
compilers sometimes do not consider offset zero.  However, it appears
that these compilers initially consider another offset for an empty
virtual base that depends on where that empty virtual base was allocated
in one of the direct base types.  Furthermore, if that offset leads to a
type conflict, the current end of the object layout is increased by the
value of the offset.  For example, for a common 32-bit platform:

  struct E {};
  struct B: E { virtual f(); };
  struct D: B, virtual E {  // Base E is at offset 4 because offset 0 already
                            // has an E subobject.
  #ifdef NO_CONFLICT
    int i;
  #endif
  };
  struct P { virtual g(); };
  struct X: P, D, virtual E {};
    // Virtual base E should go at offset 0 in X, but GNU compilers first
    // attempt offset 4 because that was the offset of E in direct base D.
    // If NO_CONFLICT is not defined, offset 4 creates a conflict with the
    // nonvirtual base E.  Normally, offset 8 should be tried in case of
    // conflict (because offset 8 is the end of the object prior to placing
    // the virtual base), but GNU compilers try 4+8 instead.

This behavior is now imitated when emulating GNU IA-64 bugs.

8/7/03   GNU C++ mode: Unnamed "class" treated as "struct"

In GNU C++ mode, an unnamed class type defined with the "class" keyword is
treated as if it had been defined with the "struct" keyword instead.
For example:

  typedef class { int i; } C;
  C x;
  int *pi = &x.i;  // Normally an access error, but C::i is public in
                   // GNU C++ mode.

8/7/03   GNU IA-64 ABI: Empty base subobject conflict criterion

The Changes entry of 7/14/03 said:
  When emulating GNU IA-64 ABI bugs the front end used to ignore base classes
  of nonprimary virtual bases when looking for empty base subobject conflicts.
  However, it appears GNU compilers only do so for base classes of direct
  virtual bases. 
Unfortunately, this turned out not to be correct.  Instead it appears that GNU
compilers ignore bases of virtual bases that are neither primary bases in the
current object being laid out (as we originally emulated) nor primary bases in
an intermediate base class type.  This does not exclude bases of indirect
virtual bases.  The front end has been updated to emulate this new criterion.

8/6/03   GNU IA-64 ABI: Virtual base cannot overlap with nonvirtual empty base

Early GNU implementations of the IA-64 ABI do not allocate a virtual base
at the same offset as a nonvirtual empty base.  This behavior is now imitated
when emulating GNU IA-64 bugs.

8/5/03   Missing error (and abort) on invalid partial specialization

The front end failed to diagnose an invalid out-of-class partial
specialization in which a template parameter of the partial specialization
was used in the type of the partial specialization, but in a way in which
the parameter could not be deduced.  The front end could abort on such
cases.  Now fixed.

  template <class T> struct A {
    template <class U> class B;
  };
  template<class T> struct A<T>::B<char> { };
  A<int> ai;


8/5/03   Internal error on instantiation pragma in template

An internal error would occur if an instantiation pragma appeared in
a prototype instantiation context.  This includes the body of a class
template and the body of a function template when using --parse_templates.
This has been fixed.

  template <class T> void f(T) {}
  template <class T> void g(T) { 
    #pragma instantiate void f(T)
  }

8/5/03   Spurious error on qualified name in namespace class definition

If a previously declared class was defined in its namespace using a
qualified name, an error was issued.  Although such an error is correct
for functions, variables, etc., it is not correct for a class definition.
Now fixed.

  namespace N {
    class X;
    class N::X {};
  };

8/5/03   Microsoft calling convention keywords in diagnostics

Setting SUPPRESS_MICROSOFT_KEYWORDS_IN_GENERATED_CODE to TRUE no longer
prevents calling convention keywords (such as "__stdcall") from appearing in
diagnostics: It only inhibits such keywords in compilable generated code.

8/5/03   Microsoft compatibility: function call returning class isn't
         exactly an lvalue

Previous changes (see entries of 5/2/96 and 7/29/97) emulated an MSVC++
bug in which function calls returning classes and "constructor calls"
were considered to be lvalues instead of rvalues.  This emulation turns
out to be simplistic.  MSVC++ seems to consider those rvalues, but
in many contexts to allow them to be used as lvalues, e.g., in
binding a reference or on application of the "&" operator.  This
is now emulated more precisely.

8/4/03   Microsoft compatibility: template deduction qualifier bug emulation

Version 7.1 of the Microsoft compiler fixes a template argument
deduction bug in which it ignored qualifiers when comparing deduced
types.  As a result, we have updated our emulation of this bug to
apply in Microsoft bugs mode only when Microsoft version is <= 1300.
This example is accepted when the bug is emulated:

  template <class T> void f(T& t1, T& t2) { }
  int main() {
    int i1, i2;
    const int ci1 = 1;
    f(i1, i2);
    f(ci1, i2); // calls f(const T&, const T&)
  }

8/4/03   Microsoft compatibility: deduced reference to non-const can
         no longer bind to rvalue

The MSVC++ bug  described in the Changes entry of 10/7/00
was apparently corrected in MSVC++ 7.0 (but not in the 7.0 beta
we had).  The emulation is therefore now turned off for
microsoft_version >= 1300.  Note, however, that the change only
affects cases where the rvalue is a constant.

8/4/03   Microsoft C++ mode: Attributes on variable declarations

In Microsoft C++ mode, the front end now accepts some attributes on variable
declarations.  For example:

  [idl_quote("Hello")] int i;

Previously, attributes in that position resulted in an error in all cases.

8/4/03   GNU C++ mode: Exception specifications in system headers

In GNU C++ mode, the front end now issues a warning (instead of an error,
as it did previously) when a declaration's exception specification conflicts
with a previous declaration from a system header.  Note that since warnings
are not issued on declarations in system headers, no diagnostic will be
issued at all if both the original and the conflicting declarations appear
in system headers.

8/4/03   Microsoft compatibility: long long bit fields promote to long long

In Microsoft C and C++ modes, long long bit fields with lengths equal
to or smaller than long now promote to long long (or unsigned long
long), as in MSVC++.

8/4/03   C-generating back end aborts due to Microsoft property fields

IL lowering did not always correctly remove Microsoft property fields from
class types.  The C-generating back, which does not expect property fields in
the IL, would then either abort or incorrectly generate the property field as
a normal field.  This is now fixed.

8/4/03   System header flag in GNU preprocessor line directives

The preprocessor line directives emitted by the GNU preprocessor can include
a flag that indicates that code originated in a system header file.  Formerly,
this flag was accepted but ignored.  The system header flag is now recognized
and the associated code is treated as if found in a file specified by the
--sys_include option.  The flag is recognized in all modes (not just in
GNU modes).

8/4/03   GNU C++ mode: Undefined extern inline functions

The EDG normally issues an error when an extern inline function is referenced
but not defined.  In GNU C++ mode we now issue a warning instead for such
situations.  For example:

  inline void f();  // Referenced but undefined: Warning in GNU mode
                    // (error in default mode).
  int main() { f(); }

-------------------------------------------------------------------------------
Version 3.3, August 1, 2003

7/31/03  IL version number changed to 3.3

7/31/03  Export template enabling

The EXPORT_ENABLING_POSSIBLE configuration macro has been added to make
it possible to prevent users from enabling exported templates.

7/31/03  Export template and mangling without distinct template signatures

The export mechanism requires that distinct template signatures be
used.  Previously, the front end did not enforce this requirement and
an internal error could result if exported templates were used when
distinct template signatures were disabled.  The front end now enforces
this requirement.

7/31/03  Unset variable in instantiation_directive

In certain error cases, the do_flags variable in instantiation_directive
was used without having been set.  This has been fixed.

  struct A {
    template <class T> struct B {};
  };
  template union A::B<int>;

7/30/03  C++-generating back end: Nonstandard friend class declarations

The C++-generating back end used to not render (nonstandard) friend class
declarations that do not make use of an elaborated type specifier (because
no source sequence entry was created for such friend declarations).
For example:

  struct F;
  class C {
    friend F;  // Used to be dropped in the C++-generating back end output.
  };           // (Not accepted in strict mode.)

This is now fixed.

7/30/03  GNU mode: Additional built-in functions

In GNU C and C++ modes, the front end now recognizes the built-in functions
__builtin_exp, __builtin_huge_val, __builtin_huge_valf, __builtin_huge_vall,
__builtin_nan, __builtin_nanf, __builtin_nanl, __builtin_nans, __builtin_nansf,
__builtin_nansl, and __builtin_prefetch.  These functions were introduced in
version 3.3 of the GNU C and C++ compilers.  Uses of these functions appear
in the GNU headers.  Furthermore, the following additional functions are also
predeclared by the front end (but they do not appear in GNU headers):
__builtin_putchar_unlocked, __builtin_puts_unlocked, __builtin_printf_unlocked,
__builtin_fputc_unlocked, __builtin_fputs_unlocked, __builtin_fwrite_unlocked,
__builtin_fprintf_unlocked, __builtin_sprintf, __builtin_snprintf,
__builtin_vprintf, __builtin_vsprintf, __builtin_vsnprintf, __builtin_scanf,
__builtin_sscanf, __builtin_vscanf, __builtin_vsscanf, __builtin_expf,
__builtin_expl, __builtin_log, __builtin_logf, __builtin_logl, __builtin_inf,
__builtin_inff, __builtin_infl, __builtin_abort, __builtin_exit,
__builtin__exit, and __builtin__Exit.

7/30/03 C++-generating back end: inaccessible typedefs from template arguments

When the C++-generating back end emits a template argument list, it usually
does so using the type that was first specified for a given class template
instance.  In the example below where B<A::X> and B<char> refer to the same
type, B<A::X> would be emitted.  Because this could result in access errors,
non-public typedefs are now stripped in most cases when emitting template
argument lists.

  template <class T> struct B { };
  struct A {
  private:
    typedef char X;
    B<A::X> b;
  };
  void f() {
    B<char> b;
  }

7/30/03  Abort in do_all_namespace_member_promotion, multiple translation
         units

An abort in do_all_namespace_member_promotion ("namespace type not found")
occurred in multiple-translation-unit mode (e.g., with exported
templates) in some rare cases involving instantiations of class
templates inside otherwise unused class types.  One indication that
you have this specific problem is that the source file compiles okay
as a primary translation unit, and also compiles okay as a secondary
translation unit when --no_remove is specified.  Now fixed.

7/29/03  Microsoft compatibility: guiding declarations no longer accepted

Version 7.1 of the Microsoft compiler no longer accepts guiding declarations,
so they are now disabled in Microsoft mode when Microsoft version is >= 1310.

  template <class T> struct A {
    friend void f(A);  // No longer refers to an instance of the template f
  };
  template <class T> void f(T){}
  int main() {
    A<int> ai;
    f(ai);
  }

7/30/03  Microsoft compatibility: Microsoft attributes

Microsoft attributes of the form "[attribute_name(args)]" are now accepted.
The attribute facility was added by Microsoft in Visual C++ 7.0.  Such
attributes are scanned and an IL representation of the attribute is
created.  This information is used by the C++-generating back end to emit
the attributes in the generated code.  Other than certain error checks,
attributes have no semantic impact in the front end (for example, no
code injection is performed for the COM attributes).  Processing of
attributes depends on several configuration parameters.  If
RECOGNIZE_MICROSOFT_ATTRIBUTES is FALSE, attributes will still be parsed,
but any use of an attribute will result in an unrecognized attribute
warning.  This is the default except when using the C++-generating back
end.  SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING controls whether any error
checking of attributes is performed when attributes are recognized.  When
TRUE (the default value), no checking of attribute arguments is performed.
When SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING is FALSE, the front end
recognizes all of the attributes included in the Microsoft 7.1 documentation.

7/29/03  C++-generating back end: avoid putting out both inline and Microsoft
         __forceinline

The C++-generating back end now avoids putting out the "inline"
specifier on a declaration if the Microsoft "__forceinline" specifier
is also put out.  (See also the similar Changes entry of 4/18/03.)

7/29/03  Symbol table performance improvement

The size of the symbol table has been increased to improve performance when
compiling large programs.

7/29/03  Abort in trans_copy.c on Microsoft asm in secondary translation unit

The front end aborted in copy_string_entry in trans_copy.c on
attempting to copy a Microsoft asm that appeared in a secondary
translation unit (e.g., with exported templates).  Now fixed.

7/29/03  GNU mode: Typedef redeclarations and the mode attribute

In GNU modes the front end used to apply all attributes on a typedef after
checking for type compatibility.  This caused the following to trigger an
error:

  typedef short S;
  typedef int S __attribute__((mode(__HI__)));
    // Previously an error; now accepted (with a warning in GNU C mode).

Now the mode attributes are applied before checking for redeclaration
compatibility and the example above is accepted.  Furthermore, the mode
__QI__ has been changed to produce type "signed char" instead of plain "char".

7/28/03  Nested classes have access to surrounding classes

Core issue 45 changed a rule in the ARM that said that nested
classes have no special access to members of the containing class.
The front end now implements that resolution, which means the
following example gets no error:

  class C {  // Entire body is private
    static int i;
    struct Parent {
        Parent() { }
    };
    struct Derived : Parent {
        Derived() { i = 0; // No access error now }
    };
    
    Derived d;
  };
  int C::i;
  int main() {
    C c;
    return 0;
  }

Core issue 45 has DR status but is not in TC1, so strictly speaking
the current C++ standard does not allow this.  However, the standards
committee has made it clear that this test case should be accepted,
so we're making the change at this time.

The error on the above was formerly issued only in strict mode;
in all other modes the example was already accepted without error.

In a related change, an error is now issued in default mode for
references to private members of enclosing classes from within the 
body of a friend function nested in the class:

  class A {
    int i;
    struct B {
      friend void f(A *p) {
        p->i = 0;  // Now gets access error
      }
    };
  };

This was formerly flagged only in strict mode.

7/28/03  static_cast of pointer to member of derived class to private base

According to core issue 54, a static_cast from a pointer to member of
a derived class to a pointer to member of a private base should not be
allowed.  The front end now enforces that.

7/25/03  C++-generating back end: Workaround for GNU C++ extern "C" bug

GNU C++ compilers are unable to parse variable declarations of the form

  extern "C" struct S { int i; } x;

To work around this GNU problem, the C++-generating back end now produces

  extern "C" { extern struct S { int i; } x; }

when GCC is selected as the back end's code target.

7/24/03  Microsoft and GNU C++ compatibility: typedef in explicit instantiation

In Microsoft and g++ modes, a typedef that refers to an instance of a class
template is accepted in an explicit instantiation directive.

  template <class T> struct C {};
  typedef C<int> CI;
  template CI;

7/24/03  Microsoft compatibility: change in overload resolution for
         built-in operators with promoted operands

MSVC++ (6.0, 7.0, and 7.1, at least) has a bug in overload
resolution for built-in operators.  The prototypes for operators
like "+" are supposed to include only promoted arithmetic
types, and those for operators like "%" are supposed to include
only promoted integral types.  However, it appears that
unpromoted types are also included.  This causes an
ambiguity on a case like

  struct A {
    operator int();
  };
  struct B {
    B(A);
  };
  int operator+(B, unsigned short);
  int main() {
    A a;
    unsigned short us;
    a + us;  // Ambiguous in MSVC++ and now in Microsoft bugs mode
  }

One can also come up with cases like this that the Microsoft
compiler considers unambiguous, whereas the EDG Front End
issued an ambiguity error (one case appears in the comdef.h
header in MSVC++ 7.1).  The MSVC++ behavior is now emulated
in Microsoft bugs mode.

7/24/03  Microsoft compatibility: _WCHAR_T_DEFINED predefined macro

In Microsoft mode, the macro _WCHAR_T_DEFINED is predefined when wchar_t
is a keyword.

7/24/03  Uninitialized field in_handler_parameter_declaration

The field in_handler_parameter_declaration in the statement
stack entry was not initialized.  If by chance it had the
initial value TRUE, access checking on constructors might
have been suppressed in certain cases in Microsoft mode,
which might mean that some access errors that should have
been emitted would not have been.  Now fixed.

7/23/03  Side effect routines now use expression traversal routines

The routines that discover whether expressions and the like have
side effects, e.g., node_has_side_effects, now use the generalized
expression traversal routines (See Changes entry of 4/29/03).

7/21/03  Spurious error on local static array of const in C99 inline

In C99, an inline function may not declare a local static variable
that is modifiable.  The check for this did not work correctly for
arrays with const element type, and such cases were incorrectly
rejected.  Now fixed.

  inline f() { static const int x[5] = {0}; }  // Accepted now in C99

7/21/03  Microsoft compatibility: Exception specifications on redeclarations

In Microsoft mode (with exceptions enabled and microsoft_version >= 1300),
the front end now only issues a warning on function and member function
redeclarations whose exception specification does not match that of a
previous declaration.  Previously, an error was issued.  For example:

  struct S {
    void f() throw(...);
  };
  void S::f() throw() {}  // Warning only in Microsoft mode
                          // (previously an error).

See also the Changes entries of 7/18/03 and 6/19/03.

7/20/03  Abort in gcc mode on difference of pointers to array of empty struct

The front end aborted in do_pdiff ("size of object pointed to is zero") or
do_padd ("size is zero") when folding constant pointer operations
on addresses in an array of empty structs in gcc mode.  gcc defines
sizeof(...) as zero for an empty struct, so these cases involve
multiplication or division by zero.  Aborts fixed; the pointer
difference case (which uses division) now gets an error.

  struct Empty {};
  struct Empty a[3];
  int b[&a[1] - &a[0]];

7/20/03  Overloaded operator-> return value can have any type

Years ago, the Working Paper for the C++ standard required that
the value returned by an overloaded operator-> have class type,
pointer to class type, or reference to class type.  That
requirement was dropped before the standard was issued, but
we failed to remove the check.  It's now gone.  Most of the
time this change simply results in a different error message,
but when the "->" turns out to be a pseudo-destructor call,
it eliminates a spurious error.

  template<class T> struct PTR {
    T& operator*() const;
    T* operator->() const;
  };
  template<class T> void f() {
    PTR<T> p = PTR<T>();
    p->~T();  // Formerly got error when T is int
  }
  struct A {};
  int main() {
    f<A>();
    f<int>();
 }

7/18/03  Microsoft compatibility: explicit overriding

In Microsoft mode, the front end now accepts declarations of virtual
member functions with a class qualifier to indicate that only the 
virtual member in the indicated class is overridden by the qualified
declaration.  The overridden function must be pure virtual.
For example:

  struct B1 { virtual void b() = 0; };
  struct B2 { virtual void b() = 0; };
  struct X: B1, B2 {
    virtual void B1::b();  // Only overrides B1::b()
  };
  void X::b() {}           // Definition does not include base class name.

Note that since the overriding is incomplete in the above example, the
member B2::b is hidden by X::b (a warning to that effect will be issued).
Multiple selective overriders can be defined in a class:

  struct A {
    virtual void f() = 0 { }
  };
  struct B {
    virtual void f() = 0 { }
  };
  struct D: A, B {
    virtual void A::f() { }
    virtual void B::f() { }
  };

In the latter example, the name D::f is ambiguous and the corresponding
members can therefore not be defined outside of D.

A name mangling change has also been made, because with examples such as
the second one above it is possible to end up with two member functions
with the same name and signature in a class, each overriding a different
base class member.

The overridden function information must be added to the mangled name
to make the names unique.  In the Cfront-like ABI, the sequence

  O class-type-encoding

is added after the member function class and before the "F", e.g.
a member D::f that explicitly overrides B::f is encoded as f__1DO1BFv.
In the IA-64 ABI, the sequence

  O <nested-name>

where the <nested-name> encodes the overridden function, is added to
an <encoding>:

  <encoding> = <function name> O <nested-name> <bare-function-type>

So, for example, a member D::f that explicitly overrides B::f is
encoded as _ZN1D1fEON1B1fEv.

7/18/03  Missing stmk_init for lowered compound literal in C++ mode

IL lowering failed to add an stmk_init statement to cause the
initialization of a temporary added for a compound literal in
C++ mode (meaning, at the moment, in g++ mode).  Depending on how a
back end handled this incorrect IL, the compound literal might
have ended up uninitialized.

  extern "C" int printf(const char *, ...);
  int main() {
    printf("m=%x\n", ((struct { int m; }){ m:123 }).m );
  }

7/18/03  Access checking on member template in presence of using-declaration

A spurious access error was sometimes generated on a use of an
overloaded member function template, when a using-declaration in a
derived class made it accessible.  Now fixed.

  class Base {
    protected:
      template <typename T>
      void f(const T &) { }
      void f(const int &) { }
  };
  class Derived : public Base {
    public:
      using Base::f;
  };
  int main() {
     Derived d;
     d.f(7.0); // Formerly got access error
  }

7/17/03  alignment-of operator for incomplete types

Previously, the front end silently accepted alignment-of operators (e.g.,
__alignof__) with an argument of incomplete type and the result of the
operator was 1.  Now, the following changes were made:
  - In strict ANSI modes, an error is issued.
  - In GNU modes, an error is issued, but not for a void type and
    not for an expression-form argument.
  - In Microsoft C and C++ mode, the result of the operator is zero for
    incomplete class types (and arrays thereof).
  - In Microsoft C mode, the result of the operator is zero for void types.

In cases that do not elicit an error, a warning is issued instead.
For example:

  extern struct S x;         // Incomplete struct type.
  int a1 = __alignof(S);     // a1 == 0 in Microsoft C and C++ modes.
                             // Error in GNU and strict ANSI modes.
  int a2 = __alignof(x);     // a2 == 0 in Microsoft C and C++ modes.
                             // Error in strict ANSI modes only.
  int a3 = __alignof(void);  // a2 == 0 in Microsoft C mode only.
                             // Error in strict ANSI modes only.

7/17/03  GNU C compatibility: comma expression as lvalue

gcc considers a comma expression to be an lvalue if its second
operand is an lvalue.  This is like C++ but nonstandard for C.
This was previously emulated (see 8/28/01 Changes entry's
10/11/01 addendum regarding generalized lvalues), but not
accurately enough.  It turns out that gcc handles this case just
like C++, and not in the (convoluted) way it handles the
similar issue for the "?" operator.  Emulation now improved.

  struct {
     unsigned int i;
  } x;
  void f() {
    int j = 0;
    ((void)j, x).i += 1;  // Now accepted in gcc mode
  }

7/17/03  GNU C++ compatibility: static data member initializer relaxation

The in-class initializers for static data members in GNU C++ mode are
now allowed to contain some constructs not allowed by the standard.

  struct A {
    static const int x = 1.0 ? 0 : 0;  // Now accepted in g++ mode
  };

7/17/03  GNU predefined vararg primitives in C- and C++-generating back ends

A new configuration macro GCC_BUILTIN_VARARGS_IN_GENERATED_CODE can be set
to make the C- and C++-generating back ends use the GNU predefined vararg
primitives (such as __builtin_va_list, __builtin_va_arg, ...) instead of
the standard <stdarg.h> facilities.  (This behavior was previously tied to
the choice of a GNU mode for the source language.)  The macro is set by
default if both GCC_IS_GENERATED_CODE_TARGET and GCC_BUILTIN_VARARGS are
set.

7/16/03  Microsoft compatibility: default Microsoft version changed

The default Microsoft version number is now "1310".  This corresponds
to the value of _MSC_VER used with Visual C++ 7.1.

7/16/03  Microsoft compatibility: internal error on in-class specialization

When EXPENSIVE_CHECKING is enabled, an internal error would occur
in Microsoft mode when a Microsoft in-class specialization with
a dependent type was declared.  This has been fixed.

  template <class T> struct A {
    template <class X> void f(X);
    template <> void f(A<T>){}
  };

7/16/03  IA-64 ABI name mangling: predefined substitutions in virtual
         function table names

The name mangling for the IA-64 ABI failed to use the predefined
substitutions for certain types when they appeared in virtual
function table names.  Now fixed.  This is an ABI change, so
the old behavior is preserved when ABI_COMPATIBILITY_VERSION is
less than 303.

7/16/03  GNU C++ mode: __cplusplus defined to 1

In g++ mode the __cplusplus macro is now defined to the 1 instead of
199711L as specified by the C++ standard.

7/16/03  GNU IA-64 ABI: Offset of virtual empty bases

The IA-64 ABI specifies that a virtual empty base should be placed at
offset zero in its containing object if doing so does not cause a
conflict with another subobject of the same type at that zero offset.
However, it appears GNU compilers do not consider offset zero for a
virtual base of type E in a complete type X if a virtual base of type E
had been placed at a nonzero offset during the layout of a direct base
of X.  For example:

  struct E {};
  struct B: E { virtual f(); };
  struct D: B, virtual E {};  // Virtual base E cannot be allocated at
                              // offset 0 in D.
  struct P { virtual g(); };
  struct X: P, D, virtual E {};  // Virtual base E should go at offset 0,
                                 // but GNU compilers do not do so.

This behavior is now imitated when emulating GNU IA-64 bugs.

7/15/03  Enabling GNU mode when Microsoft mode is the default

In a version that supports both Microsoft and GNU modes and in which
Microsoft mode was the default, the --gcc/--g++ command-line option was
not sufficient to enable GNU mode.  It was also necessary to use the
--no_microsoft_mode option.  This has been fixed.

7/15/03  Call of placement delete with ABI_CHANGES_FOR_PLACEMENT_DELETE FALSE

When ABI_CHANGES_FOR_PLACEMENT_DELETE is FALSE, placement delete is
supposed to be disabled because the runtime cannot handle calling
a non-default operator delete on a thrown exception.  A case using
a default argument on the operator new snuck by that test:

  struct A {
    void* operator new(size_t alloc_size, size_t dummy=0);
    void operator delete(void* p, size_t s);
    A();
  };
  int main() {
    A* ap = new A; 
  }

This caused IL lowering to generate an internal try-block, which
is not supposed to happen when ABI_CHANGES_FOR_PLACEMENT_DELETE
is FALSE.  Now fixed (the operator delete is not called on an exception).

7/15/03  Microsoft compatibility: __declspec(intrin_type)

The front end now accepts the Microsoft specifier __declspec(intrin_type).
This specifier only has an effect when it appears on a class type definition.
It is used in Microsoft headers to mark certain types used in conjunction
with SIMD operations (such as Intel's MMX and SSE instruction set extensions,
as well as AMD's 3DNow! instructions).  For example:

  struct __declspec(intrin_type) __declspec(align(16)) __m128 {    
    float       m128_f32[4];
  };

The specifier is rendered by the C- and C++-generating back ends.

7/14/03  GNU IA-64 ABI: Empty base subobject conflicts not ignored

When emulating GNU IA-64 ABI bugs the front end used to ignore base classes
of nonprimary virtual bases when looking for empty base subobject conflicts.
However, it appears GNU compilers only do so for base classes of direct
virtual bases.  The front end has been changed to behave similarly.
For  example:

  struct E {};
  struct P: E { virtual void f1(); };
  struct V: E { virtual void f2(); };
  struct B: V {};
  struct D: P, E, B {};
    // The allocation of virtual base V (of B) in D does consider the
    // conflict between V's empty base E and D's direct empty base E,
    // because V is not a direct virtual base of D.

7/11/03  Microsoft compatibility: one-argument operator++() for
         postfix ++

Microsoft mode now allows a one-argument operator++() or operator--()
to match a postfix use of ++ or --, as an anachronism (the standard
requires a two-argument function for the postfix operators; the "this"
parameter counts as one of the arguments in either case).  A warning
is issued.

  struct A {
    void operator++() {}
  };
  int main() {
    A a;
    a++;  // Okay with warning in Microsoft mode
  }

7/11/03  Error on \x with no following hex digit in string/character literal

The sequence \x in a string or character literal should be followed
by at least one hexadecimal digit.  If it isn't, an error is now issued
(except in pcc mode).  Formerly, only a warning was issued.

  int f() { return '\x'; }

7/11/03  Incorrect mangling for promoted local types

The mangled names generated in the Cfront-like ABI for types
promoted out of functions were broken by a change in version 3.1
(see changes entry of 12/8/02).  The names were "broken" in
that they were missing a length, which meant that the demangler
could not demangle them.  Since these names are local to functions,
this was not an ABI breakage.  However, debuggers that use
demangling to convert object-file names to user-readable
names would have had problems.  Now fixed.

  int main() {
    struct A {
      struct B {
        void f(B) {}
      };
    };
    A::B b;
    b.f(b);
  }

Correct mangled name for f: f__Q2_15A__L0__main__Fv1BFQ2_15A__L0__main__Fv1B
Bad     mangled name for f: f__Q2_A__L0__main__Fv1BFQ2_A__L0__main__Fv1B

7/11/03  Error on throw of pointer-to-incomplete type

An error is now issued on a throw of an expression with pointer-to-
incomplete type.

  struct S;
  int main() {
    throw (S *)0;  // Gets error now.
  }

In Microsoft C++ mode, a warning is issued instead.

7/11/03  Abort on GNU min/max operators

For certain uses of the g++ min/max operators ("<?" and ">?") where
the operands are lvalues for variables of the same type and having
static storage duration, the front end aborted in scan_gnu_min_max_operator.
Now fixed.

  int j = 1;
  int main() {
    int a = j >? j;
    return 0;
  }

7/10/03  Abort in C++-generating back end on Microsoft in-class specialization

In configurations with CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
set to TRUE and NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set
to FALSE, the C++-generating back end triggered an internal error when
generating an in-class specialization (a feature accepted in Microsoft mode
only) for a class instantiation.  For example:

  template<typename T> struct S {
    template<typename X> void operator=(S<X> const&) {}
    template<> void operator=(S<T> const&) {}
      // Abort while rendering this explicit specialization for the S<int>
      // instance.
  };
  template struct S<int>;

This is now fixed.

7/7/03   Incorrect size on virtual function table for local class

The virtual function table generated for a local class in some
cases had twice the elements it is supposed to have (the number
of initialized members was correct).  In addition, in the
Cfront-like ABI, the size recorded in the type of such an array
was for the correct number of members, so it did not match
the size of the array as dimensioned.  Now fixed.

7/7/03   Microsoft compatibility: __declspec(noinline)

In Microsoft mode, the front end now accepts the __declspec(noinline)
specifier.  When specified on a function declaration, it indicates that
a back end should not attempt to inline the function.

7/2/03   Microsoft compatibility: __declspec(align(...))

In Microsoft mode, the front end now accepts declaration specifiers of the
form __declspec(align(x)), where x is an integer literal that is a power of
two.  This allows the alignment to be specified explicitly for typedef types,
class types, variables, and fields (the latter only when the configuration
macro USER_CONTROL_OF_STRUCT_PACKING is set to TRUE).

7/1/03   Microsoft compatibility: __FUNCTION__ etc. are string literals

The Microsoft keywords __FUNCTION__ and __FUNCDNAME__ now represent
string literals instead or local static variables in Microsoft mode,
and the new keyword __FUNCSIG__ has been added.

  int main() {
    char x[] = __FUNCTION__;  // Now accepted in Microsoft mode
    return 0;
  }

Some minor adjustments have also been made in GNU modes.  For
example, __func__ in GNU C mode is now a variable rather than
a string literal, even though the very similar __FUNCTION__ remains
a string literal.

7/1/03   GNU IA-64 ABI: Reuse of tail padding of indirect base

The default (IA-64-based) GNU C++ ABI deviates from the IA-64 ABI
specifications by allowing the tail padding for indirect bases to be
reused.  For example:

  struct S1 {
    char m1;  // Offset 4 in S1 (virtual function table pointer at offset 0)
    S1() {}
    virtual ~S1() {}
  };
  struct S2 {
    short m2;
    S2() {}
  };
  struct S3: S1, virtual S2 {
    char m3;  // Offset 5 in S3 (reuses tail padding of direct base S1).
    S3() {}
  };
  struct S4: S3 {
    short m4;  // When emulating GNU ABI bugs, offset 6 in S4 because the
               // tail padding of indirect base S1 is reused.
    S4() {}
  };

This behavior is now imitated when emulating GNU ABI bugs.

6/27/03  GNU mode: Warning only on duplicate clobber

In GNU C and C++ modes, the front end used to issue an error when a
register clobber was specified twice in an extended asm construct.
Now the diagnostic has been weakened to a warning.

  void f() {
    __asm ("nop" : : : "bx", "bx");  // Warning: "bx" clobbered twice
  }                                  // (previously a hard error).

6/27/03  Microsoft compatibility: __declspec(deprecated)

In Microsoft mode, the front end now supports the __declspec(deprecated)
specifier.  Using an entity marked with this specifier results in a warning
(unless the use is for an entity that is itself deprecated).  For example:

  struct __declspec(deprecated) X {};
  void f(X);  // Warning: X is deprecated

The IL representation of this specifier is identical to that for the GNU
attribute "deprecated" (see Changes entry of 2/4/03; IL CHANGE: the field
has_gnu_deprecated_attribute of a_source_correspondence has been renamed to
is_deprecated).

6/27/03  Microsoft __COUNTER__ macro

The Microsoft __COUNTER__ macro, which returns an incrementing
integer value each time it is used, is now implemented in Microsoft
C and C++ modes.

6/27/03  Microsoft compatibility: __debugbreak

In Microsoft C and C++ modes with microsoft_version 1300 or greater,
the intrinsic function __debugbreak is now predeclared.  Calling it
causes a debug breakpoint.

6/25/03  GNU C++ mode: Accessibility check for friend function declarations

In GNU C++ mode, the front end no longer checks the accessibility of the
name of a function specified in a friend function declaration.  For example:

  class X { void priv(); };
  class Z {
    friend void X::priv();  // No longer triggers an accessibility error.
  };

6/25/03  Spurious error caused by using-declaration referring to a
         dependent base

The front end sometimes emitted various spurious errors when a using-
declaration referring to a member of a dependent base class was overloading
a member of the derived class template.  For example:

  template<typename T> struct B {
    void f() const;
  };
  template<typename T> struct D: B<T> {
    void f();
    using B<T>::f;
  };
  template<typename T> void D<T>::f() {}  // Used to trigger a spurious error
                                          // "inherited member is not allowed"
This is now fixed.

6/25/03  Internal error on invalid class definition in member of class template

If a class definition appeared in an unexpected place within a class template
(in the parameter list of a function declaration, in this example) an
internal error could result.  This has been fixed.

  template <class T> struct A {
    void a(struct B { T f() {return f;} });
  };

6/24/03  Incorrect virtual function tables with no RTTI, no Cfront
         compatibility

In the mode where the ABI selected is the Cfront-like ABI but without
full Cfront compatibility (IA64_ABI FALSE and
CFRONT_OBJECT_CODE_COMPATIBILITY FALSE) and RTTI information is
turned off (e.g., with SUPPRESS_TYPEINFO_VARIABLES_WHEN_RTTI_DISABLED
TRUE and --no_rtti), IL lowering sometimes did not generate a virtual
function table for a base class that shares a virtual function
table with another base class, if the other base class did not itself
contain any overridden virtual functions.  This could result in incorrect
dynamic call behavior at runtime.  Now fixed.

6/24/03  Spurious correspondence errors on unnamed class types

Under some circumstances the front end produced spurious correspondence
errors in a multiple-translation-unit compilation involving unnamed
class types that acquire a "name for linkage purposes" through a typedef.
For example, errors were produced on compiling two identical source files
containing the following declarations:

  template<typename T> struct S {
    typedef T *P;
  };
  typedef struct {
   int i;
  } N;
  typedef struct {} E;  // Spurious correspondence error on E
  typedef S<E>::P SEP;
  typedef S<N>::P SNP;

This is now fixed.  Note that the multiple-translation-unit mode
is used only in some special configurations, or in the presence
of exported templates.

6/24/03  Diagnostic on member typedef with same name as enclosing class

The front end now diagnoses a member typedef of the enclosing class using
the same name as that enclosing class.  An error is issued in strict C++
mode; a warning otherwise.  For example:

  struct S {
    typedef struct S S;  // Error in strict mode; warning otherwise.
  };

6/24/03  Diagnostic for duplicate member typedef declaration

In strict ANSI and Sun C++ modes, the front end now issues an error on
duplicate member typedef declarations.  In other modes, a warning is issued.
For example:

  struct S {
    typedef int I;
    typedef int I;  // Duplicate typedef declaration.  Error in strict mode
  };                // and in Sun mode; warning otherwise.

This is a consequence of a clarification in the TC1 revision of the C++
standard.

6/23/03  Sun compatibility: spurious error in class template specialization

In Sun mode, we emulate a Sun bug that makes template parameters visible
in class template specializations.  A consequence of our emulation was
that a spurious error was issued in Sun mode if the name of the template
parameter was redeclared within the specialization.  This has been fixed.

  template <class T> struct A {};
  template <> struct A <void> {
    typedef void T;
  };

6/22/03  Abort in get_token: bad lexical escape on #define in macro arguments

In some cases, the appearance of a #define within a macro argument
list confused the front end and resulted in an abort in get_token
("bad lexical escape").  Now fixed.

  #define N d
  #define M(j)j
  M(N,
  #define O 1
  )

6/19/03  Microsoft compatibility: Treatment of exception specifications

In Microsoft bugs mode, the front end used to discard all exception
specifications, except for those of the form "throw (...)" (see also
the Changes entry of 10/2/00).  This behavior has been modified to
more closely match the actual behavior of Microsoft C++ compilers.
In Microsoft bugs mode with microsoft_version <= 1200, all standard
exception specifications are ignored and the "throw (...)" form is
not recognized.  (In Microsoft mode without Microsoft bugs mode and
with microsoft_version <= 1200, standard exception handling treatment
is available, as was the case previously.)  In Microsoft modes with 
microsoft_version >= 1300, the front end recognizes both standard
exception specifications and the "throw (...)" specification with
the following caveats:
  - non-empty throw specifications (e.g., "throw (char*)") are
    all recorded as "throw (...)", and
  - only the form "throw ()" is recorded on functions that do
    not have extern "C" linkage.
A consequence of these changes is that, when microsoft_version >= 1300,
the front end now accepts two declarations of the same function where
one has a throw (...) specification and the other not if those functions
do not have extern "C" linkage.  For example:

  void f() throw(...);  // throw (...) parsed but no longer recorded
  void f();             // No longer an error

Previously such a mismatch triggered an error.  Furthermore, various
mismatches that were previously ignored are now warned about.  For example:

  struct B {
    virtual void f() throw() {}
  };
  struct D: B {
    virtual void f() {}  // Now a warning when microsoft_version >= 1300.
  };                     // (Previously silently ignored.) 

6/20/03  Microsoft compatibility: #pragma pack(show)

The front end now recognizes a new form of "#pragma pack": When its argument
is the simple identifier "show", the front end issues a warning with the
value set by the most recent "#pragma pack".  For example:

  #pragma pack(show)  // Warning: current value of pragma pack is not set
  #pragma pack(1)
  #pragma pack(show)  // Warning: current value of pragma pack is 1

In Microsoft mode the identifier "show" may be followed by another identifier
and/or an integer constant (in that specific order) separated by commas.
These additional arguments are ignored with a warning.  For example:

  #pragma pack(show, ignored, 33)  // Additional pack arguments ignored
                                   // with a warning

6/19/03  Side-effect testing routines moved into il.c

The various routines that test expressions and dynamic initializations
for side effects have been moved into il.c (from expr.c and
decl_inits.c) to make them more easily accessible from various
parts of the front end and from back ends.

6/19/03  Bug in C99 designated initializer processing

Defect Report 253 from the C standard committee clarifies the
required behavior of designated initializers in a corner
case.  The front end has been changed to conform.

  int main() {
    struct fred {
      char s [6];
      int n;
    };
    // Following two initializers are no longer equivalent:
    struct fred x [] = { { { "abc" }, 1 }, [0].s[0] = 'q'        };
    struct fred y [] = { { { "abc" }, 1 }, [0] = { .s[0] = 'q' } };
  }

6/19/03  Abort on overridden construction in C++ designated initializer

IL lowering aborted in il.c/gather_initializer_expressions while
processing a designated initializer in C++ mode where an initialization
via a constructor call was overridden by a later initialization.
(The constructor call is done for side effects and the result is
discarded.)  Now fixed.

  struct A { A(); ~A(); };
  A a[2] = { A(), [0] = A() };

6/19/03  C++-generating back end: default-initialized members of arrays

The C++-generating back end formerly put out initializations for
some default-initialized members of aggregate arrays of classes
when a constructor must be called.  Now, the implied initializations
of such trailing members are suppressed.

  struct A {
    A();
  };
  const A arr[2] = {A()};

6/18/03  Microsoft compatibility: __alignof

The front end now recognizes the Microsoft __alignof operator.
It's similar to the EDG __alignof__ extension: __alignof(type)
and __alignof(expression) return the alignment of the indicated
type or expression.  Parentheses are required around the expression,
unlike for sizeof.

6/18/03  Microsoft compatibility: __w64 type annotation

The front end now recognizes the Microsoft __w64 type annotation.  This
new keyword is syntactically a type qualifier (like "const"), but it does
not really modify the type to which it is applied (and hence it is not
recorded as a type qualifier in the IL).  Instead it is an aid to transition
to an environment where int, long, and pointer types are 64 bits wide (ILP64).
When applied to other types, an error is issued.  When a type marked with __w64
is converted to an integral type not so marked, the front end issues a remark
(which can be changed to a more severe diagnostic using command-line options).
This feature is usually used with typedef types.
For example:

  typedef int __w64 Index;
  Index f(long);
  int main() {
    f(f(3));    // Remark: Potentially narrowing conversion
    void *__w64 ptr = 0;
    (long)ptr;  // Remark: Potentially narrowing conversion
  }

6/18/03  Abort in push_object_lifetime on g++ typeof

An abort in push_object_lifetime has been eliminated.  It came
up in g++ mode on a use of typeof within a template argument
list used within a function body.

  template <class T>
  struct A {
    void g(T* t) {
      A<typeof(t)> a;
    }
  };
  int main() {
    A<int> a;
    int b;
    a.g(&b);
  }

6/17/03  Abort on lowering of GNU [a...b] designated initializer

IL lowering aborted in lower_init.c (lower_aggregate_designated_initializers)
while processing certain multi-level designated initializers that
use the GNU array element range designator form [a...b].  Now fixed.

  int a[][2][4] = { [2 ... 4][0 ... 1][2 ... 3] = 1, [2] = 2, [2][0][2] = 3 };

6/17/03  C99 floating-point operations can have side effects

In C99, the floating-point status can be queried, and therefore
when the STDC FENV_ACCESS pragma state is ON a floating-point
operation can have a side effect.  The side-effect analysis
routine in the front end now considers such operations to
have side effects in the appropriate mode.

When TARG_HAS_IEEE_FLOATING_POINT is TRUE, folding of constant
floating-point operations that involve NaNs, infinities, or
division by zero is now suppressed (the operation is delayed
to run time) so that such operations can affect the floating-point
status.  Although that status can be queried only in C99 mode, the
folding is suppressed in all modes and regardless of the
setting of FENV_ACCESS.

  #define _Infinity __INFINITY__
  int main() {
    #pragma STDC FENV_ACCESS ON
    0.0 * _Infinity;  // Gets no warning now in C99 mode.
  }

6/17/03  Slight type mismatches in calls of runtime routines for arrays

The code generated by IL lowering had in some cases some slight
type differences between argument types and parameter types on
calls of the runtime library routines that deal with array
construction and destruction.  In particular, the types of
pointers to functions for constructors, destructors, operator
new, and operator delete routines were slightly more generic
than the corresponding parameter types, and in the Cfront-like
ABI the argument that specifies the number of elements of the
array sometimes had type size_t whereas the parameter has type int.
Now fixed.  The size_t/int difference might have caused problems
if those types have different promoted sizes, but the function
pointer issues are unlikely to have caused actual bugs.

6/13/03  Microsoft compatibility: spurious typename warning

A change introduced in version 3.2 could result in a spurious "typename
may only be used within a template" warning in Microsoft mode.  This
has been fixed.

  template<class T> struct A {
    typedef int X;
    static X i;
  };
  template <class T> typename A<T>::X A<T>::i = (typename A<T>::X)(0);
  int main() {
    return A<int>::i;
  }

6/13/03  C99 STDC floating-point pragmas recorded for local block scopes

The C99 STDC pragmas had been incorrectly labeled as "global"
instead of local, which means that when they appeared in
local blocks in functions they were recorded in the IL in a
way that didn't easily allow one to recover the associated
block.  Now, they are recorded on the local block's pragmas
list.

6/12/03  Errors on offset overflow in tables built by IL lowering

IL lowering checks that offsets within classes and indexes within
virtual function tables fit in the fields used for them in the
generated code.  Unfortunately, the check was issuing only a
warning, and a very unhelpful warning at that.  Now, an error is
issued, and in most cases it includes the name of the 
overly-large or -complex class.

6/12/03  C99 imaginary: imaginary * integer, x ? imaginary : imaginary

In a few cases, operations involving imaginary operands in C99
mode were incorrectly done as complex operations instead of
as imaginary operations.  The cases are:

  -- a multiplication or division involving an imaginary and an
     integral operand
  -- a "?" operation with the second and third operands imaginary
  -- a comparison of two imaginary operands

The results were correct though inefficiently computed, but at least
in the first two cases one could observe the difference by using
sizeof on the operation result.  Now fixed.

6/12/03  C++-generating back end: compound literals in C++ mode

The C++-generating back end did not handle compound literals in
C++ mode, even though g++ mode now accepts compound literals.
Now, it does.

6/11/03  Microsoft compatibility: dllimport variable address not constant

A variable declared with the dllimport attribute in Microsoft mode
is now considered not to have a constant address (such variables
are implemented by indirection through pointer variables).
That means cases like the following now get an error in Microsoft
C mode (as they do with the Microsoft compiler):

  __declspec(dllimport) int GLOB;
  int *P = &GLOB;

6/11/03  GNU mode: Keep routine with "used" attribute

A routine marked with the GNU attribute "used" is now always kept in the IL,
even if the routine has internal linkage.  This used not to be the case
(contrary to what was reported in the relevant Changes entry of 2/4/03).
For example:

  static void f() __attribute__((used));
  static void f() {}  // Unused definition is now kept in the IL

6/11/03  Temporary for g++ compound literal incorrectly reused in block

The code generated by IL lowering for a compound literal in g++
mode incorrectly considered the temporary created a short-lifetime
temporary.  Though the C++ standard doesn't have compound literals
and therefore doesn't offer guidance on the lifetime of such temporaries,
the C99 standard says that local compound literals survive to
end of block, so we have changed to that interpretation.  The
former approach also caused a bug: two compound literals of the
same type in the same block used the same temporary, but of
course the temporary could be initialized to only one of the
compound literals, so the other use got the wrong value.
Now fixed.

6/11/03  Unset variable with multiple translation units,
         MAINTAIN_NEEDED_FLAGS FALSE

In versions built with MAINTAIN_NEEDED_FLAGS FALSE, some processing
in trans_copy.c/copy_entry used an uninitialized variable.  The
code in question is reached only with multiple translation units
(e.g., with exported templates).  Now fixed.

6/10/03  C mode: Abort on unusual syntax error in function definition

In C mode, the front end sometimes aborted during the processing of what seems
to be a function definition whose type is specified using a typedef name.
For example:

  typedef void F();
  F (x) int x; {}    /* Used to trigger an internal error. */

This is now fixed (normal errors are issued).

6/10/03  Use of (int)0 as null pointer constant in Microsoft C++ mode

MSVC++ versions up to 7.0 have a bug that considers zero cast to
an integral type, e.g., (int)0, not to be a null pointer constant.
This bug has been fixed in MSVC++ 7.1, so the emulation for the
bug is now turned off when microsoft_version is 1310 or greater.

6/9/03   IL structure error (based types list), C mode enum operation

The result type constructed for a C-mode enum operation sometimes
was a copy of another type, and the based_types list in the copy
was not cleared, which could cause IL traversal aborts later
(two IL entries had the same based_types list).  Now fixed.

  extern int foo (unsigned int *a) ;
  extern int bar (const unsigned int a);
  typedef enum { DECL_NONE } declType;
  static void addOtherFields ()
  {
    (0 ? DECL_NONE : (declType)0);  // Aborted in --gcc --no_remove mode
  }

6/5/03   GNU C++ mode: lookup of injected class name vs. constructor

g++ finds the injected class name in certain contexts where, according
to the standard, the constructor should be found.  Version 3.2 included
changes that addressed most such uses.  An additional case involving the
new operator is now also supported.

  struct A {
    A(int) {};
  };
  int main() {
    new A::A(1);  // now accepted in g++ mode
  }

6/5/03   Possible unaligned access in store_hex_fp_value

On some platform/configuration combinations, store_hex_fp_value could
perform improperly aligned memory accesses.  This could result in an
abort.  Now fixed.

6/5/03   Microsoft compatibility: __pragma operator

The Microsoft __pragma operator is now supported in Microsoft mode.

6/5/03   Expressions in g++ mode asm not lowered

Expressions used as operands in GNU C++ mode asm statements
were not subjected to IL lowering, which meant back ends might
see unexpected IL operators in some cases.  Lowering is now
done.  A similar though more rare problem could also occur in
gcc mode; C lowering (see lower_c99.c) is now done in that case.

6/4/03   Abort on member function used as template argument in
         template-dependent context

The front end aborted in expr.c on a use of the name of a member
function as a nontype template argument when the corresponding
template parameter is a reference type, in a template-dependent
context.  Now fixed.

  template<class>
  struct A {
    void f();
    template<int&> struct S;
    S<f> Sf;  // Formerly aborted on "f" here
  };

6/4/03   IA-64 ABI, bad code for dynamic_cast to reference type

The code generated by IL lowering for the IA-64 ABI for a dynamic_cast
to a reference type was wrong when the operand of the cast is not
simple (e.g., it is a function call rather than a simple variable).
The code failed to evaluate the operand, and then used the value
of an uninitialized temporary as the argument to the
__dynamic_cast runtime routine.  (The temporary should have been
set to the operand value.)  Now fixed.

6/3/03   Correspondence between functions referred to by friend declarations

Identically named inline functions in different translation units are now
made to correspond if they are referred to by matching friend declarations
of corresponding classes, even in modes without support for "extern inline"
functions (e.g., Sun mode).  For example:

  // Translation unit 1:
  inline void f() {} // (1) Internal linkage in Sun mode.
  struct X {
    friend void f();
  };
  // Translation unit 2:
  inline void f() {} // Corresponds to (1) even in Sun mode.
  struct X {
    friend void f();
  };

See also the Changes entry of 5/6/03.

6/3/03   GNU mode: Diagnostic on invalid type attributes

The front end used to issue a hard error when encountering attributes on
types that do not actually apply to types.  Now only a warning is issued.
For example:

  struct S {} __attribute__((section("text")));      // Now a warning.
                                                     // Previously an error.

Note that in cases like this GNU compilers sometimes issue hard errors
if the type involved is a typedef, but we do not emulate this distinction:
A warning is issued in all cases.

6/3/03   Microsoft compatibility: abort on in-class specialization

An abort would occur if a Microsoft in-class specialization of a class
template contained a member declaration with a default argument.  This
has been fixed.

  template<class T> class A {
    template<class U1, class U2, class U3> class B {};
    template<> class B<char, char, char> {
      B(int = 0);
    };
  };

6/2/03   Microsoft compatibility: Interface class types

In Microsoft C++ mode, the front end now supports interface class types.
Interface class types are essentially struct types declared with the
keyword "__interface" instead of "struct", and with the following additional
limitations:

  a)  An interface type cannot contain data members, constructors,
      destructors, member operator functions, friend declarations,
      private or protected access specifiers, member templates, member
      typedefs, static member functions, or nested class types.
  b)  An interface type cannot inherit from non-interface types (except
      that the IUnknown struct is treated as an interface in this case)
      and cannot have virtual bases.
  c)  Interface type templates are not allowed.
  d)  Interface types cannot be nested or local class types.

Furthermore, interface types are always abstract (i.e., a complete object
cannot have an interface type) and all their nonstatic member functions
are implicitly pure virtual (although the "virtual" and "= 0" specifiers
can be mentioned explicitly with no change in meaning).

For example:

  __interface I1 {
    void f() {}      // OK, but I1::f is pure virtual.
  };
  __interface I2 {
    struct N1;       // Error: No nested types.
    operator int();  // Error: No user-declared member operators.
  private:           // Error: No "private" or "protected".
    int  count;      // Error: No data members.
  };

6/2/03   Microsoft compatibility: _INTEGRAL_MAX_BITS predefined macro

The macro _INTEGRAL_MAX_BITS is now predefined in Microsoft mode to the
number of bits in the largest integral type supported by the front end.

6/2/03   IA-64 ABI: incorrect code to access virtual base class

The code generated by IL lowering for the IA-64 ABI failed to
initialize the virtual function table pointer early enough in
some cases to allow access to virtual base classes.  Now fixed.
This was okay in 3.1, but was broken by an optimization in 3.2.

  struct Base { Base();};
  struct Derived: virtual public Base {
    Derived() {;}
  };
  Derived d;
  extern Derived& obj = d;
  int i;
  Base::Base() {
    if ((Base *) &obj) i = 4;  // Okay by 12.7p2 of standard
  }
  int main() { return 0; }

6/2/03   Spurious error on elaborated type specifier in typedef inside template

A change introduced in version 3.1 resulted in a spurious error if a
class was initially declared using an elaborated type specifier in a
class template.  This error occurred when not using dependent name
lookup mode.  Now fixed.

  template <class T> struct A : public T {
    typedef struct X* my_x;
  };

5/30/03  Unset memory reference on error case in Microsoft and g++ modes

In certain error cases, unset memory could be referenced after diagnosing
errors on an invalid typedef declaration.  Now fixed.

  typedef I (*A)(B);

5/30/03  Incorrect parsing of "<" in function explicit template argument list

When scanning an explicit template argument list of a function template,
a "<" was sometimes incorrectly considered to start a nested template
argument list.  This has been fixed.

  template <char c> static void f() {}
  int main() {
     const char A=1, B=2;
     f< A < B ? A : B >();  // spurious '"A" is not a template' error
  }

5/28/03  Template template parameters with dependent default values

In certain cases, a template template parameter with a default value
that depended on another template parameter of the template did not
work properly.  This has been fixed.

  template <class T> struct A {};
  template <class T, class U = A<T> > struct B {};
  template<class T, template<class U, class = A<U> > class TT>
  void f(TT<T>& tt) { }
  int main() {
    B<int> v;
    f(v);  // formerly 'no instance of "f" matches the argument list'
  }

5/27/03  Problem with comparisons of nesting depths of template template
         parameters

A nonreal template class reference that makes use of a template parameter
of a template template parameter could sometimes result in the reuse
of a nonreal class for a template parameter that has a different nesting
depth.  In the example below, this would result in B<U> being treated as
B<T>.  Now fixed.

  template <class T> struct A {};
  template <class T, class U = A<T> > struct B {};
  template<class T, template<class U, class V = A<U> > class TT> void f(TT<T>);

5/24/03  Warning for nonstandard conversion between pointer to function
         and pointer to data

In strict warnings mode, a warning is now issued for a nonstandard
conversion between pointer to function and pointer to data.

5/22/03  Compilation error in cmd_line.c with NEAR_AND_FAR_ALLOWED FALSE

cmd_line.c did not compile correctly in a configuration with
MICROSOFT_EXTENSIONS_ALLOWED TRUE and NEAR_AND_FAR_ALLOWED FALSE.
Now fixed.

5/15/03  Microsoft C mode: Accept leading ", ..." parameter declaration

In Microsoft C mode, the front end now accepts a leading parameter spelled
", ..." as a way to indicate that a function can take an arbitrary sequence
of call arguments.  For example:

  void f(, ...) {}  /* Accepted in Microsoft C mode. */

Note that the C++ alternative "(...)" is still not accepted.

5/15/03  Incorrect IL increment operator, IA-64 ABI zeroing helper routine

In the code created by IL lowering in a generated routine that
deals with zeroing of an array containing a pointer to data member
in the IA-64 ABI, an increment operator in a loop increments a
pointer but had the operator for integer incrementation.  The
operator is now the pointer post-increment operator.

  struct A {
    int A::*p;
  };
  int main() {
    new A[10]();
  }

5/14/03  Abort on lowering of default initialization of anonymous union

IL lowering aborted in adjust_nonstandard_anonymous_union_references
(in a configuration with ALLOW_NONSTANDARD_ANONYMOUS_UNIONS) while
processing the zeroing of a standard anonymous union in an uninitialized
part of an aggregate, if the anonymous union is followed by a field
of a class type having a constructor.  Now fixed.

  struct XX { XX(); ~XX(); };
  struct A {
     char *name;
     union {
        long i;
        long j;
     };
     XX xx;
  };
  class A x[] = {{"1"}, {"2"},};

5/13/03  Abort in get_scope_for_list for unusual error case in strict mode

In some very unusual cases, the front end aborted in strict mode with an
internal error in get_scope_for_list.  For example:

  */ (
  namespace N {
    class A {
      template<class T> friend f(T, A a) { f(i, a); }
    };
  }

This is now fixed (normal errors are issued).

5/13/03  Microsoft/GNU C++ modes: Pure virtual specifier syntax

Normally, pure virtual member functions are declared using the "= 0" suffix,
where zero must be spelled exactly like "0".  However, Microsoft and GNU
compilers also accept alternative spellings like "00" and "0L".  This
relaxed behavior is now emulated in the corresponding C++ modes.  For example:

  struct X {
    virtual void f1() = 00;  // Accepted in Microsoft and GNU C++ modes.
    virtual void f2() = 0L;  // Accepted in Microsoft and GNU C++ modes.
  };

5/13/03  Microsoft compatibility: problem with using-directive bug emulation

In Microsoft bugs mode, when Microsoft version is <= 1200, we emulate a
Microsoft using-directive bug that makes visible certain names that
should not be visible.  There was a bug in this emulation that could
result in lookup errors when the using-directive in question appeared in
the std namespace.  This has been fixed.

  namespace std {
    namespace N {
      typedef int X;
    };
    using namespace N;
  };
  class X;
  int f(X *); // spurious ambiguity on X

-------------------------------------------------------------------------------
Version 3.2, May 12, 2003

5/11/03  IL version number changed to 3.2

5/10/03  GNU C++ init_priority attribute

The init_priority attribute is now implemented in GNU C++ mode
if GNU_INIT_PRIORITY_ATTRIBUTE_ALLOWED is TRUE.  It requires
back end and linker support, so it is not allowed by default.
See the init_priority field in a_routine.  The C-generating back
end implements this feature when it generates C code for gcc on
Linux.

5/10/03  USE_PATCH_INIT_STARTUP

A separate configuration flag USE_PATCH_INIT_STARTUP now controls
whether IL lowering puts out the code needed for startup initialization
for the Cfront "patch" approach.  This is a mostly-obsolete technique,
and the default is FALSE.  Previously, this code was put out in
many configurations, and was harmless but unneeded.

5/9/03   Internal error on overlong bit field with some configurations

When both configuration macros TARG_MICROSOFT_BIT_FIELD_ALLOCATION and
TARG_PAD_BIT_FIELDS_LARGER_THAN_BASE_TYPE were set to TRUE, the front end
would abort when processing bit fields whose specified length exceeds
the number of bits in the field's type.  For example:

  struct S {
    int m: 100;  // Used to abort with some configurations.
  };

This is now fixed.

5/9/03   Internal error on strange specialization syntax

An unusual syntax error suggesting a specialization of a static data member
could lead to an internal error.  For example:

  template<class> struct S {
    static int i;
    template<> int i = 1;  // Used to abort during instantiation.
  };
  template struct S<int>;

This is now fixed.

5/8/03   GNU C++ compatibility: use and redeclaration of inherited type name

The g++ compiler permits an inherited type name to be used in a derived
class and then for the same name to be redeclared as a typedef in the
derived class.  We now accept this in g++ mode.

  struct A {
    struct B { typedef int I; };
  };
  struct C : public A {
    typedef B::I B;
  };

5/8/03   Microsoft compatibility: spurious ambiguity from overridden
         using-declaration

In Microsoft mode, a member using-declaration that refers to a function
that is also declared in the class could result in a spurious ambiguity
when the function is called.  This has been fixed.

  struct B {
    void f(int);
  };
  struct D : public B {
    void f(int) {}
    void g() { f(0); }
    using B::f;  // causes ambiguity on previous line
 };

5/7/03   Unreachable code removed after constructor function try block

Some code that pops the top entry off the exception handling stack
at the end of the code for a constructor with a function try block
as the top statement is no longer emitted by IL lowering.  It was
unreachable, because the try block itself ends with a return and
each catch clause end with a rethrow.

5/7/03   K&R/pcc mode: Visibility of block-extern declarations

In K&R/pcc mode, block extern declarations are treated as if they appeared in
file scope.  This used to be case in version 2.40 and earlier of the front
end, but version 2.41 accidentally removed that aspect of K&R/pcc emulation.
For example:

  void f() {
    int foo();       /* Declared in file scope in K&R/pcc mode. */
  }
  int (*p)() = foo;  /* Accepted in K&R/pcc mode. */

5/7/03   Internal error on overloaded template with explicit argument list

An internal error (in equiv_template_arg_lists) could occur when using
an explicit template argument list, but no destination type, to identify
a unique instance of a function template from an overload set containing
multiple templates.  Now fixed.

  template <class T, class T2> void f(T);
  template <class T> void f(T);
  int main() {
    f<int>;
  }

5/7/03   Microsoft compatibility: static in-class specialization

The Microsoft compiler accepts a storage class on a nonstandard
in-class specialization.  We now accept this in Microsoft mode.

  struct A {
    template <class T> static void f(T) { }
    template <> static void f(int) { }
  };

5/6/03   GNU C++ compatibility: __null same size as void * pointer

The GNU C++ extension constant __null is now given an integer
type whose size matches that of a "void *" pointer, rather than
simply "int".  On Itanium and other 64-bit architectures, this
makes the constant work better when passed to an ellipsis
parameter.

5/6/03   IA-64 ABI: pointer-to-data-member not set to -1 in casts

The IA-64 ABI uses -1 for a NULL pointer-to-data-member value.
When entities are "zeroed", pointer to data members must be set
to -1.  This was not done for some cases involving casts to class
types.  Now fixed.

  struct A {
    int A::*p;
  };
  const A &r = A();  // p was not set to -1
  int main() {
    A();  // p was not set to -1
  }

5/6/03   Missing bool normalization in IA-64 ABI __cxa_guard_acquire call

In the IL, a tested boolean expression is supposed to be normalized
by addition of a "!= 0" test if the expression is not guaranteed
to be a pure 0/1 value already.  This was not done for the generated
call of __cxa_guard_acquire generated by IL lowering to do locking
of the initialization of a local static variable in the IA-64 ABI.
The "!= 0" has now been added.

5/6/03   C99 real + imaginary: new IL operators

The mixed real/imaginary add/subtract cases in C99 are now represented
by specialized expression operators (IL CHANGE):

  eok_fjadd      real      + imaginary
  eok_jfadd      imaginary + real
  eok_fjsubtract real      - imaginary
  eok_jfsubtract imaginary - real

These differ from the former implementation, of converting to
complex and adding, in that they preserve unusual values such as
negative zeroes.  The new operators are rewritten by lowering, so
customers who use lowering will not see these new operators.

5/6/03   Microsoft compatibility: nonstandard uses of typename

The standard requires that the typename keyword be followed by
a qualified name.  The Microsoft compiler accepts other keywords and
unqualified identifiers following the typename keyword.  We now emulate
this behavior in Microsoft mode.

  template <class T> struct B {
     typedef typename void (T::*pfunc)();
     typename pfunc my_pfunc;
  };
  struct A {};
  B<A> ba;

5/6/03   Correspondence between functions defined in friend declarations

During compilations involving multiple translation units, a function with
internal linkage does not normally correspond to another function of the
same name and type in another translation unit.  However, the front end
now makes an exception for functions defined in a friend declaration.
(A similar exception was already made for inline member functions.)
Such functions usually have external linkage, but in mode without support
for "extern inline" functions (e.g., Sun mode) they have internal linkage.
For example:

  // Translation unit 1:
  struct X {
    friend void f() {}  // (1) Internal linkage in Sun mode.
  };
  // Translation unit 2:
  struct X {
    friend void f() {}  // Corresponds to (1) even in Sun mode.
  };

This special treatment avoids surprising (albeit not entirely unjustified)
correspondence errors in Sun mode during compilations involving multiple
translation units.

5/6/03   Dual lookup of conversion type names

The standard requires that the type specified in a conversion operator
must be looked up in both the context in which it is called and in the
class of the object on which the operator is being called.  We now
implement the required dual lookup.  In default mode, a warning is
issued and the same type found by earlier versions is used.

  struct A { };
  struct B {
    typedef int A;
    operator A();
  };
  int main() {
    B b;
    int i = b.B::operator A();  // diagnostic now issued on A
  }

5/6/03   IA-64 ABI: mangled name for __alignof__

The mangling code for the __alignof__ operator in the IA-64 ABI
has been changed to match the mangling used by g++.  This is
a "vendor extended operator", for which the ABI spec does not
dictate an encoding, and the one we chose was slightly different
than the one chosen by g++.  We've changed ours to avoid a
gratuitous difference.  This is an ABI CHANGE, but highly
unlikely to appear in any code other than ABI test suites.
The fix is not controlled by ABI_COMPATIBILITY_VERSION.

5/6/03   IA-64 ABI: constructors return void

The spec for the IA-64 ABI says (in 3.1.5) that constructors return
void.  We missed that when we did the IA-64 ABI implementation.
That is now fixed.  Note that the fix is not controlled by
ABI_COMPATIBILITY_VERSION.

When we made this change, we noticed that our previous practice of
having the front end proper (rather than IL lowering) make the
return type of constructors be "reference to class" was not in
keeping with our model of what the IL should be.  (It matched the
Cfront-like ABI implementation, but not what was specified in the
source code.)  So we have changed things so that the front end
proper gives constructors a return type of void in all cases,
and for the Cfront-like ABI IL lowering changes the return type.
This is an IL CHANGE, though it is not visible for those who use
IL lowering.

5/5/03   Microsoft compatibility: Name linkage of variable redeclarations

In nonstrict modes (including Microsoft mode) the front end issues a warning
when a variable redeclaration conflicts in name linkage with the original
declaration.  Normally, an explicit name linkage specifier on the 
redeclaration is retained if the original declaration had no explicit 
linkage.  Now, however, the name linkage on the redeclaration is always
ignored in Microsoft mode.  For example:

  extern int v;          // Declaration implies "C++" linkage.
  extern "C" int v = 1;  // "C++" linkage retained in Microsoft mode;
                         // "C" linkage applied in other modes.

5/5/03   GNU C++ mode: Abort on use of typeof in namespace scopes

In GNU C++ mode, the IL lowering code (when enabled) used to abort when
processing a typeof operator applied to a nondependent type in namespace
scope.  For example:

  namespace N {
    int n;
    typeof(n) m;  // Used to trigger an abort in IL lowering.
  }

This is now fixed.

5/5/03   Template template parameters that depend on other template parameters

Support is now provided for template template parameters that have template
parameter lists that depend on other template parameters.  Formerly, an
error was issued for such cases.

  template <class T, template <T t> class X> class A {};
  template <int I> struct B {};
  A<int, B> b;

5/2/03   GNU mode: Unrecognized attributes with multiple arguments

In GNU mode, unrecognized attributes are normally ignored with a warning.
However, the front end used to not correctly skip a list of multiple
arguments following an unrecognized attribute.  This resulted in spurious
syntax errors.  For example:

  void f() __attribute__((unknown(1, 2)));
    // Used to result in a warning followed by errors.  Now just a warning.

This is now fixed.

5/1/03   Microsoft compatibility: Redeclaration of dllexport functions

In Microsoft mode, when a function first declared with a dllexport modifier
was redeclared without such a modifier, the front end used to issue a warning
and removed the modifiers from the IL entry for the function.  For example:

  __declspec(dllexport) void f();
  void f() {} // Used to trigger a warning and "dllexport" was ignored.
              // Now no longer a warning, and "f" is still marked "dllexport". 

This was changed to no longer issue a warning and to retain the original
declaration modifier.  (Note that similar cases with dllimport still trigger
a warning and the dllimport modifier is dropped when it is missing in the
redeclaration.)

4/30/03  Spurious correspondence error with friend name injection

In modes that enable friend name injection (such as Sun compatibility mode)
the front end sometimes emitted a spurious correspondence error (during
compilations involving multiple translation units) when a function was only
declared in a friend declaration.  This is now fixed.

4/30/03  Abort in C-generating back end on GNU statement expression

The C-generating back end aborted with the internal error "Routine
assignment inits not dumped out" on processing a statement
expression within an initializer, when the statement expression
itself contains another dynamically-initialized variable.
Now fixed.

4/29/03  Boolean literals in #if and #elif expressions

The front end used to treat the boolean literals "true" and "false" like any
other keywords when processing #if and #elif expressions: They were
transformed into the token "0".  Now their actual value is taken into
account.

  #if !true
  #error  No longer triggered since "true" is not turned into "0"
  #endif

4/29/03  Expression and statement traversal routines

New routines to traverse expression and statement trees have been
added in il_walk.c.  These routines, traverse_expr and traverse_statement,
allow us to remove a lot of duplicated custom code that walks those
trees and instead use a single set of generic routines with
user-supplied callback functions.

4/28/03  Statement expressions in GNU C++ mode

Statement expressions, i.e., ({ ... }), are now accepted in GNU C++
mode.  Formerly, they were accepted only in GNU C mode.  To avoid
various implementation difficulties, the following are prohibited
in statement expressions in C++ mode: destructible entities,
dynamically-initialized local static variables, local non-POD class
definitions, and try/catch.  Also, branching out of a statement
expression is not allowed, and statement expressions may not be
used in default argument expressions.  Variable-length arrays are
no longer allowed in statement expressions in GNU C mode (likewise
in GNU C++ mode, but VLAs are not allowed at all in C++ mode
anyway, at least so far).

4/28/03  GNU mode: Warning instead of error on promotable va-arg types

In GNU modes, the front end used to issue an error if the type passed to
va_arg would have been promoted to another type when passed through a
variable argument list (this is for configuration with built-in support for
va_arg; e.g., when DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE is TRUE).
This corresponded to the behavior of GNU C/C++ 3.0, but newer versions of the
GNU C and C++ compilers only issue a warning in such cases.  For example:

  #include <stdarg.h>
  void g(int n, ...) {
    va_list  ap;
    va_arg(ap, char);  // Used to be an error in GNU modes; now a warning.
  }

The front end now only issues a warning in GNU mode, in accordance with
newer version of the GNU compilers.  (See also Changes entry of 1/22/02.)

4/23/03  Spurious correspondence errors on inline functions

When support for "extern inline" functions was disabled (e.g., in Sun mode),
the front end sometimes issued spurious correspondence errors on inline
functions.  This is now fixed.

4/23/03  Internal error on dependent friend class

When source sequence lists and prototype instantiations are recorded in the
IL (i.e., GENERATE_SOURCE_SEQUENCE_LISTS and PROTOTYPE_INSTANTIATIONS_IN_IL
are both TRUE), the front end sometimes aborted with an internal error if an
unused class template contained a dependent friend class declaration.
(This problem only appears when removal of unneeded entities is enabled.)
For example:

  template<class T> class S;
  template<class T> class R { friend class S<T>; };
  template<class T> class S { inline void f(); };
  template<class T> inline
    void S<T>::f() {}
    // This translation unit used to trigger an abort.

This problem is now fixed.

4/22/03  Internal errors caused by layout of prototype instantiations

The front end used to perform complete class layout computations on
prototype instantiations, even though the resulting layout was void of any
meaning.  In addition, laying out prototype instantiations using the IA-64
ABI sometimes triggered internal errors when the layout code attempted to
analyze parameterized types.  For example:

  template<typename T, int N> struct S {
    T x[2][N];  // Used to abort during layout in IA-64 ABI configurations.
  };

To avoid these problems, and in the interest of compilation performance,
the front end no longer performs a complete layout for prototype
instantiations of class templates.  (Instead, such class types are given
the same size as an empty class type.)

4/22/03  Error on branch into GNU statement expression

An error is now issued on a transfer into a GNU statement expression.
gcc and g++ do not enforce this, but we think this is ridiculous
enough that an error check is appropriate.  It may also make life
easier for back ends.

  int main() {
    int i = ({ L: 0; });
    goto L;  // Gets error now
  }

4/21/03  GNU C++: Format attribute on nonstatic member functions

In GNU C++ mode, the parameter numbering scheme for the "format" and
"format_arg" attributes treats the implicit "this" parameter of nonstatic
member functions as number one.  Previously, the front end ignored the "this"
parameter and treated the first explicit parameter as number one.

  struct S {
    void f(char const*, ...) __attribute__((format(printf, 2, 3)));
      // Previously an error because the front end considered the ellipsis
      // parameter to be parameter "2".  Now accepted.
  };

4/21/03  Universal character names in identifiers

UCNs in identifiers were not translated to a canonical form.  As a result,
identifiers in which the UCNs were specified differently were considered
different identifiers.  This has been fixed.  All alphabetic characters
are converted to lower case, and only those UCNs that require more than
four digits are put out using the 8 digit notation.  Because this is an
ABI change, the new behavior is used only when ABI_COMPATIBILITY_VERSION
is >= 302.

  int i\u00c0\u1234\Uabcdabcdx;
  int i\u00c0A\u1234B\UabcdabcdY;
  int main() {
    i\U000000C0\u1234\UabcdABCDx = 1;
    i\u00C0A\u1234B\UAbCdAbCdY = 2;
  }

4/21/03  GNU C and Microsoft C: Type of block-extern variable declarations

In GNU C and Microsoft C modes (but not in the corresponding C++ modes), the
type of a block-extern variable declaration can include information from prior
declarations of that variable.  Specifically, the type used is the composite
type of the locally declared type and the previously obtained type.
For example:

  int x[] = { 1, 2 };  /* Type of x is "int[2]". */
  void f() {
    extern int x[];  /* Type of x in "int[2]" in GNU C and Microsoft C modes.
                        Type of x is "int[]" (incomplete) in other modes. */
    sizeof(x);  /* OK in GNU C and Microsoft C modes; error in other modes. */
  }

4/20/03  No const-qualification on "this" parameter in declaration
         when "new" is folded into constructor

The type of the "this" parameter generated by IL lowering for a
declared-but-not-defined constructor no longer has top-level const
qualification when NEW_CAN_BE_FOLDED_INTO_CTOR is TRUE.  Formerly,
const was removed on the interface when a definition is present
(because the added allocation code will assign to "this" within the
constructor body), but const was retained in any corresponding
declarations.  This was not incorrect C code, but some compilers and
back ends did not like it, and it wasn't an intentional difference,
so we've made the type the same for the declaration and definition
cases.

4/19/03  Incorrect using-directive lookup in template instantiation

In some unusual circumstances, names made visible by a using-directive
may not have been visible in a template instantiation (this problem
has existed since at least 2.38 but has only now been discovered).
Now fixed.

  namespace NA1 {
    namespace NA2 {
      int na2_var;
      template <class T> struct Base {
        Base() {
          typedef typename T::template Nested<int> nested_t;
          nested_t d;
        }
      };
    }
  }
  namespace NB {
    using namespace NA1::NA2;
    struct Derived : public Base<Derived> {
      template <class T> struct Nested {
        Nested() {
          (void)na2_var;
        }
      };
    };
    Derived d;
  } 

4/18/03  C++-generating back end: avoid putting out both inline and Microsoft
         __inline

The C++-generating back end now avoids putting out the "inline"
specifier on a declaration if the Microsoft "__inline" specifier
is also put out.

4/18/03  Spurious ambiguity on use of conversion function

A spurious ambiguity error could result if a conversion function was inherited
by more than one path.  This has been fixed.

  struct A {
    operator void *() const { return 0; }
  };
  class B : virtual public A {};
  class C : virtual public A {};
  class D : public C, public B {};
  int main() {
    D x;
    if (x == 0) return 1;
  }

4/18/03  Improved code for virtual base class access in constructor and
         destructor wrappers, IA-64 ABI

The code generated by IL lowering to initialize and destroy virtual
base classes in constructors and destructors is now improved for the
IA-64 ABI.   It now sets the virtual function table pointer of the
class less frequently, and addresses the virtual base classes
directly instead of going through the virtual base class pointer
in the virtual function table.

4/18/03  GNU C mode: Internal error on nonlocal address-of-label construct

In GNU C mode, the front end used to abort with an internal error when
encountering a use of the unary && operator ("address-of-label") outside a
function definition.  For example:

  void *j[] = { &&p };  // Used to trigger an internal error.

This is now fixed (a normal error is issued).

4/18/03  Microsoft/Sun compatibility: interaction with dependent name lookup

Dependent name lookup processing is disabled by default in Microsoft and
Sun modes, but if it is explicitly enabled (using a command-line option) it
did not work properly in those modes. In particular, lookup errors would
occur in explicitly specialized classes.  Now fixed.

  template <class T> struct A { };
  void g() {}
  template <> struct A<int> {
    void f() { g(); }  // spurious error: no matching "g"
  };

4/17/03  Unlinking from IL of destructions for non-polymorphic typeid

If a source program contains a typeid applied to an expression
that contains destructible entities but has an overall type that
is not polymorphic, the expression is not put into the IL tree
(it's not needed to evaluate the typeid at runtime) but the
destructions were still linked into the object lifetime
information.  This could potentially confuse back ends that
would see unlowered dynamic initialization entries on object
lifetime destruction lists.  Now fixed (the destructions are
unlinked once it has been determined that the expression is
not needed).

A related fix was made for other situations where expressions are
discarded.  That comes up mostly for errors, but there are
some odd cases with nonstandard pointers to members where the
selector object is discarded.

4/17/03  Abort in IL lowering on aggregate-initialized array of array

IL lowering aborted in lower_eh.c (in cleanup_region_number) on lowering
an array of array of class type that has a {...} form initializer
that leaves some implicitly-initialized array members, when exception
handling is enabled.  Now fixed.

  struct CString {
    CString();
    ~CString();
  };
  int main() {
    CString astringTypeParam[10][10] = {{CString(), CString()},
                                        {CString(), CString()}};
  }

4/16/03  IA-64 ABI: null pointer passed to __cxa_vec_new2 runtime routine

The IA-64 ABI runtime routine __cxa_vec_new2 has parameters for
the allocation and deallocation routines to be used.  Somewhat
surprisingly, the ABI spec says that one cannot pass null pointers
for those if they are not needed (as one can for the constructor and
destructor routines).  We assumed null pointers were okay and
did pass them in some cases, and the versions of the runtime
routines we provide handle that okay, but it does not conform
to the ABI spec.  Now, the front end passes the address of the
appropriate default operator new[] or operator delete[].

4/16/03  Global scope va_list alias not created when cstdarg is included first

When using built-in stdarg processing, if <stdarg.h> was included after
<cstdarg> had been included, the global scope alias for std::va_list
was not created.  Now fixed.

  #include <cstdarg>
  #include <stdarg.h>
  ::va_list x;  // resulted in spurious "va_list undefined" error

4/16/03  Spurious correspondence errors on prototype instantiations

When PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the front end sometimes issued
spurious correspondence errors between a class template and its prototype
instantiation (during compilations involving multiple translation units).
This is now fixed.

4/16/03  Spurious error on specialization of template static data member

A spurious error could occur when a template static data member is specialized,
and the type of the static data member is an array with an element type that
is an instance of a class template that has not yet been instantiated.  Now
fixed.

  template<class T> struct A { } ;
  template<class T> struct B {
    static A<T> arr[2];
  };
  template<> A<int> B<int>::arr[2] = { };

4/16/03  IA-64 ABI: Virtual bases can overlap with empty nonvirtual bases

Our original implementation of the IA-64 ABI could allocate virtual base
subobjects in the tail padding of trailing nonvirtual base subobjects.
A Changes entry of 3/11/03 explains that this was incorrect, but the fix
went too far by preventing virtual base subobjects from overlapping with
direct nonvirtual empty base classes.  (However, it appears that the
GNU C++ compiler also behaves in this way by default.)  For example:

  struct A {};
  struct B: A { virtual ~B() {} };
  struct C { int c; };
  struct D: B, A, virtual C {
    // Direct base A subobject should overlap with virtual base C subobject,
    // except when emulating GNU ABI bugs.
  };

This is an ABI CHANGE.

4/15/03  Declaration scope of function template prototype instantiations

The symbol entry created for the prototype instantiation of a function
template did not have its declaration scope set properly (it was set to
NO_SCOPE_NUMBER).  It is now set to the scope number of the associated
function template.

4/15/03  C99: keywords may be handled improperly in _Pragma operators

When scanning a pragma for which "processing_C_code" is FALSE, keyword
recognition should have been disabled but was instead enabled when the
pragma was specified using a C99 _Pragma operator.  Now fixed.

4/15/03  IA-64 ABI: g++ bug emulation of mangling for reference to
         member of template-dependent class

The emulation for g++ IA-64 ABI name mangling bugs has been toned
down in one case: a reference to a name like T::x, where T is
a template parameter, was rendered incorrectly (the second
operand of the "sr" scope-resolution operator was the full qualified
name instead of just the member name).  g++ apparently generates
the incorrect form only for members of non-dependent classes,
e.g., &B::x where B is not a template parameter.

4/15/03  IA-64 ABI: g++ bug emulation with mangling for array with
         dependent bound

An additional case has been added to the emulation of g++ 3.2 IA-64 ABI
bugs: the name mangling for a non-dependent array bound under a
dependent array bound is now rendered as an expression instead of a
constant.

4/15/03  IA-64 ABI RTTI information for pointer to array: g++ bug emulation

An additional case has been added to the emulation of g++ 3.2 IA-64 ABI
bugs: on a pointer to array, const and volatile qualifiers on the
array element type are not put out in the RTTI information.

4/15/03  Internal error on multi-translation unit case with unprototyped
         functions in C mode

The front end gave an internal error in trans_copy.c (in routine
transfer_routine_flags, though that was not indicated in the message)
on a multiple-translation-unit case in C mode in which a function
was unprototyped with no parameter information in one translation
unit and unprototyped with parameter information in another.  Now
fixed.

4/14/03  GNU C++ compatibility: default arg. in member of class template

g++ allows a default argument to be specified on the definition of a
member function of a class template that appears outside of its class
(the standard requires that such default arguments be specified
on the declaration in the class).  This is now accepted in g++ mode.

  template <class T> struct A { void f(T); };
  template <class T> void A<T>::f(T value = T() )  { }

4/14/03  Multiple preinclude search path problem

When using multiple preinclude files, the incorrect include file search path
was used for some of the preinclude files.  This has been fixed.

4/14/03  Microsoft C compatibility: output of __int8

The __int8 type, distinct from normal integers when microsoft_version
is 1200 (VC++ 6), was not output properly in C mode.  Instead, the
front end got an internal error in form_int_type_name
("bad integer kind").  Now fixed.

  void f(__int8);
  void f(char x) {}

4/3/03   GNU C++ compatibility: cast on address-of-reference is not lvalue

In g++ mode, the front end aborted while processing a use of
a cast of the address of a reference variable to a pointer type
as an lvalue (e.g., in an assignment).  The abort was in
prep_conversion_operand ("dest_type is reference").  Now fixed (by
making this case an error, as g++ does).

  int main() {
    int i = 1;
    const volatile int &ri = i;
    (int *)(&ri) = &i;  // Aborted in g++ mode, now an error
  }

4/3/03   IA-64 ABI: incorrect IL for string literals in aggregate initializer

In the IA-64 ABI, IL lowering replaces string literals in inline
functions with variables with specific mangled names, so that
a single copy of the string is shared among all the uses of the
function.  This lowering process did not work correctly when
a string literal appeared in an aggregate initializer.
The bug could result in truncated initializers (the constants
following the string were dropped), or IL write/read errors
if an IL file is written.  Now fixed.

  inline char* f() {
    char* vec[] = {"a", "b", "c", "d", "e", "a"};
    return vec[4];
  }

4/3/03   Abort in r_mangled_parent_qualifier, with exported templates

In come complicated test cases involving exported templates,
the front end aborted in r_mangled_parent_qualifier
("parent class has no body").  This came up during name mangling
for a local class used in a typeid, when the reference is
in a secondary translation unit and some combination of
circumstances causes the local class to be needed in the
secondary translation unit while the enclosing inline function's
body is not.  Now fixed.

4/3/03   Internal error when using insert_string_into_token_stream

A problem with insert_string_into_token_stream could result in an
internal error if the macro buffer required reallocation while
processing the insertion.  This has been fixed.

4/2/03   Zero-valued const integer variable as null pointer constant in cast

The front end did not properly consider a zero-valued const integer
variable as a null pointer constant in an explicit old-style cast.
Old-style casts to pointer types were accepted but were considered
reinterpret_casts, which might be a problem on odd architectures
where a null pointer is not actually all bits zero.  Old-style
casts to pointer-to-member types got a spurious error.

  const int null = 0;
  class B {};
  int main() {
    (int *)null;     // Accepted, but incorrectly considered a
                     //   reinterpret_cast
    (int B::*)null;  // Got spurious error
  }

4/2/03   Abort on use of # inside macro argument in #if expression

When ATT_PREPROCESSING_EXTENSIONS_ALLOWED is TRUE, a use of a "#"
inside a macro argument in a #if expression resulted in an abort
in scan_assert_predicate_reference in macro.c.  Now fixed.

  #define f(x) x
  #if f(#)  // Caused abort
  #endif

4/2/03   GNU C++ mode: lookup of injected class name vs. constructor

g++ finds the injected class name in certain contexts where, according
to the standard, the constructor should be found.  We now emulate this
in g++ mode.

  struct A {
    A(int) {};
  };
  A::A a(1);

4/1/03   Microsoft compatibility: __noop

The __noop keyword, added in MSVC++ 7.0, is now implemented.
When used as the "function" in a function call, it indicates
that the argument list should be discarded.  It is intended
for use with debug routines, e.g.,

  #if DEBUG
  #define dbprint printf
  #else
  #define dbprint __noop
  #endif

  dbprint("%d", i);

4/1/03   Subobject copies and generated bitwise operator=

The generated operator= function for a class is defined to do
memberwise copying.  That means that it must work when called for a
base class subobject.  The code generated to do the bitwise copying
did not do this correctly when base classes can have tail padding,
which can happen with the IA-64 ABI.  In those cases, the structure
copy generated by IL lowering could clobber some fields of a derived
class allocated in the tail padding.  IL lowering now generates a
memcpy call in those cases, which copies only the data bytes of the
subobject and does not touch the tail padding.

4/1/03   C++-generating back end, GNU C++ mode: 0 put out as __null

The C++-generating back end incorrectly put out a constant 0 as
__null after a use of __null in the source code in GNU C++ mode.
Now fixed.

  #define NULL __null
  void f(char *tmp) {}
  int g() {
    f(NULL);
    return 0;  // Incorrectly put out as return __null;
  }

3/31/03  Improved error message for invalid diagnostic option

The messages issued for an invalid operand to the --diag_suppress, etc.
options have been modified so that the cause of the error is more
obvious.

3/31/03  IA-64 ABI: No call of _main at start of main program

IL lowering no longer generates a call of _main at the start of
the main program when using the IA-64 ABI.  Such a call was
not in accordance with the ABI specification.  The runtime has been
updated to ensure that __cxa_terminate is called at the end of
the program, which was the main purpose of the call of _main.
The old behavior remains when ABI_COMPATIBILITY_VERSION is less
than 302.

3/30/03  IA-64 ABI: abort in lower_eh.c on RTTI for local enum

An abort in make_typeinfo_var in lower_eh.c has been eliminated.
It came up in versions using the IA-64 ABI for uses of typeid
or throw/catch on an enum type that is a member of a local class.

3/28/03  Unnecessary VTT parameter on constructors/destructors, IA-64 ABI

When the IA-64 ABI is used, IL lowering adds parameters to
constructors and destructors.  One of those parameters is
the so-called VTT parameter, which points to an array of
virtual function table pointers used in subobject construction
or destruction.  This parameter is necessary only when the
class has virtual base classes, but IL lowering added it always.
The parameter has now been removed on the internal constructors and
destructors for classes without virtual base classes.  Note
that the "internal" constructors and destructors, though external,
are called only from the alternate entry points in the same
translation unit, and therefore this change is not really an ABI
change.

3/28/03  Unnecessary wrapper routines for IA-64 ABI constructors

In some cases when the IA-64 ABI is used, IL lowering generated
some unnecessary wrapper routines for references to constructors,
in particular in array "new" operations.  This was harmless but
inefficient.  The unnecessary wrapper routines are no longer
generated.

  struct A {
    A();
  };
  A::A() {}
  struct B {
    int A::*i; 
    A a; 
  };
  int main() {
    B *p = new B[10]();
  }

3/27/03  Performance improvement of string literals in IA-64 ABI

Special processing is required for function-scope string literals when
using the IA-64 ABI.  The performance has been improved for functions
that use a very large number of string literals.

3/26/03  GNU C++ mode: Syntax for pure virtual function declarations

In GNU C++ mode, the front end now accepts, in addition to the "= 0" form,
the "= __null" syntax for declaring a pure virtual function.

  struct S {
    virtual void f() = __null;  // Accepted in GNU C++ mode; same as "= 0".
  };

3/26/03  Zeroing for value-initialization in array new, IA-64 ABI

The code generated by IL lowering for an array new with value
initialization was incorrect in some cases with the IA-64 ABI,
in that it did not zero the storage before calling the
default constructor.  Now fixed.

extern "C" int printf(const char *, ...);
  struct A {
    A();
  };
  struct B {
    int i; 
    A a; 
  };
  int main() {
    B *p = new B[10]();  // "i" field should have been zeroed, but wasn't
  }

3/26/03  Improvement of helper routine for IA-64 ABI zeroing

When IL lowering needs to do zeroing of an entity that contains
a pointer to data member, it generates a helper routine that
does the initialization.  In the past, this helper routine
always had a second parameter that indicated the number of
array elements to be initialized.  Now, in cases where the
entity to be initialized is not an array (i.e., most of the
time), the helper routine no longer has the added parameter, and
no longer contains a loop to do the initializations.

3/26/03  Bad code generated for zeroing of value-initialized base class

The code generated by IL lowering to zero a base class before
calling the constructor when the base class appears in a
ctor-initializer that requests value-initialization (i.e., one
with "()") did a structure assignment, which zeroed too much space
if the class has virtual base classes.  This could potentially
cause aborts if something already initialized follows the base
class.  A memcpy call of the proper size is now generated instead.

  struct A { int i; };
  struct B : virtual public A { int j; };
  struct C : public B {
    C() : B() {}  // Zeroing of B cleared too much storage
  };

3/26/03  Lookup error when using multiple translation units

When using exported templates or compiling multiple translation units,
a lookup in translation unit X using a namespace from translation unit
Y could produce an incorrect result.  This could, for example, cause
certain functions to be ignored when doing argument-dependent lookup.
This has been fixed.

3/26/03  GNU mode: Rendering of asm operands by C/C++-generating back ends

The C- and C++-generating back ends incorrectly omitted a colon when
generating extended asm operand descriptions that included output operands
and clobber specifications but no input operands.  For example:

  void f() {
    int x;
    __asm__("\n1:\t" : "=m"(x) : : "memory"); // ": :" used to be reduced
  }                                           // to just ":"

This is now fixed.

3/26/03  C99: spurious error on hex floating-point constant

In C99 mode, a spurious error was issued if a hexadecimal floating-point
constant had a exponent that was too large but a mantissa of zero.  Now fixed.

  double d = 0x0.0p100000000;

3/26/03  GNU C mode: Declarations can appear anywhere in a block

In GNU C mode, the front end now no longer requires that all the declarations
in a block appear at the beginning of that block.  For example:

  void f(int *p) {
    *p += 1;
    int a = *p;  // Now accepted in GNU C mode.
  }

3/25/03  Problem with comparison of dependent nontype template arguments

A problem with the comparison of dependent nontype template argument
values could cause them to compare incorrectly in some cases.  The
cases involve nontype template arguments of the form "T::x", where T
is a dependent type.  In the example below, this resulted in a spurious
ambiguity because the two function template declarations were treated as
declaring separate templates.  Now fixed.

  template <int* ip> struct A {};
  struct B { static int x; };
  template <class T> void f(A<&T::x>);
  template <class T> void f(A<&T::x>);
  int main() {
    f<B>(A<&B::x>());
  }

3/25/03  Microsoft compatibility: ctor-initializer lookup

In Microsoft mode, the front end emulates the ctor-initializer lookup
that is done by the Microsoft compiler.  This lookup finds base class names
that may not otherwise be visible even though the Microsoft compiler
(prior to version 7.1) does not support class name injection.  A flaw in
this emulation resulted in a spurious error on examples such as this one.
Now fixed.

  struct B { };
  struct C : public virtual B {
    int B;
    C(int i = 62) : B(i) { }
  };

3/25/03  GNU C++ mode: Minimum and maximum operators

In GNU C++ mode, the front end now recognizes the binary operators "<?" and
">?".  They evaluate (respectively) to the minimum and maximum values of
their operands.  These are built-in operators for arithmetic types and for
pointer types.  When both operands are lvalues of identical type, the
built-in minimum and maximum operators result in lvalues.  For example:

  int a[3<?4]; // Same as a[3]
  void f(double x, double y) {
    x >? y = 1.0;  // The largest of x and y is set to 1.0.
  }

The operators can also be overloaded for user-defined types.

3/25/03  GNU C++ mode: injected template names

When doing name lookup in a base class, g++ does not find the injected
class name of a template class.  We now emulate this behavior in g++ mode.

  namespace N {
    template <class T> struct A {};
  }
  struct A {
    int i;
  };
  struct B : N::A<int> {
    B() { A x; x.i = 1; }  // g++ uses ::A, not N::A
  };

3/25/03  Microsoft compatibility: nonstandard use of specialization syntax

The Microsoft compiler (prior to version 7.1) allows the definition
of non-templates using the "template <>" specialization syntax.  We
now emulate this behavior in Microsoft bugs mode when Microsoft version
is < 1310.

  template <class T> struct A {
    void f(T){}
  };
  template <> struct A<int> {
    void f(int);
  };
  // A member of a specialized class should be defined without the
  // "template <>".
  template <> void A<int>::f(int){}

3/24/03  Internal error on catch parameter with ambiguous copy constructor

The front end used to abort with an internal error when catch clause
parameter had a type with an ambiguous copy constructor.  For example:

  struct S {
    S(S const&);
    S(S volatile&);
  };
  void f() {
    try {} catch (S) {}  // Error: Ambiguous copy constructor for S.
  }                      // Used to trigger an internal error.

This is now fixed: An error is issued without aborting.

3/21/03  GNU compatibility: Label attributes

The front end now parses attributes following a label as being associated
with that label.  In particular, the "unused" attribute is now recognized for
labels: It inhibits warnings about a label being unreferenced.

3/21/03  Remark no longer issued for unused template parameter

Formerly, a remark was issued if a template parameter was not used
in the signature of the function template.  This proved an annoyance as
such usage is fairly common, so the remark has been removed.  A warning
is still issued for constructors and conversion operators as unused
template parameters render such functions uncallable.  An error is
still issued when distinct_template_signatures is FALSE.

  template <class T> void f();

3/21/03  Microsoft compatibility: __declspec and other modifiers allowed
         in invalid locations

The Microsoft compiler accepts __declspec and other modifiers in a
variety of invalid locations.  We now emulate this behavior in
Microsoft bugs mode.  A warning is issued.

  template <class T> class A {};
  class __declspec(dllexport) B {};
  template <> class A<__declspec(dllexport) B>;
  template <> class A<__forceinline B>;
  int i = sizeof(__declspec(dllexport) B);

3/21/03  Microsoft compatibility: explicit template arguments in
         function declarations

In Microsoft mode, explicit template arguments have been allowed on
certain function declarations.  Our support of this has been refined
in two ways: First, the Microsoft compiler does not generally accept
such arguments on function declarations, so we now reject line #2.
Second, this bug has been fixed in the 7.1 compiler, so line #3 is
accepted only if microsoft_version is < 1310.

  template <class T, class T2> int f(T) { return 1; }  // #1
  // Should be rejected:
  template <class T> int f<double>(T) { return 2; }  // #2
  // Accepted when microsoft_version < 1310
  int f<int,int>(int){ return 3; }  // #3

3/21/03  Spurious error on operator template friend

A spurious "too few parameters" error was issued on a operator template
friend declaration.  This has been fixed.

  template <class T> struct X {
    template <class U> friend void U::operator+=(U);
  };

3/20/03  Abort in which_binary_operator after declaration error

An abort ("internal error: which_binary_operator: bad type")
occurred after an error for a declaration that mixes a
conversion function declaration and a variable declaration in a
declaration comma list.  Now fixed.

  operator int(), flag;
  void f() { flag = 1; }

3/20/03  Virtual function table tables now const

The tables of virtual function table addresses (also known as
VTTs, in the IA-64 ABI terminology) generated by IL lowering are
now generated as const so they can be placed in read-only memory.

3/18/03  Missing access error in compiler-generated function

If a compiler-generated function was produced during the instantiation
of a template, the access of the template could affect the access checking
done during the generation of the function.  This could result in missing
access errors.  Now fixed.

  template <class T> class B {
      B() {}
  public:
      static B * f() { return new T; }
  };
  class D : public B<D> { };
  int main(void) {
    B<D> * p = B<D>::f();
  }

3/18/03  Multiple --preinclude and --preinclude_macros options

The use of multiple --preinclude and/or --preinclude_macros options
is now supported.  As with gcc/g++, all of the macro preincludes are
processed before the other preincludes, but within each group they are
processed in the order specified on the command line.

3/17/03  Incorrect check for loop on operator->

The check for a loop while resolving overloaded operator->
references ignored cv-qualifiers, which could sometimes cause
a spurious error in some cases where the "->" actually could
be resolved.  Now fixed.

3/13/03  Instantiation of virtual functions for types used by RTTI

Changes made in version 3.1 caused virtual functions of types used in
operations that rely on RTTI data structures to be instantiated
earlier than had previously been the case.  That caused problems in
certain cases.  The previous behavior has been restored.

  template <class T> struct A;
  template <class T> struct B { virtual void f(){} };
  template <class T> struct D : B<T> {
	virtual void f() { A<T> a; }
  };
  void f(B<int>* b) {
    D<int>* d = dynamic_cast<D<int>*>(b);
  }
  template <class T> struct A {};

3/13/03  C-generating back end: #line inside comment

In some cases, the C-generating back end put out a #line
directive inside an annotation comment when a long line was
continued to another line.  This was mostly harmless, but
also unintentional.  Now fixed.

3/12/03  __FUNCTION__ and other macros accepted in all modes

The __FUNCTION__, __PRETTY_FUNCTION__, and __BASE_FILE__ macros are now
accepted in all modes.

3/12/03  GNU C++ mode: friend declaration of undeclared template

In g++ mode, a friend declaration in which the function name is a
template-id of an undeclared template is now accepted when the declaration
appears within a class template.

  template <class T> struct A {
    friend void f<>(A<T>);
  };

3/12/03  Incorrect code for C99 _Bool decrement

IL lowering generated incorrect code for prefix or postfix decrement
of a _Bool variable in C99 mode.  The C99 standard requires that
such a decrement flip the value (0->1, 1->0), and we had implemented
setting the variable to zero instead.  Now fixed.

3/12/03  Diagnostic control pragmas

Pragmas have been provided that can be used to override the severity of
certain diagnostics (similar to the --diag_xxx command-line options).
The pragmas are diag_suppress, diag_remark, diag_warning, diag_error,
and diag_default.  The syntax is:

  #pragma diag_xxx [=] err_code, err_code, err_code, ...

The "=" is optional.  The pragma specifies one or more error codes.  As
with the command-line options, each error code can be an error number or
an error tag.  The diag_default pragma returns the severity associated
with a given message to the value used before any pragmas were specified
(i.e., either the normal value of the value specified by a command-line
option).  As with the command-line versions, only messages with a
severity of "discretionary error" or below may have their severity
overridden.

  #pragma diag_suppress 522
  class A { friend class A; };  // pointless friend warning suppressed here
  #pragma diag_default 522
  class B { friend class B; };  // but not here

3/11/03  Folding "new" into constructor or runtime routine, with unusual
         delete

In two cases, IL lowering generated incorrect code for "new" operations
where the operator new routine is the default one and the operator
delete is unusual, and exceptions are enabled:

  a)  A ::new of a class type, where the class declares a class-specific
      operator delete but no class-specific operator new, and
      NEW_CAN_BE_FOLDED_INTO_CTOR is TRUE (default for the Cfront-like
      ABI).  The allocation was performed by the constructor, which
      would call the wrong operator delete if an exception is thrown.
      The allocation is now done before calling the constructor.
  b)  A new of an array type, where the class declares a class-specific
      operator delete[] but no class-specific operator new[], and
      NEW_AND_DELETE_FOR_ARRAY_CAN_BE_FOLDED_INTO_RUNTIME_ROUTINE
      is TRUE (default).  A default runtime vector-allocation
      routine was called, which would call the wrong operator delete[]
      if an exception is thrown.  A general-purpose vector-allocation
      routine, which has a parameter that can be used to specify
      the appropriate operator delete[] routine, is now called.

3/11/03  IA-64 ABI: Virtual bases should not reuse the tail padding of
         nonvirtual empty bases

The EDG implementation of the IA-64 ABI used to allocate virtual base classes
in the tail padding of trailing nonvirtual empty base classes under some
circumstances.  However, this is not allowed by the IA-64 ABI specifications.
This is an ABI CHANGE, which we are retroactively considering part of the 
3.1 release.  [Patch sent out 3/19/03.]

3/10/03  Incorrect code for copy of empty base class in generated copy
         constructor

When empty base class optimization is enabled (see
TARG_OPTIMIZE_EMPTY_BASE_CLASS_LAYOUT), the code added in a generated
copy constructor to copy an empty base class for which construction by
bitwise copy can be done was incorrect.  Specifically, nothing should
be copied in that case, but the generated code copied a block of
memory of length sizeof(empty_class).  That would clobber space
following the point of allocation of the empty base class.  If that
space contained other members or base classes, this was generally
harmless, but if it contained a pointer to a virtual base class (in
the Cfront-like ABI) the pointer would have been set already and the
move clobbered it.  Now fixed.  [Patch sent out 3/19/03.]

  struct E {};
  struct A {
    virtual ~A();
  };
  struct B : virtual A, public E {};
  B b;
  B bb = b;

3/10/03  IL field not initialized and not displayed

The field "range_end" in switch case entry fields was neither initialized
(in il_alloc.c) nor displayed (in il_display.c).  This has been fixed.
[Patch sent out 3/19/03.]

3/6/03   Spurious type incompatibility errors with multiple translation units

In some relative rare situations, the front end would issue an error that
a type in a secondary translation unit is incompatible with the same
type in the primary translation unit.  The types were members of class
type instantiations.  The problem has been fixed.

3/6/03   Incorrect construction vtable setup, with multiple translation
         units

In compilations with multiple translation units (e.g., with exported
templates), where a base class requires the special construction
vtable handling (it has virtual functions in virtual base classes),
and the constructor and or destructor for the derived class is
defined only in a secondary translation unit, the code generated
to do construction or destruction sometimes did not properly pass
a set of virtual function tables to the subobject constructor or
destructor.  As a consequence, the program was likely to abort
at runtime.  [Patch sent out 3/19/03.]

3/6/03   "restrict" keyword in template strings

When building template strings, the processing for the "restrict" keyword
is now the same as that used when emitting "restrict" in code generated
by the C++-generating back end.  If SUPPRESS_RESTRICT_IN_GENERATED_CODE
is TRUE, it is not emitted at all.  Otherwise, it is emitted as "restrict"
unless GCC_IS_GENERATED_CODE_TARGET is TRUE, in which case it is
emitted as "__restrict__".

3/5/03   IA-64 ABI: __cxa_vec_ctor returns void

The IA-64 ABI runtime routine __cxa_vec_ctor returns void, not
void * as we thought.  The front end and the runtime have been
changed accordingly.  Note that this is an ABI CHANGE, which
we are retroactively considering part of the 3.1 release.
[Patch sent out 3/19/03.]

3/5/03   GNU C++ mode: cast from pointer to smaller integer allowed

In GNU C++ mode, a cast from a pointer type to an integer type that
is smaller than the pointer type is now allowed, with a warning.

3/5/03   GNU C and C++ modes: nonstandard casts allowed in null pointer
         constants

GNU C and C++ modes now allow some nonstandard casts in null pointer
constants, e.g., (int)(int *)0 and, in C mode, (void *)(int *)0.

3/5/03   GNU C++ mode: Redeclared function template default arguments

In GNU C++ mode, a function template default argument may be redeclared.
A warning is issued and the default from the initial declaration is used.

  template<class T> void f(int i = 1);
  template<class T> void f(int i = 2){}
  int main() {
    f<void>();
  }

3/5/03   Missing definition of extern inline function with export and
         LOWER_EXTERN_INLINE

In some very complicated cases using export, in a configuration
with LOWER_EXTERN_INLINE set to TRUE, the definition of an extern
inline member function of a template might be missing (resulting
in an unsatisfied external at link time).  This was due to a problem
in the copy process for multiple translation unit IL, now fixed.
[Patch sent out 3/19/03.]

3/5/03   compiler_generated flag in cast following conversion function
         call

The compiler-generated flag is now FALSE in a cast generated to
perform the standard conversion following the invocation of
a conversion function, if the overall conversion is caused by
an explicit cast in the source code.

3/4/03   File handle not released on Windows version

On Windows, the routine that reads directory entries failed to release
a file handle after the last entry had been read.  Now fixed.

3/4/03   Microsoft compatibility: injected class name handling

In Microsoft bugs mode, special treatment is given to injected class
names to emulate the special way they are handled by the Microsoft
compiler.  This special treatment is no longer needed when emulating
version 7.0 of the Microsoft compiler, so it is now done only when
microsoft_version is < 1300.  This example compiles with the
Microsoft 7.0 compiler but not with 6.2.

  namespace N { struct A { }; }
  struct B : public N::A {
    A a;
  };

3/3/03   Invalid lowered code for virtual function call (this parameter
         mismatch)

In some convoluted cases involving multiple translation units
(e.g., with exported templates), IL lowering failed to lower the
function type used in a virtual function call.  As a consequence,
the type in the cast of the function address from the virtual
function table did not have a "this" parameter, while the associated
argument list (correctly) did.  Now fixed.  [Patch sent out 3/19/03.]

3/1/03   Incorrect setting of C99 STDC pragma information

The settings of C99 STDC pragma information (FP_CONTRACT, FENV_ACCESS,
and CX_LIMITED_RANGE) were not reset properly when exiting a scope.
This would, for example, result in the function g() incorrectly having
its FENV_ACCESS state set to ON instead of DEFAULT.  Now fixed.

  void f() {
    #pragma STDC FENV_ACCESS ON 
  }
  void g() {}

2/28/03  Emulation of GNU bugs in IA-64 object layout algorithm

Some changes were made to the front end to more closely emulate the
erroneous behavior of the GNU C++ 3.2 implementation of the IA-64 ABI
when DEFAULT_EMULATE_GNU_ABI_BUGS is TRUE.  (The GNU C++ 3.2 ABI is
also used by default in later versions of GNU C++.)  These relatively
subtle changes are all related to the alignment of virtual base class
subobjects.  [Patch sent out 3/19/03.]

2/27/03  GNU C mode: Ignore anonymous union field name conflicts

Version 3.1 of the front end added support for nonstandard anonymous unions
in GNU C mode (version 3.0 erroneously parsed these as ordinary struct
definitions).  However, we used to issue an error when such a construct
injected a field name in the surrounding class that conflicts with an
existing field name.  We now emulate GNU compilers by issuing a warning
instead of an error and by making the later declaration invisible.
For example:

  struct S {
    int f;
    struct AU {  // Nonstandard anonymous union.
      int f;     // No longer an error in GNU C mode, but this field is
    };           // no longer visible in struct S.
  };

2/25/03  Duplicate definition of wrapper routine for virtual function
         with covariant return, Cfront-like ABI

When the Cfront-like ABI is used and LOWER_EXTERN_INLINE is TRUE,
the generated wrapper routine (or "thunk", or "surrogate function")
for an inline virtual function with a covariant return type was
put out as an external definition.  This could cause a link-time
error for a duplicate definition if another copy of the same
function was generated in another compilation.  Such a function
is now put out properly as a static inline function.
[Patch sent out 3/19/03.]

  struct A {
    virtual A *f() {}
  };
  struct AA { int i; };
  struct B : public AA, public A {
    virtual void g();
    virtual B *f() {}
  };
  void B::g() {}

2/25/03  IL lowering typeinfo variable handling with GENERATE_EH_TABLES
         set to FALSE

The no-EH-lowering mode indicated by GENERATE_EH_TABLES set to FALSE
did not work quite right with regard to typeinfo variables.  Specifically,
eff_type_for_typeinfo should do nothing in that mode, not drop pointer
and reference types (that's appropriate for the EDG EH implementation,
but not in general).  Also, the code that determines whether a local
type typeinfo should be put into a COMDAT in the IA-64 ABI was
incorrect and could cause an assertion failure in make_typeinfo_var
(on a line that tests innermost_function_scope != NULL).  Both fixed.
[Patch sent out 3/19/03.]

2/25/03  IA-64 ABI: missing typeinfo for class used only in pointer to member

A class used only in a pointer-to-member type in an exception
handling context in a version that uses the IA-64 ABI could result
in a link error due to a missing typeinfo variable for that
class type.  Now fixed.  [Patch sent out 3/19/03.]

  template <class T> struct A {
    A(int) {}
    virtual ~A();
  };
  template <class T> A<T>::~A() {}
  void f(A<int>) {}
  void f(int) {}
  int main() {
    f(0);
    throw (int A<int>::*)0;
  }

2/24/03  Bad C for function with covariant return and two return statements

The C-generating back end generated bad C, specifically several
temporary variables with the same name within a single function, when
processing a function with a covariant return type and more than
one return statement in its body.  Now fixed.

  struct A {
    int i;
    virtual A *f();
  };
  struct AA { int j; };
  struct B : public AA, public A {
    virtual B *f();
  };
  B *B::f() {
    if (i == 0) return 0;
    return 0;
  };
  B b;
  int main() {
    b.f();
  }

2/24/03  Internal error in IL lowering of exception handling

An internal error ("region table generated but empty lifetime on func",
in lower_eh.c) was generated while lowering a generated routine
in exception handling.  Now fixed.  [Patch sent out 3/19/03.]

2/20/03  GNU C mode: Nonempty class types marked as empty

In GNU C mode, a nonempty class type sometimes had its is_empty_class
flag set to true.  For example:

  typedef int I;
  struct S { I i; };  // Incorrectly marked as empty

This is now fixed.  [Patch sent out 3/19/03.]

2/20/03  Use of uninitialized variable in process_overloaded_operator_arrow

Some code in process_overloaded_operator_arrow (used to check the
left operand of the "->" operator for overloading) used an uninitialized
structure in some cases, which could lead to a crash.  Now fixed.
[Patch sent out 3/19/03.]

2/20/03  Abort in extract_constant_from_operand, "?" operator in C mode

An abort in extract_constant_from_operand has been fixed.  The
abort occurred in C mode on a "?" operator in a constant expression,
where the first operand's value is not known at compile time.

  void *f();
  void*(*p)() = f ? f : f;
  int main(void) {
    return 0;
  } 

2/20/03  Abort in process_local_types on export cases

An abort has been fixed in process_local_types (il_walk.c line 2377
in version 3.1).  This bug was introduced in version 3.1 and
comes up only for complex export cases.  [Patch sent out 3/19/03.]

2/19/03  IL lowering generated multiple virtual function tables for type_info

When the source code for the EDG runtime routine typeinfo.c is compiled
by the front end, a bug introduced in version 3.1 caused IL lowering
to generate two virtual function table variables for type_info.  With
C generation, this made no difference, because the declarations for
the two variables would be considered to declare a single variable.
However, when the IL is fed to a back end, the two global variables
with the same name could end up causing problems.  Now fixed.
[Patch sent out 3/19/03.]

2/19/03  Internal error when lowering base classes with classic EDG layout

Under relatively rare circumstances, an internal error was triggered while
lowering a class with a virtual base class, but without virtual functions.
This problem only occurs in configurations with the classic (Cfront-like)
EDG layout algorithm.  For example:

  struct C1 {};
  struct C2 { C1 d1; };
  struct C3 {};
  struct C4 : C2, virtual C3 {};
  struct C5 : virtual C3, C1, C4 {};  // Abort while lowering this class

This is now fixed.  The underlying issue is an ABI problem that was
introduced when the empty base class optimization was implemented for
the Cfront-like ABI.  This is therefore also an ABI CHANGE, although
in most configurations (i.e., when IL lowering is enabled) an internal
error was triggered.  In the latter case, the ABI difference could not
be noticed since no object file was actually generated.
[Patch sent out 3/19/03.]

2/19/03  Internal error when using precompiled headers with export

An internal error (in init_date_and_time_macros) could occur when using
precompiled header files in conjunction with exported templates.  this
has been fixed.  [Patch sent out 3/19/03.]

2/13/03  Spurious correspondence error

A spurious correspondence error was issued if a class like the one below
was included in more that one translation unit.  The problem occurred
when the initializer of a const static data member involved a dependent
function call, and only in compilations involving multiple translation 
units (e.g., with exported templates).  Now fixed.  [Patch sent out
3/19/03.]

  template <class T, class T2> struct A {
    static int test(...);
    static int test(T2);
    static const bool value = sizeof(test((T())));
  };

2/13/03  Spurious warning on unintended use of alternative token

Certain valid uses of alternative tokens would result in an "unintended
use of alternative token" warning.  This has been fixed.

  char t<::> = "t";

2/12/03  GNU mode: Attribute "aligned" on typedefs

The front end used to ignore attributes on typedefs of class types and
enumeration types.  This is no longer the case: In GNU modes, an attribute
on a typedef will affect the alignment field of the corresponding tk_typeref
type entry.  As a result, care is advised when accessing the alignment
field of a type obtained from the application of the skip_typerefs macro.

2/12/03  Abort in IL display utility with C99 variable-length arrays

The IL display program used to abort when trying to output the type of a
variable-length array.  This is now fixed.  [Patch sent out 3/19/03.]

2/12/03  Missing error: storage class in template static data member definition

The front end failed to diagnose the presence of a storage class in a
template static data member definition.  Now fixed.

  template <class T> struct A {
    static int i;
  };
  template <class T> static int A<T>::i = 1;

2/12/03  Missing strict-mode error on implicit "int" in template parameter

A nontype template parameter declaration that omits an explicit type
specifier resulted in a warning instead of an error in strict mode.
Now fixed.

  template <const> struct A {};

2/11/03  GNU C++ mode: Old-style parameter lists and attributes

In GNU C++ mode, the front end would sometimes erroneously treat as an
old-style parameter list a parenthesized initializer followed by an
attribute.  For example:

  struct S { S(int); };
  int x;
  S s(x) __attribute__((alignment(4)));  // Used to trigger an error
                                         // in GNU C++ mode.

In the example above, "s(x)" was incorrectly parsed as a function declarator.
This is now fixed.

2/11/03  UPC mode: Folding of unary operations

The front end no longer attempts to constant-fold unary operators applied on
the UPC pseudo-constants THREADS and MYTHREAD.  The implicit conversion of
these constants to a boolean constant is also inhibited.

2/10/03  Microsoft/Sun/Cfront compatibility: Ambiguous virtual function
         overriders

In Microsoft bugs mode, Sun mode, and Cfront mode, no diagnostic is issued
for classes defined in such a way that a virtual function is ambiguously
overridden in some base classes when all but one of those base classes is
ambiguous.  For example:

  struct V { virtual void f(); };
  struct B: virtual V { virtual void f(); };
  struct D1: B {};
  struct D2: B { virtual void f(); };
  struct X: D1, D2 {};  // Normally an error, but not in Microsoft bugs mode,
                        // Sun mode, or Cfront mode.

In such cases, the overrider selected by the front end is the one from the
unambiguous base class.  This error check was added in version 3.1 in
accordance with the standard (and g++), but in these other modes it was
effectively a regression because those other compilers do not diagnose the
ambiguity in cases such as this.  [Patch sent out 3/19/03.]

2/10/03  Unspecified array size computed from extended designator

The front end sometimes incorrectly computed the size of an array with an
unspecified length when that array was initialized with an initializer
containing an extended designated initializer.  For example:

  int a[] = { [ 0 ... 1 ] = 42 };  // Used to set sizeof(a) = sizeof(int)

This is now fixed.  [Patch sent out 3/19/03.]

2/10/03  GNU mode: Diagnostic for unrecognized format function type

In GNU C and C++ mode, an error used to be issued when the "format" attribute
referred to an unknown format function type.  Now, only a warning is issued
and the attribute is ignored.  For example:

  int f(char const*, ...) __attribute__((format(diag_printf, 1, 2)));
    // Triggers warning about diag_printf not being known
    // (previously, this triggered an error).

2/7/03   Abort in correspondence processing

Under relatively obscure circumstances the front end could abort while
attempting to establish a cross-translation-unit correspondence between
two types have the same name but different parent classes.  This is now
fixed.  [Patch sent out 3/19/03.]

2/6/03   GNU C++ mode: Attributes on members not recorded in IL

In many cases, attributes specified on member functions and static data
members were not correctly recorded in the IL in GNU C++ mode.  This is
now fixed.  [Patch sent out 3/19/03.]

2/6/03   GNU C++ mode: asm name on class members

In GNU C++ mode, the front end now accepts the "asm name" construct on
member functions and on static data members.  For example:

  struct S {
    static void f() asm("S_f");  // Now accepted in GNU C++ mode
  };

[Patch sent out 3/19/03.]

2/6/03   assoc_template not set for predeclared template instance

When guiding declarations are enabled, the assoc_template field was not
set for a function that should be considered an instance of a template
when that instance is declared before the template is declared.  This
has been fixed.

  void f(const int&) { }
  template <class T> void f(const T&) {}

2/5/03   Microsoft compatibility: parsing errors caused by prescan
         problem with __declspec

The routines used to prescan declarations did not handle __declspec
properly.  This could result in disambiguation problems and/or spurious
errors on declarations of members of template classes.  Now fixed.
Note that this test case correctly results in an error about the invalid
use of dllimport.  [Patch sent out 3/19/03.]

  template <class T> struct X{ __declspec(dllimport) X(); };
  template <class T> __declspec(dllimport) X<T>::X() { }

2/5/03   GNU C mode: Initialization of array of structs of size zero

In GNU C, it is possible for a complete struct to have size zero.  The
front end used to issue a spurious error when attempting to initialize
such an array in GNU C mode.  For example:

  struct S {} s[] = { 1 };  // Now accepted in GNU C mode.

This is now fixed.

2/5/03   Microsoft compatibility: disambiguation

The MSVC++ 7.0 compiler fixes some disambiguation bugs that we emulated.
This emulation is now done only in Microsoft bugs mode when microsoft_version
is < 1300.  In this example, "i" should be a function declaration, but is
considered an object declaration when emulating the Microsoft bug.

  int main() {
    int i(int());
  }

2/5/03   Invalid form of name reference for moved inline members

When FRIEND_AND_MEMBER_DEFINITIONS_MAY_BE_MOVED_OUT_OF_CLASS and
RECORD_FORM_OF_NAME_REFERENCE are TRUE, the front end combined with
the C++-generating back end sometimes rendered the input

  struct S { void f() {} };

as:

  struct S { inline void f(); };
  void f() {}  // Missing qualifier!

I.e.,  it mistakenly omitted class qualifiers on definitions that were
moved outside the class.  This problem was caused by incorrectly
recording the form of name reference for the moved definition.
This is now fixed.  [Patch sent out 3/19/03.]

2/5/03   Microsoft compatibility: argument-dependent lookup

Argument-dependent lookup is enabled when microsoft_version is >= 1310 (i.e.,
for MSVC++ version 7.1 and above).

2/5/03   Deduction should fail if creating a void parameter type

An attempt to create a void parameter type as a result of template argument
substitution should cause deduction to fail.  Formerly, this resulted in
a "unexpected function type" error during template instantiation.
[Patch sent out 3/19/03.]

  template <class T> char f(T*, void (*)(typename T::value_type) = 0);
  struct X { typedef void value_type; };
  char x = f((X*)0);

2/4/03   GNU compatibility: "deprecated" and "used" attributes

In both GNU C and GNU C++ modes, the front end now supports the GNU
attributes "deprecated" and "used."  A warning is issued for uses of
an entity (variable, function, member function, field, or type) 
declared with the "deprecated" attributes.  A routine declared with
the "used" attribute is kept in the IL even when it is not used.

2/4/03   IL display build problem with IA-64 ABI and no IL lowering

The IL display program did not build correctly when using the IA-64
ABI without IL lowering.  This has been fixed.  [Patch sent out 3/19/03.]

2/3/03   GNU C++ mode: Exception specifications ignored when no support for
         C++ exception handling

When support for C++ exception handling is disabled, the front end normally
ignores exception specifications on function declarations that aren't
definitions, but exception specifications on function definitions are
usually diagnosed as errors.  In GNU C++ mode, even the latter are now
ignored.

2/3/03   GNU C mode: Old-style vararg parameter declarations

GNU C allows old-style parameter lists to be followed by an ellipsis to
indicate that the function accepts variable length argument lists.  For
example:

  void f(x) int x; ... {}

This GNU extension is now emulated in our front end.

2/3/03   GNU C++ mode: disambiguation problem with __null

As a result of a disambiguation problem, a spurious error was issued
on declarations such as this one.  This has been fixed.
[Patch sent out 3/19/03.]

  extern int f(int, void (*fp)(int) = (void (*)(int)) __null);

2/1/03   Abort in src_seq.c in C mode

An abort in src_seq.c (in src_seq_check_for_non_autonomous_tag) has
been corrected.  This could come up in some versions that use source
sequence entries (e.g., C++-generating back end versions), with
an attempt to declare a nested class in C mode.  [Patch sent out
3/19/03.]

  struct named1 {
    int aa;
    int bb;
    struct named2 {
      int mm;
      int nn;
    }; 
  } var_named;

1/30/03  Abort on __INTADDR__ of reference eliminated

Use of a field selection for a field of a reference type inside
the __INTADDR__ operator (an EDG extension intended to be used to
implement the offsetof macro) caused an abort
("extract_constant_from_operand: bad operand kind").  Now fixed.

  struct A {
    int& x;
  };
  int main() {
    int i = ((unsigned int)__INTADDR__(&(((A *)0)->x)));
  }

1/29/03  IA-64 ABI: performance with complex class hierarchies

The performance on examples with very large complex inheritance
hierarchies has been improved when using IL lowering.
[Patch sent out 3/19/03.]

1/29/03  IA-64 ABI: extra unneeded thunks

In the IA-64 ABI, extra unneeded thunks were sometimes generated
for virtual destructors.  This caused no problem, other than
possibly code bloat, but the thunks (for the internal and
subobject versions of the destructor) were unnecessary and never
called.

1/29/03  Compilation problem with GENERATE_EH_TABLES set to FALSE

lower_eh.c did not compile correctly when GENERATE_EH_TABLES is
set to FALSE.  Now fixed.  [Patch sent out 3/19/03.]

1/27/03  Partial ordering and template template parameters

Use of certain function templates that use template template parameters
resulted in spurious ambiguity errors when one template should have been
preferred based on the partial ordering rules.  This has been fixed.
[Patch sent out 3/19/03.]

  template<template<class> class TTP, class T> int f(TTP<int>, T) {
    return 1;
  }
  template<template<class> class TTP> int f(TTP<int>, int) {
    return 2;
  }
  template<class T> struct A { };
  int main() {
    f(A<int>(),1); 
  } 

-------------------------------------------------------------------------------
Version 3.1, January 26, 2003

1/23/03  IL version number changed to 3.1

1/22/03  Implementation of IA-64 ABI

The front end has until now supported only a runtime model that
is an enhanced version of the one provided by Cfront.  The runtime
model, or ABI, dictates class layout, virtual function table
and pointer to member layout, name mangling, etc.

Now, we have added support for the IA-64 ABI (see
www.codesourcery.com/cxx-abi/).  This is the ABI designed for
IA-64 (a.k.a. Itanium), but it is a nice modern ABI and is being
used on many other architectures as well.  In particular,
g++ uses the IA-64 ABI as its default ABI when no other native
ABI is dominant.

The new ABI is enabled by setting IA64_ABI to TRUE (and not setting

  CFRONT_OBJECT_CODE_COMPATIBILITY,
  CFRONT_2_1_OBJECT_CODE_COMPATIBILITY, or
  CFRONT_3_0_OBJECT_CODE_COMPATIBILITY

to TRUE).  It requires an object format and linker that supports
COMDAT sections, i.e., multiple identical definitions of routines
and variables, from which the linker retains only one instance.

The usual implementation of the IA-64 ABI (e.g., in g++) uses
an instantiation model without a prelinker.  All templates are
instantiated wherever they are used, and the linker throws
away duplicates.  We support this mode, when
INSTANTIATE_TEMPLATES_EVERYWHERE_USED is TRUE, but our default
is to use the prelinker, because we think that that produces better
results.  In particular, note that exported templates and the
one-instantiation-per-object mode require the use of the prelinker.

The prelinker mode that does not use .ti files is not supported
for the IA-64 ABI.

The C-generating back end does work with the IA-64 ABI except
that it isn't capable of dealing with fields allocated in the
tail padding of base classes (see TARG_REUSE_TAIL_PADDING).
Therefore a C-generating version is not 100% compatible with
the ABI spec.

Similarly, the fully-lowered and partially-lowered implementations
of exception handling work with the IA-64 ABI, but they do not
conform to the ABI spec.  Therefore if you wish to be 100%
conformant to the spec you must either write your own implementation
of EH or disable EH.

The pointer-to-member-function representation mandated by the ABI
spec can be implemented only on architectures in which the
low-order bit of the address of a function is always zero.
On architectures where that is not true, e.g., ARM, you should
set IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR to TRUE
to use an alternate representation.  (That representation matches
what g++ uses on ARM.)

The name demangler has been updated to support the IA-64 ABI
form of name mangling, and it addition it can be compiled into
the runtime library to provide a user-callable demangler
(via the ABI-mandated __cxa_demangle interface).

The runtime library now contains versions of some ABI-mandated
routines, which can be excluded if they are already present
in system libraries.  See the macros in config.h.

g++ 3.2 implements the IA-64 ABI, but it has a considerable number
of bugs.  We have added code to do a fairly thorough emulation of
those bugs, which is enabled by DEFAULT_EMULATE_GNU_ABI_BUGS.
We believe that by default g++ 3.3 will continue to have these
bugs except when invoked with -fabi-version=0, so the emulation
may be necessary for some time on some platforms.

1/22/03  Overload resolution, nonstatic member function and no selector

In accordance with core issue 364, overload resolution now does not
disqualify a nonstatic member function if no implicit selector
object can be created.  If the function is chosen as the best
function, an error is issued because it is not callable.

  struct S {
    static void f (int);
    void f (char);
  };
  void g () {
    S::f ('a');  // Now gets error.  Formerly, f(int) was chosen.
  }

1/22/03  Placement array delete on exception handles array prefix

The code generated to do a delete on exception for a placement
array new now adjusts the address passed to the placement array
delete routine to account for the array prefix, if one is
used.  Without this change, the pointer passed to the "delete"
routine was not the same as the one returned by the "new"
routine.

1/22/03  Microsoft compatibility: lvalue cast of float to same-sized type

In Microsoft C mode, the front end now accepts an lvalue cast of
a floating-point value to another type with the same size and
alignment.

1/20/03  Abort on invalid wide-string initializer in GNU C mode

Attempting to initialize an array of the wrong type with a wide string
literal could trigger an internal error in GNU C mode.  For example:

  int a[] = L"x";  // Used to abort in GNU C mode; now an error.

This is now fixed.

1/20/03  EH destruction of base class subobjects, with construction vtables

When base class subobjects are constructed or destroyed in objects
that have virtual function in base classes, it is sometimes necessary
to use special versions of virtual function tables during the subobject
construction and destruction (see Changes entry of 4/25/98).
This mechanism has not worked correctly when the destruction
call is done from the runtime as a result of a thrown exception
(there was no way for the runtime to know that a special virtual
function table was needed, let alone which one).  Now, a new
RDF_SUBOBJECT_VTABLE flags has been added in the set of flags in
the EH region table entry, and the front end and runtime have
been changed to specify and pass the appropriate pointer.
This is an ABI CHANGE, but an upward-compatible one.
(Note in particular the way that RDF_SUBOBJECT_VTABLE is
overlaid on the existing RDF_LET_THIS bit, to avoid increasing the
size of the flags byte.)

1/20/03  Precompiled headers: workaround for mmap problem on Linux

When using MAP_FIXED on Linux, mmap will succeed if a request is made to
map the same block more than once.  This can result in aborts or other
incorrect behavior when using precompiled header files.  The routine
map_input_file_to_region has been modified to work around this problem
when the front end is built with __linux__ defined.

1/20/03  Precompiled headers: abort caused by include guard processing

An abort would occur when using a precompiled header file associated with
a primary source file in which the initial sequence of preprocessing
directives preceding the #include that terminates the precompiled header
prefix looks like include file guard code.  This has been fixed.

  #ifndef __FLAG__
  # define __FLAG__ 1
  #endif
  #include "t.h"

1/18/03  Argument-dependent lookup and template template arguments

Argument-dependent lookup failed to consider the namespaces associated with
template template arguments, resulting in incorrect lookups in certain
cases.  This has been fixed.

  namespace M {
    template<template<class> class T> class A;
  }
  namespace N {
    template <class T> struct Y {};
    void f(M::A<Y> * A);
  }
  int main() {
    M::A<N::Y> *a;
    f(a);  // should find N::f
  }

1/17/03  Precompiled headers: internal error if memory cannot be mapped

Before a precompiled header is loaded, the front end attempts to map the
memory required to use the PCH file.  Later, when the PCH file is being read,
if the memory can no longer be mapped, the front end issues a catastrophic
error.  A bug caused an internal error to result from the attempt to
issue the error.  This has been fixed.

1/16/03  Incorrect handling of cv-qualified reference template parameter

A cv-qualifier should be ignored when applied to a reference type.
This was done in most cases, but when applied to a template parameter
of reference type an invalid type with a cv-qualifier on top of a
reference was created.  This could result in incorrect behavior,
particularly when the type is used for template argument deduction.
This has been fixed.

  extern "C" int printf(const char *, ...);
  template <class T> struct A { static const int value = 0; };
  template <class T> struct A<const T> { static const int value = 1; };
  template <class T> struct A<T&> { static const int value = 2; };
  struct B {};
  template <class T> struct C { typedef const T CT; };
  int main() {
    typedef C<B&>::CT CT;
    printf("%d\n", A<CT>::value);  // should print 2, but used to print 1
  }

1/15/03  Bad code generated for covariant return thunk, cv-qualifiers

In some cases where the return type of a covariant virtual function
is cv-qualified at the top level (unusual), the IL generated by
IL lowering was incorrect with regard to cv-qualifiers.  Also, the
C-generating back end generated code that could attempt to assign
into a const variable.

  struct S {
    virtual S* const f ();
  };
  struct T : virtual public S {
    virtual T* const f ();
  };
  T* const T::f () {
    return 0;
  }

1/15/03  Bug in covariant return adjustment with dominance

The overriding functions list was not built correctly when an
entry that doesn't have covariance on the return type is dominated
by an entry that does -- the return adjustment base class
was not set, and as a consequence incorrect code would be
generated that did not adjust the return type.  Now fixed.

1/15/03  "||" or "&&" expression with dependent second operand should
         be considered dependent

A "||" or "&&" expression where the second operand is not evaluated
because the first determines the result can still be value-dependent
according to the standard if the second operand is value-dependent,
e.g., if it is a template parameter.  This can have an effect if
the expression is used in a call inside a template.  Now, such
an expression is considered dependent.  (There's some question about
whether this is what the standard should say, but it is clear.)

1/14/03  Partial specialization fails to match template template parameter

As a result of a bug in template argument deduction, partially specialized
classes would fail to match template template parameters in certain cases.
This has been fixed.

  template <class T1, class T2> struct A {};
  template <class T> struct A<T, T> {};
  template <class T> struct B {};
  template <template <class T1, class T2> class X, class T1, class T2>
  struct B<X<T1, T2> > {
    typedef int type;
  };
  A<int, int> a;  // next line fails if this declaration is present
  B<A<int,int> >::type b;

1/9/03   address_taken flag on use of static member function with
         selector

The address_taken flag is now correctly set in the routine entry
for a static member function whose address is taken by way of a
reference that includes a selector object (which is evaluated but
then thrown away).

  struct A {
    static void f1() { }
  };
  int main() {
    A a;
    void (*fptr)() = &a.f1;  // address_taken in f1 now set
  }

1/8/03   IL field "unused" changed to "has_gnu_unused_attribute"

When GNU_EXTENSIONS_ALLOWED is TRUE, a_routine and a_variable entries
have a flag indicating that the GNU "unused" attribute was applied to
the entry.  This flag used to be spelled "unused," but that was causing
confusion.  It is now called "has_gnu_unused_attribute" instead.

1/8/03   Missing instantiations of exported templates when
         AUTOMATIC_TEMPLATE_INSTANTIATION is FALSE

In general, use of exported templates requires that
AUTOMATIC_TEMPLATE_INSTANTIATION be TRUE.  However, if all of the
source files that involve exported templates are provided as multiple
translation units in a single invocation of the front end, it should
be possible to generate the required instantiations.  Formerly, this was
not the case, but the front end now supports this usage of exported
templates.

1/7/03   MSVC++ 7.x compatibility: non-default operator delete[] ignored,
         non-array operator delete used instead

MSVC++ 7.0 has a new slightly different behavior for ignoring
inappropriate operator delete[] functions when processing a
delete[] operator, which is now emulated in Microsoft mode with
microsoft_version >= 1300.  If there are operator delete[]
routines visible, but none of those is a default operator
delete, they are ignored, and the non-array operator delete
is used instead.

  void operator delete[](void *, int);
  int main() {
    int *p = 0;
    delete [] p;  // Uses non-array operator delete
  }

1/6/03   String literals have same address in all copies of extern inline
         functions

IL lowering has been changed so that string literals in extern inline
functions are now made external, so that each copy of an extern inline
function will get the same copy of each such string literal (i.e.,
if you take the address of the string, it will be the same everywhere).
This is as required by the C++ standard.  This feature is controlled
by ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS, and note that the default
for the Cfront-like ABI is FALSE, because the required technique for
sharing strings in that ABI is unreasonably expensive.

1/6/03   GNU compatibility: Abort on attribute syntax error

In GNU C mode, the front end used to abort on certain syntax errors in
attributes taking an argument.  For example:

  static int f() {}
  int g() __attribute__((alias "f"));  // Syntax error.  Used to abort.

This is now fixed.

1/2/03   GNU mode: Unrecognized registers in GNU extended asms

A configuration flag (ACCEPT_UNRECOGNIZED_GNU_ASM_OPERANDS) has been added
to indicate that unrecognized extended asm operands should be accepted.
This lets the front end process source files with asm directives intended
for an architecture for which specific asm support is not provided.

12/31/02 Microsoft compatibility: explicit instantiation without definition

The Microsoft compiler allows the explicit instantiation of an entity
for which there is no template definition.  This is now accepted in
Microsoft mode.  A warning is issued.

  template <class T> void f(T);
  template void f<int>(int);

12/31/02 Microsoft compatibility: defining a destructor using a typedef name

The Microsoft compiler allows a typedef name to be used when defining a
destructor.  This is now accepted in Microsoft bugs mode.

  class C { ~C(); };
  typedef C B;
  B::~B(){}

12/30/02 Microsoft compatibility: const string literals

String literals are const by default when microsoft_version is >= 1310
(MSVC++ 7.1 and above).

12/29/02 Position in cleanup statements generated at end of block or break

Any statements generated by IL lowering to destroy variables at the
end of a block or at a break statement are now labeled with the
appropriate source position, i.e., the closing "}" or the "break"
keyword.  Previously, they had the source position of the previous
statement.

12/27/02 C++-generating back end: Order of base class specifiers

In some cases involving virtual base classes that are inherited both
directly and indirectly, the generated C++ did not render the base class
specifiers in a correct order.  For example:

  struct V {};
  struct B: virtual V {};
  struct D: virtual B, virtual V {};

This is now fixed.

12/27/02 GNU mode: improved error position on invalid asm registers

The error position of an invalid register name in an asm register
name specification has been improved.

  register unsigned int x asm("29") ;

12/26/02 Spurious correspondence error on class template instances

When using multiple translation units, spurious correspondence errors
could be issued on certain class template instances.  This has been
fixed.

12/23/02 Multiple translation units, abort in trans_copy.c

An abort in trans_copy.c (line 1126 in the 3.0 source) has been
corrected.  It came up in C mode with multiple translation units,
where the declaration of a function is unprototyped in one
translation unit and prototyped in another.

12/23/02 Microsoft compatibility: pointer minus void *

In Microsoft mode (C and C++), a pointer minus a void * is
now allowed.  A warning is issued.

  int  * ptr1;
  void * ptr2;
  void foo() {
    int x = ptr1 - ptr2;
  }

12/19/02 Nontype template arguments in dependent contexts

If a nontype template argument is used in a context in which the
associated parameter type is not known (e.g., in certain dependent
contexts as in the template argument list of B below) and that
template argument requires a conversion to be done when the associated
parameter type is eventually known, the conversion was not done in
certain cases.  In addition, if no conversion is possible, deduction
succeeded when it should have failed.  These problems could result in
spurious errors.  Now fixed.

  template <class T> struct A {
    template <int I> struct B { B(int); };
  };
  template <class T> void f(typename A<T>::template B<'c'>);
  int main() {
    f<int>(1);
  }

12/18/02 Incorrect handling of escapes in C99 _Pragma operator

Escapes in the string used to specify a C99 _Pragma were not handled
properly, resulting in spurious errors.  This has been fixed.

  _Pragma("some_pragma=\"abc\"")

12/18/02 Preprocessing pragmas in C99 _Pragma operators

The preprocessing pragmas recognized by the front end (hdrstop, no_pch,
and once) cannot be used in C99 _Pragma operators, but instead of
issuing a diagnostic they were either silently ignored or produced
incorrect behavior (use of hdrstop caused a loop).  A diagnostic
is now issued.

  _Pragma("hdrstop")
  int f() {return 1;}

12/16/02 Microsoft compatibility: conversions for "<" operator and MSVC++ 7.1

MSVC++ 7.1 fixed a bug we have been emulating, related to using
conversion functions to convert to a pointer type for an operand
of a "<", ">", <=", or ">=" operator.  With microsoft_version >= 1310,
we no longer emulate the bug.

12/16/02 Type of argument passed to __vec_cctor runtime routine for
         number of elements

The expression passed to the __vec_cctor runtime routine by code
generated by IL lowering had type int, whereas the parameter has
type size_t.  (The other similar runtime routines have a
number-of-elements parameter of type int, which was originally
dictated by compatibility with Cfront.)  The argument now
has type size_t.

12/16/02 gcc compatibility: void * argument passed to transparent union
         pointer

The transparent_union feature in gcc compatibility mode now allows
a void * argument to be passed to a pointer member of the union,
and a pointer argument to be passed to a void * member of the union.

12/16/02 C-mode inlining (C99, gcc) sometimes loops on recursive calls

In some cases, minimal inlining in C99 or gcc mode could loop while
trying to expand a recursive call.  The call had to be a full
statement at block level with a very simple argument list.
Now fixed.

  inline static void f(int i) {
    f(i);
  }
  void g() {
    f(1);
  }

12/14/02 Microsoft compatibility: do-nothing cast to array type allowed
         and ignored

In Microsoft bugs mode in C++, a do-nothing cast to an array type is
now allowed and ignored, as an old-style cast, functional-notation cast,
or static_cast.

  int a[100];
  (int[100])a;

12/14/02 C++-generating back end: "?" operator with equal-length strings

The C++-generating back end rendered a "?" with equal-length
string literals as the second and third operand (which is an lvalue)
slightly strangely.  For the input

  char *p = (char *)(i ? "ab" : "cd");

The output produced was

  auto char *p = ((char *)(&((i) ? "ab" : "cd"))); return 0; 

which is correct, but ran into bugs in the Sun CC and HP aCC
compilers.  The IL for such cases has now been changed to produce
output that more closely matches the input.

As part of this change, the C++-generating back has been
changed to always output the cast that implements the implicit
deprecated conversion from a string literal to "char *", which
makes examples like the above less sensitive to how the
target C++ compiler implements that conversion and any
extensions of it.

12/14/02 C++-generating back end: inaccessible typedefs in generated code

When the C++-generating back end generates template arguments
in template references, in a configuration in which template
instances are put out in the generated code as specializations,
there are cases where the generated code contained access
errors.  This is not a problem that can be solved in general,
because within such a specialization entities that could be
referenced via the template parameter in the original code
must be referenced directly, and that underlying type
may not be accessible in the template.  We have, however,
checked in a workaround that strips off member typedefs
if the underlying type is not a class member, which avoids
some of the most common problem cases.

12/13/02 Missing inline function, multiple translation units

In some convoluted cases involving multiple translation units,
a configuration with LOWER_EXTERN_INLINE set to TRUE and
removal of unneeded entities enabled, and an extern inline function
defined but not referenced in one secondary translation unit and then
defined and referenced in a later secondary translation unit, the
body of the function was incorrectly eliminated with the consequence
that the function ended up as an unresolved external at link time.
Now fixed.

12/12/02 GNU C++ mode: Visibility of variable with parenthesized initializer

In GNU C++ mode, a variable declaration is now invisible in its own
parenthesized initializer.  (See also Changes entry of 7/27/01 for the
identical behavior in Microsoft bugs mode.)

12/12/02 GNU C mode: Vacuous member declarations allowed

The following code is now accepted in GNU C mode:

  struct S {
    ;  // Previously only accepted in C++ modes.
  };

12/11/02 GNU C mode: Abort on function with transparent union parameter

In GNU C mode, the front end sometimes aborted with an internal error if
a function taking a parameter of transparent union type was redeclared
with an unknown type.  For example:

  typedef union {} U __attribute__((transparent_union));
  void f(int, U);
  void f(int, X);  // Abort on invalid (unknown) type X.

This is now fixed (an error is still issued, but the front end no longer
aborts).

12/10/02 C++-generating back end, Microsoft compatibility:
         Qualified member names

Microsoft MSVC++ 6.0 (and earlier) cannot parse expressions of the form
this->X::Y::f() if X is not a direct base or a member of the type of *this.
The C++-generating back end was therefore modified to avoid generating such
expressions when msvc_is_generated_code_target is TRUE and
microsoft_target_version_number is less than or equal to 1200.  For example:

  struct A { struct AN { virtual void f(); }; };
  struct B {
    struct BN: A::AN {
      virtual void f() {
        AN::f();  // Used to always be rendered as "this->A::AN::f();".
      }           // For Microsoft targets we now generate "this->AN::f();".
    };
  };

12/10/02 Ambiguous virtual function overrider not diagnosed

In some cases involving virtual functions declared in virtual base classes,
the front end failed to issue a required diagnostic for ambiguously
overridden virtual functions.  For example:

  struct A { virtual void f() {} };
  struct B: virtual A { virtual void f() {} };
  struct C: B {};
  struct D: B, C {};  // Front end failed to diagnose that A::f is not
                      // uniquely overridden.

This is now fixed.

12/10/02 Access set incorrectly for non-member class prototype instantiations

The access field in the source correspondence entry of non-member class
prototype instantiations was incorrectly set to as_inaccessible when it
should have been as_public.  This has been fixed.

12/9/02  GNU compatibility: Line directives output by GNU cpp

The line directives generated by the GNU preprocessor have an optional
set of flags at the end of the line.  Previously, the front end supported
only a single flag.  We now accept (and ignore) an arbitrary number of
flag values.

12/9/02  GNU compatibility: Token pasting operator with variadic macros

When extended variadic macros are enabled (the default in GNU C and C++ mode),
the token pasting operator has a special effect when it is followed by an
empty variadic macro argument.  Previously, this effect amounted to deleting
the sequence of whitespace (if any) immediately preceding the macro argument,
after which the preceding continuous sequence of non-whitespace was also
removed (this is the behavior implemented by GNU C/C++ 2.x compilers).
Now, we emulate the behavior of GNU C/C++ 3.x compilers: Only a comma
(possibly followed by some whitespace) is deleted.  For example:

  #define M(X, Y...) int x, ##Y
  M(1);  // Should expand to "int x;".  Previously, it resulted in "int ;"

Previously, in the example above, the complete sequence "x," was deleted.
Now only the comma is elided, and the "x" remains (making this valid C code).

12/8/02  Virtual function tables generated by lowering are now const

The virtual function tables generated by IL lowering are now const,
which makes it easier to put them into read-only storage.  Likewise
typeinfo entries and pointer-to-member-function constants.

12/8/02  Abort in r_mangled_parent_qualifier

In certain cases name mangling would abort with an assertion failure
("parent class has no body") in r_mangled_parent_qualifier.
These aborts involved cases where a class was not needed in the
IL except for a use in generating a parent class in a mangled
type name.  The class was removed and then mangling tried to
reference the deleted class.  Now fixed.

  class _86 {
    public:void _87() {
      class _88 {
        public:class _89 {
          public:void _90() {
          };
        };
      };
    };
  };

This fix exposed another problem, an ordering issue in demangling,
which was fixed by largely removing the final type name mangling
and mangling type names fully at the start of lowering.

12/6/02  More local statics than necessary externalized

When exported templates are used, some static functions are
"externalized", i.e., made external so they can be referenced
from other translation units.  The local statics of such functions
were made external also, but that isn't in general necessary
(there is only one copy of the function).  The variables are no
longer made external.

12/3/02  Microsoft compatibility: duplicate inline function list entry

If INSTANTIATE_EXTERN_INLINE is used, a class given external linkage
though a typedef declaration could result in a duplicate inline
function list entry being created when compiled in Microsoft mode.
Note that the class must be initially unnamed for the problem to occur.
This is now fixed.

  typedef struct {
    void f() { }
  } S;

12/3/02  GNU C compatibility: Implicitly declared exit() function

In GNU C mode, implicitly declaring the exit() function (by calling it)
makes it visible in the file scope.  The following complete program is
therefore accepted:

  int main() { exit(0); }
  void (*pf)(int) = (void(*)(int))exit;  // Accepted in GNU C mode, but not
                                         // in strict ANSI C mode.

12/2/02  GNU compatibility: Attributes in parenthesized declarators

In GNU mode, the front end now accepts attributes as the first component of
a parenthesized member declarator.  For example:

  struct S {
    void (__attribute__((stdcall)) *pf)();
  };

12/1/02  Microsoft property fields, reference types

Microsoft property fields did not work quite right when the "get"
function returns a reference type.  The result of a reference to
the field should be an lvalue in that case, and now it is.

Also, a declaration of a property field with a reference type
caused a spurious warning about the class having no constructor
to initialize the reference field.  That warning is no longer
issued.

12/1/02  End position on some function expressions

The end positions (maintained when EXTRA_SOURCE_POSITIONS_IN_IL is
TRUE, which is not the default) on some expression nodes relating
to static functions called with an unnecessary object were sometimes
not set (they remained [0,0]).  They are now set.

  struct A {
    static void f();
    void f(float);
  };
  A g();
  int main() {
    g().f();
  }

11/27/02 Spurious error on return statement in Microsoft mode templates

In Microsoft C++ mode with prototype instantiations of function templates
enabled (option --parse_templates), return statements of functions with
dependent return types elicited spurious errors.  For example:

  template<typename T> T f() {
    return 1;  // Used to trigger an error
  }            // (with --microsoft --parse_templates).

This is now fixed.

11/26/02 Small optimization in IL lowering of temp-initialization

The case of an indirection over a cast over an enk_temp_init, where
the cast only adjusts cv-qualifiers that will be dropped anyway
because the result is an rvalue in C, is now optimized in IL
lowering to avoid generation of an extra copy.

11/26/02 Support for instantiate-as-used template model

We've added some new configuration macros that make it easier to
implement a template instantiation model in which all templates
are instantiated in every compilation that uses them, and the
duplicates in the object files are removed at link time.  This
requires linker support and, when the C-generating back end
is used, C compiler support.  See

  LINKER_CAN_DISCARD_DUPLICATE_DEFINITIONS
  INSTANTIATE_TEMPLATES_EVERYWHERE_USED
  DEFAULT_INSTANTIATION_MODE

As part of this change, local static variables are promoted out
of functions and made external in more cases.  For template functions
instantiated wherever used, this is clearly necessary.  Less
obviously, it's necessary for all extern inline functions, even
when this new mode is not selected, and even when inline functions
are instantiated, because even though instantiation will guarantee
a single external definition, any given call of the function might
be expanded from the inline definition.  (This does not come up with
the EDG minimal inlining, because functions with inline statics are
not inlined, but it is possible when inlining is done in the back end).

11/26/02 IL write-read error on extern "C" redeclaration

In configurations with IL_SHOULD_BE_WRITTEN_TO_FILE set to TRUE, the front
end sometimes aborted with an IL write-read error if an extern "C" function
was declared in two different namespaces.  For example:

  namespace N { extern "C" void f(int x) {} }  // Used to trigger an
  extern "C" void f(int);                      // IL read-write error.

This is now fixed.  The fix also ensures that the type of the routine
definition has assoc_routine pointing to the associated routine entry.

11/25/02 Precision of output of long double constants, with 128-bit
         long doubles

When using 128-bit long double floating point (i.e., on Sun systems)
long double constants were emitted with one fewer digit than would
normally be used.  This was done to avoid a problem encountered when
the Sun C++ compiler is used to compile the generated code (the value emitted
for LDBL_MIN was rejected by the Sun compiler).  The workaround could
cause problems because of the reduced precision of the resulting values.
As a result the workaround is now used only with the C++ generating back end.
Of course, this means that precision problems could occur when using the
C++-generating back end, and the LDBL_MIN problem could occur when using
the C-generating back end, but this behavior was selected to provide the
best result for most users.  fp_to_string in float_pt.c can be modified
if different behavior is desired.

11/24/02 End position wrong on expression for "new"

The end position (maintained when EXTRA_SOURCE_POSITIONS_IN_IL is
TRUE) on a "new" expression for a class type was wrong when the
processing of the initializer arguments caused the instantiation
of a default argument expression.  Now fixed.

  template <class T> class C {
    public : C(int a, int b = 0) { }
  };
  int main () {
    C<int> *c;
    c = new C<int>(0); // End position on "new" expression was wrong
    return 0;
  }

11/24/02 Microsoft compatibility: overload resolution, reference-to-
         pointer parameter, pointer argument with different cv-qualifiers

In Microsoft bugs mode, overload resolution now allows a non-const
reference to a pointer type to bind to a pointer argument even when
the cv-qualifiers of the types pointed to do not match.  This
Microsoft extension was already accepted in reference binding,
but overload resolution was not aware of that relaxation.

  void a(int &a);
  void a(const char *&a);
  int main() {
    char* p = 0;
    a(p);   // Now accepted in Microsoft bugs mode.
  }

11/21/02 Spurious error of template friend declaration

A spurious error could result when a friend declaration referred to
a member template of a non-template class.  This has been fixed.

  struct B {
     template <class T> static void f(T*);
  };
  template<class T> struct A {
    template<class T1> friend void B::f(T1*);
  };

  A<int> a;

11/20/02 GNU compatibility: Typeof syntax ambiguities

In GNU mode, expression-vs-declaration ambiguities used to lead to syntax
errors for some uses of the GNU typeof operator.  For example:

  struct S { S(int); };
  S s(__typeof__(int)(42));  // The front end used to parse this as a function
                             // declaration.

This is now fixed.

11/20/02 GNU C++ compatibility: Type definitions allowed in cast expressions

In GNU C++ mode, the front end now allows type definitions in cast
expressions.  For example:

  void f(int *p) {
    (struct { int *p; }*)p;  // Accepted in GNU C++ mode; error in other
  }                          // C++ modes.

11/19/02 GNU C++ compatibility: template argument list following
         constructor name

g++ permits a template argument list to appear following a constructor name
in a constructor definition that appears outside of the class.  This is now
accepted in GNU C++ mode.

  template <class T> struct A {
    A();
  };
  template <class T> A<T>::A<T>(){}

11/19/02 GNU C++ compatibility: redeclaration of handler parameters

In GNU C++ mode, within a catch clause an entity may be declared with
the same name as the handler parameter.

  try {  }
  catch(int e) {
    char e;
  }

11/19/02 GNU C++ compatibility: incompatible template parameter accepted
         in the definition of a member of a class template

In g++ mode, the definition of a member of a class template that appears
outside of the class definition may declare a nontype template parameter
with a type that is different than the type used in the definition
of the class template.  A warning is issued.

  template <char s> struct B { void f(); };
  template <int i> void B<i>::f(){}


11/18/02 GNU C++ compatibility: Uninitialized non-const members

In GNU C++ compatibility mode, only a warning (instead of an error) is issued
when a constructor fails to initialize a const data member.  For example:

  struct S {
    S() {}  // Warning only, even though ic is left uninitialized.
    int const ic;
  };

11/15/02 GNU compatibility: Typo in name of built-in function

The IL definition file misspelled the name of the GNU built-in function
"__builtin_dwarf_cfa" as "__builtin_unwind_dwarf_cfa".  This is now fixed.

11/14/02 Configuration option DEFAULT_GCC_COMPATIBILITY renamed and extended

The new configuration option DEFAULT_GNU_COMPATIBILITY now controls whether
GNU extensions should be enabled by default both in C and C++ modes.  If the
(now obsolete) configuration option DEFAULT_GCC_COMPATIBILITY is defined,
DEFAULT_GNU_COMPATIBILITY is set to the same value.

11/12/02 Compiler-generated fields marked as such

A "compiler_generated" flag was added to field entries.  It is set for
fields that are not explicitly declared in the source (e.g., __vptr fields,
anonymous union parent objects, ...).

11/11/02 Stricter diagnostics for void parameter types

The front end used to issue a warning when a function parameter list consists
solely of a typedef alias for void.  Now a discretionary error is issued in
strict mode, and a warning otherwise.

  typedef void V;
  void f(V);  // Error in strict mode; warning otherwise.

11/11/02 Cv-qualifiers on function types

The C++ standardization committee has clarified (as a resolution to Core
Issue 295) that cv-qualifiers on function types are simply ignored when
they are added through typedef declarations or through template parameter
substitutions.  Such cases are therefore no longer diagnosed as errors.

  typedef void F();
  F const *pf;  // OK, but "const" is ignored
  template<typename T> int f(T const*);
  int g = f<F>(0);  // OK: f<F> takes a parameter of type "void (*)()"

11/7/02  Block-extern declaration mismatch ignored in K&R/pcc mode

In K&R/pcc mode, two block-extern declarations with the same name but in
different scopes can have a different type (and hence no diagnostic is
issued in case of a mismatch).  For example:

  void f1() {
    void g();
  }
  void f2() {
    int g();  /* No error (but warning) in pcc mode. */
  }

This was accepted in versions 2.40 and earlier of the front end, but
versions 2.41 through 3.0.1 diagnosed such cases as errors.  Now it is
again accepted, but with a warning.

11/7/02  Spurious error on using declaration of member of dependent base

Certain kinds of using-declarations naming members of dependent classes
were incorrectly flagged as errors.  Now fixed.

  template <class T>
  class X {
  public:
  typedef T *ptr;
  };
  template <class T>
  class Y : public X<T> {
    using X<T>::ptr;
  };
  template <class T>
  class Z : public Y<T> {
     using X<T>::ptr;  // Formerly got an error
  };

11/5/02  Incorrect EH cleanup state after local block containing array

A change in 3.0 (see 11/19/01 entry below) introduced a bug in
the determination of the exception handling cleanup state when
a block ends whose first variable is an array with a {...}
initializer.  This could cause incomplete destruction if there
were destructible variables preceding that block.  For example,
if T is a class with a destructor:

  void abc() {
    T var;
    {  
      T arr[1] = {other_var};
    }
    // Cleanup state here does not include destroying "var"
    throw 1;
  }  

11/5/02  GNU C++ compatibility: New expressions

In standard C++, when the type specified in a new expression starts with a
(left) parenthesis, the whole type must be enclosed in parentheses.  That
means that in "new (int)[2]" only "new (int)" is treated as a new expression,
and the trailing "[2]" should be parsed as a subscript operation.
However, GNU C++ compilers will attempt to parse a type past the closing
parenthesis (i.e., "new (int)[2]" is treated as "new (int[2])").  This
behavior is now emulated in GNU C++ mode.

11/5/02  GNU C compatibility: Local declaration can hide parameter

In GNU C mode (but not in GNU C++ mode) a local declaration can hide a
parameter of the same name.  A warning is issued in such cases.

  void f(int x) {
    int x;  // Warning in GNU C mode.  (Previously an error.)
  }

11/5/02  Diagnostics on missing return statements

In strict C++ mode and in non-Microsoft C99 mode, the front end used to issue
an error when a value-returning function did not terminate with a return
statement.  This diagnostic has now been weakened to a warning, and it is
not issued at all if the front end knows that the end of the function cannot
be reached.

  int f1() { }  // Triggers a warning, even in strict C++ or C99 modes
  int f2() {
    /*NOTREACHED*/   // A hint indicating this point is never reached
  }                  // inhibits the warning about a missing return.

[12/20/02] Also, the C-generating back end no longer puts out a 
"return;" for the implied return, to avoid getting a hard error if 
the target compiler is a C99 compiler.

11/4/02  GNU C++ compatibility: Predefined macro _GNU_SOURCE on Linux

In GNU C++ mode (but not in GNU C mode) the front end now predefines a
macro "_GNU_SOURCE" to expand to "1" on Linux configurations.
This macro guards GNU extensions in GNU operating system header files.

11/1/02  GNU compatibility: Use of __FUNCTION__ outside a function

In GNU C and C++ mode, the reserved identifiers __FUNCTION__ and
__PRETTY_FUNCTION__ now expand to the empty string literal ("")
when they appear outside of functions.  In GNU C++ mode, however,
the result is not considered for concatenation with other literals.

  char const *p1 = __FUNCTION__;    // Now accepted (previously an error).
  char const *p2 = ""__FUNCTION__;  // Now accepted in GNU C mode, but an
                                    // error in GNU C++ mode.

The second initialization in the example used to cause the front end to
abort in GNU C mode.  This is now fixed.

11/1/02  Abort on undefined nested class in unnamed class

The front end used to abort when processing a typedef of an unnamed class
containing an undefined nested class, such that the unnamed class acquires
the typedef name for linkage purposes.  For example:

  typedef struct {
    struct N;
  } S;

This is now fixed.

10/31/02 Incorrect end-of-specifiers position when defining classes

The end-of-specifier position recorded for a class definition (available
when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE) used to be set to the position
of the token following the closing brace.  This is now fixed: The position
of the closing brace is used if it is the last token of the specifier.

10/31/02 Microsoft __inline and __forceinline specifiers set is_inline flag

In Microsoft mode, the front end accepts the __inline and __forceinline
specifiers.  Until now, however, these specifiers did not cause the is_inline
flag of a routine entry to be set.  This has now been changed: Both the
is_inline flag and a bit in the decl_modifiers field are set when either of
these specifiers appear on a function declaration.

10/31/02 Uninitialized bit fields

Two bit fields in front end data structures were not initialized,
which could lead to incorrect behavior if they happened to come
out as 1/TRUE.  The fields are the "variadic" field in a_macro_def
and the "using_directives_apply" field in a_scope_stack_entry.

10/30/02 Performance improvement in looking up operator=

Because each class has an operator= function, the inactive list for
operator= can become very long.  class_qualified_id_lookup now uses
an alternate method of looking up operator=, resulting in a significant
performance improvement for programs that have a large number of classes.

10/30/02 Performance improvement in handling of type lists

Some changes were made to accelerate the routine move_to_end_of_types_list
in many cases.

10/29/02 Carriage return in error output

The source line displayed as part of a diagnostic message could include
a trailing carriage return if one was present on the original source
line.  This has been fixed.

10/27/02 Deduction problem with cv-qualified typedef

The template argument deduction/matching process could fail when a type
was specified using a cv-qualified typedef.  This has been fixed.

  template <typename T> void f(T const (&)()) {}
  typedef int volatile volatile_int;
  template void f<int volatile>(volatile_int const (&)());

10/21/02 Problem with GNU asm operand list IL entry "next" pointer

The "next" pointer in the IL an_asm_operand IL entry (used when GNU
extensions are enabled) was not properly handled in some cases.  One 
consequence is that in configurations that write an IL file lists of more 
than one operand did not work correctly.

10/17/02 GNU C++ compatibility: Field with array type of unspecified length

In GNU C++ mode (but not in GNU C mode) a field whose type is an array of
unspecified length is treated as a zero-length array.  As a consequence,
such a field is not restricted to appearing as the last field of its class
type.

  struct S {
    char a;
    int b[];  // Accepted in GNU C++ mode (and treated as "int b[0];").
    char c;
  };

10/17/02 Expression copy of throw for inlining, not full EH lowering

The routine that copies expression trees did not copy one of the
fields of the supplement for an enk_throw in the
!DO_FULL_PORTABLE_EH_LOWERING mode.  The expr field is now copied.

10/17/02 GNU compatibility mode: Undefined inline functions

In GNU C and C++ modes, the front end now issues a warning (instead of an
error) for extern inline functions that are referenced but not defined.
(The same behavior was already implemented in Microsoft mode, see the Changes
of 12/3/98.)

10/17/02 C++-generating back end, Microsoft compatibility: Out-of-class
         definitions of nested classes

The Microsoft MSVC++ 7.0 compiler has a bug that prevents it from correctly
parsing an out-of-class definition of a nested class that is a member of
a class template specialization, unless the name of the specialization is
itself preceded by a qualifier.  For example:

  template<typename T> struct S;
  template<> struct S<void> { struct N; };
  struct S<void>::N {};   // Triggers MSVC++ 7.0 error
  struct ::S<void>::N {}; // Accepted by MSVC++ 7.0

The C++-generating back end has been modified to emit the extra qualifier
when msvc_is_generated_code_target is TRUE and msvc_target_version_number
is at least 1300.  The macro MSVC_TARGET_VERSION (see entry of 5/23/02)
has been renamed MSVC_TARGET_VERSION_NUMBER (we had two similar
variables).

10/16/02 Microsoft compatibility: instantiating the type of a static data
         member

The Microsoft compiler instantiates a template class used as the type in
a static data member declaration even though the type need only be complete
when the static data member is defined outside of the class.  Whether or not
the class is instantiated can be important if the class declares friend
functions that are expected to be visible.  In Microsoft bugs mode we now
instantiate the type used in a static data member declaration.

  template <class T> struct A {
    friend void f(T);
  };
  struct B {
    static A<int> ai;
  };
  int main() {
    f(1);  // f visible in Microsoft bugs mode
  }

10/15/02 Incorrect mangled name for dependent operator name constants

If a pointer-to-member function that refers to a dependent operator name
is used in the signature of a function template, an incorrect mangled name
could be generated (containing the unmangled form of the operator).  This
has been fixed.

  struct B {
    int operator+(int) { return 0; }
  };
  template <int (B::*P)(int)> struct A {};
  template <class T> void f(A<&T::operator+> *) {}
  int main() {
    f<B>(0);
  }

10/14/02 Missing diagnostic on "T::template *"

No diagnostic was issued if the template keyword (used for disambiguation
purposes in a qualified name) was followed by the "*" of a pointer-to-member
operator.  This has been fixed.  Note that the example requires
--parse_templates for the diagnostic to be issued.

  template <class T> void f(T) {
    typedef void (*T::template *FP)(int);
  }

10/14/02 Cast of function template with explicit arguments

A reference to a function template with explicit template arguments
can often be used as if it were the name of a simple function.
This was often accepted, but not in a case like the following where
the cast has a different type than the implied function.  Now fixed.

  typedef void (*FP)(int *);
  template <class T> void doIt(T T_t) {}
  int main() {
    FP p = (FP)doIt<int>;  // Formerly got error (note int vs. int *)
  }

Some related issues with using nonstatic member function templates
in this way were also resolved.

10/10/02 Missing precompiled header memory mismatch message

When using --pch_verbose mode, messages for memory mismatches were not
displayed.  In addition, the memory mismatch message was not displayed
when using an explicitly specified PCH file if the DEBUG configuration
flag was FALSE.  These problems have been fixed.

10/10/02 Default maximum pack alignment increased in some configurations

For configurations where GNU_EXTENSIONS_ALLOWED is TRUE, the default value
of TARG_MAXIMUM_PACK_ALIGNMENT has been increased to 128 (previously it was
8 or 16).  GNU compilers normally accept values up to 2^31, but increasing
the maximum pack alignment of the EDG front end beyond 128 requires a change
in the configuration of TYPE_FOR_TARG_ALIGNMENT.

10/10/02 Spurious error on partial specialization with template
         template parameter

A spurious "type of partial specialization template parameter depends on
another template parameter" error could be issued on a partial specialization
that has a template template parameter.  This occurred only under very
unusual circumstances so there is no small example to illustrate the
problem.  Now fixed.

10/10/02  Typedef using operator name undiagnosed

The front end now diagnoses attempts to typedef an operator name in
namespace scope (it already issued an error when such typedefs appeared
in class scope).  For example:

  typedef void operator+();  // Now an error (previously accepted)

10/9/02  Spurious correspondence error

A spurious correspondence error was issued if a template class was specialized
in one translation unit and incomplete in another (and both translation
units were loaded either by export processing or in --multi_trans_unit
mode).  This has been fixed.

  file 1:
  template <class T> struct A;
  template <> struct A<int> {};

  file 2:
  template <class T> struct A;
  void f(A<int>*){}

10/9/02  Invalid IL for some friend class declarations in templates

The IL produced for some nondependent friend class declarations appearing in
class templates was sometimes invalid.  For example:

  template<typename T> struct S {
    friend class C;
  };

The IL entry for C was placed in the wrong scope.  This in turn could cause
the IL display utility to abort with an IL write-read error.  The problem is
now fixed.

10/9/02  Guiding declarations disabled in default mode

The ARM and early drafts of the C++ standard included feature known as
"guiding declarations" in which a normal (non-template) function declaration
would participate in overload resolution but a template that matches the
guiding declaration would actually be used to provide the definition of
the function.  Because this feature is nonstandard, and because it can
produce incorrect results for programs that expect the standard behavior,
guiding declarations are now disabled in default mode in our standard
configuration.  The old behavior can be obtained by setting the configuration
macro DEFAULT_GUIDING_DECLS_ALLOWED to TRUE or by using the --guiding_decls
command line option.

  template <class T> void f(T, T){}
  // The following is now treated as a normal function declaration, not
  // a guiding declaration.
  void f(int, int);
  int main() {
    f('c', 1);
  }

10/9/02  GNU compatibility: Extended asm operands can have class type

In GNU C and C++ modes, the front end used to require that operands have
a scalar type.  Now, class types are also accepted.

  void f() {
    struct S { int i; } *p;
    __asm__("xchgl %0, %1": "=r"(*p): "m"(*p));
                  // Used to trigger an error in GNU mode; now accepted.
  }

10/8/02  GNU compatibility: Attributes in parenthesized declarator

In GNU C and C++ mode, the front end now accepts a GNU-style attribute
specifier as the first element of a parenthesized declarator.  For example:

  typedef void (__attribute__((stdcall)) *WinCall)();

10/8/02  GNU compatibility: cc clobber ignored

In GNU C and C++ modes, the front end now ignores (with a warning) the use
of "cc" (condition codes) in an extended asm clobber list.  (The similar
"flags" register is not ignored.)

10/7/02  Dual alignments for built-in types

A new configuration macro TARG_DUAL_ALIGNMENTS_FOR_BUILTIN_TYPES causes the
front end to consider an alternative alignment for builtin types when a field
of such a type appears in a class type (including structs and unions).  These
alternative alignments are configured through macros of the form
TARG_<XYZ>_FIELD_ALIGNMENT (where <XYZ> can be SHORT, INT, LONG, LONG_LONG,
FLOAT, DOUBLE, and LONG_DOUBLE).  This allows the front end to emulate more
accurately the object layout behavior of some GNU compilers on Intel x86-based
platforms.

10/4/02  Spurious error on static member template friend declaration

A spurious error was issued if a friend declaration referred to an instance
of a static member function template.  This has been fixed.

  struct A {
    template <class T> static void f();
  };
  struct B {
    friend void A::f<int>();
  };

10/03/02 Internal error on function reference with explicit template arguments

An internal error (in explicit_arg_list_identifies_specialization)
could occur if a function template is called with an explicit argument
list in a context in which a destination function type is not
available (a feature added in version 3.0).  The error would occur if
the template was made visible by a using-directive or using-declaration.
Now fixed.

  namespace N {
    template <class T> void f(T);
  }
  int main() {
    using namespace N;
    f(&f<int>);
  }

10/1/02  Microsoft compatibility: abort when using --parse_templates
         and Microsoft version > 1200

An abort could occur using --parse_templates in Microsoft mode when
Microsoft version is greater than 1200.  The abort would occur if a
template function used an array new operation with a dependent type.
This has been fixed.

  template <class T> struct A {
    void f() { new T[5]; }
  };

9/27/02  Specializations first declared in an enclosing namespace

The standard requires that an explicit specialization be declared in
the namespace containing the template before it can be declared or defined
in an enclosing namespace.  We now issue a diagnostic in strict mode if
this rule is violated.

  namespace N {
    template <class T> void f(T);
  }
  template <> void N::f(int);  // error in strict mode

9/27/02  Default transformation of UPC affinity expression

An implicit array-to-pointer conversion now applies to UPC affinity expressions
of array type.  In addition, lvalue-to-rvalue conversions are performed if
the expression is a pointer to a shared entity.

9/27/02  Diagnostic on redeclaration of parameter in catch clause

In a function try block, the standard prohibits a catch handler variable
or a variable in the outer block of the catch clause from having the same
name as a parameter of the function.  A diagnostic is now issued for
such cases.

  void f(int i, int j)
  try { }
  catch (int i) {
    int j;
  }
 
9/26/02  Member function template with template args as pointer to member

When a reference to a member function template includes explicit
template arguments that select a specific instance of the template,
the reference can be preceded by "&" to make a pointer to member
of the specific instance.  That didn't work previously, but now
it does.

  struct Foo {
    template<class T> T square(T x) const { return x*x; }
    template<class T> T fold(T (Foo::*f)(T) const) const {
      return 0;
    }
  };
  int main() {
    Foo foo;
    foo.fold(&Foo::square<float>);  // Got error previously
 }

9/26/02  typeid of member function

The typeid operator applied to a member function now gets an
error in strict mode.  In default mode the reference to the
member function is turned into a pointer to member and the
typeid of that is returned.

  #include <typeinfo>
  struct foo { double f(int); };
  int main() {
    typeid(foo::f);
  }

9/26/02  Abort on "?" operator with class and throw as operands

An abort in conv_class_operand_to_object_pointer resulted from
a case where a "?" operator has a class value and a throw expression
as its second and third operands, and the overall expression is
used in a context where the address of the class rvalue is needed,
e.g., in calling a copy constructor.  Now fixed.

  struct Foo;
  struct Bar {
    Bar(const Bar&);
    Bar f(const Bar&);
    Foo* value;
  };
  struct Foo {
    virtual Bar g(const Bar&);
  };
  Bar Bar::f(const Bar& args) {
    return value != 0 ? value->g(args) : throw 1;
  }

9/26/02  Microsoft compatibility: missing access error in instantiation

In Microsoft mode, certain access errors were not diagnosed during
template instantiations.  This has been fixed.

  template<class T> void h(T* p) {p->g();} // should get access error
  template<class T> class A {
  public:
     void f() {h(this);}
  private:
     void g()    {;}
  };
  int main() {
     A<int> a;
     a.f();
  }

9/25/02  Incomplete lowering of pointers to members

In cases where an aggregate containing a pointer to member is
initialized with an initializer that is partly constant but
contains an expression for the pointer to member term, the
lowered IL still contained a pointer to member type.  Now fixed.

  struct TF { int a; void (TF::*pmf)(); };
  void (TF::*gf())();
  void f() { TF t = { 0, gf() }; }

9/25/02  Microsoft C++ compatibility: 0(x) treated as call, ignored

In Microsoft C++ mode, a call expression where the "function" is a
constant zero is now accepted and ignored.  This is used in some
Microsoft code for conditional compilation, e.g.,

  TRACE("abc");

where TRACE is defined as either a function to be called or as 0
when no trace output is wanted.

9/24/02  Typedefs and elaborated type specifiers

The lookup rules for names used in elaborated type specifiers are different
in C and C++ (a change introduced in C++ by the standardization process).
In C++ the lookup finds typedef names (resulting in an error) while in C
the lookup ignores typedef names.  We now implement the new rules in C++
mode.

  class A {};
  typedef A TA;
  void f() {
    // Old behavior: new declaration of local class TA
    // New behavior: error - typedef in elaborated type specifier
    class TA* p;
  }

9/24/02  GNU compatibility: Nonstandard anonymous unions

When ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE, the front end now allows
nonstandard anonymous unions in GNU C and C++ modes.

9/24/02  Cleaner output of floating-point values

Floating-point values in generated C code (and, in some configurations,
in template arguments in diagnostics) are now output in simple
floating-point form, e.g., 1.5, instead of always in scientific
notation, e.g., 1.500000000e+00.

9/24/02  Signedness of bool bit fields

By default, the underlying type representation of "bool" is (plain) "char".
When plain chars are signed, this used to cause 1-bit bool bit fields to be
fairly useless and a warning was issued.  For example:

  struct S {
    bool b: 1;  // If treated as a signed quantity, this cannot represent
  };            // both "0" and "1".

Now, such situations are recognized and the field is forced to be unsigned
("bit_field_is_signed" is set to FALSE in the field's IL entry).

9/23/02  Visibility of "using operator="

The front end used to ignore (with a warning) a using-declaration referring
to an implicitly declared copy assignment operator from a base class.
Now, such a using-declaration can make the inherited operator visible along
with the copy assignment operator of the derived class.  For example:

  struct B {};  // Implicit operator=(B const&).
  struct D: B {
    using B::operator=;  // Used to be ignored, but no longer.
  };
  int main() {
    B b; D d;
    d = b;  // Calls B::operator=(B const&).
  }

9/23/02  Overload resolution, conversion function returning reference
         to derived class

When overload resolution resolves a copy-initialization by choosing
a conversion function returning a reference to a derived class of the
type of the entity being initialized, the search for a copy constructor
looked for a copy constructor of the derived class instead of one
for the base class.  As a consequence, there could be a spurious
error (copy constructor not found), or the derived constructor
could be called to copy into a base object, which could overwrite
surrounding storage at runtime.  Now fixed.

  class V {
  public:
        int i;
        V() : i(1) { }
        V(volatile V& v) { i = v.i; }
  };
  class Vd : public V {
  public:
        Vd() : V() { }
//      Vd(volatile Vd& vd) : V(vd) { }
  } t;
  class C {
  public:
        operator volatile Vd& () { return t; }
  } c;
  int test(void)
  {
        V v = c;  // Got spurious error
        return v.i == 1;
  }


9/23/02  Predefined macros recorded in IL

When RECORD_MACROS_IN_IL is TRUE, the front end now also records predefined
macros (such as __DATE__) in the IL.  A new field "is_predefined" has been
added to type "a_macro" to distinguish such entries (this is used by the
C++-generating back end, which does not render these macros).

9/18/02  Microsoft compatibility: "thread" specifier requires variable with
         static storage duration

In Microsoft mode, the front end accepted the __declspec(thread) specifier
on all variable declarations.  Now an error is issued if a variable with
that specifier does not have static storage duration.

  __declspec(thread) int g;  // OK
  void f() {
    __declspec(thread) int a;  // Error: Specifier doesn't apply to
  }                            // automatic variable.

9/18/02  Internal error on overloaded unusable conversion operators

An internal error would occur if a class template contained overloaded
conversion operators that convert to a base class (and are therefore
unusable).  This has been fixed.

  class N {};
  template <class T> class A: public N {
    operator N() volatile;
    operator N() volatile const;
  };
  A<int> ai;

9/18/02  GNU C++: Spurious errors on accesses to partial specializations

An early (unreleased) version of the GNU C++ compatibility changes contained 
a bug that caused the front end to issue spurious errors when accessing the
members of certain partial specializations.  This is now fixed.

9/18/02  Spurious access error on overloaded function in explicit instantiation

Explicit instantiation directives are permitted to make use of inaccessible
entities.  A spurious access error was issued when an inaccessible overloaded
function was used in an explicit instantiation directive.  This has been fixed.

  class C {
    static int g ();
    static int g (int);
  };
  template <int I> void f(){}
  template void f<sizeof (C::g ())>();

9/17/02  Cleanup state on branch back to label inside "if" statement

The cleanup state in the IL (used to generate destructions on
exceptions and on transfers like gotos and returns) was incorrectly
computed when a label appears inside an "if" statement and there
is a "goto" to that label from later in the block surrounding
the "if".  This caused at least a missed destruction, and possibly
confusion in back ends.

  struct C {
    C();
    ~C();
  };
  void foo(int i) {
    if (i)
      label1: return;
    C c;
    goto label1;  // Formerly failed to destroy c
  }

9/17/02  GNU C++ compatibility: Calling convention differences ignored

In GNU C++ mode, the front end now accepts typedef redeclarations that include
different calling conventions.  The calling convention of the first declaration
is retained in the IL.  For example:

  typedef void F();
  extern "C" {
    typedef void F();  // Accepted in GNU C++ mode; error otherwise.
  }

g++ seems never to save extern "C" indications on function types,
and therefore it never notes incompatibilities.

9/16/02  Spurious error on injected class name in elaborated type

A spurious error was issued if an elaborated type specifier referred
to an injected class name.  This has been fixed.

  struct A {};
  struct A::A a;

9/16/02  Operator overloading, conversion function returning reference
         to const enum

In cases where a conversion function returns a reference to a const
enum, operator overloading processing could sometimes give a spurious
ambiguity, considering the enum and const enum solutions different
solutions, whereas -- because the returned value is used as an rvalue --
only the cv-unqualified version should be considered.  Now fixed.

  enum primary {red, green, blue };
  struct port {
    operator const primary&( ) { return value; }
    primary value;
  };
  primary func () {
    port    pp;
    primary tint = red;
    if (red == pp) {  // Formerly got ambiguity
      tint = green;
    }
    return tint;
  }

9/16/02  GNU compatibility: Flexible array member constraints

In GNU C and C++ mode, the front end requires that a flexible array member
be the last field of a class type (see Changes entry of 6/14/02).  However,
A field of such a class type can now be followed by other fields.
For example:

  struct F {
    int n;
    int a[];  // Flexible array member
  };
  struct X {
    struct F f;  // Now accepted in GNU modes (previously an error).
    int x;
  };

9/16/02  Some constants not folded in array bound expressions, with VLAs

When variable-length arrays (VLAs) are enabled (e.g., in C99 mode and
gcc mode), in certain cases complex array bound expressions were not
folded to constants.  It most cases this was merely inefficient (an array
that is not a VLA was treated as one), but in array bounds for
local static variables this caused a spurious error.  Now fixed.

  struct s {
    int a;
    double bl;
  };
  int main() {
    static char carr[((size_t) &((struct s *)0)->bl)];
    return 0;
  }

9/13/02  Missing error on invalid template default argument

The front end failed to issue a diagnostic when a template default argument
was supplied in the out-of-class definition of a member class template.
This resulted in a surprising "too few template arguments" diagnostic when
the template was referenced in a way that would require use of the
default argument.  This has been fixed.

  template <class T> struct A {
    template <class T2> struct B;
  };
  template <class T> template <class T2 = int> struct A<T>::B { };  // invalid
  A<int>::B<> ab;

9/12/02  Sun compatibility: template parameters visible in specializations

The Sun compiler incorrectly makes template parameters visible within
specializations of class templates and specializations of members of
class templates.  We now emulate this in Sun mode.

  template <class T> struct A {
    void f();
  };
  template <> struct A<int> {
    T t;  // T should not be visible here
  };
  template <> void A<char>::f() {
    T t;  // T should not be visible here
  }

9/12/02  GNU C++ Compatibility: elimination of previous dependent lookup
         facility

In version 3.0, the variable force_dependent_name_rules_for_base_class_lookup
was added to let customers turn on just part of the dependent name processing
code to emulate the behavior of g++.  Upon further investigation, the lookup
done by g++ is more complicated than simply ignoring dependent base classes.
We now implement more complete emulation of the g++ lookup in g++ mode and as
a result, have eliminated force_dependent_name_rules_for_base_class_lookup.

9/11/02  Microsoft compatibility: spurious warning on overloaded template

In Microsoft bugs mode, a spurious "incompatible template parameter
declaration" warning could be issued on the declaration of an overloaded
function template.  This has been fixed.

  template<class T, int i> void f();
  template<int i, unsigned int ui> void f();

9/11/02  Microsoft compatibility: explicit instantiation of specialized class

In Microsoft bugs mode, an explicit instantiation of a specialized class is
accepted.

  template <class T> struct A {};
  template <> struct A<int> {};
  template struct A<int>;

9/11/02  GNU C compatibility: Extraneous long specifiers

In GNU C mode (but not in GNU C++ mode) the front end now ignores extraneous
"long" specifiers in typedef declarations (with a warning).  For example:

  typedef long long long LL; // Same as "typedef long long LL;"

9/11/02  Microsoft compatibility: Declaration in for-initializer can be
         hidden by declaration in surrounding scope

Microsoft Visual C++ version 7 allows a variable to be declared in a scope
that already contains a for-initializer variable with the same name.  The
earlier declaration is then hidden.  For example:

  int main() {
    for (int k = 0; k<10; ++k);  // Declaration #1
    int k = 1;                   // Declaration #2 hides declaration #1
    k = k+1;                     // k becomes 2
  }

This behavior is now emulated (with a warning) in Microsoft C++ mode with
--microsoft_version=1300 or higher.  (See Changes entry of 7/2/02 for the
complementary case of a declaration in a for-initializer that follows an 
ordinary declaration.)

9/11/02  Use of translation unit information in error routines

The error routines test the translation unit data structure to determine
whether a message is from a secondary translation unit.  This can cause
an access to freed memory if the error routines are called from a back end.
The use of the translation unit structure is now bypassed when the error
routines are called from a back end.

9/11/02  Microsoft compatibility: qualifiers on in-class specializations

Qualifiers were not accepted in Microsoft in-class specializations.  This
has been fixed.

  struct C {
    template <class T> void f(T) const;
    template <> void f(int) const { }
  };

9/11/02  Abort when using implicit inclusion

Version 3.0 introduced a problem that could cause an abort when processing
implicitly included files when guiding declarations are enabled.  This
has been fixed.

  t.c:
  #include "ex.h"
  void f(int);
  A<int> a;

  ex.h:
  template <class T> struct A { void f(); };

  ex.c:
  template <class T> void f(T){}

9/11/02  Microsoft compatibility: __if_exists problems

Two problems with the processing of Microsoft __if_exists directives have
been fixed:

1. If two __if_exists/__if_not_exists directives appeared one after another
with no intervening tokens, the second directive would actually be processed
while caching the tokens of the first one, producing incorrect results.

  __if_not_exists(func) {
   int func() { return 0; }
  }
  //void dummy_decl();  // works if this is uncommented
  __if_not_exists(func) {
   int func() { return 0; }
  }

2. An __if_exists would not be processed correctly when inserted using
   insert_string_into_token_stream.

9/10/02  va_list put in std namespace when using built-in stdarg

When using the built-in stdarg processing va_list was put into the global
namespace, but the C++ standard requires that it be in the std namespace.
It is now put into the std namespace and a using-declaration is put into
the global namespace if the include was of "stdarg.h" (rather than "cstdarg").
The old behavior can be obtained by setting DEFAULT_VA_LIST_IN_STD_NAMESPACE
to FALSE.

9/9/02   Pragma redefine_extname

The front end now recognizes the redefine_extname pragma when the new
configuration macro REDEFINE_EXTNAME_PRAGMA_ENABLED is TRUE.  This pragma
must be followed by two identifiers and causes entities named with the first
of these identifiers to have the second name as their external (asm) name.
When this feature is enabled, the macro __PRAGMA_REDEFINE_EXTNAME is 
predefined (to the value "1") by the front end.  The entity whose external
name is changed in this way must have external C linkage.

  #ifdef __PRAGMA_REDEFINE_EXTNAME
  #pragma redefine_extname f g
  #endif
  extern "C" void f() {}  // Seen as function "g" by the linker

(This pragma appears in some system headers of the Sun Solaris operating
system.)

9/6/02   Instantiation incorrectly removed from the IL in -tall mode

Version 3.0 introduced a problem that would cause unused function
instantiations to be removed from the IL in -tall mode.  This has
been fixed.

9/5/02   Microsoft compatibility: IL write/read error on nested class in
         Microsoft in-class specialization

An IL write/read error would occur in certain cases when a Microsoft
in-class specialization contained a nested class containing a template
declaration.  This has been fixed.

  template <class T1> struct A {
    template <class T2> struct B {};
    template <> struct B<int> {
      struct C {
        template <class T3> static void f(T3 t3){}
      };
    };
  };
  int main () {
    A<int>::B<int>::C::f(1);
  }

9/5/02   Microsoft compatibility: Failure to instantiate template defined
         in Microsoft in-class specialization

The front end failed to instantiate a member of a nested class that is
specialized using a Microsoft-mode in-class specialization.  This has
been fixed.

  template <class T1> struct A {
     template <class T2> struct B {};
     template <> struct B<int> {
       template <class T3> static void f(T3 t3){}
     };
  };
  int main () {
    A<int>::B<int>::f(1);  // link error: f not defined
  }

9/4/02   GNU C compatibility: structs of size zero

The front end already allowed empty structs in GNU C mode, but such structs
used to have a nonzero size.  Now, such empty structs have size zero.  The
same is true of unions.  Structs and unions containing only fields of size
zero (zero-length arrays, zero-length bit fields, and structs of size zero)
also have size zero.  For example:

  struct E {};  // sizeof(E) == 0
  struct CE { struct E e; int a[0]; };  // sizeof(CE) == 0
  union EU { struct CE s; int: 0 };  // sizeof(EU) == 0

Note that in GNU C mode, the size field of a type entry can be zero even
though the type is complete (both in the case described above and in the
case of zero-length arrays).  Use the is_incomplete_type macro to determine
completeness.

9/4/02   Abort in make_global_var_with_prefixed_name

In configurations using an old ABI (e.g., 2.28) and the old driver
interface (using generated variables instead of a .ti file) it
was possible to get a generic abort (internal error: assertion
failed at: "lower_il.c", line 1635 -- which turns out to be in
make_global_var_with_prefixed_name) on processing of an extern "C"
inline function in a configuration that instantiates extern inline
functions.  Now fixed.

  extern "C" {
    inline void f(int i) {}
  }
  int main() {
    f(1);
  }

9/3/02   GNU mode: alias of undeclared entity

Some GNU C compilers (notably on x86-based platforms) accept an alias
attribute that refers to an entity not declared in the translation unit
in which the attribute appears.  The effect of such an attribute is to
change the assembler name of the entity on which the attribute appears.
The EDG front end now emulates this behavior in GNU modes (with a warning).

  extern int f() __attribute__((alias("g")));
  int main() {
    f();  // Calls "g" defined in another translation unit (with a warning).
  }

8/29/02  GNU mode: volatile and noreturn attributes

In GNU modes, the front end now accepts the "volatile" attribute as a
synonym for the "noreturn" attribute.  In addition, these attributes are
now taken into account when making simple indirect calls to inhibit a
warning about a missing return statement.  For example:

  void (*pf)() __attribute__((volatile));
  int g() {
    pf();
  }       // No warning about missing return statement because a
          // simple indirect call was made to a function with the
          // noreturn/volatile attribute.

8/28/02  GNU mode: Memory clobber representation (IL Change)

In GNU modes, the front end previously parsed "memory" clobber specifications,
but it did not represent that specification in the IL.  Now, such extended
asm clobber specifications are represented with the pseudo-register
anr_memory.

8/28/02  GNU compatibility: Extended asm operand constraints

In GNU modes, the front end now distinguishes between "input" and "output"
operations when verifying that an operand is used only once.  Now, an operand
can be used once for input and once for output ("early clobber" is treated as
both input and output).  For example:

  void f(int p) {
    __asm__ ("movl %0, %1" : "=b"(p) : "b"(p));  // Accepted now.
  }                                              // ("b" used once for input,
                                                 // and once for output.)

8/27/02  Microsoft compatibility: selectany constraints

In Microsoft versions prior to 1300, variable definitions with selectany had
to have an explicit, static initializer.  In versions 1300 and later (which
correspond to Visual C++ 7/.Net and later), these constraints are removed.
For example:

  int f();
  struct S {
    static int x, y;
  };
  __declspec(selectany) int S::x;        // OK in Microsoft mode versions 1300
                                         // and later (error otherwise).
  __declspec(selectany) int S::y = f();  // OK in Microsoft mode versions 1300
                                         // and later (error otherwise).

8/27/02  Microsoft compatibility: friend declaration with __declspec specifier

In Microsoft mode, a friend class declaration could either omit the class 
(or struct or union) keyword or add a __declspec specifier, but not both.
Now the combination of both extensions is accepted in Microsoft mode.

  struct S;
  class C {
    friend __declspec(dllimport) S;  // Previously an error; now accepted in
  };                                 // Microsoft mode.

8/22/02  IL CHANGE: opname_or_builtin field of a_routine renamed "variant"

As part of the IA-64 ABI changes, the field named "opname_or_builtin"
in the IL a_routine entry has been renamed "variant".

8/21/02  GNU C compatibility: "visibility" attribute on variable declarations

In GNU C mode, the front end now accepts the visibility attribute on
variable declarations (see also the entry of 6/27/02).

  int i __attribute__((visibility("hidden")));  // Accepted in GNU C mode

8/21/02  Build problem when not using IEEE floating point

The front end did not build properly when TARG_HAS_IEEE_FLOATING_POINT
was FALSE.  This problem was introduced in version 3.0 and is now fixed.

8/21/02   Spurious error on member using-declarations

Member using-declarations must refer to declarations that are visible in a
direct base class.  The front end used to interpret this rule too strictly
when the using-declaration refers to an overloaded function that is made
visible in a direct base class through another using-declaration.

  struct A {
    void foo (int) {}
    void foo (float) {}
  }; 
  struct B: public A {
    using A::foo;
  }; 
  struct C: public B {
    using A::foo;  // Used to trigger an error; now accepted.
  };

This is now fixed.

8/21/02  Abort using precompiled headers on invalid input file

Certain invalid input files (e.g., a file that contains only the string
literal "test") would cause the front end to abort when using precompiled
headers.  This has been fixed.

8/21/02  Spurious error on text in "#if" that looks like hex FP constant

In C99 mode a spurious error was issued on a string that looks like a
hexadecimal floating point constant in text being skipped because of a "#if"
directive.  This has been fixed.

  #if 0
  x is 0x1234.
  #endif

8/21/02  Missing error on extraneous right parenthesis in ctor-initializer

In some cases, the front end silently ignored an extraneous right parenthesis
following a ctor-initializer.  For example:

  struct S {
    S(): x(1.0)) {}  // Used to be accepted.  Now a syntax error.
    double x;
  };

This is now fixed.

8/21/02  Microsoft compatibility: internal error on __super reference

An internal error would occur on certain uses of the Microsoft __super
keyword when the entity referenced is a member of an indirect base class.
This has been fixed.

  struct Base {
    void f() {}
  };
  struct Derived : public Base {};
  struct MoreDerived: public Derived {
     void f() { __super::f(); }
  };

8/20/02  GNU compatibility: Built-in functions misdeclared

The following built-in functions were previously misdeclared: __builtin_apply,
__builtin_trap, __builtin_unwind_init, __builtin_unwind_dwarf_cfa, and
__builtin_dwarf_fp_regnum.

  int main() {
    __builtin_unwind_init();  // Used to trigger an error in GNU C mode;
    return 0;                 // now accepted.
  }

This is now fixed.

8/20/02  GNU compatibility: Typedef attributes

The front end used to systematically apply typedef declaration attributes
to a copy of the underlying type.  This caused problems with class types
(and, potentially, with enumeration types).  To avoid such problems, the
front end now no longer attempts to copy class types and enumeration types.
Instead, the attributes are either applied to the original underlying type,
to the typedef entry itself, or they are ignored with a warning.

  typedef struct S { int i; } ST __attribute__((unused));
  void f(ST *p) {
    p->i = 1;  // Used to trigger an error.  Now fixed.
  }

8/19/02  Preinclude can be used in conjunction with precompiled headers

The use of preinclude files was previously not supported when using
precompiled header files.  These features may now be used together.

8/17/02  IL write/read error, pragma on Microsoft property field

Inconsistent IL (and an IL write/read error if an IL file is written)
resulted from placing a pragma on a field that is declared to be
a property in Microsoft mode.  The problem is that the field does
not really exist, and is removed by IL lowering.  A pragma in
such cases is now ignored, with a diagnostic.

8/16/02  GNU compatibility: x86 calling convention attributes on typedefs

When GNU_X86_ATTRIBUTES_ALLOWED is TRUE, the front end now allows the
__stdcall__ and __cdecl__ attributes on typedefs in GNU C and C++ modes.
The underlying type must be a function or pointer-to-function type.
for example:

  typedef int __attribute__((__stdcall__)) (*proc)( void );

8/16/02  GNU compatibility: x86 register names can be prefixed with %

The GNU compiler accepts a "%" on register names in asm constructs.
This is now emulated when GNU_X86_ASM_EXTENSIONS_ALLOWED is TRUE.

8/16/02  Abort on use of "::" in #if expression

The front end aborted on use of a leading "::" in an expression
in a #if.  "::" is meaningless in preprocessing expressions
because there are no identifiers in such expressions.  Fixed (an
error is issued).

  #if ::x  // Aborted
  #endif

8/15/02  Fix on fix to overload resolution tiebreaker processing

The fix to overload resolution tiebreaker processing done recently
(see Changes entry of 6/3/02) was not correct in some cases.
Now fixed.

  struct vstr  {
    vstr(unsigned short * const &);  // 1
    vstr(unsigned short const *);
    vstr(unsigned short const * &);
  };
  static unsigned short *p;
  static const vstr x = p;  // Should choose 1, got ambiguity previously

8/15/02  Microsoft C++ compatibility: extern inline declarations

In Microsoft C++ mode, inline functions have external linkage by default.
However, if the extern keyword is explicitly specified on an inline function
declaration, Microsoft compilers will always generate code for the function
(even if it is not used in that translation unit).  This behavior is now
emulated when INSTANTIATE_EXTERN_INLINE is TRUE.

  inline void f() {}         // Not emitted by Microsoft compilers unless
                             // really needed.
  extern inline void g() {}  // Always emitted by Microsoft compilers. 

The IL also records whether "extern inline" was explicitly specified on a
function declaration and the C++-generating back end uses that flag to avoid
the rendering of an unnecessary extern keyword when generating code for a
Microsoft compiler (flag msvc_is_generated_code_target is TRUE).

8/13/02  -0.0 versus 0.0 in constant sharing, fp_same_representation

The use of fp_compare in the search for a shareable constant
was incorrect, because it must return equality for 0.0 <?> -0.0,
and those really aren't the same constants.  In the front end
as delivered this did not matter, because fp_hash always
returned a different bucket number for 0.0 and -0.0, so they
were never compared.  However, when our customers replace the
floating-point routines, they could too easily fall into the
situation where this mattered, especially if they did not zero
the full floating-point value on initialization.  To fix this
problem, we have added a new routine fp_same_representation,
which compares two floating-point values and returns true if
they have the same representation, i.e., it returns false for
a comparison of 0.0 and -0.0.  This routine is now called
from the constant-sharing code.

8/10/02  Configuration option for signedness of one-bit bit fields

Heretofore, bit fields with length one and having a base type that
is not explicitly signed or unsigned have always been made unsigned,
even when TARG_PLAIN_INT_BIT_FIELD_IS_UNSIGNED is FALSE, with the
rationale that a bit field consisting of only a sign bit is not
very intuitive or useful.  However, lots of other compilers go
ahead and make a signed one-bit field in that case.  Therefore,
there is now a configuration option
TARG_FORCE_ONE_BIT_BIT_FIELD_TO_BE_UNSIGNED to control that behavior.
The default is TRUE, which retains the old behavior, except in
IA-64 ABI mode.

8/9/02   GNU compatibility: flexible array members

In GNU C and C++ modes, the front end now accepts C99-style flexible array
members.  Just as in Microsoft mode, the last field of a class type can
have a type whose last field is a flexible array member.

  struct A {
    int a;
    int x[];  // OK in GNU C and C++ modes
  };
  struct B {
    int b;
    A y;  // OK in GNU C and C++ modes
  };

8/8/02   Layout of bit fields with size larger than their base type

If C++, bit fields are allowed to be declared with a size that is
larger than the number of bits in the base type of the bit field.
Heretofore, the size of such bit fields was truncated to the
size of the underlying type.  This is allowed by the standard but
surprising to some users.  Now, if TARG_PAD_BIT_FIELDS_LARGER_THAN_BASE_TYPE
is TRUE (which is the default), padding bits are added following 
the bit field to bring the bit field up to the declared size.
The bit field itself holds no more bits: the added bits are 
padding bits, not data bits.  This is an ABI CHANGE; it is
disabled if ABI_COMPATIBILITY_VERSION is less than 301 or if
TARG_PAD_BIT_FIELDS_LARGER_THAN_BASE_TYPE is explicitly set to
FALSE.

  struct A {
    char i : 1024;  // A char-sized bit field followed by padding bits
                    // to make a total of 1024 bits.
  };

[8/12/02:] A related change -- bit fields of enum type are no longer
allowed to have sizes greater than their base types unless the mode is
C++ and the padding option above is enabled.  In C++ mode with the
option enabled, there will be no meaningful net change from the
previous behavior.  In C mode, or in C++ mode with the padding option
disabled, some bit fields formerly accepted will be rejected; however,
configurations that have TARG_ENUM_TYPES_CAN_BE_SMALLER_THAN_INT set
to FALSE (which is probably most of them) will see a change only for
bit fields larger than int size, which means the impact is very small.
For the affected cases, the code generated by the C-generating back
end was incorrect (or at least nonstandard) C in any case.

8/8/02   GNU compatibility: __restrict__

In GNU C and C++ modes, the front end now recognizes the __restrict__
keyword.  Except for its spelling, it is identical to the restrict keyword
in C99.

8/8/02   Undeclared memset, memcpy in generated C not C99-conformant

The code generated by the C-generating back end sometimes called
memset and memcpy without having declared them.  This was okay
in C89, but no longer is in C99 (all functions must be declared).
The C-generating back end now puts out declarations at the
beginning of the generated code in case memset and memcpy are
needed.

8/7/02   Microsoft compatibility: long + int now long in VC7

The Microsoft bug that caused long+int to be seen as int (see
Changes entries of 4/22/97, 5/2/98) has been fixed in VC 7 (aka
VC .NET).  When --microsoft_version=1300, emulation of
that bug is now turned off.

8/7/02   Inlining in GNU C statement expressions

A GNU C statement expression, i.e., ({ ... }), returns a value if
the final statement is an expression statement.  Inlining can foul
that up by rewriting a final statement that is a function call as
a block statement.  To avoid that, inlining is now disabled in
statement expressions.

8/7/02   Start position on IL block statement for GNU C statement expression

The start position was not set in the stmk_block statement attached
to an enk_statement expression node for a GNU C ({...}) statement
expression.  Now, it is.

8/6/02   GNU C++ compatibility option

The front end now supports command-line switches --g++ and --no_g++ that
provide some language compatibility with GNU C++ compilers.  The compatibility
is neither exact (i.e., some extensions may have a slightly different meaning)
nor complete (some extensions are not implemented). 

To enable these switches, GNU_EXTENSIONS_ALLOWED must be configured TRUE.
In that case, the default value of the command-line switch is determined by
the new configuration option DEFAULT_GPP_COMPATIBILITY.

The set of extensions enabled with the --g++ option initially includes:
the __attribute__ syntax, the __extension__ keyword, builtin <stdarg.h> and
<varargs.h> support, other builtin functions such as __builtin_alloca (but
not all GNU C++ builtin functions are recognized), excess aggregate
initializers are ignored, zero-length arrays, sizeof can be applied to void
and to function types, pointer arithmetic is applicable to void pointers and
to function pointers (they behave much like char*), the dereferencing
operator can be applied to void pointers, &&label, typeof, global variables
can be mapped to specific registers using the asm keyword, assembler names
of variables and routines, adjectives such as short and signed are accepted
in combination with typedefs of integer types, the inline keyword is accepted
on block extern declarations, some basic type specifiers can be duplicated
(e.g., "int int"), "extern template <declaration>" indicates that the given
specialization should not be instantiated.  [8/8/02] Exceptions are enabled
by default.  std::type_info needs no special pragma.  Unqualified names are
not looked up in dependent base classes.  Infinity is silently used for
out-of-range floating-point literals.  [8/13/02] Support for __null.
[8/15/02] Switch case ranges.  The \e escape sequence in string and character
literals.  A backslash can be the last character in a file.  Multiline
string literals are accepted.  __FUNCTION__ expands to the undecorated name
of the function in which it appears (but, unlike in GNU C mode, does not act
like a string literal).  A few non-standard constant-expressions are accepted
(e.g., (int)"str" & 0).  Support for extended variadic macros.
[8/30/02] __PRETTY_FUNCTION__ expands to the decorated name of the function in
which it appears.  [9/12/02] Emulation of the dependent base class lookup
done by g++.  [9/16/02] Compound literals and designated initializers.
[9/17/02] Predefined __GNUG__ macro.  [9/24/02] Attributes following
parenthesized initializers.  [9/24/02] Nonstandard anonymous unions.
[9/24/02] Member typedefs are accepted in elaborated type specifiers.
[10/9/02] Guiding declarations are disabled. [10/16/02] String literals
are const. [10/18/02] Namespace std is predeclared.

8/5/02   Final name mangling not done on some promoted local static
         variables

Final name mangling (which handles compression and truncation) was
not done on some local static variables promoted out of functions and
some generated variables (e.g., the __LSG__ guard variables for
local statics).  The final mangling is now done for those.

8/5/02   ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS and throws

When ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS is TRUE (not the
default), a "?" operator whose first operand is constant is
rewritten as simply the second operand or the third operand.
This wasn't done right when one of them is a throw expression.
Now fixed.

  int main() {
    int i = (true ? throw 4 : 5);
  }

8/5/02   C-generating back end: avoid "inline" as entity name

"inline" has been added to the list of known C keywords used
in the C-generating back end to avoid outputting an entity
with a name that is a keyword.

8/5/02   bool type and SAME_REPR_INTS_INTERCHANGEABLE_IN_IL

When SAME_REPR_INTS_INTERCHANGEABLE_IN_IL is TRUE (not the default),
an integral type should not be considered equivalent to a bool type
because there's a zero/non-zero to 0/1 transformation on a conversion
between them.  Now done correctly.

  int main() {
    char c = 15;
    bool b = c;  // Formerly was missing normalization to 0/1
  }

8/5/02   C++-generating back end: Nested class declarations not rendered

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the IL
generated by the front end would sometimes cause the C++-generating back end
to erroneously not render a nested class declaration.  Specifically, this
happened when the nested class was a member of a class template, while a
friend declaration of that class template also nominated that nested class.
For example:

  template<typename T> struct S {
    struct N {};      // Left out of the generated explicit specializations
                      // of S<>.
    friend struct N;
  };
  template struct S<int>;

This is now fixed.

8/3/02   GNU C compatibility: &(a, b) is treated as (a, &b)

In GNU C mode, it is now acceptable to take the address of a
comma expression whose second operand is an lvalue.

7/31/02  Overload resolution: binding reference to non-constant to
	 pointer produced by array-to-pointer decay

Overload resolution incorrectly allowed an exact match on a case
where an array decays to a pointer type and a reference to non-const
parameter attempts to bind to the resulting pointer (it can't,
because a reference to non-constant can bind only to an lvalue).

  void f(wchar_t *&);		// Was selected, shouldn't be
  void f(wchar_t const *);	// Can be called, wasn't selected
  int main() {
    f(L"");
  }

7/30/02  Uninitialized field in statement control flow block

The any_vla_variables field of the statement control flow block
was not initialized, which could cause a reference to an
uninitialized value later.  Fixed.

7/23/02  GNU C mode: Enumerator constant types

In GNU C mode, enumerator constants take on the first type from the following
list that can accommodate their values: int, unsigned int, long, unsigned
long, long long, unsigned long long.  (With the --short_enums option or with
the packed attribute, the list starts with signed char, unsigned char, short,
and so forth.)  All enumerators acquire the same type (this is the gcc 3.x
behavior; earlier versions could lead to different enumerators having
different types).
For example, assuming long is a 32-bit type:

  enum E { x = 0x400, y = 0x4000000000, z = 0x401 };

Here x, y and z have type long long.  (Previously, this would have triggered
an error because the type of enumerators was always int in GNU C mode, and
0x4000000000 does not fit in an int.) The underlying type of E is unsigned
long long, because no negative enumerators were seen (this preference for
unsigned types was already emulated in GNU C mode).

7/22/02  Spurious warnings about partial overriding of virtual functions

When only a few of a set of overloaded virtual member functions are
overridden in a derived class, the front end warns about the potentially
unintended hiding of the non-overridden functions in the base class (see 
Changes entries of 9/23/99 and 9/30/99).  This warning was incorrectly
emitted in some situations involving using-declarations and multiple
levels of inheritance.  For example:

  struct B {
    virtual void f(); 
    virtual void f(int);  
  };
  struct D: public B {
    using B::f;
    virtual void f();
  };
  struct X: public D {
    using D::f;
    virtual void f();  // Used to trigger a spurious warning
  };

This is now fixed.

7/22/02  Abort in compare_constants: GNU C, RECORD_CONSTANT_EXPRESSIONS_IN_IL

An abort in compare_constants ("bad constant kind") has been fixed.
It came up in configurations with RECORD_CONSTANT_EXPRESSIONS_IN_IL
set to TRUE (e.g., C++-generating back end versions), in GNU C mode,
when compiling a compound literal surrounded by an extra set of
parentheses that is used to initialize a non-automatic variable.

  struct A { int i; };
  struct A a = ((struct A){1});
  struct A b = ((struct A){1});

7/16/02  GNU C mode: Abort on too large enumerator constant

The front end would sometimes abort when processing too large an enumerator
constant in GNU C mode.  For example:

  enum a { i = 0x400000000000000000000000000 }; // Used to abort

This is now fixed.  [Patch sent out 7/23/02.]

7/16/02  Bug fix in mangled name truncation

The code to do truncation of mangled names to ensure that they
do not exceed a maximum length (given by DEFAULT_MAX_MANGLED_NAME_LENGTH)
did not work correctly for names that are already within 10 characters
of the maximum length.  This potentially caused string copies that
overwrote characters beyond the end of space allocated for the name,
which could have various unfortunate consequences.  Now fixed.
[Patch sent out 7/23/02.]

7/15/02  GNU compatibility: Excess aggregate initializers

In GNU mode, the front end already ignores excess array initializers
with a warning.  This has now been extended to aggregate initializers
for class type objects (including objects of union types).
For example:

  struct S { int a, b; };
  struct S a = { 1, 2, 3 }; // "3" ignored with a warning in GNU mode

7/11/02  Abort in set_pm_base_class_cast ("could not find base class")

An abort on handling folding of some undefined-behavior pointer-to-
member casts as constant casts has been fixed.  The problem cases
involve multi-step casts such that the original member does not
exist in the class of the final cast.  The cases are now not folded,
leaving them to work, or not, as casts at execution time.
[Patch sent out 7/23/02.]

  struct A { int a; A() : a(2) { } virtual void f() = 0; };
  struct B { int b; B() : b(3) { } virtual void f() = 0; };
  struct C { int c; virtual void f() = 0;  };
  struct D : A, B, C { virtual void f() { } };
  void (B::*ff())() { return (void (B::*)())(void (D::*)())&C::f; }

7/10/02  GNU compatibility: __VERSION__ macro

In GNU mode, the __VERSION__ macro is now supported.  The macro
expands to a string literal, the value of which is specified by
the GCC_VERSION_STRING configuration macro.  [Patch sent out 7/23/02.]

7/9/02   C++-generating back end: name references

When RECORD_FORM_OF_NAME_REFERENCE is TRUE (which it is by default
when BACK_END_IS_CP_GEN_BE is TRUE), the front end now records the
form of name references in IL entries of type a_name_reference
and a_name_qualifier (IL CHANGE if configured in); the C++-generating
back end then uses those to output the name reference exactly the way
it was in the source code.  This is currently being used in only
a few kinds of references; we will be gradually expanding the list
of cases.

7/8/02   Multiple translation units, address_taken on routines and variables

When a compilation involves multiple translation units (e.g., when
exported templates are used), and the IL for those translation units
is merged, the address_taken flags on routines and variables were not
being merged (or-ed) correctly.  Now, they are, so that when the
address of an entity is taken in one translation unit and the definition
appears in another (in which the address is not taken) the address_taken
flag is correctly set.  [Patch sent out 7/23/02.]

7/2/02   Sun compatibility: Explicit instantiation of a class does not
         instantiate inline members

In Sun mode, the explicit instantiation of a class does not cause the
instantiation of inline member functions.  [Patch sent out 7/23/02.]

  template <class T> struct A {
    void f() { g(); }  // error if instantiated -- g is undefined
  };
  template class A<int>;

7/2/02   GNU C compatibility: Unprototyped function redeclaration
         supersedes prior prototyped declaration

In GNU C mode, the front end already accepted unprototyped redeclarations of
previously prototyped functions.  However, in such situations the type
information associated with the original prototyped declaration was kept for
later error checking.  This is now changed for improved compatibility with the
GNU C compiler: An unprototyped redeclaration of a function essentially
nullifies the type information implied by an earlier prototyped declaration
(unless a definition of the function has been seen).  For example:

  void f(char);        // First declaration (prototyped)
  void f();            // Second declaration (unprototyped)
  void f(c) int c; {}  // Third declaration conflicts with first:
                       // Previously an error, now accepted with no diagnostic

[Patch sent out 7/23/02.]

7/2/02   Microsoft compatibility: Declaration in for-initializer can hide
         declaration in surrounding scope

Microsoft Visual C++ version 7 allows a for-initializer to declare a
variable with a name that is already declared in the scope surrounding
the for-loop.  The earlier declaration is then hidden.  For example:

  int main() {
    int k = 1;                   // Declaration #1
    for (int k = 0; k<10; ++k);  // Declaration #2 hides declaration #1
    k = k+1;                     // k becomes 11
  }

This behavior is now emulated (with a warning) in Microsoft C++ mode with
--microsoft_version=1300 or higher.

7/1/02   Incorrect sizeof result of substituted template type

When evaluating a sizeof expression in a context in which template
parameters are being replaced with the corresponding template
argument values, a full instantiation of a template class was not
being done in some cases, resulting in an incorrect size.  This
has been fixed.  [Patch sent out 7/23/02.]

  template<int size> struct A { };
  template <class A> struct B { };
  template <class T> A<sizeof(B<T>)> f(T);
  int main() {
    f(1);
  }

7/1/02   GNU C compatibility: __BASE_FILE__ macro

The GNU C macro __BASE_FILE__ is now implemented in gcc mode.  It
is similar to __FILE__ but indicates the primary source file rather
than the current source file.

6/28/02  Warnings on just-past-end invalid subscripts, multi-dimensional
         array

A warning is now issued for a use of a just-past-the-end subscript
in a subscript other than the last in a multi-dimensional subscripting
operation.

  struct A {
    int x[10][3];
  };
  int main() {
    A *p = new A;
    p->x[10][1];  // [10] is invalid
  }

6/27/02  GNU C mode: Extended asm improvements

The front end used to generate incorrect IL for certain extended asm
constructs.  For example

  void f() { asm ("nop" : : : "bx", "ax"); }

was rendered by the C-generating back end as

  void f() { asm volatile("nop" : : : "ax", "invalid"); return; }

This is now fixed.  We also corrected a missing initialization that could
make the front end abort on some platforms when compiling extended asm
constructs.  [Patch sent out 7/23/02.]

6/27/02  Abort on using-declaration of template-dependent name

An abort on processing a using-declaration of a member of a
template-dependent class has been fixed.  [Patch sent out 7/23/02.]

  template<typename T>
  struct X: T {
    using typename T::T2;
    X(T2);
  };
  template<typename T>
    X<T>::X(T2) {
  }

6/27/02  GNU C compatibility: New "visibility" attribute

In GNU C mode, the front end now accepts the visibility attribute on
function declarations.  This attribute specifies the visibility of a
function in an ELF object file.  The attribute must be used with one
of the following string literal arguments: "hidden", "protected", or
"internal".  For example:

  void f() __attribute__((visibility("internal")));

6/27/02  Abort on inlining in GNU C mode

An abort while doing inlining in GNU C mode has been corrected.  The
abort came about when it is first determined that inlining cannot be
done for the dependent statement of an "if".  [Patch sent out 7/23/02.]

  int i, j;
  extern inline void set_close_on_exec(unsigned int fd, int flag) {
    if (flag) switch(i) { case 1: j = 4; break; case 2: j = 2; break; }
  }
  long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) {
    set_close_on_exec(fd, 1);
    return 4;
  }

6/26/02  Abort on definition of function previously misdeclared in a namespace

The front end used to abort when processing the definition of a function that
was first declared with undeclared types in a namespace, and then named by a
friend declaration not enclosed by that namespace.  For example:

  namespace N { void f(X); }  // Error: No type X declared
  class X { friend void N::f(X); };
  namespace N {
    void f(X) {}              // Used to cause an abort
  }

This is now fixed.  [Patch sent out 7/23/02.]

6/26/02  Microsoft compatibility: Using-declarations of masked members

MSVC++ 7 (but not MSVC++ 6) accepts using-declarations of members that are not
visible in a direct base class of the class in which the using-declaration
appears.  For example:

  struct B { void f(); };
  struct D: B { void f(); };
  struct X: D {
    using B::f;  // Accepted by MSVC++ 7
  };

The EDG front end now emulates this behavior when microsoft_version is larger
than 1200.

6/26/02  PODs can have pointer-to-member fields

A field of pointer-to-member type no longer makes a class type a non-POD
(in all C++ modes).

6/25/02  Microsoft __intN specifiers are synonyms for other types

The change to make Microsoft __intN specifiers distinct types (see
entry for 12/14/99 below) for MSVC++ 6 turns out to have been a bug
and not a feature in version 6, and has now been changed back in
MSVC++ 7 to the way it was before.  The EDG front end has been changed
likewise, and now gives the VC6 behavior only when microsoft_version
is 1200.  [Patch sent out 7/23/02.]

6/24/02  Abort in same_type_with_added_qualifiers

An abort in same_type_with_added_qualifiers has been fixed.
It involved comparisons of template conversion functions in
overload resolution.  [Patch sent out 7/23/02.]

  class StrictType {
    public:
      StrictType(const char* x);
  };
  class ISDCPars : public StrictType {
    public:
      virtual operator char*();
      template <typename A>
      inline A CopyFromPar() {
        return StrictType(*this);
      }
    private:
      template <typename A>
      inline operator A() {}
  };
  ISDCPars::operator unsigned short() {
    return CopyFromPar<unsigned short>();
  }

6/23/02  Source positions on overloaded operator-> call

The source positions on the operand for an overloaded operator->
call have been adjusted so that they point appropriately to the
operand and the "->" operator.  This is mostly visible in the
position in error messages, because source positions are not
recorded in expression nodes for generated operations (and would
in any case be recorded only if EXTRA_SOURCE_POSITIONS_IN_IL is
TRUE).

6/20/02  Use of predefined macros on X86 architecture

Formerly, the front end tested the __i386__ macro to determine whether
the X86 architecture was being used.  Because certain compilers define
only __i386 and not __i386__, we now test the __i386 macro instead.  The
front end now, by default, defines both __i386 and __i386__ when built on
an X86 architecture system.  Formerly, only __i386__ was defined.
[Patch sent out 7/23/02.]

6/20/02  Partial ordering and cv-qualified references

The partial ordering rules used by the front end have been revised
to better handle cv-qualified references.  This example was ambiguous
with the old rules but prefers f(S<T>) with the new rules.  The language
specification in this area is sufficiently unclear to be sure that either
of these interpretations is the correct one.  We are working on a
proposed clarification of the rules in the standard and will incorporate
this change as part of the proposed rules.  [Patch sent out 7/23/02.]

  template <class T> struct S { };
  template <class T> void f(S<T>);
  template <class T> void f(const T&);
  int main() {
    S<int> s;
    f(s);
  }

6/20/02  Anonymous types in anonymous unions

The C++ standard does not permit the declaration of types in anonymous
unions, but the front end failed to diagnose this when the type declared
in the anonymous union is itself anonymous.  For example:

  struct S {
    union {
      struct {} x;  // Used to be accepted in strict ANSI C++ mode
    };
  };

This is now fixed (i.e., an error is issued in strict mode; a warning in
default mode).

6/20/02  GNU C compatibility: Redeclaration of a transparent union parameter

In GNU C mode, a parameter first declared as a transparent union can be
redeclared with the type of a member of that union and vice versa.
For example:

  typedef union {
    void *vp;
    double *dp;
  } U __attribute__((__transparent_union__));
  void f(U);
  void f(void*);  // OK in GNU C mode
  void g(double*);
  void g(U);      // OK in GNU C mode

In such cases, the resulting composite parameter type is the union type.
[Patch sent out 7/23/02.]

6/20/02  GNU C mode: last line of file can end with backslash

In GNU C mode, the last line of a file is now allowed to end with a
backslash.  A warning is issued.

6/20/02  asm member function definitions

When ASM_FUNCTION_ALLOWED is TRUE, the front end now also accepts out-of-class
asm member function definitions (these definitions are passed uninterpreted to
the back end; see Changes entry of 2/9/95).  For example:

  struct S { void f(); };
  asm void S::f() { iret }  // Now accepted in some configurations

Previously, asm definitions were only permitted for non-member functions.

6/20/02  GNU C compatibility: infinity used for FP values out of range

In GNU C mode, instead of issuing a diagnostic when a floating point
value is out of range, the "infinity" value is silently used instead.
[Patch sent out 7/23/02.]

6/19/02  C-generating back end: Sequencing of C99 STDC pragmas

The C-generating back end used to emit all the file scope C99 STDC pragmas
prior to emitting the routine definitions to which the pragmas apply.  This
resulted in incorrect C code.  For example:

  #pragma STDC FP_CONTRACT OFF
  void f1() {}  // floating-point contraction disabled
  #pragma STDC FP_CONTRACT ON
  void f2() {}

was compiled to the equivalent of

  #pragma STDC FP_CONTRACT OFF
  #pragma STDC FP_CONTRACT ON
  void f1() {}  // floating-point contraction enabled
  void f2() {}

This is now fixed.

6/19/02  Missing ambiguity error on ctor-initializer

The front end failed to diagnose an ambiguous name used as a base class
in a ctor-initializer.  This has been fixed.  [Patch sent out 7/23/02.]

  struct D { struct X {};};
  struct C { struct X {};};
  struct A : C::X, D::X {
     A() : X() {}  // X should be ambiguous
  };
  A a;

6/19/02  UPC Extensions

The front end can now accept the Unified Parallel C (UPC 1.0) core language
extensions when the command-line switch --upc is provided.  A configuration
option UPC_EXTENSIONS_ALLOWED enables those switches.  The extensions are
only allowed in C mode (and not in K&R C mode).

Among other things, UPC adds new type qualifiers (shared, relaxed and
strict), predefined pseudo-constants (THREADS, MYTHREAD), operators
(e.g., localsizeof), control statements (e.g., upc_forall) and pragmas.

The UPC constructs are recorded in the IL and can be regenerated by the
C- and C++-generating back ends.  No lowering of these constructs is
attempted.

EDG only provides support for the core language constructs; the UPC
library extensions (such as the upc_phaseof function) are not included.

6/18/02  Macro to determine whether long long is enabled not set in C mode

The front end can be configured to define a macro when long long is not
enabled (__NO_LONG_LONG, by default).  This macro should have been defined
in C mode, but was not.  This has been fixed.  [Patch sent out 7/23/02.]

6/18/02  GNU C compatibility: Redefinition of extern __inline__ function

In GNU C mode, a "extern __inline__" function definition can be followed
by another definition of that function (a warning is issued).  The earlier
definition is discarded and replaced by the latest one. For example:

  extern __inline__ int f() { return 3; }  // No out-of-line copy
  int f() { return 3; }                    // Out-of-line copy

A call to the function may appear between two such definitions; if that
call is inlined (by the lowering process), the first definition will be
used for that purpose.  [Patch sent out 7/23/02.]

6/17/02  Sun and Microsoft compatibility: Declaration of a variable visible
         through a using-declaration.

In Sun and Microsoft modes, the front end now accepts the redeclaration of a
variable visible through a using-declaration, even when that variable has
C++ linkage (this is a generalization of the Changes entry of 6/28/00).

  namespace N {
    extern int x;
  }
  using N::x;
  int x = 3;  // OK in Sun and Microsoft modes; defines N::x.

6/17/02  Null (zero) characters in source lines

The front end can now be configured to allow null (zero) characters
in source lines, by setting DEFAULT_NULL_CHARS_ALLOWED_IN_SOURCE
to TRUE.  Null characters in string and character constants are
preserved, and null characters elsewhere are discarded.  In GNU C
mode, the option is always enabled.  In Microsoft mode, the option
is always enabled, but null characters in strings and character
constants are ignored rather than preserved.

6/14/02  GNU C compatibility: Invalid flexible array members

In GNU C mode, the front end used to accept array fields with unspecified
bounds (flexible array members) even when those fields were not the last
field of the enclosing struct.  For example:

  struct {
    int n;
    int a[];  // Used to be accepted in GNU C mode; now an error.
    int b;
  };

Now an error is issued in such situations.  [Patch sent out 7/23/02.]

6/14/02  Microsoft compatibility: Calling convention on out-of-class definition

The front end used to fail to diagnose a mismatch between the calling
convention declared on the in-class declaration of a member function and
that declared on the corresponding out-of-class definition.

  struct S { void f(); };
  void __stdcall S::f() {}  // Used to be accepted; now an error

This is now fixed.

6/14/02  GNU C compatibility: Duplicate type specifiers

In GNU C mode, the front end now accepts duplicate type specifiers (with a
warning).  For example:

  unsigned short unsigned short x;  // Accepted in GNU C mode

[Patch sent out 7/23/02.]

6/13/02  TARG_HAS_IEEE_FLOATING_POINT on non-Linux X86 Unix Systems

TARG_HAS_IEEE_FLOATING point now defaults to TRUE on Unix systems
that define the __i386 macro.  Formerly, this defaulted to TRUE on Linux
and Windows, but not some other X86 operating systems such as Intel
Solaris.  [Patch sent out 7/23/02.]

6/11/02  Duplicate module IDs

Version 3.0 introduced a problem that could cause files with the same
name and containing the same inline function to have the same module IDs,
resulting in multiple definition errors at link time.  This has been fixed.
[Patch sent out 7/23/02.]

6/11/02  GNU C compatibility: extended integral constant expressions

GNU C mode now allows integral constant expressions with
nonstandard forms.  [Patch sent out 7/23/02.]

  int i [((char *) &((struct foo *) 0)->c[0]) - (char *) 0];

6/11/02  GNU C compatibility: alias attribute should not find macros

The front end used to mistakenly find macros when looking up an entity
named by the alias attribute.  [Patch sent out 7/23/02.]

  void SX() {}  // (1)
  #define SX sx
  extern void sx() __attribute__((alias("SX")));  // Should bind to (1)

This is now fixed.

6/11/02  Microsoft and Sun compatibility: static_cast to same type
         leaves lvalue

In Microsoft bugs mode and Sun mode, a static_cast to the same type
the operand already has now does nothing; in particular, it does not
force conversion of an lvalue to an rvalue.  [Patch sent out 7/23/02.]

6/11/02  GNU C compatibility: "register" and "q" in asm

The gcc asm support now accepts "q" as a constraint code (equivalent
to "Q") for X86, and "memory" as a legal register on all machines in 
the context of the clobber expression.  [Patch sent out 7/23/02.]

6/3/02   Improper tiebreaker processing in overload resolution (reference
         versus pointer)

In certain cases, overload resolution concluded that one or the
other conversion was better when a reference to pointer parameter
is compared against a pointer parameter and one has more cv-qualifiers
than the other.  They are now correctly treated as indistinguishable.

  template <class T1> int f(T1 *p, double = 0.0) { return p->a; }
  template <class T2> int f(const T2 &p, float = 0.0f) { return p->b; }
  int x = f((int *)0);  // Now ambiguous

A related bug has also been corrected.  In determining whether a
conversion for a parameter is possible in overload resolution,
the front end mistakenly concluded that an argument of pointer
type P1 could be used with a parameter of type P2& (with P2 also
a pointer type) if P1 can be converted to P2.  This was incorrect.
A pointer to char, for example, cannot be passed to a reference to
pointer to const char.  This mistake was generally hidden by the
above problem, and by the fact that a check done after the best
function was selected would catch the error, but it can be seen
in the difference in error messages on the following:

  void foo(int);
  void foo(const char*&);
  int main() {
    char* cp = 0;
    foo(cp);
  }

[Patch sent out 7/23/02.]

5/30/02  Spurious remark ("controlling expression is constant") on
         dependent expression

A spurious remark was issued on a boolean controlling expression
in a prototype instantiation of a template (e.g., in strict mode)
when the expression is a member of a nonreal class.  Now fixed.
[Patch sent out 7/23/02.]

  template<class T> struct B {
    int a;
  };
  template <class T> struct X {
    void f() {
      if (B<T>::a) {}  // Formerly got spurious remark
    }
  };

5/24/02  Microsoft compatibility: reference to const volatile can bind to
         rvalue

In Microsoft bugs mode, a reference to a const volatile can now bind
to an rvalue.  The ISO standard forbids that.  [Patch sent out 7/23/02.]

5/24/02  Compilation problem in IL display program with CHECKING set to FALSE

The il_display.c file did not compile correctly when CHECKING is
set to FALSE.  An internal_error call should have been a call
of unexpected_condition_str.  Fixed.  [Patch sent out 7/23/02.]

5/23/02  Static initialization on Windows

Version 7 of the Microsoft C compiler supports a pragma that can be
used to perform static initializations at program startup.  A new
configuration macro, MSVC_TARGET_VERSION, specifies the default
Microsoft version being targeted when MSVC_IS_GENERATED_CODE_TARGET
is TRUE.  The C generating back end now emits the new pragma to get
static initialization routines invoked at program startup when
MSVC_IS_GENERATED_CODE_TARGET is TRUE and MSVC_TARGET_VERSION is 1300 or
higher.  The --msvc_target_version command-line option can be used to
override the default version number.  [Patch sent out 7/23/02.]  
[10/17/02:] The name of the macro has been changed to
MSVC_TARGET_VERSION_NUMBER.

5/23/02  Spurious error on destructor reference

When a destructor is called using a qualified name that names a base
class, and the base class is a template class, a spurious ambiguity
error could result.  This has been fixed.  [Patch sent out 7/23/02.]

  namespace N {
    template <class T> struct A { };
  }
  template <class T> struct B : public N::A<int> {
    void f(B *bp);
  };
  template <class T> void B<T>::f(B *bp) {
    bp->N::A<int>::~A();
  }

5/17/02  Dependent name lookup: base class incorrectly treated as dependent

When using dependent name lookup mode, a dependent base class of a
nondependent base was incorrectly treated as dependent during lookups
in a derived class that is a template.  This has been fixed.
[Patch sent out 7/23/02.]

  template <class T> struct A {
    typedef int AA;
  };
  template <class T> struct B : public A<T> { };
  class C : public B<int> { };
  template <class T> struct D : public C {
    AA a;  // spurious error here
  };

5/15/02  GNU C compatibility: Invalid asm operand validation code

An error in the code that validates asm operand description could cause
spurious diagnostics on some extended GNU C asm constructs.  This is
now fixed.  [Patch sent out 7/23/02.]

5/15/02  Copying of function-scope constants while inlining

When the inlining process is copying the statements and expressions
of an inlined routine, any function-scope memory constants that
are encountered should be copied, because they are in the wrong
memory region.  That is now done.  This problem seldom came up,
but did arise more frequently when RECORD_CONSTANT_EXPRESSIONS_IN_IL
is set and IL lowering/inlining is also done (an unusual
combination).  [Patch sent out 7/23/02.]

5/15/02  GNU C compatibility: Spurious error when ellipsis in prototype
         declaration follows an unprototyped definition

Mixing unprototyped definitions with prototype declarations that
include an ellipsis parameter sometimes triggered a spurious error
in GNU C mode.  This has been fixed.  [Patch sent out 7/23/02.]

  void f(int, ...);
  void f(n) int n; {}
  void f(int, ...);  // Used to trigger an error; now accepted


5/15/02  Microsoft compatibility: disambiguation problem with __based

Disambiguation of declarations vs. expressions did not handle the
Microsoft __based feature properly.  This has been fixed.

  char *pc;
  int main() {
    int(__based(pc) f(int));
  }

5/15/02  Alignment problems with IL entries read from file

The code that reads IL files into memory did not properly ensure
alignment of the IL entries in configurations in which
HOST_POINTER_ALIGNMENT is smaller than HOST_ALIGNMENT_REQUIRED.
Now fixed.  [Patch sent out 7/23/02.]

5/14/02  Microsoft compatibility: spurious error on function-style cast

Contrary to the standard, the Microsoft compiler accepts a function-style
cast in which the type consists of more than one token.  Although this
feature is accepted in Microsoft mode, the front end sometimes failed to
disambiguate such cases properly, resulting in spurious errors.  This has
been fixed.

  int main() {
    long a = 100;
    (unsigned long(a)+1);
  }

5/13/02  C++-generating back end: explicit destructor call, Sun C++

The Sun C++ compiler has a bug with explicit destructor calls that
don't use qualified names to name the destructor.  The change of
4/28/02 ran into this bug.  We've backed this out partly by forcing
use of a qualified name on a destructor call of a non-virtual
destructor.

-------------------------------------------------------------------------------
Version 3.0, May 9, 2002

5/7/02   Exported templates

Exported templates are now implemented, as required by the C++
standard.  Templates declared with the keyword "export" can be
separately compiled, meaning a template can be referenced in a file
containing only a declaration of the template (marked with "export"),
and the definition (also marked with "export") can be placed in
another source file.  The front end does appropriate processing to
ensure that when the complete program is linked the template will be
instantiated.

When the front end compiles a file containing a definition of
an exported template, it writes a file with a .et suffix to
record the location of the definition.  Later, when a template
needs to be instantiated, the front end searches the .et
files to find the location of the definition, compiles the
definition file as a secondary translation unit, and instantiates
the template in a synthesized context formed by merging
information from several translation units.

As part of the process of reading secondary translation units,
the front end checks that the declarations of entities with
external linkage in different translation units match up, and
issues errors if they do not.

"export" is not quite the panacea that some users might hope
for.  It does allow users to omit the definitions of templates in
header files, but it doesn't make templates more efficient.  On the
contrary, because the front end has to process multiple translation
units simultaneously, the cost of compilation can be large, both
in terms of time and in terms of memory use.  Accordingly, "export"
is off by default, and we've tried hard to make sure that with the
feature disabled C++ programs that don't use "export" do not compile
slower than they did with previous versions of the front end.
"export" can be enabled by --export or --strict.

EDG's implementation requires that the source code for the
definitions of exported templates be available at the time of
instantiation, even for library code, so this feature does not
allow library vendors to avoid shipping source code.

For information on using "export" with libraries, and more
general information, see the External Interface chapter of the
internal documentation.

"export" requires dependent name lookup, which means it is
unlikely that "export" can simply be added to existing code
if the code is not modern template code (using typename, etc.).

This feature does not require any IL, back end, or ABI changes, but
the prelinker does more work than it used to and the formats of
some prelinker information files (.ti files, and .ii files on
Windows) have been changed.  There are substantial changes in
the structure of the front end, in particular in initialization
and wrapup.  Note that initializations in customer modifications
may have to be reworked (a) to do the initialization at the right
time (per-compilation or per-translation-unit), and (b) to register
variables that should be per-translation-unit.

5/6/02   IL version number changed to 2.38

5/6/02   Source position on rvalue array in C99 or GNU C mode

The source position on an array rvalue operand that was converted to
a pointer was not maintained correctly in C99 and GNU C mode, with
the consequence that positions in error messages could be slightly
wrong.

  char *a;
  struct s { char b[5]; };
  struct s f();
  char *test() {
    return a += f().b;  /* Position on error was on semicolon. */
  }

5/3/02   Macro to determine whether long long is enabled

The front end can now be configured to define a macro when long long is not
enabled.  The lang_feat.h flag DEFINE_MACRO_WHEN_LONG_LONG_IS_DISABLED is
used to request that such a macro be defined.  The name of the macro is
specified by the lang_feat.h flag MACRO_DEFINED_WHEN_LONG_LONG_IS_DISABLED.
By default, a macro named "__NO_LONG_LONG" is defined when long long is
disabled.

5/2/02   Internal error in copy_parent_type_with_substitution

An internal error would occur during template argument substitution
when the unsubstituted type is something like "U::type" and the
substitution results in a name that is actually a class template.
This has been fixed.
  
  extern "C" int printf(const char *, ...);
  typedef char small_t;
  typedef char (& large_t)[256];
  
  template<class T> class has_nested_type {
    private:
      template<class U> static small_t check(typename U::type*);
      template<class U> static large_t check(...);
    public:
      static const bool value = sizeof(check<T>(0)) == sizeof(small_t);
  };
  
  template<class T> const bool has_nested_type<T>::value;
  
  struct X { // 'type' is a template
    template<class> struct type { };
  };
  
  int main(int argc, char* argv[]) {
    printf("%d\n", has_nested_type<X>::value);
    return 0;
  }

5/2/02   Corrections to optimization of empty base classes

Two corrections were made to the empty base class optimization algorithm.
The first ensures that an empty base class is not allocated at the same
address as a field whose type is an array of that same empty class type.
E.g.:

  struct E {};
  struct S: E {
    E m[2];  // Used to be allocated at offset zero (causing a conflict
  };         // with the base class); now allocated at a positive offset.

The second correction avoids the optimization of empty classes with 
nonoptimized empty bases.  Without this change, a derived class could
end up being larger than its base class.  E.g.:

  struct S1 {};
  struct S2 : public S1{};
  struct S3 : public S1, public S2 {};  // Cannot optimize both S1 and S2
                                        // (hence: sizeof(S3)>1)
  struct S4 : public S3 { char c; };    // Base S3 used to be optimized so
                                        // that sizeof(S4) could be 1

This is an ABI change.  The previous behavior is restored if
ABI_COMPATIBILITY_VERSION is less than 300.

5/2/02   Microsoft compatibility: Qualified constructor declarations

In Microsoft mode, the front end now accepts nested class constructors
declared with a qualified name.  For example:

  struct S {
    struct N {
      S::N();  // Accepted in Microsoft mode.
    };
  };

5/1/02   Explicit instantiation of pure virtual permitted

An error was issued on an attempt to instantiate a pure virtual function,
but such instantiations are allowed by the standard.  The error has
been removed.

  template<class T> struct A {
     virtual void f() = 0;
  };
  template<class T> void A<T>::f() {}
  template void A<int>::f();

4/29/02  Failure to diagnose address of bit field in C mode initializer

The front end failed to issue an error on taking the address of a bit
field in a constant initializer in C mode.  Now fixed.

  struct {
    unsigned char a;
    unsigned char c:1;
  } x;
  const unsigned char * y = &x.c;  /* Should get error. */

4/29/02  .ti file should only be created when using automatic instantiation

The front end created a .ti file even when automatic instantiation was
disabled.  This has been fixed.

4/28/02  C++-generating back end: condition declaration must always
         have initializer

A condition declaration must always have an initializer, even when the
initialization is default initialization.  Now fixed.

  struct A {
    A();
    ~A();
    operator bool() const;
  };
  int main() {
    if (const A a = A()) {}
  }

4/28/02  Spurious error regarding casting away const in prototype instantiation

The front end gave a spurious error regarding casting away const
on a cast involving a pointer to a template parameter type.  Now fixed.
This error was given only in modes where prototype instantiation
is done (e.g., strict mode).

  template <class T> void f() {
    const int *p;
    static_cast<T *>(p);
  }

4/28/02  Minimal inlining: temporary must be used to pass local static

Minimal inlining has been changed so that it always uses a temporary
to pass a local static variable into an inlined call.  Without this, it
was possible for the flow of control to get back to the function
having the local variable and for the value of the variable to be
changed.

4/28/02  C++-generating back end: explicit call of destructor not qualified

The C++-generating back end was always using a qualified name for the
destructor when it put out explicit calls of destructors.  This is
incorrect when the destructor is virtual, because it suppresses the
virtual property of the call.  Now fixed (a qualified name is used
only when it is needed).

  struct A {
    A();
    virtual ~A();
  };
  int main() {
    A *p;
    p->~A();
    p->A::A~A();
  }

4/25/02  Spurious access error using template default arguments

Access checks were not done properly on default arguments of template
functions.  This could result in spurious access errors.  Now fixed.

  template<class T> void f(int = T::i);
  class A {
    static const int i = 0;
    template<class U> friend void f(int); 
  };
  template<class T> void f(int) {}
  int main() {
    f<A>();
  }

4/16/02  Size of available memory blocks displayed wrong in debug output

The computation of the amount of available space in available memory
blocks displayed in debug output was wrong, with the consequence that
the amount of memory indicated was too low.  Now fixed.

4/15/02  Qualification conversion now permitted in template argument deduction

Qualification conversions are now considered as part of the template argument
deduction process, as specified in the standard.  As a result, examples
like the following are now accepted.

  template <class T> void f(const T * const * t) {}
  int main () {
    int **p;
    f(p);
  }

4/13/02  Abort ("missing typeinfo variable") on typeid of pointer type

IL lowering aborted on generating the typeinfo variable for a typeid for
a pointer or reference type.  Now fixed.

  #include <typeinfo>
  const std::type_info *__runtime_typeinfo[] = {
    &typeid(const int *)
  };

4/11/02  C++-generating back end, prototype instantiations, ->* and .*

The operators .* and ->* were swapped in output from the C++-generating
back end for prototype instantiations of templates.  Now fixed.

4/10/02  Microsoft compatibility: use of specialized member template
         for copy-assignment

In Microsoft bugs mode the front end may now select an explicit
specialization of an assignment operator template for copy-
assignment operations.  For example:

  template<typename T>
  struct S {
    template<typename U>
    S<U>& operator=(S<U> const&);
    template<> S<T>& operator=(S<T> const&) {}
  };
  int main() {
    S<int> s1, s2;
    s1 = s2;  // Uses specialization defined above in Microsoft bugs
              // mode (instead of generated copy-assignment operator
  }           // in ANSI mode).

4/10/02  Internal error using UNC file names on Windows

An internal error could occur when using UNC file names (e.g.,
"\\sys\sharename\dir") on Windows.  This has been fixed.

4/10/02  Internal error when using preinclude and precompiled headers

An internal error would occur when using a preinclude file and
precompiled headers.  This has been fixed.

4/10/02  Internal error on using-declaration with --ignore_std

An internal error would occur on using-declaration that refers to a
member of the std namespace when the --ignore_std option was specified.
This has been fixed.

  namespace std {
    class A { };
  }
  namespace M {
    using std::A;
  }

4/10/02  Loop in overload resolution on classes that convert to each other

Faced with a case involving classes that can convert to each other
and have no normal copy constructors, the front end looped and
then crashed in overload resolution.  Now fixed (an error is issued).

  struct A;
  struct B {
    B(A);
    B() {}
  };
  struct A {
    A(A&){}
    A(){}
    A(B) {}
  };
  A source() {
    return A();
  }

4/10/02  C99 hex float constants when double and long double are the same

The routines that handle C99 hex floating point constants did not support
configurations in which long double was configured to be the same size
as double.  This required setting LONG_DOUBLE_AS_DOUBLE_IN_GENERATED_C to
TRUE on such systems.  These routines now support long double representations
that are the same size as double.

4/10/02  (*this) incorrectly viewed as dependent in prototype instantiation

In prototype instantiations of functions (done in strict mode, not
usually by default), the front end incorrectly concluded that
the expression (*this) might involve an overloaded operator* in
a real instantiation.  This is incorrect, because an overloaded
operator requires an operand of class or enum type, and this
expression's only operand has pointer type.  A consequence of this
mistake was that a call like

  f((*this).x);

was treated as dependent, unlike the supposedly equivalent

  f(this->x);

This is now fixed.

4/8/02   __INFINITY__ and __NAN__ available in all modes

The EDG extensions __INFINITY__ and __NAN__, which represent the
corresponding IEEE floating-point constant values, are now supported
in all modes, not just in C99 mode.  They are defined only when
TARG_HAS_IEEE_FLOATING_POINT is TRUE.

4/8/02   Bad expr pointer, inlining + RECORD_CONSTANT_EXPRESSIONS_IN_IL

When the RECORD_CONSTANT_EXPRESSIONS_IN_IL option is on at the same
time as IL lowering (an unusual combination), inlining may produce a
situation where a constant is copied from one function scope memory
region to another.  If the constant points to an expression, the
expression pointer must be cleared, because it can't point into the
other memory region.  The clearing is now done.  Formerly, the
failure to clear the pointer could cause an abort during an IL walk.

4/8/02   Template function with explicit arguments treated as simple function

In accordance with the proposed resolution to Core Issue 115, the front
end now treats a template function with explicit template arguments
as a simple function if the arguments are sufficient to select a
unique template function.

  template <class T> void f(T);
  int main() {
    &f<int>;  // Okay now
  }

4/6/02   Abort in copy_template_param_expr fixed

An abort in copy_template_param_expr has been fixed.  It came up
for complicated template cases, in particular ones involving
arrays as nontype template parameters in parts of names qualified
by nonreal class types, one example of which is the following:

  template <class T> struct A {
    template <unsigned int H[10]> struct N {};
  };
  unsigned int arr[10];
  template <class T> struct B {
    template<class P> typename A<P>::template N<arr> f(P);
  };
  int main() {
    B<int> b;
    b.f(1);
  }

4/4/02   explicit_cast_applied field in constant entry now set always

The explicit_cast_applied field in the IL a_constant entry is now set in
all cases (formerly, it was set only for tpck_cast constants).  It is
also now used by the C++-generating back end to eliminate certain
implicit casts in the generated code.

4/4/02   GNU C mode: Warning only on invalid uses of "inline"

In GNU C mode, declaring a variable "inline" causes the front end to only
issue a warning (rather than an error).  The keyword is ignored after the
warning is issued.

  int inline x;  /* Warning in GNU C mode; error in other modes. */

The use of "inline" in block-extern declarations of functions is treated
similarly:

  void f() {
    inline void g();  /* Warning in GNU C mode; error in other modes. */

4/3/02   Name mangling for sizeof(expression) in nontype template argument
         expression

The existing mangling code for sizeof, "sz", has been extended so that
it can deal with the case of sizeof(expression), when it has a
template-dependent type and therefore can't be represented simply
as sizeof(type).  We've chosen to use "e" instead of the type for this
case, which solves the main problem without opening another problem,
that of coming up with manglings to encode all possible non-constant
expressions (think "sizeof(delete[] x)").  This solution has the
drawback that templates that differ only in an expression under a
sizeof could potentially be mangled to the same name, which is
possibly a violation of the standard.  We'll take this up with
the standards committee to see if it's really necessary to mangle
all non-constant expressions.  This extension also applies to alignof
and uuidof.

4/3/02   Spurious "incomplete type not allowed" during automatic instantiation

Instantiations of functions and static data members are deferred while
class instantiations are in progress to ensure that the class definition
is completed before any references that might use the class are processed.
This deferral did not work properly for entities instantiated because they
were specified in the .ii file, resulting in possible spurious errors.
This has been fixed.

4/2/02   Abort in Cfront mode when redeclaring a class in its own definition

The front end used to abort in Cfront mode when processing a declaration
of the following kind:

  struct S {
    struct S;
  };

This is now fixed: the nested declaration is treated as a redeclaration of
the struct S at file scope.

4/2/02   Use of stale scope stack pointer in class_specifier

Under certain rare circumstances, a scope stack reallocation could occur
while class_specifier is executing causing a later use of a stored scope
stack pointer to be invalid.  This could result in an abort or other
incorrect behavior and is now fixed.

4/2/02  Microsoft compatibility: falling off function try block handlers

Normally, falling off the handler of a function try block for a constructor
or destructor implicitly rethrows the caught exception.  In Microsoft bugs
mode, this rethrowing does not occur.

3/27/02  GNU C mode: typedefs with sign or size modifiers

The front end now accepts the modifiers short, long, signed and unsigned
on typedef types that are synonyms for builtin integer or floating-point
types.

  typedef int Int;
  typedef unsigned Int UInt; /* Accept in GNU C and pcc modes; error in
                                other modes. */

3/25/02  Template destructor not defined with ABI < 2.38

In a copy of the front end configured with ABI_COMPATIBILITY_VERSION < 238,
in some cases a destructor in a template was not instantiated when
the destructor was only referenced from the typeinfo variable for
the class.  Now fixed.

3/25/02  Inlining: address of external routine incorrectly assumed to be
         non-NULL

The folding of constant expressions in inlining incorrectly assumed
that all routines have non-NULL addresses.  This is not true when
there is linker magic like weak externals involved.  Now fixed.

  void f(void);
  int effect;
  inline void g(void) {
    effect = f ? 1 : 2;  // Was folded, should not have been
  }
  int main() {
    g();
  }

3/24/02  Performance problem with inlining

Some performance problems with inlining have been resolved.  They
involved constructor calls in exceedingly deep class hierarchies
(e.g., depth > 100).

3/21/02  C++-generating back end, casts to dependent types in prototype
         instantiations

In some cases the C++-generating back end, when configured to
use prototype instantiations of templates to output the template
definitions, incorrectly rendered a functional-notation cast to
a possibly dependent type by placing a "class" keyword in front of
it (not allowed, because a functional-notation cast must have a
single identifier before the open parenthesis).  Now fixed.

3/20/02  How conversion functions compete with constructors

The C++ standards committee in closing core issue 243 without action
affirmed a piece of the C++ standard we weren't sure was intended,
that constructors win out over conversion functions in direct-
initializations.  Accordingly, we have changed the Front End to
follow that rule, except in cfront mode.

  extern "C" int printf(const char *, ...);
  struct B;
  struct A {
    A(B);
  };
  struct B {
    operator A() { printf("B::operator A()\n"); return A(*this); }
  } b;
  A::A(B) { printf("A(B)\n"); }
  void f(A) {}
  int main() {
    f(A(b));  // Prints A(B)
    f((A)b);  // Prints A(B)
    return 0;
  }

3/20/02  GNU C: --short_enums option

The front end now accepts the --short_enums option in GNU C mode.  It
indicates that all the enumeration types should be treated as if they
were declared with the "packed" attribute (i.e., the underlying type
should be the smallest integer type that can accommodate the enumerator
constants).

3/20/02  GNU C compatibility: parameter names in unprototyped declarations

The front end now accepts parameter names in unprototyped function declarations
that are not definitions.  A warning is issued (in strict C mode an error is
issued; in Microsoft mode, no diagnostic is issued at all).

  void f(i);  /* Accepted with a warning in GNU C mode. */

3/20/02  C++-generating back end, prototype instantiations, reference
         binding

In some cases the C++-generating back end, when configured to
use prototype instantiations of templates to output the template
definitions, incorrectly rendered the binding of a reference
to a class type to a constant, when in an actual instantiation a
conversion would be required.  Now fixed.

  template <class T> struct A {
    const A<T>&r;
    template <class P> explicit A(P) : r(37) {}  // "37" was "*37"
  };

3/19/02  Use of va_start with no ellipsis parameter

In GNU C mode, the front end now issues an error when va_start is used
in a function with no ellipsis parameter.  In other modes, a warning is
issued instead, but not if the function has no prototyped declaration.
(This is the case only in configurations with built-in support for the
va_start macro.)

  #include <stdarg.h>
  void f(int i) {
    va_list ap;
    va_start(ap, i);  /* Error in GNU C mode; warning otherwise. */
  }

3/19/02  Spurious error on qualified template-id in ctor-initializer

A spurious error was issued when a qualified template-id was used as
a base class ctor-initializer when not using implicit typename.  This
has been fixed.

  template <class T, int I> struct B {};
  template <class T> struct A : public T::template B<T,2> {
    A();
  };
  template <class T> A<T>::A() : T::template B<T,2>() {}  // error here

3/18/02  Hex floating point constants when using double as long double

When USE_LONG_DOUBLE_FOR_HOST_FP_VALUE is FALSE (i.e., when using
"double" to represent "long double") hexadecimal floating point
values (in C99 mode) for long doubles were sometimes converted
improperly, and some error cases were not detected.  This has been fixed.

3/18/02  Predefined macros on Sparc architecture

The front end now tests both the "sparc" and "__sparc" macros to determine
whether the Sparc architecture is being used (formerly only "sparc" was
tested).  When using the Sparc architecture, the "__unix", "__sun", and
"__sparc" macros are now predefined in addition to the "unix", "sun",
and "sparc" macros that were previously defined.

3/18/02  Microsoft compatibility: abort on const-qualified anonymous union

The front end used to sometimes abort in Microsoft mode when an anonymous
union was declared with a const qualifier.

  struct S {
    S(S const&);
    const union {  // Used to cause an internal error
      int p;
      float q;
    };
  };
  S::S(S const &b): p(b.p), q(b.q) {};
  
This is now fixed.

3/18/02  Sun compatibility: abort on extern "C" static function

The front end used to abort in Sun mode when a declaration of an extern "C"
static function was followed by another declaration that is also a definition.
For example:

  extern "C" {
    namespace N {
      static void f();
      static void f() {}
    }
  }

This is now fixed.

3/17/02  rvalue_expr.reference_field should produce an lvalue

A field selection that selects a field of reference type from
an rvalue class object should produce an lvalue, but the front
end incorrectly considered the result an rvalue.  Now fixed.

3/17/02  Cross-reference output on reference field selection

On a field selection of a field of reference type used thereafter
as an lvalue, the reference field was incorrectly noted in the
cross-reference output as being modified, when in fact in such
a case it's really just referenced.  The cross-reference output
is now correct.

3/14/02  GNU C: incomplete array parameter types

In GNU C mode, the front end now accepts the following code:

  void f(int x[][]) {}

Within the definition of the function, the parameter x is treated as being
a pointer to an incomplete type (e.g., it cannot be subscripted).

3/11/02  Abort on lowering of static for-init variable in extern inline

IL lowering aborted ("set_block_start_insert_location: NULL stmt")
on processing a static variable declared in the for-init clause of
a "for" statement in an extern inline function, in a configuration with
LOWER_EXTERN_INLINE set to TRUE.  Now fixed.

  inline void f() {
    for (static int i = 0;;) {}
  }

3/11/02  Checking of exception specifications on function templates

The front end now diagnoses nonmatching exception specifications when
redeclaring a function template (in strict mode).  For example:

  template<typename T> void g();
  template<typename T> void g() throw (T) {} // Used to be accepted;
                                             // now an error

3/10/02  Abort in add_dyn_init_cleanup: no temps

An abort in add_dyn_init_cleanup has been eliminated.  The abort
was provoked by binding a reference to a temporary in a
ctor-initializer that also contains an array new with a non-default
operator delete.

  struct A {
    A();
    A(int);
    ~A();
    void *operator new[](size_t);
    void operator delete[](void *, size_t);
  };
  struct B : virtual A {
    const A &r;
    A a;
    B() : a(0), r(((new A[5]), 1)) {}
  };
  B b;

3/8/02   Name mangling problem: apparent unnamed structs as template arguments

Due to a name mangling problem, pointer-to-member types that appear as
template arguments on classes with partial specializations were
sometimes incorrectly mangled.  The generated names referred to
unnamed structs instead of the pointer-to-member types.

3/8/02   GNU C compatibility: "auto" ignored in file scope

In GNU C mode, the front end ignores the "auto" specifier with a warning
when it appears on a file-scope declaration.

  auto int i;  // Warning in GNU C mode; error otherwise

3/8/02   Bad code for initialization of local static array in extern inline

The code generated by IL lowering for initializing a local static
variable having array type and partial dynamic initialization in an
extern inline function was incorrect when LOWER_EXTERN_INLINE is TRUE
(the default).  The code generated did an eok_sassign (structure
assignment) on an array.  When C code is generated, this resulted
in a compilation error.  Now fixed.

  int f() { return 0; }
  inline void g() {
    static int a[] = {f(), 0};
  }
  int main() {
    g();
  }

3/8/02   Missing error on unnamed type as class template argument

No diagnostic was issued when an unnamed type was used as a template
argument of a class template.  This has been fixed.

  template <class T> struct A {};
  typedef struct {} *a;
  A<a> x;

3/8/02   Call of non-overloaded function with dependent selector

In prototype instantiations of templates, a call of a non-overloaded
function with a selector object that is dependent was incorrectly
treated as returning a dependent type, which is not necessarily true.
This can have an effect on the resolution of surrounding calls.

  template <class T> static void f(T) { }
  template <class T> struct A {
    T g() {
      f(g());  // Formerly got error, now accepted
      return 0;
    }
  };
  int main() {
    A<int> x;
    x.g();
  }

3/6/02   Abort on attempt to inline C function with old-style declaration

The attempt to inline a call of a function declared with an old-style
parameter list in C resulted in an abort in
set_up_variable_remapping_for_inlining.  Now fixed (no inlining is
done).

  inline void f(n)
    int n;
  {}
  void g() {
      f();
  }

3/5/02   Qualified void return types in strict C mode

In strict C mode, the front end now issues an error on declarations of
functions with a cv-qualified return type.

  void const f();  /* Error: void return type cannot be qualified. */

3/4/02   Sun compatibility: default arg. in member of class template

The Sun compiler allows a default argument to be specified on the
definition of a member function of a class template that appears outside
of its class (the standard requires that such default arguments be specified
on the declaration in the class).  This is now accepted in Sun mode.

  template <class T> struct A { void f(T); };
  template <class T> void A<T>::f(T value = T() )  { }

3/4/02   Internal error in reactivate_class_scope with --parse_templates

An internal error could occur in reactivate_class_scope when doing
nonclass prototype instantiations.  The error is "pushing class
not from curr. namespace" and is now fixed.

3/4/02   GNU C: variable-length array fields of local structs

The GNU C compiler accepts variable-length array fields in local struct
declarations, which may result in size and offset computation being
delayed until run time.  However, it is common for this feature to be used
simply to indicate that the last field of a structure is a flexible array
member.  To enable the latter idiom, the front end now accepts such
declarations in GNU C mode, but it discards the given length with a
warning, and sets the length of the array to zero.  For example:

  void f(int n) {
    struct S {
      int a[n]; /* Warning: equivalent to "int a[0];". */
    };
  }

3/2/02   Virtual destructor referenced only in array delete not generated

A compiler-generated virtual destructor that is referenced only in
an array delete was not generated, if the class has a nondefault array
operator delete, with the consequence that there would be a link error
for that destructor on a version configured not to instantiate extern
inline functions.

  struct A {
    A() {}
    virtual ~A() {}
  };
  struct B : public A {
    void operator delete[](void *) {}
  };
  int main() {
    B *p = 0;
    delete[] p;
  }

3/2/02   Cast of non-class rvalue to reference to const

Explicit casts of rvalues of non-class type to a reference-to-const
type are now accepted.

  void f() {
    static_cast<const int&>(123);
  }

3/1/02   Missing typeinfo variable, class mentioned in catch type

The typeinfo variable was not defined for a class mentioned in a
catch handler type but not otherwise much used in the program, when
the class has a decider function that has to be instantiated and
no object of the class type is actually created.

  template <class T> struct C {
    virtual void f();
  };
  template <class T> void C<T>::f() {}
  int main() {
    try {
    } catch (C<int> *) {
    }
  }

3/1/02   "called" flag in IL routine not set for call of static function
         with discarded object

The "called" flag in the IL a_routine entry is supposed to be set if
the routine is called anywhere.  It was not being set for calls of
static functions of the form

  object.f()

i.e., calls that specify an object that is simply discarded.
The flag is now set correctly.

2/28/02  Storage class incorrect for specialization of static template

An explicit specialization should have the same linkage as an implicit
specialization.  When a static template was explicitly specialized, the
specialization was incorrectly given external linkage.  This has been fixed.

  template<typename T> static void f(T);
  template<> void f<int>(int){}

2/27/02  Incorrect keep_in_il flags, IL write/read error

The maintenance of needed flags, in particular the keep_definition_in_il
flag on routines, had a small flaw which could cause an inconsistent
IL tree, which could result in an IL write/read error (but is
probably harmless otherwise).  In a rare case involving a default
argument expression that is the only reference to a routine, and
which is never used in the compilation, and in which the routine with
the default argument is called (without using the default argument)
from a function that is lowered immediately, there ensued a
situation where the routine had keep_definition_in_il but not
definition_needed set before the body of the routine was processed.
This is okay (though unusual), but the definition is supposed to be swept
appropriately once it shows up, and that didn't happen in this case.
Now fixed.

2/27/02  Display of backslashes in error messages

When a file name contains backslash characters (typically as a directory
separator on Windows) the backslashes would be escaped if the file name
was used in a diagnostic message, resulting in a double backslash in the
diagnostic output.  This has been fixed.

2/27/02  Microsoft compatibility: inline flag of in-class specializations

When a function is specialized using a Microsoft in-class specialization,
the inline flag was not set properly.  This has been fixed.

  template<class T> struct A {
     template<int I> void f(void);
     template<> void f<1>(void){}  // now marked as inline
  };

2/26/02  C99, GNU C mode: lowering of bool increment/decrement

In C99 mode and GNU C mode, when a bool value is incremented or
decremented it should be set to 1 (true) or 0 (false), respectively.
The lowered code for those cases now does that.

2/25/02  LONG_DOUBLE_AS_DOUBLE_IN_GENERATED_C: no "L" suffix on constants

When the LONG_DOUBLE_AS_DOUBLE_IN_GENERATED_C option is enabled,
"long double" is put out as "double" in the C-generating back end.
One nit that was not done correctly: long double constants should not
have the "L" suffix -- they should be double constants, with no suffix.
Now fixed.

2/23/02  Microsoft compatibility: overload resolution, template constructors

MSVC++ has some quirks related to overload resolution involving
template copy constructors.  These quirks are slightly different
in MSVC++ 6 and MSVC++ 7.  They are now emulated in the appropriate
mode.

  extern "C" int printf(const char*,...);
  struct function2 {
    function2() {}
    template<typename Functor>
    function2(Functor&) { printf("in function2 template ctor\n"); }
  };
  int main() {
    function2 f1;
    function2 f2(f1);  // Chooses the generated copy constructor in
                       // Microsoft bugs mode
  }

2/22/02  Precompiled header processing problem when DEBUG == 0

Compilations that make use of a precompiled header file may fail when
the compiler was built without DEBUG code.  This has been fixed.

2/19/02  Problem setting DEFAULT_DEPENDENT_NAME_PROCESSING to TRUE

Setting DEFAULT_DEPENDENT_NAME_PROCESSING did not have the intended
effect because it did not also result in the setting of
nonclass_prototype_instantiations, which is a prerequisite of doing
dependent name processing.  This has been fixed.

2/18/02  Name hiding by template parameters

The hidden name table used to not record name hiding by template parameters.
This would e.g. cause the C++-generating back end to not correctly regenerate
the following example:

  class T {};
  template<typename T> class List {
    ::T x;  // C++-generating back end rendered this as "T x;"
  };

This is now fixed.

2/18/02  Microsoft compatibility: overload resolution, reference versus
         non-reference

An idiosyncrasy of MSVC++ overload resolution related to comparing two
parameters when one is a reference and the other is not (see Changes
entries of 9/11/97 and 12/5/98) has been fixed in MSVC++ 7.0.  Therefore,
the EDG front end now disables that quirk when the Microsoft version
indicates 7.0 or above.

2/14/02  Demangling of template member addresses in nontype template arguments

A bug in demangling for nontype template arguments that are the address
of a member that is a template instance has been corrected.  An example
of a name that was not demangled correctly is

__dt__73CT7__tm__62_XCPFSc_Sc50mt1__tm__3_Sc__Q2_2N127CT6__tm__16_XCPFSc_\
                                                                     Sc3tf11BFv

2/13/02  Incorrect instantiation file suffix list on Windows

When the front end is built with the __MICROSOFT_OS__ macro set, the
DEFAULT_INSTANTIATION_FILE_SUFFIX macro contained some null file
suffix entries which could result in the front end using a file with
no suffix as an implicitly included template definition file (this
would only occur if implicit inclusion was enabled).  This has been
fixed.

2/13/02  __ALIGNOF__ no longer requires parentheses around argument expressions

The __ALIGNOF__ (or __alignof__) operator now more closely matches the
standard sizeof operator in that it can be followed by an expression that
is not parenthesized.  For example:

	int a = __ALIGNOF__ a;

This change makes the __ALIGNOF__ extension more compatible with similar
extensions in other (non-EDG) front ends.  (See also Changes entry of 9/10/01.)

2/13/02  Instantiation of function used in pointer to member in default
         argument

Functions used in pointer-to-member references in a default argument
expression are now marked to be instantiated when the default
argument is used.  The following example got an instantiation loop
before this fix.

  template <class T> struct A {
    void f();
  };
  template <class T> void A<T>::f(){}
  void f(int i = (&A<int>::f,1)){}
  template <class T> void g(T) {
    f();
  }
  int main() {
    g(1);
  }

2/13/02  "new" of nonreal class in prototype instantiation

In some cases, a "new" of a nonreal class processed inside a prototype
instantiation of a template was not processed properly.  Aborts
were possible on certain configurations.  Now fixed.  This happened
only when prototype instantiations were done, i.e., in strict mode
or with --parse_templates.

A similar problem also existed with "delete" operations, also now fixed.

2/12/02  RECORD_CONSTANT_EXPRESSIONS_IN_IL: parenthesized constants

When RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, an expression is now
recorded for a constant that is parenthesized.  That gives access
to the source start/end position for the constant itself and also for the
parenthesized form.

Also, a change was made in the C++-generating back end to put parentheses
around such expressions when they are put out.

2/12/02  Sun compatibility: static friend function declarations

In Sun mode, the front end now accepts a "static" specifier in the declaration
of a friend function with internal linkage.  The specifier must precede the
keyword "friend".

  struct S {
    static friend void f1();  // OK in Sun mode
    friend static void f2();  // Error
  };

2/12/02  Function declarations involving types with no linkage

The front end now more consistently diagnoses function declarations that
involve types with no linkage.  Previously, cases involving typedefs of
unnamed const-qualified types were not diagnosed in configurations where
CFRONT_OBJECT_CODE_COMPATIBILITY is TRUE.

  typedef const enum { e1 } E;
  void func(E *e) {}  // Error in strict mode; warning in default mode.

2/9/02   Order of classes on routine befriending_classes list in IL

Since some time in 1995, the befriending_classes list of a routine in
the IL has been maintained so that if the routine is defined in a
friend declaration, the class in which the friend declaration appears
is first on the befriending_classes list.  It turns out that we haven't
used this property since shortly after we instituted it, so the extra
code to do the list maintenance has been removed.  (This is motivated
by the fact that we did not want to add more code to maintain this
property in multi-translation mode when IL from secondary translation
units is copied to the primary IL.)

2/7/02   Visibility of declarations designated by member using-declarations

When checking the visibility of member using-declarations, the front end did
not properly handle overload sets resulting from a mix of ordinary member
functions and using-declarations. E.g., a spurious error was issued for the
following example:

  struct A {
    int f(int n) { return 1+n; }
  };
  struct B: A {
    int f(unsigned int n) { return 3+n; }
    using A::f;
  };
  struct C: B {
    using A::f;  // A::f visible in direct base class B: OK.
  };

This is now fixed (i.e., no error is issued for the above example anymore).

2/7/02   Limiting the amount of instantiation context output in diagnostics

In certain cases, the context information provided for errors during
template instantiations can become very lengthy.  In many cases much
of the context information is unnecessary.  The front end now provides
a mechanism to limit the volume of context output.  The "context limit"
is the maximum number of context entries to be displayed as part of
a diagnostic message.  The default is provided by the DEFAULT_CONTEXT_LIMIT
macro and may be overridden with the --context_limit command-line option.
A value of zero is used to indicate that there is no limit.  If the number
of context entries exceeds the limit, the first and last N context
entries are displayed where N is half of the context limit.  The following
is an example of the output when a portion of the context is suppressed
using --context_limit=2.  The default limit is 10.

          detected during:
            instantiation of "void f(T) [with T=int ***]" at line 4
            [ 20 instantiation contexts not shown ]
            instantiation of "void f(T) [with T=int]" 


2/6/02   Abort on inlining in C99 mode, with block extern

In certain cases in C99 mode, a call of an inline function made in
the presence of a compatible but not identical block extern
declaration provoked an abort.  Now fixed.

  inline int g(int a, int b) { return a + b; }
  int f(void) {
    int g();
    return g("test");
  }

2/6/02   Field selections instead of casts for lowered base class accesses

IL lowering has been changed slightly so that whenever possible it uses
a field selection to get to a base class within a larger object.
This restores the code generated prior to the addition of the
optimization for empty base classes (see Changes entry of 8/9/99).
After that change, and until now, a base class at offset zero
was accessed by simply casting the pointer to the new type.  One
customer complained that this made it more difficult to optimize
the accesses, so we have restored the old field-selection code.

2/6/02   Missing typeinfo for base class at link time

In some strange cases involving a base class, none of whose member
functions are defined, and a derived class, whose decider function
is defined, but for which no object of the class type is created,
a typeinfo variable for the base class was not emitted even though
it is referenced from the typeinfo for the derived class, which is
referenced from the virtual function table for the derived class.
The problem is fixed, by forcing the definition of the typeinfo
and virtual function table variables for the base class also.

2/6/02   C++-generating back end, MSVC++ output: no leading "::" in selection

The MSVC++ compiler (versions before 7.0) does not accept a leading "::"
following a field selection "->" or ".".  When MSVC is the generated
code target, and the Microsoft version is less than or equal to 1200,
the C++-generating back end now avoids generating such qualifiers.

  struct one {
    bool func();
  };
  struct two : public one {};
  struct three : private two {
    bool func() { return(one::func()); }  // Output now okay for MSVC++ 6
  };

2/6/02   Abort in add_dyn_init_cleanup: no temps

An abort in add_dyn_init_cleanup in IL lowering has been fixed.
It came up for use of a non-default operator new in an aggregate
initializer for a global array of a class type having a destructor,
with exception handling enabled.

  struct A {
    A();
    ~A();
    A(int);
    void* operator new[](unsigned int) throw ();
  };
  static A x[5] = { (new A[100], 0) };

Another similar example involving a temporary whose lifetime is
extended by binding it to a reference, also fixed:

  struct A {
    A();
    A(int);
    ~A();
    void *operator new[](unsigned int);
  };
  int main() {
    const A &r = (new A[3], 1);
  }

2/5/02   Command-line option to allow long long in strict mode

Except in C99 mode, the use of long long results in a diagnostic in
strict mode.  The --long_long option can now be used to override this
behavior so that code that uses long long can be compiled without
diagnostics in strict mode.  The --long_long option must follow
the strict mode option on the command line.

2/5/02   Error on taking the address of an assignment to a bit field

An error is now issued in C++ on attempting to take the address of
an assignment to a bit field.  Since the result of the assignment is
an lvalue for the bit field, allowing taking its address allows taking
the address of a bit field.

  struct S { int a:3; int b:3; int c:3; };
  void f() {
    struct S s;
    const int *p = &(s.b = 0);
  }

2/3/02   No breaking of long strings in #pragmas

Long strings that appear in #pragmas (e.g., #pragma ident) are no
longer broken into multiple strings if they exceed 128 characters.

2/2/02   Problem with unnamed enums and list of nontag types used in
         exception handling

The front end builds a list of nontag types used in exception handling
and RTTI contexts, so it knows what type_info structures to generate.
The construction of this list did the wrong thing with unnamed enums,
which could have disastrous consequences later.  A throw of a variable
whose type is an unnamed enum, for example, could cause an abort.
Now fixed.

  enum { e1 } e;
  struct A { int i; } a;
  int main () {
    a.i = 1;
    throw e;
  }  

2/1/02   Mangled names for type-as-subobject structs, possible abort

The generation of mangled names for the type-as-subobject structs
generated by IL lowering (a) has the possibility of aborting on
names that are long enough to require compression, and (b) included
the parent name information more than once.  The abort is fixed, and
the duplicate parent information has been eliminated.  This results
in different mangled names, but these names are internal to a
compilation, so there is no ABI change.

2/1/02   Extra names visible in the presence of using-directives

In certain very complex cases involving namespaces and template
instantiations, names are visible that should not be.  This could result
in spurious ambiguity errors or improper overloading.  This is now fixed.

1/31/02  Reference to bit field, with side effects, as discarded lvalue

In a case where an expression statement names an lvalue and then does
nothing with it, the lvalue is not converted to an rvalue.  IL lowering
converts it to some kind of rvalue in C.  In cases that involve
a bit-field reference at the top and a side effect somewhere below
that, this transformation was not done correctly, with the
consequence that an eok_bit_field operator appeared in an rvalue
context in the IL.  The C-generating back end aborted on that, and
other back ends might also have had trouble with it.  Now fixed.

  struct A {
    int i:1;
  };
  A *f();
  int main () {
    A *p;
    p->i;
    f()->i;
  }

1/31/02  Abort in IL lowering with empty base and virtual base

In some rare situations involving a trailing nonvirtual empty base class,
a nonvirtual base class with virtual functions and a virtual base class,
the front end would generate a nonstandard layout for the derived class
type on some configurations.  That layout would cause the IL lowering code
to abort.  The following is a minimal example:

  struct E {};
  struct V {};
  struct P: E, virtual V { virtual ~P() {} };
  struct D: P, E {};

1/30/02  Template deduction and ambiguous base class deduction

Template argument deduction can deduce T in Base<T> from a derived
class that has a Base base class.  The standard requires that deduction
succeeds if there is only one such conversion possible.  The front end
failed to detect this ambiguity and would choose one of the possible
template argument values.  This has been fixed.

  template<class T> class A {};
  class B : public A<int>, public A<char> { };
  template<class T> void f(A<T>) { }
  int main(void) {
    B b;
    f(b);  // now ambiguous
  }

1/30/02  Template arguments and abstract classes

When evaluating explicit template arguments, an attempt to create an
array of abstract class type should cause argument deduction to fail.
This is not currently specified in the standard but has been raised
as a core language issue.  The front end now enforces this rule.

  template <class T, int I> void f(T (*p)[I]){}  // #1
  template <class T, int I> void f(int i){}  // #2
  struct A { virtual void f() = 0;};
  int main() {
    f<A,5>(0);  // should call #2
  }

1/30/02  Address of static member of current class is dependent in
         prototype instantiation

The address of a static member (data or function) of the current class
should be considered dependent in a prototype instantiation of a
template.  Now, it is.  Without this fix, the front end did not
correctly recognize template classes having nontype template
arguments that are the address of a static member as being nonreal
classes, and this could cause aborts (e.g., IL write/read errors)
later.  The following test case aborted in the C++-generating
back end version when compiled in strict mode:

  namespace NN1 {
    template <int* ip> struct E {
      E();
      static int s1;
      void ff1();
    };
    template <int* ip> E<ip>::E() {
      E<&s1>().ff1();
    }
  }

1/30/02  Spurious error when conversion template appears in a deeply nested
         namespace

A corrupted scope stack pointer could be used when processing the definition
of a conversion operator that is a member of a class template when the
enclosing class is deeply nested within namespaces.  This would usually
result in a spurious "template argument list must match the parameter
list" error on the definition.  This has been fixed.

namespace N1 { namespace N2 { namespace N3 { namespace N4 { namespace N5 {
namespace N6 { namespace N7 { namespace N8 { namespace N9 { namespace N10 {
namespace N11 { namespace N12 { namespace N13 { namespace N14 { namespace N15 {
template <class T> struct A {
  operator int();
};
template <class T> A<T>::operator int(){}
} } } } } } } } } } } } } } }


1/29/02  Repeated friend declarations (IL Change)

The front end used to avoid duplicates in the representation of friend
declarations.  For example:

  class X {
    friend class F;
    friend class F;  // Used to be ignored (with a remark)
  };

For the above example, the IL now records class F twice as a friend of class X
and class X appears twice on the list of class befriending class F.  A remark
is still emitted.  (Friend function declarations are treated in a similar way.)

1/28/02  Error recovery abort on invalid nested class of class template

An abort could occur during the fixup processing for a member of a
nested class of a class template if the nested class declaration was
invalid in some way.  This has been fixed.

  template <class T> struct A { 
    struct A {  // invalid -- same name as enclosing class
      int f() { return 0 ; } 
    };
  };

1/26/02  C++-generating back end: calls to functions only declared as friends

In Microsoft mode, functions only declared as friends are visible in the
namespace scope surrounding that friend declaration.  As a result, such
functions can be referred to using qualified names.  For configurations
that accept Microsoft extensions (MICROSOFT_EXTENSIONS_ALLOWED is TRUE)
but generate C++ code for compilers that do not visibly inject friend
declarations in the surrounding namespace, a new configuration option
TARG_CPP_COMPILER_DOES_NOT_VISIBLY_INJECT_FRIEND_NAMES is now available
to force the use of unqualified names to refer to functions only declared
as friend functions.

1/26/02  Name mangling performance improvement

The name mangling code in lower_name.c has been reworked (again)
to fix a performance problem.  Instead of generating some mangled
names twice -- once to get the size, and then again for real --
it now leaves extra space for the lengths and then removes the
unneeded extra characters at the end of processing.

1/23/02  Microsoft compatibility: __super keyword

The Microsoft __super keyword is accepted in Microsoft mode.

  struct A {
    void f(int);
  };
  struct B {
    void f(short);
    void f(char);
  };
  struct C : A, B {
    void f(short) {
      __super::f(1);    // calls A::f(int)
      __super::f('x');  // calls B::f(char)
    }
  };

1/23/02  va_start may take the address of a given parameter

Many implementations of va_start take the address of the parameter passed to
it.  The front end now sets the address_taken flag of such a parameter when
the new configuration variable BUILTIN_VA_START_TAKES_ADDRESS_OF_VARIABLE
is TRUE (which is its default value).  This is only applicable in
configurations with builtin support for the va_start macro.

1/22/02  va_arg type should not be promotable

In configurations with builtin support for the va_arg macro (e.g., when
DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE is TRUE), the front end
now issues a diagnostic (an error in GNU C mode, a warning otherwise) if
the type passed to va_arg would have been promoted to another type when
passed through a variable argument list.

  void f(int n, ...) {
    va_list ap;
    va_start(ap, n);
    va_arg(ap, char);  /* Error or warning: a char would have been promoted */
                       /* to an int */
    va_arg(ap, int);   /* OK. */
    va_end(ap);
  }

1/22/02  Spurious error on sizeof of template-dependent type

When "implicit typename" is enabled for templates (not in strict
mode, but typically in default mode), there are some cases where
a construct that could be a call was seen instead as a function type
when it appears in a sizeof in a template.  This is additionally
confusing because the construct is properly scanned as a call in
strict mode (in that mode, without "implicit typename", the reference
is taken to be to a non-type because typename is not specified).
Now fixed.

  template <class T> struct ConversionHelper {
    static T MakeT();
  };
  template <class T> struct Conversion {
    enum { exists = 1 == sizeof(ConversionHelper<T>::MakeT()) };
  };

1/20/02  IL walk routines: separate remap routine for list pointers

The IL walk routines (il_walk.c, walk_entry.h) have been changed so
that there are now two pointer-remapping routines (optionally) used
during the walk process.  The new one is used for list pointers,
i.e., "next" pointers and start-of-list pointers.  The calling
sequences of some of the top-level routines (e.g., walk_file_scope_il,
walk_routine_scope_il) have been changed by adding a parameter for
the new remapping function.  The list pointer remapping routine is
generally the same as the normal one, but having two routines allows
them to be different if necessary.

1/18/02  Mangling of virtual function table names for ambiguous base classes

The name mangling for virtual function tables for ambiguous base classes
has been changed in some cases: the "__A" suffix now sometimes has a
number following it to distinguish multiple ambiguous base classes with
the same name.  The demangler has been changed to demangle such names.

1/17/02  Abort in IL lowering for "new" of array of pointer-to-member

An abort in new_or_delete_type_requires_array_handling which occurred
when doing IL lowering on a "new" of a type that is an array of 
pointer to member functions has been fixed.

  class A { };
  typedef bool (A::*TFP)();
  TFP *tp1 = new TFP[1];

1/15/02  Microsoft compatibility: __if_exists directive

The __if_exists and __if_not_exists directives are now recognized in
Microsoft mode.

1/14/02  Indirect flexible array members in C99 mode

The default C99 mode of the front end now accepts structure definitions whose
last field has a struct type containing a flexible array member.  For example:

  struct F { int i; int a[]; };
  struct S {
    int n;
    struct F f;  /* Now accepted in default C99 mode. */
  };

This is still an error in strict C99 mode.

1/14/02  Microsoft compatibility: type definitions in function return types

In Microsoft C++ mode, the front end now accepts type definitions in function
return types.  For example:

  struct S { enum T { yes, no, maybe } answer(); };

1/10/02  Abort on ambiguous conversion template reference

An abort could occur on an explicit call of an ambiguous conversion template
when the class in which the lookup is done is different from the class
in which the conversion function is declared, and the two classes have
different template parameter lists.  This has been fixed.

  struct Z { } ; 
  template < class T > struct A { 
    template < class S > operator S () { return S () ; } 
  }; 
  template <class T1, class T2> struct B : public A<T1>, public A<T2> { } ; 
  int main() {
    B<int, char> b;
    b.operator Z ();
  }

1/6/02   Removal of unneeded entities, default arguments in pointers to
         functions

It's possible though unusual to declare a pointer-to-function variable
with a function type that has default arguments that involve destructible
temporaries.  When such a declaration is removed because it is unneeded,
in a version configured with source sequence entries, the removal was
not done properly and the resulting IL was inconsistent, which could
cause -- among other problems -- an IL write-read abort.

  struct A {
    A();
    ~A();
    operator int();
  };
  static int (*pf)(int = A());

1/4/02   Missing instantiation of destructor referenced only in default
         argument

Destructors that are referenced only in default arguments were
not instantiated, which resulted in link errors in some cases.
This is a problem introduced by the change of 10/8/00 to delay
instantiations in default arguments until a use of the default
argument.  There was also a similar problem with constructors
referenced only in a "new" operation.

1/3/02   Semantic analysis of friends of class templates

The standard currently specifies that semantic analysis of a friend
function defined in a class template is done when the enclosing class
is instantiated, even if the friend function is never used.  Most
implementations, however, defer such analysis until the function is
used.  As a result, there is a body of code that requires such
deferral to compile.  We believe that the standard should be revised
to require such deferral and have changed the front accordingly
pending consideration of the issue by the standard committee.  This
was formerly done only in Microsoft mode.

  template <class T> struct A {
    friend void f(A a) {
      g(a);
    }
  };
  
  A<int> ai;

1/1/02   C++-generating back end, prototype instantiations: cast to reference

In some cases, the code generated by the C++-generating back end for a
cast to a reference type within a prototype instantiation of a template
was incorrect (it rewrote the cast as a cast to a pointer type, which
incorrectly applied a "&" address-of operator to the operand).

  struct A {};
  template <class t> struct X { int i; };
  template <class T> struct B {
    typedef X<T> TT;
    TT f();
    int f(int);
    void g() {
      int j = ((const TT &)(f())).i;  // Generated code was incorrect
    }
  };

12/26/01 Mechanism to insert strings into the token stream

A mechanism has been provided that may be used to insert a string, that
is interpreted as a sequence of tokens, into the token stream processed
by the front end.

The function insert_string_into_token_stream is used to access this
mechanism.  The tokens may be inserted before or after the current token.

12/25/01 Microsoft compatibility: lvalue cast that drops cv-qualifier

A previous change (see entry for 1/17/00) emulates MSVC++ in
allowing a cast that drops cv-qualifiers to remain an lvalue, as in

  int i = 1;
  const int j = i;
  (int)j = 2;  // Allowed by MSVC++

It turns out that MSVC++ doesn't interpret this as an lvalue cast
if the entity being cast is a constant-valued variable, as in

  const int j = 0;
  (int)j = 2;  // Gets error from MSVC++

(See related change 11/18/01 for the "?" operator.)  This is now
emulated more accurately, which avoids strange generated C or C++
output for cases like

  const long MMM = 3;
  long x = (long)MMM;

Also, the code that converts lvalues to rvalues now recognizes this
Microsoft case as a form of lvalue cast and produces the IL that would
have been produced by a standard rvalue cast.

12/19/01 Funny IL for compound literal in local static initializer, with
         RECORD_CONSTANT_EXPRESSIONS_IN_IL

When RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE (e.g., with the
C++-generating back end), the IL for a compound literal in the
initializer of a local static variable had a constant in the function
scope memory region that pointed to an expression that was (partly)
in the file scope memory region.  This was not wrong, strictly
speaking, but it was surprising and unintentional, and has been
corrected (by eliminating the expression for the constant, which
doesn't make sense in this case).

12/19/01 Improper setting of is_local_to_function flag

Under certain very unusual circumstances the is_local_to_function flag
could be set incorrectly for a class template specialization.  This
could result in incorrect mangled names.  Now fixed.

12/18/01 Abort in corresponding_base_class with deep ambiguous inheritance

In some situations involving an ambiguous base class that is itself derived
from an ambiguous base class, the front end issued an internal error when
attempting to reference a member of the deepest ambiguous base class.
For example:

  struct V {};
  struct A: virtual V { int x; };
  struct B: A {};
  struct C: B {};
  struct D: B, C {};
  void f(C *p, D *q) {
    int r = p->x;
    q->x = 2;  // Used to trigger an internal error in
  }            // "corresponding_base_class".  Now an ambiguity is reported.

This is now fixed.

12/18/01 New-expression mistaken for explicit specialization in template

Under certain circumstances involving a new expression using an elaborated
class name (i.e., "new class X" or "new struct Y") in a template, the front
end erroneously reported an error that an explicit specialization could not
appear where the new-expression was written.  The following example, when
compiled with -tused, illustrates the problem:

  template<typename T> struct S {
    S() { new class C; }  // "class C" mistaken for a specialization
                          // declaration
    class C { T *p; };
  };
  void f() { new S<int>(); }

This is now fixed.

12/17/01 C++-generating back end: "extern" on const variable definition

The C++-generating back used to systematically emit an explicit "extern" on
definitions of const variables with external linkage.  However, that turns a
definition into a declaration if the variable definition does not include an
initializer.  For example:

  struct S {};
  extern const S c;  // Declaration.
  S const c;         // Definition: used to be rendered "extern const S c;"
                     //             which is not a definition anymore.

This is now fixed.

12/15/01 Spurious warning on use of template template parameter

A spurious "template parameter not used" warning was sometimes issued
when a template template parameter was used as a template template
argument of a class template in a function template declaration.  This
has been fixed.

  template <template <class> class T> struct A {
    A(){}
    template <template <class> class T2> void f(A<T2>&){}
    template <template <class> class T2> A(A<T2>&){}  // warning here
  };

12/13/01 Spurious conversion template ambiguity

A derived class conversion template should hide a base class conversion
template when both templates convert to the same type.  This hiding did
not work properly when the templates involved had different template
nesting depths (i.e., when the number of template parameter lists
that are visible differed).  This would result in a spurious ambiguity
and is now fixed.

  template <class X> struct A {
    template <class T> operator T();  // template nesting depth of 2
  };
  struct B : public A<int> {
    template <class T> operator T();  // template nesting depth of 1
  };
  int main() {
    int *i = B();
  }

12/12/01 Incorrect IL after lowering of file-scope initialization

In some cases involving IL lowering of an initialized global-scope
or namespace-scope variable whose initializing expression creates
a class temporary by calling a constructor, a necessary copy of
IL did not correctly unlink the old expression from the IL tree.
As a consequence the object lifetime tree could contain an unlowered
dynamic initialization for the variable.  This could cause an abort,
e.g., an IL write/read error, especially if the constructor is
inlinable and is removed from the IL tree because all references
were expanded inline.

12/9/01  Microsoft compatibility: (void *)1 allowed as case label constant

MSVC++ allows integral constants cast to pointer types as case label
constants, as in

  case (int *)2:

These are now accepted by the C++ Front End in Microsoft mode, with a
warning.

12/9/01  No function-to-pointer conversion on second operand of comma
         operator

In C++ mode, the front end used to force the function-to-pointer
conversion on the second operand of a comma operator.  This was
incorrect and is no longer done.

  void f(void);
  void (*fp)(void);
  typedef void (FTYPE)(void);
  void x(void);
  void h(int n) {
    FTYPE &fr = (x(), f);
  }

12/9/01  Error recovery, constructor that copies own class by value

An error is correctly issued for a constructor that copies its
own class by value.  However, if an out-of-class definition of
the constructor appears, and there is also a user-declared
copy constructor, the error recovery on future copies of the class
fails and that results in an abort in determine_dynamic_init_for_class_init.
Now fixed.

  struct Z {
    Z(Z);    // Error
    Z f();
    Z(const Z&);
  };
  Z::Z(Z) {} // Error again
  Z Z::f() { return 0;}  // Abort

12/8/01  Abort on unreachable code at end of destructor

The front end aborted in some cases on a destructor that has unreachable
code at the end of the top-level block.  Now fixed.

  struct B {
    ~B() { throw 1; {} }
  } b;

12/8/01  Handling of rethrow, lowering and unordered expressions

In two places in the front end, now fixed, the IL for a throw with
no expression (a "rethrow") was not correctly handled, which could
result in very rare cases in a dereference of a null pointer,
in examine_expr_for_unordered_temp_inits or mark_expr_slice_dyn_inits.

12/4/01  Spurious error on typedef to base class member

A spurious error was issued on a typedef of a base class member named as
a member of the current class and given the same name in the derived class.
This has been fixed.

  template <class T> struct A : public T {
    typedef typename A::X X;
  };

12/4/01  Dependent base class lookup when not doing dependent name processing

A variable has been added to make it possible to do the base class portion
of dependent name lookup without enabling full dependent name processing.
Some compilers (e.g., g++) do use the standard rules for lookup of dependent
base class members even though they don't fully implement the dependent
lookup rules.  This provides a means to emulate that behavior.  The variable
is named force_dependent_name_rules_for_base_class_lookup.

  class A {
    typedef int X;
  };
  template <class X> struct B {
    struct C : X {
      C(){}
      C(X x) {}
    };
    C c;
  };
  B<A> b;

11/30/01 Change in behavior of -H (list included files) option

Formerly, the -H option (list included files) would cause the front end
to do preprocessing only.  It appears that most compilers, however, do
full compilation when the -H option is used.  We now do full compilation
when the -H option is used.  The output, which used to be directed to
the preprocessed output file (which defaults to standard output) is now
sent to standard error (because that is what other compilers seem to do).

11/28/01 Reduced IL prefix memory use when using 8 byte alignment

When HOST_ALIGNMENT_REQUIRED is 8 bytes, but the alignment required for
pointer and certain structures is less than 8 bytes, the IL prefix was
larger than necessary.  This has been fixed by providing new configuration
macros named HOST_POINTER_ALIGNMENT and HOST_IL_ENTRY_PREFIX_ALIGNMENT.
These macros permit components of the IL prefix to be allocated using only
the alignment actually required by each component.  The default value of
these macros should be correct on most systems, but may require adjustment.

When CHECKING code is enabled, the values of these macros are tested during
the initialization of the front end.  If they are not set correctly, an
internal error is issued.  Checking code is also now provided for the
HOST_ALIGNMENT_REQUIRED macro.

11/27/01 --sun rejected when Microsoft mode is the default

When Microsoft mode is enabled by default, the front end would issue
an error if the Sun mode option was used.  The --sun option now disables
Microsoft mode.

11/25/01 Abort after error in "?" in Microsoft mode

In some cases, in Microsoft mode, there could be an abort in
take_address_of_lvalue after an error on the second operand
of a "?" operator.  Now fixed.

  int global;
  void f() {
    int i=3;
    char *cp=(char*)0;
    i=cp ? i:: :global;
  }

11/19/01 Abort while computing overriding virtual functions

The front end used to abort under certain circumstances involving virtual
functions defined both in a base subobject of a virtual base subobject and
in a subobject derived from that virtual subobject.  For example:

  struct S0 { virtual void f(); };
  void S0::f() {}
  struct S1: public S0 {};
  struct S2: public virtual S1 { virtual void f(); };
  void S2::f() {}
  struct S3: public S2 {};
  struct S4: public S2 {};
  struct S5: public S3, public S4 {};  // Internal error while establishing
                                       // that S2::f overrides S0::f.

This is now fixed.

11/19/01 Setting EH cleanup state at epilogue label in destructors

The exception handling cleanup state is now set after epilogue labels
in destructors even if there are no members or bases to destroy,
in partial-eh-lowering configurations (DO_FULL_PORTABLE_EH_LOWERING
set to FALSE).

11/18/01 Microsoft compatibility: const var as operand of "?" operator

A previous change (see 11/14/00 entry below) dropped cv-qualifiers
on operands of "?".  It turns out MSVC++ doesn't do this when the
operand is a const-valued variable.  The behavior has been adjusted 
to match MSVC++.

  const int n1 = 1000;
  const int n2 = 1000;
  const int n3 =  0 > 1 ? n1 : n2;
  int x[n3];  // Formerly got an error in Microsoft mode

11/18/01 Memory region problem with use of const local var in nontype
         template argument

When the prototype instantiation of a function template is done (e.g.,
in strict mode), a use of a local const variable in a nontype
template argument resulted in some cases in the use of a data structure
whose storage had already been freed.  Now fixed.

  template <int I> struct A {};
  template<class T> void f() {
    const int n = sizeof(T)+1;
    A<n> x;
  }  // Later use of A<same-value> could cause reference to freed memory

11/17/01 Setting of "system_include_dir" for primary include search directory

In most configurations, the include search path is updated to include the
directory containing the current include file.  The "system_include_dir"
flag for the primary include search directory is now set based on the
value of the flag for the directory in which the current include file
was found.

11/16/01 Microsoft compatibility: abort caused by lookup emulation bug

In Microsoft mode, an abort could occur when a template name is used
in a derived class and the base class contains an overload set in which
one of the members is a nonstatic member function template with the
same name.  This has been fixed.

  template <class T> struct x {};
  class A {
    void x(int);
    template <class X> void x(X);
  };
  class B : public A {
    typedef x<int> xi;  // Microsoft compiler finds template ::x
  };

11/16/01 "this" as selector doesn't make call dependent

Overload resolution has assumed that a member function called on
the basis of the "this" parameter of the current (template) function
is dependent, which appears not to be correct with the revised
definition in TC1.  Such calls are no longer considered to be
dependent merely because of the selector.

11/15/01 Incorrect scope stack state in certain nested instantiations

Under certain unusual circumstances involving nested instantiations
the scope stack state was not maintained correctly.  This could cause
the nesting depth of template parameters to be assigned incorrectly,
and could cause other problems such as spurious errors concerning
the redeclaration of template parameters.  The incorrect nesting
depths could, in turn, cause various kinds of incorrect behavior.  In
one example it resulted in a spurious ambiguity on the call of a
conversion template.  The scope stack state problem has been fixed.

11/14/01 Raw listing output problem with comment inside macro call

The raw listing output line produced for a // comment inside a
macro argument list was incorrect (it did not match the source
line).  Now fixed.

  #define WRITE_REG(a, b) a, b

  void display_out_setup()
  {
    WRITE_REG(1,
  // comment
       0
    );
  }

11/14/01 Line synchronization problem with preprocessing output and
         inert macro alone on line

In cases where preprocessed output is being generated and the name
of a function-like macro appears alone on an input line, with no
opening parenthesis on the following line, the preprocessed output
was incorrect in that line synchronization was thrown off.  Now
fixed.

  #define A()
  line 2
  A              // Output after this line was out of sync
  line 4
  line 5

11/13/01 Final set of cleanup state in constructors and destructors

The code to set the final cleanup state ("nothing left to clean up")
in a constructor or destructor was sometimes omitted.  Ordinarily,
this is not a problem (and can even be viewed as an optimization),
but in versions that do inlining of routines with exception-handling
code, and in versions where the cleanup state instruction is used to
fill a program-address-based table of cleanup states, the omission
might be a problem.  The cleanup state instruction at the end is now
generated in versions that have DO_FULL_PORTABLE_EH_LOWERING set to FALSE.

11/12/01 db_opt and db_name pragmas

Pragmas have been added that can be used to specify debugging options as
pragmas within a file being compiled.  These pragmas are available only
when the front end is compiled with DEBUG enabled.  The argument to
the db_opt pragma is the same string that would follow the "-d" of a debug
command-line option.  The argument to the db_name pragma is the same string
that would be used as an argument to the "--db_name" command line option.

A mechanism to turn off a debug flag is now provided.  If the flag name
is preceded by a "#", a previously set debug flag is cleared.

The following example illustrates how this could be used to display
"nondep_call" information only for a certain portion of the program.

  template <class T> void f() {
  #pragma db_opt -nondep_call
    g();
  #pragma db_opt #nondep_call
  }

11/8/01  Incorrect error on template boolean expression when "bool" is not
         a keyword

Certain boolean expressions in template contexts were not processed
correctly when "bool" is not a keyword in C++ mode (--no_bool option).
As a consequence, some incorrect errors were issued.  This has been
corrected.

  struct decimalBase {
    enum {maxwidth=31};
    enum {maxbytes=16};
  } ;
  template <unsigned int w,int p=0>
  struct decimal: public decimalBase {
    enum {width=(w>decimalBase::maxwidth)?
                decimalBase::maxwidth:w};
    enum {precision=(p<0)?0:(p>width)?width:p};  // Error here
  };


11/8/01  Inconsistent optimization of empty base classes

The empty base class layout optimization (Changes entry of 8/9/99) was
sometimes inhibited by the IL lowering of certain functions.  This could
result in the layout of a class being inconsistent across translation units.
This is now fixed.

11/7/01  Use of _AIX to detect use of AIX

The front end uses the __AIX__ macro as an indication that the front end
is being built under AIX.  The __AIX__ flag is now automatically set if the
_AIX macro is defined (as is the case for certain AIX compilers).

11/5/01  Change in template conversion lookup

A bug in the lookup of instances of conversion templates would cause the
following program to call A::operator int instead of C::operator T (with
T = int).  The standard is not really clear on how such cases should be
handled, but in the absence of a clearer specification, calling the
C conversion template seems like the desired behavior.

  struct A {
    operator int();
  };
  struct B { };
  struct C : A, B {
    template <class T> operator T() {return 0;}
  };
  int main() {
    C().operator int();
  }

11/5/01  Diagnostic on invalid use of "template" keyword

The "template" keyword when used for syntactic disambiguation can only be
used within templates (i.e., where it is possible to form a dependent
name reference that requires such disambiguation).  We now issue a
diagnostic for invalid use.  The diagnostic is usually a warning but may
be an error in strict mode.

11/5/01  Certain invalid usage of "typename" changed to a warning

Use of the "typename" keyword other than in a template context now
results in a warning (in default mode) instead of an error.  An error
may still be issued in strict mode.

11/2/01  Microsoft compatibility: friend class template abort

In Microsoft mode, an abort could occur when processing a template
friend declaration that refers to a class template that is a member
of another class template.  This has been fixed.

  template <class T> struct A {
    template <class T1> struct B;
  };
  template <class T1> template <class T2> struct A<T1>::B {
    template <class T3> static int f() {
      return C<int>::i;
    }
  };
  template <class T> struct C {
    template <class T1> template <class T2> friend struct A<T1>::B;
    static int i;
  };
  int main() {
    int i = A<int>::B<int>::f<int>();
  }

11/1/01  Spurious error on class member template specialization declaration

The declaration (not definition) of a specialization of a class member
template resulted in a spurious error.  This has been fixed.

  template <class T> struct A {
    template <class U> struct B;
  };
  template <> template <class U> struct A<int>::B;

10/17/01 Change in handling of constructor vs. injected class name in lookup

The standard, as amended by core issue 147, says that the lookup of a name
such as A::A always names the constructor.  We believe this rule to be
incorrect in lookups for which the constructor is not visible (such as
when a name is followed by :: as in the example below).  A new core issue
will be opened to address this problem.  Pending clarification by the
committee, the front end now accepts examples like this one.

  struct A { struct B {}; };
  A::A::B ab;

10/17/01 Spurious error when injected class name follows a field selection

The front end produced an incorrect lookup result when the lookup of
the name following a field selection operator should have found the
injected class name of a nested class.  This has been fixed.

  struct A {
    struct B { int i; } ;
  };
  void f(A::B* p) {
    p->B::i = 0;
  }

10/17/01 --db_name command-line option

A new command-line options --db_name can be used to specify a
name to be traced during processing.  The tracing code uses the
db_has_traced_name macro to test whether extra information should
be generated about an entity.  There is also a new db_trace, which
combines the functionality of db_flag_is_set and db_has_traced_name,
and symbol versions db_sym_has_traced_name and db_sym_trace.

10/14/01 Microsoft compatibility: template name used in base class specifier

Within the scope of class template the template name may be used
either with or without a template argument list.  The Microsoft
compiler also accepts the template name without a template argument list
in the base-specifier list of the class.  We now emulate this behavior
in Microsoft bugs mode.

  template <class T> class A { };
  template <class T> class B : public A<B> { };

10/11/01 Default temporary directory changed to /var/tmp

On non-Windows systems the default temporary directory has been changed
from /usr/tmp to /var/tmp, which is more commonly used on modern Unix
systems.

10/11/01 Spurious ambiguity between injected and non-injected name

If a class inherited both the injected name of a class and the non-injected
name, a reference to the name was incorrectly treated as ambiguous.  This
has been fixed.

  struct A {
    struct B { };
  };
  struct C : public A, public A::B {
    B *p;
  };

10/10/01 Spurious error on injected class name used as a template

The injected class name of a class template can be used as either
a class name or a template name.  References that would be ambiguous
as a class name are accepted as a template name if they uniquely
identify a template.  Certain cases resulted in spurious ambiguity
errors.  This has been fixed.

  template <class T> struct A { static int i; };
  template <class T> struct B : public A<T> { };
  template <class T> struct C : public A<char> { A a; };
  template <class T> struct D : public B<T>, C<int> {
    int f() {
      return D::A<char>::i + 1;
    }
  };
  int main() {
    D<int> d;
    d.f();
  }

10/10/01 Partial specialization permitted to be declared outside of a class

The standard permits a partial specialization of a member class template to
be added outside of the class containing the member class template.  This
feature is now implemented.

  template <class T> struct A {
    template <class T2> struct B { };
  };
  template <class T> template <class T2> struct A<T>::B<T2*> { };
  A<int>::B<char*> ab1;

10/7/01  Missing diagnostic on invalid template-id in destructor call

No diagnostic was issued when the type of a template-id used as a
destructor name did not match the type of the object being destroyed.
This has been fixed.

  template <class T> struct A {
    ~A(){}
  };
  int main() {
    A<int> *aip;
    aip->A<int>::~A<char>();
  }

10/5/01  New configuration variable to set the alignment type

The type of a_targ_alignment is a_byte.  However, a new configuration
variable TYPE_FOR_TARG_ALIGNMENT allows this to be changed (it is still a_byte
by default), thereby enabling a larger range for TARG_MAXIMUM_PACK_ALIGNMENT.

10/2/01  Spurious error possible when using-declaration refers to both
         a tag and non-tag

A special lookup is done to determine whether a using-declaration refers
to both a tag and non-tag name.  A problem in this lookup could cause
it to find the incorrect symbol, resulting in a spurious error.  This
has been fixed.

  template <class A> struct X {};
  struct A {};
  int A;
  namespace N {
    using ::A;
    int B = N::A;
    struct N::A x;
  };

10/1/01  Ordering of variable-length array deallocation and return expressions

The front end used to create deallocation points for variable length arrays
preceding return statements.  This was not valid if the return expression
referred to a (incorrectly deallocated) variable length array.  For example:

  int f(int n) {
    int x[n];
    /* stmk_vla_dealloc node for x used to precede evaluation of x[0]. */
    return x[0];
  }

This is now fixed by evaluating the return expression into a temporary
variable when necessary.

9/25/01  Abort in C99 lowering on empty dependent statement

When REPRESENT_EMPTY_STATEMENTS_IN_IL is FALSE, C99 lowering aborted
on processing an empty dependent statement.  Now fixed.

  int main () {
    int i = 1;
    while (i);  // Dependent statement is empty
    return 0;
  }

9/20/01  Microsoft compatibility: "extern template" allowed in class scope

In Microsoft mode, the front end now accepts "extern template" directives in
class scope.  (Such directives suppress instantiation of the named entity;
see Changes entry of 2/4/97.)

  template<class T> struct S {};
  class C {
    extern template struct S<int>;  // Now accepted in Microsoft mode
  };

9/20/01  #warning directive

The front end now supports a #warning directive that is similar to #error,
except that it generates a warning instead of a catastrophic error.

  #warning Issue this warning

This new directive is not recognized in strict ANSI mode.

9/20/01  Abort on unlowered specialization of a member of a class template

The front end used to abort when attempting to eliminate the source sequence
entries of an unused specialization of a member of a class template
when IL lowering is not done.  For example:

  template<typename T> struct S { void mf(); };
  template<> inline void S<int>::mf() {}  // Unused.  Could trigger an abort.

This is now fixed.

9/19/01  C++-generating back end: moving of in-class definitions

When TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the source
sequence lists associated with in-class member and friend definitions were
usually transformed into lists representing out-of-class definitions.
With unnamed enclosing classes, after the change of 9/19/01 to put out
such classes unnamed, this resulted in erroneous code generated by
the C++-generating back end.  The transformation is therefore now inhibited
for members of unnamed classes.

  struct { void f() {} } s;  // Member definition no longer moved outside
                             // the class definition

In addition, the flag FRIEND_AND_MEMBER_DEFINITIONS_MAY_BE_MOVED_OUT_OF_CLASS
can be configured FALSE to disable the transformation altogether (the flag is
TRUE by default).

9/10/01  __alignof__ equivalent to __ALIGNOF__

The front end now accepts __alignof__ as an alternative spelling of
__ALIGNOF__.  The two are exactly equivalent, but the former was added
to increase compatibility with other C++ front ends.  The __ALIGNOF__
spelling remains available.

8/28/01  GNU C compatibility option

The front end now supports command-line switches --gcc and --no_gcc that
provide some language compatibility with GNU C compilers.  The compatibility
is neither exact (i.e., some extensions may have a slightly different meaning)
nor complete (some extensions are not implemented).  This compatibility is 
only provided in C mode; in fact, the command-line switches imply C mode even
when no "--c" option is specified.

To enable these switches, GNU_EXTENSIONS_ALLOWED must be configured TRUE.
In that case, the default value of the command-line switch is determined by
the new configuration option DEFAULT_GCC_COMPATIBILITY.

The set of extensions enabled with the --gcc option initially includes:
variable length arrays, extended designated initializers, compound literals
([9/20/01] extended over C99 to allow more kinds of initializations),
extended variadic macros, identifiers with dollar signs, C++-style comments,
digraphs, long long (and related extensions provided by C99), hexadecimal
floating-point constants, nonconstant aggregate initializers for automatic
variables, the typeof operator, the __inline__ (and inline), __asm__, and 
__extension__ keywords, __FUNCTION__ and __PRETTY_FUNCTION__, zero-sized 
arrays, and the \e escape sequence. [9/10/01] Empty structs and structs with
flexible array members are now also accepted in GNU C mode.
[9/15/01] Attributes, &&label, goto *expression, builtin functions.
IL CHANGE: added stmk_assigned_goto for goto *expression, and
abk_label variant of ck_address constant for address of label.
[9/18/01] Statement expressions i.e., ({...}). [9/19/01] Multi-line
strings. [9/26/01] Binary conditional operators ("x ?: y") are now accepted.
This required the addition of a new expression operator eok_binary_question,
which can be lowered to a normal eok_question (IL CHANGE).
[9/27/01] extern inline [10/1/01] The sizeof operator is applicable to void
and function types and evaluates to the value one.  Arithmetic on pointers
to these types is possible (they behave much like char*). [10/2/01] Variables
can be redeclared with different top-level cv-qualifiers (the new qualification
is merged into existing qualifiers). [10/3/01] Locally declared labels.
[10/11/01] Generalized lvalues: the (ternary) conditional operation produces
an lvalue if its second and third operand are lvalues, the comma operator
produces an lvalue if its second operand is an lvalue, and certain casts
also preserve the lvalueness of their operands.  [10/12/01] Case ranges.
[10/15/01] Assembler names of variables and routines. [10/17/01] Union casts.
[10/30/01] Implicit conversions between integer and pointer types, and
between incompatible pointer types, with a warning.  Also implicit
conversions between pointer types that drop cv-qualifiers. [11/1/01] typedef
initializers. [11/1/01] Extended asm syntax. [11/2/01] Variables mapped to
specific registers.  [12/7/01] --preinclude_macros option (like the gcc
--imacros feature). [12/26/01] Do-nothing casts to struct or union types.
[1/9/02] Return expressions in void functions. [1/21/02] Oversized bit fields
are turned into ordinary fields. [1/22/02] Builtin varargs operations.
[1/25/02] Old-style definitions with unpromoted parameter types can follow
function prototypes with those same parameter types. [2/26/02] _Bool
keyword.  [3/10/02] "?" operators with mixed void/non-void operands.

8/28/01  C++-generating back end: unnamed classes/structs not given names

The C++-generating back end no longer gives names to unnamed classes
and structs.  This was formerly necessary for some cast cases, but
those casts were implicit and are now suppressed, so there's no
longer any reason to generate names.

As part of making this change, the original expression is now
preserved for the cfront- and Microsoft-extension use of expressions
like x.e1 or p->e1 as constants, when RECORD_CONSTANT_EXPRESSIONS_IN_IL
is TRUE.  This was necessary because the class of the constant
might be unnamed, and formerly the constants were put out as
class_name::constant.

8/28/01  Typedefs and cv-qualifiers preserved in runtime sizeof type

The type recorded in an enk_runtime_sizeof expression node
now preserves any typedefs or cv-qualifiers that were in the
source code.  enk_runtime_sizeof is typically used only in
source-to-source versions or in prototype instantiations.

8/24/01  Enum operator overloading in Microsoft mode

The overload resolution processing for enum relational and
equality operator overloading for has been changed somewhat to
reflect some fixes in MSVC++ 7.0 and the fact that the bugs in
MSVC++ 6.0 were more complicated than we thought.

8/21/01  Templates referenced from prototype instantiations

The instantiation required flag for template functions and static data
members was being set for references from prototype instantiations.  Such
references should not result in the setting of the flag.  This has
been fixed.

This example fails as a result of this problem.  Because removal of
unneeded entities will often mask this problem, the example fails only
if compiled with --no_remove_unneeded_entities.

  template <class T> int f(T t){
    return t.x;  // will fail if instantiated on int
  }
  template <class T> void g(T){
    f(1);
  }
  int main() {}

8/17/01  Internal error in diagnostics in standalone program

An internal error could result when a diagnostic was issued from a
front end component compiled with STANDALONE_UTILITY_PROGRAM set to TRUE.
The internal error occurred in alloc_in_region called from
record_prototype_diagnostic.  This has been fixed.

8/9/01   Spurious error on qualified template friend declaration in a
         class template

A spurious error was issued on a qualified template friend declaration
that appeared in a class template.  This problem was introduced in version
2.44 and is now fixed.

  namespace N {
    template <class T> void f(T);
  }
  template <class X> struct A {
    template <class T> friend void N::f(T);
  };

8/8/01   Using expand_macros in pragmas saved as text strings

The front end contained a number of assertion checks to make sure
that a pragma did not have its expand_macros flag set if the
make_text_not_tokens flag was also set.  These checks are no longer
necessary and have been removed.

8/7/01   File names containing "." and PCH usage

The routine that reads directory entries did not handle file names with
embedded "." (e.g., t.x.c) characters properly.  As a result, a PCH file
generated by such a file would never be used.  This has been fixed.

8/2/01   C++-generating back end: inline specifier on friend declarations

The C++-generating back end no longer emits the inline keyword on friend
function declarations if the function is a class member or if it has explicit
template arguments.  For example:

  struct A { inline void f() {} };
  struct B {
    friend void A::f();  // Used to be rendered with "inline"
  };

8/2/01   Sun and Microsoft compatibility: abort when redeclaring a function
         made visible with a using-declaration

The front end used to abort with an internal error on a redeclaration of
a function with C linkage made visible through a using-declaration if the
function was overloaded after the using declaration.  (Such declarations
are only allowed in Sun and Microsoft modes: see Changes entry of 6/28/00.)
For example:

  namespace N { extern "C" void f(); }
  using N::f;
  namespace N { void f(int); }
  void f();  // Used to trigger an internal error in decls.c

This is now fixed.

8/2/01   C++-generating back end: explicit specializations with explicit
         template arguments

The C++-generating back end now always generates a "template<>" prefix when
regenerating an explicit function template specialization with explicit
template arguments (even when the original source used the old specialization
syntax).  This avoids errors due to C++ compilers (including the front end
itself) not accepting old-style function template specializations with
explicit template arguments.

7/31/01  Spurious ambiguity when using nonstandard template lookup

In default mode, the front end uses a nonstandard algorithm when looking
up names in templates.  The algorithm used is similar to the rules from
a draft version of the standard and more closely approximates the rules
used by other compilers.  When using the nonstandard lookup, a spurious
ambiguity was reported when a non-function name was found in the
template definition context and a function name was found in the
context in which the template was referenced.  This has been fixed.

  namespace N {
    template <class T> struct A { };
    template <class T> struct B : A<T> { };
  }
  void A();
  N::B<int> bi;

7/30/01  Syntax checking for asm functions

When ASM_FUNCTION_ALLOWED is TRUE, the front end used to discard the token
introducing the definition of an asm function without verifying that it was
in fact a left brace.

  asm void f() any_token }  // "any_token" used to be treated as a left brace;
                            // now it is reported as an error.

This is now fixed (i.e., an error is issued).

7/27/01  Microsoft compatibility: visibility of variable declarations

In Microsoft bugs mode, a variable declaration is now invisible in its
own parenthesized initializer.  For example:

  int x = 7, y = 8;
  void f() {
    int x = x;  // x is assigned its own uninitialized value
    int y(y);   // Same as "int y(::y)" in Microsoft bugs mode
  }

7/27/01  Change in a_template entries for members of class templates

When a member template is declared in a class template, there is now a
separate canonical a_template entry for each instance of the enclosing
class.  Formerly, all of the instances would share the same canonical
entry.  In the example below, there are canonical entries for A,
A<T>::B, A<int>::B, and A<float>::B (where previously there were only
entries for A and A<T>::B).

A new field named prototype_template has been added to the a_template
entry.  This field is used in a_template entries for members templates
of class templates and points to the corresponding a_template entry in
the prototype instantiation of the enclosing class.  In this example,
the A<int>::B and A<float>::B a_template entries have a prototype_template
field that points to the a_template entry for A<T>::B.

  template <class T> struct A {
    template <class U> struct B {};
  };
  A<int>::B<short> ab;
  A<float>::B<int> ab2;

7/27/01  Precision of output of long double constants, with 128-bit
         long doubles

The change of 2/9/01 to add one more digit of precision on output
of long doubles caused a small amount of grief on versions hosted
on Solaris and generating compilable output to be processed
by the Sun C++ compiler.  The value of LDBL_MIN as converted
with the new length is not accepted by that compiler.  That's
probably a bug in the Sun compiler, but to avoid it we have
restored the old (one smaller) precision for hosts with
LDBL_DIG > 30 (i.e., 128-bit long double).

7/26/01  IL lowering of compound assignments to bool variables

IL lowering now generates extra code to ensure that the result of
a compound assignment that assigns to a bool variable is limited
to 0/1.

  int main() {
    bool b = true;
    b += 2;  // Yields 1, not 3
  }

This processing is also now done in C99 lowering.

7/24/01  Value-initialization

Value-initialization, a refinement of default-initialization
introduced in TC1 of the C++ standard (and core issue 178), is
now implemented.  It ensures that all fields of non-POD classes
without user-written constructors are properly initialized, by
zeroing the storage for the object before calling the constructor.

Three new runtime routines, __array_new_zero, __placement_array_new_zero,
and __vec_new_eh_zero, have been added to the runtime library.
They have the same parameter lists and functionality as the existing
routines with similar names without "_zero", but they zero the storage
before calling the constructor.

7/19/01  Incorrect storage class for function prototype instantiations

When generating non-class prototype instantiations, the storage class
for the prototype instantiation of a function with external linkage
was sc_extern but should have been sc_unspecified.  This has been fixed.

7/18/01  Built-in operators on enums with same signature as user-written
         functions are discarded

In overload resolution, built-in operators on enum types that have the
same signature as user-written operator functions are now ignored
as specified in 13.3.1.2 [over.match.oper] paragraph 2 bullet 3
sub-bullet 4 of the C++98 standard.

  enum e { a };
  bool operator==(e, e) {
    return 0;
  }
  bool f() {
    return a == a;  // No longer ambiguous
  }

7/17/01  Overload resolution for built-in operators taking ptrdiff_t

The overload resolution processing for built-in operators that take
an operand of type ptrdiff_t (e.g., []) is now improved in that when
evaluating a conversion function it takes into account any conversion
needed after the conversion function to get to ptrdiff_t.

  struct A {
    operator char();
  };
  struct B {
    operator char*();
    operator[](int);
  };
 void foo() {
   A len;
   B ret;
   ret[len];  // was ambiguous, now selects B::operator[]
  }

A similar issue with the cost of converting from an enum type returned
by a conversion function to an integral type has also been addressed.

7/17/01  Incorrect instantiation context when using nested namespaces

A problem in the way in which the instantiation context is established
resulted in incorrect name lookups in certain cases involving nested
namespaces.  This has been fixed.

  // Got a spurious error when compiled in strict mode.  
  namespace N0 {
    namespace N1 {
      template <class T> struct A { };
    }
    using namespace N1;
    namespace N2 {
      template <class T, class T2> void f1(A<T>, A<T2>);
      template <class T> void f2(T);
    }
    using namespace N2;
  }
  using namespace N0;
  namespace N0 {
    template <class T> void N2::f2(T)
    {
      f1(A<int>(), A<int>());
    }
  }

7/17/01  "p" and "P" in pp-numbers when hex floating-point literals accepted

In strict mode, when hexadecimal floating-point constants are
accepted (e.g., in C99 mode), the sequences "p+", "p-", "P+" and
and "P-" are allowed as part of preprocessing numbers.  The
front end now implements that.  This has little if any visible effect
on the set of valid programs.

7/13/01  Information on object type in overload resolution errors

Overload resolution errors now list the type of the object in
a member function call, which can be helpful in figuring out
why no function is callable or why there is an ambiguity (e.g.,
because the object is const-qualified).

7/13/01  Operator keywords in #if directives

The front end now correctly processes operator keywords (like "compl" or
"new") in #if directives.  For example:

  #if 0 or 1    // Now tests positive when alternative tokens are enabled
  #if delete 0  // Still invalid, but different diagnostic
  #endif
  #endif

7/13/01  Error on implicit conversion to abstract class type

An error is now issued on any attempt to create an object of
an abstract class type via an implicit conversion.

  struct A {
    A(int);
    virtual void f() = 0;
  };
  void g(const A& a);
  int main() {
    g(42);
  }

7/12/01  assoc_template not set for function template prototype instantiation

The assoc_template field was not set properly for most function templates.
This has been fixed.

  template <class T> void f(T){}

7/12/01  Sun compatibility: typename is ignored in most contexts

The Sun compiler ignores the typename keyword in most contexts.  It
accepts the typename keyword in contexts where it is not permitted
and does not enforce the semantic constraints required by the language.
The front end now emulates this behavior in Sun mode.

  // The Sun compiler does recognize typename in a template parameter list
  template <typename T> class C {
    // Illegal uses of typename that are accepted by the Sun compiler
    typename T t;
    typename typename T typename typename x;
  };

7/12/01  Flag defined_in_friend_decl incorrectly set in routine entries

The field defined_in_friend_decl (see Changes entry of 2/25/96) was set
incorrectly in some circumstances.  One of the circumstances occurred when
TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, which causes the
front end to transform in-class function definitions into out-of-class
definitions.  The problem also occurred when instantiating a class template
containing a friend declaration which was later defined outside the class
template definition.

7/12/01  Elimination of duplicate functions in overloading error message

In some cases involving namespaces and using-directives, an error
message issued for an ambiguity in overload resolution listed the
same function twice.  Now fixed.

  namespace N {
    template <class T> struct A {};
    template <class T> void f(const T&);
    template <class T> void f(A<T>);
  }
  using namespace N;
  int main() {
    A<int> ai;
    f(ai);
  }

7/10/01  C++-generating back end: extraneous namespace qualifier on friend
         function declaration

The C++-generating back end sometimes generated a namespace qualifier on
friend function declarations that are only members of the indicated namespace
through friend name injection (see Changes entry of 2/25/99).  For example:

  namespace N { class A { class B; }; }
  class N::A::B {
    friend void f();  // Used to be rendered as "friend void N::f();" which
  };                  // is not valid C++.

This is now fixed.

7/10/01  C++-generating back end: missing namespace qualifier on member of
         anonymous union

The C++-generating back end never emitted a namespace qualifier when emitting
a reference to a member of a namespace-scope anonymous union.  For example:

  namespace N {
    static union { int i; };
  }
  int r = N::i;  // Used to be mistakenly rendered as "int r = (i);"

This is now fixed.

7/9/01   Internal error during instantiation of template static data member

Under certain unusual circumstances, an internal error can occur in
define_template_static_data_member when using automatic template
instantiation.  The example below results in the internal error when
compiled and then linked using the prelinker.  This has been fixed.

  template <class T> struct A {
    static int i;
    static int j;
  };
  template <class T> int A<T>::i = j;
  template <class T> int A<T>::j = i;
  int x = A<int>::i;

7/9/01   Conflicts between using-declarations and function declarations

The front end used to issue an error when a function in namespace scope had
the same name and type as a function imported by using-declaration in that
scope.  Now the same error is issued even when the function types only differ
in their return types.  For example:

  namespace N {
    void f();
  }
  int f();
  using N::f;  // Used to be accepted; now an error (except in Microsoft mode)

Furthermore, in Microsoft mode, a diagnostic is issued only if the using-
declaration precedes the function declaration and if the two have different
return types.  For example:

  namespace N {
    void f();
    void g();
  }
  using N::f();
  int f();  // Used to be accepted; now an error in all modes
  using N::g();
  void g(); // Used to be accepted; now only accepted in Microsoft mode

7/6/01   Exceptions enabled by default in C++-generating back end versions

The value of DEFAULT_EXCEPTIONS_ENABLED, which controls whether
exception handling is enabled by default, is now taken to be TRUE
if it's not defined, in versions that use the C++-generating back end.
This makes sense because exception handling has no associated overhead
in such versions.

7/6/01   Base classes without destructors

The front end used to issue a remark when deriving from a base class with a
nonvirtual destructor (see Changes entry of 9/13/92), but not when deriving
from a base class with no user-declared destructor.  Now, both cases are
treated identically.

  struct B1 {};
  struct D1: public B1 { int f; };  // Remark now issued (but not previously)
  struct B2 { ~B2() {} };
  struct D2: public B2 { int f; };  // Remark issued 

In both cases no remark is issued if the derivation involves only one base
class, declares no destructor, and does not result in a derived class with a
size larger than the base class.

7/6/01   Microsoft compatibility: inline specifier on friend member functions

Ordinarily, the front end issues an error on friend declarations that add an
inline specifier to member functions that were previously not declared to be
"inline".  For example:

  struct A { void f(); };
  struct B {
    friend inline void A::f();  // Normally an error
  };

In Microsoft mode, the front end now ignores the inline specifier without
issuing a diagnostic.
  
7/5/01   Prototype instantiation default argument information in IL tree

In some cases, IL for prototype instantiations of default argument
expressions was left in the IL tree even when prototype instantiations
were not supposed to be kept in the IL.  This happened only when
prototype instantiations for non-classes were enabled, e.g., in strict
mode.  The incorrect IL could cause aborts (e.g., an IL write/read
consistency error).  Now fixed.

  template <class T> struct A {
    ~A();
    int f1();
    int f2(int = A().f1());
    virtual void vf3();
  };

7/3/01   C++-generating back end: qualification on overloaded member
         function accessed via using-declaration

In cases where an overloaded member function is called without an
explicit object (i.e., an implicit "this" applies), and the access
to the function is modified by a using-declaration, one of the casts
in the IL constructed did not have the implicit_in_member_naming
flag set, which caused the C++-generating back end to generate code
with unnecessary name qualification.  The generated code was not
valid in some cases, and was valid but not accepted by some compilers
in other cases.

  struct A {
    void f();
    static void f(char *);
  };
  struct B : private A {
  public: A::f;
  };
  struct C : public B {
    void g() {
      f();  // Was put out as this->::A::f(), not accepted by some compilers
    }
  };
  int main () {
    C c;
    c.g();
  }

6/29/01  C++-generating back end: spurious qualifier in anachronisms mode

In anachronisms mode, the C++-generating back end used to generate a
spurious qualifier for nested type declarations if another type with
the same name was inherited from a base class declared in another
namespace.  For example:

  namespace N {
    struct A { enum E {}; };
  }
  struct B: N::A {
    enum E {};  // Used to be rendered as "enum B::E {};" with --anachronisms
  };

This is now fixed.

6/29/01  Requirement for object pointer for builtin operator forces
         instantiation

A requirement of a builtin operator that an operand type be a pointer
to object type now forces the instantiation in overload resolution
of the underlying type of the pointer when it is a template class.

  template <class T> struct A {};
  struct B { operator int(); };
  int main () {
    A<int> *p;
    B x;
    p[x];  // No error now
  }

6/29/01  Incorrect result from division of large values with simulated integers

When using simulated integers (i.e., when INTEGER_VALUE_REPR_IS_HOST_INTEGER
is FALSE), the compile-time division of certain large values would
sometimes produce an incorrect result.  This has been fixed.

  int main()   {
    long long l = 0x7fffffffffffffdll / 0x3ffffffffffffffll;
  }

6/28/01  Spurious error on declaration of conversion template specialization

Declarations of conversion functions that are instances of conversion
templates that return references where not handled properly, resulting
in spurious errors in cases such as this.  This has been fixed.

  struct A { 
    template < class T > operator T & ( );
  }; 
  template<> inline A::operator const int &();

6/28/01  C++-generating back end: qualifiers in array declarators

The C++-generating back end used to not reproduce cv-qualifiers appearing
in array declarators of function parameters.  For example:

  void f(int a[const 10]) {}

was rendered without the "const".

This is now fixed.  The fix required the addition of a new field "qualifiers"
to tk_array type entries (IL CHANGE).

6/27/01  Spurious warning on members of nested classes in unnamed namespaces

When a member function of a nested class in an unnamed namespace was defined
the front end used to issue a warning that that function was defined but
not referenced even though it was used by a member function of the enclosing
class.  For example:

  namespace {
    struct S {
      struct N {
        static void f() {}  // Used to be reported as "unreferenced"
      };
      static void g() { N::f(); }
    };
  }
  int main() { S::g(); }

This is now fixed.

6/27/01  Exception specifications and address of overloaded function

The front end failed to diagnose an incompatibility in exception
specifications when the address of an overloaded function is taken
(and one function is selected from that overload set according
to the required destination type).  The error is now issued.

  struct S {
    S& operator++();
    S operator++(int);
  };
  int main() {
    S& (S::*pf)() throw () = &S::operator++;  // Error now issued
  }

6/27/01  C++-generating back end: bad rendering of variadic macro parameter

The text rendering of macros used to systematically substitute "__VA_ARGS__"
for the variadic macro parameter.  This caused

  #define M(...) __VA_ARGS__

to be rendered as

  #define M(__VA_ARGS__) __VA_ARGS__

by the C++-generating back end.  That is now fixed.

In addition, the identifier __VA_ARGS__ is now allowed as a named variadic
macro parameter when extended variadic macros are enabled.

  #define X(__VA_ARGS__...) __VA_ARGS__ /* No longer an error. */

6/26/01  Abort when attempting to define a function previously declared
         with a cv-qualified typedef

Declaring an ordinary (i.e., non-member) function with a typedef for a
cv-qualified function type is an error diagnosed by the front end.
However, if such a declaration was followed by an attempt to define the
function (with or without cv-qualifiers), the front end aborted with an
internal error.

  typedef void FT() const;
  FT f;       // Error: f cannot be "const"
  void f() {} // Used to abort

This is now fixed.

6/25/01  Abort on severely malformed class template declaration

In certain cases, the parser can get confused during the initial parse
of a class template.  In such cases, an abort could occur (in
find_member_function_template) during an attempt to generate a real
instantiation of the template.  This has been fixed.

  template <class T> class C : std::A<char> {
    void f(T); 
  };
  namespace std { template <class T> class A; }
  C<char> c;

6/25/01  cv-qualifiers on return type of template conversion function

cv-qualifiers are now preserved in type deduction on the return type of
a template conversion if the destination will be bound to a reference.

  struct A {
    template <class T> operator T&(); // Deduced T is "const int" not "int"
  };
  int main() {
    A a;
    (const int &)a;
  }

6/25/01  cv-qualifiers on template parameters in implicit pointer conversions
         in prototype instantiations

The processing for implicit conversions in prototype instantiations
now assumes that a template parameter might represent a type that
is cv-qualified, and therefore that "T *" and "const T *" might be
the same type.

6/22/01  Effect and configuration of custom name linkage kinds

The front end would abort on certain redeclarations when custom name linkage
kinds were added by defining the macros CUSTOM_NAME_LINKAGE_KINDS,
CUSTOM_NAME_LINKAGE_KIND_NAMES, and NUM_BITS_FOR_NAME_LINKAGE while omitting
a definition of is_custom_name_linkage_kind_for_rout_type (or when that
macro resulted in a false expression).  For example:

  void f();
  extern "MyLinkage" void f();  // Used to abort in some configurations

Furthermore, custom name linkages were applied to a routine type even when the
macro is_custom_name_linkage_kind_for_rout_type indicated that this should
not be the case.  These problems are now fixed.

To help prevent unintended configurations, a preprocessor error will now be
issued if custom name linkages are added by defining CUSTOM_NAME_LINKAGE_KINDS
while failing to define NUM_BITS_FOR_NAME_LINKAGE and
is_custom_name_linkage_kind_for_rout_type.  (See also Changes entries of
2/26/97 and 4/3/97.)

6/22/01  Nontemplate friend declaration had is_template_function set

The IL entry created for a nontemplate friend function declaration in the
prototype instantiation of a class template used to have is_template_function
set (only significant in configurations where PROTOTYPE_INSTANTIATIONS_IN_IL
is set).

  template <class T> struct S {
    friend void f1(T);   // Not a template function: is_template_function
                         //    should be FALSE
    friend void f2<>(T); // Template function: is_template_function should
  };                     //    be TRUE

This is now fixed.

6/22/01  Use of template conversion function in context that requires
         different cv-qualification

Template conversion functions are now considered in contexts where
the required class type has different cv-qualification than what
the conversion function produces.

  template <class T> struct A { };
  struct S {
    template <class T> operator A<T>();
  } s;
  int main() {
    const A<int> &r = s;  // Requires conversion to const A<int>;
                          // accepted now.
  }

6/21/01  Constructors marked "explicit" no longer used for copying

To match TC1 of the C++ standard, the front end no longer uses
constructors marked "explicit" as copy constructors.

  struct X {
    X();
    explicit X(const X&);
  };
  void f(X);
  int main() {X x; f(x); }  // Error now -- no way to copy an "X"

6/20/01  Spurious error on member using declaration

A spurious error was issued when a class member using-declaration referred
to a typedef of a template dependent type.  This has been fixed.

  template <class T> struct A : T {
     typedef typename T::X my_x;
     using typename my_x::Y;
  };

6/19/01  C++-generating back end, prototype instantiations: output
         of name from unknown dependent base class

A reference to an unknown name in the prototype instantiation of
a class template that has one or more dependent base classes is considered
to be okay because the unknown name might turn out to be a member
of one of the dependent base classes when the template is
actually instantiated.  When the C++-generating back end outputs
templates from prototype instantiation IL, such cases were incorrectly
output as qualified names indicating that the name appears in the
first dependent base class.  If the name actually appears in
a different base class, of course, this ends up being incorrect.
This is now fixed: the name is put out as an unqualified name.

  template <class T1> class A {};
  template <class T> class B {
    void internal();
  };
  template <class T1, class T2> class C : A<T1>, B<T2> {
    void method() {
      internal();  // Formerly put out as A<T1>::internal();
    }
  };

6/19/01  C++-generating back end, Microsoft compatibility: further
         work-around on MSVC++ problem with template uses in default arguments

The MSVC++ bug workaround of 7/21/98 has been extended to apply to
uses of qualified names for variables and constants in default
arguments.  Because the MSVC++ 7 beta appears to no longer have this
bug, the behavior has also been made conditional on the value of
a new variable, msvc_target_version_number, which is set by default
to match DEFAULT_MICROSOFT_VERSION.

  template <int D> class ccXform { };
  typedef ccXform<2> cc2Xform;
  struct ccXform<2> { static const ccXform<2> I; };
  struct ccPelRect { };
  struct ccAffineRectangle {
  ccPelRect encloseImageRect(
    const cc2Xform& imageFromClientXform = cc2Xform::I) const;// Typedef used
  };

6/18/01  Wrong IL negation operator on "-" applied to class converted to
         floating type

The IL operator for a negation was wrong (eok_inegate instead
of eok_fnegate) in a case where a unary "-" is applied to a
class and the class is implicitly converted to a floating-point
value.

  struct A {
    operator double();
  };
  double f( A& x ) {
    return -x;
  }

6/17/01  Spurious error on typename std::X when using --ignore_std

When using the g++ compatibility feature "--ignore_std", which treats
the std namespace as an alias for the global namespace, an error would
be issued on a typename specifier in which the qualifier named the
std namespace.  This has been fixed.

  namespace std {
    template <class T> class A {};
  }
  template <class T> void f(typename std::A<T>);

6/17/01  Extra source positions on operands of "?" operator

The extra source positions recorded when EXTRA_SOURCE_POSITIONS_IN_IL
is TRUE were missing in some cases for "?" operators (and other
operators that may return lvalues but turn out to return rvalues
in the problem cases).  The source positions were not transferred
correctly when the internal expression tree is converted to an
rvalue.

6/16/01  C++-generating back end, prototype instantiations: output of
         dependent Microsoft __uuidof

The output generated by the C++-generating back end for a template-
dependent Microsoft __uuidof in a prototype instantiation had an
extra level of indirection, i.e., *(__uuidof(T)) instead of simply
__uuidof(T).  Now fixed.

  template <class T> class A {
    template <class Q>
    void fun(Q **pc) {
      p->query(__uuidof(Q), (void **)pc);
    }
    T *p;
  };

Note that doing prototype instantiations of functions in Microsoft mode
(e.g., by specifying --parse_templates) is unusual, as it does match
the behavior of MSVC++ itself.

6/15/01  Internal error on leading space in command-line macro definition

A command-line macro definition in which the macro name begins
with a space resulted in an internal error (in enter_symbol).  This
has been fixed (the leading spaces are discarded).

6/15/01  Problem with -I option and directory names that begin with "-"

Directory names beginning with a "-" were not handled properly when used
as an argument to the -I command-line option.  This has been fixed.

6/14/01  C++-generating back end, prototype instantiations: elimination
         of unnecessary qualifiers on name references

The C++-generating back end now avoids putting out some unnecessary
qualifiers on names of entities in field selections in prototype
instantiations, where the class type of the left operand is
template-dependent.

  template <class T> struct A {
    T *p;
    void f() {
      p->g();  // g formerly put out as T::g
    }
  };

[6/15/01:] On a similar front, the keyword "template" following
such a field selection is now put out when required.

  template <class T> struct A {
    T *p;
    void f() {
      p->template f<int>(1);  // "template" preserved in output
    }
  };

6/13/01  Combining Microsoft mode and C99 mode

Microsoft mode and C99 mode may now be used together.  Previously, the
--c99 and --microsoft options could not be used together.  In addition,
if --microsoft was the default, --c99 would silently turn off Microsoft
mode.  Now, if --microsoft is the default, --c99 enables C99 features
but Microsoft mode is still enabled.

6/12/01  Lookup of unqualified names in template contexts

In default mode, when doing a lookup in a class with a dependent base
class, an unqualified name that would not otherwise be found by
a normal lookup is considered to be a member of the dependent base
class.  This allows X to be used in the definition of class template B
in the example below.  In version 2.43 a change was made that caused
the lookup of X in the definition of B<T>::f to fail.  This resulted in
spurious errors in examples like this one.  A change has been made to permit
such use in the definition of a class template member that appears outside
of the class.  Note that this kind of use is not permitted by the standard.
The standard requires that such a reference be written as "typename T::X"
or "typename B::X".

  template <class T> struct B : T {
    void f(X);
  };
  template <class T> void B<T>::f(X){}

6/11/01  No source positions in compiler-generated cast expressions

Compiler-generated implicit cast expressions no longer have source
position information.  The extra source position information
is present only when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, and
should not have been set for generated casts, because they do not
have corresponding source code.

6/7/01   Microsoft compatibility: internal error on default argument in
         template declaration

The Microsoft compiler allows a default argument to be specified on the
definition of a member function of a class template that appears outside
of its class (the standard requires that such default arguments be specified
on the declaration in the class).  In Microsoft mode, this would result
in an internal error.  This has been fixed.

  template <class T> struct A { void f(T); };
  template <class T> void A<T>::f(T value = T() )  { }

6/4/01   C++-generating back end, output of member function calls in
         prototype instantiations

Certain member function calls in prototype instantiations were put
out by the C++-generating back end in the form f(p, a1, a2, ...)
instead of the original source form p->f(a1, a2, ...).  Now fixed.
This required the addition of a new expression operator
eok_generic_member_call (IL CHANGE), which will be seen only in
IL for prototype instantiations.
 
6/1/01   Microsoft compatibility: floating-point nontype template
         parameters accepted

Floating-point nontype template parameters are now accepted in
Microsoft mode.

  template <double d> struct A {};
  A<2.0> x;

6/1/01   "friend T;" accepted when T is a template parameter

A nonstandard friend declaration of the form "friend T", where T
is a template parameter, is now accepted.  This form of friend declaration
was previously accepted only when T was a class name.  A diagnostic is
issued in strict mode.

  class X;
  template <class T> struct A {
    friend X;  // previously accepted
    friend T;  // now accepted
  };

5/31/01  Operations like 1.0/0.0 get no diagnostic when IEEE floating-point
         is supported

When TARG_HAS_IEEE_FLOATING_POINT is TRUE, floating-point divisions
by a constant zero are now allowed, without a diagnostic.  The result
is the appropriate NaN or Infinity.

5/30/01  static template should not be found on dependent call

A template declared static is no longer found on the lookup for
a dependent function call.

  template<class T> static void f( T i );
  template<class T> void g( T t ) { f( t ); }  // Will not find static f
  void h() { g( 42 ); }

5/25/01  Internal error when a template refers to a real instantiation of
         itself

The front end used to abort with an internal error when it encountered a real
instantiation of a member function with at least one parameter of a class
template while parsing that class template.  For example:

  template<class T> struct S {
    void f1() { S<int> s; s.f2(0); }  // Causes the instantiation of
                                      // S<int>::f2(int) while parsing S<T>
    void f2(int) {}  // Abort in func_def.c on this function when parsing
  };                 // of function templates is enabled (e.g., with -A)

This is now fixed.

5/25/01  C++-generating back end: storage class on for-initialization

The storage class put out by the C++-generating back end on a
for-initialization is now always the one specified in the source,
which avoids a problem when the storage class was omitted and
one entity declared is a function:

  int main() {
    for (int i, foo();;) {}  // "auto" was put out previously, which
                             // caused an error on foo
  }

5/25/01  Generation of __asm instead of asm(...) when MSVC is generated
         code target

When MSVC_IS_GENERATED_CODE_TARGET is TRUE, the C- and C++-generating
back ends now put out asm statements in the Microsoft __asm form.
Formerly, this was done only when running in Microsoft mode.

5/21/01  Abort on C99 designated initializer on string and aggregate that
         doubly initialize same character

The lowering for C99 designated initializers aborted while attempting
to lower an initializer that initializes the same spot twice, once
with a string literal and once with an aggregate or individual
characters.  Now fixed.

  struct H {
   char I[6];
   int J;
  };
  struct H m[] = { { { "foo" }, 1 }, [0] = { .I[0] = 'b' } };

5/21/01  Name linkage strings and character conversions

The front end now converts the strings in the array name_linkage_kind_names
to the internal (target-dependent) representation.  This eases the adaptation
of the front end for configurations where, e.g., the front end is compiled on
an ASCII platform while its input is EBCDIC source.

5/17/01  Abort on __based specifier with local variable

The front end used to produce invalid IL when processing __based pointer types
with local base variables.  This resulted in internal errors in some
configurations.  Such pointer types are now diagnosed as errors.

  int main() {
    int *bp;
    int __based(bp) *p;  // Used to generate invalid IL.
  }                      // Now diagnosed as an error.

Note that Microsoft compilers do accept such code though it is believed to
be too rare in practical code to warrant an expensive implementation.

5/15/01  Microsoft compatibility: definitions of members of in-class
         specializations not emitted

The Microsoft compiler permits a member class template to be specialized in
the scope of the enclosing class (this is prohibited by the standard).  We
emulate this behavior in Microsoft mode.  When processing such a
specialization, the members of the specialization were not being handled
properly.  This could result in link errors or other incorrect behavior,
and is now fixed.

  template < class T > struct A {
    template <class T2> struct B { void f() { } };
    template <> struct B< char > { void f() { } };
    B<char> b;
  };
  int main() {
    A<int> a;
    a.b.f();  // link error: A<int>::B<char>::f not defined
  }

5/14/01  Return without expression in non-void function in C mode gets
         remark instead of warning when not at top level

In a non-void function, a return statement that does not specify an
expression should get a warning in C mode.  When the return statement is
not at the top level of the function, however, a remark was issued
instead.  Now, the diagnostic is a warning as intended.

  int foo(int i) {
    if (i != 0) { 
      return;  /* Formerly a remark instead of a warning. */
    }
    return 0;
  }

5/9/01   Abort on processing "for" statement with complex embedded
         declaration

The code that scans "for" statements held a pointer to an entry
in the structured statement stack over the scanning of a complex
declaration that caused a storage reallocation.  The consequence
was an abort in the C-generating back end, but any number of
disastrous outcomes were possible.  Now fixed.

5/2/01   Abort on mem-initializer for nonreal base class, with
         prototype instantiations

A test case like the following, which has a mem-initializer for
a nonreal base class, aborted sometimes when prototype instantiations
of nonclass templates were done (e.g., in --parse_templates mode or
in strict mode).  The abort we observed occurred only when Microsoft
mode is enabled, but we believe this is only because of differences
in layout of internal data structures; the problem is there in all
configurations.

  template <class Base>
  struct A : public Base {
    A(): Base() {}
  };

4/26/01  Internal error when recording instantiations of members of class
         templates in source sequence lists (Microsoft mode)

When TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the front end
used to abort in Microsoft mode if a member of a class template was 
instantiated for multiple template argument combinations.  E.g.:

  template<typename T> struct S { void f(int); };
  template<typename T> void S<T>::f(int) {}
  template void S<char>::f(int);
  template void S<long>::f(int);  // Triggers internal error in Microsoft mode

This is now fixed.

4/25/01  Extra cross-reference lines when argument-dependent lookup enabled

When argument-dependent lookup is enabled, a call of a non-overloaded
function is forced through overload resolution.  The process ended
up producing extra calls to record_symbol_reference and extra
lines in the cross-reference output file.  Now fixed.

  void f(int);
  int main () {
    f(1);  // Two references to "f" were put out
  }

Extra lines were also produced for non-dependent calls in prototype
instantiations.  Also fixed now.

4/19/01  Internal error in default argument processing when doing nonclass
         prototype instantiations

When doing nonclass prototype instantiations (which is also implied by
strict mode and dependent name lookup mode) an internal error could
occur if the prototype instantiation of a member function of a class
template caused a real instantiation of the same class template.  The
internal error would only occur if the class template contained a member
function template with default arguments.  This has been fixed.

  template <class T> struct A {
    template <class T2> void g(T2, int i = 1){}
    void f() {
      A<int> ai;
      ai.g(1);
    }
  };
  int main() {
    A<int> ai;
    ai.f();
  }

4/18/01  Compiler-generated flag on lowered cast to derived class

The IL lowering process applied to an explicit cast to a derived
class produced a similar cast marked as compiler-generated.
Now, the compiler_generated flag is FALSE in such cases.

4/16/01  End position on operand for implicit "this" expression

The end position is now set (in versions with EXTRA_SOURCE_POSITIONS_IN_IL
set to TRUE) on operands created for implicit uses of "this" (e.g.,
calling a member function).  This is in the an_operand entries used internally
by the front end, rather than in the expressions in the IL.

4/16/01  C99 lowering of complex constants and
         RECORD_CONSTANT_EXPRESSIONS_IN_IL

The combination of C99 lowering and having RECORD_CONSTANT_EXPRESSIONS_IN_IL
set to TRUE (an unusual configuration) did not work right for some cases
involving lowering of complex constants.  Now fixed.

  int main() {
    _Complex long double c = 57.0;
    const _Complex long double x[] = {0, -c * __I__};
  }

4/16/01  C99 extern inline function definitions out-of-lined

In C99 mode, the front end now keeps inline function bodies in translation
units where a declaration marked "extern" also appeared.  Previously, such
functions were discarded if they were unused and removal of unneeded IL
entities was done. For example:

  inline void f() {}
  extern void f();  /* Causes an out-of-line copy to be kept. */

4/16/01  Microsoft compatibility: reinterpret-like cast of pointer-to-member
         can be a constant

In Microsoft mode, the front end now treats as a constant a pointer-to-member
constant that is cast to another pointer-to-member type with an unrelated
member type.  However, the class types associated with the pointer-to-member
types must be related.  For example:

  struct B {};
  typedef void (B::*PMB)();
  struct D: B {
    void f(int);
    static PMB x[];
  };
  __declspec(selectany) PMB D::x[] = { (PMB)&D::f };

This example used to trigger an error because the initializer "(PMB)&D::f"
was not treated as a constant expression.  Now it is accepted in Microsoft
mode.

4/16/01  Enumerator expression that is template-dependent member of
         class, in prototype instantiation

The processing for the expression of an enumerator was incorrect in
a prototype instantiation of a template when the expression is
a template-dependent member of a class.  One consequence was an
abort in end_of_scope_symbol_check ("il-entry parent-class mismatch").
Now fixed.

  template <class T> struct A {
    enum { a = 1 };
  };
  template <class T> void f() {
    enum { x = A<T>::a };  // Aborted with --parse_templates or
                           // --strict
  }

4/16/01  IL write-read error caused by reference to member qualified with
         dependent type

When doing nonclass prototype instantiations with a configuration that uses
the hidden name table, the front end could produce an inconsistent IL tree
if the declaration of an entity in a class template member had a name that
was also used with a dependent qualifier.  For example:

  template<typename B> struct S: B {
    S(int x): { B::x = x; }  // name of parameter x is also used with
  };                         // dependent qualifier "B::".

This could manifest itself as an IL write-read error.  It is now fixed.

4/16/01  Missing parentheses in generated code with "&" (modified version)

The C code generated for certain address expressions was missing
a set of parentheses on a use of the "&" operator, in a case that
apparently cannot be reproduced with the IL generated by the unmodified
Front End.  (It requires creation of a combination of IL operators
that we never produce.)  The parentheses have now been added to avoid
any precedence confusion.

4/13/01  Spurious error on prototype instantiation of aggregate initializer

When doing nonclass prototype instantiations, the front end would issue a
spurious error on an aggregate initializer containing multiple values when
it initializes a static data member whose type is a template parameter.
For example:

  template<typename T> struct S {
    int a, b;
    static T x;
  };
  template<typename T> T S<T>::x = { 7, 8 };  // Used to trigger spurious
                                              // "missing brace" error.

This is now fixed.

4/3/01   Return type of main() in C99 mode

A main() function with a return type different from int now produces a warning
in default C99 mode and an error in strict C99 mode.  (Previously, no
diagnostic was issued.)

  void main() {}  /* Warning or error in C99 mode. */

4/3/01   Microsoft compatibility: __declspec ignored on template type
         parameter declaration

The Microsoft compiler accepts and ignores a __declspec modifier on a
template type parameter declaration.  We now emulate this behavior
in Microsoft mode.  A warning is issued.

  template <class __declspec(dllexport) T> class A { };

4/2/01   Extraneous deallocation points for variable length arrays (VLAs)

The front end used to generate VLA object deallocation points
(stmk_vla_dealloc statement entries) at the end of many statement blocks
that followed (but didn't contain) the definition of a VLA object.

  void f(int n) {
    int A[n];
    {}  /* Used to generate an extraneous stmk_vla_dealloc entry for A
           at this point. */
  }  /* stmk_vla_dealloc entry at this point is valid. */

This is now fixed.  (See also Change entry of 9/8/00.)

3/30/01  Malformed float constants accepted in Microsoft mode

The MSVC++ compiler accepts floating-point constants like .1.234.
Everything at or after the second decimal point is ignored.  Now,
in Microsoft bugs mode, we do the same.

3/25/01  Template instantiation can cause spurious access errors

In certain unusual circumstances, the access checking state was not
correctly restored after a template instantiation, resulting in spurious
access errors.  This has been fixed.

  struct A {
    template<class> struct B {
      void f(int = 0);
    };
    class C {
     int i;
      void g() {
        B<int> a;
        i = 0;
      }
    };
  };

3/22/01  Treatment of using-declaration duplicating a built-in declaration

Using declarations are not added to the IL when they duplicate an equivalent
declaration already visible in that scope.  However, when the type in the
using-declaration was previously only visible as a built-in type, it need not
be inhibited from appearing in the IL.  Specifically, in Microsoft mode:

  namespace std { typedef unsigned int size_t; }
  using std::size_t;  // Used to not appear in the IL because the size_t type
                      // is already implicitly visible in the file scope (in
                      // Microsoft mode).  Now it is added to the IL.

3/22/01  Abort on class or enum declaration in template argument when
         source sequence entries are enabled

Under relatively rare circumstances, the front end would sometimes abort with
an internal error when a class or enum type was first declared in a template
argument (e.g., "vector<class X>").  The problem occurred only when source
sequence entries are enabled.  This is now fixed.

3/22/01  Error checking on non-positive VLA size after inlining

An error is now issued for a non-positive constant variable-length
array size that is visible only after inlining.

  inline int neg() { return -1; }
  int main() {
    int b[neg()];  // Now gets an error when inlining is done
  }

3/18/01  Improved error message on labeled declaration in C99 mode

The error message has been improved on a labeled declaration in
C99 mode.  (The C99 syntax allows a label only on a statement,
not on a declaration.)  Also, the diagnostic is now a warning
in non-strict C99 mode.

  int main() {
    int a;
  label:
    int b;
  }

3/15/01  Internal error on invalid C99 _Pragma operator

An internal error would occur if an ill-formed _Pragma operator
followed by an end-of-file was encountered while flushing tokens
because of a syntax error.  This has been fixed.

  int x _Pragma 

3/14/01  Abort in inlining with non-inlinable function

An abort in inlining has been corrected.  The abort came up on
a call of a non-inlinable function that has more than one
argument, where the first argument must be evaluated for
side effects but need not be stored in a temporary because the
corresponding parameter is not used, and some other argument is
non-constant.

  int g();
  inline int f(int, int j) { int l = j; }  // Not inlinable because of
                                           // missing return
  int main () {
    int i = f(g(), g());
  }

3/12/01  Incorrect parent pointer in static data member template entry

When using PROTOTYPE_INSTANTIATIONS_IN_IL, the template entry created for
a static data member of a template class had an incorrect parent pointer.
This has been fixed.

  template <class T> struct A {
    static int i;
  };

3/10/01  Microsoft C mode: plain char is the same as signed char or unsigned
         char

In Microsoft C mode, the "plain" char type (i.e., char without an explicit
signed or unsigned) is equivalent to either signed char or unsigned char,
depending on configuration.  That is, in this mode there are only two
distinct char types instead of the three required by the C standard.

3/10/01  Abort ("user_convert_operand: unusable conversion") on ambiguous
         conversion of operand of "?" operator

An abort in user_convert_operand has been eliminated.  The abort
occurred on processing a "?" operator in which one operand can be
converted to the type of the other, but only ambiguously.

  struct QCString {
    QCString( int size );			
    QCString( const QCString &s ) {}
    QCString( const char *str );		
    operator const char *() const;
  };
  struct QString {
    QCString utf8() const;
  };
  void foo() {
    int err = 0;
    QString serv;
    err ? 0L : serv.utf8();  // Formerly got abort
  }

3/9/01   Missing error check on default nontype template argument

A nontype template argument may not reference an external entity.  This
test was omitted when the value came from a default template argument.
This could result in an internal error.  Now fixed.

  template <char *p = "xxx"> struct A { } ; 
  A<> a;

3/9/01   Error recovery problem: abort in type_pointed_to after error
         on cast to virtual base

An error recovery problem has been corrected.  It caused an internal
error in type_pointed_to after an error on an invalid cast to a
virtual base class.

  class bar {
  public:
    int j;
    virtual void f();
  };
  class blah : public virtual bar {
  public:
    int k;
  };
  class foo : public blah, public virtual bar {
  public:
    int i;
  };
  void f(bar*x) {
    ((foo*)x)->f();  // Formerly caused abort after error
  }

3/9/01   static_cast between enum types allowed

The standards committee ruled in Core Issue 128 that static_cast
between enums is allowed.  The Front End now allows that.

  enum E1 { ke1 };
  enum E2 { ke2 };
  int main () {
    static_cast<E2>(ke1);   // Now allowed
  }

3/5/01   Diagnostic on fields involving variable length array types

The front end now diagnoses the use of variable length array types in field
declarations.  In the past, such uses sometimes led to internal errors.

  void* f(int n) {
    typedef int VLA[n];
    struct A {
      VLA a;  /* Used to trigger an internal error.  Now an ordinary error. */
    };
    static struct A a;
    return &a;
  }

3/5/01   Name mangling change for partially specialized classes

The name mangling for partially specialized classes has been changed
slightly.  The special double template argument list used for
partially specialized classes in parent types in qualified names
is now suppressed for any such types that occur inside template argument
lists.  For example, when A<T1, T2>::x appears in a template argument
list, it is now encoded simply as A<T1, T2> even if it is partially
specialized.  This is an ABI change.

3/5/01   Nonstandard anonymous union types now marked in IL

The class types of anonymous-union-like constructs are now marked as such
provided the type itself is anonymous (as opposed, e.g., to being named
through a typedef declaration).  A new flag is_nonstd_anonymous_union_type
was added to the class/struct/union variant of a_type entries (IL CHANGE,
but only in configurations where ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE).

  typedef struct {
    int i;
    double d;
  } Anon;
  struct S {
    Anon;     // Nonstandard anonymous union construct but the associated type
              // "Anon" is not anonymous and therefore not marked.
    struct {  // Nonstandard anonymous union construct with an unnamed type:
      char c; // marked as such in the IL entry for that type.
      long l;
    };
  };

3/4/01   C99 __NAN__ and __INFINITY__

In C99 mode, there are now predefined constants __NAN__ and
__INFINITY__, which are Not-a-Number and positive Infinity values
of float type.  These are intended for the use of library
writers in implementing the C99 NAN and INFINITY macros.

[3/16/01:] The floating-point constant routines have been made
aware of IEEE floating point, under control of the configuration
macro TARG_HAS_IEEE_FLOATING_POINT.  NaN and Infinity constants
are now output in compilable code as (0.0/0.0) and (1.0/0.0),
respectively, which produce the required values.

3/2/01   Loop in preprocessor on #if within macro argument

The preprocessor looped as a result of processing a macro invocation
in the expression of a #if directive that appears within a macro
argument of a surrounding macro invocation, when there is a previous
macro argument at the top level that includes a macro invocation.
Now fixed.

  #define A(U)    ((U) + (U))
  #define S(U, V) ((U) * (V))
  #define T 1
  const int X = S(A(0),
  #if T == 1
    T
  #endif
  );

3/2/01   Default arguments of friends of class templates

Lookups during the instantiation of default argument expressions of
friends of class templates would, in certain circumstances, incorrectly
find names from the prototype instantiation of the enclosing class instead
of names from a real instantiation.  This could result in an internal
error or other incorrect behavior.  This has been fixed.

  template <class T, class T2> struct A {
    static int si;
  };
  template <class T> class B {
    template <class T2> friend void f(B<T>& s, T2* p, int i = A<T,T2>::si );
  };
  int main() {
    B<int> b;
    f(b, (char*)0);
  }

3/1/01   Lowering of compound literals in parameter VLA bound expressions

C99 compound literals in bound expressions of variable-length-array
parameter types were not lowered properly.  Now fixed.

  void f(int x[(int){3}][(int){1}]) {}

3/1/01   Lowering of compound literal with variably-modified type

The code generated by lowering of a C99 compound literal with
a variably-modified type was not correct.  Now fixed.

  void f() {
    int m = 10, o = 10;
    int (*p1)[m][o] = (int(*)[m][o]){0};
  }

3/1/01   Missing initializer for static data member definitions

The front end used to not diagnose missing initializers on definitions of
const static data members.

  struct S {
    static bool const Yes = true;
    static bool const No;
  };
  bool const S::Yes;  // OK: initializer already seen
  bool const S::No;   // Used to be OK, now an error: missing initializer

This is now fixed.

3/1/01   C++-generating back end: suppressing implicit related-class
         conversions

The C++-generating back end now suppresses related-class casts
that are implicit in the source program.

  struct A {
    void f() throw () {}
  };
  struct B : A {};
  void f() {
    void(B::*pf)(void);
    pf = &A::f;  // Implicit cast no longer put out
  }

3/1/01   RECORD_CONSTANT_EXPRESSIONS_IN_IL: switch case constants

When RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, switch case constants
that are implicitly converted to the switch expression type now have
a recorded expression that gives the original unconverted constant.

3/1/01   Missing diagnostic on invalid file scope C99 STDC pragma

A STDC pragma in the global scope may only appear between declarations.
A diagnostic is now issued.

  int x[] = {1,
    #pragma STDC FP_CONTRACT ON
             2};

3/1/01   C-generating back end: VLA declarations in middle of blocks

The C-generating back end now puts out an extra set of braces around
variable-length array declarations in the middle of a block to avoid
having the code rejected by C compilers that do allow VLAs but do
not allow mixed declarations and executable statements (e.g., gcc).

  void f() {
    int n = 10;
    int x[n][n];
    x[5][5] = 37;
    int y[n][n];  // Extra brace put out before this line
  }

3/1/01   Undiagnosed missing comma

The front end sometimes failed to diagnose a comma that should have preceded
a designator.

  struct I { long l; };
  struct S { struct I i; };
  struct S s = { { 3 } .i = { 2 } };  // Used to be accepted without a
                                      // diagnostic; now an error.
This is now fixed.

3/1/01   Abort on invalid designated initializer

The front end used to abort when encountering certain designated initializers
for flexible array members inside unions.

  union U {
    struct S {
      char c;
      _Bool b[];
    } s;
  } u = { .s = { .b = { 0 } } };  // Error: cannot initialize flexible array
                                  // member (but used to abort).
This is now fixed.

3/1/01   C99 __generic builtin operator, complex-typed expressions

The C99 builtin operator __generic, provided to allow implementation of
the <tgmath.h> type-generic math header, has been enhanced to deal
with complex expressions of mixed types.  The C99 standard fails
to specify the behavior in this case, which is probably an oversight
because it's needed for the "pow" function.

  double _Complex cpow(double _Complex, double _Complex);
  int main () {
    float _Complex fc = 0;
    double rd = 0;
    double _Complex dc = __generic(fc, rd,,,,,cpow,,)(fc, rd);  // Works now
  }

3/1/01   Abort on ill-formed C99 _Pragma operator

An abort would occur on certain ill-formed C99 _Pragma operators.  This
has been fixed.

  _Pragma // followed by end of file

3/1/01   C99 compound literals not considered "side effects"

The creation of a C99 compound literal is no longer considered
a "side effect" in an expression.  This change allows warnings
for declared-but-not-referenced variables to come out in cases
where the variables are initialized with a compound literal.

  void f() {
    int i = (int){1};  // Now gets a warning
  }

2/28/01  Lowering of C99 designated initializers: bad code generated

In some obscure cases involving designated initializers for unions
that initialize different members of the same union, the generated
IL was incorrect, and therefore the generated code was incorrect.
There is also an obscure case involving array initializations and
skipped elements and re-initialization.  Both are now fixed.

2/27/01  Microsoft compatibility: internal error on _asm with macro reference

In version 2.45, an internal error would occur when a Microsoft _asm
included a reference to a macro.  This has been fixed.

  #define ONE 0x01
  void f() {
    _asm int ONE;
  }

2/27/01  More information in il_to_str output of some constants

The il_to_str routines now put out more information on ck_dynamic_init
and ck_init_repeat constants.  These constants are output output in
debugging output.

2/22/01  Constant expression for local constant variable not recorded in IL

Even when RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, the front end used to
not record a reference to a local constant variable in constants that were
constructed from such a reference.

  void f(int k) {
    int const ic = 12;
    switch (k) {
      case ic:  // Constant for case label did not point to an expression
        break;  // representing a reference to the variable "ic".
    }
  }

This is now fixed.

2/20/01  Spurious error in member partial specialization declaration

If a partially specialized class is declared in a class template,
and the template parameter list of the primary template has a nontype
template parameter with dependent type, a lookup error could occur
when processing the definition of the partial specialization.  This
has been fixed.

  template < class T > class A {
    template <typename T::X, class Z> class B {};
    template <class T2> class B<1, T2> {};
  };

2/20/01  Sequence to physical line number translation could produce incorrect
         results

The routine conv_seq_to_physical_file_and_line could produce incorrect
results when making use of a previously cached conversion result.
This has not been observed in an unmodified front end because of the
way in which that routine is used, but could occur in a modified front
end that does additional calls to conv_seq_to_physical_file_and_line.
This has been fixed.

2/19/01  Command-line option to disable special <stdarg.h> processing

The front end can be configured to pass references to the macros defined
in stdarg.h to the output instead of expanding the macros as would usually
be done.  The --no_stdarg_builtin option has been added to permit the
special handling of <stdarg.h> to be disabled if it is enabled by default.

2/15/01  Deduction fails with dependent pointer to member and explicit
         template arguments

Template argument deduction would fail (resulting in an error or in
unexpected results from overload resolution) when the function parameter
list contains a pointer-to-member type whose member class type is
dependent, and where the call explicitly specifies some template
arguments.  This has been fixed.

  struct A { void f() {} };
  template <class T, class T2> void g(void (T2::*)()) {}
  int main() {
    g<int>(&A::f);
  }

2/14/01  Internal error when using non-alternate IL file format

An internal error would occur when compiling a program that uses
partial specialization of class templates with a version configured
to use an IL file in the non-alternate IL file format.  This has
been fixed.

  template <class T, class T2> struct A { };
  template <class T> struct A<T*, T*> { };

2/13/01  C99 mode, C-generating back end: VLAs in for-init declarations

The C-generating back end did not correctly process declarations of
variable-length arrays in the initialization section of for loops,
and the resulting generated C did not compile.  Now fixed.

  int main() {
    int j = 10;
    for (int i = 1, a[j]; i < j; i++) { a[i] = 0; }
  }

A similar problem in the C++-generating back end has also been fixed.

2/12/01  RECORD_CONSTANT_EXPRESSIONS_IN_IL, enums with typedef type

In some cases involving enum constants whose values are given by
expressions, and whose type is attached to a typedef, the expression
recorded for the implicit cast to the typedef type when
RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE retained the expression
associated with the constant definition, when that should have been
cleared.  This caused incorrect output from the C++-generating back
end on such cases.  Now fixed.  [Patch sent out 2/14/01.]

  typedef enum {a, b=a+1} eType;
  void f() {
    eType v=b;  // C++-generating back end output had "a+1" instead of "b"
  }

2/12/01  Spurious error on partial specialization within class template

Spurious errors could be issued on certain partial specialization
declarations that appear in the definition of a class template.  This
has been fixed.  [Patch sent out 2/14/01.]

  template < class T > class A {
    template <int I, class U> class B {};
    template <class V > class B<T::X, V> {};
  };

2/11/01  C-generating back end and RECORD_CONSTANT_EXPRESSIONS_IN_IL

The (unusual) combination of RECORD_CONSTANT_EXPRESSIONS_IN_IL set to
TRUE and the C-generating back end did not work right.  The back end
attempted to output some unlowered expressions and got internal errors.
Now fixed.

2/11/01  C99 aggregate initialization: abort ("bad type on eok_comma")

In some complex cases involving C99 nonconstant aggregate initialization,
elided braces, and use of designated initializers to re-initialize
a member already initialized, an abort could occur.  Now fixed.
[Patch sent out 2/14/01.]

  struct A { const int i; };
  struct B { struct A a; };
  int f();
  int main () {
    struct B b[] = { { f() , .a = 1 } };  // Formerly aborted
  }

[Another similar case was fixed on 2/27/01.]

2/11/01  C99 aggregate initialization: incorrect processing for
         const struct member initialized from non-const expression

C99 aggregate initialization did not correctly handle some cases
where the initializer expression has a class type and the member being
initialized has the const-qualified version of the same type.
Now fixed.  [Patch sent out 2/14/01.]

  struct A { int i; };
  int main () {
    struct A aa = {0};
    const struct A a[] = {aa};  // Formerly got error in C99 mode
  }

2/10/01  C++-generating back end: output of template-dependent switch
         case values in prototype instantiations

Template-dependent switch case values of the form T::name, where
T is a template parameter, were not put out correctly in prototype
instantiations in the C++-generating back end in some cases.
A generated name like __T12345678 was put out instead.  Now fixed.
[Patch sent out 2/14/01.]

  template <class T> void f() {
    switch (T::type(1)) {
      case T::i:;
    }
  }

2/9/01   Compiling multiple translation units

It is now possible to compile multiple source files and produce a
single merged IL tree.  This mode is enabled by the macro
COMPILE_MULTIPLE_TRANSLATION_UNITS.  Declarations with external
linkage are compared between the translation units to ensure that
they match, and errors are issued if not.  Note that this is not
the same as the mode that already existed that is enabled by
COMPILE_MULTIPLE_SOURCE_FILES.  In that mode, multiple files are
compiled but they are kept completely separate, and a separate
IL tree is produced for each file.  The eccp script has a new
command-line option --multi_trans_unit which indicates that all
the files specified on the command-line should be compiled
together as multiple translation units.

2/9/01   sizeof expression involving local variables, with
         RECORD_CONSTANT_EXPRESSIONS_IN_IL

When RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, a sizeof operator
that appears inside a function in an integral constant expression
for an array size and references a local variable produced
incorrect IL that could cause aborts in some cases.  Now fixed (by
eliminating the recorded expression in such cases).  [Patch sent
out 2/14/01.]

  int main() {
    int i;
    int ar [ sizeof(i) ];
  }

2/9/01   C99 lowering of cast of imaginary to bool

The code produced by C99 lowering of a cast from imaginary to bool
compares the operand to a zero constant.  The constant had imaginary
type, however, and should have real type.  Now fixed.  [Patch sent
out 2/14/01.]

2/9/01   C99 mode: sign inversion in imaginary divide operation

In C99 mode, the division of a real floating point value by an imaginary
floating point value was erroneously represented as an ordinary floating point
division.  This resulted for example in "0.5/__I__" being (incorrectly)
treated equal to "0.5*__I__" instead of "-0.5*__I__" (the latter is correct).
IL CHANGE: a new operator eok_jdivide has been introduced to represent these
operations (it is eliminated when LOWER_COMPLEX is TRUE).  [Patch sent
out 2/14/01.]

2/9/01   Long double requires additional digit for full precision

When a long double value is emitted as a string in the C or C++ generating
back ends, the resulting string did not contain enough digits to
guarantee that all of the bits of the value were represented (one
more digit was needed).  This has been fixed.  [Patch sent out 2/14/01.]

2/8/01   Checking of template-dependent switch case values

Spurious errors about duplicated values were sometimes issued for
template-dependent case values in switch statements when prototype
instantiations of functions are done (e.g., in strict mode).  Now fixed.
[Patch sent out 2/14/01.]

  template <class T> struct A {
    void f(int i) {
      switch (T::name(i)) {
        case T::value_1:
        case T::value_2:  // Formerly got spurious error
          break;
      }
    }
  };

2/8/01   Redeclaration of new/delete operators with differing exception
         specification

Although they are predeclared, the front end allows the explicit declaration
of operator new and operator delete with an exception specification that is
different from that of the predeclared type.  However, the explicitly
declared specification used to be ignored, which could result in surprising
diagnostics on additional redeclarations.  For example:

  void operator delete(void*);  // OK in strict mode
  void operator delete(void*);  // Used to cause an error in strict mode:
                                // conflict with predeclared "throw()"
                                // specification.

This is now fixed by retaining the throw specification of the first explicit
declaration.  [Patch sent out 2/14/01.]

2/7/01   Extra position information on explicit declaration of size_t in
         Microsoft mode

The front end used to not record extra position information (available when
EXTRA_SOURCE_POSITIONS_IN_IL is configured TRUE) for explicit declarations
of the size_t typedef in Microsoft mode (in that mode, size_t is predeclared).
This is now fixed.  [Patch sent out 2/14/01.]

2/6/01   Microsoft compatibility: spurious error on in-class specialization

A spurious error would result when a Microsoft in-class specialization
that includes an explicit template argument list appears in a nested
class of a class template.  This has been fixed.  [Patch sent out 2/14/01.]

  template < class > class A {
    class B {
      template < class > void f(){}
      template <> void f<int>(){}
    };
  };

2/2/01   Inaccurate declared type information in routine entries

The front end records the type as declared in the source in routine entries
and attempts to reuse the type already associated with the routine for that
purpose.  However, in configurations where EXTRA_SOURCE_POSITIONS_IN_IL or
RECORD_NAME_IN_PARAM_TYPE_ENTRY are TRUE, this often results in invalid
information regarding the names and positions of parameters.  This is now
fixed.  [Patch sent out 2/14/01.]

2/2/01   Source positions on preserved expressions for constant expressions

When RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE, when constant expressions
are replaced by constants the original expression is preserved and
pointed to by the constant.  For the simplest preserved expressions,
those for references to const variables replaced by their values,
the expression node for the preserved expression did not have the
source positions recorded when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE.
The positions are now set.  [Patch sent out 2/14/01.]

2/2/01   C++-generating back end: nonconstant scalar compound literals

The C++-generating back end aborted on attempting to output compound
literals that are scalar and nonconstant (e.g., in C99 mode).
Now fixed.  [Patch sent out 2/14/01.]

  int main() {
    int i = 1;
    int *p = &(int){i+1};
  }

2/1/01   Error in lowering of C99 nonconstant initialization of union
         using designated initializers

The lowering for C99 did not correctly handle lowering a nonconstant
initialization of a member of a union other than the first or second.
Now fixed.  [Patch sent out 2/14/01.]

  union U { float x; int y; int i; };
  int main () {
    int i = 1;
    union U u = { .i = i+1 };
  }

2/1/01   Spurious conversion errors in some configurations

When INTEGER_VALUE_REPR_IS_A_HOST_INTEGER was configured FALSE the front end
could sometimes issue an error when converting a very large integer constant
to a floating point value, even though in fact it could represent the very
large value internally.  This is now fixed.

1/31/01  Missing default member functions in prototype instantiations

The front end used to omit the generation of default member functions in
prototype instantiations of class templates.  This could lead to errors
when parsing templates that called such default members.  [Patch sent
out 2/14/01.]

  template <class T> struct X { X(); }; // Contains generated copy-constructor
  template <class T> X<T>::X() {
    new X<T>(*this);  // Calls generated copy constructor.  Used to trigger
  }                   // a spurious diagnostic.

This is now fixed.

1/29/01  Lowering of for-initializations in C99 mode can result in
         dropped initialization

The lowering of a complicated initialization in a for-initialization
statement in C99 produced incorrect IL.  One consequence of this
incorrect IL was that the initialization code was omitted.  Another
possible consequence is an IL write/read error.  The problem did not
occur when source sequence entries are generated.  [Patch sent out
2/14/01.]

  int main() {
    _Complex long double a = 37.0;
    for (_Complex long double* x[] = {(_Complex long double[]){a}};;) {
    }
  }

1/28/01  C-generating back end output of union initializer with
         designator

The C-generating back end put out invalid code for an initialization
of a local union that follows an executable statement, when the
member initialized is not the first member of the union.  The problem
is more widespread when LOWER_DESIGNATED_INITIALIZERS is FALSE.
[Patch sent out 2/14/01.]

  union U {
    char c;
    unsigned long long ll;
  };
  int main() {
    int i;
    i = 1;
    union U u1 = {.c = 1, .ll = 2};  // Generated code was incorrect
  }

1/28/01  Abort on "?" operator with
         ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS set to TRUE

When ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS is TRUE and
a "?" operation is replaced by one of its operands and the result of
the "?" operator is an lvalue, a flag was set incorrectly, which
might flip a bit of a memory address and cause an abort later (in
other words, whether you get an abort is dependent on what that
bit was in the original address, so such cases didn't always abort).
Now fixed.  [Patch sent out 2/14/01.]

  int func(int n) {
    return n ? n : 1 ? n: n;
  }

1/26/01  Abort when parsing members of classes nested in templates for
         some configurations

When both NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
PROTOTYPE_INSTANTIATIONS_IN_IL are TRUE the front end used to abort while
parsing members of classes nested in class templates.

  template<class T> struct X {
    struct N { T f(); };  // Used to cause an abort with --parse_templates
  };

This is now fixed.

1/26/01  Mangled names for constructors in unnamed classes that get
         names from typedefs

The generated constructors of classes that are unnamed but get a name
for linkage purposes from a typedef now get mangled names based on the
linkage-name of the class.  Formerly, they were unnamed.  [Patch sent
out 2/14/01.]

  struct X {
    X();
    ~X();
  };
  typedef struct {
    X x;
  } A;
  A a;

The lack of a name on the constructor led to an abort in make_module_id
in some unusual cases.

1/26/01  Microsoft compatibility: __declspec specifiers on enum definitions

In Microsoft mode, the front end now accepts the same __declspec specifiers
on enum definitions as on class definitions.  For enums, however, only the
uuid variant of these extended specifiers is recorded in the IL.
For example:

  enum __declspec(dllexport) E {};  // Accepted but the dllexport attribute
                                    // is not recorded
  enum __declspec(uuid("11111111-1111-1111-1111-111111111111") E;
                                    // Accepted and uuid string is recorded
  enum __declspec(uuid("22222222-2222-2222-2222-222222222222") E {};
                                    // Error: incompatible uuid specifier

IL CHANGE: new fields (uuid_string and uuid_variable) were added to the 
integer variant of a_type (when MICROSOFT_EXTENSIONS_ALLOWED is TRUE).

1/25/01  Performance bug in module-id routine

A bug in the routine that generates the module-id caused it to loop
through the all of the file scope functions instead of stopping on the
first one that could be used to form the module-id.  This has been fixed.

1/25/01  C++-generating back end: missing throw specifications

In some cases, the C++-generating back end did not put out throw
specifications that were present in the source.  Now fixed.
[Patch sent out 2/14/01.]

  void f() throw(int) {}
  void (*pf)() throw(int)=f;  // throw-specification here was dropped

1/25/01  Error recovery problem: call of member function on volatile
         rvalue of class with bitwise copy constructor

An abort in error recovery has been corrected.  The problem came
up in a case that involves calling a member function of a class with
a generated bitwise copy constructor, with an object that is volatile
(which therefore cannot be copied by the generated copy constructor).
[Patch sent out 2/14/01.]

  struct A {int i; void f();};
  volatile A fv();
  int main() {
    volatile A tv;
    fv().f();  // Formerly aborted after error
  }

1/24/01  Spurious error on dependent const variable definitions

If the definition of a variable with a const type has no initializer
a diagnostic used to be issued when the underlying type was dependent.
This was unwarranted when the type could become a class type with a
default constructor after template argument substitution.

  template<typename T> void f(T) {
    T const x;  // Used to trigger an error; fine now.
    T *const p; // Still an error (missing initializer).
  }

This is now fixed.  [Patch sent out 2/14/01.]

1/24/01  Friend declarations in prototype instantiations

When not doing dependent name lookup, the front end does some special
processing when looking up unqualified names during the prototype
instantiation of a class template with a dependent base class.  If the
name is not found by normal lookup, it essentially considers the name
to be a member of the dependent base class.  As a result, in the
example below, the IL for the friend declaration refers to the class
T::X.  When dependent lookup is being done, the friend declaration
refers to an X that is associated with the prototype instantiation.

The special processing that is done in default mode is no longer done
when looking for the name in a friend declaration (i.e., the behavior
for this case in default mode is now the same as it is when using
dependent name lookup)

  template <class T> class A : public T {
    friend class X;
  };

1/23/01  Prelinker loop when the module-id includes the compilation time

The front end creates a "module-id" that is used to create names that
are required to be unique across an entire program (for example, when
creating the names of unnamed namespace members).  In certain unusual
circumstances, the time and date of the compilation are used as
components of the module-id.  This caused problems when templates with
external linkage include types from unnamed namespaces in their
signatures.  Because the module-id would change each time the file was
compiled, and because the module-id is incorporated in the mangled
name, the prelinker could not successfully assign the instantiation to
a file and end up with an instantiation of the expected function,
resulting in a prelinker loop.  This is now fixed.  [Patch sent out
2/14/01.]

  namespace {
    struct X {};
  }
  template <class T> void g(X, T){}
  template <class T> void f(T t) {
    X x;
    g(x, t);
  }

  template void f(int);

1/23/01  Warning on returning address of local variable

The front end now issues a warning on a return statement that returns
the address of a local variable.

  int *f() {
    int i = 1;
    return &i;
  }

1/22/01  Incorrect lookup in "p.template f<>()" during prototype instantiation

When doing nonclass prototype instantiations, in examples such as the
following, the lookup of "f" would find the global scope function f instead
of using the f that is a member of the class specified by template parameter
T during a real instantiation.  This has been fixed.  [Patch sent
out 1/23/01.  Correction patch sent out 2/14/01.]

  void f();
  template <class T> void g(T t) {
    t.template f<T>();
  }

1/20/01  Superseded code to set instance-required flags in IL lowering
         removed

Some code in lower_il.c that set instance-required flags for virtual
member functions of templates has been removed.  The code dealt with
the interaction of decider functions and virtual function tables.
It's now unnecessary, because the more general code in func_def.c
takes care of setting the necessary flags.

1/20/01  C99 compound literals in static initializers

The front end failed to diagnose errors in certain cases involving
use of compound literals in initializers for static variables.
This caused aborts later in some cases.

  struct A {int y;};
  struct B {struct A a;};
  struct B b = { (struct A){1} };  // Now gets an error

[Patch sent out 1/23/01.]

1/20/01  Microsoft compatibility: abort in get_integer_attributes

An abort in get_integer_attributes in Microsoft C mode has been fixed.
The cause was an implicit cast from a pointer type to an integral
type, where the source was an integral constant explicitly cast to a
pointer type.

  int main() {
    int x = (void *)-1;  // Formerly aborted in Microsoft C mode
    return 0;
  }

1/19/01  IL lowering: code to zero allocated array of classes

IL lowering is now capable of generating code to zero an array allocated
in a "new", when the array element type is a class with a destructor but
no constructor and the explicit initialization "()" is specified.
Previously, IL lowering aborted with an error in elem_dynamic_init.

  struct T { int x,y; ~T(); };
  int main() {
    T *p = new T[7]();
  }

[Patch sent out 1/23/01.]

1/19/01  Linux configuration has incorrect alignment of long long

The defines_linux.h file did not specify an alignment for long long.
This resulted in the use of the default value, which is not correct
for Linux.  This has been fixed.

1/19/01  Spurious error on explicit destructor call in prototype instantiation

When doing nonclass prototype instantiations, a spurious error was issued
on an explicit destructor call where the destructor type name was a typedef
to a template parameter type.  This has been fixed.  [Patch sent out
1/23/01.]

  template <class T> void f(T t) {
    typedef typename T::some_type xxx;
    t.x->~xxx();
  }

1/19/01  Suppression of "expression has no effect" warning on comma
         expressions

The "expression has no effect" warning is now suppressed on comma
expressions where the second operand is cast to void.  Formerly,
a cast to void on the first operand, or on the entire expression,
would suppress the warning, but not a cast on the second operand.

  ((void)0, (void)0);  // Formerly got a warning

1/17/01  Missing function body in nested class template strings

When a nontemplate class contained a class template, the bodies of member
functions of the class template were missing from the template string.
This has been fixed.  [Patch sent out 1/23/01.]

  struct A {
    template <class T> struct B {
      void f() {}  // emitted as "void f()" (no {} or semicolon)
    };
  };

1/17/01  Use of invalid pointer could cause undefined behavior

In versions that use the hidden name table, it is possible for the
scope stack to be reallocated during pop_scope processing.  This
could result in the use of an invalid scope stack entry pointer.
The use of the invalid pointer causes an IL read/write error on
some versions and could in theory, result in other kinds of behavior
such as aborts, etc.  This has been fixed.  [Patch sent out 1/23/01.]

This example results in the use of an invalid pointer on versions
that use the hidden name table.

  struct S2 { struct S3 { struct S4 { struct S5 { struct S6 {
    struct S7 { struct S8 { struct S9 { }; }; }; }; }; }; }; };

1/17/01  #ident/#pragma ident string incorrectly rendered by C/C++-generating
         back ends

The C- and C++-generating back ends used to replace tab characters in
#ident/#pragma ident directives by their escaped form ('\t').
This is now fixed.

1/16/01  Lowering of an aggregate initializer containing a complex expression

When DO_C99_IL_LOWERING is TRUE, the front end failed to entirely remove
IL references to complex types in cases where an aggregate initializer
contained a nonconstant complex expression.

  int main() {
    _Complex double z = 1.2;
    _Complex double w[] = { 0.0, z*__I__ };  // Lowered initializer used to
  }                                          // refer to complex type.

This is now fixed.  [Patch sent out 1/23/01.]

1/16/01  Support for complex unary minus in C++-generating back end

Support for the complex unary minus operator had accidentally been left out
of version 2.45 of the C++-generating back end.  This caused internal errors
when the operator had to be rendered.

  void f() {
    _Complex double a = __I__, b = -a;  // Used to trigger an internal error.
  }

This is now fixed.  [Patch sent out 1/23/01.]

1/16/01  Errors on qualified references to names from base classes
         in templates

A bug introduced in 2.44 caused spurious errors on certain references
to members of dependent base classes in templates, when dependent name
processing is being done.  Now fixed.  [Patch sent out 1/23/01.]

  template <class T> struct A {
    template <class T2> void f(T2);
  };
  template <class T> struct B : A<T> {
    void h() {
      this->f(1);  // Formerly got an error
    }
  };
  int main() {
    B<int> bi;
    bi.h();
  }

1/16/01  C++-generating back end: missing parentheses in "->*" output

Parentheses were sometimes missing around the first operand of a "->*"
operation as put out by the C++-generating back end.  This could cause
the generated code to be uncompilable.  Now fixed.  [Patch sent out
1/23/01.]

  class A {
    void f(A *obj) {
      typedef int A::* T;
      T p;
      (&obj[0])->*p;
    }
  };

1/16/01  Keeping instance-required flag on decider virtual function in
         unreferenced class

In some strange cases where, after IL lowering, the definition of a
template class is not needed even though an object of the class type is
constructed, the instance-required flag on the decider function
of the class (the first non-inline virtual function, the presence of
whose definition is used to decide whether to put out the virtual
function table definition) was incorrectly cleared, resulting in
an unresolved external at link time in versions with
INSTANTIATE_EXTERN_INLINE set to FALSE.

  struct Foo {
    virtual ~Foo () {}
  };
  template <class T> struct Bar : public Foo {
    virtual void decider();     // Decider function
  };
  template <class T> void Bar<T>::decider() {}
  int main() {
    new Bar<int>();  // Object constructed but not used
  }

1/16/01  Abort on empty function bodies in C99 mode for some configurations

In configurations where VLA_DEALLOC_STATEMENTS_IN_IL was TRUE, the front end
used to abort with an internal error (in statements.c) when processing an
empty function body in C99 mode (or another mode allowing variable-length
arrays).  This is now fixed.

1/16/01  Default configuration of VLA_DEALLOC_STATEMENTS_IN_IL

VLA_DEALLOC_STATEMENTS_IN_IL is now TRUE by default (it used to be FALSE)
when VLA_ALLOWED is TRUE.  (See Changes entry of 9/8/00.)

1/16/01  Declared parameter types recorded in IL

A declared_type field was added to a_param_type entries (which describe
function parameter types).  This is useful, among other things, to determine
which array bound was specified for a static array parameter in C99.

  void f(int a[static 4]) {}  // Bound "4" recorded in declared_type field
                              // of a_param_type entry

The C++-generating back end also uses this type (when available) to
regenerate function declarators.

1/15/01  Missing diagnostic when overloading static and nonstatic member
         function templates

An error is now issued if two member function templates, one static, the other
nonstatic with a function qualifier, have the same parameter types:

  class A {
    template<class T> void f(int) const;
    template<class T> static void f(int);  // Error.
  };

(See also the Changes entry of 9/26/95.)

1/15/01  Incorrect lowering of cast between real and imaginary types

In C99, the conversion of a real expression to an imaginary type (or vice
versa) results in a zero value.  However, the C99 complex lowering routines
used to just change the type of the converted converted expression (if it was
not a constant).

  _Imaginary double id = 1.2 * __I__;
  double rd = id;  // Should be zero, but used to be lowered as if
                   // id were real with value 1.2.

This is now fixed.  [Patch sent out 1/23/01.]

1/15/01  Missing diagnostic and possible abort on wrong number of template<>
         constructs

The front end used to not diagnose missing or extraneous 'template<>'
constructs when specializing certain member templates.  The resulting
IL could end up being inconsistent leading the C++-generating back end
to abort.  For example:

  template<class T> struct S {
    template<class U> struct N {};
  };
  template<> template<> template<class V>
    struct S<int>::N {};  // Extraneous 'template<>' was not diagnosed

This is now fixed (an error is issued).  [Patch sent out 1/23/01.]

1/15/01  Base classes are only dependent when the derived class is a template

When looking up an unqualified name in a class context, a base class should
only be considered dependent when the most-derived class from which the
lookup is done is a class template.  Formerly, we would unconditionally
treat such a base class as dependent, causing "f" to be undefined in the
example below.  [Patch sent out 1/23/01.]

  template <class T> struct A {
    void f();
  };
  template <class T> struct B: A<T> { };
  struct C: B<int> {
    void g() {
      f();  // A<int>::f is visible
    }
  };

1/11/01  Microsoft compatibility: name lookup in templates defined outside
         of their namespace

In Microsoft bugs mode, names used in the declaration of a template
declared in a namespace (or in a class in a namespace) but defined outside
of the namespace were not looked up properly.  This could result in
spurious errors or other incorrect behavior.  This problem was introduced
in version 2.43 and is now fixed.  [Patch sent out 1/23/01.]

  namespace N {
    template <class T> struct A {
      A(const A&s);
    };
  }
  template <class T> N::A<T>::A(const A<T>&s){}


1/11/01  Error issued on types declared as members of anonymous unions

The front end now emits an error (in strict mode) or warning (in default mode)
when a type is declared as a member of an anonymous union (except in Sun,
Microsoft and Cfront modes).

  struct S {
    union { class C {} c; };  // Error or warning (accepted in Sun, Microsoft
  };                          //                   and Cfront modes)

1/11/01  Setting assoc_template for prototype instantiations of function
         templates

The assoc_template field was not set for the routine entry that represents
the prototype instantiation of a function template.  This has been fixed.
[Patch sent out 1/23/01.]

1/10/01  Abort on invalid compound literal

Certain invalid compound literals could result in an abort.  This has
been fixed.  [Patch sent out 1/23/01.]

  void f() {
    (char []){1 , .* , 2} = 0;
  }

1/10/01  Use of __VA_ARGS__ diagnosed in nonvariadic macros

The front end used to accept the use (as a normal identifier) of __VA_ARGS__
in nonvariadic macros.  This is now reported as an error in modes that
recognize variadic macros.

  #define M(P) __VA_ARGS__  /* Now an error in C99 mode */

1/10/01  Error issued on invalid STDC pragma in strict mode

In strict C99 mode, an error (instead of a warning) is issued on an
invalid STDC pragma.

1/9/01   Internal error when initializing a block extern variable length array

The front end used to abort when encountering a block extern variable with
a variable length array type followed by an initializer (in modes accepting
variable length arrays; e.g., C99 mode).

  void f(int n) {
    extern int a[n] = { 1 };  // Invalid, but used to abort in C99 mode
  }

This is now fixed: an error is issued.

1/9/01   SVR4 mode error erroneously issued as warning in some configurations

In configurations where TARG_SIGNIF_CHARS_IN_EXTERNAL_NAME is nonzero and/or
TARG_CASE_SENSITIVE_EXTERNAL_NAMES is FALSE, the front end issued a warning
instead of an error for certain SVR4 mode declaration conflicts.

  int f();
  void g() {
    extern long f();  /* Should trigger an error; used to result in a warning
  }                      only. */

This is now fixed.

1/9/01   Spurious error when friend injection is disabled

A spurious redeclaration error was issued in certain cases when friend
injection is disabled.  This has been fixed.  [Patch sent out 1/23/01.]

  class A {
    friend class B;
    class  B *b;  // spurious redeclaration error
  };   

1/8/01   Microsoft compatibility: lookup of nontype names in base classes

When looking up a name used in a type specifier in a class member
declaration the Microsoft compiler ignores names that do not name
types when looking in base classes.  We now emulate this behavior
in Microsoft bugs mode.

  struct A {
    int Y;
  };
  template <class T> struct Y : public T {
    Y* p;  // ::Y not A::Y
    void f() { Y = 1; }  // A::Y, not ::Y
  };
  int main() {
    Y<A> y;
    y.f();
  }

1/8/01   Wrong selection of conversion function in C++-generating back end

The C++-generating back used to sometimes incorrectly put out an explicit
call to a conversion function as an explicit cast.  For example:

  struct B { operator int*(); };
  struct D: B { operator int*(); };
  void f(D *p) {
    p->B::operator int*();  // Used to be rendered as ((int *)(*p));
  }

This is now fixed.  [Patch sent out 1/23/01.]

1/5/01   Poorly worded diagnostic for invalid STDC pragma

The message issued for an invalid STDC pragma was mangled.  This has been
fixed.  [Patch sent out 1/23/01.]

  void f() {
    int x;
    #pragma STDC FP_CONTRACT ON
  }

1/4/01   Spurious error on compiler generated virtual destructor in an
         unnamed namespace

The front end used to issue an error when it generated a virtual destructor
for a class in an unnamed namespace.

  struct B { virtual ~B() {} };
  namespace { struct D: B {}; }  // Used to cause error because of undefined
                                 // <unnamed>::D::~D

This is now fixed.

1/4/01   C99 mode cannot be enabled when Microsoft mode is the default

The front end gave an error if the --c99 option was used when Microsoft mode
was the default.  This has been fixed.  [Patch sent out 1/23/01.]

1/4/01   Inconsistent positions on certain variable declarations

When a variable with linkage was declared (and not defined) in two different 
scopes, the decl_position field of the variable's source correspondence
referred to the first declaration, while the extended position information
of the decl_pos_info field (available when EXTRA_SOURCE_POSITIONS_IN_IL is
TRUE) referred to the last declaration.

  extern int i;
  void f() {
    extern int i;  // Inconsistent position information in the IL entry
  }                // corresponding to "i"

This is now fixed (both point to the first declaration).

1/3/01   Incorrect end position on asm statements

When using EXTRA_SOURCE_POSITIONS_IN_IL, the end position for asm statements
was incorrect (it was the start of the following statement).  This has
been fixed.

  int main() {
    asm("nop");
  }

1/3/01   Dependent lookup problem with base classes of nested classes

When using dependent name lookup, a dependent base class of a nested class
of a class template was incorrectly being treated as nondependent during
real instantiations.  This could result in incorrect name resolution.
This has been fixed.  [Patch sent out 1/23/01.]

  template <class T> struct A {
    typedef int X;
  };
  template <class T> struct B {
    typedef T X;
    struct C : A<T> {
	typedef X my_X;  // X should be B::X not A::X
    };
  };

1/2/01   Spurious error on initialization of multilevel array field

In C++ and C99 modes, the front end used to issue a spurious error message
when braces are omitted in the initializer for the first element of a field
with multilevel array type.  The error only occurred if the structure
containing the field was itself used as the type of a class member.
For example:

  struct S {
    struct N {
      int a[2][2];
    } n;
  } s = { 0 };  // Used to trigger a spurious error

This is now fixed.  [Patch sent out 1/23/01.]

1/2/01   Setting of is_template_function for member function prototype
         instantiations

The is_template_function flag was not set in the routine entry associated
with the prototype instantiation of a member function of a class template
(e.g., for A<T>::f and A<T>::g in the example below).  This has been fixed.
[Patch sent out 1/23/01.]

  template <class T> struct A {
    void f();
    void g();
  };
  template <class T> void A<T>::g(){}

1/1/01   Microsoft mode initialization oddity: abort in lower_constant

A bug was introduced in 2.45 in the handling of an obscure Microsoft-mode
initialization oddity first emulated in 2.44 (see Changes entry of 6/24/99).
The symptom was an abort in lower_constant.  Now fixed.

  int f(int);
  int main() {
    int r = { f(17), { 26 } };  // Aborted in Microsoft mode
  }

12/31/00 Microsoft mode macro expansion: abort on inert macro name

A bug introduced in 2.44 caused aborts in some cases in Microsoft
mode preprocessing.  The cases involved a top-level macro call that
expands to a string that includes a recursive reference to the macro
(such a reference is not expanded; we refer to that as an "inert"
macro name).  The aborts are now corrected.  [Patch sent out 1/23/01.]

  #define f() +f()
  f()   // Formerly aborted in Microsoft mode

-------------------------------------------------------------------------------
Version 2.45, December 26, 2000

12/25/00 More automatic configuration for long long host integer container

The setting of the macros related to the container used in the front
end to represent integer values is now more automatic when long long
is supported.  (This is desirable because C99 includes long long as a
standard type.)  Now, if both LONG_LONG_ALLOWED and
INTEGER_VALUE_REPR_IS_A_HOST_INTEGER are true, the macros are set
to use the host "long long".

12/24/00 typeid(*(T *)0) should throw an exception

The (somewhat contrived) case of applying typeid to an "lvalue" produced
by dereferencing a constant null pointer should throw an exception at
runtime.  Now, it does.

  #include <typeinfo>
  struct S { virtual ~S() { } };
  int main () {
    try {
        typeid (*(S*)0);
    }
    catch (...) {
        return 0;
    }
    return 1;
  }

12/21/00 IL version number changed to 2.37

12/21/00 Function template entries when using PROTOTYPE_INSTANTIATIONS_IN_IL

When using PROTOTYPE_INSTANTIATIONS_IN_IL, the template entries for
function templates and member functions of class templates always have the
prototype routine pointer set, even when not doing nonclass prototype
instantiations.  There is, of course, no definition associated with the
prototype instantiation in such cases.

12/21/00 C++-generating back end: elaborated type specifier omitted on
         reference to previously invisible name

When friend name injection is disabled, an elaborated type specifier
must sometimes be considered to be the first visible declaration of a
name, and such a reference, when emitted by the C++-generating back end,
must include the elaborated type specifier.  Such references are now
emitted properly.

  struct XX {
    friend class X;
  };
  class X *x;  // formerly emitted as simply "X *x"

12/21/00 static_cast of bool to enum type

A static_cast from bool to an enum type is now allowed.  The C++ standard
is not entirely clear on this issue (see 5.2.9p6 and 7, and 7.2p9), but
we think it was probably intended to be allowed.

12/19/00 MSVC++ compatibility: Output of long long constants in non-Microsoft
         mode

"long long" constants are now put out with i64 suffixes when MSVC++ is
the target for the C- or C++-generating back end even when the
front end is not running in Microsoft mode.

12/19/00 Missing typeinfo variable for local class of member function

A change made in 2.44 (see Changes entry of 3/5/00) caused IL lowering
to fail to produce a definition of a typeinfo variable for a local class
of a member function in some cases.  Now fixed.

  namespace N {
    struct A {
      void* f ();
    };
  }
  using namespace N;
  void* A::f () {
    struct B {  // typeinfo variable for this class was missing
      virtual void make() {}
    };
    return new B;
  }

12/16/00 Abort on block extern with same name as member function

A block extern declaration in a member function, with the same name
as a member function of the class or one of its base classes, could
result in an abort in routine_linkages_are_compatible or
compute_name_linkage.  Now fixed.  For example, the following case
aborted when compiled with --no_extern_inline:

  #include <stdio.h>
  struct Print {
    void printf( const char* str ) {
      extern int printf( const char*, ... );
    }
  };

12/16/00 Overload resolution: comparison of conversions to const void *

Overload resolution incorrectly compared the standard conversions
after conversion functions when the destination type is "const void *"
and only one of the conversion functions returns a const-qualified
pointer.  The conversion should be considered ambiguous, but the
conversion that didn't require the addition of "const" was chosen.

  void f(const void *);
  struct X;
  struct A {
    operator const char *();
    operator X*();
  } a;
  int main() {
    f(a);  // Now flagged as ambiguous
  }

12/16/00 Warning on conversion from integer to smaller pointer

A warning is now issued on a conversion from an integral type to a
smaller pointer type, e.g., from long long to a 32-bit pointer.

12/14/00 "\n" in name in #line directive

A "\n" appearing in the file name specified in a #line directive is now
correctly passed to the output files and to the expansion of __FILE__
as "\n" rather than as a newline character.  Formerly, a use of
__FILE__ in such a case could produce an internal error.

12/14/00 Spaces in macro-expanded file name in #include

The file name in a #include directive can be produced by macro expansion.
A change made to the processing for the "<...>" form of #include
resulted in the removal of any spaces in the file name.  Some systems
make use of such names, and the removal of the spaces produced
the wrong file name.  Now fixed.

 #define INCHEADER(x) <C:\Program Files\Microsoft Visual Studio\VC98\Include\x>
 #include INCHEADER(exception)

12/13/00 Conditional destruction of temporary added by implicit conversion
         for operand of "?"

A temporary added for an implicit conversion on the second or third
operand of a "?" operator was not marked as conditionally generated,
and therefore IL lowering generated code to destroy it unconditionally,
rather than only when it is created.  This bug was introduced by the
changes associated with the Changes entry of 8/5/99.

  struct A {
    A(int);
    ~A();
  };
  int main() {
    int i = 1;
    i ? A(1) : 2;  // Temporary for implicit A(2) destroyed unconditionally
  }

12/12/00 C- and C++-generating back ends: <stdarg.h> macros and line wrapping

Line wrapping is now disabled in the C- and C++-generating back ends
while uses of the <stdarg.h> macros (e.g., va_arg) are put out (which
is done when DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE is
TRUE).  On long output lines, that prevents generation of #line directives
in the middle of the macro calls.  Standard C does not allow use of
preprocessing directives in the middle of macro calls.

12/8/00  Old-style casts misclassified as reinterpret_casts

Some old-style casts, those that correspond to a const_cast or to
a combination of a static_cast and a const_cast, were misclassified
as reinterpret_casts.  In cases where there is a base-derived
multiple-inheritance relationship between the pointers, the resulting
code may have been incorrect.

  class A {
    int a_;
  };
  class B {
    int b_;
  };
  class AB : public A, public B {
  };
  int main () {
    B b;
    const B *p = &b;
    AB *q = (AB*)p;  // Cast was incorrectly treated as reinterpret_cast
  }

12/7/00  Internal error while lowering designated initializers in structures
         with unnamed fields

The C-generating back end sometimes aborted with an internal error while
attempting to lower a designator for a structure with unnamed fields.
For example:

  struct A {
    int x: 2;
    int: 0;
    int y: 3;
  };
  struct A a = {.y = 5, .x = 1, 2};  /* Used to abort when lowering of
                                        designated initializers is enabled. */

This is now fixed.

12/7/00  Problems in lowering designated initializers for unions

The lowering of designated initializers sometimes got confused when
lowering unions where a scalar member is initialized and then
an aggregate member is initialized (which is pointless, because only
the last initialization is retained).  This could result in various
kinds of problems, including aborts.

12/7/00  Microsoft compatibility: errors in #pragma pack parentheses

In Microsoft mode, missing opening or closing parentheses in a
#pragma pack are now diagnosed with warnings.

12/6/00  Internal error on default arguments of member functions

When DEFAULT_INSTANTIATIONS_PERMITTED_IN_CLASS_SRC_SEQ_LIST is TRUE and
source sequence entries are generated for template instantiations, the
front end used to abort with an internal error while processing the default
argument of a member function.  E.g.,

  struct S {
    void f(int a = 0) {}  // Used to cause an abort in certain
  };                      // configurations.

This is now fixed.

12/6/00  C99 support

We have added support for the 1999 version of the ISO C standard.
There is now a --c99 command-line option, and also the configuration
macro DEFAULT_C99_MODE which controls whether the default dialect
of C is C99 or the old C89.

Some of the C99 features produce new IL constructs that require
support in the back end.  These features are enabled by the configuration
macro C99_IL_EXTENSIONS_SUPPORTED.  When this flag is FALSE, the --c99
command-line option is disabled.

See the section "C99 and the Intermediate Language" in the IL chapter of
the internal documentation for a summary of the IL issues.

When DO_C99_IL_LOWERING is TRUE, many of the C99 IL extensions are
lowered to C89 IL, to minimize the back end changes required to support
C99.  See the section "C99 Lowering" in the IL Lowering chapter of the
internal documentation for a summary of the issues.  Note that
lowering of complex/imaginary operations produces runtime routine
calls, and we have provided a sample implementation of those runtime
routines in the new runtime library file c99_complex.c.

Note that if you don't need to support C99 at all (e.g., if your
product supports only C++), you can set C99_IL_EXTENSIONS_SUPPORTED
to FALSE and make no changes to your back end.

The existing implementations of designated initializers, compound
literals, VLAs, restrict, and long long have been integrated into
the overall C99 changes.  They are still available in older C modes
as they have been previously.

The C99 standard is ISO/IEC 9899:1999.  The foreword contains a
short summary of the features added.

12/6/00  Abort in do_conversions_on_operands_of_copied_template_expr

Some uses of "&&" and "||" operators in constant expressions in
nontype template arguments could result in an abort in
do_conversions_on_operands_of_copied_template_expr.  Now fixed.

12/4/00  Diagnostic on invalid long long suffix

A diagnostic is now issued in strict mode when a long long suffix of
"lL" or "Ll" is used on an integral constant (only "ll" or "LL" should
be used).

12/2/00  C-generating back end, RECORD_NAME_IN_PARAM_TYPE_ENTRY: parameter
         names on function declarations

The C-generating back end now puts out parameter names on function
declarations When RECORD_NAME_IN_PARAM_TYPE_ENTRY is TRUE.

11/24/00 Microsoft compatibility: __uuidof and templates

The Microsoft extension operator __uuidof has interesting behavior when
applied to a template -- it returns the uuid for the template argument
and ignores the one for the template itself.  That is, for __uuidof(A<B>)
the uuid of B, not A, is returned.  This is now emulated in Microsoft
mode.

11/23/00 pcc and Microsoft mode preprocessing: strange parentheses in macro

pcc and Microsoft mode preprocessing does special processing to
support old-style (nonstandard) token pasting.  This special
processing broke down for macros that expand to the beginning
of a macro call, which is then completed in the source line text
following the original macro call.  Formerly, such cases (which
are standard-conforming) got the error "Improperly terminated macro
invocation" in pcc and Microsoft mode.  Now, they are correctly
expanded.

  #define Y(a, b) a = b
  #define X(a) Y(a,
  float X(x)1.5);  /* Expands to float x = 1.5; now */


11/21/00 Richer template representation (IL CHANGE)

A number of additions were made to the representation of template entities
when the PROTOTYPE_INSTANTIATIONS_IN_IL configuration flag is TRUE:
  - Every template IL entry (except those for template template parameters)
    contains a pointer to a canonical template.  (The canonical declaration is
    the first declaration.)
  - The canonical template entry points to the template entry of the template
    definition (if a definition was seen).
  - The assoc_template field is now also set for nontemplate members of class
    templates.  A placeholder template entry (without template parameter
    information) is generated for these cases.

11/20/00 printf argument checking and const char * arguments

The argument checking done for printf (when #pragma __printf_args is
used) permitted a const char * argument to be passed to a %s printf
specifier, but only when string literals are const in C++ mode; in other
modes (e.g., C, C99, C++ when string literals are not const), a remark was
issued.  Such arguments are now accepted in all modes.

  #pragma __printf_args
  int printf(const char *, ...);
  int main()
  {
    const char *cc = 0;
    printf("%s\n", cc);
    return 0;
  }

11/18/00 C++-generating back end: unnecessary cast on template argument
         eliminated

In some cases where unnecessary casts were generated on nontype template
arguments because of typedef differences, the cast is now suppressed.

11/18/00 Compound literals off in C++ mode even if on by default

Compound literals (a C99 feature) are not supported in C++ mode.
Due to an oversight, we did not turn them off in C++ if they are
enabled by default by setting DEFAULT_COMPOUND_LITERALS_ALLOWED
to TRUE.  Now, they are turned off as intended.

11/16/00 Abort on designator referring to a flexible array member

A designation referring to a flexible array member used to trigger an
internal error in the front end.  Now it is diagnosed with a normal
error, except in Microsoft mode where it is accepted.

  struct A { int i; int a[]; };
  struct A a = { .b = 2; };  // Used to cause an abort

11/16/00 On Linux, __unix__ predefined instead of unix

When the front end is compiled on a Linux system, the macro __unix__
is now predefined.

11/15/00 Predefined macros on SPARC systems

When the front end is compiled on a SPARC system, the macros
sun, sparc, and unix are now predefined.  To change that, see
sys_predef.c.

11/15/00 Use of front end routines in a back end or middle end

Some additional guards (testing the global variable in_front_end)
have been added to traverse_type_tree and type_change_constant to
allow those routines to be used outside of the front end.

11/15/00 IL macro entries for command-line macro definitions

IL macro entries are now recorded for macros defined on the command
line (e.g., -DXXX=1).  Formerly, the entries were created (since
the change described in the 9/10/99 Changes entry) but then lost.
IL macro entries are recorded only when RECORD_MACROS_IN_IL is TRUE.

11/14/00 Warnings on unreferenced inlined functions

The front end no longer warns about extern inline functions that are not
referenced in a translation unit in which they are defined.  (In that respect
they are treated like other extern functions instead of like functions with
internal linkage.)  However, unlike other extern function definitions, they
are not always marked as referenced.

11/14/00 Microsoft compatibility: cv-qualifiers dropped on non-class
         operands of "?"

In Microsoft bugs mode, cv-qualifiers are now dropped on the second and
third operands of a "?" operator if those operands are lvalues and have
the same cv-unqualified non-class type.  The operands remain lvalues.

  int main () {
    int i = 1;
    const int j = i;
    (i ? i : j) = 1;  // Accepted in Microsoft bugs mode
  }

11/9/00  No setlocale call when multibyte characters not enabled

When MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is TRUE but
DEFAULT_MULTIBYTE_CHARS_IN_SOURCE_ENABLED is FALSE (that is, multibyte
character support can be enabled, but it's not on by default), a
setlocale call was done at the beginning of the compilation, and
it shouldn't have been.  Now, the setlocale call is done only when
multibyte character support is turned on.

11/8/00  RESTRICT_ALLOWED macro eliminated

The RESTRICT_ALLOWED macro has been eliminated (i.e., restrict support
is always configured into the front end).  Actual recognition of the
restrict keyword is still conditional, however.  The default is specified
by the DEFAULT_RESTRICT_ENABLED macro (as before).  The restrict keyword is
recognized by default in C99 mode.

11/8/00  Change in default for SUPPRESS_RESTRICT_IN_GENERATED_CODE

The restrict keyword is now suppressed by default in code generated by
the C and C++ generating back ends.

11/3/00  Abort on field designator in array initializer

The front end used to abort when an initializer for an array with unspecified
length contained a field designator and the element type was a struct with
no fields.  (Designators are only recognized in C mode.)

  struct S { union { int i; float f; }; };
  struct S a[] = { .z = 0 };  /* Triggered an internal error. */

This is now fixed.

11/2/00  End position on function reference on implicit function
         declaration in C mode

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the end position on the
IL expression node for a function in a call was not set when the function
is implicitly declared by the call (this is possible only in C mode).
The end position is now set correctly.

11/2/00  Abort in type_pointed_to when doing prototype instantiation
         of dependent call of member function using qualified name

The front end aborted with an assertion failure in type_pointed_to
on a call of the form dependent_expression->X::f() (i.e., using
a qualified name for the member function) when such a call was
processed during the prototype instantiation of a function (e.g.,
in strict mode).  Now fixed.

11/1/00  Microsoft compatibility: call of non-const function on const
         object via pointer-to-member

MSVC++ (at least versions 6.0 and 7.0) allow a call of a non-const
member function on a const object when the call is done via the
pointer-to-member operator .* and ->*.  This is now emulated in
Microsoft bugs mode.  A warning is issued.

  struct A {
    void f();
  };
  void (A::*pmf)() = &A::f;
  int main() {
    const A ca;
    (ca.*pmf)();    // Accepted in Microsoft bugs mode
    const A *pca = &ca;
    (pca->*pmf)();  // Accepted in Microsoft bugs mode
  }

10/31/00 Abort on invalid string literal in Microsoft uuid construct

The front end used to abort when processing a string literal with a missing
quote inside a Microsoft uuid declaration specifier.  For example:

  struct __declspec(uuid("11111111-2222-33
  33-4444-555555555555")) S { };  // Abort on bad string literal

This is now fixed.

10/31/00 Microsoft compatibility: injected class names marked as needing
         qualification

In Microsoft mode, injected class names are now marked as needing qualification
in the hidden name table.  This changes the output of the C++-generating
back end in the following example:

  namespace N { struct S {}; }
  class C: public N::S {
    static void f() {
      sizeof(N::S);  // Used to always be regenerated as "sizeof(S)";
    }                // now "sizeof(N::S)" is produced in Microsoft mode.
  };

10/31/00 Extra source positions, recording constant expressions in IL

When both EXTRA_SOURCE_POSITIONS_IN_IL and RECORD_CONSTANT_EXPRESSIONS_IN_IL
are set, the source positions were not recorded correctly in some of the
expressions attached to constants for constant expressions.  Now fixed.

10/31/00 C++-generating back end: dropped intermediate disambiguating cast

In some cases, the code generated by the C++-generating back end
dropped an intermediate cast that served to disambiguate a use of
an overloaded function or template.

  struct A {};
  struct B: public A {};
  template < class T >
  inline long proc(T * pObject, char *pData) { return 0; }
  typedef long (*PFA)(A *, void *);
  long f2(PFA pfnMapProc);
  long g() { 
    return (f2(((PFA)(long (*)(B*,char*))proc)));  // Okay now
  }

10/30/00 Microsoft compatibility: initialization of enum bit fields

The change that enabled the initialization of any enum entity with a value of
integer type has been undone (Changes entry of 1/21/00).  Instead, in
Microsoft mode, bit fields of enumeration type can now be initialized with
integer values in aggregate initialization constructs.

  enum E { e1, e2 };
  struct X { E i: 2; E j; } x = { 1,   // Accepted in Microsoft mode
                                  2 }; // Error (not a bit field)

10/29/00 Nit in cast_is_valid_in_current_expression_kind

One test in cast_is_valid_in_current_expression_kind was incorrect.
It tested for an arithmetic or enum type when it should have tested
for a template parameter type (as indicated by the comment).  This
is now corrected.  The code is in the section related to initializer
expressions, which are not really used in C++, and therefore this
problem was not visible in unmodified versions.

10/12/00 Inconsistent source sequence entry list for prototype instantiation
         of a class template

When both TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
PROTOTYPE_INSTANTIATIONS_IN_IL were configured TRUE, the source sequence
entries for the prototype instantiation of a class template were reordered
into an inconsistent list.  This could e.g. lead the C++-generating back end
to abort.  Now fixed.

10/12/00 Incorrect lowered code for ctor-initializer copies of empty base
         classes

The empty base class optimization (see Changes entry of 8/9/99) introduced
a bug in the lowered code for ctor-initializers that do a bitwise copy
of an empty base class.  The copy should be suppressed, because any kind of
assignment will copy at least one byte and clobber storage following the
empty base class (see also the Changes entry of 5/2/00).

10/10/00 Call of pointer-to-template-parameter-type in prototype instantiation

A call of an entity of type pointer to T, where T is a template parameter
type in a prototype instantiation, was incorrectly rejected in 2.44.
This happened only when prototype instantiations of nonclass entities
are being done, e.g., in strict mode.  Such a case should be accepted
because the template parameter might have a function type.  Now, it is.

  template<typename F> struct wrapper {
    F* f;
    wrapper(F* f) : f(f) {}
    void operator()(F p) { f(); }  // Formerly got an error here
  };
  typedef void (fun)();
  void f() {}
  wrapper<fun> v(f);

10/10/00 C99 _Bool type

In C99 mode, the front end now recognizes the keyword _Bool and associates
it with the same representation as that of the C++ bool type.  (IL CHANGE:
the bool_type field of struct a_type can now also be TRUE in C99 mode.)
For example:

  _Bool b, *pb = &b;
  int main() {
    _Bool nn = pb;
    printf("%d\n", nn);  /* Prints "1" in C99 mode. */
    return 0;
  }

10/10/00 Looking for composite pointer type in operator overloading for
         comparison operators

When operator overloading considers user-defined conversions while
resolving overloading of the operators

   ==  !=  >  <  >=  <=

and pointer difference (pointer - pointer), it now looks for conversion
functions that can bring the operands to a composite pointer type
(as defined in 5.9p2 of the C++ standard):

  struct X {
    operator const int *();
  };
  struct Y {
    operator volatile int *();
  };
  int main() {
    X x;
    Y y;
    x == y;  // Both converted to const volatile int *, then compared
  }

10/8/00  Template entities referenced in unused default argument expressions
         not instantiated

Template entities referenced in default argument expressions that are
never used are no longer instantiated.  This conforms to a requirement
in 14.7.1p9 of the C++ standard.

  template <class T>
  struct Obj {
      Obj(int* myPtr) { *myPtr = T::ID; }
  };
  class IEnt;
  void foo(Obj<IEnt> myEnt = 0);  // No longer draws an error

10/7/00  Microsoft compatibility: deduced reference can bind to rvalue

In Microsoft bugs mode, the front end now allows a deduced template
function parameter of type reference to non-const to bind to an rvalue.
This matches the behavior of MSVC++ 6.0 and 7.0 beta.

  template <class T> void f(T &) {}
  int main() {
    f(1);       // Accepted in Microsoft bugs mode, error normally
    f<int>(1);  // Error (T is specified, not deduced)
    return 0;
  }

10/7/00  C99 and Microsoft compatibility: function name strings

In C99 mode the front end now recognizes the reserved identifier __func__.
When used, this identifier causes the implicit declaration of a constant
local static variable initialized with the name of the current function
(type is "array of const char").  The identifier cannot be used outside of
function definitions.  For example:

  #include <stdio.h>
  void main() { printf("%s\n", __func__); }  /* Outputs "main". */

In Microsoft mode, the special identifier __FUNCTION__ has the same role as
__func__ in C99, and the identifier __FUNCDNAME__ is similar but it
corresponds to an array initialized with the mangled name of the function
currently being defined (though the mangled names generated by the front end
are different from those generated by Microsoft compilers).

10/6/00  Change in the default include file suffix list

When a header file name is specified without a suffix, the front end
appends each of the suffixes from the include file suffix list when
searching for the file.

Formerly, the EDG C++ headers used the .h suffix.  The front end would
implicitly add the .h so that, for example, an include of <typeinfo>
would result in the inclusion of typeinfo.h.  Unfortunately, the
implicit addition of a .h to file names with no suffix created
problems when some other file with the .h name was found in the
include search path before the desired file.

To resolve this, the default suffix list has been changed to use a
suffix that is unlikely to be used on other header files (.stdh).  The
EDG C++ headers have been renamed to use that suffix.  The default
suffix list continues to include the null suffix so that header files
without a suffix may also be used.

If an implementation chooses to use (only) suffix-less names for headers,
the include file suffix list can be changed to "" or "::" to turn off the
feature of adding suffixes to such file names.

See the include directory Changes file for more information about the
header file changes.

10/5/00  Spurious error on function try block on template constructor

A spurious error was issued when a class template constructor with a
function try block was defined outside of the class template.  This has
been fixed.

  template<class T> struct X {
    X();
  };
  template<class T> X<T>::X() try {} catch (...) {}

10/2/00  Spurious error on "\u" in skipped #include

A \u in a header file name was incorrectly diagnosed as an invalid
universal character name when the #include was in code skipped as the
result of an #if or #ifdef directive.  This has been fixed.

  #if 0
  #include <a\u\x.h>
  #endif

10/2/00  Microsoft compatibility: throw (...)

In Microsoft mode, the front end now accepts the special "throw (...)"
exception specification.  Recent Microsoft compilers recognize this to
explicitly indicate that a function may throw any exception (this is useful
for modes where a Microsoft back end assumes that extern "C" functions will
not throw any exception).  Although other exception specifications are
ignored in Microsoft mode, this special syntax is recorded in the IL through
the new "throw_any" flag of an_exception_specification (IL CHANGE).
The C++-generating back end uses that flag to correctly regenerate the
associated declarations.  For example:

  extern "C" void f() throw (...); // "f" may throw any exception

10/2/00  Improve file name comparisons

The file name comparison routines have been improved so that two names
that name the same file should now compare equal in all cases.  The
code added in 2.44 that compares inode numbers on Unix systems has
been removed because the new code produces the same results with improved
efficiency.

As an example of the kind of usage that now works, consider this example:

  #include "x.h"
  #include "../this_dir/x.h"
  #include "/a/b/this_dir/x.h"

If the path name of file x.h is /a/b/this_dir/x.h and /a/b/this_dir is
the current directory, these includes would have been considered to
include different files.  They are now known to include the same file.

9/29/00  Carriage returns now ignored by default

The IGNORE_CARRIAGE_RETURN_IN_SOURCE configuration flag is now set
to TRUE by default to ensure that source files created on Windows systems
can be compiled elsewhere.  (The default was already TRUE on Windows
systems.)

9/28/00  Microsoft compatibility: Usual arithmetic conversions and sized
         types like __int32

When the changes were made in version 2.44 to treat Microsoft sized types
like __int32 as distinct from the same-sized standard types (see
Changes entry of 12/14/99), the usual arithmetic conversion rules
weren't updated accordingly.  An operation like __int32 + short should
have type __int32, but instead it was given type int (the standard
integral type with the same size as __int32).  Now the sized type is
used.

9/28/00  Preprocessor output: #include <stdarg.h>

In configurations with DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE set
to TRUE the preprocessor used to generate

  #include <stdarg . h>

for the input

  #define M <stdarg.h>
  #include M

(note the extra spaces).  This is now fixed.

9/28/00  Preprocessor output: separate stringized token when necessary

Previously, the preprocessor did not always properly separate a stringized
token from preceding text.  This could result in preprocessor output being
valid code even though the input contained errors.  For example:

  #define M1(id) (L## #id)
  #define M2(id) (L#id)
  wchar_t const *s1 = M1(a);  // Fine.   Same as: s1 = L"a"
  wchar_t const *s2 = M2(b);  // Error.  Same as: s2 = L "b"

Previously, the preprocessor output for M2(b) was L"b" without intervening
space.

9/27/00  Microsoft compatibility: __forceinline and __inline allowed on
         explicit specializations and explicit instantiations

The front end now accepts the Microsoft mode storage modifiers __forceinline
and __inline on declarations that are explicit specializations or explicit
instantiations.  For example:

  template<class T> struct S { void f(); };
  template<> __forceinline void S<int>::f() {}  // No longer an error

9/27/00  Instantiation of static data member type

The front end used to instantiate the element type of a static data member
array at the point of the declaration of such a member.  The instantiation
is now delayed until the complete element type is actually needed.
For example:

  template <class T> struct S: public T {};
  struct I;
  class C {
    static S<I> foobar[7];  // Fine now.  Used to trigger an error because
  };                        // S<I> was instantiated with an incomplete base

9/25/00  Template conversion function usable for conversion to bool

In a context that requires an expression of type bool, a template
conversion function will now be considered as a way to do the conversion.

  struct A {
    template <class T> operator T();
  } a;
  int main() {
    if (a) ;  // Formerly an error
  }

This change also improves the standard conformance on non-template
conversions to bool where one of the choices is a user-defined
conversion to a pointer type followed by a standard conversion
to bool (which should be considered worse than other possibilities):

  struct A {
    operator int();
    operator char *();
  };
  int main() {
    A a;
    a ? 1 : 2;  // Formerly got ambiguity error; now operator int()
                // is selected.
  }

9/22/00  Diagnostics on extra text after preprocessing directives

Previously, extraneous text following preprocessing directives was only
diagnosed in strict ANSI mode.  Now it is warned about in all other modes,
except K&R/pcc mode.  For example:

  #define A 7
  #if A
  #endif A    // Warning (or error) except in K&R/pcc mode: extra "A"
  #undef A+1  // Warning (or error) except in K&R/pcc mode: extra "+1"
  int i = A;  // Error: A is undefined (behavior unchanged)

9/21/00  Microsoft compatibility: specialization allowed after use

The Microsoft compiler allows a member function template or a member
function of a template class to be explicitly specialized after it
has been used.  This is not allowed by the standard.  The front end
now allows such specializations in Microsoft bugs mode.  A warning
is issued.

9/21/00  IL memory corruption when
         NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE

When nonclass instantiations are included in the source sequence list,
different instantiations of a same template could corrupt each other's IL
memory.  This could lead to all kinds of strange behavior such as internal
errors or (perhaps) invalid results.  This has been fixed.

9/21/00  Incorrect line numbers following multi-line #line directive

The line number used in diagnostics and in the __LINE__ macro was incorrect
following a #line directive that spans more than one line.  This has been
fixed.

  extern "C" int printf(const char *, ...);
  int  main() {
  #line 1 "A\
  B"
    printf("%d\n", __LINE__);
  }

9/20/00  IL write-read error: unused complicated default arguments,
         IL lowering

In some rare cases, default argument expressions that are unused and
involve destructible temporaries were removed from the IL by IL lowering
after some of the entities referenced by the default argument expression
were marked as needed.  This produced an inconsistent IL tree if
removal of unneeded IL entities was done, which could manifest itself
(among other ways) as an IL write-read error.

9/18/00  Functional-notation cast incorrectly seen as dependent

When prototype instantiations of nonclass templates are done (e.g.,
in strict mode), functional-notation casts in template definitions were
mistakenly taken to be dependent in some cases.  As a consequence, some
errors were not detected.

  struct B {
    B(int);
  };
  template <class T> void f(T) {
    B("hello");    // Error, formerly not detected
  }

9/18/00  Microsoft compatibility: lookup problem introduced in 2.44

A bug was introduced in version 2.44 that could cause members of
an enclosing class to be ignored during certains lookups in a
template class in Microsoft mode.  This has been fixed.

  template <class T> struct A {
    struct C { };
    struct B { B(C); };
  };
  template<> A< int>::B::B(C); // spurious error: "C is undefined"

9/15/00  Visibility of operator functions in template base classes in
         strict mode

Overloaded operator functions declared in template-dependent base classes
were not found on lookup for operator uses in strict mode.  Now, they are.
This problem was introduced in version 2.44.

  struct a {
     short operator~() const;
  };
  template <int I, int J> class b: public a {
  };
  template <int I> class c: public b<I,I> {
  };
  short test2(const c<3> v) {
    return ~v;  // Formerly got error because a::operator~ was not found
  }

9/15/00  Suppressed inclusions listed by --trace_includes (-H) option

The front end suppresses the inclusion of a header file that has previously
been included, and that contains guard code (or a #pragma once directive)
to ensure that subsequent inclusions have no effect.  Formerly, the
--trace_includes (also -H) option would display only the names of those
files actually included.  Now, all #include directives processed will
be displayed, even if the actual inclusion of the file is suppressed.
Note that any #include directives in the suppressed file will not be
displayed a second time, however.

9/14/00  Microsoft compatibility: warning only on invalid #pragma pack values

In Microsoft mode, #pragma pack (n) directives with an invalid value (e.g.,
zero) are ignored with a warning.  In other modes this remains an error.

9/12/00  Additional source position information for class template
         prototype instantiations

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, prototype instantiations of class
templates now carry the same kind of extra position information as ordinary
class types do.  (Previously, the decl_pos_info field of prototype
instantiations pointed to a block of null positions.)

9/11/00  Abort on invalid friend declaration in a class template

2.44 introduced a problem that could cause an abort on a friend declaration
that specified an invalid qualified name.  This has been fixed.

  template <class T> struct A {
    friend void A::f(){}
  };

9/11/00  defined_outside_of_parent flag for member function specializations

The flag defined_outside_of_parent in a_routine entries (present when
GENERATE_SOURCE_SEQUENCE_LISTS is TRUE) was not set when a member function
was explicitly specialized (outside of its parent class template).

  template<typename T> struct S {
    void f() {}
  };
  template<> void A<int>::f() {}  // Should have defined_outside_of_parent
                                  // set to TRUE
This is now fixed.

9/11/00  Error recovery on invalid partial specialization

An internal error could occur if a partial specialization was
(incorrectly) declared within the definition of the primary template.
This has been fixed.  Note: This example aborts only when parsing
non-class templates.

  struct A {};
  struct B : A {};
  template <class T, class U> struct C {
    class A {};
    template <class T2> struct C<T2, A*> {
      static int f() {return 2;}
      int g() {
        if (C<int, B*>::f() != 1){}
      }
    };
  };

9/8/00   Indication of deallocation point for variable-length arrays (VLAs)

A new statement kind, stmk_vla_dealloc, has been added (IL CHANGE).
It is generated when variable-length arrays are enabled (only in C mode,
by default in C99 mode) and indicates the point at which the storage
for a VLA should be deallocated.

9/8/00   Abort on friend declarations with default arguments

The front end used to produce invalid IL when a function is redeclared as
a friend and the friend declaration adds default arguments.  This could lead
to internal errors during IL lowering.  For example:

  void f(int, int) {}
  struct S {
    friend void f(int, int = 0);  // (1)
  };
  void f(int = 0, int);
  void g() { f(); }

This is now fixed.  When friend injection is enabled, the friend declaration
(1) is treated the same as an ordinary function redeclaration and the
example is valid.  When injection is disabled, an error is issued for default
arguments specified on a friend function redeclaration.

9/7/00   Microsoft compatibility: ignore leading and trailing whitespace in
         #include <...> directives

In Microsoft mode, the front end ignores leading and trailing whitespace in
#include directives of the form #include <...> (but not when the form is
#include "...").  For example:

  #include < stdio.h >

is equivalent to

  #include <stdio.h>

in Microsoft mode, but not in other modes.

9/6/00   Microsoft compatibility: extra text after preprocessing directive
         is not fatal

The front end now ignores extra text following a preprocessing directive in
Microsoft mode (with a warning).  In other modes, a discretionary error is
issued.  For example:

  #line 1 "hello.c" "this is ignored with a warning in Microsoft mode"
  int i;

9/6/00   Microsoft compatibility: "extern" and "static" ignored on parameter
         declarations

In Microsoft mode, the storage class specifiers "extern" and "static" are
ignored (with a warning) on parameter declarations.  In other modes, they
result in an error.

  void f(static int x); // Warning in Microsoft mode; error otherwise

9/6/00   Microsoft compatibility: qualifiers ignored when comparing deduced
         types

The Microsoft compiler ignores qualifiers when comparing the types
deduced for different function parameters.  The front end duplicates
this behavior in Microsoft bugs mode.  In this example, deduction
succeeds for the second call even though the first parameter results
in a deduced type of "const int" while the second results in a deduced
type of "int".  The first type deduced is the one actually used as the
template parameter type.

  template <class T> void f(T& t1, T& t2) { }
  int main() {
    int i1, i2;
    const int ci1 = 1;
    f(i1, i2);
    f(ci1, i2); // calls f(const T&, const T&)
  }

9/6/00   Derived to base deduction failed on uninstantiated type

Template argument deduction involving a derived to base conversion failed
if the argument type had not yet been instantiated.  This has been fixed.

  template <class T> class Base{};
  template <class T > class Derived : public Base<T> { };
  template <class T> struct D {
    template <class T1> void f(Base<T1> &rpt);
  };
  void g(Derived<int> *dip) {
    D<int> da;
    da.f(*dip);  // fails if Derived<int> has not yet been instantiated
  }

9/1/00   Conversion to non-reference type that uses conversion function
         to reference type is not lvalue

The result of casting to a non-reference type by way of a conversion
function that returns a reference type was mistakenly taken to be
an lvalue.  It is now an rvalue.

  struct A {
    operator int&();
  };
  int main() {
    A a;
    ((int)a) = 1;  // Now gets an error
  }

9/1/00   Abort on array rvalue selected from base class of class rvalue

The front end no longers aborts on passing an array rvalue as
an argument, when the array rvalue is produced by creating a class
rvalue and selecting an array member of a base class of that value.

  struct B {
    char arr[10];  
  };
  struct D : public B {
    D(const char*);
  };
  D f();
  int main() {
    D d(f().arr);  // Formerly, aborted in exprutil.c
  }

9/1/00   Microsoft compatibility: standard conversion after different
         user-defined conversions

The MSVC++ 6.0 compiler considers a standard conversion after a user-defined
conversion as part of deciding which conversion is better in overload
resolution, even when (contrary to the standard) the user-defined
conversion routines are different.  This behavior is now emulated
in Microsoft bugs mode.

  struct A {
    operator double();
    operator int();
  } a;
  void f(int);
  void f(float);
  int main() {
    f(a);
    return 0;  // Should be ambiguous; MSVC++ picks f(int)
  }

8/31/00  Incorrect passing of function call arguments for calls through
         certain template-dependent function pointers

Parameters of certain instantiated pointer-to-function types were sometimes
not marked as having to be copied using their copy-constructor.  Depending
on the back end, this could lead to aborts or otherwise incorrect results.
For example, the C-generating back end generated an extraneous bitwise copy
in the following example:

  extern "C" int printf(char const*, ...);
  void *last_copy = 0;
  struct S {
    S() {}
    S(S const&) { last_copy = this; }
  };
  template <typename A1, typename R, typename OP>
  struct F {  
    F(OP const &o): m_op(o) {}
    F(F const &o): m_op(o.m_op) {}
    R operator()(const A1 a1) const { return m_op(a1); }
    OP m_op;  
  };
  template <typename A1,typename R> inline
  F<A1, R, R (*)(A1)> const makeF(R (*pf)(A1)) {
    return F<A1, R, R (*)(A1)>(pf);
  }
  void test(S v) { // "v" should be the most recent copy at this point
    if (last_copy != &v) { printf("Unexpected address\n"); }
  }
  int main() { makeF(test)(S()); }

This is now fixed.

8/31/00  C++-generating back end: references to overloaded functions in
         the presence of using-declarations

The C++-generating back end formerly used incorrect qualified names in
some references to overloaded functions in the presence of using-declarations
that adjust access.  The generated code was incorrect because it
referred to an inaccessible base class.

  class A {
  public:
    void f();
    void f(int);
  };
  class B : private A {
  public:
    A::f;
  };
  int main() {
    B b;
    b.f();  // Formerly put out as b.A::f()
  }

8/30/00  Prototype instantiations in the IL

(See also entry of 7/18/00.)  Previously, the front end could only record
prototype instantiations of templates in the IL if both class and nonclass
template prototype instantiations were recorded (e.g., with the command-line
option --parse_templates).  Now, when PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE,
class prototype instantiations will be recorded even if nonclass prototype
instantiations are not.  However, if nonclass prototype instantiations are
not recorded, the C++-generating back end will not use the class prototype
instantiations to regenerate source code (the unparsed template token
sequence will be output instead).

8/30/00  Compilation errors in il_display.c

Compilation errors occurred in il_display.c when building an IL display
program configured with PROTOTYPE_INSTANTIATIONS_IN_IL equal to TRUE.
(See also entry of 8/21/00.)

8/29/00  Microsoft compatibility: bad output of IL display program

A bug introduced in version 2.44 caused the IL display program to output
"**BAD-SIZED-INT-KIND**" for Microsoft sized integer types (like __int64).
This is now fixed.

8/28/00  C++-generating back end: regenerating a cast sequence on an
         overloaded function

The C++-generating back end failed to regenerate a sequence of more than one
cast operation applied to the name of an overloaded function.  The problem was
due to the incorrect recording of constant expressions when
RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE.  For example:

  int f(int) { return 3; } 
  int f(char) { return 4; } 
  int (*p)() = (int (*)())(int (*)(char))f; 

was regenerated as follows (leaving out #line directives):

  int f(int) { return 3; } 
  int f(char) { return 4; } 
  int (*p)() = (int (*)())f; 

This is now fixed.

8/28/00  C++-generating back end: internal error on Microsoft-mode namespace-
         qualified variable declaration

In Microsoft mode, the front end accepts nondefining redeclarations of
namespace variables outside of the namespace (see Changes entry of 8/14/97).
However, the C++-generating back end would abort when attempting to
regenerate such declarations.  For example:

  namespace N { extern int i; }
  extern int N::i;  // Used to abort in the C++-generating back end

This is now fixed.

8/27/00  C++-generating back end: avoid ambiguity on one-argument casts

Casts with one argument are now put out as old-style casts, e.g.,
as (X)y rather than X(y).  This helps avoid ambiguities, for example
in

  struct A { A(int); A(const A&); };
  int main() {
    int x = 1;
    A f((A)x);  // Should not be rewritten as int f(A(x))
  }

8/24/00  Overload resolution: conversion functions with bitwise copy
         constructor

Overload resolution sometimes did not consider all appropriate conversion
functions when processing an initialization of a class whose copy
constructor is generated and performs bitwise copying.  This resulted
in errors indicating that the initialization could not be done.  Now
fixed.

  struct B { };
  struct D : B {};
  struct Y {
    operator D();
  };
  Y oy;
  void f() {
    B b1(oy); // Now accepted
  }

In a related change, a bitwise copy constructor is no longer considered
to be able to copy an object of volatile-qualified class type.

8/25/00  Duplication of type_info objects with internal linkage in
         one instantiation per object mode

Previously, all routines and variables with internal linkage that were
referred to by template instantiations were "externalized" in one
instantiation per object mode so that a single definition could be created
and referred to from all the instantiations generated in the different object
files.  This behavior has changed for the special case of type_info objects
with internal linkage: these are duplicated across the object files (with
internal linkage, which results in better linker performance).  Setting
DUPLICATE_SPECIAL_STATICS_IN_INSTANTIATION_SLICES to FALSE restores the
previous behavior.  Otherwise, back ends that use the one instantiation per
object mode may need to inspect the duplicate_static_in_instantiation_slices
field in the a_source_correspondence structure.

8/23/00  Microsoft compatibility: "charizing" macro operator

In Microsoft mode, the combination of the special token #@ followed by a macro
parameter is replaced by the corresponding argument surrounded by single
quotes (') on expansion.  If necessary, backslashes (\) are inserted to escape
special characters.

  #define MC(x) #@ x
  char c = MC(*);     // Expands to: char c = '*';
  char d = MC(\000);  // Expands to: char d = '\000';
  char e = MC('o');   // Expands to: char e = '\'o\''; (not valid code)

8/22/00  C++-generating back end: spurious scope qualification on namespace
         scope declaration

When the name of a declaration in a namespace scope was hidden in that scope,
the C++ generating back end would sometimes emit a spurious qualifier on the
declaration itself.  For example:

  namespace N {
    int i;  // C++-generating back end used to regenerate "int N::i;"
    namespace { int i; }  // Hides N::i in N
  }

This is now fixed.

8/22/00  Throw specifications and reference to function initialization

The front end now requires that the throw specification of an initializer for
a reference to function exactly matches that of the reference type.
Previously, it was sufficient for the initializer to have a more conservative
throw specification.

  void f() throw() {}
  void (&rf) throw (int) = f;  // Previously accepted
                               // Now a discretionary error

8/22/00  C++-generating back end: qualified names for local types

When generating code to refer to a protected indirect base class defined in
function scope, the C++-generating back end sometimes used a qualified name
(which cannot be done for local names).

  void g() { 
    class A {}; 
    class B : public A {}; 
    class C : protected B { 
      A *f(); // C++-generating back end used to regenerate "::A *f();"
    }; 
  }

This is now fixed.

8/22/00  Pcc mode: local typedef applied to extern variable

In Pcc mode, the type declared on a block extern declaration is remembered
after processing of the block scope in which that declaration appears.  When
the block extern type is a local typedef, this results in a file scope IL
entity acquiring a local type.  The following example illustrates this:

  int *ep;
  void f() {
    typedef int *IP;
    extern IP ep;
  }
  /* In Pcc mode, ep was recorded to have type IP even outside f(). */

To reduce the likelihood of such situations occurring, the file-scope type
is now restored if it is equivalent to the locally declared type.

8/22/00  Incorrect position range information

The front end used to record incorrect position information for an add
operator when its first operand has an integral type and its second has
a pointer type.  A similar problem occurred when an integral type was
subscripted with a pointer type.  For example:

  void f(int *p) {
    int a = 1+p;  // Incorrect position range for IL entry of add
    int b = 1[p]; // Incorrect position range for IL entry of subscript
  }

This is now fixed.

8/22/00  C++-generating back end: extern "C" and local class definition

The C++-generating back end formerly put an extern "C" block around
a local class defined inside an extern "C" function.  That's not
necessary, and it's not valid C++.  The extern "C" on the class
is now suppressed.

  extern "C" void f () {
    class X {};  // Formerly put out with extern "C" { ... }
  }

8/21/00  Linker errors when building some configurations

A mistake in conditional compilation directives could cause linker errors when
building the front end with GENERATE_SOURCE_SEQUENCE_LISTS set to TRUE and
both MICROSOFT_EXTENSIONS_ALLOWED and MAINTAIN_NEEDED_FLAGS set to FALSE.
This is now fixed.

8/21/00  Compilation errors in il_display.c

Compilation errors occurred in il_display.c when building an IL display
program configured for the C++-generating back end.  This is now fixed.

8/21/00  C++ generating back end: invalid redeclaration of typedef class name

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was TRUE, the
front end would occasionally attempt to forward declare a class whose name
was set by a typedef declaration only.  This would result in invalid
generated code.  For example:

  template<class T> C {};
  typedef struct { C<int> c; } S;

would result in (excluding #line directives):

  template < class T > class C { };
  struct S;                      // <-- Invalid forward declaration
  template<> class C< int>  { }; 
  typedef struct { C< int>  c; } S; 

This is now fixed.

8/21/00  Exceptions on by default in strict C++ mode

Exceptions are now enabled by default when strict C++ mode is enabled.

8/21/00  Warnings on explicit conversions to qualified types

The front end no longer issues a warning about useless cv-qualifiers in
explicit conversion expressions if the cv-qualifiers didn't explicitly
appear in the expression.  For example:

  template<class T> inline
  T f(T a) {
    int x = (int const)a;  // Warning: "useless const"
    return T(0)+x;         // No longer a warning, even if T is "int const"
  }
  int  g(int c) {
    return f<int const>(c);
  }

8/17/00  C++-generating back end: parameter declarations

The C++-generating back end was modified to generate "(void)" instead of "()"
for empty parameter lists in function declarators that do not declare an
actual function.  This avoids certain declaration ambiguities.  In addition,
when RECORD_NAME_IN_PARAM_TYPE_ENTRY is TRUE, parameter names are regenerated
even in function declarations that are not definitions.  For example:

  void f(void (void));
  void g(int *p);
  void h(void);

is now translated to:

  extern void f(void (void)); // "(void)" used to be "()"
  extern void g(int * p);     // "p" used to be omitted
  extern h();                 // Unchanged

8/17/00  C++-generating back end: access declarations vs. using-declarations

A new configuration variable USING_DECLARATIONS_IN_GENERATED_CODE determines
whether access declarations or class member using-declarations should be
generated by the C++-generating back end.  The default value of this variable
is TRUE, which means that using-declarations are generated (previous versions
only generated access declarations).

8/16/00  Diagnostics on invalid constructor and destructor definitions

The front end used to diagnose missing return types and missing return
statements in definitions of constructors that were not actually declared
in the class definition.  For example:

  struct S {};
  S::S() {}  // Used to report a missing return statement and an omitted
             // return type in addition to the fact that there is no S::S()
             // declared in S.

Such diagnostics are no longer emitted.  (The missing declaration in the
function definition is still reported as an error.)

8/15/00  Nested class redeclarations

The redeclaration of a nested class inside the enclosing class is valid only
if that redeclaration is the definition of that class.  The front end now
diagnoses the invalid cases with an error in strict ANSI mode and with a
warning otherwise.

  struct S {
    struct N;
    struct N {};  // Redeclaration is definition: OK
    struct N;     // Redeclaration is not definition: error or warning
  };

8/15/00  Comparison of conversions to ambiguous base classes in overload
         resolution

The comparison of conversions to base classes in overload resolution
has been changed to conform more closely to the standard in cases
involving ambiguous base classes.

  class base {};
  class inter1 : public base {};
  class inter2 : public base {};
  class derived : public inter1, public inter2 {};
  void f(base *);
  void f(inter2 *);
  int main () {
    derived *p = 0;
    f(p);  // Not ambiguous: calls f(inter2 *)
  }

8/14/00  Spurious error on pure virtual function declared in unnamed namespace

The front end used to issue a spurious error on pure virtual functions
declared (but not defined) in an unnamed namespace.

  namespace {
    struct S {
      virtual void f() = 0;  // Used to trigger an error.
    };
  }

This is now fixed.

8/14/00  Microsoft compatibility: block-scope class member redeclaration

In Microsoft mode, the front end now accepts a redeclaration of a class
member in block scope.

  struct S { void f(); };
  void g() {
    void S::f();  // Accepted in Microsoft mode only
  }

See also Changes entry of 7/3/00.

8/10/00  EXTRA_SOURCE_POSITIONS_IN_IL, parentheses in expressions

The source positions recorded in expressions when EXTRA_SOURCE_POSITIONS_IN_IL
is TRUE no longer include parentheses, if any.  For example, on the
expression

  (x)+1

the first operand expression now has the start/end position of "x",
rather than of "(x)".

Also, the operator_position had been set (to indicate the position of
the parentheses as the "operator") even in expressions that are not
enk_operation nodes, which was incorrect.  That is no longer done.

8/10/00  Microsoft compatibility: ignore nondefining class declaration first
         declared as a class template

In Microsoft bugs mode a class declaration (that is not a definition) that
attempts to redeclare a class template declaration is ignored.

  template<class T> struct S;
  struct S;  // Ignored (with a warning) in Microsoft bugs mode

8/9/00   Nonstandard anonymous unions mistakenly represented as standard C++
         anonymous unions

The modifications applied for the Changes entry of 7/18/00 (nested types in
nonstandard anonymous unions) brought about the unintended side effect of
having nonstandard anonymous unions represented as standard auk_field C++
anonymous unions.  In C mode, this led to implicit field selections not being
generated in the IL and potential aborts in back ends that consumed that IL.

8/9/00   Source position on expression from pointer-to-member call

The source position in the IL expression for a pointer-to-member call
of the form

  (p->*x)(y)

was not quite correct.  The start position of the call was
given as the position of the "p" rather than the position of the
opening left parenthesis.  Now fixed.

8/9/00   Folding of constant address expressions in aggregate class
         initializations

A change to provide greater conformance with the C++ standard on
initializations in aggregate classes (see Changes entry of 4/7/99)
had the unintended side effect of suppressing some constant address
folding in such initializers.  The folding has been restored.

  struct X {char *x;};
  static char a[3];
  static X x[] = {&a[0]};  // Once again folded to a constant address

8/8/00   Microsoft compatibility: typedef name of a class visible to in-class
         member definitions

In Microsoft bugs mode, when a class definition appears as part of a typedef
declaration, the body of a member function defined inside that class
definition is not rescanned until the typedef has been processed.  This
makes the following example valid:

  typedef struct {
    enum { e };
    void f() { S::e; }  // In Microsoft bugs mode "S" and hence "S::e" is
  } S;                  // known; in other modes, the typedef is processed
                        // after the body of "f" and an error is issued since
                        // "S" is not yet known.

8/4/00   Microsoft compatibility: inherited members can be named as friends

In Microsoft mode, the front end now allows friend declarations to refer to
an inherited member of another class.  For example:

  struct B { void f(); };
  struct D: B {};
  struct X {
    friend void D::f();  // Accepted in Microsoft mode only
  };

8/3/00   C++-generating back end: output of static extern "C" function in
         Sun mode

In Sun mode, a static function can also be extern "C".  The C++-generating
back end did not quite handle that combination correctly.  Now fixed.

  extern "C" {
    static void f();  // Was put out as extern "C" void f();
  }

The field "surrounding_name_linkage_state" of "a_routine" entries is now set
for all routine declarations (not just definitions; see also Changes entry of
8/31/99).

8/2/00   Correct selection of overriding virtual functions

In some relatively complex situations involving multiple base classes of a
same type, the C++ front end could select the wrong virtual function as the
final overrider.  For example:

  extern "C" int printf(const char*, ...);
  struct A { virtual void f() = 0; };
  struct X: public A {
    virtual void k() = 0;
    void f() { k(); }
  };
  struct B: public X {
    int b;
    void k() { printf("b = %d\n", b); }
    B(int ii = 0): b(ii) { }
  };
  struct C1: public B {
    C1(int ii = 0): B(ii) {}
  };
  struct C2: public B {
    C2(int ii = 0): B(ii) {}
  };
  struct D: public C1, public C2 {
    D(): C1(1), C2(2) { }
  } dd;
  main() {
    C2* cp = &dd;
    cp->f();  // Should select the f() in C2's base A and print "b = 2";
  }           // used to select C1's A::f instead printing "b = 1".

This is now fixed.

8/2/00   Microsoft compatibility: Names from the instantiation context not
         considered during instantiation lookups

When not using dependent name lookup, the front end considers functions
from both the template definition context and the context of the reference
to the template.  In the following example, this would result in a call of
::f(char) when instantiating N::g(char).  The Microsoft compiler does not
consider names from the referencing context, resulting in a call of N::f(int).
We now emulate this behavior in Microsoft mode.

  void f(int);
  namespace N {
    void f(int);
    template <class T> inline void g(T t) {
        f(t);
    }
  }
  void f(char);
  int main()
  {
    N::g('c');
  }

8/2/00   Certain hidden names considered visible for dependent lookup

When doing dependent name lookup, certain symbols that should not be visible
were incorrectly included in the lookup.  This could result in spurious
ambiguity diagnostics or the calling of the incorrect function.

  void f(int);
  namespace N {
    void f(int);
    template <class T> inline void g(T t) {
      f(t);
    }
  }
  int main() {
    N::g(1);
  }

-------------------------------------------------------------------------------
Version 2.44, August 1, 2000

7/31/00  Missing diagnostic on friend declaration with too many template
         parameter clauses

The front end failed to issue an error on an unqualified friend template
declaration that contained multiple template parameter clauses.  In
addition, the subsequent use of offending template could result in confusing
diagnostics.  This has been fixed.

  class A {
  template <class T1> template <class T2> friend struct C;
  };
  template <class T> struct C { };
  C<int> c;


7/31/00  Missing diagnostic or internal error on typedef with destructor name

Depending on the configuration, the following kind of code would either pass
without a diagnostic or cause a compiler component to abort:

  struct S {
    typedef ~S();
  };

This is now fixed (a normal diagnostic is issued).

7/31/00  Internal error on erroneous use of reserved class name "type_info"

Some unusual and erroneous uses of the reserved class name "type_info" in
namespace "std" could lead to an internal error.

  namespace std {
    class type_info {
      union type_info(const type_info&);  // Could lead to an internal error
    };
  }

This problem was already described in the Changes entry of 11/23/99, but some
configurations (e.g., with a C++-generating back end) still suffered the bug.
Now fixed.

7/31/00  Abort when redeclaring a namespace name as an alias

The front end used to abort when a name first declared as a namespace was
redeclared as a namespace alias.

  namespace N {}
  namespace N = N;

This is now fixed (a normal diagnostic is issued).

7/30/00  C++-generating back end: Abort on type declaration within cast
         in C+ mode

The C++-generating back end aborted on a declaration of a type within
a cast in C++ mode.  Now fixed.

  void f() {
    (class A*)0;
    0;
  }

7/29/00  C++-generating back end: Abort on pointer-to-member of class
         from unnamed namespace

The C++-generating back end aborted on trying to output a pointer-to-
member type based on a class that is a member of an unnamed namespace.
Now fixed.

  namespace {
    class A;
  }
  A A::* p1;

7/26/00  in_front_end variable

A global variable "in_front_end" has been added, which is TRUE while
the front end is running, and FALSE otherwise, e.g., in the C-generating
back end.  This allows testing to avoid code that depends on front-end
data structures such as the symbol table.

7/26/00  C++-generating back end: conversion function calls put out as casts

The C++-generating back end now puts out calls of conversion functions
(except those that come from implicit conversions; see Changes entry of
7/20/00) as casts.  This avoids some problems with conversion functions
that cannot be named because of the limited type syntax available
in conversion function names.

7/24/00  C++-generating back end: "=" versus "()" form of initializers
         preserved

The form of an initializer ("(...)" versus "= ...") is now preserved
by the C++-generating back end.  Failure to do so caused the output
to run into disambiguation problems.

  struct B {
    B();
  };
  struct A {
    A();
    A(const B&);
  };
  void f() {
    A a = B();  // Output of "A a(B());" looks like a declaration
  }

IL CHANGE: the flag has_parenthesized_initializer was added to the
IL variable entry.

7/24/00  IL version number changed to 2.36

7/20/00  Elision of implicit cast, no type change

When an implicit cast in the IL is elided (because the underlying
expression already has the right type), the type of the expression
node is no longer changed to the destination type of the implicit
cast.  The two types are "the same", but might differ in typedefs.
Now, the original type is preserved, which may preserve useful
typedefs.

7/20/00  C++-generating back end: implicit conversions not put out

The C++-generating back end has been improved so that it does not
in general put out code for implicit conversions.  This includes
implicit calls of constructors and conversion functions, and
elided copy constructor calls (most of which were already suppressed).
To implement this, a new is_explicit_cast flag has been added to
the a_dynamic_init entry (IL CHANGE), and the compiler_generated
flag in an_expr_node is now being set in implicitly-generated function
calls (e.g., of conversion functions).

7/18/00  C++-generating back end: extraneous casts in template arguments

The C++-generating back end used to add invalid casts to certain template
argument lists.  To solve this problem, a new flag explicit_cast_applied was
added to a_constant (IL CHANGE).  It is set for tpck_cast variants of
ck_template_param constants.

7/18/00  Lookup of names in templates

The front end now implements the special template name lookup rules
specified in the standard (known as "dependent name" lookup).  This feature
can be enabled or disabled with the --[no_]dep_name command-line option.
The default is specified by the DEFAULT_DEPENDENT_NAME_PROCESSING
configuration flag.  It is automatically enabled in strict mode, and is
automatically disabled in Microsoft mode and cfront mode.

Dependent name processing requires that nonclass prototype instantiations
be enabled (see below).  As with nonclass prototype instantiations, enabling
dependent name lookup is likely to cause compilation errors when compiling
code that was not written with the feature in mind.

The dependent name lookup rules require that nondependent names be
looked up at the point of use in the template definition, and that
overload resolution be performed on nondependent calls at that point.
For dependent calls, the set of names considered is the set visible
at the point of use in the template definition plus any names made
visible by argument-dependent lookup at the point of instantiation.
Note that built-in types have no associated namespaces, so calls
with only built-in types can only resolve to names visible in the
template definition.  Furthermore, names from dependent base classes
are not visible to unqualified lookups.

The following illustrates some of the most common code problems encountered
when using dependent name lookup:

  template <class T> struct B {
    void f();
  };

  template <class T> struct A : public B<T> {
    X x;  // error: X not visible yet (formerly an error in strict mode)
    void g() {
      f();        // error: B<T>::f not visible
      this->f();  // must be written this way
      h(1);  // error: h(int) not visible using argument-dependent lookup
    }
  };

  struct X {};
  void h(int);
  A<int> ai;

7/18/00  Semantic analysis of nonclass template definitions

The front end is now capable of doing semantic analysis of nonclass
template definitions (it always has done semantic analysis of class
template definitions).  This processing is enabled using the
--parse_templates option, and is automatically enabled when
standard conforming dependent name lookup is enabled.  Although the
option is called --parse_templates, it also controls the
analysis of template static data member definitions, function template
default arguments, and default template arguments.

The EDG term for the semantic analysis of a template definition
is "prototype instantiation".  The processing enabled by the
--parse_templates option is known as nonclass prototype
instantiations.

The semantic analysis of these constructs requires the ability to parse
the template definitions without the use of actual template argument
values.  This, in turn, requires the use of the "typename" and "template"
keywords for syntactic disambiguation.  For example:

  template <class T> void f(T) {
    typename T::X *x;  // "typename" needed to know that X is a type
    typename T::template Y<int> y; // "template" needed to know that
                                   // Y is a template
  }

Code that was not written with this requirement in mind will probably
not compile when doing nonclass prototype instantiations.

7/18/00  Prototype instantiations in the IL (IL CHANGE)

The front end can now be configured to provide detailed information about
template definitions in the IL.  Formerly, only a textual representation
of templates was available.  Now, a parsed IL representation -- a
"prototype instantiation" of the template -- can be produced.  For example,
a class template is represented by a type entry for a class, a function
template is represented by a routine entry, etc.

The PROTOTYPE_INSTANTIATIONS_IN_IL configuration flag must be TRUE for
IL entries for prototype instantiations to be generated.  This flag
provides the default value for the variable prototype_instantiations_in_il,
which controls whether or not the prototype instantiation IL entries
are preserved in the IL.

Prototype instantiations can only be supplied when doing semantic
analysis of nonclass template definitions because it is the semantic
analysis that produces the IL for the template definition.  Consequently,
it is only possible to produce prototype instantiations for code that
can be parsed using the --parse_templates option.  [See Changes entry
of 8/30/00: class template prototype instantiations can now be saved even
if nonclass template prototype instantiations are not done.]

When PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the a_template entry
contains a pointer to the prototype instantiation for the template and
a pointer to an a_template_decl entry that describes the template
parameter list(s) of the template.  In addition, each template-based
class, routine, or variable (for static data members) contains a
pointer to the template from which it was generated.

The IL for prototype instantiations can contain some new "generic"
expression operators (e.g., eok_add, eok_lvalue) and can have a null
pointer for the constructor routine in a dik_constructor dynamic
initialization.  The C++-generating back end has been enhanced so
that can generate source code from the IL for prototype instantiations.

7/18/00  Nested types in nonstandard anonymous unions

Microsoft compilers accept named nested types in nonstandard anonymous unions
that are not introduced with a typedef name.  The front end now emulates this
extension in Microsoft mode.

  struct A {
    struct {  // Nonstandard "anonymous union" (with --microsoft)
      int i;
      union U { float f; double d; } u;  // Named nested type
    };
  };
  typedef struct X {
    int i;
    union U { float f; double d; } u;  // Named nested type
  };
  struct B {
    X;  // Not a nonstandard "anonymous union" because X has a named nested
  };    // type and the anonymous member is introduced with a typedef name


7/17/00  Name linkage of implicitly declared functions in C mode

Recent versions of the front end recorded implicitly declared functions in C
mode as having no name linkage.  This has been restored to "C" name linkage.

  void f() {
    g();  // Implicit declaration of "g" is valid in C mode;
  }       // now recorded as having "C" name linkage.

7/17/00  Microsoft C mode: void * operands in "?" operation

In Microsoft C mode (and also pcc and SVR4 modes), a "?" operator
with the second operand of type void * was treated as having a result
type of the first operand type rather than void *.  Now fixed.

  struct A {
    int dummy;
  };
  void g(int x)
  {
    struct A a;
    void *p=&a;
    (x?&a:p)->dummy = 0; // Should be an error.  Was accepted in Microsoft
                         // C mode.
  }

7/15/00  Sun compatibility: extern "C" functions with internal linkage

In Sun mode functions with internal linkage that appear in extern "C" blocks
now acquire extern "C" name linkage (ordinarily, they do not).  This interacts
with the Sun compatibility feature described in the Changes entry of 6/28/00
as illustrated by the following example:

  namespace X {
    extern "C" {
      inline void f() {}  // "inline" implies "static" in Sun mode
    }
  }
  using X::f;
  extern "C" void f();  // Redeclaration of X::f without a qualified name is
                        // possible because f has C name linkage

The C++-generating back end was also modified to generate

  extern "C" { inline void f(); }

instead of 

  extern "C" inline void f();

because the latter form is not accepted by Sun compilers.

7/13/00  Improved file name comparisons

The file name comparison routines have been improved so that certain
distinct file names that name the same file are considered to match.
For example, "t.c" and "./t.c" are now considered to match.  On
Unix-like systems, the inode numbers are compared for files that have
the same file name but different directory names.  This permits an
even broader range of differently-specified file names to match.
For example, "t.c" and "/a/b/t.c" will be considered to match when
the current directory is "/a/b".

7/13/00  Microsoft compatibility: include-kind ignored in PCH comparisons

In Microsoft bugs mode, a file included as "xyz.h" is treated as equivalent
to <xyz.h> when determining whether a given precompiled header file
can be used.  This is not done in other modes because the two directives
do not necessarily name the same file.

7/10/00  C++-generating back end: expressions preserved in more cases

When RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE (default for
C++-generating back end versions), constants that are subjected
to implicit type conversions now preserve the original expression
in more contexts.

  int main() {
    switch (55L) {
      case 22+33: // This expression is now preserved after implicit
                  // conversion to type of switch expression (long)
        break;
    }
  }

7/8/00   C++-generating back end: sizeofs preserved

When RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE (default for
C++-generating back end versions), constants for sizeof operations
now have an enk_runtime_sizeof expression attached so that the
original sizeof can be re-created in the generated code.

IL CHANGE: the fields associated with the enk_runtime_sizeof
expression variant have been changed to allow either an expression
or a type, but not both, and to indicate whether the expression
is an lvalue.

7/8/00   Compilation problem with uncompiled code in enter_predefined_type

The sample code in enter_predefined_type (enclosed in #if 0/#endif,
so not compiled ordinarily) had a compilation error introduced in
version 2.41, which is now corrected.

7/6/00   Constant-expressions for bit field lengths and array bounds
         recorded in IL

The Changes entry of 10/18/99 describes the configuration option
RECORD_CONSTANT_EXPRESSIONS_IN_IL that enables the recording of the structure
of constant-expressions in the IL.  This feature has now been improved to also
record constant-expressions appearing in the declaration of array bounds and
bit field lengths.  The C++-generating back end can use the new IL information
to regenerate such declarations in a form that is closer to the original.

  struct S {
    int a[2*3];
    int b: 2+3;
  };

In the example above, the constant expressions "2*3" and "2+3" can be recorded
by a_constant nodes in the IL (in addition to the reduced integer values 6 and
5 respectively).

7/5/00   Namespace scope extern "C" variables with internal linkage

Unlike their counterparts with external linkage, namespace scope extern "C"
variables with internal linkage refer to distinct entities when declared in
distinct namespaces.  However, they used not to get mangled which could cause
name collisions.  For example:

  namespace N1 {
    extern "C" {
      int x;
      static int i = 2;
    }
  }
  namespace N2 {
    extern "C" {
      int x;            // Refers to same entity as N1::x.  Not mangled.
      static int i = 3; // Distinct from N1::i.  Should be mangled.
    }
  }

This is now fixed by mangling the names of such variables.

7/3/00   C++-generating back end: "inline" suppressed in some cases

The C++-generating back end now suppresses the keyword "inline"
on function definitions that appear within a class definition (such
functions are implicitly inline).

7/3/00   Microsoft out-of-class member function redeclarations

The Changes entry of 11/22/99 reported that in Microsoft mode the front end
now accepts out-of-class member function redeclarations (even if they are not
definitions).  However, the resulting IL representation was incorrect and
could lead to a variety of errors later on.  For example:

  struct A { void f(); };
  struct B { void f(); };
  void A::f();  // Accepted in Microsoft mode
  void B::f();  // Used to trigger a redeclaration error; now accepted

This is now fixed.

7/3/00   C++-generating back end: MSVC++ bug workarounds controlled by
         msvc_is_generated_code_target

Several workarounds for MSVC++ bugs in the C++-generating back end are
now controlled by the msvc_is_generated_code_target switch instead of the
microsoft_mode switch.  The latter is really related more to the source
language rather than to the capabilities of the target compiler.

6/28/00  Microsoft compatibility: bit-field cast to similar type gets error

In Microsoft C++ compatibility mode, a bit field selection cast to a
similar but not identical type got the error "taking the address of a
bit field is not allowed" in some cases.  Now fixed.

  typedef struct A {
    struct {
      unsigned long pad: 21; 
    } flags;
  } A;
  void f(const A *pcs)
  {
    unsigned long i = (unsigned long)pcs->flags.pad;
  }

6/28/00  Sun and Microsoft compatibility: declaration of function or variable
         made visible with a using-declaration

In Microsoft and Sun modes, a declaration of a variable or function with an
unqualified name that was previously made visible with a using-declaration
may be accepted as a redeclaration (or definition) of the imported entity
provided it was previously declared with C linkage.  For example:

  namespace N {
    extern "C" void f();
  }
  using N::f;
  void f() {}  // Accepted in Microsoft and Sun modes: the defined function is
               // N::f and it has C name linkage.  (Error in other modes.)

6/26/00  C++-generating back end: injected base class names hidden by the
         name of the derived class

The hidden name table processing used to assume that injected base class names
are always visible as unqualified names.  However, it is possible for a
member of a derived class to have the same unqualified name as one of the base
classes; the unqualified name then refers to the derived class.  For example:

  struct A { struct N {}; };
  struct B {
    struct M: A::N {
      int N;        // "N" refers to B::M::N, not A::N despite name injection
      void f() { A::N *p = 0; }
    };
  };

In this example, the C++-generating back end used to (erroneously) rewrite the
declaration of "p" using the unqualified name "N".  This is now fixed.

6/23/00  Microsoft compatibility: allow duplicate inline specifier

In Microsoft mode, a duplicate "inline" specifier in a function
declaration now elicits only a warning, not a fatal error.

  inline inline void f();  // Warning in Microsoft mode; error otherwise

(See also similar 6/13/00 entry for "virtual".)

6/23/00  Declaration position in diagnostic of exception specification
         mismatch for function template redeclaration

When a function template was first declared and then defined with a different
exception specification, the front end used to refer to the first declaration
as if it appeared at the position of the latter definition.

  template<class T> void f() throw(int); // Line 1
  template<class T> void f() {}          // Line 2

In the above example, the mismatch would mention the "previous function
template (declared at line 2)"; it now correctly says "line 1".

6/23/00  Local static variable with constant initial value,
         when RECORD_CONSTANT_EXPRESSIONS_IN_IL is TRUE

In configurations with RECORD_CONSTANT_EXPRESSIONS_IN_IL set to TRUE
(e.g., C++-generating back end versions), a const integral local static
variable with a constant initializer was sometimes not seen to be a
constant value.  Now fixed.

  int main () {
    static const int n = 6;
    int a[n];  // Got error, "constant value is not known"
  }

6/23/00  Elision of explicit cast above implicit cast in IL

When an explicit cast above an implicit (compiler_generated) cast is
elided in the IL, the remaining cast is now marked as explicit.

  int main () {
    char a[5];
    char *p = (char *)a;  // Cast now has compiler_generated FALSE
                          // Implicit cast is array -> pointer decay
  }

6/23/00  Keeping do-nothing explicit casts in the IL

In the past, casts that have no effect, for example

  int i = 0;
  int j = (int)i;

have not been included in the IL.  Now, when
PRESERVE_EFFECTLESS_EXPLICIT_CASTS_IN_IL is set to TRUE, they are.
This may be useful for some source-analysis applications.
Note that class casts always create a temporary, and consequently they
are never do-nothing casts, so they are unaffected by this change.

6/22/00  Position information for redeclared function prototypes

When processing a function prototype redeclaration, the front end used to
record the position information for the initial declaration on the routine
IL entry, but the position information of the last declaration on its
parameters (pointed to by the routine type).  For example:

  void f(void*);  // This position recorded for "f"
  void f(void*);  // This position recorded for the specifier "void*"

This has been changed to consistently record the first declaration.

6/22/00  Abort on using-declaration of overloaded delete operators

The front end used to abort when processing a class that imports a set of
overloaded delete operators from a base class with a using-declaration or
an access declaration.  The abort occurred only with exception handling
enabled.

  struct B {
    void operator delete(void* p);
    void operator delete(void* p, void* q);
  };
  struct D: public B {
    D() {};
    using B::operator delete;  // Caused front end to abort
  };

This is now fixed.

6/22/00  C++-generating back end: output of extern "C" for static functions

The C++-generating back end failed to output extern "C" for the declaration of
a static function with C linkage if that declaration was not a definition.
For example:

  extern "C" { static void f(); } // Used to be regenerated as:
                                  //   static void f();

This is now fixed.

6/22/00  C++-generating back end: improved output for class casts

Thanks to the addition of an "is_explicit_cast" flag to the
enk_temp_init expression node (IL CHANGE), the C++-generating
back end now does a slightly better job of preserving class casts
in the generated code for casts that are implemented as bitwise
copies.

  struct A {};
  struct B : A {};
  void e() {
    (A)B();  // Formerly put out as (B()), i.e., the cast to "A" was missing.
  }

6/21/00  Redeclaration of elaborated type in presence of using-declaration
         and typedef name referring to the same type

The front end used to issue a redeclaration error when referring to an
elaborated type that has been made visible by both a using-declaration
and a typedef declaration.  Similarly, a redeclaration error was issued
when a using-declaration brought in a type that was already made visible
through a typedef.

  namespace N {
    struct S {};
  }
  using N::S;
  typedef ::S S;
  void f(struct S*);  // Used to cause a redeclaration error
  using N::S;         // Idem

This is now fixed (see also related Changes entries of 11/1/99 and 11/8/99).

6/21/00  Non-constant sizeofs: SIZEOF_TYPE_IS_UNKNOWN

In some cases when using the C++ generating back end it is difficult
or impossible to fully duplicate the layout algorithm of the target C/C++
compiler.  In such cases, the sizes of primitive types and simple
classes may be knowable, but the sizes of complicated classes may
not.  By defining SIZEOF_TYPE_IS_UNKNOWN to a function-like macro
that tests a type and returns TRUE for the complicated cases, one
can now make sizeofs of complicated types unknown at compile time.
(And therefore the value determined by layout processing will be
irrelevant.)  Such sizeofs will be represented as expression nodes
and will therefore be passed through to the generated code as
sizeofs and not a specific constant value.  However, because they
are considered non-constant, they cannot be used in constant
expressions, e.g., as array bounds.  Because of that, when this
feature is used the front end is not completely standard-conforming.

A setting that makes non-POD class sizes unknown is

  #define SIZEOF_TYPE_IS_UNKNOWN(type) \
    (is_class_struct_union_type(type) && \
     !symbol_supplement_for_class(type)->is_POD)

6/21/00  Use of make_variable instead of alloc_variable

To ease the type-dependent customization of a_variable nodes, every allocation
of such nodes is now done through the make_variable function (i.e., no other
function calls alloc_variable directly anymore).  The make_variable function
was modified to prevent the created variable from being added to a scope list
if the indicated scope depth is NO_SCOPE_DEPTH.

6/21/00  IL file read abort due to bad pointer-to-member type

A mistake in building up related types for pointer-to-member casts
caused two routine types in the IL to point to the same parameter type
list.  If that IL was written to a file and read back in, and the
parameter type list had more than one parameter type, the "next"
pointers in the list would have had their addresses remapped twice,
which generally caused an abort in ptr_remap_function
("address not in any mem block").

6/19/00  C++ generating back end: abort on initialization of non-POD aggregate

The C++ generating back end used to abort when trying to generate C++ code for
the initialization of certain non-POD aggregate objects.  These cases involve
the default initialization of a field that itself has a non-POD aggregate
type.

  struct A { ~A(); };             // Non-POD aggregate
  struct B { B(); };
  struct X { int i; A a; B b; };  // Non-POD aggregate
  X x = { 3 };  // C++ generating back used to abort when attempting to
                // generate the initializer for x.a.

This is now fixed.

6/16/00  Microsoft compatibility: constructor declared with elaborated name

In Microsoft mode, the front end now accepts constructor declarations starting
with "struct", "class" or "union".  The "struct" and "class" keyword are
interchangeable, but the "union" keyword must be used in unions.  Such
elaborated constructor names cannot be parenthesized.  For example:

  struct S {
    struct S(int);       // Accepted in Microsoft mode
    class S();           // Accepted in Microsoft mode
    // union S(char);    // Not accepted (in any mode)
    (S)(float);          // Accepted (standard C++)
    // (struct S)(bool); // Not accepted (in any mode)
  };

6/14/00  Internal error on old-style specializations when guiding declarations
         are allowed

When the definition of an explicit function template specialization was
encountered without the "template<>" prefix (i.e., using the old pre-ANSI
syntax), the front end used to abort if one of the parameter types was
declared with a top-level qualifier.  This only happened when guiding
declarations were allowed.

  template<class T> void f(T a);
  void f(int const a) {}  // Used to abort with --guiding_decls

This is now fixed.

6/13/00  Microsoft compatibility: const/volatile anonymous unions

In Microsoft mode, the front end now accepts anonymous unions qualified with
"const" and/or "volatile".

  struct S {
    const union {
      int i;
      double d;
    };  // Accepted in Microsoft mode; not in default and strict ANSI modes
  };

6/13/00  Microsoft compatibility: spurious floating point range error

When the front end is built using the Microsoft Visual C++ Compiler
version 6.0 and is compiled with optimization, the code generated
for the routine conv_host_fp_to_float in float_pt.c is incorrect
resulting in spurious errors for floating point values that are nearly
out of range.  A workaround has been added to this routine to prevent
the problem.

6/13/00  Microsoft compatibility: allow duplicate virtual specifier

In Microsoft mode, a duplicate "virtual" specifier in a member
declaration now elicits only a warning, not a fatal error.

  struct S {
    virtual virtual void f();  // Warning in Microsoft mode; error otherwise
  };

6/12/00  Microsoft 7.0 compatibility: void return expressions

In MSVC++ 7.0, void return expressions are permitted (just as in strict ANSI
mode) in functions with void return type.  This is now emulated in Microsoft
mode with --microsoft_version=1300 or higher.

  void f();
  void g() {
    return f();  // Accepted with --microsoft_version=1300
  }

6/12/00  Microsoft compatibility: empty __declspec specifiers

The front end now allows empty __declspec specifiers in Microsoft mode.

  class __declspec()  A {};  // No longer an error with --microsoft

6/9/00   &T::x as nontype template argument

A nondeduced nontype template argument that is the address of a member
of a template-dependent class (e.g., &T::x, &A<T>::x) is now handled
correctly.  The case where the member turns out to name a set of
overloaded functions, and the matching function must be selected
on the basis of context, is also now handled correctly.

  template<class T, void (T::*f)(int)> class C { };
  template<class T> C<T, &T::output> call(T& obj);
  struct Test {
	  void output(int);
  };
  void sub()
  {
	  Test t;
	  call(t);
  }

6/8/00   Spurious error on block scope redeclaration of extern "C" function
         in Microsoft mode

Version 2.43 of the front end introduced a bug that caused the front end to
issue a spurious overloading error in Microsoft mode if an extern "C" function
was redeclared in block scope.

  extern "C" void f();
  void g() {
    void f();  // Error in version 2.43 with --microsoft
  }

This is now fixed.

6/8/00   Spurious error on namespace qualified template friend declaration

A spurious error was issued on a template friend declaration in which the
class or function name was specified with a namespace qualified name
in which the namespace qualifier named the current namespace.  This has
been fixed.

  namespace AA {
    template <class T> class A {
      template <class T2> friend class AA::A;
    };
  }

6/5/00   No warning on undefined special class members in unnamed namespaces

The front end used to warn about unreferenced and undefined class member
declarations in unnamed namespaces.  However, such declarations are a common
technique to prevent compiler-generated declarations.  For example:

  namespace {
    struct S {
      S();      // No longer causes a warning to be emitted
      void f(); // Still causes a warning if undefined
    };
  }

The front end has therefore been modified to not warn about undefined and
unreferenced constructors, destructors and assignment operators.

5/31/00  C++-generating back end: output of wide character constants

The C++-generating back end now correctly puts out wide character
constants in the L'x' form.

5/30/00  reinterpret_cast between pointer-to-function and pointer-to-object
         not allowed

A reinterpret_cast between a pointer-to-function type and a pointer-to-object
type is no longer allowed in strict C++ mode.  It continues to be allowed
in other modes so long as the destination type is at least as large as
the source type.

5/30/00  Abort in final_type_name_mangling on mangling of local type name

An abort in final_type_name_mangling has been corrected, on mangling
of a type name that is local to a member function and requires
compression.

5/24/00  Complete diagnostics when main() is declared as a friend function

The front end now diagnoses violations of constraints on main() when it is
declared as a friend function.  For example:

  struct S {
    friend void main();  // Warning or error: return type should be "int"
  };

5/23/00  Source position on expression for argument passed via elided
         copy constructor

The source position in the expression node for an argument passed via
an elided copy constructor (provided when EXTRA_SOURCE_POSITIONS_IN_IL
is set to TRUE) was incorrect.  Now fixed.

5/18/00  Microsoft compatibility: incompatible template parameter accepted
         in the definition of a member of a class template

In Microsoft bugs mode, the definition of a member of a class template
that appears outside of the class definition may declare a nontype template
parameter with a type that is different than the type used in the definition
of the class template.  A warning is issued.

  template <int I> struct A { void f(); };
  template <unsigned int I> void A<I>::f(){}

5/17/00  Cast of class rvalue to reference-to-nonconst no longer accepted
         in default mode

A cast of an rvalue of class type to a reference to nonconst is no
longer accepted in default mode.  It continues to be accepted in cfront,
Microsoft, and Sun modes, and it continues not to be accepted in strict
mode.

  struct A {};
  A f();
  int main () {
    static_cast<A&>(f());  // No longer accepted in default mode
  }

5/17/00  Cast of class rvalue to reference-to-const type accepted

An rvalue of class type can now be cast to a reference-to-const type
in strict mode.  This was formerly allowed only in default (non-strict)
mode.

  struct A {};
  A f();
  int main () {
    static_cast<const A&>(f());  // Now accepted in strict mode
  }

Also, a reinterpret_cast that does such a cast is no longer
accepted in default mode; it continues not to be accepted in strict
mode; and it continues to be accepted in Sun compatibility mode.

5/17/00  Overload resolution: "this parameter" of static member function
         doesn't count

In conformance with 13.3.3 paragraph 1 bullet 1 of the C++ standard,
overload resolution now considers the made-up "this parameter" for
a static member function call to have a match that's no better,
no worse than the match on any other function in the overload
set (i.e., it doesn't affect the selection of the best function).
Formerly, in conformance with some earlier drafts of the Working
Paper, the made-up parameter was considered an exact match.

  struct A {
    A(long);
  };
  struct B {
    static void y(const A& p);
           void y(long p);
  };
  struct C : public B {
    void z() { long j = 1; y(j);}  // Formerly got an ambiguity error;
                                   // Now calls B::y(long)
  };
  int main() {
    C c;
    c.z();
  }

5/15/00  C++-generating back end: typedefs preserved in initialization

Formerly, the front end removed type qualifiers and typedefs from
the type while processing the initialization of an entity.  This is
largely harmless, but it did cause a problem in the C++-generating
back end where a typedef might be removed in a cast and the type
could not be exactly represented without using a typedef.

  struct A {
    virtual void fun()=0;
  };
  struct AA : A {
    void fun() {}
  };
  extern "C" {
    typedef void (A::*PMFA)();
  }
  struct tagD {
    PMFA p;
  } matrix = { (PMFA)(&AA::fun) };  // Formerly, the cast did not use the
                                    // typedef, which lost the extern "C"

5/15/00  g++ compatibility: std as an alias for the global namespace

By default, the g++ compiler treats the "std" namespace as an alias for
the global namespace.  The --ignore_std option causes the front end
to emulate this behavior.

5/15/00  #include_next preprocessing directive

The #include_next preprocessing directive of gcc is now supported.
It has the same form as the #include directive, but begins searching
for the indicated file in directories on the search path following
the directory of the current file.  This is useful in header files
that replace another header file -- they can include the file they
override via #include_next and then adjust the defined values.

5/15/00  Internal error when declaring a nonstandard member constant in an
         expression context

The front used to abort when encountering a nonstandard member being declared
as part of an expression:

  void f() {
    (struct S { int const K = 20; })0;  // Used to abort; now a normal error
  }

This is now fixed (normal errors are issued).

5/15/00  Microsoft compatibility: using-declaration of extern "C" function

In Microsoft mode, declarations of synonymous extern "C" functions in
different namespaces introduce distinct entities (Changes entry of 10/6/99).
The front end has been modified to allow one of such entities to be made
visible in the scope of another such entity without conflict.  Overload
resolution can not distinguish the declarations however.

  namespace N {
    extern "C" void f();
  }
  extern "C" void f();
  using N::f;  // Now also accepted in Microsoft mode
  void g() {
    f();  // Ambiguous call in Microsoft mode
  }

5/12/00  static_cast of bool to pointer-to-member no longer allowed

A static_cast of a bool to a pointer-to-member type is no longer
accepted.  This was allowed -- probably by mistake -- in some versions
of the Working Paper, but 5.2.9p6 of the standard makes it clear that
it no longer is.  Conversions of bool constants to pointer-to-member
constants used to provoke an internal error.  They now simply get
an error.

5/9/00   Internal error when defining a friend of a local class with a
         namespace-scope qualified name

The front end used to abort when processing a friend declaration that is
also a definition if the name of the friend was qualified and if the friend
declaration appeared in a local class.  For example:

  namespace N { void g(); }
  void f() {
    struct L {
      friend void N::g() {}  // Used to abort
    };
  }

This is now fixed (a normal error is issued).

5/9/00   IL eok_unary_plus operator, for unary "+", in some configurations

When UNARY_PLUS_IN_IL is TRUE (default is FALSE except when the
C++-generating back end is being used), the unary plus operator is
retained in the IL.  When it is FALSE, +expr is represented simply as
expr, which is what the front end has heretofore done.

5/7/00   Change in cfront mode command-line option processing

Formerly, the cfront mode command-line options would set certain
flags to the appropriate mode for cfront compatibility regardless
of whether or not specific values had previously been specified.
Now, cfront mode only updates the value of flags that have not
been explicitly set.

For example, the command "edgcpfe --bool --cfront_3.0" did not enable
the bool keyword (because bool is disabled by default in cfront mode).
But now the bool keyword is enabled by this command.

5/5/00   File name sometimes omitted from error context output

In the error context output, the file name associated with the context
position should be displayed if it is not the same as the file name
indicated for the message in general.  Sometimes the file name was
omitted when it should have been displayed or displayed when it
should have been omitted.  This has been fixed.

5/2/00   Lowering of assignments of empty classes

IL lowering now suppresses assignments of empty classes (preserving
any side effects in the operands of the assignment).  This was
made necessary by the changes to optimize allocation of empty base
classes.  If a pointer to such a base class is obtained, and an
assignment is made to the base class, the assignment must copy
nothing, or otherwise it would destroy bytes of the following
subobjects.

5/2/00   C++-generating back end compilation problem when
         SUPPRESS_MICROSOFT_KEYWORDS_IN_GENERATED_CODE is TRUE

A minor problem has been corrected in the C++-generating back end.
Formerly, when cp_gen_be.c was compiled with MICROSOFT_EXTENSIONS_ALLOWED
TRUE but SUPPRESS_MICROSOFT_KEYWORDS_IN_GENERATED_CODE FALSE, there
was an unresolved reference to gen_microsoft_class_decl_modifiers at
link time.

5/2/00   IL lowering: clearing default argument expressions in declared_type

IL lowering now clears the default argument expressions on the parameter
types of the declared_type of a function.  The declared_type field is
present only when GENERATE_SOURCE_SEQUENCE_LISTS is TRUE (which is not the
default when IL lowering is done).  This problem caused an unlowered
pointer-to-member constant to remain in the IL, which provoked
an internal error in pm_class_type ("not a pointer to member type").

5/2/00   C++-generating back end: extern "C" around typedef declarations

The C++-generating back end now puts out an extern "C" block around typedef
declarations that appeared in such a block in the original source.

  extern "C" {            // This is now retained
    typedef void (*f)();
  }

5/2/00   Abort when declaring a template with a qualified declarator

The front end used to abort when encountering the declaration of a qualified
function template name while another entity with the same name had already
been declared in that scope.

  float f;
  template<typename T> void ::f(T) {}  // Used to abort

This is now fixed (an ordinary error message is issued).

5/2/00   Redeclaring an overloaded ::main

The front end used to abort when encountering the redeclaration of the
::main() function in a context where it was overloaded with a using-
declaration.

  int main();
  namespace N { void main(); }
  using N::main;
  int main() {}  // Used to abort processing

This is now fixed.

5/1/00   Breaking long strings in generated code

Long string constants in the generated C or C++ code are now broken
every 128 characters to avoiding stressing C compilers.

5/1/00   Suppressing duplicate diagnostics in template instantiations

When an error was detected while scanning a template definition, duplicate
diagnostics would often be issued during the instantiation of the
template.  These redundant diagnostics are now suppressed.  Note that
only diagnostics initially generated during the prototype instantiation
of a template are suppressed, so when the same diagnostic is issued during
different instantiations of a template (but not during the prototype
instantiation), the duplicate messages are not suppressed.  In addition,
because this processing depends on prototype instantiation processing,
duplicate messages in function bodies are suppressed only when doing
prototype instantiations of functions.

4/28/00  Internal error when a qualified file scope declaration finds an
         overload set in an unnamed namespace

The front end used to abort while processing a qualified file scope
declaration if a lookup of the declared name found an overloaded set of
functions in an unnamed namespace.

  namespace {
    void f();
    void f(int);
  }
  int ::f; // Used to abort

This is now fixed (a normal error is issued).

4/26/00  Microsoft compatibility: allow a namespace alias to be used to
         extend the aliased namespace

In Microsoft mode, a namespace extension can be defined using a namespace
alias.  For example:

  namespace N1 {
    namespace N2 {
      int x = 42;
    }
  }
  namespace NA = N1::N2;
  namespace NA {  // Fine in Microsoft mode (cannot use "N1::N2" here)
    int y = x;
  }

Note that this allows the extension of a namespace that is not in scope.

4/24/00  Abort in extract_constant_from_operand on "?" operator operating
         on template parameter values

An abort has been eliminated on processing a "?" operator whose first
operand is a known constant value and whose second and/or third
operands use nontype template parameters.

  template <class T> class A {
    typedef typename T::size_type size_type;
    static const size_type i = 12345;
    static const bool b = 1;
    static const int result = b ? i : i + 1;
  };

4/24/00  Diagnose use of virtual on nested classes and enumeration types

The front end now diagnoses the use of the keyword virtual when declaring
a nested class or enum type.

  struct X {
    virtual struct Y;       // Error.
    virtual enum E { e1 };  // Error.
  };

4/24/00  Block extern declarations of extern "C" static functions

In C++ mode, the front end used to ignore previous name linkages when
redeclaring a function with internal linkage in block scope.  In some cases,
this resulted in unwarranted diagnostics about incompatible linkage
specifications.

  extern "C" { static void f() {} }
  void g() {
    extern void f(); // OK, refers to declaration above.
  }                  // (Used to trigger an error.)

This is now fixed.

4/13/00  Diagnostics when redeclaring functions in Microsoft C mode

In C mode, Microsoft compilers only issue a warning when redeclaring a
function with an incompatible type.  However, if the return type is
incompatible, a strict error is issued.  The front end now emulates this
behavior (it used to just warn in all cases; see Changes entry of 4/28/95).

  long f(int);
  long f(double, int);  /* Warning in Microsoft C mode */
  long g(int);
  char g(int);          /* Error in Microsoft C mode */

4/12/00  Incorrect handling of template template arguments in
         nested instantiations

When a function template with a template template parameter passes that
template template parameter on to another function template, the
second template did not get the correct argument value.

This could result in incorrect behavior, incorrect mangled names, and
possibly internal errors.  This has been fixed.

  template <class T> struct B { };
  // T will have the wrong type inside g()
  template <template <class _T> class T> void g() { T<int> ti; }
  template <template <class _T> class T> void f() { g<T>(); }
  int main() {
    f<B>();
  }

4/7/00   Abort in Microsoft mode on duplicate dllimport definition

The front end used to abort processing when encountering a duplicate
definition of a function specified as "dllimport".

  __declspec(dllimport) void f() {}
  __declspec(dllimport) void f() {}  // Used to abort; now a normal error

This is now fixed.

4/5/00   Microsoft and Sun compatibility: friend class lookup

When a friend declaration nominates a class or struct using an unqualified
name, the C++ standard requires that the lookup of that name stops at the
innermost enclosing namespace scope (if not found, a class declaration is
injected in that scope).  In Microsoft and Sun modes, this limitation is
lifted and class names in outer namespace scopes can also be found.

  struct S;
  namespace N {
    class C {
      friend struct S;  // ::S in Microsoft and Sun modes; N::S otherwise.
    };
  }

4/5/00   Microsoft compatibility: explicit specialization of class inside
         of a class template

In Microsoft mode, an explicit specialization of a member class template
can be declared in the scope of a class (or class template).  Formerly, the
front end only supported such specializations of functions.  The standard
does not permit any form of specialization to be declared within a class.

  template <class T> struct A {
    template <int I> struct B { };
    template <> struct B<0> { };
  };
  A<int>::B<0> b;

4/4/00   Aborts when casting address constant expressions to integral types

The front end used to sometimes abort processing when encountering address
constant expressions that are cast to an integral type.  This was the case
in particular when the address constant was used as the size of an array
allocated with a new-expression, or when the address constant was assigned to
a const integral variable that was itself used in a context that requires an
integral constant expression.  For example:

  int y;
  int const i = (int)&y;
  double z[i];  // Used to abort
  double *p = new double[(int)&y];  // Used to also abort

This is now fixed.

3/31/00  Microsoft compatibility: two sets of template parameter names
         are visible in the definition of a member of class template

In the definition of a member of a class template outside of its class
both the template parameters of the enclosing class template and the
template parameters used in the definition of the member are visible
when using the Microsoft compiler (only the template parameters of
the member definition should be visible).  We now emulate this behavior
in Microsoft mode.

  template <class T> struct A {
    static int i[];
  };
  // Note that both T and T2 are visible
  template <class T2> int A<T2>::i[] = { sizeof(T), sizeof(T2)};
  int *x = A<int>::i;

3/30/00  Allow function redeclaration involving typedef with incompatible
         calling convention

When the configuration variable c_and_cpp_function_types_are_distinct is FALSE
the front end will now accept the redeclaration of a function with a (C or
C++) calling convention different from that of a previous declaration.
For example:

  typedef void F();
  extern "C" F f;
  extern "C" void f() {}
         // Now accepted when c_and_cpp_function_types_are_distinct is FALSE

3/24/00  Avoid generation of namespace qualifiers when selecting fields or
         member functions in output for MSVC++

Microsoft compilers do not accept expressions of the form p->N::X::f() where
N is a namespace name and X is a class name.  The C++-generating back end has
therefore been modified to never emit namespace qualifiers in such expression
contexts when msvc_is_generated_code_target is TRUE.  Previously, such
namespace qualifier was omitted only if X was a nontemplate class.

3/22/00  C-generating back end: extraneous casts on function call targets

Under some circumstances, the C-generating back end used to emit a cast on the
name of a function in a function call even though the function already had the
right type in the context of the call.  This extraneous cast can hinder some
C compilers from fully optimizing the expression.  Such casts are now entirely
avoided when the C-generating back is not configured as a standalone utility.
A standalone C-generating back end may still issue the casts in C mode or in
Microsoft C++ mode.

3/22/00  Microsoft compatibility: abort in IL lowering on __leave in __try

The object lifetime processing in the front end was not right for
__leave statements inside __try statements in some cases.  One possible
consequence was an abort in IL lowering in gen_goto_cleanup_actions
("common lifetime not found in curr lifetime parents").  Now fixed.

3/21/00  Abort in C-generating back end when an empty base is followed by a
         bit field

Under some circumstances, the front end would attempt to take the address of
a bit field when lowering the access to an empty base that was optimized to
share the offset of a bit field.  This caused the C-generating back end to
trigger an internal error.

  struct E { void operator=(E&); };
  struct S: public E { int s: 3; };
  void f(S &dst, S &src) {
    dst = src;  // Implicit access to empty base of S causes internal error
  }

This is now fixed: the lowered IL no longer takes the address of a bit field.

3/16/00  Abort in pm_class_type on pointer-to-member constant in
         local static initializer, after lowering

When LOWER_EXTERN_INLINE is TRUE, IL lowering promotes local static
variables to external and initializes them with code instead of
statically.  In some cases, it failed to lower pointer-to-member
constants in the initializer, which caused aborts later.

  template <class T> struct A {
    void (T::*pfn)();
  };
  struct B {
    void f() {
      static A<B> a = {0};  // Initializer was not lowered
    }
  };
  int main () {
    B x;
    x.f();
  }

3/15/00  Detection of loop in operator-> sequence

The front end looped when given a source program containing an
operator-> loop.  This is now corrected, and an error message is
issued.

  struct B;
  struct C;
  struct A {
    int z;
    B& operator->();
  };
  struct B {
    C& operator->();
  };
  struct C {
    A& operator->();
  };
  void func(A p) {
    int i = p->z;
  }

3/10/00  Lowering of condition declarations: missing "!= 0" test

Boolean controlling expressions in the IL are supposed to be normalized,
i.e., they are supposed to have an operator that returns 0/1 on top, or
they are constants 0/1.  In one case -- lowering of condition declarations --
the lowered code was not normalized.  Now fixed (a "!= 0" test has
been added).

  struct Foo {
    operator bool();
    Foo();
  };
  void Bar() {
      if (Foo f = Foo()) {  // Now has "!= 0" test on top of call
      }
  }

3/10/00  Internal error on local incompatible redeclaration of ::main

In C++ mode, the front end used to abort processing when encountering a local
declaration of the function "main" that was incompatible with a previous
declaration of that function.

  int main(int argc, char *argv[]) {
    int main(); // Used to abort
  }

This is now fixed (a normal incompatibility error is issued).

3/10/00  End position of bound function in call

With EXTRA_SOURCE_POSITIONS_IN_IL, the expression node for the
address of a nonstatic member function in a call of that function
had a null end position.  (The start position was correct.)  The
end position is now set correctly.

3/10/00  Microsoft compatibility: conflicting dllimport/dllexport
         specifications on class declarations

The front end now allows multiple class declarations to have conflicting
dllimport/dllexport specifications.  If a complete class definition has
not been seen yet, the new specification overrides the previous one.
Otherwise, the new specification is ignored.

  class __declspec(dllimport) X;
  class __declspec(dllexport) X;     // Replace "dllimport" by "dllexport"
  class __declspec(dllimport) X {};  // Back to "dllimport"
  class __declspec(dllexport) X;     // Still "dllimport"

3/9/00   Accessibility of using-declarations for privately inherited member

A using-declaration adjusting the access of a privately inherited member
used to be ignored when an elaborated name was used the refer to the 
inherited member.

  struct B { struct S {}; };
  struct D: private B { using B::S; };
  struct X: D { struct S s; };  // Used to result in an error.
  void f() { struct D::S s; }   // Ditto.

This is now fixed.

3/9/00   Generation of __int64 rather than long long in output for MSVC++

The front end has heretofore put out "__int64" instead of "long long"
in code generated by the C or C++-generating back end when in Microsoft
mode.  This wasn't quite right, because it confuses the source dialect
with the target compiler dialect.  To fix this, we have added a
configuration flag MSVC_IS_GENERATED_CODE_TARGET, which is the initial
value of the global variable msvc_is_generated_code_target.  When the
variable is TRUE, "long long" is always put out as "__int64", regardless
of the setting of Microsoft mode.  The default for the macro is TRUE
when the front end is compiled on a Windows system.

3/8/00   Microsoft compatibility: ignore __declspec(dllimport) from class
         definition on out-of-class member function definition

When a class is marked __declspec(dllimport), the front end used to also mark
the out-of-class definitions as dllimport (with a warning).  Such definitions
were consequently discarded (to avoid conflict with the definition that
should presumably have been imported).  However, Microsoft compilers treat
such out-of-class definitions as not having the dllimport property and the
front end now emulates that behavior.

  struct __declspec(dllimport) X {
    void f();
  };
  void X::f() {}  // Not a dllimport routine: keep its definition in the IL.

3/8/00   Pointer-to-member argument deduction problem

A bug was introduced in version 2.43 that caused template argument deduction
to succeed for certain pointer-to-member cases where it should fail
because the function qualifiers do not match.  This resulted in ambiguous
deductions, which in turn resulted in spurious errors.  This has been fixed.

  struct A {
    void f() const;
    void f();
  };

  template<class T, class R> void g(R (T::*f)() const);

  int main()
  {
    g(&A::f);
  }

3/7/00   Microsoft 7.0 compatibility: array new and non-array operator new

In MSVC++ 7.0, the processing for array new operators is slightly
changed, and this is now emulated in Microsoft mode with
--microsoft_version=1300.  If no operator new[] matches, the
overload resolution is done again with the non-array operator new
functions, to attempt to find a non-array new that can be used.

  void * operator new[](size_t);
  void * operator new(size_t, char const *, int);
  char *f() {
    return new(__FILE__, __LINE__) char[4]; // OK, --microsoft_version=1300
  }

3/7/00   Abort on pointer-to-member constant cast in initializer

In some rare situations involving the casting of a pointer-to-member function
constant that appears in a local static initializer, the front end would abort
processing while lowering the C++ IL.  For example:

  struct X {};
  struct Y { void mf(); };
  typedef void (X::*CB)();
  struct S { int i; CB c; };
  void f() {
    static S s[] = { { 0, (CB)(&Y::mf) } };  // Processing aborts here
  }

This is now fixed.

3/5/00   Abort on name mangling for Microsoft __uuidof(T)

An abort in name mangling, with the message

  mangled_encoding_for_address_constant: addr of unnamed

has been corrected.  It involves use of the address of a __uuidof
as a nontype template argument of a template class for which IL
lowering needs to generate a typeinfo variable.

This problem was solved via a fairly large reworking of the processing
for typeinfo variables in IL lowering.  IL CHANGE: This included renaming
the type entry flag used_in_exception to used_in_exception_or_rtti
and adding a new list pointer nontag_types_used_in_exception_or_rtti to
il_header.

3/3/00   Fix in insert_if_statement in lower_init.c

The logic in insert_if_statement was wrong when the caller passes
both an else-insert location and an argument in which to return the
pointer to the "then" block.  That particular combination was not
used in EDG's code, so this bug had no effect in the standard release.

3/3/00   Small change in lower_il.c for compilation as strict C++

A small change was made in lower_il.c to make the code there compile
as strict C++.  The code in question is only included when
ONE_INSTANTIATION_PER_OBJECT is defined.

3/2/00   Microsoft compatibility: multiple initializations of anonymous
         union members

In Microsoft mode the front end now accepts multiple mem-initializers for
members of the same anonymous union.  For example:

  struct X {
    X(): i(0), j(3.0) {}  // Now accepted in Microsoft mode
    union { int i; double j; };
  };

Both initializations occur in the IL in the order of the field declarations.

3/2/00   Internal error on redeclaration incompatibility in SVR4 mode

The front end sometimes aborted its processing with an internal error when
a block extern declaration was incompatible with a previous declaration of
that entity.

  extern int g;
  void f() {
    extern void (*g[])();  /* Used to trigger an internal error with --svr4 */
  }

This is fixed and a normal error message is issued.

2/29/00  Spurious error on certain command-line macro definitions

In 2.43, the processing of command-line macro definitions was modified
to permit the definition of function-style macros on the command line.
This change resulted in errors when characters that are not permitted
in tokens were used in macro definitions, such as "-Dx=\\a".  Such
macro definitions are once again accepted.

2/17/00  Accurate declared_type for parameters of template functions

The declared_type field of parameter variables in the IL definitions of
template functions is now set correctly.  Previously, the decayed type
was recorded instead.

  template <class T> T f(T a[10]) { return a[0]; }
  main() {
    int x[10] = { 0 };
    int i = f(x); // IL for f<int> definition now has variable "a" with
                  // declared_type int[10]; previously: int*
  }

2/16/00  Bug in IL lowering promotion of members of local classes

IL lowering did not correctly promote members out of local classes
in some cases involving templates that are first instantiated inside
a class.  For example, in the following the constructor of the local
class L remained on the scope list of L, when it should have been
promoted to the file scope.  Now fixed.

  template <class T> struct A {
     void f(T) {
       struct L {
         L() {}
       } l;
    }
  };
  struct B {
    A<int> x;
  } b;
  int main() {
    b.x.f(1);
  }


2/16/00  Compilation problem with C++-generating back end,
         MAINTAIN_NEEDED_FLAGS set to FALSE

A problem when compiling lower_name.c as part of a configuration
that uses the C++-generating back end with MAINTAIN_NEEDED_FLAGS
set to FALSE has been corrected.

2/11/00  Incorrect lookup in certain instantiations within namespaces

When using templates in namespaces, a lookup bug could cause the wrong
declaration to be found.  In particular, when the instantiation involved
a class reactivation inside a particular namespace, names from the namespace
sometimes hid names from the class reactivation scope.  This has been fixed.

  namespace N {
    int ZZ;
    template<class T> struct B {
      static int i;
      struct ZZ {};
      friend void f() {
        ZZ z;  // Incorrect ZZ found
      }
    };
    struct A { int f() { return B<int>::i; } };
  }

2/10/00  Microsoft compatibility: anonymous structs with non-POD fields

The front end now accepts Microsoft anonymous struct members with non-POD
fields.  Previously, such member declarations were reported as useless.

  struct P { int x; P() {} };  // Non-POD type.
  struct S {
    struct { P a; };  // Microsoft anonymous struct.
    S() { a.x = 3; }  // Used to not find 'a', even in Microsoft mode.
  };

2/8/00   Microsoft compatibility: name of current class not found as an
         injected class name

The Microsoft compiler does not find injected class names when looking for
an unqualified name.  While the front end ignored injected names from base
classes, the injected name of the current class was not ignored (as it
should have been).  The injected name of the current class is now ignored
in Microsoft mode for unqualified names.  [Patch sent out 2/10/00.]

  struct C {
    struct B { B(int); };
  };
  struct B : C::B {
    B() : B(1) {}
  };

2/8/00   IL lowering: unnecessary temporaries in generated code

In some cases, IL lowering used more temporaries than required.  This
came up in particular for pointer-to-member comparisons where one of
the pointer-to-member expressions contained an assignment.  The
extraneous temporaries have been eliminated.

2/7/00   Abort when defining certain predefined macros

A bug was introduced in version 2.43 that would cause the front end to abort
when invoked with an option that attempts to redefine any of the special
predefined macros "__LINE__", "__FILE__" or "defined".  This is now fixed:
the error issued by previous releases has been restored.

2/5/00   Allow expression like a.k or p->k, where k is a constant,
         as constant expression in cfront mode

An expression like a.k or p->k, where k is something like a member
enumeration constant, is now allowed as a constant expression in
cfront 2.1 and 3.0 modes.

  struct {
    enum E { e1, e2 };
  } a;
  void foo() {
    int x[a.e2];
  }

2/5/00   Reference to nonstatic local variable of enclosing function allowed
         in sizeof in local class

The C++ standard forbids a reference from within a local class to a
nonstatic local variable of an enclosing function, even when the variable
is not evaluated (e.g., in a sizeof expression).  A non-evaluated reference
is now allowed in non-strict mode.  A warning is issued.

  void foo() {
    int i;
    struct S {
      char a[sizeof(i)];  // Now allowed in non-strict mode.
    } s;
  }

2/3/00   Microsoft compatibility: disable access checks on copy constructor
         for base classes of handler parameters

In Microsoft mode, access checks to copy constructors for base classes of a
handler type are now disabled.  The access check for the copy constructor of
the handler type itself was already disabled in prior releases.

  struct Base { private: Base(const Base &src); };
  struct Derived: public Base {};
  void f() {
    try {}
    catch (Derived d) {}  // No longer an access error in Microsoft mode
    catch (Base b) {}  // No error in Microsoft mode in prior releases
  }

2/3/00   Internal error when allowing pointers to incomplete types in catch
         clauses

A bug was introduced in version 2.43 when stricter checking of catch types was
implemented (entry of 8/25/99).  In modes where pointers to incomplete types
are allowed in catch clauses, the front end would abort when lowering the
representation of an incomplete catch type.

  struct S;
  int main() { try {} catch (S*) {} }  // Used to abort in --microsoft mode

This is now fixed.

2/2/00   Abort while processing command-line macros

The changes made to allow function-style macros on the command line (entry of
9/10/99) introduced a bug in version 2.43 that would cause an abort when a
command-line macro contained an unclosed comment.

  edgcpfe -DM='/*' ...

Versions prior to 2.43 would accept this and expand the macro textually.
With this fix, however, the command-line macro is diagnosed as having an
invalid definition (just as would the equivalent #define in the source).

2/1/00   Exception handling cleanup state: new not folded into constructor

When "new" operations are not folded into constructors
(NEW_CAN_BE_FOLDED_INTO_CTOR is FALSE), the exception handling cleanup
state was sometimes incorrect when a new operation is done as part of
the initialization of a member or variable.  Now fixed.

  void might_throw();
  struct A {
    A(int j);
    int a_member;
  };
  struct B {
    B(A *a);
    ~B();
    A *b_member;
  };
  struct C : public B {
    C(int i, int j);
    int c_member;
    ~C();
  };
  C::C(int i, int j) : B(new A(j)),  // Cleanup state after this was wrong:
                                     // did not include destroying base class
                       c_member(i) {
    might_throw();
  }

2/1/00   Microsoft compatibility: freeing-on-exception entry for array new
         that uses non-array delete

In Microsoft mode, an array new operation can use a non-array operator
new if no operator new[] is found.  If placement delete applies, the
corresponding (non-array) operator delete will be called.  The dynamic
initialization entry that requests the deletion was left in the IL tree
by IL lowering, which is incorrect because the deletion is done by a
runtime routine.  The entry is now removed.

1/31/00  Microsoft compatibility: block extern declaration not linked to
         a later redeclaration

The implementation of the Microsoft compatibility feature documented in the
Changes entry of 10/6/99 caused the front end not to link an initial block
extern declaration to a later redeclaration of that same entity, even though
the entity had C++ linkage.  This caused two distinct routine entries to be
created in the IL.  For example:

  void f(char *x, char *y) {
    int cmp(char *, char *);  // (1)
    int d = cmp(x, y);
  }
  int cmp(char *s1, char *s2) { return 1; }  // Not linked to (1) in version
                                             // 2.43 of the C++ front end (in
                                             // Microsoft bugs mode).

This is now fixed.  [Patch sent out 2/10/00.]

1/31/00  Failure to diagnose ambiguous partial ordering

The front end incorrectly accepted certain function template partial
ordering cases that should have been diagnosed as ambiguous.  This has
been fixed.

  template <class T,class U> T f(U);
  template <class T> T f(int);
  int i = f<int>(1);

1/26/00  Abort on missing left brace in certain catch-clauses

The front end used to abort in the absence of a left brace following the
"catch (<decl>)" construct of a function-try-block of a function template or
in-class member function definition.

  template<class T> void f() try {} catch (...) }  // Used to abort.

This is now fixed.

1/26/00  Useless destructions and object lifetimes from default arguments
         left in IL

Some useless object lifetimes and dynamic initialization entries for
destructions were left in the IL tree when an array new was done on
a class whose default constructor has a default argument that builds
a destructible temporary.  These extra entities were not referenced
from elsewhere, and therefore they were probably harmless in most
applications.

  struct A {
    A();
    ~A();
  };
  struct B {
    B(A = A());
    ~B();
  };
  int main () {
    B*p = new B[10];  // main had extra object lifetimes/destructions
  }

1/26/00  Extra position info for explicitly declared intrinsic functions

Extra position information was not attached to routine entries for predeclared
functions (like operator new or, in Microsoft mode, _alloca) even when the
function was explicitly declared in the source.  This is now fixed.

  void* __cdecl _alloca(size_t);  // If EXTRA_SOURCE_POSITIONS_IN_IL is TRUE
                                  // (and assuming "--microsoft --c") then
                                  // extra position information is now
                                  // recorded in the predefined IL entry for
                                  // _alloca.

1/25/00  C-generating back end: startup code using the Sun C compiler

The Sun C compiler has a pragma that can be used to indicate initialization
routines that must be called at program startup.  The C-generating back
end now generates that pragma.  The pragma is automatically enabled
when the front end is compiled with the Sun C compiler.  The pragma
can be enabled separately by compiling with SUNPRO_C_IS_C_GEN_BE_TARGET
set to TRUE.

1/24/00  Microsoft compatibility: use of #import directory

In Microsoft compatibility mode, the import directory name (specified with the
option --import_dir, or "." by default) used to be combined with the include
search path if it was a relative name.  This is no longer the case: a relative
import directory name is now simply relative to the current directory.

1/21/00  Copy constructor elision for generated bitwise copy constructor

Copy constructor elision (optimizing away a copy constructor call) is
now done even when the copy constructor involved is a generated
bitwise copy constructor, i.e., something implemented as an assignment,
not a call.

  struct A {
    A(int);
    ~A();
    // Note: no declared copy constructor
  };
  A a = A(1); // No temporary created now
  A aa[2] = { A(1), A(2) };  // No temporaries created now

This eliminates some surprising (but correct, even though unoptimized)
behavior in classes that have some user-written constructors but no
user-written copy constructor.

1/21/00  Microsoft compatibility: type names as parameter names (C mode)

In Microsoft bugs C mode, the front end accepts old-style parameter-id lists
in function declarators even when the declarator is not the topmost declarator
of a function definition (i.e., even in contexts where such lists are not
allowed by the C standard, and where there is no way to define the type of the
parameters).  In the past, the front end did not allow the names of such
parameters after the first to match a type name; now, to conform to MSVC++, it
does.  For example:

  typedef void *PVoid;
  typedef int (*Fptr)(ident, PVoid);  // Accepted with --c --microsoft_bugs

1/21/00  Exception thrown in return of function with throw specification

The code generated for IL lowering to handle throw specifications
was wrong in the case where a function that contains no destructible
objects and has a throw specification calls a function in the return
statement.  The throw specification stack entry was popped off the
stack before the function call was executed.  Now, the return statement
is broken apart and the function call is done before the throw
specification stack entry is popped.

1/21/00  Microsoft compatibility: initializing enums with integer values

In Microsoft mode, the front end now allows the initialization of enum
entities with values of integer types (with a warning).

  enum { e1, e2 } v = 1;  // Accepted with a warning in Microsoft mode

[ Change undone.  See entry of 10/30/00. ]

1/20/00  Templates in unnamed namespace fail in one instantiation
         per object mode

Templates in unnamed namespaces did not work properly when using
one instantiation per object mode.  This has been fixed.

1/20/00  Microsoft compatibility: predefined macros defined in C mode

Formerly, the Microsoft predefined macros (_MSC_VER, etc.) were only
defined in C++ mode.  They are now defined in C mode too.  [Patch sent
out 2/10/00.]

1/20/00  Possible abort on definition of nested class

A bug was introduced in version 2.43 that resulted in an invalid memory
reference when a nested class was declared and later defined.  This could
potentially cause an abort or other unspecified behavior.  This has been
fixed.  [Patch sent out 2/10/00.]

  class A {
    class B;
    class B  { };
  };

1/19/00  Alternate implementation of extern inline functions

A new mechanism for providing out-of-line definitions of extern
inline functions has been implemented.  The old mechanism, which
is still the default, generates static copies of the extern inline
function in those translation units in which an out-of-line copy
is needed.  The drawback of this approach is that the address of
an extern inline function is not constant across translation
units as mandated by the standard.  The new mechanism is similar
to that used for the automatic instantiation of templates.  If
an out-of-line definition is needed for an extern inline function,
the prelinker assigns the "instantiation" of the inline function
to one of the translation units in which it could be defined.  Thus,
the new mechanism provides a slightly greater level of standard
conformance.

If "-tused" mode is being used, a definition of the inline function
is generated if the function is referenced in that translation unit.
Note that when using the prelinker, an out-of-line definition is only
created if one is actually required, but when using "-tused", an
out-of-line definition may be created even if it is not strictly
needed.

The principal drawback of the new approach is that it usually requires
a prelinking step even for programs that don't make use of templates.
This may require changes in users' Makefiles when creating libraries
because the object files that comprise the library may need to be
prelinked before the library is built.

When one instantiation per object mode is used, a separate instantiation
object file is created for each extern inline function body that is
generated.

There is no mechanism to manually control the definition of extern
inline function bodies (i.e., there is no equivalent of the
"#pragma instantiate" or explicit instantiation directive that
controls extern inline function definitions).

The new mechanism is enabled by setting the INSTANTIATE_EXTERN_INLINE
configuration flag to TRUE.  When the new mechanism is used, the back
end must check the new "suppress_inline_body" flag in the routine entry.
The body of the function must not be emitted if this flag is set.
Failure to check this flag will result in multiple definitions when the
program is linked.  No changes to the prelinker are needed to support
this feature.

1/19/00  C++-generating back end: constant expression output, lvalues

The changes made to record and use constant expressions in the IL
(see Changes entry of 10/18/99) disabled some optimizations done in
the generation of lvalues in the C++-generating back end.  As a
consequence, code was sometimes put out that included a "&" operation
on a class where operator& is overloaded.  Now fixed.  [Patch sent out
2/10/00.]

1/18/00  Internal error on pragma before template-id when using
         source sequence lists

An internal error could occur if a pragma appeared in a function body
immediately before a template-id when using source sequence lists.
For example:

  template <class T> struct A { static int f() { return 0; } };
  void g() {
    int i = 
  #pragma weak x
             A<int>::f();
  }  // Internal error while reading IL

This has been fixed.  [Patch sent out 2/10/00.]

1/17/00  Microsoft compatibility: cast to abstract class is allowed

In Microsoft bugs mode, a cast to an abstract class type is now
allowed:

  struct A {
    A(int);
    virtual void f() = 0;
  };
  void g() {
    A(1);  // Accepted in Microsoft bugs mode
  }

1/17/00  Microsoft compatibility: lvalue cast that casts away const

In Microsoft bugs mode, a cast of an lvalue to the type it already
has is ignored (that is, the expression remains an lvalue).  It turns
out that MSVC++ 6.0 also allows this even when the source and destination
types differ in their top-level cv-qualifiers.  Such cases are now
accepted.

  int main () {
    int *const q = 0;
    (int *)q = 0;  // Accepted in Microsoft bugs mode
    return 0;
  }

1/16/00  Microsoft compatibility: inline functions instantiated later

Normally, inline functions are instantiated when first referenced.
The Microsoft compiler, however, instantiates such functions at the
end of the translation unit.  The difference in instantiation point can
result in errors or differences in behavior because types may be
incomplete at the earlier point, or the set of visible functions
may be different.  In Microsoft bugs mode, inline functions are now
instantiated at the end of the translation unit.

1/14/00  Preserve bool-correctness in IL lowering of bool increment

IL lowering now uses a constant "1" of bool type in the code generated
for bool increment.  This preserves bool-correctness in the IL for
back ends that care.

1/13/00  Needed typedef removed as "unneeded", with cv-qualified parameter

The typedef in the following example was incorrectly removed as
"unneeded", when in fact it is referenced from the parameter variable
types.  Now fixed.  This bug is not visible in versions that write out
an IL file.  [Patch sent out 2/10/00.]

  typedef float * volatile * volatile pfv;
  void D( pfv y, pfv x, float a, int n ) {
    int i;
    for( i=0; i<n; i++ )
        (*y)[i] += (*x)[i]*a; 
  }

1/12/00  Nonstandard pointer-to-member constant passed to reference
         parameter of template function

A pointer-to-member constant without the required preceding "&"
was not accepted as the argument for a parameter of a template function
of type "reference to constant pointer to member".  Now fixed.

  template <class C, class TRT, class TP1>
  void f(TRT (C::* const & p)(TP1));
  struct A {
    int g(char *);
  };
  int main() {
    f(A::g);   // &A::g is standard and worked okay.
    return 0;
  }

1/12/00  Preprocessing: token pasting and inert macro identifiers

The preprocessor incorrectly handled cases where two identifiers
that are inert (i.e., they are macro names that appear within their
own expansions, and are protected from further expansion) are
pasted together.  The resulting identifier was still considered
inert, and it should not be.

  #define paste(a,b) a ## b
  #define paste2(a,b) paste(a, b)
  #define G "AB" G
  #define L L "EF"
  #define GL "CD"
  paste2(G,L)  // Should give "AB" "CD" "EF"

1/9/00   Eliminating blank in textual preprocessing output with inert
         macro identifiers

The textual preprocessing output for certain cases involving macro
names within their own expansions has been changed to eliminate a
blank in the output.  The affected cases have undefined behavior
according to the C and C++ standards, so the new output is just as
valid as the old, and it is useful to some people who use the C
preprocessor to process non-C text.

  #define need(func) .##need func
  need(__dtoi)  // Now expands to .need __dtoi
                // Formerly gave  . need __dtoi

1/7/00   Template static data members given wrong linkage in -tlocal mode

Version 2.42 introduced a bug that caused template static data members to
be given external linkage even in -tlocal mode.  This has been fixed.
[Patch sent out 2/10/00.]

1/5/00   result_is_not_used set incorrectly on argument of non-inlined
         function

The result_is_not_used flag was set to TRUE on an expression node
whose value is indeed used, when (a) the front end is doing inlining,
(b) the expression is an argument to a call of an inline function,
(c) the expression has side effects, (d) the corresponding parameter
is not referenced within the called function, and (e) the function
call cannot not be inlined for some reason (e.g., the function body
contains a switch statement).  This caused an internal error in
dump_expr if the C-generating back end is used.  Now fixed.

  inline void f(int a) {
    switch(1) {}
  }
  int g();
  int main () {
    f(g()+1);
  }

1/5/00   Ignoring multiple carriage returns at ends of lines

The change made on 7/2/99 to ignore multiple carriage returns at
the ends of source lines when IGNORE_CARRIAGE_RETURN_IN_SOURCE is
TRUE was incomplete.  It did not cover cases where the carriage
returns appeared at the end of a line that contains something
"unusual" like a trigraph.  Now fixed.

1/5/00   C++-generating back end: enumeration constants put out as
         defining expression instead

Due to a bug in the changes made in 2.43 to record the expression form for
constant expressions (see Changes entry of 10/18/99), the C++-generating
back end put out enumeration constants incorrectly in some cases.
Enumeration constants defined with the "name = value" form were put
out as the "value" expression, which doesn't usually have the correct
type (it's integral instead of the enum type).  Now fixed.  [Patch sent
out 2/10/00.]

  enum E { a, b = a+1 };
  void f(E);
  int main () {
    f(b);  // Was put out as f(a+1)
  }

1/3/00   Internal error on use of invalid partial specialization

The type of a nontype template parameter in a partial specialization is not
allowed to depend on another template parameter of the specialization.  We
correctly diagnose that error on this example, but an internal error results
later on a use of the partial specialization.  This has been fixed.

  template <class T, T, int> struct A {};
  template <class T, T t> struct A<T, t, 0> {};
  A<int, 0, 0> ai;

1/3/00   Internal error in C mode when pragma appears in a struct

A bug was introduced in version 2.43 that would cause an internal error
when a pragma that is to be included in the IL is used in a struct scope
in C mode.  This has been fixed.  [Patch sent out 2/10/00.]

12/27/99 Corrupted source sequence list when
         NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE

When nonclass instantiations are included in the source sequence list, the
entry for the partial instantiation of a function template first referenced
in a class declaration was not handled properly.  This could cause the
links that establish the list to become corrupted, effectively removing
certain entries from the list.  This has been fixed.  [Patch sent out
2/10/00.]

12/20/99 __cplusplus defined as 199711L

The predefined macro __cplusplus is now defined as 199711L as required
by the C++ standard.  In Microsoft and cfront modes it continues to be
defined as 1.

12/20/99 Internal error on preprocessing directive in template default argument

An internal error would result if a default argument in a template function
or member function of a class template was immediately followed by a
preprocessing directive.  This has been fixed.  [Patch sent out 2/10/00.]

  template <class T> struct A {
    A(int
#if 1
          = 0
#endif
          );
  };

12/18/99 Front end does not compile when ADDR_OF_BIT_FIELD_ALLOWED is set

When ADDR_OF_BIT_FIELD_ALLOWED is set to TRUE, exprutil.c did not compile
correctly because it contained a call to cast_node with too few parameters.
This problem was introduced in version 2.43 when the interface of cast_node
was updated.  This is now fixed.  [Patch sent out 2/10/00.]

12/16/99 Internal error while reading IL for local class member function

With certain configurations of the front end (e.g., the default C++-generating
back end configuration) an internal error would occur while reading the IL for
a local class member function that was the only entity to refer to a type in
namespace scope.  [Patch sent out 2/10/00.]

  typedef enum E {} T;
  void f() {
    class C {
      void* mf(T) { return 0; }  // Could cause an internal error
    };
  }

This is now fixed.

12/15/99 New empty statement kind

A new configuration flag REPRESENT_EMPTY_STATEMENTS_IN_IL enables a new
statement kind stmk_empty to represent empty statements in the IL.
Previously, empty statements were encoded using NULL pointers or empty blocks
with null positions.  The new representation has the advantage of allowing
accurate position information to be recorded (the position of the semicolon)
and simplifies the overall processing logic.  It also eliminates the need for
the flag has_empty_else_clause in a_statement.

  void f(int i) {
    if (i) ; else ;
    //     ^------^--- represented using statement kind stmk_empty
  }

12/14/99 is_specialized flag not set on routines specialized with old syntax

An internal logic error caused the front end not to set the is_specialized
flag when processing old-style explicit specializations with explicit template
arguments.

  template<class T> void f(T) {}
  void f<int>() {}  // Used to not be marked is_specialized

This is now fixed.

12/14/99 Microsoft compatibility: intrinsic __intN types

When emulating Microsoft Visual C++ 6.0 and higher the front end now treats
the extension types __int8, __int16, __int32 and __int64 as distinct built-in
types instead of making them synonyms for standard integer types of the
appropriate size.  An integer literal with an "i-suffix" then assumes one of
these types; e.g., "5i16" is a literal expression of type __int16.  This
feature makes the following example valid:

  extern "C" int printf(char const*, ...);
  void f(__int32 x) { printf("Special\n"); } 
  void f(int) { printf("Normal\n"); }
  int main() {
    f(1);                         // Calls f(int)
    f(2i32);                      // Calls f(__int32)
    f(__int32(3)+__int32(4));     // Calls f(int) (promotion for '+')
    f(5i16);                      // Calls f(int) (promotion)
    return 0;
  }

Note that the new types promote to the standard integer types.  The example is
not accepted with the option "--microsoft_version=1100" because with Visual
C++ 5.0 (and earlier) "int" and "__int32" are synonyms for the same type and
hence "f(int)" is considered to be defined twice.

Name mangling and demangling was adapted to encode and decode the new types.

12/13/99 Extra position information for switch cases

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the front end now maintains for
each switch clause a list of IL entries (type a_switch_case_entry) describing
the positions of the "case" and "default" keywords and the positions of the
associated colons.  For nondefault cases, a pointer to the constant label is
also recorded.  Unlike the list of constants in a_switch clause, these entries
are maintained in source order and useless "case" labels appearing in a
default clause are also recorded.

12/13/99 On Windows, when using a PCH file, open with read access only

The routine used on Windows to open a precompiled header file has
been changed to open the file for read access only.  It has been
reported that the previous behavior of opening the file for both read
and write access created performance problems when using ClearCase.

12/10/99 AT&T #assert processing with pcc mode or Microsoft mode

The AT&T preprocessing extension that allows testing of values set
by #assert predicates did not work correctly in conjunction with
pcc-style preprocessing or Microsoft-mode preprocessing, if the
tested value came from a macro expansion.  Now fixed.

  #define __sparc_conditional #machine(sparc) || defined(__sparc)
  #if __sparc_conditional  // Got error
  #endif

12/10/99 Microsoft compatibility: default arguments on class template
         member declarations

In version 2.42 we began to diagnose the use of an invalid template
default argument in the declaration of a member of a class template.
Such default arguments are now accepted and ignored in Microsoft mode.
A warning is issued.

  template <class T> struct A {
    void f();
  };
  template <class T = int> void A<T>::f(){}

-------------------------------------------------------------------------------
Version 2.43, December 8, 1999

12/8/99  IL version number changed to 2.35

12/7/99  Microsoft compatibility: template class names are not injected

In Microsoft bugs mode, the name of a template class is not injected into
its own scope.

  namespace N {
    template <class T> struct A { };
  }
  typedef int A;
  struct B : public N::A<int> {
    A *p;  // Finds global A
  };

12/7/99  Offset to base of object in virtual function table when
         construction vtbls are used

The offset to the base of the object stored in entry [0] of a
virtual function table was wrong in some cases, for the virtual
function tables generated for temporary use during construction
and destruction of subobjects.  Now fixed.

12/7/99  C++-generating back end: qualified name on function definition in
         the presence of using-directive

In some cases, the C++-generating back end put out a qualified name
on the definition of a namespace member function within the namespace,
which is invalid.  This happened when a using-directive in the file
scope made it necessary to use a qualified name for the function in
some cases.  Now fixed.

  namespace N1 {
    void f(int) {}  // Was put out as N1::f
  }
  using N1::f;
  namespace N2 {
    void f(float) {}
    float v;
  }
  using namespace N2;

12/6/99  Overload resolution gave incorrect ambiguity error

In certain cases involving three or more viable functions, at least one
of which is a template, overload resolution incorrectly reported
ambiguity instead of picking the best function.  Now fixed.

  template<class T> int getd(const T &);
  int getd(char *a);
  int getd(const char *a);
  int main(){
    char c[5];  
    getd(c);  // Incorrectly gave ambiguity
  }

12/6/99  Access of nested class in class template when redeclared

A spurious access error was issued when a nested class of a class template
was declared with the "class" keyword but defined later with the "struct"
keyword.  This has been fixed.

  template<class T> struct A {
    class B;
    struct B {
      void f(){};
    };
  };
  int main(){
    A<int>::B ab;
    ab.f();
  }

12/6/99  Declaration matching problem with member template and member function
         with the same signature

A bug in the process that matches a template declaration with a previous
declaration resulted in spurious errors in cases where a member function
template and a nontemplate member function have the same signature.
This has been fixed.

  template<int N> struct A {
    template <int M> int f();
    int f();
  };
  template<int N> template<int M> int A<N>::f() { return 2; }
  template<int N> int A<N>::f(){ return 1; }

12/3/99  Nondeduced array bound expressions not handled properly

Array bound expressions involving template parameters were not treated
as nondeduced contexts.  Instead, they would cause deduction to fail.
This has been fixed.

  template <int I> class A {};
  template <int I, int J>
  void f( int (&x)[I+J], A<I>, A<J>);
  int main() {
    A<1> a;
    A<2> b;
    int arr[3];
    f(arr, a, b);  // now accepted
  }

12/2/99  Microsoft compatibility: specifiers on free standing member type
         declarations

In Microsoft C++ mode, the front end now accepts various specifiers on free
standing member declarations of structs, classes, unions and enums.

  struct S {
    inline union T1 {};
    virtual class T2 {};
    typedef struct T3 {};
    const enum T4 {};
    explicit class T5 {};
  };

This example is accepted in Microsoft mode.

12/2/99  ABI CHANGE: Name mangling for template conversion functions

The mangled name for a template conversion function has included the
return type, which is redundant because the "name" of the conversion
function also includes the type.  The return type has now been removed.
This is an ABI change.  The old mangled form will be generated if
ABI_COMPATIBILITY_VERSION is less than 243.

12/2/99  is_reinterpret_cast flag in IL an_expr_node entry

The operation variant of an_expr_node now has an is_reinterpret_cast flag
indicating that a reinterpret_cast was used in the source form for the cast
(see Changes entry of 11/8/99 for the similar flag in a_constant entries).
The C++-generating back end was adapted to use this flag to avoid generating
reinterpret_cast constructs when the original source construct was a C-style
cast.  For example:

  struct R;
  struct CR;
  struct X {
    CR *p;
    R* mf() const { return (R*)this->p; }
  };
  struct R {};
  struct CR: R {};

The cast in X::mf() used to be issued by the C++ generating back-end as a
reinterpret_cast.  It is now preserved as a C-style cast.

12/2/99  Sun compatibility: undeclared template allowed in friend declaration

The library header files that come with the Sun 5.0 compiler include code
like the following:

  template <class T> struct iterator { };
  template <class T> struct reverse_iterator : public iterator<T> {
    friend void f<>(T&);
    void f(T&, T&) const;
  };
  template <class T> void f(T&);
  reverse_iterator<int> i;

This code is invalid because at the point at which "friend void f<>" is
encountered, f has not yet been declared as a template.  The Sun compiler
does accept this code, however.  In Sun compatibility mode, we now accept
references to undeclared function templates when the code appears in the
definition of a class template.

12/2/99  Improved error on unexpected end of default argument expression

The front end gave a confusing message when the default argument of a
template function ended with an unexpected token.  A better message is
now issued.

  template <class T> void f(T t,
                            int i = 1  // note missing ","
                            int j = 2);
 
12/2/99  Microsoft compatibility: no error issued on floating-point
         constant that is too small

The Microsoft compiler silently accepts floating-point constants that are
too small.  We now emulate this behavior in Microsoft mode.

12/2/99  Internal error when pragma appears in template argument list

An internal error could occur if a pragma occurred in a function body
immediately before a template-id or as part of the template-id.  This
has been fixed.

12/1/99  Microsoft compatibility: conversion of pointer to function to
         void * in overloading

In Microsoft mode, a pointer to function can now be implicitly converted
to "void *" in overload resolution.  (Formerly, this was allowed only
outside of overload resolution.)

  void f(const void *);
  void f(int);
  int main () {
    void (*pf)() = 0;
    f(pf);  // Now allowed in Microsoft mode.
    return 0;
  }

12/1/99  static_cast of float literal to integral type in constant expression

A static_cast of a floating-point literal to an integral type is now
allowed in a constant expression.

  class bar {
    static const int foo1 = (int)1.0;              // Was already allowed
    static const int foo2 = static_cast<int>(1.0); // Now allowed
  };

12/1/99  Hidden name table, C++-generating back end: better name output

Several improvements have been made in the name generation in the
C++-generating back end.  These were motivated largely by the need
to get around bugs in MSVC++, but the generated names are now better
in certain cases in all modes in that they look more like the names
that a human programmer would write.

  (1)  The suppression of "this->" on member function calls is
       more sophisticated.  It is still done only in Microsoft 4.2
       mode, however, where it is needed to avoid some MSVC++ bugs.
  (2)  The hidden name table and C++-generating back end are now
       aware of injected class names and handle them better.
       The same mechanism is used for block extern declarations.
  (3)  Some Microsoft-mode special processing has been removed because
       it is subsumed by this new processing (see Changes entries of
       7/10/97, 8/25/97, 5/21/99).

12/1/99  Microsoft compatibility: spurious error on injected class name in
         constructor initializer

A bug was introduced in version 2.42 that would cause a spurious error to be
issued in Microsoft mode when an unqualified non-visible base class name was
used in a constructor initializer list.  This has been fixed.

  struct A {
    struct C { };
  };
  struct B : A::C  {
    B() : C () {}  // error on use of C
  };

12/1/99  Additional information about PCH files that cannot be used

It automatic precompiled header file mode, it can sometimes be difficult
to know why a given PCH file is not used for a compilation.  The
--pch_verbose option has been added to display a message for each PCH
file that was rejected for a given compilation.

11/30/99 Microsoft compatibility: using-directives make names visible in
         the file scope

The Microsoft compiler (as of Visual C++ 6.0) has a bug that causes a
namespace nominated by a using-directive to be visible in the file scope.
We now emulate this bug in Microsoft bugs mode.

  namespace N  { }
  namespace N {
    class C{ };
    using namespace N;
  }
  void f(C*); // C is visible in the global namespace

11/29/99 Microsoft compatibility: spurious access errors in template
         declarations

A Microsoft compatibility change in version 2.40 introduced a problem
that resulted in spurious access errors in explicit specializations and
other similar template declarations.  This has been fixed.

  template<class T> class A { };
  template<class T> class B {
    typedef int T2;
    static A<T2> x;
  };
  A<B<char>::T2> B<char>::x;  // spurious access error on B<char>::T2

11/29/99 Problem with #assert when one value is prefix of another

The processing for #assert values (an AT&T preprocessing extension)
did not work right when one value was a prefix of the other.  Now
fixed.

  #assert foo(a)
  #assert foo(a b)
  #if #foo(a)
  int a;  // Should be compiled; formerly wasn't
  #endif

11/29/99 Template template parameters

Template template parameters are now implemented.  For example:

  template <template <class X> class T> struct A {
    T<int>	ti;
  };
  template <class T> struct B {};
  template <template <class X> class T, class T2> void f(T<T2>);
  template <template <class X> class T> void g(A<T>);
  int main()
  {
    A<B>   ab;
    g(ab);
    B<int> bi;
    f(bi);
  }

One aspect of template template parameters, the specification of which
is unclear in the standard, remains unimplemented.  We currently
do not allow the declaration of a template template parameter to depend
on another template parameter.  Other compilers that we tried also failed
to compile cases such as this:

  template <class T, template <T t> class X> struct A {
  X<1>	x1;
  };
  template <int N> struct B {};
  A<int, B> ab;

We will revisit this aspect of the feature after clarification by
the standard committee.

11/29/99 RECORD_TEMPLATES_IN_IL renamed to RECORD_TEMPLATE_STRINGS

Formerly, template IL entries were created only when RECORD_TEMPLATES_IN_IL
was TRUE.  They were created primarily as a means of saving the textual
representation of templates.  Now, IL template entries are always created,
but the textual representation is included only when RECORD_TEMPLATE_STRINGS
is TRUE.

11/29/99 NEED_NAME_MANGLING TRUE and DO_IL_LOWERING FALSE

The front end did not include the name mangling driver routines when
compiled with NEED_NAME_MANGLING TRUE but DO_IL_LOWERING FALSE (an
unusual combination).  The driver routines (e.g., do_all_name_mangling)
are now included in that configuration.

11/23/99 Internal error on erroneous use of reserved class name "type_info"

Some unusual and erroneous uses of the reserved class name "type_info" in
namespace "std" used to lead to an internal error.

  namespace std {
    class type_info {
      union type_info(const type_info&);  // Could lead to an internal error
    };
  }

The abort occurred when the configuration flags ABI_CHANGES_FOR_RTTI and
PRAGMA_DEFINE_TYPE_INFO_IS_REQUIRED were both TRUE.  This is now fixed.

11/23/99 Internal error when redeclaring namespace std using a template-id

The following example no longer triggers an internal error:

  namespace std {}
  namespace std<> {}  // Used to trigger an internal error

11/22/99 Clearer diagnostic for unresolved type names

During the processing of certain declaration specifiers, the front end now
distinguishes between names which were not found at all, and names which were
found but were not type names as was expected.  This makes for more
intelligible error messages.

  struct X { enum { B } };
  typedef X::A A;  // Name X::A not found
  typedef X::B B;  // Expected X::B to name a type

11/22/99 Microsoft compatibility: using-declaration of constructor or
         destructor

Ordinarily, using-declarations naming constructors or destructors are reported
as errors.  In Microsoft mode this is now reduced to a warning.  In nonstrict
modes the error is discretionary.

  struct B { B() {} };
  struct D: public B {
    using B::B;  // Error by default.  Warning in Microsoft mode.
  };             // Accepted (but ignored) with option
                 //   --diag_suppress=no_ctor_or_dtor_using_declaration

Such a using-declaration is ignored in the rest of the program.

11/22/99 Microsoft compatibility: allow member function redeclaration outside
         class definition

In Microsoft mode, the front end now allows member function redeclarations
outside the class definition even when the redeclaration is not a definition.

  struct S {
    void f();
  } s;
  void S::f();  // Accepted in Microsoft mode.

11/22/99 Keyword typename in friend class declaration

The front end now diagnoses the use of the keyword typename to declare a
friend class.  In the past this was accepted, but would lead to an internal
error when upon instantiation the designated type turned out not to name a
class type.

  template<class T> class C {
    friend typename T::X;  // Error.  Used to be accepted, unless T::X was
  };                       // instantiated to a non-class (internal error).
  struct S { typedef int X; };
  C<S> x;  // Causes T::X to resolve to int -> internal error.

11/19/99 Error on repeated default arguments on function templates

Default arguments on function templates and members functions of class
templates can only appear in the first declaration of those functions.
However, the front end used to not diagnose default arguments on a second
declaration if it appeared outside the namespace scope of the first
declaration.  Similarly, no diagnostic was issued if a member function of a
nested class template was defined outside its enclosing class.

  struct X {
    template<class T> struct Y {
      void f(int i = 0);
    };
  };
  template<class T>
    void X::Y<T>::f(int i = 0) {}  // Error cannot redeclare default arguments
                                   // (used to be silent).

This is now fixed.

11/18/99 Typedef of operator names

The front end now correctly diagnoses attempts to introduce an operator name
as a typedef name:

  struct S {
    typedef int operator new();  // Now correctly diagnosed
  };

Previously, such declarations usually resulted in a slightly misleading
diagnostic, but occasionally no diagnostic was issued or the front end
aborted.

11/17/99 Aborts while recovering from syntax errors in templates

Various syntax errors in class definitions occurring in the scope of a
template declaration could lead the front end to abort compilation.
For example:

  template<class T> volatile struct A {
    static int f() { return sizeof(T); }
  };

Many such cases are now fixed (i.e., an ordinary error message is issued).

11/17/99 Microsoft compatibility: treatment of names hidden by injected class
         names in the C++ generating back end

Injected class names are only visible to Microsoft compilers when they are
used as qualifiers.  For example:

  struct I { enum { max = 10 }; };
  struct E {
    typedef double I;
    struct N: ::I {      // "Partially injected" class name I
      N(::I *);
      N(I *);            // (1) Refers to E::I (i.e., double); not a
                         // redeclaration error
      N(int a[I::max]);  // Refers to ::I
    };
  };

In Microsoft mode, the C++ generating back end used to generate "E::I" for the
unqualified use of "I" at line (1), but Microsoft compilers do not accept
names qualified with class types for which a complete definition has not yet
been seen.  The front end and C++ generating back end have been adapted to
recognize such cases in Microsoft mode and generate C++ source that is
accepted by Microsoft compilers (i.e., in the example above "I" in line (1)
is left unqualified in the generated C++ source).

11/16/99 Microsoft compatibility: use and replacement of inherited typename

In Microsoft C++ mode, an inherited typename can be used with an unqualified
name in a class definition, and later that same name can be declared as a new
typedef synonym.

  struct A { typedef int I; };
  struct B : A {
    typedef I J;       // Refers to A::I
    typedef double I;  // Now accepted in Microsoft mode (introduces B::I)
  };

11/16/99 Overloaded function as call argument, with argument-dependent lookup

An argument of a call that is the address of an overloaded function
was not being handled properly in argument-dependent lookup.  The
function parameter types and return types of the functions in the
overload set were not processed, and therefore the scopes associated
with those types were not searched by the argument-dependent lookup.
Now fixed.

11/15/99 Name linkage of block extern declaration with visible type name
         synonym in surrounding scope

When a block extern declaration was processed with the same name as a
previously declared type, the declaration was sometimes given no name
linkage.

  typedef int I;
  int f() {
    extern I I(I a);  // Used to be processed as having no linkage;
    return I(1);      // now C++ linkage (or C linkage in C mode).
  }

This is now fixed.

11/15/99 Diagnose unqualified destructor name in friend declarations

Friend declarations that refer to a destructor using an unqualified name are
now diagnosed more clearly and more consistently.  Previously, in cases of
(useless) friendship of a class' own destructor, internal errors could result.

  class A {
    friend ~A() {}  // Used to result in an internal error; now an error.
  };
  class B {
    friend ~B();  // Used to be accepted; now an error.
  };

11/10/99 Microsoft compatibility: guiding-like friend declaration is not a
         new-style explicit specialization

In Microsoft mode, a function declaration that matches a function template
is treated as a specialization (see Changes entry of 3/12/98).  However, in
Microsoft compilers this is not the case if a friend is being declared.
This special treatment of friends is now implemented.

  void f(int);                 // A specialization in MS mode
  class A {
    friend void f(short);      // Not a specialization in MS mode (but used
  };                           // to be one previously)
  template <class T> void f(T) {}

11/10/99 Unresolved typeinfo variable due to dynamic_cast or typeid

In some cases where a dynamic_cast or typeid uses a class template type
that is little used elsewhere in the program, the typeinfo variable for
the class was not defined, leading to a link-time unresolved external.
This was due to a failure to recognize that the decider function
for the class must be instantiated.  (The instantiation of the decider
function in a compilation causes the virtual function table definition
to be put out, which causes the typeinfo variable definition to be put
out.)  Now fixed.

  template <class T> struct A {
    virtual void f();
  };
  template <class T> void A<T>::f(){}
  template <class T> struct B : public A<T> {};
  int main() {
    A<int>* a = 0;
    B<int>* b;
    b = dynamic_cast<B<int>*>(a);
  }

11/10/99 Internal error with source sequence entry for a pragma attached to a
         void parameter list

When source sequence list generation was enabled, the front end would trigger
an internal error when certain pragmas were attached to a void parameter list.
When INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL was set to TRUE, the following example
exhibited the problem:

  void f(
  #pragma mysterious // Unrecognized pragma
    void);

This is now fixed.

11/10/99 Microsoft compatibility: predefine macros

In Microsoft mode, _MSC_EXTENSIONS and _WIN32 are now predefined.
In addition, if the front end is built with the _M_IX86 macro defined,
the front end defines _M_IX86 to the same value.

11/10/99 Incorrect temporary file name on DOS/Windows

If the temporary directory environment variable ended in a backslash,
the generated temporary file name would omit the backslash.  This
has been fixed.

11/10/99 Internal error in ensure_il_scope_exists

Certain obscure and erroneous uses of elaborated type names appearing as part
of a default function argument could lead to an internal error in function
ensure_il_scope_exists (file il.c).  The following example used to trigger the
problem:

  struct S { int f(int, int = sizeof(enum)); };

Another example involves template arguments:

  template <class T> struct A { static int x; };
  template <class T> void f(T, int = A<class {}>::x) {} 
  void g() { f(42); }

This is now fixed.

11/10/99 Recursive instantiation of template default arguments

The front end failed to detect the recursive instantiation of a template
default argument.  This resulted in problems such as incorrect generated
C code.  A diagnostic is now issued.

  int i;
  template <class T> int f(T, T = f(i));
  int main() {
    f(1);
  }

11/9/99  Sun compatibility option

The front end now supports command-line switches --sun and --no_sun that
provide some language compatibility with the Sun CC compiler (version 5.0).
The default setting of these switches is determined by the new configuration
option DEFAULT_SUN_COMPATIBILITY.

Sun compatibility is only applicable in C++ mode, and cannot be enabled at the
same time as strict ANSI mode, or Microsoft or cfront compatibility modes.

The routine proc_command_line (cmd_line.c) was reworked to more cleanly
accommodate the new mode combinations.

11/9/99  Sun compatibility: using-directive non-tag hides tag from other scope

In Sun mode, a non-tag from one scope hides a tag from another scope when
both are visible as a result of a using-directive (such names should
be ambiguous because the hiding of a tag name should occur only when both
names are from the same scope).

  template <class T> struct B { };
  namespace N {
    typedef B<char> A; 
  }
  using namespace N;
  class A; 
  typedef A C;   // Sun mode uses typedef N::A instead of ambiguity

11/8/99  Visibility of declarations designated by member using-declarations

The front end now verifies that declarations designated by member using-
declarations are visible in the scope of at least one direct base class of
the class containing the using declaration.

  struct A { void f(int); };
  struct B: virtual public A { void f(long); };
  struct C: virtual public A { void f(short); };
  struct D: public B, public C {
    using A::f;  // Error: A::f not visible in the scope of B or C
  };

This diagnostic is not issued in Cfront mode.

11/8/99  is_reinterpret_cast flag in IL a_constant entry

The IL a_constant entry now has an is_reinterpret_cast flag that supplements
the existing implicit_cast flag, indicating that a reinterpret_cast
was used in the source form for the cast.  This is used in the il_to_str
output routines to produce better output in some cases involving ambiguous
base classes.

11/8/99  Using declaration of type name in presence of compatible tag name

The front end now allows a using-declaration to import a typedef name that is
also tag name in the scope containing the using-declaration, provided the two
names refer to the same underlying type.  (This is similar to the constraints
on a plain typedef.)

  namespace A { struct x {}; }
  namespace B { typedef A::x x; }
  namespace A { using B::x; }  // Now OK: imported name "x" refers to the same
                               // type as "struct x" in the current scope.

(See also the related Changes entry of 11/1/99.)

11/5/99  Array new/delete for class with two-argument operator delete

An array delete operation for a class that has no constructor or
destructor but does declare a two-argument operator delete did not
work correctly (the value passed to the second argument was the size
of one element of the array, not the whole array).

  struct S {
    void operator delete[] (void*, size_t s);
  };
  int main () {
    S* p = new S[7];
    delete[] p;
  }

This has been fixed, by using the runtime array allocation/deallocation
routines, rather than the simpler non-array routines, for news/deletes
of such classes.

11/3/99  Lookup of names in member templates of nontemplate classes

When looking up a function name in a member function template of a
nontemplate class, names from the referencing context of the template
instantiation were incorrectly being considered.  This could result in
incorrect behavior (e.g., calling ::g instead of A::g in the example
below) but could also result in an abort in compare_arg_match_levels.
This has been fixed.

  struct A {
    A(int){}
    A(){}
    template <class T> void f(T) {
    	g(1);  // should call A::g
    }
    void g(A);
  };
  void g(int);


11/3/99  Folding of address constants

In the past, certain cases of address constant folding were inhibited in order
to have the C++-generating back end generate nicer looking output (see the
Changes entries of 2/19/96 and 8/4/98).  However, these inhibitions are no
longer needed now that the front end can record constant expressions in the IL
(see Changes entry of 10/18/99) and the C++-generating back end exploits this
capability.  Since the original changes turned out to adversely affect code
generation quality, they have been removed.

11/3/99  Access check on operator delete for new folded into constructor

When an exception is thrown during a "new" operation, after
the storage is allocated but before the initialization of the storage
is completed, the storage is freed automatically by a call of
the appropriate operator delete routine, which must be accessible.

In some configurations, the allocation of a class object is handled
by the constructor, and the deallocation as well.  The access to
the operator delete routine should nevertheless be checked at the
point of the "new", even if the delete routine is not called
directly at that point.  Formerly, this was not done.  Now fixed.

11/3/99  Names for conversion functions to typedef types

The default name-output routine in the il_to_str routines now puts
out the names of conversion functions by converting the return type
rather than using the name in the routine IL entry.  This produces
output that duplicates the spelling of the type used in the source
code, e.g., with regards to typedef names used.  (The IL name is
the correct type, but not necessarily spelled the same way.)

This affects diagnostic output and the name as seen in customer code
that uses the il_to_str routines.  It does not affect the output
from the C++-generating back end, which already regenerated the name
from the return type in all cases.

11/3/99  Diagnostic for storage class without a declarator

The error issued when a storage class is specified without a declarator is
now discretionary (i.e., its severity can be weakened through the command
line).

  extern class C; 
    // --diag_suppress=storage_class_requires_function_or_variable
    // inhibits the usual diagnostic.

11/2/99  Pointer conversions not allowed on nontype template argument

Inplicit null pointer conversions, related-class conversions, and
conversions to "void *" are no longer allowed on a nontype template
argument.  See [temp.arg.nontype] paragraph 5 in the C++ standard.

  template <int *p> struct A { };
  A<0> a;     // error

11/1/99  New IL entry created for typedef redeclaring type in presence
	 of using-declaration

A new IL entry is now created on a typedef that redeclares a type name
that was previously visible via a using-declaration.  That is, the second
typedef in the following is now considered to declare ::ptrdiff_t rather
than to redeclare std::ptrdiff_t:

  namespace std {
    typedef int ptrdiff_t;
  }
  using std::ptrdiff_t;
  typedef int ptrdiff_t;  // declares ::ptrdiff_t
  ptrdiff_t x;

This change should be invisible to programmers, but it fixes some
incorrect output produced by the C++-generating back end on the above
test program.

(See also the related Changes entry of 10/15/99.)

10/31/99 Loop with NEAR_AND_FAR_ENABLED but not MICROSOFT_EXTENSIONS_ALLOWED

A bug in the disambiguation routines could cause an infinite loop when
NEAR_AND_FAR_ENABLED is TRUE but MICROSOFT_EXTENSIONS_ALLOWED is FALSE.
This has been fixed.  The only case known to loop is the following, which
also happens to be ill-formed:

  template <class T> struct near A {};

10/29/99 IL file reading problem with pragma in certain instantiation contexts

An IL read/write internal error could occur when processing a pragma in
a template declaration (but not in the body of a class or function).
This has been fixed.

10/29/99 Internal error when not using INSTANTIATION_BY_IMPLICIT_INCLUSION

In Microsoft mode, an internal error could occur when the end of the
primary source file is reached when using a version without
INSTANTIATION_BY_IMPLICIT_INCLUSION.  Now fixed.

10/29/99 Using-declarations for tag names and non-tag names

The front end used to ignore tag names referred to by using-declarations if
non-tag names were also present in the nominated scope.  This led to an
error in the following example:

  namespace N {
    struct S {};
    void S();
  }
  void f() {
    using N::S;  // Used to only import function N::S, but not struct N::S
    struct S s;  // Used to cause an error message (::S was incomplete)
  }

This is now fixed (also for using-declarations appearing in class
definitions).

10/28/99 Using-declaration of a type name when a synonym tag already exists

The front end now accepts a using-declaration importing a type name when that
name is already declared as a tag name for the underlying type in the scope
where the using-declaration appears.

  struct T {};
  namespace N {
    typedef ::T T;
  }
  using N::T;  // Accepted now (used to be a redeclaration error)

10/28/99 Extra source positions for "else" token

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the source position associated
with the "else" keyword in an if-statement is recorded in a_statement
(variant field variant.if_stmt.else_position).

10/28/99 Microsoft compatibility: (int)0 is not a null pointer constant

In Microsoft C++ bugs mode, (int)0 is no longer considered a null
pointer constant.  This duplicates a bug in MSVC++ 6.0 on the following:

  void f(unsigned long);                    
  void f(char *);                 
  int main () {                                                              
    f((int)0);  // MSVC++ 6.0 picks f(unsigned long); should be ambiguous
    return 0;                      
  }

10/28/99 Microsoft compatibility: qualifiers in template arguments

In version 2.39, we duplicated a Microsoft bug that ignored qualifiers
when comparing template argument lists.  This bug has been fixed
in Visual C++ version 6.0.  Our support for this bug is now dependent
on the Microsoft version value that is used (i.e., it is only supported
for Microsoft versions of 1100 and earlier).

10/28/99 offsetof based on __INTADDR__ when size_t smaller than pointer

An implementation of offsetof that uses __INTADDR__ on a system where
the size of size_t is smaller than a pointer no longer gets an error
on the implicit cast of the pointer operand to size_t.

10/28/99 Microsoft compatibility: ambiguous class reference allowed

If a lookup of a name before a "::" finds both a typedef to a class and
a class name made visible by a using-directive, the Microsoft compiler
chooses the class name rather than issuing an ambiguity error as is
required by the language.  We now duplicate this behavior in Microsoft
bugs mode.

  template <class T> struct basic_ios { };
  typedef basic_ios<char> ios;
  namespace std {
    struct ios { const static int i;};
  };
  using namespace std;
  int i = ios::i;  // uses std::ios

10/28/99 Microsoft compatibility: error in vacuous destructor call

A bug was introduced in 2.42 that caused the following example to be
rejected in Microsoft bugs mode.  This has been fixed.

  typedef int I;
  int main () {
    I *p = 0;
    p->I::~I();
  }

10/27/99 Microsoft compatibility: allocation of bitfields in unions

When the configuration variable TARG_MICROSOFT_BIT_FIELD_ALLOCATION was TRUE,
the front end would usually allocate twice the space required for a bit field
in a union.

  union U {
    char c1;
    char c2: 3;  // Allocated in 2 chars, so that sizeof(U) == 2;
  };             // sizeof(U) should be 1.

This is now fixed.

10/27/99 Abort while expanding extended variadic macro

The special treatment of the token pasting operator followed by an empty
variadic macro (as enabled with --extended_variadic_macros) could abort with
an internal error when the token pasting operator was preceded by replacement
text without embedded whitespace.

  #define M(a, b...) a, ## b  // Requires --extended_variadic_macros option
  int M(x);  // Used to abort

This is now fixed.

10/18/99 Configuration option to record constant-expressions in IL

Ordinarily, the front end folds constant-expressions into simple a_constant
nodes whenever possible.  The exact structure of the constant-expression is
discarded: "1+2" has the same representation as "3".  A new configuration
option has been added (RECORD_CONSTANT_EXPRESSIONS_IN_IL, in host_envir.h) to
add a field expr to struct a_constant; this new field will point to the
expression forming the constant if that expression is not a simple literal.
The option is off by default, unless the C++-generating back end is selected.

The C++-generating back end has been modified to use the new expr field when
it is available and non-null.  This will cause the back end to generate the
original expression rather than the resulting constant (i.e., "1+2" remains
"1+2" and does not become "3").  For example:

  int a = 3;  // No expression recorded for constant "3".
  int b = 1+2; // The constant resulting from "1+2" points to a constant
               // encoding the value "3", but also to a representation of
               // "1+2".

Some expressions are not currently representable in the IL; this includes
sizeof and __INTADDR__ operators, as well as expressions for constants
allocated in the file scope memory region but resulting from operations on
entities from a function scope memory region.  For example:

  void f() {
    int const start = 22;  // "start" allocated in function scope
    enum { e1 = start+1 };  // "e1" allocated in file scope; "expr" field
  }                         // of associated a_constant is NULL.

Note also that some constant expressions (array and bit field lengths in
particular) are not represented using a_constant nodes, and are therefore
never recorded in the IL.

10/15/99 Typedef redeclaration of a type reintroduced with a using-declaration

The front end now allows a typedef redeclaration of a type name that was
already reintroduced with a using declaration, provided the redeclaration is
benign (i.e., it declares the same type).

  typedef int I;
  namespace N { typedef int I; }
  using N::I;
  typedef int I;  // No longer an error

10/15/99 Microsoft compatibility: inline on block-extern declarations

In Microsoft bugs mode, the front end now accepts the inline specifier on
block-extern function declarations.

  int main() {
    inline void f();  // Accepted in Microsoft bugs mode
  }

10/14/99 Padding of allocated empty bases

An "allocated empty base" is an empty base class subobject that was not
optimized to share its offset with another subobject (see Changes entry of
8/9/99).  Even when the alignment requirement of that base is larger than one,
the front end used to allocate fields at the byte following the offset of the
empty base when other alignment requirements permitted so.  However, if the
C generating back end is used, this can lead to a mismatch between the offsets
computed by the front end and those assigned by the target C compiler.
For example:

  struct B {};  struct D: B { char c; };

produces essentially the following C code:

  struct B { char __dummy; };
  struct D { struct B __b_B; char c; };

Assuming targ_minimum_struct_alignment is four, the front end always concluded
that both B and D have size four (with field "c" at offset 2), while the C
compiler allocates 8 bytes for D (with field "c" at offset 5).
Setting the new configuration option TARG_PAD_ALLOCATED_EMPTY_BASE to TRUE
causes the front end to force padding on such allocated empty bases.  The
default value of this option is TRUE if the C generating back end is used,
and FALSE otherwise.

10/13/99 Abort on IL lowering of asm function with EH enabled

A change introduced in 2.42 caused an assertion failure on IL lowering
of an asm function (an optional feature -- see ASM_FUNCTION_ALLOWED)
when exception handling is enabled.  Now fixed.

10/13/99 Exception specification on return types

The front end now accepts exception specifications on return types of
functions.

  void (*f())() throw (int);  // Now accepted.

10/13/99 Abort while generating template strings

A bug was introduced in 2.42 that would cause an abort when generating
template strings (when RECORD_TEMPLATES_IN_IL is TRUE).  The abort would
occur when a function with default arguments was declared in a member class
template declared with another class template.  This has been fixed.

  template <class X> struct A {
    template <class Y> struct B {
      template <class Z> void foo(Z z = Z());
    };
  };

10/13/99 IL file reading abort on macros inside dllimport function definitions

In Microsoft mode, when a macro appeared inside a dllimport function body,
the IL reader aborted (as a consequence of a corrupt source sequence structure
being written to the file).

  struct __declspec(dllimport) X {
    void f();
  };
  void X::f() {
  #define M 2
  }

This example used to abort in configurations that accept Microsoft extensions
and also use source sequence entries, e.g., C++-generating back end
configurations.  This is now fixed.

10/13/99 Improved wording on nontype template parameter with class type

The diagnostic issued when a nontype template parameter has been declared
with class type has been changed to make its meaning clearer.

10/13/99 operator= that takes base class no longer taken as default operator=

The default value for DEFAULT_ALLOW_COPY_ASSIGNMENT_OP_WITH_BASE_CLASS_PARAM
has been changed to FALSE, which is what the standard requires.  Formerly,
it had a default value of TRUE, which allowed an operator= function
whose parameter is a reference to a base class to serve as the default
copy assignment operator for a class (thus suppressing the generation
of the default operator=).

  struct B { };
  struct D : public B {
    void operator=(const B&);
  };
  int main () {
    D d;
    d = d;  // Formerly called operator=(const B&), now calls generated
            // operator=(const D&)
  }

The behavior is unchanged in strict mode and Microsoft mode (where a
value of FALSE was used), and cfront mode (where a value of TRUE
was used).  The new command-line options --base_assign_op_is_default
and --no_base_assign_op_is_default can be used to override the default.

10/13/99 Stricter diagnostic on "void" exception specification

By default, the front end used to issue an error on incomplete types in
exception specifications for function definitions, except when that incomplete
type is "void": in that case the error was weakened to a warning.  This
special case has been removed: an error is issued in all cases.

  void f() throw (void) {}  // Used to be a warning by default; now an error.

Note that previously an error was already issued in strict ANSI mode.

10/12/99 Abort in Microsoft mode with calling conventions applied to a
         nonfunction abstract declarator

The front end used to abort in Microsoft mode if a calling convention was
specified on an abstract (i.e., unnamed) declarator for a nonfunction type.

  bool (__cdecl *p)[4] = (bool (__cdecl*)[4])1;  // Aborted while parsing the
                                                 // cast declarator.

This is now fixed.

10/12/99 Source positions on generated code at start/end of functions

The source positions on code generated at the start and end of functions,
e.g., constructor and destructor wrappers and exception-handling prologue
code, had source positions that matched the line of the function
header.  This was confusing to debuggers sometimes, in that it
fell outside the braces that delimit the body of the function.  Now,
the opening or closing brace position is used, as appropriate.

Some minor adjustments were also made in the generation of #line
directives by the C-generating back end for such cases.

10/11/99 Clarify diagnostic on qualified friend function definitions

A qualified name cannot be used in the declarator of a friend declaration that
is a function definition.  This used to be diagnosed as a scoping problem; now
the message is more explicit.

  void f();
  class C {
    friend void ::f() {}  // Error: a qualified name is not allowed for a
  };                      // friend declaration that is a function definition.

10/8/99  Call enter_system_specific_predeclared_symbols in all modes

The front end now also calls enter_system_specific_predeclared_symbols in C
mode (previously, it only did so in C++ mode).

10/8/99  Make use of ppd_ident conditional

The enumeration constant ppd_ident is only declared when the macro name
IDENT_DIRECTIVE_AND_PRAGMA is TRUE, but the front end used to refer to it
unconditionally.  This is now fixed.

10/8/99  __ANSIC__ set twice when EDG_WIN32 is TRUE

The basics.h header set __ANSIC__ twice (to the same value) when EDG_WIN32
is TRUE.  This could result in a warning from some compilers.  Now fixed.

10/7/99  Source position on bound function converted to pointer to member

In some modes (e.g., Microsoft), a bound function can be converted to
a pointer to member.  When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the
beginning source position of the pointer to member in the IL was incorrect.
Now fixed.

  struct A { int f(); };
  int main() {
    A b;
    if ( b.f == 0 ) return 0;
  }

10/6/99  Microsoft compatibility: extern "C" entities across namespaces

Microsoft compilers do not treat extern "C" declarations of identical names in
different namespaces as declarations of identical entities.  This behavior is
now emulated in Microsoft bugs mode.  Note that this may lead the C generating
back end to produce invalid C code without a diagnostic (though a Microsoft
C compiler will accept the code produced).

  extern "C" { void f(int); }
  namespace N {
    extern "C" { void f() {} }  // Warning (not error) in Microsoft bugs mode
  }
  int main() { f(1); }

In Microsoft bugs mode, this example causes two distinct IL routine entities
to be created, even though both have the same mangled name (a warning is
issued).  The C generating back end emits declarations for both entities, but
a Microsoft compiler will accept these conflicting C declarations of the same
name with a warning.

10/4/99  C++ generating back end: abort on specialization in Microsoft mode

In Microsoft mode, source sequence entries were not being created for
specializations of members of template classes.  This could cause an abort
in the C++ generating back end.  This has been fixed.

  template <class T> struct A { int f(); };
  int A<int>::f() { return 1; }

10/1/99  Abort when the end of a member function is missing

An abort would occur if a source file ended unexpectedly in the middle of
the definition of a member function that was defined inside its class or
class template.  This problem was introduced in version 2.42.

  template <class T> struct A {
    int f(int){

9/30/99  Abort when declaring namespace scope function inside a member
         function

When declaring a namespace scope function in a member function block scope,
the front end would abort (with an internal error) if a member function with
the same name was inherited.  This defect was introduced in 2.42.

  struct B { void f(int); };
  struct D: B {
    void g() {
      void f(); // Used to trigger an internal error.
    }
  };

This is now fixed.

9/30/99  Virtual function hiding and using-declarations

The front no longer warns about virtual function declarations in base classes
being hidden (or only partially overridden) when that declaration is in fact
visible through a using-declaration.

  struct X { 
    virtual void f(); 
    virtual void f(int);  
  }; 
 
  struct Y: public X { 
    using X::f; 
    virtual void f(int); 
  };

This no longer warns that X::f is only partial overridden in Y.

9/28/99  Matching of exception specifications on variables

The front end now correctly diagnoses mismatches in exception specifications
when (a) redeclaring variables or static data members with a pointer to
function, reference or function, or pointer-to-member function type, and
(b) when assigning or initializing entities of such types.  Assignment and
initialization was already partially checked, but exception specification are
now also checked on the return type and parameters types of the function
types involved.

  extern void (*pf1)(void ());
  extern void (*pf1)(void ()) throw (int); // Redeclaration error
  void (*pf2)(void () throw (char)) = pf1; // Initialization error

9/27/99  Spurious error when a preprocessing directive appears in
         a qualified name

An optimization used in a lookahead to determine if a given name is
part of a qualified name did not work properly if a preprocessing
directive appeared in the middle of the qualified name.  Now fixed.

  struct A { void f(); };
  void A
  #line 3
  ::f() {}

9/27/99  Support for long long size_t and ptrdiff_t

The front end did not work properly when configured to have "long" be
32 bits, but for size_t and ptrdiff_t to be 64 bits.  This has been
fixed. It did work properly if "long" was 64 bits and size_t and ptrdiff_t
were also 64 bits. Two new configuration macros have been added:
PRINTF_FORMAT_FOR_HOST_LARGE_INTEGER and PRINTF_FORMAT_FOR_HOST_LARGE_UNSIGNED.
The default configuration of these should always be correct (i.e., they should
not need to be changed).

The current recommendation for #defines to support long long using the
host long long are as follows (assuming a host machine with 32-bit
int and long and 64-bit long long):

#define LONG_LONG_ALLOWED 1
#define INTEGER_VALUE_REPR_IS_A_HOST_INTEGER 1
#define TYPE_FOR_AN_INTEGER_VALUE unsigned long long
#define TYPE_FOR_A_SIGNED_INTEGER_VALUE long long
#define PRINTF_FORMAT_FOR_SIGNED_INTEGER_VALUE   "%lld"
#define PRINTF_FORMAT_FOR_UNSIGNED_INTEGER_VALUE "%llu"
#define PRINTF_FORMAT_FOR_HEX_INTEGER_VALUE      "%llx"
#define MAX_INTEGER_VALUE 9223372036854775807LL
#define MIN_INTEGER_VALUE (-MAX_INTEGER_VALUE-1)
#define MAX_UNSIGNED_INTEGER_VALUE 18446744073709551615ULL
#define HOST_ALIGNMENT_REQUIRED 8

If, in addition, you want to use long long types for size_t and
ptrdiff_t, the following defines should also be used:

#define TARG_SIZE_T_MAX MAX_UNSIGNED_INTEGER_VALUE
#define TARG_PTRDIFF_T_MAX MAX_INTEGER_VALUE
#define TARG_PTRDIFF_T_MIN MIN_INTEGER_VALUE
#define TARG_SIZE_T_INT_KIND ((an_integer_kind)ik_unsigned_long_long)
#define TARG_PTRDIFF_T_INT_KIND ((an_integer_kind)ik_long_long)

9/23/99  Partial overriding and hiding of virtual functions

Minor changes have been made to the diagnosis (warning) of virtual function
declarations in base classes hidden by declarations in a derived class.
As before, the front end warns about an overloaded set in a base class being
only partially overridden in a derived class.  However, if such a warning is
emitted, no other warning regarding symbol hiding is issued for that name:

  struct B {
    virtual void f();
    virtual void f(char);
  };
  struct D: B {
    virtual void f(char);
    virtual void f(double);
  };

In the above example only a warning is issued about B::f being partially
overridden; previously, the front end also warned that D::f(double) does not
match B::f.
When all of the declarations of a virtual function with a given name in a base
class are hidden by a declaration in the derived class, this is now reported
as a case of name hiding; previously, this was reported as a failure to match
a virtual function declaration in the derived class.

9/22/99  Diagnostic on nonstandard subtraction of pointers

The front end now diagnoses subtraction of pointer types that differ in more
than just their cv-qualification signatures (error in strict ANSI mode,
warning otherwise).

  struct B {};
  struct D: B {};
  void f(B *p1, D const *p2) {
    p1 - p2; // Used to compile without diagnostic; error or warning now.
  }

However, no new diagnostics are issued in Microsoft and Cfront modes.

9/22/99  Microsoft compatibility: "asm" not a keyword in C mode

In Microsoft C mode, "asm" is no longer treated as a keyword.

9/22/99  Comparisons and conditional operators on multilevel pointer types

In C++ mode, the front end now accepts multilevel pointer types with differing
cv-qualification signatures on relational operators, and as second and third
arguments to conditional operators.  (Previously, this was only accepted when
one pointer type could be implicitly converted to the other type.)

  bool f(int const **p1, int **p2) {
    return p1 < p2;
  }

9/22/99  Performance problem with empty base class layout optimization

The empty base class layout optimization (see Changes entry of 8/9/99) could
lead to huge compile times (hours, days or longer) when dealing with
exceptionally deep class hierarchies.  Without the empty base class layout
optimization, some of these cases are compiled in seconds.  This is now fixed.

9/21/99  Diagnose undefined and unused members of classes in unnamed
         namespaces

The front end now issues an error on member functions and static data members
that are used (or virtual) but not defined.  Furthermore, a warning is
issued for unused nonvirtual member functions and unused static data members.

9/21/99  Abort with nonstandard anonymous unions (Microsoft mode)

Nonstandard anonymous unions introduced with typedef names could lead to an
internal error.  The problem was introduced in 2.42 (Changes entry of 6/14/99:
"Classes always contain a copy assignment operator").

  typedef struct { int i; } h;
  struct {
    int j; 
    h;  // Nonstandard anonymous union: used to abort.
  };

This is now fixed.

9/20/99  C++-generating back end, MSVC++ compatibility, function-typed
         parameters

MSVC++ 6.0 does not correctly parse a function-typed parameter if the
parameter name is omitted, e.g.,

  void foo(void  (void*));  // gets error
  void foo(void f(void*));  // okay

The C++-generating back end puts out no name for parameters on
function declarations even if the source code includes a name, so
it ran into this problem.  It now generates a name for a function-typed
parameter.

9/17/99  Linkage in unnamed namespace scope

Names declared in an unnamed namespace scope now follow the same rules to
determine their linkage as names declared in named namespaces.  Previously,
such names would not have external linkage unless they also had extern "C"
name linkage.  As a side-effect of this change, certain declarations that were
previously treated as definitions are now only declarations:

  namespace {
    extern int i; // Previously a definition of "i" with internal linkage;
  }               // now just a declaration with external linkage.

For mangling purposes (during IL lowering), the unnamed namespace is treated
as a namespace whose name is "__N<module-ID>" where <module-ID> is a
translation-unit-specific string generated by the front end (see also Changes
entry of 10/8/97); the name demangler has been updated to decode such a
sequence as "<unnamed>".

9/16/99  Conversions and pointer-to-members

The front end now accepts reinterpret_cast conversions of pointer-to-member
constants to unrelated pointer-to-member types, but the result is no longer a
constant.  static_cast conversions are allowed as part of pointer-to-member
constant-expressions.

  struct A { void f(); };
  struct B {};
  struct C: B { void f(); };
  void (B::*pmf1)() = (void (B::*)())&A::f; // Dynamic initialization
                                            // (like a reinterpret_cast)
  void (B::*pmf2)() = (void (B::*)())&C::f; // Static initialization
                                            // (like a static_cast)
  void (B::*pmf3)() = reinterpret_cast<void (B::*)()>(&C::f);
                                            // Dynamic initialization

9/16/99  Assignment problems in cfront mode introduced in 2.42

A change for operator= functions made in version 2.42 (see Changes
entry of 6/14/99) broke the handling of "=" in cfront mode in some
cases.  Now fixed again.

  struct Y {
    Y& operator=(int);
  };
  int main() {
    Y yobj1;
    Y yobj2 = yobj1;
    yobj1 = yobj2;  // Got error in 2.42 in cfront mode, now okay again
  }

9/13/99  __declspec(dllimport) processing could refer to freed memory

Bodies of functions marked with __declspec(dllimport) are always discarded,
but the process of discarding them occasionally referred to memory that had
already been freed at the end of the function scope processing.  This is now
fixed.

9/10/99  Command line allows function-style macros

The "-D" command-line option has been extended to allow function-style macros.
For example:

  edgcpfe '-Df(X)=a##X' ...

is essentially equivalent to "#define f(X) a##X" inserted before the first
source line.  (Note that some quoting may be required to prevent command line
interpreters from treating some characters -- like parentheses -- specially.)

9/9/99   Abort in C-generating back end when implicitly defined function
         is marked with dllimport (Microsoft mode)

In Microsoft C++ mode the front end used to abort when an implicitly defined
member function (e.g., a destructor or constructor) acquired the
__declspec(dllimport) property:

  struct A { virtual void f(); };
  struct __declspec(dllimport) B : public A {};
  B b;

This is now fixed.

9/9/99   Error when "friend class T" refers to a typedef

The front end accepts, as an extension, a friend declaration that names
a template parameter.  It did not, however, accept such a declaration
when the type supplied as the template argument specified a typedef name.
It now accepts such typedefs, provided the typedef names an acceptable
class type.

  template <class T> struct A { friend class T; };
  template <class T> struct B { friend class T; };
  struct X {};
  typedef X XX;
  A<X>  ax;  // worked
  B<XX> bx;  // failed

9/8/99   Cv-qualifiers on function typedefs

The front end now accepts cv-qualifiers on typedef declarations that introduce
synonyms for function types.  The resulting typedef names can be used only to
declare class members, pointer-to-member types and equivalent typedefs.
For example:

  typedef void MF() const; // OK now. (Used to be an error.)
  struct S { MF f; };      // OK: member S::f is a const member function.
  typedef MF S::*PSMF;     // OK, declaration of pointer-to-member-function.
  typedef MF MF2;          // OK: MF2 is equivalent to MF.
  typedef MF *PMF;         // Error: PMF is not equivalent to MF.

IL CHANGE: The field implicit_this_param_type in a_routine_type_supplement has
been replaced by two new fields: (a) class_type points to an unqualified
representation of a member function's parent type (if any), and (b) qualifiers
describes the qualification of the function type.  Code relying on the old
representation can usually easily be adapted to the new representation using
the macro implicit_this_param_type_of.

9/8/99   Assertion failure after ill-formed default template argument

In certain unusual circumstances, a template parameter with an ill-formed
default argument would cause an assertion failure when that parameter later
appears in a default template argument itself.  For example:

  template <class T = operator int> struct A { 
    template <class U = T&> struct B {};  // Assertion failure on T& when
  };                                      // instantiated.
  A<>::B<> ab;

This is now fixed.

9/8/99   Abort in gen_goto_cleanup_actions: labels, object lifetimes, and
         switch statements

An abort in gen_goto_cleanup_actions has been eliminated.  The abort
occurred when a case label was preceded by a label and there was a previous
switch clause with a destructible entry.

  struct X {~X();};
  class A {
    void f();
    void g(X);
  };
  void A::f() {
    X x;
    switch (1) {
      case 2: 
        g(x);
        break;
  L:  case 1:  // Abort on processing this
        break;
    }
  }

9/8/99   Access check on friend function nominations

If a friend function declaration nominates a member function, that member
function is now checked for accessibility from the scope of the nominating
class.

  class A { void f(); };
  class B { friend void A::f(); }; // Error: A::f not accessible from B

9/8/99   Initialization of const members in union aggregates

In C++ mode, the front end now diagnoses (with a discretionary error) union
aggregate variables which contain a const member and yet do not have an
initializer.

  int main() {
    union { int i; long const lc; } uv;  // Error: uv has an uninitialized
  }                                      //        const member.
      
9/3/99   Linkage of extern "C" const variables

The front end used to give external linkage to a const variable declared
in namespace or global scope and appearing inside a brace-enclosed
linkage-specification.  This is no longer the case, although a linkage-
specification without braces still causes such a variable to have external
linkage.

  extern "C" { int const two = 2; }  // two formerly had external linkage,
                                     // now has internal linkage
  extern "C" int const forty = 2;    // forty has external linkage, no change

9/3/99   Report extraneous braces in aggregate initializers

The front end now diagnoses extraneous braces around scalar elements of
aggregate initializers (error in strict ANSI mode, warning otherwise).

  struct { int i; } gs = { { 42 } };  // Error or warning.

8/31/99  C++-generating back end: extern "C" around static functions and
         classes

The C++-generating back end now puts out an extern "C" block around
functions and classes that are not themselves extern "C", e.g.,
static functions.

  extern "C" {           // This is now retained ...
    static void f() {
      extern void g();   // ... so that this is implicitly extern "C"
      g();
    }
  }

8/26/99  Microsoft C mode: Implicit pointer conversion can drop cv-qualifiers

In Microsoft C mode, an implicit pointer conversion is now allowed
to drop "const" and/or "volatile".  A warning is issued.

  int main () {
    const char *a = "abc";
    char *b = a;  /* Drops "const" in conversion. */
    return 0;
  }

8/26/99  Microsoft C mode: (void)0 accepted as null pointer constant

In Microsoft bugs C mode, the expression (void)0 is now accepted as
a null pointer constant in an initialization.

  int main() {
    char *p = (void)0;
    return 0;
  }

8/26/99  End position missing on asm statements

The end position was not recorded for asm statements (including Microsoft
__asm statements).  Now fixed.

8/25/99  Stricter checking of catch types

The front end now checks whether a catch type is an abstract class (an error)
or a reference or pointer to a nonvoid incomplete type (a warning in Microsoft
mode, a discretionary error otherwise).  For example:

  struct I;
  struct A { virtual ~A() = 0; };
  void f() try {
    try {
    } catch (I*) { // Warning or error: cannot catch pointer to
    }              // incomplete type.
  } catch (A) {}   // Error: cannot catch abstract class type.

8/24/99  Unimplemented data structure for comments removed from IL

The IL definition contained a data structure intended to represent
comments.  This feature was never implemented.  To avoid confusion,
we have removed the data structure.

8/23/99  Diagnostics for corrupted PCH files

Formerly, the front end would issue an internal error if a file I/O
error occurred while reading or writing a precompiled header file.
A catastrophic error is now issued instead.

8/23/99  C++-generating back end: qualified access to an otherwise
         inaccessible base class

The C++-generating back end used to drop qualifiers on names used in a class
scope when even when the unqualified (or less qualified) version of that name
is inaccessible (due to private inheritance).  For example:

  struct A { static int i; };
  struct B: private A {};
  struct C: B { void f(); };
  void C::f() { ::A::i = 42; }; <-- Must remain "::A::i": just "A::i" fails.

This is now fixed.

8/23/99  Assertion failure when defining a file-scope variable in a namespace

The front end used to abort its processing when it encountered the definition
of a file scope variable in a namespace.  For example,

  extern int i;
  namespace N {
    int ::i;  // Used to abort; now a graceful error.
  }

This is now fixed.

8/21/99  C-generating back end, Microsoft compatibility, __declspec(dllexport)

The C-generating back end has been changed so that the Microsoft
declaration specifiers __declspec(dllexport), __inline, and __forceinline
are put out on both the forward declaration and the definition of a function.
Formerly, they were put out only on the definition.  Similarly, for
a variable, __declspec(dllexport) is now put out on both the forward
declaration and the definition.

In the C++-generating back end, __declspec(dllexport) was already put
out on both declarations and definitions, but __inline and __forceinline
have been changed so that they are also put out on declarations.

8/19/99  Diagnose cv-qualifiers on static member function templates

The front end now diagnoses const- and volatile-qualified static member
function templates.  Previously, the front end would silently ignore the
"static" character of the member function.

  struct S {
    template<class T> static void f() const {} // Error on const.
  };
  int main() {
    S::f<void>();  // Fine (used to be an error because S::f was
  }                //       considered nonstatic).

8/19/99  Throw specifications allowed on explicit instantiation directives

The front end now allows throw specifications to be specified on explicit
instantiation directives when those specifications match those implied by
the template declaration.  For example:

  template<class T> void f() throw (T) {}
  template void f<int>() throw(int);    // Accepted now.
  template void f<char>();              // Always accepted.
  template void f<bool>() throw(char);  // Error: exception specification
                                        // mismatch.

8/19/99  Fetching value of volatile bit field is a side effect

The operation of fetching the value of a volatile bit field (either
the bit field type itself is volatile, or the class/struct is volatile)
should be considered to produce a side effect.  Now, it is.  The
following example, compiled in C mode, illustrates the issue:

  volatile struct X {          int x:1; } a;
           struct Y { volatile int x:1; } b;
  void f(void) {
    a.x;  /* Has side effect */
    b.x;  /* Has side effect */
  }

8/19/99  Abort in copy_default_arg_expr

Some changes to default argument processing made in 2.42 could cause
aborts on some default argument cases related to typedefs.  Now
fixed.

  struct A {
    typedef void (*pf)(int = x);
    static int x;
  };
  void f(int i);
  int main() {
    A::pf pf = &f;
    pf(); // Abort here fixed.
  }

8/19/99  Token positions in macro expansions in macro argument lists

The token positions for tokens in macros expanded in macro argument
lists were sometimes the position of the token following the argument,
which could be confusing.  Now they are the position of the beginning
of the outer macro invocation.

  #define S "abc"
  #define strcpy(x, y) __strcpy(x, y)
  strcpy(buf, S);  // Token position of "abc" was closing paren position
                   // Now position of "strcpy"

8/18/99  Diagnose "mutable" on anonymous unions

The front end now produces an error when "mutable" is specified on a
class-scope anonymous union.  For example:

  struct S {
    mutable union { int i; float f; }; // Error.
  };

8/17/99  Strict error for missing typedef declarator in strict ANSI C++ mode

In strict ANSI C++ mode, the front end now more consistently issues an error
(instead of a warning) on typedef declarations that miss a declarator.
For example:

  typedef enum {}; /* Error in strict ANSI C++ mode; warning otherwise. */

8/17/99  New and delete operators cannot have internal linkage

The front end now diagnoses attempts to declare new and delete operators as
static file-scope operator functions.  In strict mode, the diagnostic is an
error, otherwise it is a warning.

8/17/99  Front end now builds in strict C++ mode

The front end contained a few constructs that were no longer valid in
strict C++ mode because of recent language changes.  Most of the problems
were a result of the change to make string literals const.  There were also
problems related to the linkage of the function pointer passed to the
qsort and bsearch routines.  The front end now compiles in strict C++ mode.

A new configuration flag, BSEARCH_QSORT_FUNCTION_IS_EXTERN_C, has been
added that is used when building the front end as C++ code.  The C++
standard specifies that two versions of bsearch and qsort must be
supplied so that either a C or C++ linkage pointer may be passed as an
argument.  If the front end is being built using an implementation
that only supplies the C linkage version, this flag may be set to cause
the functions that are passed to bsearch and qsort to be declared as
extern "C".

8/16/99  C linkage ignored on pointer-to-member-function

The front end no longer distinguishes pointer-to-member-functions with C
linkage from those with C++ linkage.  Hence the following example is no
longer accepted:

  struct S {};
  extern "C" typedef void (S::*PMF1)();  // extern "C" ignored on type PMF1
  extern "C++" typedef void (S::*PMF2)();
  extern "C" void f(PMF1);
  extern "C++" void f(PMF2); // Error: same signatures, but different linkage

8/16/99  Microsoft compatibility: repeated typedef of integral type (C mode)

In Microsoft bugs C mode, the front end now allows a typedef for an integral
type to be repeated with a slightly different integral type (the type should
have the same size and alignment).  For example:

  typedef signed int I;
  typedef unsigned int I;  /* Just a warning with --microsoft_bugs --c */

8/16/99  Position of the start of a function-try-block

The front end now correctly records the start position of a function-try-block
(it already did so for the end position of such a construct).

8/16/99  Configuration option for floating-point template parameters

The configuration option to allow floating-point nontype template parameters
(an extension) has been renamed from ALLOW_FLOATING_POINT_TEMPLATE_PARAMETERS
to DEFAULT_FLOATING_POINT_TEMPLATE_PARAMETERS_ALLOWED.  It is also
now stored into a variable, floating_point_template_parameters_allowed.
For backward compatibility, if the old macro is defined and the new one
is not, the value of the old macro is transferred to the new macro.

One reason for this change is to allow the disabling of this extension in
strict mode, in order to get an error on the following even when
floating-point template parameters are allowed in default mode:

  template <int I> struct A {};
  A<1.5 ? 1 : 2> x;

8/16/99  Allow global qualifier on access declaration

The front end now accepts a leading "::" on an access declaration.

  struct B { int x; };
  struct D: private B {
    ::B::x;  // Used to trigger an error diagnostic.
  };

8/16/99  Warn about "used before set" in initializers

The front end now warns about an initializer that uses the value of the
variable that it is initializing.  For example:

  int main() { int x = x; }  // Warning: "x" is used before it is set.

8/13/99  Microsoft compatibility: checking of array property types

Microsoft compilers do not require any sizes to be specified for multi-
dimensional array property types.  This behavior is now emulated.

  struct S {
    __declspec(property(put=put_a)) int a[][][];  // No longer an error
  };

8/13/99  Compilation problem when INSTANTIATION_BY_IMPLICIT_INCLUSION is 0

The front end did not build properly when INSTANTIATION_BY_IMPLICIT_INCLUSION
is set to 0.  This problem was introduced in 2.42.  Now fixed.

8/12/99  Keep function bodies in IL even when the declarator is qualified

When the removal of unneeded entities was enabled, the front end used to
remove the body of a function definition that is a redeclaration with a
function declarator that is qualified with a namespace name or the global
qualifier.  This occurred even when the function has external linkage.
For example:

  extern void f();
  extern void ::f() {}  // Used to remove the body of f from the IL

This is now fixed.
-------------------------------------------------------------------------------
Version 2.42, August 12, 1999

8/11/99  IL version number changed to 2.34

8/10/99  No implicit conversion of const string literal to void *

The change for const string literals accidentally allowed the implicit
conversion of a string literal to  "void *".  That has been removed.

8/10/99  Microsoft compatibility: improvement in __asm support

The handling of Microsoft __asm directives has been modified to preserve
the spacing of text within the directive.  Formerly spaces were introduced
between tokens, which could render assembler code invalid.  In addition
to preserving the spacing, C++ style comments can now be preserved by
setting INCLUDE_COMMENTS_IN_ASM_FUNC_BODY.

In addition, the "asm" keyword is no longer accepted in Microsoft mode
(as is the case with the Microsoft compiler).  Only the __asm and _asm
forms of the keyword can be used to specify a Microsoft asm.

IL CHANGE: The is_asm_block field has been removed from the an_asm_entry
structure.  In addition,  the string pointed to by asm_string now contains
the opening and closing braces ("{" and "}") when the string represents
a brace-enclosed Microsoft asm block.

8/10/99  Support for surrogate functions

When the expression preceding the opening parenthesis of a call has
class type, overload resolution now looks for conversion functions
that can convert the class object to a pointer to function.  Each
such pointed-to function is called a "surrogate function", and each
is evaluated alongside other possibilities (e.g., overloading using
an operator() function).  If a surrogate function is chosen by overload
resolution, the class object is converted to a function pointer and
the indicated function is called with the call arguments.  See
[over.call.object] in the C++ standard.

  typedef void (*PF)(int);
  typedef void (*PF2)(float);
  struct A {
    operator PF();
    operator PF2();
  } a;
  int main () {
    a(1);  // Interpreted as (a.operator PF())(1);
  }

8/10/99  Friend class declarations and using declarations

When a friend declaration names a class type, it can find that class type
declared in the nearest enclosing namespace scope, but it should not find
using declarations in that namespace scope.

  namespace N { struct S {}; }
  using N::S;
  class C {
    friend struct S; // Used to find N::S; now attempts to create ::S
  };                 // and issues a diagnostic because ::S already exists.

8/9/99   Empty base class layout optimization (ABI CHANGE)

The front end can now allocate a nonvirtual nonpolymorphic base with no direct
or inherited member at the same offset as another direct base or at the same
offset as the first direct field of the class containing that "empty base".
E.g., assuming 4-byte int objects aligned on 4-byte boundaries:

  struct Empty {};
  struct Class: Empty {
    int i;
  };  // sizeof(Class) == 8 without the empty base optimization, but with
      // the optimization enabled sizeof(Class) == 4 because the Empty base
      // subobject is allocated at the same offset as the field i.

The optimization can only be performed if it does not cause two subobjects of
the same type to be allocated at the same address.  The optimization can also
cause an empty base class that appears after a nonempty base in the list of
base class declarations to be allocated at an earlier offset than the nonempty
base class.  For example,

  struct Empty {};
  struct Nonempty1 { char c; };
  struct Nonempty2 { char c; };
  struct Optimized: Nonempty1, Nonempty2, Empty {};
    // Empty and Nonempty1 are allocated at offset 0, while Nonempty2
    // appears at a positive offset (only if the optimization is enabled).

The variable targ_optimize_empty_base_class_layout controls whether the
optimization is attempted.  The default value of this variable is set from
TARG_OPTIMIZE_EMPTY_BASE_CLASS_LAYOUT, which in turn is TRUE by default if
ABI_COMPATIBILITY_VERSION is at least 242 and CFRONT_OBJECT_CODE_COMPATIBILITY
is FALSE.

8/9/99   Parenthesized declarators for cv-qualified member functions

The front end used to complain about cv-qualifiers on a member function
definition whose declarator was parenthesized (when that definition appeared
outside a class definition).  For example:

  struct S {
    void f() const;
  };
  void (S::f)() const {} // Used to trigger unwarranted diagnostic.

This is now fixed.

8/5/99   Conversions for operands of "?" operator as required by standard

The processing for the "?" operator in C++ mode now conforms more
exactly to the C++ standard (5.16).  The differences from the previous
processing are extremely minor.

8/4/99   Friend template declarations in local classes

A local class is not permitted to declare a friend template.  An error
is now issued for this case.

8/3/99   Spurious error in template function default argument

Even though default arguments were not being instantiated unless they
were used, certain errors would be diagnosed in the process of skipping
over a default argument during instantiation of a template function.
For example, an error would be issued on the following example complaining
that "T" is not a class or namespace name when instantiating "f(int)".
This has been fixed.

  template <class T> int f(T t = T::x);
  int n = f(2);

8/2/99   Host FLT_MAX with form ((float)3.40282347e+38)

One some systems, FLT_MAX is defined with a cast to float.  The code
in float_pt.c that converts FLT_MAX is now capable of dealing with that
form.  Note that this relates to the host definition of FLT_MAX as seen
while compiling the C source of the front end itself, which might be
different than the definition used when compiling user source code.

8/2/99   Abort on pointer-to-member constant when operator& is declared

An abort on a pointer-to-member constant of a type that has a user-declared
operator& has been corrected.

  struct X {
    void operator&();
  };
  struct Y {
    X x;
  };
  void f() {
    &Y::x;  // Abort here eliminated
  }

7/30/99  Microsoft compatibility: access checking in elaborated type specifiers

In Microsoft bug mode, access checking of qualified names in elaborated
type specifiers is suppressed.

  class A { class B {}; };
  struct C {
    friend class A::B;  // Accepted in Microsoft bugs mode
  };

7/30/99  C++-generating back end: Leading "::" on enum definition

The C++-generating back end incorrectly put a leading "::" on a
definition of an enum in a scope where a using-directive made a
namespace-scope definition of a like-named entity visible.
Now fixed.

  enum X {x1, x2, x3};  // Output had "enum ::X { x1, x2, x3 };"
  namespace N {
    enum X {y1, y2, y3};
  }
  using namespace N;

7/29/99  Microsoft compatibility: injected class name not found in most
         contexts

The Microsoft compiler does not find injected class names in many contexts.
In Microsoft bugs mode, an injected class name is only found as a component
of a qualified name (including the first component).

  struct A {
    struct C { static void f(){} };
  };
  struct C { int i[10]; };
  struct B : public A::C {
    static void f() {
      // The following uses A::C
      C::f();
      // But the following uses ::C
      printf("Sizeof C = %d\n", sizeof(C));
    }
  };

7/28/99  Microsoft compatibility: nonclass typedef does not begin qualifier

The Microsoft compiler does not consider a nonclass typedef as the start
of a qualified name.  We now accept this usage in Microsoft bugs mode.

  typedef unsigned int size_t;
  size_t f(int);
  struct A {
    friend size_t ::f(int);  // Accepted in Microsoft bugs mode
  };

7/27/99  Incorrect handling of reference to partial specialization

Certain references within the definition of a template that should refer
to a "nonreal" class were incorrectly treated as references to a partial
specialization.  This could result in spurious errors.  Now fixed.

  template <class T> struct A;
  template <class T> struct A<T*>;
  template <class T> struct B {
    A<T*> a;
  };

7/22/99  Compound literals

Compound literals, a C9X feature, are now accepted.  They look like a
cast whose source expression is a brace-enclosed initializer, e.g.,

  int *p = (int []){1, 2, 3}

The above creates an unnamed lvalue that is an array of three ints, and
initializes it with the indicated values.  p is initialized with the
address of the first element of the array.

This feature is off by default.  See COMPOUND_LITERAL_ENABLING_POSSIBLE,
DEFAULT_COMPOUND_LITERALS_ALLOWED, and the command-line options
--compound_literals and --no_compound_literals.

If COMPOUND_LITERAL_ENABLING_POSSIBLE is set to TRUE, some back end
changes will be required (unless you are using the C-generating
or C++-generating back end): compound literals are represented by
enk_temp_init expression nodes, which are not otherwise used in C IL
(IL CHANGE).

7/21/99  Allow template overloading when only return types differ

The front end now accepts the declaration of two function templates that only
differ in their return types.

  template<class T> void f();
  template<class T> bool f();  // Used to be an error.

7/21/99  Assertion failure with invalid friend template declaration syntax

The following invalid declaration no longer triggers an internal error in the
front end:

  struct S {
    template<class T> ::friend void f(); // illegal use of "::"
  };

7/20/99  Problem with template-dependent pointer-to-member nontype
         template parameters

In certain cases, template-dependent nontype template parameters of
pointer-to-member type were not compared properly.  This could result
in spurious errors.  This has been fixed.

  template<class T> struct A {
    template<int T::*f> struct B { 
      void g();
    };
  };
  template<class T> template<int T::*f> void A<T>::B<f>::g() {}

7/19/99  Operands with template type in template argument expressions

Some problems with dealing with operands of template-based type in
operations in template arguments have been corrected.

  template <int n> struct AA {
    int aa[n];
  };
  template <class T> struct A {
    AA<T::n + 3> a;  // Now accepted
  };
  struct B {
    static const int n = 5;
  };
  A<B> x;

7/19/99  Assertion failure with nested block-extern declarations that have
         internal linkage

Recent versions of the front end would fail when processing certain block-
extern declarations of entities that had previously been declared with
internal linkage in the surrounding namespace scope:

  static void f() {}
  void g() {
    extern void f();
    {
      extern void f(); // Used to trigger an assertion failure.
    }
  }

This is now fixed.

7/17/99  Folding of constant but unevaluated parts of "?" operations

Constant but unevaluated parts of "?" expressions were not correctly folded
to constant values.  As a consequence, something like

  const int i = (1?1:(1?1:0));

was not recognized as a constant expression.  Now fixed.

7/16/99  Ambiguity of conversion functions

The front end used to fail to select a user defined conversion function when
another conversion function was ambiguous through multiple inheritance:

  struct A {
    operator int();
    operator char*();
  };
  struct B {
    operator char*();
  };
  struct C: A, B {
    void f(C c) {
      int i = c; // Used to result in an error because the unrelated
    }            // conversion to char* is ambiguous.
  };

This is now fixed.

7/14/99  EH cleanup state problem

When the initialization of a destructible variable involves a temporary,
and the declaration is both preceded and followed by declarations of
destructible variables, and the declaration following involves copy
constructor elision, the cleanup state indicated between the time the
temporary is created and the time it is destroyed was incorrect (it
did not call for destruction of the preceding variable).

  struct A {
    A(int);
    A(const A&);
    ~A();
  };
  struct B {
    B();
    B(const B&);
    ~B();
  };
  A fa();
  B fb(const A&);
  int main () {
    A a(1);
    B b = fb(A(1));  // Cleanup state was wrong on temporary here;
                     // throw during call of fb would not destroy a
    A aa = fa();
  }

7/14/99  Option to not pack bit fields that straddle alignment boundaries

A new global variable, targ_user_control_of_struct_packing_affects_bit_fields,
has been added.  TARG_USER_CONTROL_OF_STRUCT_PACKING_AFFECTS_BIT_FIELDS is
defined in targ_def.h and selects the default value of the new variable.
When the variable is equal to FALSE the front end emulates the behavior of
compilers that do not apply packing directives to bit fields that straddle
alignment boundaries of their base types.  For example, assuming 32-bit
aligned int objects:

  #pragma pack (1)
  struct S {      //   Flag FALSE          Flag TRUE
    char c1;      //    this+0              this+0
    int i: 25;    //    this+4              this+1
    char c2;      //    this+8              this+5
  };              //   size = 9            size = 6
                  //   alignment 1         alignment 1

7/14/99  Integral promotion in IL on "!= 0" generated to normalize boolean
         controlling expression

In C mode, and in C++ mode when "bool" is not a keyword, the front end
generates a "!= 0" operation on top of a boolean controlling expression
to normalize it.  Now, when the expression is integral, it undergoes
the integral promotions before it is used as the operand of the "!= 0".

  /* C mode: */
  int f() {
    short j = 2;
    return !j;  /* j is promoted to int before comparison with zero */
  }

7/14/99  Diagnostic when redeclaring an entity already seen through a
         using declaration

The front end used to issue an unjustified diagnostic when redeclaring an
extern "C" function that had already been declared in that namespace scope
with a using declaration.

  namespace N { extern "C" void f(); }
  using N::f;
  extern "C" void f(); // Used to result in an error

This is now fixed.

7/14/99  Microsoft compatibility: ignore inline function qualifier

In Microsoft mode, using the keyword "inline" as a function qualifier only
yields a warning (instead of an error).  The qualifier is ignored.

  void f() inline; // Warning: inline function qualifier ignored

7/13/99  Extra position information on throw specifications

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the front end will now record the
source position range of an exception specification (from the start of the
"throw" token to the closing parenthesis) and the starting position of each
type specified (if any).  Previously, only the start of the "throw" token was
recorded.

7/13/99  Abort on redefinition of predefined macro

In Microsoft mode, a redefinition of a predefined macro that cannot be
redefined is ignored with a warning (it is an error in default mode).
Such a redefinition would, however, result in an abort when writing
an IL file.  Now fixed.

7/13/99  Spurious error on member of specialized member class template

A spurious error was issued on the definition of a member function of
a specialized member class template (e.g., on the declaration of
A<int>::B<Y>::mg below).  Now fixed.

  template <class T1> class A { 
    template <class T2> class B { void mf(); };       
  };       
  template <> template <class X> struct A<int>::B { void mg(); }; 
  template <> template <class Y> void A<int>::B<Y>::mg() {}; 

7/12/99  Microsoft compatibility: allow most operators to be static members

In Microsoft bugs mode, operators that can be declared in namespace scope can
also be declared as static members.  The resulting operators can only be
called using a qualified name.  For example:

  struct X {
    static void operator!(X const&) {} // Accepted in Microsoft bugs mode.
  };
  int main() {
    X::operator!(X()); // OK in Microsoft bugs mode.
    !X(); // Error.
  }

7/12/99  Cfront and Microsoft compatibility: implicit int return type and
         member functions whose name is found as a type name

In Microsoft and Cfront modes, the front end now accepts member function
declarations of the following form:

  typedef int I;
  struct X {
    I(); // Declares "int X::I()" in Microsoft and Cfront modes.
    I(int); // Error.
  };

The member function parameter list must be empty for such member declarations
to be accepted.

7/12/99  Microsoft compatibility: __BOOL_DEFINED predefined macro

In Microsoft mode, the macro __BOOL_DEFINED is predefined when bool
is a keyword.

7/12/99  Alignment pragma stack in templates

Manipulations of the pragma stack for field packing inside class template
definitions could occasionally lead to unwarranted error messages about
the stack being empty.  For example:

  #pragma pack (1)
  template<class T> struct X {
  #pragma pack (push)
    int i;
  #pragma pack (pop)
            //  ^  "error: empty pack alignment stack" when instantiated
  };
  X<char> x;

This is now fixed.

7/9/99   Correctly restore token positions after instantiating templates

Occasionally, the end position of an IL entry was set to the end position of a
template entity that was instantiated as part of the processing of the IL
entry.  For example,

  template <class T> struct Example { Example(T t1) {} };
  main () {
    // The end position of the following new-expression was set to the end
    // position of the constructor above.
    Example<int> *example = new Example<int>(1);
  }

This is now fixed.

7/9/99   Do not grant access to an nontemplate function when an instance is
         nominated by a friend declaration

Under certain circumstances the front end would ignore the fact that a friend
declaration nominated a template instance, thereby granting access to a
nontemplate function.  For example,

  template<int N> class C;
  template<int N> void f(C<N>&);
  template<int N> class C {
    friend void f<N>(C<N> &c);
    int x;
  };
  void f(C<42> &c) { // Ordinary (nontemplate) function in strict mode
    c.x = 42; // Error in strict mode (used to pass undiagnosed)
  }

This is now fixed.

7/8/99   #include followed by non-trivial macro expansion

A #include directive in which the file name is given by a non-trivial
macro expansion now works correctly:

  #define tmp2 stdio.h
  #define tmp1(hfile) <hfile>
  #include tmp1(tmp2)

Formerly, this worked only for the simplest form of macro expansion:

  #define tmp3 <stdio.h>
  #include tmp3

7/8/99   Microsoft compatibility: do not generate or allow constructor
         initializers for property fields

The front end used to allow property fields to be mentioned in constructor
initializer lists, and if they were omitted it generated them.  Either
situation resulted in an internal error during IL lowering.  Property fields
will now generate an error when they appear in constructor initializer lists,
and no implicit initializer is generated for them.

  struct A { A(int); };
  struct B {
    __declspec(property(get=GetName,put=PutName)) A prop;
    B();
    B(int);
  };
  B::B() {} // Fine (no implicit initializer for B::prop)
  B::B(int): prop(42) {} // Error: property name cannot appear here

7/8/99   --microsoft_bugs and --microsoft_version do not reset
         Microsoft 16/32 bit mode

Formerly, the --microsoft_bugs and --microsoft_version options implied
32-bit Microsoft mode (i.e., where "near" and "far" are not allowed).
This meant that "--microsoft_version=1000 --microsoft_16" would enable
16-bit Microsoft mode but "--microsoft_16 --microsoft_version=1000" would
not.  The --microsoft_bugs and --microsoft_version options no longer
affect whether 16 or 32 bit mode is used.

7/7/99   Correct macro for Embedded C++:  __embedded_cplusplus

In Embedded C++ mode, the macro __embedded_cplusplus is supposed to
be defined.  When we implemented the Embedded C++ option, we incorrectly
read that as __embeddedcplusplus.  Now fixed.

7/7/99   Spurious error on friend declaration in presence of using-directives

A friend declaration that uses an unqualified name with an explicit template
argument list in which the function name potentially involves a using-directive
lookup could result in a spurious lookup error.  This has been fixed.

  namespace N {
    template <class T> inline void f(T){}
    template <class T> class B {
      friend void f<T>(T);
    };
  }
  using namespace N;
  int main() {
    B<int> b;
    f(b);
  }

7/6/99   Designated initializers for aggregates

In C mode, the front end can now accept designators in aggregate initializers
when the configuration flag DESIGNATED_INITIALIZER_ENABLING_POSSIBLE is TRUE.
With the option --designators (which can be enabled by default with the
configuration flag DEFAULT_DESIGNATORS_ALLOWED) the front end will correctly
process the syntax proposed for the next revision of the C standard ("C9X").
In particular, initializers for fields of struct objects and subobjects can be
designated with syntax of the form ".field_name" and initializers for elements
of array objects and subobjects can be designated with syntax of the form
"[subscript]".  For example:

  struct X { int a, b, c[10]; };
  struct { struct X p, q; } s = { .q = { 3, 4, 5, 6 }, .q.c[0] = 42 };

This example also shows that designators allow a subobject to be initialized
multiple times: the last initializer's value is preserved (s.q.c[0] is set to
42, not 5), but side-effects of overridden initializers do take place.
The option --extended_designators (set DEFAULT_EXTENDED_DESIGNATORS_ALLOWED to
enable it by default) implies --designators and adds to that field designators
of the form "field_name:" (these should not be followed by a "=" or another
designator) and array range designators of the from "[i...j]".  Furthermore,
the "=" is made optional after array element and array range designators.
This allows for the following example (struct X as above):

  struct { struct X p, q, r[5]; } x = { p: { 7, 8 }, .q.c[2 ... 4] 78 };

When --microsoft is combined with designators, the designated subinitializers
may contain a dynamic component (e.g., a function call), but an array range
designator does not admit such a dynamic component in its subinitializer.

IL CHANGE: Designators are represented in the IL by ck_designator
constants.  The extended designator form "[i ... j]" is represented
by a ck_designator constant (indicating the first element) followed by
a ck_init_repeat constant that repeats the initializer constant the
right number of times.  When LOWER_DESIGNATED_INITIALIZERS is TRUE,
the IL for designated initializers is lowered to (mostly) standard C.
The exceptions are: (1) when a designator is used to initialize a
member of a union other than the first, a ck_designator constant will
be left in the lowered IL to indicate the member to be initialized;
(2) when an extended designator of the form "[i ... j]" is used, the
ck_init_repeat constant that appears in the unlowered IL is passed
through; and (3) when initialization skips over some elements of an
array, a ck_init_repeat constant is inserted to indicate zero
initialization for all the elements skipped over.  Note that this
lowering is done in C mode.

7/6/99   Diagnose referenced functions that are declared inside unnamed
         namespaces, but not defined

The front end now issues an error for the following example because a function
declared inside an unnamed namespace is referenced but not defined:

  namespace { void g(); } // Error: g is referenced but not defined
  int main() { g(); }

7/6/99   Extra source positions for "__except" and "__finally" tokens

In Microsoft mode, when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the source
positions associated with the "__except" and "__finally" tokens are now
recorded in a_microsoft_try_supplement (field except_or_finally_position).

7/2/99   Diagnosing missing initializers for empty const POD objects

By default, the front end used to warn about missing initializers on unnamed
empty const POD objects, but was silent in the case of named variables.  (In
strict mode, both cases are diagnosed with a discretionary error.)  This
inconsistency has been removed by no longer issuing the warning by default.

  struct X {};
  int main() {
    X const ncx; // No initializer warning by default
    new X const; // Used to warn by default (no longer)
  }

7/2/99   Abstract class status of template classes

The front end used to erroneously consider abstract certain classes generated
from class templates with dependent base classes.  For example:

  struct A {
    virtual void f() = 0;
  };
  template<class T> struct B: virtual A {
    void f() {}
  };
  template<class T> struct C: B<T>, virtual A {
    C<T> g(); // Used to claim return type is abstract
  };
  template struct C<void>;

This is now fixed.

7/2/99   Microsoft compatibility: constructor chosen over conversion function
         to do conversion

In Microsoft bugs mode, a constructor will be chosen over a conversion
function to do a conversion.

  struct _variant_t;
  struct _bstr_t {
    _bstr_t(const _bstr_t& s);
    _bstr_t(const _variant_t& var);
  };
  struct _variant_t {
    _variant_t();
    operator _bstr_t() const;  // Not chosen
  };
  int main() {
    _variant_t v;
    _bstr_t b = (_bstr_t) v;  // Not ambiguous in Microsoft bugs mode.
    return 0;
  }

7/2/99   Extra slash in temporary file name on DOS/Windows

On Microsoft operating systems, a temporary file name would contain
an extra slash if the temporary directory name was terminated by a
backslash.  This has been fixed.

7/2/99   Microsoft compatibility: ignore self qualification

In Microsoft bugs mode, the qualifier "C::" in the declarator of a member
or friend declaration that appears in the definition of class C is ignored.
In the case of a friend declaration, this may cause the friend entity to be
in namespace scope.  For example,

  struct S {
    void S::f(); // No warning with --microsoft_bugs
    friend void S::g(); // Warning (no error) with --microsoft_bugs
  };                    // and the friend is ::g (!)

7/2/99   Multiple carriage returns ignored before newline

When IGNORE_CARRIAGE_RETURN_IN_SOURCE is TRUE, all carriage returns that
appear immediately before the end of line are ignored.  Formerly, only
one such carriage return would be ignored.

This is important for Microsoft compatibility because the preprocessor
in MSVC++ expands a backslash at the end of a line that is not part of
a macro definition (and such a line appears in the atlcom.h header
file) into a line with a line terminator of carriage-return/
carriage-return/line-feed.

7/1/99   Variadic macros

Two variants of macro definitions that can be invoked with a variable number
of arguments are now supported.  These extensions can be enabled with the
options --variadic_macros and --extended_variadic_macros.

The option --variadic_macros enables variadic macros as proposed for C9X:

  #define D(fmt, ...) printf(fmt, __VA_ARGS__)
  /* The "..." matches an arbitrary positive number of macro arguments that
     can be referred to by __VA_ARGS__ (includes the separating commas). */
  D("%c%s\n", 'E', "DG"); /* Expands to "printf("%c%s\n", 'E', "DG");" */

The option --extended_variadic_macros adds to this the ability to name the
variadic parameter and a special meaning to the token pasting operator ("##"):
when it is followed by an empty variadic argument (named or not), the
preceding parameter or continuous sequence of nonwhitespace characters (not
part of a parameter) is erased.  For example:

  #define E(fmt, args...) printf(fmt , ## args)
  E("%c%s\n", 'E', "DG"); /* Expands to "printf("%c%s\n", 'E', "DG");" */
  E("EDG\n"); /* Expands to "printf("EDG\n" );" -- no extra comma. */

6/30/99  ## operator dropped in IL

When the token pasting operator ("##") was not followed by a macro parameter,
it did not appear in the textual string for the macro definition that appears
in the (optionally generated) IL a_macro entry.  For example,

  #define M(p) p##x
  /* "##" is followed by "x", which is not a macro parameter.  The a_macro
     entry for "M" used to have "px" as a string describing its definition. */

This is now fixed.

6/29/99  #line directives in preprocessed output in presence of line splices

In some cases involving line splices (lines continued using "\"), the
textual preprocessed output produced by the front end lost line
synchronization following output of a #line directive.  Now fixed.

  int i;
  #if 0






  #endif
  int \
  j;

6/29/99  Position on IL for initialization of extern inline local static

The IL assignment statement generated to do initialization of a local
static variable promoted out of an extern inline function by IL lowering
now (once again) has the position of the variable declaration.

6/29/99  Routine linkage difference on function pointer as template argument

When the implicit conversion between a pointer to C-linkage function
and a pointer to C++-linkage function is allowed, the conversion
is accepted when an overloaded function is passed as an argument to
a template.  However, the front end failed to insert an appropriate
generated cast on the argument, which caused deduction problems later.
Now fixed.

6/29/99  Template classes given external linkage in -tlocal mode

Formerly, in -tlocal mode, template classes were given internal linkage.
This would cause a given template class to have a distinct type_info
object in each translation unit in which it was used.  Template classes
are now given external linkage to prevent this from occurring.  The
members of the classes are still given internal linkage.

6/28/99  __MSDOS__ and __WIN32__ macros no longer defined

Formerly, the front end always defined __MSDOS__ and __WIN32__ to indicate
whether the front end was being built on DOS and/or Windows.  These macros
would be defined to zero when not building on DOS/Windows.  This created
problems for header files that tested these macros using an #ifdef.  The
front end has been changed to use macros named EDG_MSDOS and EDG_WIN32 to
avoid this problem.

Note that this should not require any changes in they way in which the
front end is built on these systems.  We still test macros such as
__MSDOS__ and _WIN32 to determine whether the front end is being
built on DOS/Windows; but now we set EDG_MSDOS and EDG_WIN32 instead
of setting __MSDOS__ and __WIN32__.

6/28/99  Friend declaration in a class template could refer to wrong namespace

The lookup of a friend declaration in a class template defined within
a namespace could, under certain circumstances, find a class declared
outside of the nearest enclosing namespace.  The lookup of friend
declarations is supposed to be limited to the nearest enclosing
namespace.  This has been fixed.

  struct C { void f(); };
  namespace A {
    template <class T> class B {
      friend class C;  // A::C, not ::C
      int i;
    };
  }
  A::B<int> x;
  void C::f() {
    x.i = 0;  // Failed to issue error
  }

6/28/99  Allow nonfatal diagnostic when declaring a file-scope static with
         incomplete type in C mode

The front end used to issue an unconditionally fatal error on the following
example:

  static int fi[]; /* Could not have "static" and "incomplete type" */
  static int fi[] = { 42, 43 };

In C mode, this is now accepted by default and reported as a discretionary
error in strict mode.

6/28/99  Specifying an invalid output file name as a PCH file

The front end will not permit a file name to be used as an output file
if its suffix suggests that is really a source file.  Although such files
could not be used as precompiled header files, when writing a PCH file,
the PCH mechanism would remove the old version of a PCH file before
checking whether the name is invalid.  This could result in the removal
of a source file.  The error is now issued earlier.

6/27/99  Linkage of inline template functions

If a function template was first declared without the inline specifier and
was later redeclared inline (either explicitly or by virtue of being
defined in a friend declaration in a class) any previously created instances
were incorrectly marked as having internal linkage.  They should only have
been so marked when the "extern inline" feature was disabled.  This has
been fixed.

6/25/99  C++-generating back end: field selection of static const member

The C++-generating back end now generates a comma operation for a field
selection of a static member where the member is const and has been replaced
by its constant value.

  struct X {static const int b = 2;};
  X x;
  int i = x.b;  // Was put out as "x.2", now put out as "x,2"

6/25/99  Microsoft compatibility: calling convention applied to constructors

The front end now accepts calling convention specifications on constructor
declarations. For example,

  struct S { __stdcall S(); };

6/25/99  IL lowering: promotion of class in function in class in namespace

The type promotion code in IL lowering did not work correctly for
a local class in a member function of a class that is the last type
in a namespace.  One possible consequence of this problem is an
abort in define_scope_class_typeinfo_vars.  Now fixed.

  namespace A {
    struct B {
      void* f () {
        struct C {
          virtual void g() {}
        };
        return new C;
      }
    };
  }

6/24/99  Microsoft compatibility: multiple initializers for scalars

In Microsoft bugs mode, multiple brace-enclosed initializers may be provided
for scalar variables.  The extraneous expressions must also be enclosed in
braces.  The rules that determine which value is preserved are somewhat arcane
but they match the behavior of the Microsoft compilers.  For example, the
following is accepted and prints "f(0)123".

  extern "C" int printf(char const*, ...);
  int f(int i) { printf("f(%d)", i); return i; }
  int g = { 1, { 2 } };
  int h = { f(0), { 2 } };
  int main() {
    int k = { 2, { 3 } };
    printf("%d%d%d", g, h, k);
  }

6/23/99  Universal character name support

Universal character names (e.g., \u0401) are now accepted in C++ mode in
identifiers, character literals, and string literals (they have always been
accepted in comments because they have no special meaning there).

The UCN escapes are translated to the appropriate internal value in
character and string literals.  In identifiers, on the other hand, they
are left as UCN escapes, e.g., an identifier with the name "x\u00d6"
will have a name string that contains the "\u" and the hexadecimal
value.  If IL lowering is used and REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING
is TRUE (which it is by default), the "\" in such names will be
rewritten by IL lowering to the single other character indicated
by UCN_ESCAPE_REWRITE_CHAR.  Note that this is not a complete
solution if the character to which the escape is changed is a
character that is valid in identifiers (as is the case with the
default setting of UCN_ESCAPE_REWRITE_CHAR to "_"), because it is
then possible (if unlikely) that a user might write an identifier
that would match an identifier with a rewritten UCN escape
character (for example, with a rewrite to "_", "x\u00d6" is
rewritten as "x_u00d6").  A better choice is a character accepted
by the linker but not valid as an identifier character in C.  If
there is no such character, a character like "_" will provide a
"good enough" implementation.

6/23/99  Microsoft compatibility: static member function overrides inherited
         virtual member function

In Microsoft bugs mode, the following is accepted and prints "bxd".

  extern "C" int printf(char const*, ...);
  struct B {
    virtual void f() { printf("b"); }
  };
  struct D: B {
    static void f() { printf("d"); } // Allow only with --microsoft_bugs
  };
  struct X: D {
    void f() { printf("x"); } // Virtual overrider of B::f
  };
  int main() {
    B *p1 = new D; p1->f(); // Calls B::f
    B *p2 = new X; p2->f(); // Calls X::f
    D *p3 = new X; p3->f(); // Calls D::f (nonvirtual)
  }

6/22/99  Extra source positions for explicit template specializations

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the source positions associated
with an explicit specialization of a template are now recorded properly.

6/22/99  Microsoft compatibility, C++-generating back end: explicit template
         specialization appearing within a class definition

In Microsoft mode and with TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
configured to TRUE, the source sequence representation of an explicit
template specialization that is a definition and that appears inside a
class definition was incorrect, and consequently the generated C++ was
also incorrect.  Now fixed.

  struct S {
    template <class T> void f(T) { }
    template<> void f(int) { }        // Permitted in Microsoft mode
  };

6/22/99  Abort on unprototyped definition in C mode

In C mode, the front end used to abort when an unprototyped function
declaration was followed by an unprototyped function definition with a
return type that is different from, but compatible with, that of the
first declaration.

  char (*f())[5];
  char (*f(c))[] char c; { return 0; }

This is now fixed.

6/21/99  Property field of incomplete array type

In Microsoft mode, the front end now allows a field marked as "property" to
be an array with unknown bound even when it is not the last field in a class
type.

  struct A {
    __declspec(property(get=p)) int p_[]; // OK in Microsoft mode
    int p();
    int size;
  };

6/21/99  C++-generating back end: "explicit" on constructors

The C++-generating back end now puts out the "explicit" keyword on the
declarations of explicit constructors.  In practice, the omission of the
keyword probably made little difference, because all conversions are
made explicit in the generated code.

6/19/99  Microsoft compatibility: in-class specializations only evaluated
         if the function is used

The front end supports the Microsoft compatibility feature of allowing
a member function template to be specialized within the class in which
the member is declared.  Formerly, the semantic analysis of the specialization
was done when the enclosing class definition was processed.  The Microsoft
compiler, however, does the semantic analysis when the specialization is
first used.  We now emulate the Microsoft behavior.

  template <class T> struct A {
    A(){}
    template <class X> A(X) {}
    template <> A(int) {
      B b;  // B undefined -- Microsoft only complains if this function is used
    }
  };
  A<int> ai;

6/18/99  Inappropriate diagnostics on parenthesized constructor and
         destructor declarators

The front end used to issue errors and warnings on this example:

  struct S {
    (S)();
    (~S)();
  };
  (S::S)() {}
  (S::~S)() {}

This is now fixed.

6/18/99  Warn on use of types without name linkage in entities with linkage

Warnings (or errors in strict mode) are now issued when an entity with
linkage is declared using a type with no name linkage. For example:

  typedef struct {} *ptr_to_nameless; // typedef type has no linkage
  void f(ptr_to_nameless); // warning: f has linkage, but its parameter
                           // type does not (used to be silent)

6/17/99  Support for oversized bit fields

In C++ a bit field may now be declared with a bit count that exceeds the
size of its underlying type.  The excess bits are ignored, and a warning
is issued.

In addition, the configuration variable TARG_MAX_BIT_FIELD_SIZE has been
removed; the maximum number of bits a bit field may have is now simply a
function of its type.  With this change back ends may now have to deal
with longer bit fields than before -- e.g., if TARG_MAX_BIT_FIELD_SIZE had
been configured to the number of bits in an int and if "long long" is
allowed or sizeof(long) > sizeof(int).

6/17/99  operator void() is allowed

An error is no longer issued when operator void() is declared (in keeping
with a change to 12.3.2 paragraph 1); instead, a warning is put out that
the operator will not be used in implicit or explicit conversions.

6/17/99  Separate configuration option for nonconst call anachronism

The anachronism of calling a nonconst member function on a const
object, allowed in cfront 2.1 mode and Microsoft mode for versions
less than 1000, is now controlled by the variable
allow_nonconst_call_anachronism and the macro
DEFAULT_ALLOW_NONCONST_CALL_ANACHRONISM.

6/16/99  Function-try-blocks implemented

Function-try-blocks -- try/catch statements surrounding the entire
body of a constructor, destructor, or function -- are now implemented.

  struct A : public B {
    A(int i) try : B(i) {
      ...
    } catch (...) {
      ...
    }
  };

6/15/99  Minimal inlining: no temporaries for pointer-to-member-function
         constant arguments

Minimal inlining has been improved so that pointer-to-member-function
constants (which are represented as structs after lowering) are considered
constant arguments and can therefore be used directly in place of the
corresponding parameter within the inlined function call (no copy to a
temporary is needed).

6/14/99  Abort in default argument expression processing on use of
         field selection for template static member function

Calling a static member function of a class template by means of a field
selection, in a way that requires instantiation of a default argument,
caused an abort.  Now fixed.

  template <class T> struct A {
    static void f(T i = 0);
  };
  A<int> a;
  int main () {
    a.f();  // Caused abort on default argument processing
  }

6/14/99  Classes always contain a copy assignment operator

Formerly, not all classes were considered to have copy assignment
operators.  An implicit declaration of a copy assignment operator
was only created for classes that could not be copied with a bitwise
copy, or for classes with other (non-copy) assignment operators.  The
standard specifies that all classes have copy assignment operators, so
the front end now creates an implicit declaration for the copy
assignment operator if no user-declared copy assignment operator
exists.

6/11/99  Abort on double block-scope declaration of a predeclared function

The front end aborted compilation upon encountering two declarations of a
predeclared (nonmember) function in the same block scope:

  void f() {
    extern void operator delete(void*);
    extern void operator delete(void*); // Used to abort here
  }

This is now fixed and the fix ensures that the "compiler_generated" flag
in "a_routine" entries will be cleared if a declaration for the associated
routine was seen in the source.  Hence this bit should not be used to
determine whether a function is intrinsic since, presumably, a declaration
of an intrinsic in the source does not make that function nonintrinsic.

6/10/99   Abort on use of a template parameter in a pointer-to-member type

The front end did not correctly handle pointer-to-member types in which
the class type is actually a template parameter type.  This could result
in an abort or other undefined behavior.  Now fixed.

  template <class T> struct A {
    void f(int T :: *);
  };

6/9/99   Obsolete nonstandard destructor diagnostic eliminated

Because of a Working Paper error, the following usage was not permitted by
an earlier version of the Working Paper (the issue being the scope in which
a qualified destructor reference is looked up).  This usage was accepted in
default mode, but a diagnostic was issued in strict mode.  This usage is now
permitted by the standard and is accepted in all modes.

  namespace N {
    struct B { };
    typedef B X;
  }
  int main() {
    N::X* ab = new N::X;
    ab->N::X::~X();
  }

6/9/99   Including header files without specifying a suffix

While the front end has always permitted a file name without a suffix
to be used as a header file name, it now permits a suffix to be
implicitly appended to such a name when searching for the include
file.  This permits, for example, a header file to named "new.h" to be
included with the directive "#include <new>".

A new configuration parameter named DEFAULT_INCLUDE_FILE_SUFFIX_LIST
provides the default list of suffixes to be used.  This list can be
overridden with the --incl_suffixes command-line option.  The suffix
list must include the null suffix if the inclusion of files without
suffixes is still to be permitted.

6/7/99   Catastrophic error when accessing misdeclared functions (C mode)

In C mode, accessing a function that had previously been declared with
conflicting types in block-scope could lead to a catastrophic error:

  void f1() { extern short g(); }
  void f2() { extern int g(); /* Conflicts with previous declaration. */ }
  void f3() {
    g(); /* Used to result in a catastrophic error. */
  }

This is now fixed.

6/7/99   Symbols for predeclared new[] and delete[]

Symbols are no longer created for predeclared new[] and delete[] if global
variable array_new_and_delete_enabled is FALSE (whether because it is
turned off by default or because the front end is invoked with command
line option --no_array_new_and_delete).

6/7/99   Improper logical right shift of negative value

When TARG_RIGHT_SHIFT_IS_ARITHMETIC is TRUE, a right shift of a negative
value smaller than the size of an_integer_value did not work properly; it
failed to ignore the high order sign bits included in an_integer_value that
were not part of the type on which the shift was done.  Now fixed.

6/7/99   Extra source positions for block-extern redeclaration

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the source positions associated
with a nonmember function declared in its own scope and then redeclared in
a local scope are now recorded properly.

  void f(int);
  void g() {
    extern void f(int);    // decl_pos_info is now updated correctly
  }

6/4/99   Checking of elaborated type-specifiers in class-scope

The following example used to incorrectly trigger a diagnostic about
redeclaring a nested type with different accessibility:

  class A {
    struct N {
      int mem;
    };
  public:
   struct N *foo(); // No longer a diagnostic here
  };

This is now fixed by recognizing that an elaborated type-specifier for
a class type that is found by elaborated lookup, and which does not
introduce a definition or a declaration of the form
    <class-key> <name>;
is not in fact a redeclaration (standard par. 3.4.4).

6/3/99   Default template arguments on class template member declarations

A default template argument can only be specified on the declaration of
a class template, not on a member of the template.  A diagnostic is now
issued for such cases.

  template <class T> struct A {
    void f();
  };
  template <class T = int> void A<T>::f(){}  // error now issued

5/25/99  Standard conversion after user-defined conversion on non-direct
         reference binding

In the analysis in overload resolution of an argument of a call passed
to a reference-to-const parameter, a standard conversion is now allowed
after a user-defined conversion.  [Patch sent out 5/27/99.]

5/25/99  near/far support: no warning on near/far function in C mode

The following example got an incorrect warning about meaningless type
qualifiers when compiled in C mode with near/far enabled.  Now fixed.

  void far foo() {}

5/25/99  Partially lowered EH: keeping body of destructor of thrown type

When IL lowering does partial lowering of exception handling, and
"throw" expression nodes are preserved in the IL, if a throw supplement
refers to a destructor the destructor body should be considered needed
and not eliminated when removing unneeded entities.  Unfortunately,
its definition was not marked as needed, and if it was not otherwise
required the body was removed.  Now fixed.

5/21/99  C++ generating back end: suppression of "this->" on function calls

A change made previously to suppress "this->" on some member function
calls (see Changes entry of 7/10/97), to get around a bug in MSVC++ 4.2,
turns out to cause some other problems.  Since the bug has been fixed
in MSVC++ 5.0 and beyond, this "optimization" is now done only for
4.2 compatibility, i.e., when microsoft_version is 1000.  [Patch sent
out 5/27/99.]

5/21/99  IL lowering: zeroing of array on array new

In the code generated for an array new with an initializer of "()" (to
indicate zeroing), the code generated by IL lowering zeroed only the
first element of the array.  Now the full array is set to zero.
[Patch sent out 5/27/99.]

  union u { double d; char c; };
  int main() {
    u *pu = new u[100]();
  }

5/20/99  Compilation errors with NEAR_AND_FAR_ALLOWED

Some compilation errors appeared when MICROSOFT_EXTENSIONS_ALLOWED was set
to FALSE but NEAR_AND_FAR_ALLOWED or DECL_MODIFIERS_IN_USE was set to TRUE.
These compilation errors were introduced by the patch sent out on
3/19/99.

5/14/99  C++-generating back end: string passed to template reference param

The C++-generating back end now adds a cast to a string that is bound to
a reference to ensure that, when the reference is a parameter of a
template, the string is used as an address and not as an array of
characters.

  template<class _P>
  inline const _P& max(const _P& p1, const _P& p2) { return p1; }
  void foo() {
    max((char*)"short", (char*)"longer");  // Casts formerly dropped
  }

5/14/99  C++-generating back end: avoid extern "C" inline

The C++-generating back end now avoids putting out

  extern "C" inline

on the definition of a function, by using a brace-enclosed linkage
specification, e.g.,

  extern "C" { inline void foo() {} }

This avoids problems with some compilers (including compilers based
on versions of our front end before 2.42) that give an error on the
combination of a linkage specification and "inline".

5/14/99  Improvement on FORCE_VARIABLE_DEFINITION_VIA_ZEROING

The configuration option FORCE_VARIABLE_DEFINITION_VIA_ZEROING (see
Changes entry of 10/16/97) now applies also to cases where IL lowering
generates code for the initialization of a variable, e.g., with
FORCE_VARIABLE_DEFINITION_VIA_ZEROING set to FALSE the variable in
the following will not be explicitly initialized to zero:

  struct A {
    A() {}
    char* p;
  } a;

5/14/99  Diagnostic on invalid nontype template parameter declarations

The standard does not permit a class type to be used as the type
of a nontype parameter.  A diagnostic is now issued for such usage.

5/13/99  Microsoft compatibility: allow __declspec on explicit specialization
         of template

In Microsoft compatibility mode, an error is no longer issued when a
__declspec attribute appears on an explicit specialization of a template.

5/10/99  Microsoft compatibility: dllimport and function definition

In Microsoft compatibility mode, a function now can be initially
declared with __declspec(dllimport) and subsequently defined with
__declspec(dllexport).

  __declspec(dllimport) void f();
  __declspec(dllexport) void f() { ... }    // Error is no longer issued

In general, conflicts between dllimport and dllexport specifications
are now reported as warnings rather than discretionary errors.

5/6/99   C++-generating back end: improvements in hidden name table support

Some changes were made that, when RECORD_HIDDEN_NAMES_IN_IL is configured
to TRUE, reduce overhead incurred in building the hidden name table,
which is used by the C++-generating back end.  The principal effect of
the change was to eliminate a number of superfluous id-lookup calls;
maintainability improvements were also implemented.

5/5/99   Exception specifications missing on delete routines

The new.h file was missing exception specifications for the placement
delete routines.  In addition, the runtime routines for all of the
delete operators were missing exception specifications.

5/3/99   Implicitly declared delete functions missing from new.h

The new.h header file in the include_src directory was missing the
implicitly declared delete and array delete routines.  Now fixed.

4/28/99  C++-generating back end: missing qualifier on references hidden
         by base class members

When a name from an outer scope was referenced within the context of a
class and a base class contained an intervening declaration with the same
name, the qualifier was sometimes omitted by the C++-generating back end:

  struct I { };
  struct V {
    struct I { unsigned int* p; };
    struct C : public ::I {         // ::I hides V::I
      void f(V::I& x) { x.p; }
    };
  }; 

The declaration of V::C::f in the generated C++ was incorrect -- the
qualifier was omitted in the function parameter type.  Now fixed.

4/27/99  Linux version no longer includes sys/dirent.h

Newer versions of Linux no longer provide a sys/dirent.h file, so this
file is no longer included by host_envir.c when building on Linux.

4/27/99  Missing error on redeclaration of template name

In strict ANSI mode, no error was issued when a function template name
clashed with the name of a class or enumeration declared in the same
scope.  Now fixed.  (In default mode the old behavior continues.)

  template <class T> void X() { ... };
  class X { ... };                      // Error now in strict mode; no
                                        //   diagnostic in default mode

4/27/99  Return type of "main"

In C++ mode a diagnostic is now issued if the return type of function main
is anything but "int".  A discretionary error is issued in strict ANSI
mode, a warning otherwise.

4/26/99  C++-generating back end: using-directive and namespace qualifier

When a using-directive resulted in name overloading, the namespace
qualifier that would resolve the ambiguity was sometimes omitted by the
C++-generating back end.  Now fixed.

  namespace N {
    class X { };
  }
  using namespace N;
  class X { };
  ::X x;              // Formerly put out as "X x;", which is ambiguous

4/24/99  C++-generating back end: comma lists, typedef for unnamed class

The C++-generating back end's approach for deciding whether to put out
two variable declarations as a comma list would in some cases decide
to put out a comma list when one was not required.  This was correct
output, but not what was intended.  The cases where this was done
involved a typedef for an unnamed class or enum.  Now fixed.

  typedef struct {} X;
  void test() {
    X* xp1;
    X* xp2;  // Formerly put out as part of comma list
  }

4/22/99  C++-generating back end: abort building hidden name table

With support for class name injection introduced in version 2.41, an
internal error could occur with use of the C++-generating back end (more
specifically, with IL_SHOULD_BE_WRITTEN_TO_FILE and
RECORD_HIDDEN_NAMES_IN_IL both configured to TRUE) when a class
declaration at file scope had the same name as a local class.  Now fixed.

  void f() {
    struct S { };
  }
  struct S { };

4/21/99  Constructor names with invalid template argument lists

When a constructor is declared with an explicit template argument list,
the argument list must match the parameter list of the class in order
for the constructor declaration to be valid.  Formerly, the front end
did not consider invalid constructor declaration to be constructors
(e.g., the example below was considered to declare "I" as a nonstatic
data member).  This could result in an internal error during an
instantiation of the class.  Now, the declaration in question is
diagnosed as an invalid constructor declaration.

  typedef int I;
  template <class T1, class T2> struct A {
    A();
    A<T2,T1>(I); 
  };

4/21/99  Last line of raw listing file written on catastrophic error

On a catastrophic error, the last source line is now written out
to the raw listing file.

4/21/99  C++-generating back end: parentheses around "new" if needed
         to avoid ambiguity

The C++-generating back end now puts parentheses around some "new"
operations if needed to avoid ambiguity, e.g., "(new int)[0]" now
comes out that way instead of the incorrect "new int[0]".

Also, new operations on pointer or multi-level array types are now
put out in the unparenthesized form, e.g., "new int *" rather
than "new (int *)".

4/21/99  C++-generating back end: avoid accidental digraph on template
         argument list

The C++-generating back end now puts out a space following the opening
"<" of a template argument list to avoid a possible digraph ("<:",
meaning "[") if the first template argument uses a "::" global qualifier,
e.g., the output is now "A< ::x >" rather than "A<::x >".

4/21/99  Microsoft compatibility: storage class of local variable declared
         with __declspec(dllimport)

The storage class of a local variable declared with __declspec(dllimport)
is now set to "extern" rather than "auto".

  void f() {
    __declspec(dllimport) int x;      // storage class is now "extern"
  }

4/21/99  C++-generating back end: invalid qualifier on namespace member
         declaration

The C++-generating back end would sometimes put out a qualifier on a
namespace member when it was not only unnecessary but also invalid.
Now fixed.  For example, "N::" was incorrectly included in the
declaration of N::f(int) in the following:

  namespace N { };
  using namespace N;
  namespace N {
    void f(int) { }
    void f(double) { }
  }

4/20/99  C++-generating back end: missing qualifier on reference to
         class template instance

The C++-generating back end would sometimes fail to include a qualifier
on a reference to a template instance when the template name itself was
hidden by an intervening declaration.  Now fixed.  For example, "N::"
was omitted from the base specifier declaration in the following:

  namespace N {
    template<class T> struct iterator { };
    struct vector_bool {
      struct iterator;
      struct iterator : N::iterator<vector_bool> { };
    };
  }

4/20/99  Suppressing warnings from system include files

The front end now suppresses warnings from "system" include files.  A
system include file is a file found using a search path entry
associated with a system include directory.  The default include
directory specified by the USR_INCLUDE environment variable is
considered a system include directory as are any directories specified
using the new --sys_include option.  Include directories specified with
the -I or --include_directory option are not considered system include
directories.

4/19/99  Minimal inlining: argument passing tweaks

The decision to use a temporary to pass an argument expression to
the body of an inline function has been refined in a few ways:

 -- In determining whether an argument expression is invariant,
    local variables whose addresses are not taken are considered
    invariant as long as the argument expressions cause no side
    effects, and other variables are considered invariant if
    both the argument expressions and the called function body have
    no side effects.
 -- In determining whether the body of a function has side effects, a
    return statement that returns an expression that is an assignment
    whose destination expression has no side effects is not considered
    to have any side effects.  (The assignment is the last thing done
    before the return, and therefore can have no side effects on the
    values of argument expressions.)

4/19/99  Spurious error on declaration of conversion operator in class
         with nonreal base class in Microsoft mode

A bug was introduced in 2.41 that caused a spurious redeclaration error
to be issued when a conversion operator was declared in a class template
with a template-dependent base class.  This has been fixed.  [Patch sent
out 5/27/99.]

  template<class T> struct A : T {
    operator int();
  };

4/19/99  Partial specialization problem when the current partial specialization
         is referenced using a template argument list

A bug was introduced in 2.41 that caused a spurious error when, within
a partial specialization, the current template was referenced using
the template argument list associated with the partial specialization.
This has been fixed.  [Patch sent out 5/27/99.]

  template <class T1, class T2> struct A { };
  template <class T> struct A<int, T> {
    A<int, T>();
  };

4/18/99  Performance problem with name mangling introduced in 2.41

The reworking of lower_name.c in 2.41 introduced a performance
problem with some complicated template names.  In some extreme
cases, programs that formerly were compiled in a fraction of a second
instead took thousands of seconds.  Fixed.  [Patch sent out 5/27/99.]

4/16/99  Source sequence lists: internal error in default argument fixup

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was TRUE, an
internal error could appear during default argument processing of member
functions of a compiler-generated class template specialization; now
fixed.  A complex set of conditions was required to expose the bug, e.g.:

  namespace N {
    template <class T> struct A { void f(int=0); };
    template <class T> struct B { T t; };
    template <class T> struct C { inline ~C(); };
    C<A<char> > x;
    template <class T> inline C<T>::~C() { B<T> b; }
  }
  namespace M {
    N::C<N::A<char> > y;    // Internal error fixed
  }

4/15/99  IL lowering: internal error in lower_il.c (promotion of local types)

A problem in IL lowering could cause an internal error in lower_il.c
on processing of local types promoted out of a member function.  The test
case involves templates and is obscure and convoluted.

4/15/99  Unlowered pointer-to-member type remains in catch parameter

In versions configured without IL file write/read, a catch parameter
of type pointer to member (where the pointer to member was written in
the parameter type, and not supplied by a typedef) remained a
pointer-to-member after IL lowering in some cases.  Now fixed.
[Patch sent out 5/27/99.]

  struct A {
    int d;
    void f() {}
  };
  void TestA() throw( void (A::*)(), int A::* ) {
    {
      int caught = 0;
      try {
      } catch( void (A::* p)() ) {  // Type remained a pointer-to-member
        caught |= 1;
      }
    }
  }

4/14/99  Linkage specification with "inline"

An inline specifier is now permitted on a function declared with a linkage
specification.

  extern "C" inline void f() { ... }      // error is no longer issued

4/14/99  Spurious errors on asm functions

Version 2.41 introduced a bug whereby the storage class on asm functions
was set incorrectly, resulting in spurious errors.  Now fixed.  (This
problem appeared only if ASM_FUNCTION_ALLOWED was configured to TRUE.)

4/13/99  Statement stack address used after possible reallocation of stack

A bug in switch_statement has been fixed where a statement stack address
is taken and used later after some code has been executed that could cause
the stack to be reallocated.  This could result in an abort when the address
is used after the reallocation.  Now fixed.  [Patch sent out 5/27/99.]

4/9/99   Implicit declaration of copy assignment operator in presence of
         using declaration

The implicit declaration of a copy assignment operator is no longer
suppressed by a using declaration with a similar signature.

  struct D;
  struct B {
    D& operator=(D&);
  };
  struct D : public B {
    using B::operator=;       // no longer impedes implicit declaration of
  };                          //   D::operator=(const D&)

4/7/99   Initialization of class members and array elements of aggregate
         class type

Initializers appearing in a brace-enclosed list that apply to class
aggregate subobjects are now handled correctly.  Here's an example from the
C++ standard (8.5.1) that we now get right.

  struct A {
    int i;
    operator int();
  } a;
  struct B {
    A a1, a2;
    int z;
  } b = { 4, a, a };    // b.a1.i = 4, b.a2 = a, b.z = a.operator int()

4/4/99   C++-generating back end: initial explicit declaration of a
         predeclared type

When the initial explicit declaration of a predeclared type (e.g., class
type_info, struct _GUID) was not a definition, the C++-generating back end
was sometimes putting out invalid code.  Now fixed.

4/3/99   Microsoft compatibility: preprocessing problem fixed

A preprocessing problem in Microsoft mode, introduced in 2.41 (see
Changes entry of 2/25/99), has been corrected.  The symptom was
a macro name being expanded recursively (i.e., within its own
expansion).  [Patch sent out 5/27/99.]

  #define new dbg_new
  #define dbg_new new(x, y)
  #define MACRO new int;
  int *x = MACRO    // failed with new(x,y)(x,y) int

4/2/99   Microsoft compatibility: incompatible extern "C" declarations
         in different namespaces

In Microsoft mode incompatible extern "C" function declarations are now
accepted with a warning if they appear in different namespaces:

  namespace N {
    extern "C" int f();
  }
  extern "C" int f(int);       // No compiler error in Microsoft mode

4/1/99   purify_discard_memory eliminated

All calls of purify_discard_memory (in c_gen_be.c and cp_gen_be.c), and
the macro itself, have been eliminated.  The macro was supposed to
eliminate some spurious memory leak diagnostics from Purify, but in fact
the pointers passed in were sometimes things that shouldn't be freed,
which caused larger problems.  All things considered, eliminating
the trickery and accepting the diagnostic from Purify seems like
the best course of action.

4/1/99   IL lowering problem with aggregate initialization and return value
         optimization

In a case like the following, which involves a partially-constant
aggregate initialization of a variable that is eliminated by the
return value optimization, IL lowering got an internal error in
lower_init.c (lower_dynamic_init).  Now fixed.  [Patch sent out 5/27/99.]

  struct A {
    A(int);
    A(const A&);
  };
  struct S {
    int n;
    A   a;
  };
  S f() {
    S rv = {0, 0};
    return rv;
  }

3/31/99  C-generating back end: address of lvalue cast in pcc mode

The C-generating back end can now handle a case where the address of
an lvalue cast is taken in pcc mode.  Formerly, an example like the
following produced an internal error in dump_expr.  A similar change
was also made in the C++-generating back end.

  void func(void) {
    char *cptr;
    f(&(char *)cptr);
  }

3/31/99  Overload resolution will not consider a template conversion function
         for a conversion to an abstract class type

Overload resolution will no longer consider a template conversion
function for a conversion to an abstract class type.  A conversion
function is not allowed to return an abstract class type, so instantiating
such a thing causes an error.  This change operates before type
deduction is attempted on the template, and therefore avoids an error
on the partial instantiation of a conversion function that turns out
later not to be the function selected by overload resolution.

3/31/99  --preinclude and using precompiled header file

When a compilation specified a --preinclude file, and also used a
previously-generated precompiled header (PCH) file, the line numbers
in the IL were wrong, which could cause various problems including
internal errors.  Now fixed.  [Patch sent out 5/27/99.]

3/31/99  Internal error in add_dyn_init_cleanup: no temps

A bug in setting the overlaps_temps_in_inner_lifetime flag caused an
internal error in add_dyn_init_cleanup on processing an array new
in Microsoft mode with exceptions enabled.  This showed up only
in versions with NEW_CAN_BE_FOLDED_INTO_CTOR set to FALSE.

3/31/99  Microsoft compatibility: class name injection enabled in
         Microsoft mode

Class name injection is now enabled in Microsoft mode.

3/30/99  Spurious error when type_info appears in elaborated type specifier
         following its definition

With PRAGMA_DEFINE_TYPE_INFO_IS_REQUIRED configured to TRUE, a spurious
error might be issued on an elaborated type specifier that refers to
class type_info after the definition has appeared.  Now fixed.

  namespace std {
    #pragma define_type_info
    class type_info { };
    class type_info *tip;  // Spurious error was issued here
  }

3/30/99  Microsoft compatibility: binding of reference to _GUID to name of
         predeclared type

In Microsoft mode an elaborated type specifier referring to _GUID did
not always bind to the name of the predeclared type (e.g., when it
appeared in a function prototype).  Now fixed.

  struct __declspec(uuid("447047e7-c64d-11d2-b57c-00105aa4d93d")) A { };
  void f(const struct _GUID &);
  main() {
    f(__uuidof(A));                         // Spurious error eliminated
  }

3/30/99  Abort with type_info declared in unnamed namespace

An abort would occur if a class named "type_info" were declared in an
unnamed namespace.  Now fixed.

3/26/99  Microsoft compatibility: bit-field allocation

With TARG_MICROSOFT_BIT_FIELD_ALLOCATION configured to TRUE and
TARG_BIT_FIELD_CONTAINER_SIZE to -1 and with command line option
--pack=1 or --pack=2, the size of a struct was computed incorrectly
when the last field was a bit field.  Here's an example:

  struct C { int a; int b:1; int c; int d:1; };
  struct E { unsigned char a; unsigned int b:1; };

                  with pack=1:          with pack=2:
                 MSVC++    EDG         MSVC++    EDG
  sizeof(C)       16       13           16       14
  sizeof(E)        5        2            6        4

The problem was that padding was not being provided for the bit-field
container.  Now fixed.

3/25/99  Exception specification on function parameter

An error is now issued if an exception specification appears on a function
parameter declaration within a typedef declaration.

  typedef int FTP(int (*)() throw());       // error

3/24/99  Added "!= 0" expression nodes marked as compiler-generated

Comparisons against zero added to normalize a boolean test are now
marked as compiler generated (i.e., the compiler_generated field
in the expression node is TRUE).  This is done only when bool is
not a keyword.  Comparisons added by IL lowering are not marked.

  int i;
  if (i) {}  // IL is "if (i != 0) {}"; "!=" node is marked as generated

3/24/99  Abort eliminated in full_specialization

If an explicit function template specification that provided a
definition was declared with a typedef, no error was issued and an
abort would occur in full_specialization.  Now fixed.

  template <class T> void f (T) { }
  typedef void F(int);
  template <> F f { }            // error now issued and abort eliminated

When compiling with --guiding_decls, the same abort would occur if a
guiding declaration was first declared with a typedef type and later
defined with the template<> syntax.  Now fixed.

  template <class T> void f (T) { }
  typedef void F(int); 
  F f;                           // guiding declaration (nonstandard)
  template<> void f(int) { }     // abort fixed

3/23/99  Microsoft compatibility: p->k allowed in constant expression

In Microsoft mode, an expression of the form p->k, where k is a member
constant, is now allowed in a constant expression.  The form this->k
is also allowed.

  struct A {
    enum { i = 1 };
  } *p;
  int main () {
    switch (1) {
      case p->i: break;
    }
    return 0;
  }

3/23/99  Unqualified name in nonmember using-declaration

An option has been added to permit an unqualified name to be accepted
in a nonmember using-declaration.  This feature is controlled by
DEFAULT_NONSTANDARD_USING_DECL_ALLOWED (FALSE in the release) and by
the --[no_]nonstd_using_decl command-line option.

  typedef int TYPE;
  namespace N {
    using TYPE; // should be ::TYPE
  }

3/22/99  C-generating back end: source position for generated code at the
         beginning of a block

On generated code at the beginning of a block, the C-generating back end
now puts out a #line directive indicating the line of the opening "{"
of the block.  This should produce more reasonable behavior when stepping
through that code with a debugger.

3/22/99  Microsoft compatibility: incomplete type allowed in explicit
         instantiation directive

In Microsoft mode, an incomplete type is permitted in an explicit
instantiation directive.  A warning is issued.

  template <class T> struct A;
  template class A<int>;

3/22/99  C++-generating back end: location of generated instance
         specializations

In versions using the C++-generating back end in which generated
instances of templates are put out as specializations, code is now
put out around the specializations to adjust the current namespace
state.  This allows the specializations to be put out in contexts
where formerly they could not be, and that produces compilable output
in some complicated cases that formerly failed.

3/18/99  Abort eliminated in types_of_decl_and_using_decl_conflict

An abort could occur when a function was redeclared after a
using-declaration had extended the overload set to which it belonged.
Now fixed.  [Patch sent out 5/27/99.]  For example (on some system
but not on others):

  void f(char);
  namespace B {
    void f(int);
    void f(long);
  }
  using B::f;
  void f(char);               // Abort fixed

3/18/99  Internal error in decl_routine eliminated

An internal error could occur in decl_routine when the following was
compiled with --guiding_decls; the declaration of f(int) was erroneously
viewed as a guiding declaration for template N::f.  Now fixed.
[Patch sent out 5/27/99.]

  namespace N {
    template <class T> void f(T);
  }
  using N::f;
  template <class T> void f(T*);
  void f(int);                            // Abort fixed

3/18/99  lower_dynamic_cast did not work right for ABI versions < 241

lower_dynamic_cast made reference to an uninitialized local variable
when the front end is built with an ABI version < 241.  Now fixed.
[Patch sent out 3/19/99.]

3/18/99  Internal error in composite_array_type eliminated

A template redeclaration could trigger an internal error in
composite_array_type if the type involved an array with a dimension
specified by a non-type template parameter.  Now fixed.

  template <unsigned int N> void f(int(&)[N]);
  template <unsigned int N> void f(int(&)[N]) { }      // Abort fixed

3/18/99  Name mangling for uses of partial specialization classes

Name mangling now includes the template argument list for a partial
specialization only in parent name references.  Formerly, the
partial specialization arguments were included in all references to
the class, which was inappropriate.  In particular, it meant that
mangled names could be different depending on whether the class was
complete or not.

  template <class T> struct A {};
  template <class T> struct A<T*> {};
  void f(A<int*>*){}
  #ifdef COMPLETE
  A<int*> a;
  #endif

This produced different mangled names depending on whether COMPLETE
was defined.  Now, the same mangled name is produced in both cases.

Note that this is an ABI CHANGE.  It has been rolled into 2.41,
because a patch will be sent to all customers, rather than being
considered part of 2.42.  [Patch sent out 3/19/99.]

3/17/99  name field in typeinfo now const

The "name" field in the typeinfo structure now has "const char *" type.
The "const" has been added to make the field match the type of string
literals, which are now const in some modes (see Changes entry of 1/21/99).
[Patch sent out 3/19/99.]

3/17/99  Incorrect union variant used in too_many_unused_instantiations

The incorrect variant of a union could be accessed by the routine
too_many_unused_instantiations in certain cases.  This could cause the
front end to fail to instantiate a template static data member.  This
has been fixed.  [Patch sent out 3/19/99.]

3/16/99  Microsoft compatibility: loss of __declspec attributes on class
         redeclaration

In Microsoft compatibility mode __declspec attributes were lost on a class
redeclaration in certain cases.  Now fixed.  [Patch sent out 3/19/99.]

  class __declspec(dllimport) A { };
  class A;                              // "dllimport" no longer lost

In addition, the front end now puts out a diagnostic when the __declspec
attributes on a class declaration are incompatible with those of a
previous declaration:

  class __declspec(dllexport) A;
  class __declspec(dllimport) A { };    // diagnostic is now issued

3/16/99  printf argument checking and const string literals

The argument checking done for printf (when #pragma __printf_args is
used) was not updated when string literals were made const in C++.
As a consequence, a remark was issued when a string literal (of
type const char *) was passed for a "%s" printf specifier (which
expects a char *).  Now fixed.  [Patch sent out 3/19/99.]

  #pragma __printf_args
  extern "C" int printf(const char *, ...);
  int main() {
    printf("%s", "hello\n");
  }

3/16/99  Abort in find_base_class_of eliminated

An abort in find_base_class_of has been eliminated.  This abort came
up when a template constructor whose first parameter is the same type
as the class was called with a non-class first argument.  [Patch sent
out 3/19/99.]

  struct A {
    template<class T> A ( A , T ) { } 
  };
  void g() {
    A a(0.0, 0.0);
  }

3/16/99  Missing diagnostic on redeclared template parameter in member template

The front end failed to issue a diagnostic in certain cases when a member
template redeclared one of its template parameters.  This has been fixed.

  template <class T> struct A {
    template <class T2> void T2();
  };

3/16/99  Wrapper code missing "!= 0" in constructor with virtual base class

The code generated by IL lowering, in the wrapper for a constructor for
a class having a virtual base class, to test whether a complete object
is being constructed, was changed recently (see Changes entry of 2/23/99).
The generated code tested a boolean local variable by simply doing

  if (var) {...}

This did not conform to the IL convention that all boolean tests are
standardized by the addition of a "!= 0" test, e.g., it should be

  if (var != 0) {...}

The "!= 0" test has been added.  [Patch sent out 3/19/99.]

3/16/99  Restrictions on function default arguments

According to the C++ standard, default arguments are allowed only on the
top-level declarator of a function declaration -- i.e., they are disallowed
on typedef declarations, parameter type declarations, pointer-to-function
declarations, and pointer-to-member-function declarations.  The front end
now enforces this rule in strict mode, issuing a discretionary error or
warning.  In default mode, however, such constructs are silently accepted
(as they are by cfront, g++, and MSVC++).

3/16/99  Demangling of compressed names

In some cases, the library name demangler failed to demangle compressed
mangled names.  Now fixed.  [Patch sent out 3/19/99.]

3/16/99  Minimal inlining: No temporary for field selection argument on
         call with no side effects

Minimal inlining no longer uses a temporary for an argument that
is a field selection on a call that has no side effects.

3/15/99  Spurious error on reference to base class of nested class

The introduction of class-name injection in version 2.41 also introduced
a spurious accessibility error when the base class of a nested class was
itself a private nested class.  Now fixed.  [Patch sent out 3/19/99.]

  class C {
    class X { };
    class A : X {
      X *p;            // Spurious error eliminated
    };
    class B {
      X *p;            // Still an error (in strict mode)
    };
  };

3/13/99  Internal error in case of ambiguous base class

An internal error in path_to_fundamental_symbol_base_class has been
eliminated.  It could come up in very rare cases involving ambiguous base
classes.

3/13/99  Constraint on local class friend function declaration

In strict mode the front end now issues a diagnostic (discretionary error
or warning) on a friend function declaration in a local class that does
not specify a function declared in the enclosing scope (as required by
11.4 [class.friend] paragraph 9).

  void f(int i) {
    struct S {
      friend void x();            // diagnostic in strict mode
    };
    extern void y();
    if (i) {
      struct SS {
        friend void y();          // diagnostic in strict mode
      };
    }
  }

3/13/99  Microsoft compatibility: spurious error on inheritance kind for
         deep single inheritance

In Microsoft compatibility mode a spurious error was issued when an
inheritance kind of __single_inheritance was specified for a class with
single inheritance more than one level deep.  Now fixed.  [Patch sent
out 3/19/99.]

  struct A { };
  struct B : A { };
  struct __single_inheritance C : B { };    // spurious error eliminated

3/12/99  Class template copy constructor problem with default argument

A problem was introduced when the new rules for the instantiation of
template default arguments were added in 2.40, which caused this example
to get a spurious error when compiled in strict mode.  This has been
fixed.  [Patch sent out 3/19/99.]

  template<class T> struct A {
    A();
    A(const A&, int = 0);
  };
  void f(const A<int>&);
  void g() {
    f(A<int>()); 
  }

3/11/99  Derived object caught by handler for base pointer

2.41 introduced a bug in the runtime library in which a throw of a
derived object could be caught by a catch of a base pointer, or a throw
of a derived pointer could be caught by a catch of a base object.  This
has been fixed.  [Patch sent out 3/19/99.]

3/10/99  Internal error on invalid using declaration inside class template

An internal error has been eliminated on the following invalid code:

  template <class T> struct A {
    int x;
    using A::x;                          // internal error eliminated
  };

3/9/99   Microsoft compatibility: loop in Microsoft mode in version 2.41

A Microsoft compatibility bug fix in 2.40 introduced a new bug that
could cause an infinite loop.  The loop occurred in certain cases when
processing a template declaration that declares an operator function
declared in a class template or a class template explicit specialization.
This has been fixed.  [Patch sent out 3/19/99.]

  template <class T> struct A;
  template<> struct A<int> {
    template <class T2> A<int>& operator+(const A<T2>&);
  };
  template <class T2> A<int>& A<int>::operator+(const A<T2>&) {
    return *this;
  }

3/8/99   Overloaded operator problem with function templates

In version 2.41, if the normal lookup component of an overloaded operator
lookup returned a function template, that template would be ignored.  This
could result in spurious errors, or in the incorrect function being
chosen.  This has been fixed.  [Patch sent out 3/19/99.]

  namespace N {
    template<class T> bool operator!=(const T& _X, const T& _Y);
  }
  struct A { };
  int main()
  {
    using N::operator!=;
    A x, y;
    x != y;  // spurious "no matching !=" error
  }

-------------------------------------------------------------------------------
Version 2.41, March 5, 1999

3/5/99   IL version number changed to 2.33

3/3/99   Environment variable used for temporary directory under Windows

When the front end is built with __MICROSOFT_OS__ TRUE, the TMP
environment variable is used (when the compiler is invoked), if set, to
specify the temporary directory to be used.  If TMP is not set, the
behavior is not changed (i.e., TMPDIR is used, if set).

3/3/99   Computing the maximum length of instantiation output prefix

Formerly, the routine that creates an instantiation output file name when
using one-instantiation-per-object mode reserved enough space to allow
the GEN_C_FILE_SUFFIX to be appended.  It now uses this only when
using either the C or C++ generating back end; otherwise, OBJECT_FILE_SUFFIX
is used instead.

3/3/99   Spurious error when a member class template parameter depends on
         the type of an enclosing template parameter

If a template parameter of a member class template depends on a template
parameter of an enclosing class template, and if that member class template
is defined later outside of the class, spurious errors could result when
an argument value is supplied for the member class template parameter.
This has been fixed.

  template<class T> struct A {
    template<T& TR> struct B;
  };
  // Problem goes away of B is defined in A.
  template<class T> template<T& TR> struct A<T>::B {
     static B b;
  };
  template<class T> template<T& TR> A<T>::B<TR>  A<T>::B<TR>::b;
  int i;
  A<int>::B<i> ab;

3/2/99   Microsoft C compatibility: relax restrictions on use of old-style
         function parameter lists

In Microsoft C mode old-style parameter lists are not restricted to
function definitions.  For example:

  void f(a, b);                  // Okay in Microsoft C mode
  typedef void (*fp)(a, b);      // Okay in Microsoft C mode

3/2/99   Microsoft C compatibility: signedness difference in variable
         redeclaration

In Microsoft C mode a variable can now be redeclared with a type that
differs in "signedness" from the original integral type.  For example:

  extern unsigned int i;
  extern signed int i;          // Okay in Microsoft C mode

3/1/99   Abort in checking for ambiguous base class member

A null-pointer abort could occur when checking for an ambiguous base
class member when the member in question was an overload set that
included a member function template.  Now fixed.  For example:

  class A {
  public:
    void f();
    template <class T> void f(T);
  };
  class B : virtual public A { };
  class C : virtual public A { };
  class D : public B, public C {
    void g() { f(); }                  // No longer aborts looking up "f"
  };

3/1/99   Microsoft compatibility: bug introduced by change to make
         template parameters visible in class specializations

In version 2.40, a change was made in Microsoft mode to make template
parameters visible within a specialization.  This change resulted in
spurious errors in cases where a member template of a specialization
was defined outside of the class.  This has been fixed.

  template <class T> struct A {};
  struct A<int> {
    template <class T2> void f(A<T2>); 
  };
  template <class T2> void A<int>::f(A<T2>) {}  

2/26/99  Microsoft compatibility: string in parentheses as initializer

Microsoft mode now accepts a string literal in parentheses as the
initializer for an array of characters.  This was previously
accepted only in pcc mode and cfront mode.

  static char c[] = ("abcdef");

2/26/99  Partial ordering rules changed to conform to standard

The partial ordering rules implemented by the front end conformed to the
original rules proposed, but not the final rules specified in the
standard.  Specifically, the front end removed qualifiers under references
while the standard does not remove such qualifiers.  The front end now
implements the rules as described in the standard.  The following example
illustrates cases that are now well-formed and now ill-formed as a result
of this change.

  template <class T> void f(T&);
  template <class T> void f(const T&);

  template <class T> struct A {};
  template <class T> void g(const T&);
  template <class T> void g(A<T>);

  int main() {
    const A<int>	aic;
    A<int>		ai;
    f(aic);  // ambiguous using original rules
    g(ai);   // ambiguous using standard rules
  }

2/25/99  Microsoft compatibility: old-style concatenation macros

MSVC++ (up to version 6.0, so far) allows the use of old-style
concatenation macros.  In Microsoft compatibility mode, we now allow
them too.

  #define SELF(x)x
  #define CONCAT_BAD(a,b) SELF(a)SELF(b)
  #define DECLARE_BAD(PRIM) \
      int CONCAT_BAD(e_,PRIM) ;
  DECLARE_BAD(foo_bad)  // Accepted (nonstandard)

2/25/99  Friend functions: no injection on declaration, special lookup

Functions declared in friend declarations in classes are no longer
entered into the innermost enclosing namespace scope.  They are
after a fashion still declared in those scopes, but the name is
not visible unless it is actually declared by some other (non-friend)
declaration.  Such friend functions are found by argument-dependent
lookup (see below).  This feature can be enabled or disabled with
--[no_]friend_injection.  The default is given by
DEFAULT_FRIEND_INJECTION (TRUE in the release, i.e., not the
setting required by the standard, because this feature does seem
to break some real-world code).  The old behavior is preserved
in Microsoft mode and cfront mode.

2/25/99  Argument-dependent lookup on function calls

Argument-dependent lookup (also known as Koenig lookup) is now
implemented for function calls in the normal f(x, y, z) form.
(It was already implemented for overloaded operators, e.g., a + b.)
Argument-dependent lookup finds instances of the named functions
in the classes and namespaces associated with the argument types,
and adds them to the set of functions considered by overload resolution.
The feature can be enabled or disabled with --[no_]arg_dep_lookup.
The default is given by DEFAULT_ARG_DEPENDENT_LOOKUP (TRUE in the
release).  The feature is turned off in Microsoft mode and cfront
mode.

2/25/99  Complete runtime access checking on dynamic_cast

The dynamic_cast operation requires a limited form of access checking
at runtime.  Heretofore, the information provided to the runtime has
not been sufficient to allow it to do all parts of the access check.
To fix this, two additional parameters have been added to the __dynamic_cast
and __dynamic_cast_ref runtime routines (this is an ABI CHANGE).
The additional parameters are used to pass in the typeinfo entry
of the underlying class type of the static type of the source
pointer, and the original source pointer (in cases where the
source pointer is to a class that has no virtual function table,
the pointer passed in as the first parameter has been cast to a
base class that does have a virtual function pointer).

2/25/99  Qualification conversion on throw of multi-level pointer

The standard allows a qualification conversion on a throw of a pointer
type.  Previously, this was implemented only for single-level pointers,
e.g., throw "int *" and catch "const int *".  Now, it is also implemented
for multi-level pointers, e.g., throw "int **" and catch
"const int * const *".  This required an ABI CHANGE (for versions
that use full or partial lowering of EH features): a new runtime
routine __throw_setup_ptr has been added, and the exception specification
type structure has an additional field (ptr_flags).

2/24/99  MICROSOFT_DEFAULT_USE_NONSTANDARD_FOR_INIT_SCOPE eliminated

The configuration macro MICROSOFT_DEFAULT_USE_NONSTANDARD_FOR_INIT_SCOPE
has been eliminated.  That feature is now controlled by the
microsoft_version option instead.  (As of MSVC++ 6.0, however, the
new for-init scope has not been implemented in MSVC++, so the feature
is always off in Microsoft mode.)

2/23/99  near/far support: assignment of class object declared "far"

When near/far support is enabled (e.g., in Microsoft 16-bit mode),
an object of a class type declared "far" can now be assigned.
Formerly, the simulation of the default operator= rejected such
an assignment.

2/23/99  On exception in constructor, destroy virtual base class only if
         constructed

When an exception is thrown in a constructor, the base classes
of the object are destroyed.  Virtual base classes should be destroyed
only if they are constructed at this level, i.e., only if the object
being constructed is a complete object.  Similar processing is
also needed in destructors.

2/22/99  IL file reading problem in one-instantiation-per-object mode

When running in one-instantiation-per-object mode, in a complicated
case involving an enum constant that is referenced only in an
initializer expression inside a function, the IL file produced was
inconsistent, and the IL reader aborted when reading it.  Now fixed.

2/22/99  New semantics for unexpected()

The runtime now implements the semantics of unexpected() described in
the standard.  See the runtime Changes file for more information.

2/22/99   Folding of min_int/(-1) when integer value is represented as
          host integer

When integer values are represented as host integers
(INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is TRUE) on a two's complement
host computer, folding of the division of the smallest-valued integer
(e.g., -2147483648 when 32-bit long is the largest integral type
supported) by -1 was not done correctly.  Or rather, the folding
code noted correctly that the division overflows, but it returned
zero as the result of the division.  A better choice (and what's done
now) is the smallest integer value, i.e., the left operand value.

2/21/99   Upper limit on mangled name length

By setting DEFAULT_MAX_MANGLED_NAME_LENGTH, or the variable
max_mangled_name_length, one can now enforce an upper limit on
the length of mangled names.  Names that will not fit in that
length (or, more precisely, in that length minus 10) will be truncated
to the maximum length, with the last 10 characters of the truncated
name being two underscores followed by a computed CRC-32 value for the
full name, expressed as 8 hexadecimal characters.  For example, with
a maximum length of 40, a mangled name might look like

  g__FP24x2345678901234567890123__7b5cbe66

Truncation of names may be necessary when an underlying compiler or
linker has limits on the size of external names, which can -- with
complicated templates, as in the standard library -- be thousands
of characters long.  (Note also the Changes entry of 2/17/99 regarding
compression of mangled names, which reduces the size of names but does
not guarantee a maximum length.)  By default, max_mangled_name_length
is set to zero, which means no limit.  It should be noted that mangled
names truncated in this way cannot be decoded by the name demangler,
which can make the output of the prelinker undecipherable.  Therefore
this limit should be used only if necessary, and the value should
be as large as possible.

2/18/99   void expression on return statement in void function in C++

In C++, the standard allows a return statement in a void function
to specify an expression with void type.  This is now implemented.

  void f() {}
  void g() { return f(); }

2/18/99   Microsoft compatibility: no error on invalid command-line -D

In Microsoft mode, an error is no longer issued for a command-line -D or
-U of an invalid identifier, e.g., "-D_._".  The definition/undefinition
is simply ignored.

2/18/99   Namespace member function declared static within an extern "C"
          block

When a namespace member function was declared "static" within an extern "C"
block and subsequently defined, an abort in remove_from_routines_list could
result.  Now fixed.

  namespace N {
    extern "C" {
      static void f();
      static void f() { }  // Internal error has been eliminated
    }
  }

2/17/99   Name linkage on declaration within unnamed namespace

When an extern "C" variable or routine declaration appeared within an
unnamed namespace, it was incorrectly regarded as having internal linkage.
This bug caused an abort in remove_from_routines_list if a function was
first declared and then defined.  Now fixed.

  namespace {
    extern "C" {
      void f();        // Now gets extern "C" name linkage
      void f() { }     // Internal error has been eliminated
    }
  };

2/17/99   Microsoft C compatibility: implicit conversions between any
          pointer types

In Microsoft C mode, a pointer type can now be implicitly converted to
any different pointer type.  A warning is issued.

2/17/99   Microsoft C compatibility: lvalue cast of pointer to integral

In Microsoft C mode, an lvalue cast from a pointer type to an integral
type of a different size is now allowed.

2/17/99   Compression in mangled names

The name mangling process now runs a compression step after the
mangled name is generated.  Names that are compressed begin with
"__CPR", and the name demangler has been changed to uncompress
them before expanding them.  The compression is nothing very fancy:
the sequence "JnnnJ" means "repeat the sequence beginning at nnn
in the name".  A simple "J" is replaced by "JJ" so that uncompression
can be done without parsing the mangled name.

Names shorter than 60 characters are not compressed, and compression
is suppressed if the compressed form is longer than the uncompressed
form.  Compression is enabled/disabled by the variable compress_mangled_names
and the configuration macro DEFAULT_COMPRESS_MANGLED_NAMES.

2/17/99   Diagnosis of invalid use of "template" keyword

Invalid uses of the "template" keyword in field selection operations and
qualified names are now diagnosed.

  template <class T> inline void f(T* p)
  {
    p->template i < 1 > 2;  // Error if "i" is not a template
  }

2/17/99   Source sequence list: inline friend function of template class

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE but
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is FALSE, the
source sequence representation of a friend function defined inline within
the template specialization is now treated like a member function so
defined -- that is, the body of the inline friend function does not appear
in the source sequence lists.

2/16/99   __uuidof(T) as a template argument, where T is a template parameter
          type

The Microsoft __uuidof operator applied to a template parameter type
can now be used as a nontype template argument.  Formerly, an error
was issued during the prototype instantiation because the template
parameter type was not considered to be external.

This change required a name mangling extension: "uu" now indicates the
__uuidof operator in the mangling for an expression.

2/11/99   Template based array type has incorrect size

Under certain circumstances, an array type created by the function
template argument deduction and matching process could have an
incorrect size.  This has been fixed.

2/10/99   Incorrect lookup in partial specialization

In a partial specialization, a reference such as "A<T1,T2>" in the example
below should refer to a "nonreal" instance of the template, and the
reference to "B" should be accepted.  Instead, the front end was looking
up the name in the primary template and issuing an error.  This has been
fixed.

  template <class T1, class T2> struct A { };
  template <class T1, class T2> struct A<T1*, T2*> {
    typedef typename A<T1,T2>::B B;
  };

2/8/99    Abort in Microsoft 16-bit mode

When MAINTAIN_NEEDED_FLAGS is configured to TRUE, an abort could occur with
the elimination of an unused routine whose type is qualified.  Now fixed.
This is a problem that could come up only for implementations providing
support for near/far function qualifiers, e.g., in Microsoft 16-bit mode.
For example, if function f was never called:

  static void near f() { }  // Abort during elimination of unneeded routine

2/5/99    Allow typedef and using-declaration to same typedef in a scope

In default mode, a using-declaration that refers to a typedef of a
given type is permitted to coexist with a typedef of that type or
another using-declaration that refers to that type.  An error is still
issued in strict mode.

  typedef unsigned int size_t;
  namespace std {
    typedef unsigned int size_t;
  }
  using std::size_t;

2/2/99    Source sequence lists: internal error when class template
          instantiation is triggered by namespace member function

With TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS configured to TRUE,
if a namespace member function definition triggered the instantiation of a
class template that was a member of the same namespace, an internal error
was sometimes produced when the definition did not appear in the scope of
the namespace.  Now fixed.

  namespace N {
    template <class T> struct A {
      A(int i = 0);
    };
    void f();
  }
  void N::f() { A<int> a; }     // Abort while generating source sequence
                                //   entries for constructor of A<int>

1/30/99   Minimal inlining: no temporary for parameter when argument
          is unaliased automatic variable

When minimal inlining expands a function call, it assigns the argument
values to temporaries except in certain special cases where the argument
expression can be used directly in place of the parameter, e.g., when
the argument expression is a constant.  Now, no temporary is used
when the argument is an auto variable whose address has not been
taken, since such a variable cannot change its value across the
function call.  (2/3/99:)  Also, if the function call has no side
effects, an argument that is a simple global variable can be
passed without using a parameter.

1/29/99   lower_name.c reworked

The name-mangling code in lower_name.c has been reworked to make it
simpler.  The mangled name is built up in a temporary text buffer and
then copied elsewhere.  This makes it possible to do processing
that looks at the complete mangled name at the end of the process
and does some transformation.  See the routine end_mangling.

1/28/99   Missing access error on inherited name used in qualifier

The front end failed to issue an error when an inaccessible inherited
type was used in the qualifier of a qualified name.  This has been
fixed.

  struct A {
    static int i;
    typedef A my_a;
  };
  struct B : private A { };
  struct C : public B {
    int f() { return my_a::i; }  // my_a is inaccessible
  };

1/26/99   Overload resolution: comparing standard conversions from class
          pointers to void * after user-defined conversions

On an initialization by user-defined conversion, one conversion can be
chosen over another on the basis of the standard conversion that
follows the user-defined conversion.  In particular, if A is a base
class of B, a standard conversion of A* to void* is better than
a conversion from B* to void*.  That is now implemented.

1/26/99   Union improperly marked as an anonymous union

Recent changes exposed a long-standing bug whereby a union referenced in
a useless class member declaration could end up incorrectly marked as an
anonymous union; moreover, no diagnostic was issued on the invalid
member declaration.  Now fixed.  Here's an example:

  union U { int i, j; };
  class A {
    U;          // error: declaration does not declare anything
  };

1/26/99   Abort on incomplete explicit template argument list

An abort on processing a function call that includes an explicit template
argument list that is incomplete is now fixed.

  template <int I> struct A { A(int); };
  template <int I, char J> void f( A < J * 12.34 >) {}
  void g() {
    f<'x'>(1);  // Gets error now, not abort.
  }

1/26/99   &T::x now allowed, where T is a template parameter

Taking the address of a member of a class indicated by a template
parameter, e.g., &T::x where T is a template parameter, is now
allowed.

1/26/99   Class name injection

In C++ mode the name of a class is now optionally entered as a member of
itself, as required by clause 9 (para 2) of the standard; this is
implemented more or less as an implicitly declared member typedef.  The
functionality is governed by global variable class_name_injection_enabled,
with a default value of DEFAULT_CLASS_NAME_INJECTION (in lang_feat.h) and
controlled by command line option --[no_]class_name_injection.  In strict
mode declaring a nonstatic data member with the same name as its class is
now an error; otherwise it is still permitted -- the explicitly declared
name hides the implicit class name declaration.  (See also Changes entry
for 9/29/98.)

1/26/99   Partial specialization problem when mixing "class" and "struct"

The partial specialization processing did not work properly in certain
cases if a partial specialization was declared as a "class" and the
primary template was declared as a "struct" (or vice-versa).  This
has been fixed.

  template<class T1, class T2> struct A { };
  template<class T1> class A<T1, int> { };  // worked if "struct"

  template<class T1> struct B { };
  template<class T1, class T2> struct B< A<T1, T2> > { };
  template<class T1> struct B< A<T1, int> > { };

  int main()
  {
     B< A<float, int> > b;
  }

1/25/99   Cast like int() allowed as constant expression

A functional-notation cast with no arguments, which for scalar
types is equivalent to casting a constant zero to the scalar type,
is now allowed as part of a constant expression.

  int a[int()+1];  // Same as int a[1]

1/25/99   Template argument deduction, arrays passed to references

When an array actual argument is passed to a reference parameter of
a function template, the argument is now never subjected to the
array-to-pointer decay before the template argument deduction is done.
Formerly, it was if the type after decay matched the underlying
type of the reference.  That made sense to us, and that's what
we proposed to the standards committee, but it's not what ended
up in the standard.

1/25/99   Nested class access to enclosing classes in strict mode

Nested classes now have no access to enclosing classes in strict mode.
Formerly, they had access in certain cases, which was necessary as
a transitional step until class name injection was implemented.
Nested classes continue to have access to enclosing classes in
non-strict mode.

1/25/99   C++-generating back end: constructors in instantiation directives

The C++-generating back end formerly put out instantiation directives
incorrectly for constructors, destructors, and conversion functions,
because it included a return type in the declaration.  The return type
is now suppressed.

1/24/99   Microsoft compatibility: array new and delete

A refinement of the 5/2/98 change for array new and delete in Microsoft mode:

 -- operator new[] and operator delete[] are no longer predeclared.
 -- On any array new or array delete, if no operator function is found
    the corresponding non-array function will be used instead.  (In the
    previous change, this was done only for placement array new; it is
    now done in all cases.)

1/24/99   Virtual function call optimization and using-declarations

In the presence of a using-declaration that makes a virtual function
visible and makes its final overrider invisible, the optimization to
use a non-virtual call to call a virtual function (when the complete
object type is known) failed, with the consequence that the wrong
function was called.  The bug occurred only when the function is
overloaded.  Now fixed.

  struct A {
    virtual void f();
    virtual void f(int i);
  };
  struct B : virtual A {
    virtual void f();
    virtual void f(int i);
  };
  struct C : B , virtual A {
    using A::f;
  };
  void foo() {
    C c;
    c.f(); // Should call B::f, but called A::f instead
  }

1/24/99   Code for conversion function call that requires derived->base
          conversion afterwards

In some cases, when code was generated to call a conversion function
in a context where the result of the conversion function needs to
be converted from a derived class to a base class, and where the
derived class cannot be copied bitwise, the final conversion was
omitted.  Now fixed.

  struct B {
    int m;
    B(int a=0) { m=a; }
  };
  struct C : virtual public B {
    C(int a) : B(a) {}
  } e1(1);
  struct A1 {
    operator C() { return (e1); }
  } a1;
  int main() {
    B b = a1;  // Bad code was generated here
  }

1/23/99   Preinclude command-line option uses include search path

The command-line preinclude option now searches the include search
path for the indicated file name.  Formerly, the file was searched
for only in the current directory.

1/23/99   Implicitly-generated operator= allows rvalue as left operand

Assignment of an object of class type in C++ is defined in terms of calling
the operator= function of the class.  Even if the actual assignment
can be implemented as a bitwise copy, the semantics of the assignment
are defined by the standard in terms of calling a generated operator=
function.  Therefore, the left operand of an assignment of class type
should be allowed to be an rvalue, even if a bitwise copy is used to
implement the assignment.  This is now accepted (it was already accepted
when a user-written operator= is present).

  struct B { };
  struct C { C& operator=(const C&); };
  int main() {
     B b;
     B() = b;  // Okay
     C c;
     C() = c;  // Okay (was already supported)
  }

1/23/99   C-generating back end, Microsoft compatibility: __asm output

In Microsoft mode, the C-generating back end now puts out asm
statements in the form

  __asm { ... }

Previously, it used the (incorrect) form

  __asm("...");

1/22/99   IL lowering of pointer-to-member calls: no optimized code sequence

IL lowering of pointer-to-member calls has used a simpler code sequence
when the class involved has no virtual functions.  The C++ standard now
disallows that optimization (see WG21/N0644), so it has been removed.
The old behavior can be retained by setting
DEFAULT_POINTER_TO_MEMBER_CALL_OPTIMIZATION_ALLOWED to TRUE.

1/22/99   C-generating back end: bit field base types

When ALLOW_NON_INT_BIT_FIELD_BASE_TYPE_IN_GENERATED_C is TRUE, the
C-generating back end now puts out "signed int" or "unsigned int"
for a plain "int" bit field, to take away the target compiler's
choice of signedness.  (Actually, what's new is putting out "unsigned"
in that case; "signed" was already put out.)  This also comes up for
bit fields declared with enum type.

1/22/99   C++-generating back end: virtual function calls, qualified names

The C++-generating back end now never puts out a qualified name for a
virtual function when the function is called virtually (which is to
say when the source code did not use a qualified name, because the
use of a qualified name suppresses the virtual-ness).  This has
been a problem only in obscure cases involving using-declarations.

1/21/99   const string literals

String literals and wide string literals now have const type as
required by the C++ standard.  That is, "abc" has type "array[4] of const
char", and L"abc" has type "array[4] of const wchar_t".  This
feature is controlled by DEFAULT_STRING_LITERALS_ARE_CONST (FALSE
in the release) and by the --[no_]const_string_literals command-line
option.

IL CHANGE: IL lowering does not change the types of string literals
to non-const, so back ends will now see const string literals.  We
are guessing this will not be a problem, but it is a difference,
and it is another case where the output of IL lowering is not
fully-standard C.

1/19/99   C++-generating back end: multiple nested class declarations

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured
to TRUE (so that class template instantiations appear in the generated C++
as explicit specializations), nested class definitions are delayed (i.e.,
put out sometime after the class template definition), and a simple
declaration is put out instead.  However, when the nested class definition
was preceded by a forward declaration, code was put out that didn't
conform to a strict reading of the standard.  This has been fixed -- only
the first nested class declaration is put out.  For example:

  template <class T> class A {
    class N;
    N *pn;
    class N { };
  };
  A<int> a;

The C++-generating back end now puts out the specialization of A<int>
with only a single declaration of A<int>::N:

  template<> class A<int> {
    class N;
    N *pn;
    // extra declaration of N is suppressed here
  };
  class A<int>::N { };

1/18/99   Name linkage for "main"

The name linkage for "main" is now extern "C++" (instead of extern "C").
This change will not be noticed by implementations using IL lowering.

(The previous state of affairs was inconsistent: the name-linkage of
"main" used to be extern "C", whereas the routine-name-linkage recorded in
the associated routine type was extern "C++".  Now both are extern "C++",
and IL lowering has been changed to avoid mangling "main" whatever the
linkage.)

1/18/99   String types > 80 characters now recorded on orphan lists

String and wide string types with length greater than 80 (actually,
MAX_TRACKED_STRING_TYPE_LENGTH) are now recorded as potential orphaned
types.  The failure to record them did not cause any problems in
versions that either write IL files or do IL lowering (since those
processes will cause such orphans to be recorded), but it could affect
versions that do neither.

1/18/99   is_far_type and arrays, in C mode

The function is_far_type has been changed so that it works correctly
for arrays in C mode.  is_far_type is used only when "near" and "far"
are enabled (e.g., in Microsoft 16-bit mode).

1/15/99   Backslashes in macro-expanded header names in #include

The following example now works correctly on Microsoft systems:

  #define _SYS_TIMB_H <sys\timeb.h>
  #include _SYS_TIMB_H

Formerly, the backslash in the macro expansion process caused an error.

1/13/99   "routine name linkage" set incorrectly in function redeclaration

When a function was declared with an explicit linkage specifier and then
redeclared without it, the function's type entry was sometimes updated
incorrectly.  For example:

  extern "C" void f();
  void f() { }

The name_linkage field in the routine entry for "f" was right, but the
routine_name_linkage field for f's type was wrong.  Now fixed.

IL CHANGE: new flag routine_name_linkage_is_explicit was added to
a_routine_type_supplement.

1/12/99   Spurious error in name-linkage compatibility checking

Spurious errors are no longer issued on the following:

  namespace A {
    extern "C" {
      void f();
      void g();
    }
  }
  extern "C++" void f();  // error eliminated -- declaration is no longer
                          //   treated as a redeclaration of A::f()
  int g();                // error eliminated -- declaration is no longer
                          //   treated as a redeclaration of A::g()

1/11/99   Microsoft compatibility: __declspec on class declaration

__declspec and similar declaration modifiers that can appear between the
"class" keyword and the class name (e.g., "class __declspec(dllimport) A") 
are now recorded against the class, and output by the C++-generating back
end, even when they appear in a declaration instead of a definition
of the class.

1/5/99    Scope of forward-declared enum types

When forward declarations of enum types are permitted (e.g., in Microsoft
compatibility mode), such a declaration appearing inside a class definition
was sometimes treated as a member of the class itself when it should have
been marked as a member of the innermost containing nonclass scope.  This
bug caused an internal error in some implementations; see also Changes entry
for 6/16/98.  Now fixed.  Example:

  struct S {
    enum E *p;       // forward declaration of ::E (not S::E)
  };
  enum E { x };      // forward declaration resolved

12/19/98  Class member using-declaration with "typename"

Support is now provided for class member using-declarations of the form
"using typename ...".

  template <class T> struct B {
    typedef int char_type;
  };
  template <class T> struct D: public B<T> {
    using typename B<T>::char_type;    // Spurious error no longer issued
    char_type c;
  };
  D<int> d;

12/16/98  Independent configuration support for declaration modifiers

You can now set DECL_MODIFIERS_IN_USE (in lang_feat.h) even when
MICROSOFT_EXTENSIONS_ALLOWED is configured to FALSE.  This provides a
hook for adding implementation-defined declaration modifiers; otherwise,
this change should have no effect.

12/14/98  Template information files and automatic instantiation mode

A bug was introduced in version 2.37 that caused template information
files (either .ti or .ii, depending on configuration) to be created
even when automatic instantiation is not enabled.  This has been
fixed.

12/14/98  Microsoft compatibility: constructor declaration using typedef

In Microsoft compatibility mode a constructor may now be declared (within
a class definition) using a typedef name that refers to the parent class.

  struct S {
    typedef S X;
    X() { }                 // accepted as declaration of S::S()
  };

12/12/98  Removal of redundant forward class declaration from source
          sequence list

With CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS configured to
TRUE, secondary-declaration entries representing forward declarations of
classes in the original source were mistakenly removed.  This meant the
following:

  struct S;
  struct S { };

was represented by the C++-generating back end as only a definition.
Fixed -- the code to remove such forward declarations now only removes
those that are compiler-generated.  (This problem was introduced by
the reworking of source-sequence-entry generation in 2.40.)

12/11/98  Independent configuration for support for near and far

Support for near and far memory attributes can now be configured
independently of support for other Microsoft extensions by using
NEAR_AND_FAR_ALLOWED and DEFAULT_NEAR_AND_FAR_ENABLED (see lang_feat.h).
 -- If you configure MICROSOFT_EXTENSIONS_ALLOWED to TRUE,
    NEAR_AND_FAR_ALLOWED will default to TRUE as well, and recognition of
    the keywords is enabled when --microsoft_16 is selected on the command
    line; this corresponds the old behavior.
 -- If MICROSOFT_EXTENSIONS_ALLOWED is TRUE but NEAR_AND_FAR_ALLOWED is
    FALSE, the --microsoft_16 command line option is not recognized.
 -- If both MICROSOFT_EXTENSIONS_ALLOWED and DEFAULT_NEAR_AND_FAR_ENABLED
    are TRUE, --microsoft has the same effect as --microsoft_16.
 -- If MICROSOFT_EXTENSIONS_ALLOWED is FALSE but NEAR_AND_FAR_ALLOWED and
    DEFAULT_NEAR_AND_FAR_ENABLED are TRUE, support for near and far
    (emulating Microsoft's semantics) is automatically enabled (except in
    strict mode), but without support for other Microsoft extensions.
In addition, SUPPRESS_NEAR_AND_FAR_IN_GENERATED_CODE (see targ_def.h) can
be configured to control whether the keywords "near" and "far" are passed
through in the output of the C- and C++-generating back ends.

12/11/98  Long-lifetime temporaries mode, destruction of temporary
          on switch clause fallthrough

In long-lifetime temporaries mode, a switch statement that does not
construct any destructible objects does not force destruction of
temporaries; they survive across it.  However, on a fallthrough from
one switch clause to another within such a switch statement, any
active temporaries were incorrectly destroyed (they would then
be destroyed again later at the proper end of lifetime).  This has
been fixed.

  struct A {
    A();
    ~A();
    operator int();
  };
  void f() {
    int i = 1;
    int j = A();
    switch (i) {
      case 1:
        i = 2;
        // Temporary from A() above was destroyed here
      default:
        i = 3;
        break;
    }  /* switch */
  }

12/11/98  Partially lowered exception handling: cleanup state after final
          return in destructor

When partial lowering of exception handling is done, cleanup state
instructions are placed in unreachable code to aid in generation of
arrays that map program locations to cleanup state.  The cleanup state
instruction put out following the final return of a function is
now suppressed.  It was unnecessary, and, in the case of a destructor
with an epilogue, could be confusing to a back end.  (12/17/98:)
Also, the reachable_by_fall_through flag is now FALSE on the generated
label for the epilogue of a destructor when there is no top-level
return statement, as when the end of the top block is unreachable.

12/9/98   IL write/read problem with zero-length memory blocks

In some obscure cases, a zero-length memory block could end up on the
list of blocks for a region.  IL write and IL read had difficulty
with such blocks.  Now fixed.

-------------------------------------------------------------------------------
Version 2.40, December 8, 1998

12/8/98   IL version changed to 2.32

12/5/98   Microsoft compatibility: improved __declspec(dllimport) support

In Microsoft mode, the body of a __declspec(dllimport) function that
is also declared "inline" is no longer added to the IL.

12/5/98   Microsoft compatibility: reference parameters, overload resolution

In Microsoft bugs mode, the overload resolution tie-breaker behavior
associated with single_ref_qual_ovl_res_tiebreaker is enabled (see
lang_feat.h).  However, it turns out that for Microsoft compatibility
the tie-breaker should apply only when the argument is not a constant:

  void f(int, short) {}
  void f(const int&, char);
  int g() { return 0; }
  int main () {
    int i;
    f(g(), 0);  // MSVC++ 6.0 says okay, picks f(int, short)
    f(0, 0);    // MSVC++ 6.0 says ambiguous
    return 0;
  }

Yes, this matters; some code in the Rogue Wave STL fails with the
old behavior.

12/4/98   Configurability of namespace for class type_info

Whether class type_info is assumed to belong to namespace std is now
separately configurable.  See DEFAULT_TYPE_INFO_IN_NAMESPACE_STD (in
targ_def.h) and global variable type_info_in_namespace_std.

12/4/98   Generated operator= function: base class operator= called
          non-virtually

When a copy assignment operator function (operator=) is generated,
calls therein to operator= functions for base classes and members
should be non-virtual even if the called functions are virtual.
See the C++ standard, 12.8/13.  Now fixed.

12/3/98   Microsoft compatibility: undefined extern inline function

In Microsoft mode, an extern inline function that is referenced but not
defined now gets a warning instead of an error.

12/3/98   Microsoft compatibility: friend functions in class templates
          analyzed only if used

In Microsoft mode, a friend function defined in a class template is only
semantically analyzed if it is used.  The following example, which is
rejected in default mode, is now accepted in Microsoft mode.

	template <class T> struct A {
		friend T f(T) { return T(); }
	};
	// B has no default constructor
	struct B { B(int){} };

	A<B> ab;

12/2/98   Standalone C++-generating back end

The C++-generating back end has been changed not to call
f_types_are_compatible.  This was the only thing standing in the way of
building a standalone C++-generating back end.

11/29/98  Microsoft compatibility: user-defined conversions on relational
          operators

The MSVC++ compiler does not look for user-defined conversions to pointer
types for the built-in operators >, <, >=, and <=.  In Microsoft bugs mode,
we now do the same.

  struct S {
    S(const char *);
    operator char *();
    int operator>(const S&);
  };
  int main() {
    char *p = "String";
    S x(p);
    if (x > p) {} // Resolves to S::operator>, not built-in, in Microsoft
                  // bugs mode
    return 0;
  }

11/28/98  User-defined conversions on operands of ->*

User-defined conversions are now considered on the operands of the
"->*" pointer-to-member operator.

  struct X {
    operator int X::*();
  };
  X o;
  X *p = &o;
  int main() {
    p->*o = 1;
  }

11/28/98  Template default arguments instantiated only when needed

Default arguments of function templates and member functions of class
templates are now instantiated only when the default argument is used
in a call.

  template <class T> int f(T, T = T()){}
  struct A {
     A(int){}
     // no default constructor for A
  };
  A a(1);
  int i = f(a,a);

11/24/98  Microsoft compatibility: support for __assume

In Microsoft mode the __assume(expression) construct is now accepted.
IL CHANGE: This is represented as an eok_assume expression node (only
in Microsoft mode, of course).

11/24/98  Microsoft compatibility: support for __forceinline

In Microsoft mode the keyword __forceinline is now accepted wherever
__inline is accepted.

11/24/98  Microsoft compatibility: incompatible template parameter lists

In Microsoft bugs mode, an error is not issued if a class template
definition is followed by a redeclaration of the template with an
incompatible template parameter list.

  template <class T, class T2> struct A {};
  template <class T> struct A;

11/23/98  static_cast of void * to pointer to cv-qualified object type

A permissive reading of 5.2.9/10 in the C++ standard suggests that
a static_cast should be allowed to convert a "void *" to a pointer
to a cv-qualified object type, e.g., "const char *, even though
there is no standard conversion in the opposite direction.

11/23/98  Microsoft compatibility: handling of template default arguments

In Microsoft mode, template default arguments are scanned only when
the default argument value is needed by an instantiation, so certain
invalid template default arguments are accepted without errors.  The
C++ Standard does not permit default template arguments on function
templates because they serve no purpose on such declarations.  The
Microsoft compiler accepts and ignores default arguments on function
template declarations.  We duplicate this behavior in Microsoft mode.


  template <class T = xyz> struct B {};  // invalid default
  template<class T> class A { };
  template<class T = int> void f(T);  // default on function template

11/23/98  Needed flag processing for local static initializer

The processing to set the "needed" flag unnecessarily set that flag
on an unreferenced initialized local static variable.  The flag is
no longer set in such a case.

  struct SSS {
    int aa;
    int bb;
  };
  void fff() {
    static const SSS sss = {1, 2};
  }

11/20/98  Incorrect cross-reference position on call of overloaded function

In the following example, the cross-reference position for "S::f" pointed
to the "S" while it should have pointed to the "f".  This has been fixed.

  struct S {
    static void f();
    static void f(int);
  };
  void g() { S::f(); }

11/20/98  C++-generating back end: static and nonstatic members of enum
          type erroneously merged into single declaration

A bug in the code that handles declarations that use unnamed types
caused the C++-generating back to incorrectly merge certain
declarations (e.g., "e" and "e_ptr" in the following test case) into a
single declaration.  This has been fixed.

  enum E { val };
  class A {
    static const E e;
    const E* e_ptr;
  };

11/19/98  Microsoft compatibility: operator new declared as namespace member

In Microsoft compatibility mode a warning is now issued instead of an
error if operator new or delete is declared in a namespace.  Microsoft
does not actually find such declarations when processing new or delete
expressions, and we don't either.

  void *operator new(size_t);
  namespace N {
    void *operator new(size_t);  // warning in Microsoft mode
    void f() {
      int *p = new int;          // still calls ::operator new()
    }
  }

11/18/98  "main" declared inside a namespace

An internal error could be generated if "main" was declared both in a
namespace and in the global scope.  This has been fixed.

  namespace N {
    int main();
  }
  int main() {                   // internal error has been fixed
    return 0;
  }

11/18/98  Source-sequence representation of functions defined within class
          definitions

When either NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, the
source-sequence representation of member and friend functions defined
within a non-local class is as though the definition had actually appeared
immediately after the end of the class definition.  (This used to be done
only when the first of the two configuration flags was TRUE.  See Changes
entry for 9/23/97.)  For implementations in which only the second of the
two configuration flags is set, this change fixes an internal error in the
C++-generating back end along with some problems in the generated C++
output when a class template instantiation is triggered by scanning the
body of an inline-defined member function.

11/16/98  Spurious error on friend destructor declaration in class template

A spurious error was issued if a class template declared a destructor
to be a friend, and the class type of the destructor was dependent on
a template parameter.  This has been fixed.

  template <class T> struct A {
    friend T::~X();
  };

11/11/98  C++-generating back end: scope in which specialization is
          put out to represent an instantiation

When TEMPLATES_IN_SOURCE_SEQUENCE_LISTS is configured to TRUE, if a class
definition contains a template instance reference in which a template
argument refers that very class, the C++-generating back end now avoids
when possible putting out the specialization within the scope of the class.
For example:

  template <class T> struct A { };
  struct B {
    A<B> f();
    struct N;
    A<N> g();
  };

The specialization declaration that represents the instantiation of A<B> is
now put out in front of B, with a non-defining declaration of B preceding
it.  However, this cannot be done for A<B::N>.  Here's the output:

  template <class T> struct A { };
  struct B;
  template<> struct A<B>;         // improved location
  struct B {
    A<B> f();
    struct N;
    template<> struct A<N>;       // unavoidable
    A<N> g();
  };

11/11/98  Support for building source sequence lists reworked

A major overhaul of source sequence list management in the front end has
been done.  The general scheme involves attaching the lists to the current
scope stack entry and merging them as entries are popped from the scope
stack.  For most implementations for which GENERATE_SOURCE_SEQUENCE_LISTS is
configured to TRUE, this change will mean little more than an improvement in
packaging (e.g., the inclusion of two new source files, src_seq.c and
src_seq.h).  However, if TEMPLATES_IN_SOURCE_SEQUENCE_LISTS is also TRUE,
this change represents a substantial simplification.  In particular, the
ss_insert_stack has been abandoned and the code for inserting the
specializations that are generated to represent instantiations has been
centralized.  These changes should in general improve maintainability.

11/7/98   Ordering of lowered code for exception handling (conditional flag)

The code generated by IL lowering (in the full-EH-lowering mode) for
initialization of a conditional flag put out a use of the address of
the flag followed by the dynamic initialization of the flag.  This is
not valid in C (you can't use a variable before the point at which it
is declared/initialized).  The code for the two operations has now
been swapped.

11/4/98   Internal error on specialization of member with incomplete array type

An internal error would result if a template static data member, whose type
is an incomplete array type, was specialized.  This has been fixed.

  struct B {
    B(int);
  };
  template <class T> struct A {
    static const B b[];
  };
  template <> const B A<int>::b [] = { 0 };

11/2/98   Set access in IL template entry for member templates

When RECORD_TEMPLATES_IN_IL is configured to TRUE, the access field of an
IL template entry is now being set correctly for member templates.  This
affects the output of the C++-generating back end for cases like this:

  class A {
    template <class T> class N { };
  };

10/26/98  Parent namespace set incorrectly for certain qualified friend
          declarations

If a namespace qualified friend declaration referred to an instance of a
function template, the parent namespace pointer for that instance was
sometimes set incorrectly.  This could result in name lookup errors
during the instantiation of the instance.
  
  namespace N {
    template<class T> struct A;
  }
   
  namespace O {
    template<class T> void f(N::A<T>);
  }
   
  namespace N {
    template<class T> struct A {
      friend void O::f<T>(A<T>);
    };
  }
   
  namespace O {
    void g(void) { }
    template<class T> void f(N::A<T>) {
      g();  // g not found during instantiation
    }
  }
   
  int main() {
    O::f(N::A<int>());
  }

10/26/98  Access of virtual base class set incorrectly

In cases involving multiple inheritance the access of an indirect virtual
base class was on rare occasions set incorrectly.  For instance, in the
following example the access on one of the derivation paths of D::A was
wrong, and as a result no diagnostic was issued in the reference to D::i.
Now fixed.

  class A { public: int i; };
  class B1 : virtual private A { };
  class B2 : virtual private B1, virtual private A { };       
  class D : public B2 { };
  void f() {
    D d;
    d.i = 0;              // Accessibility error is now issued
  }

10/24/98  CALL_BACK_END_EVEN_WITH_ERRORS

A (user-provided) back end can be called even when there are errors
by defining the configuration flag CALL_BACK_END_EVEN_WITH_ERRORS.
Note that the EDG-supplied back ends will not work correctly
if they are called after errors are detected.

10/23/98  Hidden name tables, macros, and the C++-generating back end

If a macro and a class template have the same name, and the
C++-generating back end is being used, unneeded elaborated type
specifiers could be produced on certain template references.  This
caused problems when the output was compiled with the Microsoft
compiler, where a bug causes spurious errors for certain uses of
elaborated type specifiers.

  template <class T> struct A { };
  struct B {};
  A<B> ab;
  #define A(X) A<X>
  template <class T> struct C {};
  template <> struct C<A(B)>;

10/21/98  Microsoft compatibility: template parameters visible in
          class specializations

The Microsoft compiler makes template parameters visible within the
definition of a specialization of a class template.  This is now
supported in Microsoft mode.

  template <class T> struct A {};
  template <> struct A<int> {
    T t;
  };
  A<int> ai;

10/21/98  Template static data member not instantiated if first referenced
          in a sizeof

A template static data member first referenced in a static data member
would not get instantiated.  This has been fixed.

10/21/98  Template information file not written when there are errors

The template information file (.ti) is no longer written (and any
existing .ti file is removed) if errors occurred during the
compilation.  This is done to prevent the prelinker from attempting
to use a corrupted .ti file.

10/21/98  Recursive instantiation causes compiler loop when using a
          definition list file

Version 2.37 added a "definition list" file that is used to improve
the performance of the automatic instantiation mechanism.  When using
a definition list file, the front end failed to detect an instantiation
loop in function instantiations that are in the process of being
adopted by the current translation unit.  This would result in an
infinite loop and eventual compiler abort.  This has been fixed.

  template <class T> void f(T t) {
    f((T*)0);
  }
  int main() {
    f(37);
  }

10/20/98  Microsoft compatibility: default Microsoft version changed

The default Microsoft version number is now "1200".  This corresponds
to the value of _MSC_VER used with Visual C++ 6.0.

10/20/98  Efficiency improvement in name lookup in the presence of
          namespaces

A change made in 2.34 to fix a problem with namespace directed
operator lookup caused some quadratic behavior in name lookup.
This was only visible in programs with extreme overloading (the
case reported to us has 2,300 friend operator<< functions).
The processing speed is now improved.

10/19/98  Microsoft compatibility: conversion for direct reference binding

The Microsoft VC++ 6.0 compiler will not consider a conversion function
when trying to directly bind a reference if the original expression is
not an lvalue.  This matches a rule in some versions of the Working
Paper that was changed before the final standard.  In Microsoft bugs
mode, we now duplicate that behavior.

  struct A {
    operator int&();
  };
  A f();
  int main() {
    int &r = f();  // Not accepted by MSVC++ 6.0
    return 0;
  }

10/19/98  Microsoft compatibility: ambiguity on conversion rules out argument

The Microsoft VC++ 6.0 compiler treats a function as non-viable if
a conversion on an argument is ambiguous.  What it should do is
keep that function under consideration and issue an ambiguity if
there isn't another function that's better (i.e., one that doesn't
require a user-defined conversion).

  struct A {};
  void f(const char *);
  void f(const A&);
  struct B {
    operator const char*() const;
    operator const A&() const;
    operator A() const;
  };
  B g();
  int main() {
    f(g());  // Should be ambiguous; MSVC++ chooses f(const char *)
    return 0;
  }

10/15/98  Problems if statement stack is resized during switch statement

The code that processes switch statements (switch_statement in
statements.c) kept a pointer to the current entry in the statement
stack over a call to a statement scan routine.  If the statement
stack was reallocated during that call to increase its size, the
pointer was obsolete and using it caused various kinds of problems.

10/13/98  Avoiding &array+n in generated C code

The il_to_str routines have been changed to avoid generating &array+n,
because some compilers have difficulty with the increment size in that case
(since the pointer is a pointer to array, the scaling should be
by the size of the array, but that isn't always implemented correctly).

A related problem when generating pcc-compatible C code has also been
corrected.

10/7/98   Error recovery abort

An error recovery abort occurred on the following code fragment, where
class D was recorded as having a base class even though it was incomplete.
Now fixed.

  class B {
    void operator delete(void *);
  };
  class D : public B;              // Error
  void f(D *p) {
    delete p;                      // Abort here has been fixed
  }

10/5/98   Recursion loop in protected member access checking

The fix for protected member access checking done recently (see Changes
entry of 7/3/98) introduced a recursion loop in some cases.  Now fixed.

10/2/98   Abort in #pragma pack support

When USER_CONTROL_OF_STRUCT_PACKING is TRUE, there was a null-pointer
abort in popping an unnamed entry from the #pragma pack stack (see
Changes entry of 4/5/95).  Now fixed.  For example:

  #pragma pack (push, begin)
  #pragma pack (push, 4)
  struct S {
    char x;
    long y;
  };
  #pragma pack (pop, begin)         // Abort here has been fixed

10/2/98   stat() declaration no longer included in host_envir.h by default

Formerly, a declaration of stat() has been provided in host_envir.h
because some (old) systems did not include a declaration of stat() in
the standard header files.  Including this declaration causes problems
on some systems (for example, Windows NT) that may specify additional
system-specific information in the declaration of stat().  The declaration
of stat() is now only provided if the STAT_DECLARATION_NEEDED macro is
defined.

10/2/98   Incorrect lookup in member template

If a member template was declared within a nested class declared within a
class template, names within the member class template were not looked
up properly.  This has been fixed.

  template<class T1> class A {
    class B {
      template<class T2> class C {
        T1 t1;  // spurious "T1 is undefined" error
      };
    };
  };

9/30/98   Microsoft compatibility: storage class in friend declaration

A bug has been fixed in Microsoft compatibility mode in connection with
specifying a storage class on a friend declaration:

  class A {
    friend static void f();   // this has been allowed in Microsoft mode
    static friend void g();   // ... but this used to get an error
  };

This spurious error has been eliminated.  In addition, if a storage class
other than "static" or "extern" appears on a friend declaration, a
warning (rather than an error) is now issued (and the invalid storage
class is otherwise ignored, as before).

9/29/98   Spurious error on nonreal union member

A spurious "union has a disallowed member function" error was issued
if a union contained a field whose type was a nonreal class.  This
has been fixed.

  template<class T> class A {
    union X {
      typename T::template X<T> x;
      int i;
    };
  };

9/29/98   Constructor initializer lookup

Pending full support for "class name injection", a change in the lookup
of a constructor initializer now eliminates several spurious errors.
Here are a few examples:

  namespace N {
    struct A { A(int); };
  }
  class B : public N::A {
    B() : A(0) { }           // spurious error eliminated: lookup of "A"
  };                         //   is now successful

  struct X { X(int); };
  void f() {
    int X;
    struct S : public X {
      S() : X(0) {}          // spurious error eliminated: lookup of "X"
    };                       //   now finds struct X (which was previously
  }                          //   hidden by the local variable X)

9/28/98   Incomplete types in exception specification

An exception specification that appears other than on a function
definition is now permitted to be an incomplete type or a pointer or
reference to incomplete type.  Except in strict mode no diagnostic is
issued; a discretionary error is put out in -A mode.  On a function
definition a complete type continues to be required in all modes.

  class E;
  void f() throw(E);           // forward declaration -- E need not be
    :                          //   defined yet
  void f() throw(E) { ... }    // still an error if E is incomplete

9/24/98   Microsoft compatibility: redeclaration of template parameters

Template parameters can now be redeclared in Microsoft compatibility mode.

  template <class T> struct A {
    typedef int T;
  };

9/22/98   TARG_ENUM_BIT_FIELDS_ARE_ALWAYS_UNSIGNED

Configuration flag TARG_ENUM_BIT_FIELDS_ARE_ALWAYS_UNSIGNED is now set
to FALSE when TARG_MICROSOFT_BIT_FIELD_ALLOCATION is TRUE (for improved
Microsoft compatibility); otherwise, it is set to TRUE when
CFRONT_OBJECT_CODE_COMPATIBILITY is TRUE; otherwise, the default is now
FALSE.  (Formerly it was unconditionally set to TRUE.)  How this flag is
set can affect whether the value extracted from an enum bit field is
treated as signed or unsigned (i.e., is potentially sign extended or
not).

9/22/98   Enum types larger than "int"

In C++ (except in Microsoft mode) enum types are now permitted to be
stored as integer types larger than "int".  The type selected is the
smallest integer type greater than int that is large enough to contain
the largest of the enumeration constants.

9/22/98   Excessive memory use when using memory mapped PCH files

Version 2.39 introduced a bug that could result in an excessive amount
of memory being used when memory mapped precompiled header files are
used.  This has been fixed.

9/18/98   Duplicate class member using declaration

Duplicate using declarations in a class definition are now reported (see
7.3.3 para 8).  A discretionary error is issued in -A mode, a warning
otherwise, and the redundant declaration is ignored.

9/17/98   Internal error in make_qualified_type

An internal error in make_qualified_type has been fixed; it was caused by
a bug in copy_type_with_substitution, which was failing to recognize a
case in which a qualifier was being added to a function type.  For example:

  template<class T> void f(const T*) { }
  typedef void (FT)(int);
  FT g;
  int main() {
    f<FT>(&g);       // Now an error; formerly an internal error
  }

9/17/98   Accessibility of destructor and copy constructor in handler

The requirement (15.3 para 17) is now enforced that, when a handler
parameter is of class type, the copy constructor and destructor be
accessible in the context of the handler.  (However, in Microsoft mode
the access check on the copy constructor is suppressed.)

9/16/98   Microsoft compatibility: support for __declspec(noreturn)

In Microsoft compatibility mode, "noreturn" is now recognized as a
__declspec modifier.  In addition, "reachability" checking now takes
it into account in issuing various diagnostics (e.g., complaints about
missing return statements).

9/16/98   New diagnostic on implicit return from non-void function

A new diagnostic (ec_implicit_return_from_non_void_function) has been
added for "falling off the end" of a non-void function.  This allows
an implementation or a user to control the diagnostic severity of two
distinct cases independently:

  int f(bool x) {
    switch (x) {
      case false:  return 1;
      case true:   return;   // ec_no_value_returned_in_non_void_function
    }
  }                          // ec_implicit_return_from_non_void_function

In -A mode both diagnostics are now put out as discretionary errors.

9/9/98    Microsoft compatibility: improved support for inheritance kinds

Support in Microsoft-compatibility mode for specifying the inheritance
kinds of classes (which the Microsoft compiler uses to determine the
representation of pointer-to-member types) has been improved:
 -- The default inheritance kind is now __virtual_inheritance (which
    corresponds to the most general pointer-to-member representation,
    instead of __single_inheritance, the most restrictive).
 -- An error is now issued when the inheritance kind for a class (either
    as specified explicitly or as acquired based on the default) is too
    restrictive compared to the actual inheritance of the class.
 -- The C++-generating back end now puts out the inheritance kind on a
    class declaration only when it appears explicitly in the source.

9/8/98    Internal errors when source sequence lists included
          nonclass template instantiations

When GENERATE_SOURCE_SEQUENCE_LISTS was set to TRUE, a configuration in
which NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was TRUE
but CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was FALSE could
produce several different internal errors.  Now fixed.

9/5/98    Missing cast on code for placement delete generated by IL
          lowering

In two cases the code generated by IL lowering did not insert a
cast to "void *" on the first argument passed to an operator
delete routine called to free storage when an exception is thrown
during a "new".  This was probably harmless, but now it's fixed.

9/4/98    Bug in lowering of __uuidof caused IL write/read error abort

A bug in lowering of the Microsoft extension __uuidof caused
an abort in the IL write/read processing in some exceedingly
obscure cases.  Now fixed.

9/3/98    Partial lowering of EH, pointer-to-member comparison, abort
          in lower_expr

A change in 2.39 to optimize the code generated by IL lowering for
pointer to member function comparisons (see entry of 2/8/98) introduced
a bug when partial lowering of exception handling is done and such
a comparison appears in a context that requires a bool.  The
problem manifests itself as an abort in lower_expr.  Now fixed.

9/2/98    Compilation errors in types.c

Several compilation errors occurred in types.c when
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS were not
configured identically.  Now fixed.

9/2/98    Microsoft compatibility: allow __uuidof of template parameter

The processing for __uuidof did not deal correctly with a template
parameter name in the type.  Now fixed.

  template <class T, const GUID* piid = &__uuidof(T)> struct A { };

9/2/98    Microsoft compatibility: ignore case when comparing GUID strings

The comparison for GUID strings on redeclarations in Microsoft mode
now ignores case:

  struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown;
  struct __declspec(uuid("00000000-0000-0000-c000-000000000046")) IUnknown;

9/1/98    Reference initialized to static member function in overload set

The processing to determine which member of a set of overloaded
functions should be used when a reference is initialized did not
work correctly for cases involving static member functions.  Now
fixed.

  struct A {
    static int f(int);
    static int f(short);
  };
  int (&r)(int) = A::f;

8/19/98   Implicit return type on "main"

In C++ mode a diagnostic is now issued on declarations of "main" with no
explicit return type.  A remark is put out by default, and a discretionary
error or warning is put out in strict mode.  To control the error severity
for this case independently of other implicit-int diagnostics, a new error
code is provided: ec_implicit_int_on_main.

8/14/98   Compilation errors in decl_spec.c

Several undefined-name compilation errors occurred in decl_spec.c in a
configuration with GENERATE_SOURCE_SEQUENCE_LISTS set to FALSE and
EXTRA_SOURCE_POSITIONS_IN_IL set to TRUE.  Now fixed.

8/13/98   Abort on lowering bit-field reference in anonymous union

An abort in IL lowering while processing an rvalue bit-field reference
in an anonymous union is now fixed.

  class A {
    union { unsigned int bf : 32;};
    unsigned int f() { return bf; }
  };

-------------------------------------------------------------------------------
Version 2.39, August 10, 1998

8/10/98   IL version number changed to 2.31

8/10/98   Spurious partial ordering ambiguity

Certain unusual partial ordering cases resulted in a spurious error
that more than one partial specialization matches the template argument
list.  This has been fixed.

  struct dummy { };
  template<class A, class B> struct foo { };
  template<class A> struct foo<A,dummy> { };
  template<class T> struct wrapper { };
  template<class A, class B> struct wrapper< foo<A,B> > { };
  template<class A> struct wrapper< foo<A,dummy> > { };
  int main(void) {
     wrapper< foo<float,dummy> > w;
  }

8/8/98    C++-generating back end: template instantiations triggered by
          base specifiers

When  CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE,
the C++-generating back end now puts out better code to represent
instantiations triggered by base specifiers.  The problematic case was
when the instantiation referred to the class whose base classes were being
specified, e.g.,

  template<class T> struct X { };
  struct D : X<D> { };

The generated C++ now includes a forward declaration of the class being
defined when there is such a dependency in the template argument list
of a base class that is instantiated as the base specifiers list is being
scanned.

  template < class T > struct X { };
  struct D;                          // New
  template<> struct X<D > { };
  struct D : public X<D > { };

8/7/98    C++-generating back end: inline virtual function definition missing

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was TRUE,
invalid C++ code was sometimes produced that declared an inline virtual
function without defining it.  This occurred because the generated class
specializations declare inline virtual functions, but definitions are only
provided for functions that are referenced.  The language requires inline
virtual functions to be defined in every translation unit.  This has been
fixed.

8/6/98    C++-generating back end: position of template instantiations
          triggered by default argument expressions within class scope

When TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured to
TRUE, template instantiations are represented by explicit template
specializations.  The standard says such declarations are not allowed
inside the body of a class definition; however, they have to appear prior
to the declaration containing the default argument, and the template
argument can be dependent on a class member.  There is sometimes no way to
resolve these conflicting constraints without causing the C++-generating
back end to put out invalid code.  Here's an example:

  template <class T> int f(T);
                              // Insert "template<> int f(B::N);" here?
  class B {
    static class N { } n;
                              // ... or here?
    void g(int = f(n));
  };

When the C++-generating back end can put out the instantiation of f<B::N>
as an explicit specialization, it can be inserted either in the right
scope or else immediately before the declaration that triggers it.  In
this case, neither strategy produces standard-conforming C++ output.

Global variable instantiations_permitted_in_class_src_seq_list (see
DEFAULT_INSTANTIATIONS_PERMITTED_IN_CLASS_SRC_SEQ_LIST in host_envir.h)
now determines which constraint is given priority.  The default setting is
FALSE, causing the instantiation to float out of the class scope; this
usually results in valid output.  However, if compilable output is not
required or if the generated C++ is to be fed to a compiler that accepts
explicit specializations within class scopes, the other setting might be
preferred.

8/6/98    C++-generating back end: no instantiation directives when
          instantiations are put out as specializations

When source sequence entries for instantiations are configured in, the
C++-generating back end puts out instantiations as specializations.
Now, explicit instantiation directives are suppressed in that mode.
They are not put out because they are unnecessary and invalid -- they
attempt to instantiate something that has been specialized.

8/6/98    Internal error when base specifier triggers template class
          instantiations

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was configured
to TRUE, an internal error could occur when a base specifier triggered
a template class instantiation that in turn triggered additional
instantiations.  Now fixed.

8/6/98    Cast to reference type that can be done directly, versus using
          conversion function

A cast to a reference type that can be done directly (by reinterpreting
an object as a different type) is now done that way even if there is
also a way to do the conversion using a conversion function returning
a reference type.

8/5/98    Order of type check for nonstatic data member

An internal error in set_type_size resulted from performing the type
checking for a nonstatic data member in the wrong order -- the check for
incomplete type is now done before the check for abstract class type.

  class X {
    virtual void f() = 0;
    X x;                  // Priority now given to incomplete type error
  };

8/4/98    Folding of casts on constant addresses

Fewer casts on address constants are now folded in contexts where a
constant is required.  An expression-form cast is generated instead.
This preserves more information about the sequence of casts, and
eliminates some implicit casts in code generated by the C++-generating
back end.  The folding was already suppressed for related-class casts
and reinterpret_casts; now it is suppressed also for casts that merely
adjust cv-qualification.

8/3/98    Spurious error on ctor-initializer in member template

A spurious error was issued if the member name in a ctor-initializer
of member template constructor was also visible as a function name
in the referencing context of the instantiation.  This has been fixed.

  struct A {
    int f;
    template <class T> A(const T& t) : f(t) {}
  };
  void f(){}  // works without this declaration
  int main() {
    A a(23);
  }

8/3/98    Microsoft compatibility: _MSC_VER defined by the front end

In Microsoft mode, the _MSC_VER macro is defined to the current value
of microsoft_version.

8/2/98    p->f(), where f is a static member function: p not cast to base

The standard is not entirely clear on this, but we believe that on a
call p->f(), where the selected function f is a static member function,
p -- which is evaluated but then discarded -- should not be cast to
a base class if the function comes from a base class of p.  This
matters if the cast causes an access or ambiguity error.  Formerly,
the cast was done if and only if f is not an overloaded function.  Now,
it is not done in all cases.

This is related to the changes of 5/29/98.

8/1/98    C++-generating back end: specialization to represent partial
          instantiation put out too soon

When a friend declaration was an instance of a function template and its
type involved the class in which it was declared, a specialization
declaration (to represent its partial instantiation) was being put out by
the C++-generating back end before the class definition, which often
resulted in invalid code.  Now fixed.  Here's an example that used to be
handled incorrectly when compiled with --guiding_decls:

  template<class T> inline void f(T&) { }
  struct A {
    friend void f(A&) { }
  };

This is relevant only in versions configured with
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE.


7/30/98   C++-generating back end: qualifier on function template references

Sometimes the C++-generating back end omitted a required qualifier on a
function template reference, causing it to be hidden by a local
declaration.  Now fixed.

  template <class T> void f(T);
  void f() {
    extern void f(int);
    ::f<double>(0);     // Qualifier is no longer omitted in generated C++
  }

7/29/98   C++-generating back end: bug in optimization to eliminate body
          of unneeded inline member function

The C++-generating back end was sometimes producing invalid output when
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was configured
to TRUE and the elimination of unneeded IL entries was enabled.  (See
Changes entries of 9/23/97 and 11/24/97.)  When a member function defined
inside a class was to be represented in the generated C++ as merely
declared inside the class and defined outside it, and when the member
function body was eliminated because it was unneeded, it sometimes
happened that the out-of-class definition was turned into a declaration
instead of being cleared completely.  Now fixed.

7/28/98   C++-generating back end: missing namespace qualifier on function
          reference

When an overload set of functions was formed to represent the effect of
a using-directive, a bug in hidden-name processing sometimes caused the
C++-generating back end to omit a necessary namespace qualifier on a
reference to a member of that overload set.  Now fixed.

7/28/98   Improvements in inlining

In the processing for minimal inlining, a parameter that is not modified
within the function is now considered constant-valued.  That means when
such a parameter is passed as an argument to an inline function, it
often will not be necessary to create a temporary for it.

In addition, temporaries allocated by inlining are now, where possible,
reused, which can reduce the total number of temporaries required.

7/27/98   Uses of ec_source_file_could_not_be_opened without fill-in

The message code ec_source_file_could_not_be_opened was used in two places
in lexical.c without the required fill-in for the file name.  Now fixed.

7/27/98   Turning off generation of typeinfo variables when RTTI is
          disabled

There is now a configuration flag
SUPPRESS_TYPEINFO_VARIABLES_WHEN_RTTI_DISABLED, which can be set to TRUE
to suppress typeinfo variables when RTTI is turned off (e.g., via
--no_rtti).  That's not the default behavior, because we believe that
allowing changes that have ABI implications to be made via command-line
options makes it too easy to shoot oneself in the foot.  However, many
customers have asked for this, and they are the best judges of what's
right in their product.

7/26/98   Disambiguation problem

Cases like the following were not disambiguated properly, owing to
an incomplete implementation of is_expr_start_token.  Now fixed.

  void main() { (int()) == (int()); }

7/26/98   Reduction of memory use in one-instantiation-per-object mode

Certain kinds of programs, when compiled in one-instantiation-per-object
mode, used more memory than necessary.  The wasted space was in full-size
blocks (i.e., typically 64K) allocated to hold function scope
per-instantiation needed flags, which generally needed much less space
than that.  Now, smaller blocks are allocated in such cases, which can
reduce the overall memory use substantially.  (For one extreme 10,000
line example, memory use was reduced from 28MB to 16MB.)

7/24/98   IL lowering: one instantiation per object mode, new not done in
          constructor: internal error in add_dynamic_init_cleanup

A bug has been fixed in the processing in IL lowering for one instantiation
per object mode.  Compiling the following example with --cfront_3.0,
--exceptions, and --one_instantiation_per_object on a version configured
with NEW_CAN_BE_FOLDED_INTO_CTOR FALSE produced an abort, now fixed.

  struct X {
    X();
  };
  X* x = new X;

7/21/98   Spurious ambiguity error

A spurious ambiguity error sometimes occurred because the final overrider
was not always computed correctly when a class inherited members from its
virtual base classes along more than two paths; now fixed.  For example:

  struct A {
    int i;
  };
  struct B {
    int i;
  };
  struct C : virtual A, virtual B {
    int i;                          // C::i "dominates" both A::i and B::i
  };
  struct D : virtual A, virtual B, virtual C { };
  int f(D *p) {
    return p->i;                    // Spurious error is no longer issued
  }

7/21/98   C++-generating back end, Microsoft compatibility: typedefs to
          circumvent MSVC++ 5.0 bug

The MSVC++ 5.0 compiler gets an internal error on certain uses of
template classes with arguments in default argument expressions, e.g.,
a member function declaration like

  virtual int f(int = X<char>::eof());

The C++-generating back end now generates a typedef and uses it, producing
something like

  typedef x<char> __T12345; virtual int f(int = __T12345::eof());

which does not provoke the abort from MSVC++ 5.0.  A similar change has been
made for template class references in specialization argument lists.

7/21/98   IL lowering: no null test for base-class cast under cast
          used as lvalue

IL lowering suppresses null-pointer-preservation code on related
class casts that appear in lvalue contexts.  If, however, the related-class
cast appears under a cast that adjusts cv-qualification on the pointer,
the optimization was not done.  Now, it is.

7/20/98   C++-generating back end:  hidden-name problem with reference
          to function template instance

The C++-generating back end was failing to use a qualified name when it
was needed on a reference to a template function instance that triggered
an instantiation; now fixed.  For example,

  namespace N {
    template<class T> void swap(T&, T&) { }
    struct list {
      int data;
      void swap(list& that) {
        N::swap(this->data, that.data);  // Now put out correctly in
      }                                  //   generated C++
    };
  }

7/17/98   Instantiations referenced by unnamed namespaces have incorrect
          linkage

A template whose instantiation is caused by a reference from within an
unnamed namespace was incorrectly given internal linkage.  For example,
function "f(A<int>)" in the example below was given internal linkage.
This has been fixed.

  namespace N {
    template <class T> class A {
      friend void f(A);
    };
  }
  namespace {
    N::A<int> a;
  }

7/11/98   C-generating back end: startup code, .init sections, gcc

The gcc compiler has a special declarator, __attribute__((constructor)),
that can be used to indicate initialization routines that must be called
at program startup.  The C-generating back end now generates that
declarator when GCC_IS_C_GEN_BE_TARGET (and the default for
GCC_IS_C_GEN_BE_TARGET is now TRUE when gcc is used to compile the front
end).

Also, the code generated when USE_INIT_SECTION_IN_GENERATED_C is TRUE
is now put inside of the initialization function.  This was done because
newer versions of the Sun ANSI C compiler do not accept asm statements
outside of a function.

Note that a special version of .init code is no longer generated for Linux,
given that gcc is likely to be the compiler used.  If you use Linux,
you should make sure that you do not set USE_INIT_SECTION_IN_GENERATED_C
to TRUE.

7/10/98   Source sequence entries for instantiations: linkage specifications

The processing that inserts source sequence entries for instantiations
(disabled by default) did not work correctly in the sequence of declarations
contained inside a linkage specification block, e.g., extern "C++" {...}.
As a consequence, the source sequence entry for a specialization could be
put out preceding the declaration of its associated template.  Now fixed.

  extern "C++" {
    template <class P> struct traits {
      static int eq(const P& p1, const P& p2) { return p1 == p2; }
    };
    struct traits<char> {
      static int eq(const char& p1, const char& p2) { return p1 == p2; }
    };
  }

7/9/98    Hidden-name problem with friend declarations that refer to
          function template instances

Friend declarations that refer to function template instances were not
handled properly by the hidden-name table processing routines.  This
could result in the use of qualified names in places in which they were
not really needed when using the C++-generating back end.  This has been
fixed.

7/9/98    EH cleanup state, long lifetime temporaries mode, switch clauses

The cleanup state determined in long lifetime temporaries mode at a
switch clause, when the previous switch clause created some temporaries
that were destroyed at the break, was sometimes wrong.  This has been
corrected.

7/9/98    __STDC__ redefinable in non-strict ANSI/ISO C mode

The predefined macro __STDC__ is now allowed to be redefined in
non-strict ANSI/ISO C mode.

7/9/98    C++-generating back end, Microsoft compatibility: qualified
          name in explicit constructor call

The C++-generating back end now uses a fully-qualified name when generating
an explicit constructor call (a Microsoft extension), e.g., "p->A::A()"
rather than "p->A()".

7/7/98    Default for CFRONT_2_1_OBJECT_CODE_COMPATIBILITY now FALSE

In targ_def.h, CFRONT_2_1_OBJECT_CODE_COMPATIBILITY is now FALSE by
default.  If you want it to be TRUE, you'll have to set it in your
defines.h.

7/6/98    IL-to-string routines, forming an lvalue: bit field problem

The IL-to-string routines had a bug in forming a description of an
lvalue in some cases involving a cast of the address of a struct
having a bit-field at the beginning.

  struct A {
    char f1 : 1;
  };
  A a;
  char f(int k) {
    return ((char*)&a)[k];  // Bad C code generated for this.
  }

7/5/98    C++-generating back end, Microsoft compatibility: abort with
          missing declared_type

An abort has been fixed in the C++ generating back end when
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured to
TRUE.  The problem came up in Microsoft compatibility mode when an
explicit specialization directive appeared inside a template body; the
declared_type pointer was not set properly.

  typedef struct _GUID {} GUID;
  typedef GUID IID;
  class _com_error { };
  template<typename _Interface, const IID* _IID  > class _com_IIID { };
  template<typename _IIID> class _com_ptr_t {
	template<typename _InterfacePtr>
            bool operator>=(_InterfacePtr p) throw(_com_error) { }
	template<> bool operator>=(int null) throw(_com_error) { }
  };
  struct __declspec(uuid("00000000-0000-0000-c000-000000000046")) IUnknown;
  typedef _com_ptr_t<_com_IIID<IUnknown, &__uuidof(IUnknown)> > IUnknownPtr;
  IUnknownPtr m_pUnknown;

7/3/98    C++-generating back end: operator function name followed by
          explicit template argument list

The C++-generating back end now puts out a space after an operator function
name when it is followed by an explicit template argument list, to
avoid problems with cases like "operator< <int>".

7/3/98    Access checking for protected members in the presence of
          nondirect virtual base classes

The checking mandated for protected members by section 11.5 of the
standard was not done correctly in the presence of nondirect virtual
base classes.  Cases like the following are now fixed:

  class A {
  protected:
    int p;
  };
  class B: public A {};
  class D;
  class C: virtual public B {
  public:
    D* mp;
    void f();
  };
  class D: public C {};
  void C::f() {
    mp->p = 1;  // Got spurious error previously
  }

6/29/98   Hidden-name problem with function templates

Function templates were not being handled properly by hidden-name
table processing.  This could cause the C++-generating back end to use
the incorrect kind of name reference when referencing an entity hidden
by a function template.  This has been fixed.

6/25/98   C++-generating back end: casts to cv-qualified class type

A previous change (see Changes entry of 12/2/97) made the C++-generating
back end put out old-style casts when constructing cv-qualified class
temporaries.  This has been improved for cases where the constructor
call doesn't take exactly one argument, by using an unqualified
functional-notation type conversion inside the old-style cast, e.g.,
((const X)X(1, 2)).  This may modify the semantics of the program,
because it creates an extra temporary, but that's probably harmless,
and there are no good alternatives.  This comes up on functional-notation
casts to template parameter types, where the deduced type is cv-qualified
and instantiations are put out.  The instantiation has no name for
the cv-qualified type, whereas the original template source can use
the name of the template parameter.

6/24/98   bool_is_keyword was TRUE in Microsoft C mode

bool_is_keyword, which should be FALSE in C mode, was inadvertently
set to TRUE in Microsoft C mode.  Fixed.

6/23/98   Improved management of the declared_type fields

The declared_type field in routine entries (see also entry for 6/16/98)
and secondary-decl source sequence entries now reflects more accurately
the declaration as it appears in the source program.  In particular, it is
the type before parameter type adjustments are made (e.g., array-type to
pointer and function-type to pointer-to-function transformations), and
indicates the default arguments accurately.

6/22/98   IL lowering: keep cv-qualifiers on enk_field node types

IL lowering no longer removes cv-qualifiers from the types of enk_field
nodes (used in field selections).  This is especially desirable in
bit-field selections, like eok_extract_bit_field, where the field
type is the only indication of the "volatile" attribute on the bit field.

6/22/98   Microsoft compatibility: nontype template parameters of pointer
          type

The Microsoft compiler seems to treat nontype template parameters of
pointer type (but not pointer-to-function type) somewhat as if they have
reference-to-pointer type, while still allowing actual arguments that
are rvalues of the proper pointer type.

  template <char *P> struct X {};
  char *p;
  X<p> x;  // Nonstandard, allowed by MSVC++
  char c;
  X<&c> y; // Standard, still allowed by MSVC++

In Microsoft mode, we now do the same.  (Additional change on 7/6/98.)

6/18/98   Generated fall-through goto between switch clauses when switch
          is unreachable

When one switch clause falls into another, the front end generates a goto
from the end of one clause to a generated label at the beginning of the
next.  It failed to do this when the switch statement itself is unreachable.
This was harmless when the C-generating back end is used, but might cause
problems for other back ends.  Now fixed.

  void f() {
    int i = 1;
    goto L;
    switch (i) {
  L:
      case 1: i++;
      // Missing generated goto here
      case 2: i--; 
    }
  }

6/17/98   Spurious error following friend with implicit int return type

A spurious error would result if a friend declaration with an implicit
int return type was followed by a declaration of a member with the
same name as the friend, and a base class also contained a member
with that name.  This has been fixed.

  class A {
    int f();
  };

  class B : public A {
    friend f();
    int f();  // spurious error: "f" has already been declared
  };

6/17/98   Ability to use long double to represent floating point values

Formerly, the floating-point routines provided in float_pt.c used
a host "double" to represent floating-point constants.  If the target
long double was larger than the host double, some constants could not
be represented.  The front end can now be configured to use a host
"long double" to represent floating-point constants by setting the
USE_LONG_DOUBLE_FOR_HOST_FP_VALUE in targ_def.h.  The default is TRUE
when an ISO C compiler is used to build the front end, or FALSE when
a K&R/pcc compiler is used.

When "long double" is used, "sscanf" is used instead of "strtod" to
convert strings into floating point values.  This should not be an
issue, provided the host "sscanf" routine is robust with respect to
precision and handling of values that are out of range.  If the host's
"sscanf" routine is not sufficiently robust it may be necessary to
implement an alternate means of performing the conversion, or to revert
to using "double" to represent floating point values.

6/17/98   Common offsetof variants allowed in nontype template expressions

The common variants of the macro offsetof use operations that aren't,
strictly speaking, allowed in constant expressions.  Previously, the
processing for integral constant expressions had been changed to
allow such expressions in non-strict mode.  Now, the processing for
constant expressions for nontype template arguments has been similarly
relaxed.

6/17/98   C++-generating back end: vacuous destructor calls

The second component of a vacuous destructor call (the part after "::~")
is generated as a simple type name by the C++-generating back end because
class/namespace qualifiers and template arguments should not be included.
This was implemented in a previous change (see Changes entry of 12/4/97).
That change was incomplete, however: if the name is the name of a
typedef that has not yet been put out, the underlying type should be
put out instead of the typedef name.  Now fixed.

6/16/98   C++-generating back end: declared_type on parameters of function
          definitions

When putting out the parameters of a function definition, the C++-generating
back end now uses the declared_type in the parameter variable.  This
declared_type has also been modified slightly so that if the original
specification of the parameter type is a function type (which is
converted to pointer to function) or an array type (which is converted
to a pointer to the element type), the original form is used.

This matters when generating output for MSVC++ 5.0 -- that compiler
gives errors if a parameter in a declaration has a function type and
the parameter in the definition has the equivalent pointer to function
type, or vice versa.  If the declaration is in a template, it is put
out textually, so it matches the source form.  This change ensures that
the definition in such a case (which is not put out textually) also
matches the source form.

6/16/98   Setting parent namespace on forward-declared enum type

A (nonstandard) forward-declared enum type belonging to a namespace scope
was not always handled correctly: when the namespace scope was not the
current scope, the enum type's parent namespace pointer was not being set.
This sometimes resulted in an internal error.  Now fixed.

  namespace N {
    class A {
      void f(enum E);      // E is now marked as a member of namespace N
    };
  }

6/16/98   Spurious error on friend declaration in presence of using-directive

A spurious error would result when a friend declaration that refers to
a template instance refers to a name that names an overload set that
contains functions made visible by a using-directive.  This has been
fixed.

  namespace N {
    template <class T> void f(T,T);
  }
  using namespace N;
  template <class T> void f(T);
  class A {
    friend void f<>(int);
  };

6/16/98   Internal error in lower_type caused by error type as
          template argument

When an overload set contains function templates, a non-matching
template could result in the creation of a template class that has an
error type as a template argument, resulting in an internal error in
IL lowering.  This has been fixed.

  template <class T> struct A { };
  template <class T> A< A<T>::B > f(T, int = 1);
  template <class T> void f(T);
  int main() {
    f(1);
  }

6/10/98   Overload resolution: callability does not figure in viability
          of function

In overload resolution, when an argument has a class type and the
corresponding parameter has the same class type (or a base class
thereof), the callability of the copy constructor is not supposed to
be considered.  Once a function is selected, it must be possible to
call copy constructors on any arguments that need them, but that
should not be considered in deciding which function to call.  This
change reflects a change in the standard; we had implemented an
earlier version that required the callability check during overload
resolution.

This change also eliminates a recursion loop in the front end in some
complicated cases involving template constructors.
          
6/10/98   Integral promotions on bit fields in left operand of compound
          assignment

The integral promotion rules for bit fields were not implemented correctly
for the left operand of compound assignment operators.  This was
visible in operators that do the usual arithmetic conversions on
their operands (e.g., %=): an unsigned int bit field of size less than
int was promoted to unsigned int instead of the correct int, which
could mean that the right-side operand was also converted to unsigned
int when it should have remained int.

  struct s { unsigned int b:7; } x;
  signed char c;
  x.b %= c;  // Right operand was incorrectly converted to unsigned int

6/9/98    Conversion of numbers near FLT_MAX

Floating-point constants with an "f" suffix whose values as written are
slightly larger than FLT_MAX, but which round to FLT_MAX, are now accepted.
Likewise for constants slightly smaller than -FLT_MAX.

6/5/98    Microsoft compatibility: pure specifier on function definition

In Microsoft compatibility mode a pure specifier may appear on a virtual
function definition:

  class A {
    virtual void f() = 0 { ... }    // No syntax error in Microsoft mode
  };

6/4/98    --ii_file_name option should not affect PCH usage

The --ii_file_name option affected whether a given PCH file could be
used by a given compilation, but should not have done so.  This has
been fixed.

6/3/98    Microsoft compatibility: subobject types can be dynamic

MSVC++ allows a placement new call on a member of a class to change the
type of the subobject to a derived class.  (This is not allowed by the
standard.)  When calls are made to virtual functions of that subobject,
they call the functions of the derived class.  The EDG front end did
not have the same behavior, because it has an optimization to do
nonvirtual calls to functions when the dynamic type of the object is
known, and a member of a class has a dynamic type the same as its
static type.  The part of that optimization that deals with field
selection is now disabled in Microsoft mode, to produce the same
behavior as MSVC++.

5/31/98   IL lowering of non-placement new that uses operator new with
          default argument

IL lowering for a non-placement "new" that uses an operator new with
default arguments did not handle the corresponding placement delete
correctly when exceptions are enabled, which resulted in an internal
error.  Now fixed.

  struct A {
    A(void*);
    ~A ();
  };
  struct B {
    B();
    void* operator new (size_t size, int type = 0);
    void operator delete (void* p, int type);
  };
  void f() {
    A r2 = new B();
  }

Also, the lowering for any non-placement "new" that makes use of
default arguments on the operator new is now done as if the operation
were a placement new.

5/29/98   Left operand of p->x evaluated even if x is a static member

The left operand of a member selection "->" or "." is now evaluated
even if the right operand is a static data member or static member
function.  This matches the FDIS.  Previously, we did not evaluate the
left operand, which matched the ARM.

This change fixes an abort when the left operand creates a destructible
temporary.

In a related change, a static selection referring to a set of overloaded
functions, all of which are static, can no longer be used in a context
where a function is selected from the overload set based on the
destination type.  We think cases like that should get an error according
to 13.4 of the standard.

  struct A {
    static void f();
    static void f(int);
  } a;
  void (*pf)() = a.f;  // Formerly accepted, now an error

(8/3/98:) IL CHANGE: in the unlowered IL, static selections are now
represented by new operators eok_points_to_static, eok_lvalue_dot_static,
and eok_rvalue_dot_static.  IL lowering rewrites them as eok_comma
nodes (or as simply the static member reference, if the selector
expression has no side effects).

5/27/98   Microsoft anonymous structs and generated copy assignment function

The code generated for default copy assignment of a class that contains
a Microsoft anonymous struct member was incorrect: it was missing the
field selection for the anonymous struct.  Now fixed.  (Further fix 5/30/98,
for ctor-initializers; further fix 6/15/98)

  struct A {};
  struct B : virtual A {
    union {
      struct {
        unsigned long m : 16;
      };
    };
  };
  B *a, *b;
  void f() {
    *a = *b;
  }

5/25/98   Friend functions definitions removed from template strings when
          function instantiations are generated as specializations

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is
configured to TRUE, the bodies of friend functions defined in class
templates are omitted from the template string that is generated for
the class template.

5/22/98   EH cleanup state problem, implicit conversions on arguments of
          overloaded functions

In calls of overloaded functions with more than one argument, where a
destructible temporary is generated by an implicit conversion in an earlier
argument and a destructible temporary is generated by explicit code
in a later argument, the cleanup state when destroying the temporaries
was wrong.  This could result in destroying a temporary more than once
or not at all if an exception is thrown in a destructor.  Now fixed.

  struct A {
    A(int);
    A(const A& p);
    ~A();
    operator int();
  };
  void f(A, int);
  void f();
  int main () {
    f(1, A(2));
  }

5/21/98   Template-ids in qualified names have incorrect cross-reference
          positions

The cross-reference position for a template-id in a qualified name
was set incorrectly.  This has been fixed.

  template <class T> struct A {
    struct B { };
  };
  A<int>::B ab;

5/21/98   Microsoft compatibility: "bool" implemented as typedef name

In Microsoft compatibility mode (but only for MSVC++ version 5.0 and
higher), the symbol for "bool" is now predeclared as a typedef name in the
global scope rather than treated as a keyword.  This means "bool" can be
declared in other scopes with a different meaning.

  enum Boolean { FALSE = 0, TRUE = 1 };
  void f() {
    Boolean bool = FALSE;          // okay in Microsoft mode
  }

5/19/98   Instances of nonreal member class templates not compared properly

A template such as "X" in "T::X<int>" is considered a "nonreal" template
because it depends on a template parameter type (T) making it impossible
to know much about the template when the reference is scanned.  A bug
in the comparison of two such types resulted in a spurious error on the
example below.  This has been fixed.

  template<class T> struct A{
    A(typename T::template X<int>);
  };   

  template<class T> A<T>::A(typename T::template X<int>){}

5/18/98   Function type involving variable-length-array parameter

When VLA support is enabled, the routine type is now set correctly (see
the Changes entry for 11/1/97) when a function takes a parameter that
(after array-to-pointer decay) involves a multidimensional VLA type.

  int n;
  f(float b[][2][n]) { }
  g() {
    float a[15][2][20];
    f(a+1);
  }

The type of function f is now recorded as "int (float (*)[2][*])"; the
type of parameter variable b continues to be "float (*)[2][n]".

5/13/98   Source sequence entries during prototype instantiation

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured
to TRUE, source sequence entries are now generated during the prototype
instantiation of class templates.  This list is not left in the IL proper,
however; it is attached to the template symbol supplement for the class
template.

5/11/98   Microsoft compatibility: static data member redeclaration

In Microsoft-bugs mode, rules of pointer-to-member compatibility are
relaxed on the out-of-class definition of a static data member.  Here's
an example:

  class A {
    static int A::* p;
  };
  class B;
  int B::* A::p;        // Only a warning in Microsoft bugs mode

5/10/98   Namespace-qualified name should be accepted following "typename"

When the "typename" keyword was added to the language, the name following
"typename" was required to be a template dependent class-qualified name.
This requirement has been removed, but the front end still rejected
namespace-qualified names following the "typename" keyword.  This has
been fixed.

  namespace N {
    template <class T> struct A {};
    template <class T> class B {
      typedef typename N::A<T> A;
    };
  }

5/9/98    Spurious error on inline class template member function in
          strict mode

A spurious "inline function was never defined" error was issued in
strict mode under certain conditions.  The error would occur for
virtual functions that are explicitly declared inline.  This has been
fixed.

  template<class T> struct A {
    inline virtual ~A(){}
  };
  struct B: public A<int> { };

5/5/98    Strange problems with default arguments on constructors with
          exceptions enabled

A problem in default_version_of_routine in lower_init.c caused a
stack variable to be referenced after the end of its scope, which
could cause highly strange and machine-dependent behavior.
Now fixed.

5/5/98    Tweak on workaround for typeinfo destructor pointer problem
          in pre-2.38 ABI

A previous fix (see Changes entry of 12/16/97) on destructor pointers
for thrown objects included a partial fix for those that want to stay
with an older ABI.  An additional tweak to that partial fix has been
made to deal with uninstantiated destructors that are template functions.

5/3/98    Microsoft compatibility: cast of bound function to pointer to
          member function

In Microsoft mode, a bound function can now be cast to a pointer to member
function.

  struct S {
    void f();
  };
  void f(S*p) {
    void(S::*fp)() = (void (S::*)()) p->f;
  }

5/3/98    C++-generating back end: avoid cast on null pointer in default
          argument

The C++-generating back end now puts out a simple 0 for a default argument
expression that is a null pointer, rather than 0 cast to the proper
pointer type.  This optimization avoids a bug in MSVC++ 5.0.

5/3/98    Constant part of nonconstant aggregate initialization dropped
          when exceptions enabled

When exceptions are enabled, there were cases where a constant part
of a nonconstant aggregate initialization would be dropped.  These cases
involve brace-enclosed initialization of the members of a class that has
a destructor, inside some containing aggregate such as an array.
Now fixed.  (5/31/98: additional small fix.)

  struct S {
    S(const char *);
    ~S();
  };  
  struct X {
    int i;
    S s;
  };
  int main () {
    X Mx[1] = {{1771,"test a"}};  // Init to 1771 was not done
    return 0;
  } 

5/2/98    Microsoft compatibility: more cases like long + int ==> int

In a previous change (see Changes entry of 4/22/97), we attempted to match
the Microsoft VC++ 5.0 compiler's behavior in some cases where it gets
the wrong result type on operations involving integers.  A number of
additional cases have been pointed out to us (for example, unsigned int +
long ==> unsigned int), and we have now implemented those as well.

5/2/98    Microsoft compatibility: on array new, operator new considered
          if no operator new[] declared

In Microsoft mode, if no global operator new[] is declared, an array new
with placement arguments will be matched against the declared non-array
global operator new functions.

  void* operator new(unsigned int, const char*, int);
  static char xxx[] = "xxx";
  int main() {
    int* p = new (xxx, 210) int[10]; // Calls non-array operator new
    return 0;
  }

4/29/98   End positions on statements

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the end positions of statements
are now recorded.  See end_position in a_statement.

4/27/98   Microsoft compatibility: define static data member using derived
          class qualifier

In Microsoft compatibility mode a static data member of a base class can
be defined using a qualified name that refers to the derived class.  For
example:

  class B { static int x; };
  class D : public B { };
  int D::x = 0;                // Allowed in Microsoft mode

4/25/98   Calls of virtual functions during subobject construction in
          the presence of virtual base classes (ABI CHANGE)

During the execution of constructors and destructors for base class
subobjects, virtual functions should act as if the complete object has
the type of the constructor or destructor class.  That is, functions in
classes further out than the subobject class do not override during
the subobject construction or destruction.  When virtual base classes
are involved, this means that some virtual function table instances
need to be built reflecting three classes: a class A (whose virtual
function table this is) that is a subobject of a class B (whose
constructor is executing, and which therefore dictates overriding)
that is a subobject of a class C (which is the complete object type,
and which therefore dictates layout).  This is necessary when there
are virtual base classes, and not otherwise, because the "delta"
field in the virtual function table is based on the offset between
the objects for the classes of the overridden and overriding functions,
and that offset varies depending on the type of the complete object.

This has been solved by generating additional virtual function table
instances to be used during subobject construction and destruction,
and having the derived class constructor or destructor pass these
down to the subobject constructors and destructors.  This introduces
a binary incompatibility, which is controlled by
ABI_CHANGES_FOR_CONSTRUCTION_VTBLS.  Constructors and destructors
for classes that have virtual base classes and certain kinds of
overriding of virtual functions now expect, when they are called for
a subobject, to receive a pointer to an array of special virtual
function table pointers.  The pointer to this array is passed down
by storing it in a "transfer pointer", which is a virtual function
pointer or a virtual base class pointer in the subobject.  The
binary incompatibility, therefore, is that if a constructor or
destructor is recompiled and now expects this information, it cannot
be called by a non-recompiled constructor or destructor to construct
or destroy a subobject.  New code can call old code, but not the other
way around.  Fortunately, this means that libraries generally need
not be recompiled.

This problem has been known to us for a while, but it was thought
to come up only very rarely.  Moreover, the front end's deficiencies in
this area came from duplicating cfront's ABI and therefore cfront's
limitations.  Recently, however, we were shown that the problem comes up
more frequently when cfront object code compatibility is turned
off (specifically, in non-cfront mode the layout of classes with
virtual base classes is done in a more efficient and sensible way,
and that difference provokes this problem more often).

(6/11/98: tweak on generated code; an array-to-pointer decay was missing.)
(7/8/98: in front end, mark more virtual functions as referenced when
virtual base classes are present.)

4/23/98   Fixed apparent inconsistency in variable-used-before-set warning

For purposes of used-before-set diagnostics, a variable is no longer
considered to have a value through being default-initialized by an
implicitly declared trivial default constructor.  For example:

  struct A { int i; };
  struct B : public A { int j; };
  int f() {
    A a;
    B b;
    return a.i + b.j;    // Warning now on use of b.j as well as of a.i
  }

Here, a used-before-set warning had been issued on the reference to a.i but
not on the reference to b.j.  There was a technical justification for this
behavior: A is a POD and so is not default-initialized, whereas B (since
it has a base class) is not a POD and therefore is default initialized --
albeit by an implicitly generated trivial default constructor, which by
definition doesn't actually do anything.  This too subtle distinction
is no longer insisted on.

4/23/98   using-directive state not maintained properly in certain cases

Under certain circumstances, the using-directive state is not maintained
properly when a template declared in a namespace is defined later
outside of the namespace.  This can result in spurious lookup errors.
This has been fixed.

  namespace std {
    template <class T> struct B { };
    template <class T, class T2 =  B<T> > struct A { };
  }  

  namespace my_namespace {
    using namespace std;
    template<class T> A<T> g(A<T>&);    
    template<class T> A<T> f(A<T>&);
  }

  template<class T> std::A<T> my_namespace::f(A<T>& v) {return v;}
  template<class T> std::A<T> my_namespace::g(A<T>& v) {return v;}

4/22/98   Access inconsistency on redeclaration of member type

It is a violation of the standard to declare a nested class (or other
member type) with one access and redeclare or define it with another
access.  We used to always issue an error on such redeclarations (except in
cfront-compatibility mode), but with this change we have relaxed the
restriction a bit.  A diagnostic is still issued -- a warning now except in
strict ANSI mode; beyond that, the access associated with the definition is
now assigned to the member type.

  class A {
    struct N;
  public:
    struct N { };      // Warning (or discretionary error in strict mode)
  };
  A::N x;              // Access error is no longer issued

4/21/98   Spurious "not a template" error during disambiguation prescan of
          an initializer expression

A spurious error was issued if an identifier was followed by a less-than
sign in an initializer that participated in an expression vs. declaration
disambiguation.  This has been fixed.

  int main() {
    int i = 1;
    bool b;
    while (int(b = (i < 10))) {  // spurious "i" is not a template
      i++;
    }
  }

4/21/98   Scope with which IL template entries are associated

When RECORD_TEMPLATES_IN_IL is configured to TRUE, the template entries
used to always be added to the templates list of the file scope; this has
been fixed, and they are now added to the templates list of the scope in
which they are declared (which may be the file scope, a namespace scope, or
a class scope).

4/20/98   Microsoft compatibility: predeclared size_t

In Microsoft compatibility mode size_t is now predeclared in the global
namespace.  (Determining the particular integer type to which it is set is
based on how TARG_SIZE_T_INT_KIND is configured; see also the Changes entry
for 2/10/97.)

4/18/98   Internal error on expansion of macro that is unclosed string ending
          in "\"

An internal error has been eliminated on expansion of a macro that expands
to an unclosed string whose last character is a backslash.  This is possible
if the macro definition is given by a command-line option.

4/17/98   Internal error in scan_base_specifier_list

A spurious assertion failure (when GENERATE_SOURCE_SEQUENCE_LISTS and
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS were configured to
TRUE) has been fixed in scan_base_specifier_list.  The problem could appear
when a base specifier reference triggered two or more template class
instantiations, one of which had a template argument involving a class
currently being defined.

  template <class T> class X { };
  template <class B> class Y { };
  class A {
    class N : public X<Y<A*> > { };    // Internal error eliminated
  };

4/16/98   Internal error on pragma in class template nested class declaration

An internal error would occur if a pragma appeared in a class template
declaration in a nested class definition between the class name and
the opening brace of the class definition.  This has been fixed.

  template<class T> struct A {
    class B 
  #pragma test_immediate
      {};
  };
  A<int> ai;

4/12/98   Using IL read routines during IL walk

The routine read_memory_region now saves and restores the global variable
walk_remap_func (which it sets for its own purposes), so that a memory
region can be read during an IL walk.

4/11/98   C++-generating back end: extern "C" definition storage class

In some cases involving extern "C" and const-typed variable definitions,
the C++-generating back end did not put out "extern" and as a consequence
the variable had the wrong linkage.  Now fixed.

  extern "C" const int x = 1;
  extern "C" { extern const int z = 1; };

4/11/98   Improvement in built-in <stdarg.h> support

In the support for built-in <stdarg.h>, it is now possible to specify
a second guard macro to be defined when <stdarg.h> is included,
by setting GUARD_MACRO2_FOR_VA_LIST.  This is useful when more than
one preprocessor macro is used by the host system header files to
avoid multiple definitions of va_list.

4/10/98   Error recovery on missing right brace in aggregate initializer

Error recovery has been improved on a missing right brace in an aggregate
initializer:

  int i[] = {1;  // Error recovery was bad on this case, now improved

4/10/98   Storage class on a condition declaration

In strict mode a diagnostic is now issued if "auto" or "register" is
specified in a condition declaration.

4/10/98   Union with member of reference type

In strict mode an error is now issued if a union member is declared
with a reference type.

4/10/98   Microsoft compatibility: qualifiers are ignored when comparing
          class template argument lists

In Microsoft bugs mode, top-level qualifiers are now ignored when
determining whether a class template argument list matches an existing
instantiation.

In the example "A<B> and A<const B> refer to the same type, which is actually
"A<B>".  "A<const C>" and "A<C>" refer to the same type, which is actually
"A<const C>".

  template <class T> struct A {
  void f(T*){}
  };
  struct B {};
  struct C {};
  int main() {
    A<B> ab;
    A<const B> ab_const;
    const B* b = 0;
    ab.f(b);  // calls f(B*) -- error

    A<const C> ac_const;
    A<C> ac;
    const C* c = 0;
    ac.f(c);  // calls f(const C*)
  }

4/7/98    Microsoft compatibility: allow explicit specification of template
          arguments in specialization declaration

In Microsoft compatibility mode a template function specialization (without
"template<>") is now permitted to include an explicit specification of
template arguments -- for example:

  template <class T> void f(int) { ... }
  void f<int>(int) { ... }                // As if "template<>" preceded

4/6/98    Array rvalue use in C mode

Use of array rvalues in C mode was introduced recently (see Changes
entry of 5/22/97, and bug fix of 10/15/97).  Some remaining problems
with comma expressions and assignment have been resolved.

  typedef struct {
    int w[2];
  } S;
  int main() {
    S u;
    (1, u).w[1];  /* Caused abort */
    (u = u).w[1]; /* Caused abort */
    return 0;
  }

IL CHANGE: this was done by renaming the eok_lvalue_from_call_result
operator to eok_lvalue_from_struct_rvalue, and broadening it to apply
also to struct rvalues produced from constructs other than a function
call.

4/5/98    Microsoft __declspec(property(...)) processing

In some cases, a field selection for a field declared with the
Microsoft extension __declspec(property(...)) was not processed
correctly, and a spurious error was issued.

  struct B {
    __declspec(property(get=getf,put=putf)) short i;
    short getf();
    void putf(short p);
  } b;
  void f(B);
  void f(short);
  int main () {
    f(b.i);  // Got spurious error
  }

4/3/98    Default arguments in the source-sequence representation of
          functions defined within class definitions

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured
to TRUE and a member or friend function is defined within a non-local class
(see Changes entry of 9/23/97), default arguments are now associated with
the in-class declaration (the type recorded in the secondary-decl source
sequence entry) instead of the definition (the type recorded as the
declared_type of the routine itself).  For example, for the following input:

  class A {
    void f(int = 0) { }
  };

the C++-generating back end now puts out:

  class A {
    void f(int = 0);
  };
  void A::f(int) { }

3/31/98   Spurious error in declaring pointer to member function type

An error is no longer issued when a pointer to member function type is
declared using a typedef name to specify the member type.  For example:

  typedef int FT();
  struct X {
    FT X::* pmf;     // Spurious error is no longer issued
  };

3/31/98   dynamic_cast should cause definition of typeinfo

A bug was introduced in 2.37 that could cause linker errors due to
missing typeinfo definitions if a template class with virtual
functions was used in a dynamic_cast but was not otherwise used in a
way that would cause its virtual functions to be instantiated.  This
has been fixed.

3/31/98   Template static data members are only instantiated if referenced

The standard now specifies that the implicit instantiation of a
template static data member should only be generated if the static
data member is used in a way that requires it to be defined.  The
front end now implements the new rule.

3/31/98   Removal of top-level type qualifiers in unprototyped parameter
          lists

When DEFAULT_REMOVE_QUALIFIERS_FROM_PARAM_TYPES was configured to TRUE, an
internal error occurred when an old-style parameter declaration with a type
qualifier was encountered in C++ mode.  (This would be only possible
running with --anachronisms or in Cfront-compatibility mode.)

  void f(x) const int x; { ... }    // Internal error has been eliminated

The problem was that type qualifiers were not being removed from the type
pointed to by the param-type entry for the parameter; now it is, though it
remains on the type for the corresponding variable entry.  This also fixes
a bug in how name mangling is done for functions with old-style parameter
lists.

3/29/98   Indirection through a void * pointer in C++ mode

Indirection through a void * pointer now gets an error in C++ mode.
Formerly, it was handled like in C, where it is valid but does not
produce an lvalue.

3/27/98   Microsoft compatibility: unrecognized __declspec attribute

In Microsoft-compatibility mode a syntax error is no longer issued on
an unrecognized __declspec attribute of the form xxx(yyy).  (See Changes
entry for 12/8/97.)

3/26/98   IL lowering: drop only const on initialized entity reference

When IL lowering generates code to initialize an entity, and the entity
is "const", a cast is added to the entity address expression to
eliminate the "const" so that the address can be used to store into the
entity.  This processing has heretofore dropped all cv-qualifiers, not just
"const".  Now, it drops only "const", thus preserving machine-specific
cv-qualifiers.

3/25/98   any_mutable_member flag in class set too often

The any_mutable_member flag in a class type (added in version 2.38)
was being set if the class has any nonstatic data members, rather
than only if the class has any mutable members.  As a consequence,
the C-generating back end removed the "const" qualifier from most
declarations of class variables.  The flag is now set only when
appropriate.

3/23/98   an_init_pos_descr in c_gen_be renamed

The local structure in c_gen_be.c called an_init_pos_descr has been
renamed a_gen_init_pos_descr because there is an IL lowering data
structure with the name an_init_pos_descr and some source-analysis
tools complain about the use of the same name for two different
local structures.

3/20/98   Microsoft compatibility, C++-generating back end: namespace
          qualified names in bound function reference

A change made previously to suppress qualified names in bound function
references put out by the C++-generating back end in Microsoft mode, to
work around a bug in MSVC++ 5.0 (see item 2 of the Changes entry of
8/25/97), has been extended to cover namespace members as well as
class members.

3/20/98   C++-generating back end: no storage class on condition declaration

Condition declarations do not allow a storage class.  The C++-generating
back end had violated that rule by putting out "auto" on such declarations.
It no longer does.

3/18/98   Cross-reference entry for old-style function parameter declaration

We now put out cross reference entries for the comma-list of names in
old-style function parameter declarations.  For instance,

  void f(i)
  int i;
  { ... }

With this change a declaration entry is now put out for the "i" that
appears between the parentheses (along with the definition entry for the
other occurrence of "i").

3/18/98   Abort on error recovery after bad "else" in C mode

The following case provoked an internal error in if_statement after
a (correct) error diagnostic, when compiled in C mode.  Now fixed.

  void f() {
    if (1) {
    } else
    else {
    }
  }

3/18/98   static_cast of void * to pointer to function, as extension

The front end allows implicit conversion of a pointer to function to
a void * as an extension (this was allowed by the ARM, but is not allowed
by the standard).  The inverse of any implicit conversion should be
allowed as a static_cast, so conversion of void * to pointer to
function is now allowed as a static_cast, as an extension, with a warning.
This is desirable, in part, because the Microsoft and Sun compilers
allow it.

3/18/98   Generated overloaded bitwise operator=

When the user declares an operator=, but not one that can serve as the
default copy assignment operator, in a class that allows bitwise
assignment, a generated default operator= is added to the overload set.
If that function is selected by overload resolution, an assignment is
generated rather than a call.  The code that generates the assignment
had a bug involving cv-qualifiers, which caused an abort in the
C-generating back end for the following example:

  struct A {
    A& operator=(const int& ci);
    A next();
    operator void*() const;
  };
  void foo( A& bar, A& p ) {
    while (p = bar.next()) {}
  }

That is now fixed.  Also, the code generated did not return an lvalue
for the assignment, with the consequence that the following (valid)
program was rejected:

  struct A { int operator=(int); };
  int main () {
    A a, b;
    (a = b) = b;
  }

It is now accepted.

3/18/98   Microsoft compatibility: not allowing call of non-const function
          on const object

The anachronism of allowing a non-const function to be called for
a const object, which has been allowed in Microsoft mode (see
Changes entry of 3/22/96), is no longer allowed when microsoft_version
is greater than or equal to 1000.  MSVC++ 4.2 and 5.0 (correctly) reject
the following program:

  struct A {
    void f();
  };
  int main () {
    const A a;
    a.f();
    return 0;
  }

3/17/98   C++-generating back end: fewer parentheses around lvalues

The C++-generating back end has been changed so that fewer unnecessary
parentheses are put around lvalues.

3/17/98   Constant conditional expressions following a destruction

The change of 11/3/97 related to folding of constant conditional
expressions when ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS is
TRUE (not the default) introduced a bug.  When an expression in
a required-constant context followed something requiring a destruction,
and internal error resulted.  Now fixed.

  struct A { ~A(); } a;
  enum { e = 0?0:1 };

3/12/98   Microsoft compatibility: guiding declaration of template function

In Microsoft compatibility mode, a function declaration that matches a
function template is treated as a specialization even when there is no
definition (unless it appears in a friend declaration).  That means the
definition will not be generated from the template but is expected to be
supplied explicitly -- i.e., its semantics are similar to those of a
new-style explicit specialization.  Example:

  template <class T> void f(T t) { ... }
  void f(int);            // Means the same as "template <> void f(int);"
                          //   in standard C++.

(See related entries from 1/13/97 and 8/20/97.)

3/9/98    Trailing spaces on line in asm function

Trailing spaces on the end of a line inside an asm function were
mistakenly added to the beginning of the following line of the function
in the IL string for the function body.  Now they are kept on the
original line.

3/8/98    Instantiation required flag on pure virtual functions

Some recent changes in setting the instantiation required flag on
virtual functions inadvertently caused the flag to be set on pure
virtual functions.  Now corrected.

3/8/98    IL walk and needed flags, with no lowering of exception handling

The code that walks the IL tree to determine "needed" flags has been
changed to walk object lifetimes.  When IL lowering does no lowering
of exception handling constructs, this change ensures that destructors
referenced from cleanup list entries (and nowhere else) are marked as
"needed" and therefore preserved in the IL tree.

3/2/98    Microsoft compatibility: C++ variable declared as zero-length array

A previous change (see entry for 1/17/97) permitted the following variable
declaration in Microsoft C++ mode:

  char s[];     // treated as implicitly "extern" in Microsoft mode

A bug was introduced at the same time insofar as const-qualified variables
such as

  const char x[] = "abc";
  const char y[];

were also made implicitly extern in Microsoft mode.  They shouldn't have
been.  Both are now treated as implicitly "static", and the second case now
gets the expected error (the definition of a const variable requires an
initializer).

3/2/98    Microsoft compatibility: cast on template argument to remove
          cv-qualifiers

In Microsoft mode, a cast on a template argument that removes
cv-qualification from a pointer type is now allowed.

  struct aaa { int i,j; };
  extern const aaa av;
  template <struct aaa *id> class abcd {};
  abcd<(aaa*)&av> tv;

3/2/98    Code generated by IL lowering for placement array new

The code generated by IL lowering for a placement array new has been
changed to look like

  ((temp = (type *)new-call(...)) != NULL ?
                                 (type *)__vec_new(temp, ...) : NULL)

The change is to add the test for non-NULL around the new-call, thus
preventing the calling of the __vec_new routine if the allocation fails.
(An existing test for non-NULL around existing code that increments
the temporary by the array header size -- not shown above -- has been
eliminated in deference to this new, higher-level test for non-NULL.)

2/27/98   Extra source positions for templates

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, source range information is now
put out for templates (when RECORD_TEMPLATES_IN_IL is TRUE) and for
template instantiation directives (when GENERATE_SOURCE_SEQUENCE_LISTS is
TRUE).  (3/19/98:) The information for template definitions includes
separate range information for the template body.  (4/7/98:) The source
range information is now provided for template function members of template
classes.

2/27/98   Param-type information clobbered on declarations preceding
          routine definition

In certain circumstances, the processing of a function definition would
overwrite information saved to describe a forward declaration; the bug
affected certain fields in param-type entries, and was manifested only when
GENERATE_SOURCE_SEQUENCE_LISTS was configured to TRUE.  Here's an example:

  void f(int i = 10);
  void f(int j) { ... };

2/27/98   Nit in IL lowering in one instantiation per object mode

When the change for local statics described by the 1/12/98 entry
below was done, a new call of
make_statics_referenced_from_instantiations_external was added.
The existing call, in lower_il_memory_region, should have been
removed, and now has been.  As far as we know, the extra call
was not harmful.

2/26/98   Spurious error on explicit specializations and explicit
          instantiations in the presence of using-directives 

A spurious error would result when an explicit instantiation or
explicit specialization references an overload set that includes
names made visible by a using-directive.  This has been fixed.

  namespace N {
    template <class T> void f(T){}
  }
  template <class T> void f(T){}
  using namespace N;
  template void f(int);

2/26/98   One instantiation per object mode: virtual function tables and
          typeinfo variables

In one instantiation per object mode, virtual function tables and typeinfo
variables for polymorphic classes are now assigned to the slice containing
the decider function for the virtual function table, rather than to
the primary slice.

2/26/98   Microsoft compatibility: __declspec permitted on "extern template"
          declaration

A spurious error is no longer issued when a __declspec modifier appears
on an "extern template" declaration in Microsoft compatibility mode.

2/26/98   Microsoft compatibility: bound function converts to pointer to
          member

In Microsoft bugs mode, a bound function expression that is not called
is now converted implicitly to a pointer to member, with a warning.

  struct A {
    void f();
  };
  void g(A *p) {
    void (A::*pmf)() = p->f;  // Allowed in Microsoft bugs mode
  }

2/25/98   IL lowering of aggregate initialization of anonymous union

Aggregate initialization of an anonymous union field was not handled
correctly in IL lowering.  The following case, now fixed, created
invalid IL, which if run through the C-generating back caused an
internal error in dump_field_from_second_operand:

  struct X {
    union { unsigned long y; };
  } x;
  void f(unsigned long p) {
    X v = { p };
  }

2/24/98   C++-generating back end: output of 64-bit constants in Microsoft
          mode

In Microsoft mode, the C++-generating back end now puts out 64-bit
integer constants in a form like 1i64 (or 1ui64 for the unsigned version).
Formerly, it put them out with a form like 1LL (or 1ULL), which the
Microsoft compiler does not accept.

2/23/98   Spurious error on specialization of static data member

A spurious "incomplete type not allowed" error would occur if a static
data member was defined in an explicit specialization declaration with a
type that is a template class that has not yet been instantiated.  This
has been fixed.

  template<class T> struct A {
    A(int i);
  };
  template<class T> struct B {
    static A<T> x;
  };
  template<> A<int> B<int>::x(1);

2/20/98   Compilation problem in lower_il.c with BACK_END_IS_C_GEN_BE set to 0

When BACK_END_IS_C_GEN_BE is set to 0, lower_il.c did not compile correctly
due to a missing #if surrounding move_class_promoted_local_types.
This problem was introduced in version 2.38.

2/18/98   Microsoft compatibility: L#param to produce wide string literal

In Microsoft mode, the idiom L#param is now accepted as requesting
a wide string literal for the value of the indicated macro parameter.

2/17/98   Microsoft compatibility: invalid explicit instantiation and
          "extern template" directives

The Microsoft compiler permits explicit instantiation directives and
Microsoft "extern template" directives even when there is no template
that matches the specified instance.  We now support this in Microsoft
mode.

  struct A {};
  template <class T> int operator >>(T,T*);
  extern template int operator <<(A,A);  // No operator << visible
  extern template int operator >>(A,A);  // No matching operator >>

2/17/98   Small bugs in supplying source range information

A number of small bugs have been fixed in supplying source range
information when EXTRA_SOURCE_POSITIONS_IN_IL is TRUE.  They involved:
  -- non-standard enum declarations
  -- bit-field declarators
  -- identifier of a conversion function
  -- a "vacuous" class declaration that follows the class's definition
  -- a typedef redeclaration (2/27/98)
  -- address of ellipsis (e.g., &...) (3/9/98)
  -- range for mem-initializer now includes field/base-class name (3/19/98)
  -- variable entry for old-style parameters (5/21/98)
  -- expressions for condition declarations (7/7/98)

2/16/98   Access check on elided constructor in strict mode

A change in the processing for copy-initialization, made in version 2.38
(see entry for 1/5/98), accidentally dropped a required access check
on an elided copy constructor in strict mode in some cases.  The check
has been restored.

  class T {
    T(const T&);
  public:
    T(int);
  };
  T x = T(1);  // Should get error in strict mode: T::T(const T&) is private

2/13/98   Local static character array initialized to string in extern inline

The change made on 12/22/97 to fix a problem with initialization of
local static arrays in extern inline functions broke the processing
when the initial value is a string literal.  Fixed, again.

  extern inline void f() {
    static char s[] = "abcd";
  }
  int main () {
    void (*pf)() = f;
  }

2/11/98   Improvement in code generated for call of function returning
          class by value

The code generated by IL lowering for a function call that returns a
class by value (i.e., the class has no copy constructor), where the
address of the returned value is not taken, no longer uses a temporary.

  struct X { };
  struct X x, f();

  x = f();  // No longer uses a temporary

2/8/98    Improvement in code generated by IL lowering for pointer to
          member comparisons

The code generated by IL lowering for pointer to member function
comparisons has been improved.  In particular, when one of the
operands is a constant, the code no longer creates a temporary
variable containing the value of the pointer to member constant.
Simpler code is also generated now for several special cases,
including a comparison against a null pointer to member constant.

2/8/98    Reachability of end of block that is body of loop with continue

The IL block statement contains an end_of_block_reachable flag.  In some
cases where a continue label is added at the end of a block that is the
body of a loop, the flag was FALSE even though the end of the block
is reachable via a transfer to the continue label.  This problem
came up only if the block contains no declarations.

void f(int *record) {
  while (1) {
    if (*record == 0) break;
    switch (*record++)  {
      case 1:
        continue;
      default:
        continue;
    }
    // continue label is inserted here, but end of block was not marked
    // as reachable.
  }
}

2/7/98    Minimal inlining: address of function as argument considered
          constant

The address of a function, passed as an argument to an inline function,
is now considered a constant, and the expansion done by minimal inlining
uses it directly instead of storing it in a temporary variable and
using that.

2/7/98    Minimal inlining: source positions on more code

Minimal inlining now inserts the source position on a few pieces of
generated code where it had not been set previously, e.g., assignments
that initialize temporaries that replace parameters.  This produces
slightly better line number information in symbolic debugging output.

2/2/98    Microsoft compatibility: #import

The #import preprocessing directive is now supported in Microsoft mode.
Our implementation depends on the fact that the Microsoft compiler
generates a header file (with a .TLH suffix) in the object directory
when it processes an #import directive.  We treat #import as an #include
of the previously-generated file.  The directory for such files can
be specified via the --import_dir command-line option.

1/31/98   Extra source position information on prefix incr/decr and
          field selection

The extra source position information (controlled by
EXTRA_SOURCE_POSITIONS_IN_IL) was wrong for expressions for prefix
increment and decrement (e.g., --x), member selection (e.g., a.b),
and pointer-to-member selection (e.g., a.*b).

1/31/98   Temporary destroyed more than once on break from loop with
          long lifetime temporaries

When long lifetime temporaries are used, the code generated by IL
lowering for a break out of a loop destroyed temporaries in some cases,
which is incorrect and could have resulted in more than one destruction
of a temporary:

  struct A {
    A();
    ~A();
  };
  void f(A);
  void g(A a) {
    f(a);  // Makes temp
    for (int i = 0; i < 10; i++) {
      if (1) {
        break;  // Should not destroy temp, but did
      }
    }
    return;  // Should destroy temp
  }

1/30/98   Lookup errors caused by interaction of templates and namespaces

A bug in the manipulation of the scope stack when instantiating templates
while using namespaces could result in spurious undefined symbol errors.
This has been fixed.

  template <class T> class X {};
  namespace N1 {
    namespace N2 {
      class A {};
    }
  }
  namespace N1 {
    namespace N2 {
      namespace N3 {
        using namespace N1::N2;
        class B {
          X<int> x;
        };
        A f(); // Spurious error on this line
      }
    }
 }

1/29/98   Microsoft compatibility: constant field selection in constant
          expression

In Microsoft C++ mode, a field selection that produces a constant is
now allowed in an integral constant expression.  For example:

  struct A { enum { e1 = 1 }; };
  int main () {
    A a;
    int x[a.e1];  // Accepted by MSVC++ 4.2 and 5.0
    return 0;
  }

1/25/98   More temporaries reused in IL lowering

Temporaries needed for enk_temp_init nodes are now allocated as
reusable temporaries when possible.  (See Changes entry of 12/30/97.)

1/23/98   Internal error on static generated function in one-instantiation-
          per-object mode

In one-instantiation-per-object mode, static variables and functions
are sometimes made external so instantiation objects can refer to them.
They are given mangled names beginning with __STV__ or __STF__.
An abort occurred when this processing was applied to a generated
routine (which has no name).  Now, an appropriate mangled name is
generated.

1/20/98   Internal error in type deduction when a function template
          declaration includes nontype member of a dependent class

An internal error would occur if a function template declaration made
use of a nontype member of a dependent class, such as A<T>::X in the
example below.  This has been fixed.

  template<class T> struct A {
    static const int X = 1;
  };
  template <int I> struct B {};
  template<class T> B<A<T>::X> f();
  int main () {
       f<int>();
  }

1/19/98   type_of_unknown_templ_param_constant not saved in PCH file

The variable type_of_unknown_templ_param_constant should have been
saved as part of a precompiled header file, but was not.  This could
cause problems if the value in the translation unit in which the PCH
file was used differs from the one in which the PCH file was created.
This has been fixed.

1/19/98   Microsoft compatibility: unnamed enumerations as template parameters

The Microsoft compiler permits unnamed template parameters to be used
as deduced template parameters of function templates.  We now support
this in Microsoft mode.

  template <class T1, class T2> void f(T1, T2);
  enum { e = 0 };
  int main() {
    int i = 0;
    f(i, e);
  }

1/18/98   Microsoft compatibility: return and "="-form declaration
          initialization is direct-initialization

The Microsoft VC++ compiler 5.0 seems to treat the initialization in
a return statement and a declaration with an "="-form initialization
as direct-initialization (instead of the correct copy-initialization).
We now do the same in Microsoft mode.

  struct A {
    operator const char*() ;
  };
  struct B {
    B(const char*) ;
  };
  B f(A a) {
    B x = a;   // Accepted in Microsoft mode
    return a;  // Accepted in Microsoft mode
  }

1/18/98   IL lowering temporaries allocated in innermost braces

When IL lowering creates temporaries, it puts them in the innermost
enclosing scope.  To date, this has only considered scopes that were
otherwise present in the IL.  Now, all brace-enclosed compound
statements are considered; an IL scope is added to the innermost
one if necessary.  In some cases, this allows temporaries to be
allocated over smaller regions, which allows better overlapping of
temporaries, and a reduction in stack space use.

1/16/98   Missing virtual function definitions

In spite of some recent changes in this area (see 11/14/97 Changes
entry), there were still some cases where virtual functions were
not instantiated when needed.  The cases were ones where the file
in which the definition of the first non-inline non-pure virtual
function of a class appears does not also have a definition of a
constructor or destructor for that class.  Now fixed.

1/15/98   Internal error on PCH file that ends with stdarg.h

An internal error would occur when <stdarg.h> is the last file
included in a precompiled header file and <stdarg.h> is treated as
a built-in (i.e., pass_stdarg_references_to_generated_code is TRUE).
This has been fixed.

-------------------------------------------------------------------------------
Version 2.38, January 13, 1998

1/12/98   IL version number changed to 2.30

1/12/98   Microsoft compat: declspec modifiers on class template declarations

The Microsoft declspec modifiers that are allowed on class declarations
are now also allowed on class template declarations.

  template <class T> class __single_inheritance A {};

1/12/98   Composite routine type formation when one or both types are
          unprototyped definitions

In C mode a bug in forming composite routine types has been fixed.  It
turned up in two cases in which at least one of the routine types was
unprototyped:

  int f(int);
  typedef int INT;
  INT f(p) unsigned short p; { return p; }     /* Spurious error */

  void f1(i,j) int i, j; {}
  void f2(i) int i; {}
  void g(int i) { i ? f1 : f2; }               /* Internal error */

1/12/98   Internal error on pragma in template declaration

An internal error could occur if a pragma appeared between the template
parameter clauses (e.g., "template <...>") and the declaration in a
template declaration.  This has been fixed.

  template <class T>
  #pragma test_immediate
  struct A  { };

1/12/98   One-instantiation-per-object mode: local statics

In one-instantiation-per-object mode, a local static entity which
is supposed to be made external so it can be referenced from an
instantiation object file sometimes was not, which would cause
link errors later.  Now fixed.

  extern "C" int printf(const char *,...);
  typedef void (*TD)();
  static void foo() {printf("foo\n"); }
  template <class T> class X { public:
    static TD td;
    void f(const T t);
  };
  template <class T> TD X<T>::td = foo;
  template <class T> void X<T>::f(const T t) {
    printf("f(const T) called\n"); td();
  }
  TD bar = X<int>::td;
  int main() {
    bar();
    X<int> x;
    x.f(6);
  }

1/10/98   Class name lookup in routine friend declaration

A spurious error was put out on the following because the special lookup
for friend declarations was incorrectly done on the class name "C" in the
friend declaration of g:

  class C { } c;
  namespace N {
    class X {
      friend class C g() { return c; }  // Incorrect lookup of "C"
    };
  }

The spurious error (invalid type on return value) followed from interpreting
the return type of X::g as N::C instead of ::C.  Now fixed.

1/9/98    Order of template specialization entries in source sequence during
          instantiation wrapup

During the instantiation wrapup phase, when GENERATE_SOURCE_SEQUENCE_LISTS
and NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS are
configured to TRUE, a function template instantiation triggered within
another function template instantiation will always be represented as
preceding the referencing instantiation in the source-sequence list.  For
instance:

  template <class T> inline void f(T t) { }
  template <class T> void g(T t) { f(t); }
  main() {
    g(0);
  }

In this example, the source-sequence entry representing the instantiation
of f<int> used to follow the entry for g<int> but now precedes it.

1/9/98    Microsoft compatibility: extern template directive that references
          a class template that is declared but not defined

As an extension, the Microsoft compiler accepts "extern template" as
a directive to suppress the instantiation of the specified entity.  The
Microsoft compiler permits an incomplete type to be specified (with a
warning).  We now issue a warning instead of an error for this case, but
still ignore the directive when the class type is incomplete.

  template<class T> class A;
  extern template class A<char>;

1/9/98    Internal error in hidden-name-table support

When RECORD_HIDDEN_NAMES_IN_IL is configured to TRUE (e.g., for the
C++-generating back end), an internal error could occur when a tag name
namespace member was hidden by a non-tag namespace member and the namespace
was specified in a using-directive in a containing scope.  Now fixed.

  namespace N {
    class A { };
  }
  using namespace N;
  namespace N {
    void A();         // No longer aborts when updating hidden-name table
  }

1/8/98    Block generated for dependent statement in C++ mode

In C++ mode when a dependent statement (e.g., for an if-statement) is not
enclosed by braces, the compiler generates a block statement anyway.  With
this change, the statement position on the generated block statement is no
longer set, which has the effect of marking the block as generated by the
compiler.

A related bug (when GENERATE_SOURCE_SEQUENCE_LISTS was TRUE) was that no
end-of-construct source-sequence entry was put out to terminate the
source-sequence entries for the generated block; this has also been fixed.

1/7/98    cfront 2.1 mode: in a.b, cv-qualifiers on a are ignored

In cfront 2.1 mode, any cv-qualifiers on the left operand of a
field selection (a.b or p->b) are now ignored, i.e., the type of
the result is just the type of the member selected.  Some code
that did a weaker version of this on reference initialization
in cfront 2.1 mode is now superfluous and has been removed.

1/5/98    Change in copy-initialization rules to support auto_ptr

The definition for auto_ptr accepted for the C++ standard depends on
a quirk of the definition of copy-initialization for classes that
we did not implement.  It is now implemented.

To make this quirk work right, the anachronism that allows binding
a reference to nonconst to a class rvalue must be disabled, so the
default value of DEFAULT_ALLOW_NONCONST_REF_ANACHRONISM has been
changed to FALSE.  The anachronism continues to be enabled in cfront
and Microsoft C++ modes.

1/5/98    Microsoft compatibility: improved handing of __asm blocks

In some cases the front end did not correctly handle Microsoft __asm
blocks in which the opening brace of the __asm was not on the same line
as the "__asm".  The problem would only occur in contexts in which
the function containing the __asm was cached and rescanned, such as
member functions and function templates.  This has been fixed.

1/3/98    EH cleanup state in partially constructed aggregate

The exception handling cleanup state when an exception is thrown
in the middle of a partially constructed aggregate was not correct
in some cases when the class involved allows bitwise copying
(i.e., it has no user-written copy constructor) but has a destructor.

  struct A {
    A(int);
    ~A();
  };
  int main () {
    try {
      A z[3] = { A(1), A(2), A(-1) };  // Cleanup state wrong if exception
                                       // thrown during construction of
                                       // z[2]
    } catch(...) {
    }
  }

12/30/97  IL lowering: reuse of some temporaries

IL lowering now frees and reuses some of the temporaries it generates.
This is helpful in reducing stack use, particularly in code that contains
many uses of pointers-to-member-functions.

12/29/97  Internal error on old-style specialization definition

An internal error would occur if an old-style definition of a given
function template specialization followed a friend declaration that
referred to that specialization.  This has been fixed.

  template <class T> void f(T);
  struct A {
    friend void f(A);
  };
  void f(A){ }

12/23/97  Instantiation request file closed before being deleted

When an instantiation request file is deleted, it is now closed before
being deleted instead of being closed after the file was deleted.
Closing the file after it had been deleted could cause an abort on
some systems.

12/22/97  Local static array initialized to constant in extern inline function

The transformation done by IL lowering in turning the initialization
of a local static variable initialized to a constant inside an
extern inline function into executable code (so that the variable,
promoted to external, is a tentative definition) failed when the
variable was an array.  Now fixed.

  extern inline void f() {
    static int i[2] = {0, 0};
  }
  int main () {
    f();
  }

12/19/97  C_generating back end: inefficient code for pointer-to-member-
          function call

In some cases, the code generated by IL lowering for pointer-to-member
function calls caused the C generating back end to generate inefficient
code (because of the rewrites done for rvalue field selections).
This has been improved and the generated C now avoids generating
and using superfluous temporaries.

12/17/97  Bug in freeing rejoined memory blocks

Due to a bug in free_mem_block, when partial memory blocks are freed
and reassembled into a full memory block they were not freed back to
the operating system.  They were, however, properly kept on the list
of available memory blocks, so the impact was minimal.

12/17/97  Integral promotion on long wchar_t when sizeof(long) == sizeof(int)

If wchar_t is defined as long (or unsigned long), and sizeof(long) ==
sizeof(int), wchar_t is supposed to promote to int (or unsigned int).
This is a quirk of the C++ standard, but since we're pretty sure now
that the quirk will not be fixed, we've implemented it.

  #include <stddef.h>
  void f(int) {}
  void f(long);
  int main () {
    wchar_t w = 0;
    f(w);  // If wchar_t is long, and long == int, should call f(int)
  }

12/16/97  Test whether functions of template class are inline, as part
          of decision to generate virtual function table definition

The decision on generating the definition of a virtual function table is
based on the first non-inline non-virtual non-pure member function of
the class.  The test of member functions of a template class falsely
concluded that any member function that is only partially instantiated
is not inline.  Ordinarily, this makes no practical difference, but in
some cases involving type_info entries (e.g., exception specifications
and typeid), it could result in an unresolved external at link time.

  template <class T> struct A {
    A() {}
    virtual ~A() {}
  };
  void g() throw(A<int>) {}
  int main () {
    g();
  }

12/16/97  Ordering problem in generated C code, local class with template
          base

When C code is being generated, if a local class of a member function
has a base class that is a template class, the order of the types in
the generated C could be incorrect and cause a compilation error.
Now fixed.

  template <class T> struct A {};
  struct B {
    void f() {
      struct C : public A<int> { int i; ~C() {} } c;
      c.i = 1;
    }
  } b;
  int main () {
    b.f();
  }

12/16/97  Destructor for thrown object

When an object of a destructible class type is thrown, the runtime is
responsible for calling the destructor once the object is no longer
needed.  To date, this has been done by having a pointer to the
destructor in the runtime typeinfo structure, and having the runtime
use that to determine whether a destructor call is needed.  There was
a bug in this area: when a class has a user-written destructor,
and a given compilation has a throw of that class and has a declaration
but not a definition of the destructor, a null pointer was put into the
typeinfo structure, with the consequence that the destructor was never
called for the thrown object.

The bug was a consequence of trying to avoid generating a destructor
merely to be able to put a pointer to it into the typeinfo structure.
The full solution involves eliminating the destructor pointer in
the typeinfo structure by passing a destructor pointer on the throw
setup call (this necessitates a new runtime routine __throw_setup_dtor).

However, for those who cannot accept an ABI change at this time, we
have also fixed the old implementation so that it does not ever put
in a null pointer for a user-written destructor, and so that it defines
a compiler-generated destructor in cases where a typeinfo entry will
be put out.  This is not a perfect solution with respect to standards
conformance, but it's acceptable from a practical point of view.
This partial fix is selected when ABI_COMPATIBILITY_VERSION is less
than 238.

IL CHANGE: a destructor pointer has been added to a_throw_supplement.

12/12/97  Bug in lookup of "p->f<..."

When the name in a class member access is both a member name and the name of
a global template, version 2.37 was incorrectly using the global template.
This has been fixed.

  template <class T> void f(T);
  struct A {
    static int f;
  };
  int main() {
    A a;
    return a.f < 1;
  }

12/11/97  Obscure bug in minimal inlining

A change made recently (Changes entry of 12/2/97), which added an
optimization in inlining, uncovered an existing bug, which relates to
expansion of a constructor call that calls an inline "new" that
returns a constant address (that happens in test cases, but is unlikely
to happen in real programs).  The symptom was an IL reference to a
temporary variable that did not appear on the list of local variables.

12/10/97  Microsoft compatibility: non-standard "anonymous struct" in C++

In Microsoft C++ compatibility mode, a struct with a compiler-generated
trivial default constructor was incorrectly seen to violate the requirement
that an "anonymous struct" have no member functions.  Now fixed.

12/10/97  IL lowering of exception handling: destructor pointer in typeinfo

When IL lowering builds typeinfo variables, it sometimes puts in
a null pointer for a declared-but-not-defined destructor, to deal with
cases where a typeinfo is generated for a throw-specification but
the destructor is not actually used and therefore no definition is
required.  This processing did not work right when the class
has a user-written destructor that is declared but not defined in
the compilation that generates the typeinfo variable.  As a
consequence, the destructor for the class was not called to clean
up objects of that type when an exception was thrown.

12/8/97   Branching into a try-block in Microsoft bugs mode

Branching into a try block is now permitted in Microsoft bugs mode.
A warning is issued.

12/8/97   Unrecognized __declspec attribute in Microsoft mode

In Microsoft-compatibility mode a warning is now issued (instead of an
error) when an unrecognized __declspec attribute is encountered.

12/8/97   IL CHANGE: additional source position information

When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, additional source position
information is now maintained in the IL.  This includes range information
on expressions (the start and end positions of each expression node) and
declarations (the start and end positions of declaration-specifier
tokens, of declarators, and of initializers).  Note that this information
can take a lot of extra space, so you shouldn't enable this feature
unless you really need the extra positions.

12/4/97   Comments in Microsoft asm statements

Comments in Microsoft asm statements are now discarded.  Previously,
delimiters, such as braces, in Microsoft asm statements could cause
parsing problems.

12/4/97   C++-generating back end: vacuous destructor calls

The "destructor name" part of a vacuous destructor call should not be
a qualified name, but the C++-generating back end was putting it
out that way sometimes.  Now fixed.

  struct A {
    typedef int I;
  };
  void f() {
    A::I *p = new A::I;
    p->A::I::~I();  // Output was wrong previously
  }

12/3/97   Code for generated bitwise operator=

Generally, if a class allows bitwise assignment, no operator= function
is generated.  However, if the address of the operator= function is
taken, a definition is needed.  The code generated for such a definition
was missing an indirection on the source operand, and therefore it
did not work correctly.  Now fixed.

12/3/97   Turning off Microsoft mode

When Microsoft mode is enabled, either by default or by a command-line
option, a number of other optional features are implicitly enabled
or disabled.  For example, wchar_t_is_keyword is disabled and old-style
specializations are enabled.  However, if Microsoft mode was disabled by
a command-line option, the related features were still being set as if
Microsoft mode were being used.  This has been fixed.

12/2/97   C-generating back end, C++-generating back end: line correspondence
          when short include file contains no declarations

When a short (<= 3 lines) include file containing no declarations (or
no needed declarations) is processed, and code is generated by the
C-generating or C++-generating back end, the line correspondence could
be off by a few lines.  Now fixed.

12/2/97   Type of temporary created on cast to cv-qualified class type

The type of temporary created on a cast to a cv-qualified class type
should be the cv-qualified type.  Instead, if the temporary was created
by calling a constructor, the cv-unqualified class type was used.

  struct A {
    A();
    void f();
  };
  int main () {
    typedef const A CA;
    CA().f();  // Should be an error; now, it is
  }

A similar issue comes up with typedefs of a class type in the C++-generating
back end.  Now, a temporary of the typedef type (instead of the class
type) is created, which avoids some naming errors in the generated code.
This prompted another change: casts to cv-qualified class type are now
put out in old-style cast form, since something like "const A(x)" is
not a valid functional-notation cast.

12/2/97   Inlining of constructor calls on cv-qualified objects

The minimal inlining feature now generates better code on calls of
constructors for objects that are cv-qualified.

12/2/97   Setting the maximum recursive instantiation depth

The front end limits the depth of recursive instantiations so that
infinite instantiation loops can be detected and a diagnostic issued
before some resource limit (e.g., available memory) is exhausted.
The limit has been changed from a configuration parameter to a global
variable whose value can be set using the --pending_instantiations
command-line option.  In addition, the default has been increased from
17 to 64.

The default value is specified by DEFAULT_MAX_PENDING_INSTANTIATIONS.
If no value is supplied for DEFAULT_MAX_PENDING_INSTANTIATIONS, and a
definition is provided for the old configuration value, which was
named MAX_PENDING_INSTANTIATIONS, that value is used as the default
value of DEFAULT_MAX_PENDING_INSTANTIATIONS.

12/2/97   Limiting the number of simultaneous instantiations

The front end now limits the number of simultaneous function
instantiations that are performed.  This is used to limit the amount
of memory used for memory regions while generating instantiations.
When a function instantiation begins, a new memory region of
HOST_ALLOCATION_INCREMENT bytes (65536, by default) is allocated.
Most of the memory region will later be made available for reuse, but
the available memory can sometimes be exhausted if a program causes a
large number of concurrent instantiations to be performed.  The limit
is specified by the MAX_TOTAL_PENDING_INSTANTIATIONS configuration
parameter.  The default is 256.

11/27/97  C-generating back end: const classes with mutable members

The C-generating back end now suppresses "const" on definitions of
variables with const class type, where the class type has a mutable
member.  This prevents the underlying C compiler from putting the
variable into read-only storage.

IL CHANGE: the a_type entry variant for classes now contains a field
any_mutable_member, similar to the existing any_const_member.

11/27/97  Inlining of function containing char array initialized to string

When MINIMAL_INLINING is enabled, an attempt to inline a function that
contains a character array variable initialized to a string produced
an internal error in which_binary_operator.  Now fixed.

  inline void f(int) {
    char a[32] = "";
  }
  void g(int n) {
    f(n);
  }

11/26/97  Nondeduced contexts in partial specializations

In version 2.37, template argument deduction was modified to handle
"nondeduced" contexts as described in the draft standard.  A bug was
introduced that could cause a partial specialization containing
nondeduced contexts to be used when it should not have been.  This has
been fixed.

  template <class T1, class T2> struct A { };  // #1
  template <class T> struct A<T, T::C> { };  // #2
  struct X {
    struct C {};
    struct D {};
  };
  A<X, X::D> x;  // Should use #1

11/24/97  C-generating back end: struct in prototype scope with
          definition_needed FALSE

The C-generating back end did not deal correctly with a struct or
union defined in a prototype scope in C, when generating ANSI C
output, if the definition of the class was not needed.  Now fixed.

  void f() {
    void (*pf) (union { union { enum X {x1} *x; } i2; } (*)) = 0;
    pf = 0;
  }

11/24/97  C++-generating back end: putting out qualified names

Previously, the C++-generating back end almost always put out references
to class and namespace members with qualified names.  Now it puts out
qualified names only when they are required to defeat name hiding.  (This
has entailed substantial changes to how the hidden-name table is built as
well as changes in cp_gen_be.c itself.)  For example:

  class A {
    class N {
      int f();
      static int x;
    };
  };
  int A::N::f() { return ++x; }

Before, the reference to "x" was put out as "A::N::x" in the generated
C++, which resulted in an access error.  Now it is put out simply as "x".

11/24/97  C++-generating back end: qualified names for extern "C" entities

The C++-generating back end now puts out qualifiers on references to
extern "C" entities when they are needed.  For example:

  namespace A {
    int f();
  }
  namespace B {
    extern "C" int f();
  }
  using namespace A;
  int g() {
    return B::f();
  }

Before, the call in g was put out simply as "f()" in the generated C++,
which meant the wrong function was called.  Now it is put out as "B::f()".

(11/27/97:)  An additional fix, for cases like

  namespace A {
    typedef unsigned I;
    extern "C" void *f(const void *, int, I);
  }
  namespace B {
    extern "C" void *f(const void *, int, A::I);  // A::I was put out as I
  }

11/24/97  C++-generating back end: internal error when unneeded entities
          are eliminated

An internal error could occur when (1) the C++-generating back end is
used, (2) NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is
configured to TRUE, and (3) elimination of unneeded IL entries is enabled.
(The problem stems from the interaction of two changes introduced in
version 2.37 -- see entries for 9/23/97 and 10/15/97.)  The bug is now
fixed, but the abort could occur with the simplest of cases:

  class A {
    void f() { }    // A::f is not referenced in this translation unit
  };

11/24/97  C++-generating back end: friend decl of static function

In Microsoft mode, a friend declaration can include a storage class,
e.g., "friend static void f();".  As part of the change to accept
that (Changes entry of 9/12/96), the C++-generating back end was
changed to recognize and output such cases.  Unfortunately, the change
did not check for Microsoft mode specifically, and that meant
incorrect output in non-Microsoft mode for cases like the following:

  static int f();
  struct X {
    friend int f();
  };

11/22/97  --preinclude command-line option

The --preinclude=filename command-line option can now be used to specify
the name of a file to be included at the beginning of the compilation.
This can be used to set system-dependent macros and types, etc.

(12/3/97:)  IL CHANGE: the a_source_file entry now contains a
bit field "included_by_preinclude" to identify these files.  The
existing fields related_file_implicit_include_done, is_include_file,
and included_by_system_include have been made bit fields as well.

11/20/97  Setting __STDC__ to zero in nonstrict mode

A configuration flag (STDC_ZERO_IN_NONSTRICT_MODE) has been added to
specify that __STDC__ should be 0 in nonstrict ANSI C and C++ modes.
This flag also overrides other factors that affect the setting of
__STDC__ (for example, __STDC__ is defined even in Microsoft mode when
this flag is set).  This flag is useful on systems, such as Solaris,
that use the value of __STDC__ to control whether certain extensions
are included in the system header files.

11/20/97  EH cleanup state for delete from constructor wrapper code

In a common configuration, the constructor wrapper code generated
by IL lowering does an allocation to handle a "new" of the class.
When exceptions are enabled, it also records that the corresponding
delete should be done if an exception is thrown within the
constructor.  If the throw comes while executing in a nested block
of the constructor that is not preceded by any declarations of
destructible objects, the EH cleanup state was incorrect and the
deletion was not done.  Now fixed.

11/20/97  Expressions involving nontype template parameters handled
          incorrectly in template argument deduction

The Draft Standard now specifies that expressions involving nontype
template parameters are "nondeduced" contexts that use the values
of template parameters deduced elsewhere.  Previously, template
parameters could not be deduced if they were used in expressions.
The new rules are now implemented.

  template <int I> struct A {};
  template <int I> A<I-1> f(A<I>){}
  template A<0> f(A<1>);  // now accepted

11/19/97  C++-generating back end, Microsoft compatibility: no qualified name
          on reference to member within class definition

As described in Changes entries for 7/8/97 and 8/12/97, the C++-generating
back end in Microsoft mode is not supposed to put out a qualified name using
a class name while still inside the definition of that class (because MSVC++
does not accept such references).  The case of multi-level qualification
was not handled correctly, and has now been fixed.

  struct A {
    struct B {
      typedef int I;
    };
    struct C {
      void f(B::I); // Was put out as A::B::I, not accepted by MSVC++
    };
  };

11/18/97  Option to put out "long double" as "double" in generated C

The type "long double" has been put out as "double" when generating
K&R C code.  Now, there is an option LONG_DOUBLE_AS_DOUBLE_IN_GENERATED_C
that controls this behavior independently, so that it can be requested
also when the output is ANSI/ISO C.  There is also a new configuration
option ISSUE_WARNING_ON_LONG_DOUBLE_AS_DOUBLE that indicates whether
a warning should be issued when the substitution is made (once per
compilation).

11/18/97  Generated output for #ident and #pragma ident

#ident and #pragma ident are both represented the same way in the IL,
as a pragma entry.  Heretofore, they have both been output (by
the C-generating back end and the C++-generating back end) as #ident,
with the idea that #ident is more widely accepted than #pragma ident.
Now, by setting USE_PRAGMA_IDENT_IN_GENERATED_CODE to TRUE, one can
request that both be output as #pragma ident instead.

11/17/97  Member class template bodies should not be removed when
          source sequence entries are created for nonclass template
          instantiations

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE,
the bodies of member class templates were incorrectly being removed from
the enclosing class along with member function bodies.  This resulted in
the creation of incorrect template strings.  This has been fixed.

11/17/97  Internal error on conversion template to nested member class

An internal error would result if a conversion template was used to convert
to a nested class of a class template.  This has been fixed.

  template<class X> class A {
    template<class T2> struct B { };
    template<class T2> operator B<T2>() throw() { }
  };
  A<int> ai;

11/14/97  Linker errors on uninstantiated virtual functions

When IL lowering is done, a change made in version 2.37 to improve the
efficiency of automatic instantiation (see entry for 6/25/97) could result
in a linker error caused by a failure to instantiate all virtual functions
of a template class; the problem had to do with the fact that destructor
wrappers (like constructor wrappers) require the existence of the virtual
function table.  Now fixed.  Here's an example where the linker complained
that A<int>::f was never defined:

  // header file xxx.h
  template<class T> struct A {
    ~A() { };
    virtual void f() { };
  };
  struct B : public A<int> {
    B();
  };

  // file xxx.C
  #include "xxx.h"
  B::B() { }               // Note that no A<int> constructor is called

  // file xxx2.C
  #include "xxx.h"
  B b;
  int main() { return 0; }

The declaration of "b" triggers the definition of B::~B(), which calls
(and causes the instantiation of) A<int>::~A(), which (when lowered)
references the virtual function table for A<int>, which requires the
address (and therefore the instantiation) of A<int>::f().  The bug was
that A<int>::f was not marked for instantiation when A<int>::~A() was
instantiated; normally the bug would be masked by the instantiation of a
constructor, but in this case no A<int> constructor is needed.

(11/25/97:) A further change.  The set of virtual functions in
the virtual function table can include non-overridden functions
from base classes, so the processing needs to mark such functions
to be instantiated also.

(12/8/97:) Another tweak.

11/12/97  extern "C" declaration inhibits generation of PCH file

When the last declaration in a header file had an explicit linkage
specification, the generation of a precompiled header file was incorrectly
inhibited.  This has been fixed.  For instance, xxx.pch is now generated
for the following:

  // header file xxx.h
  // Lots of declarations...
  extern "C" void f();

  // file xxx.C
  #include xxx.h
  main() { ... }

Note that the problem only occurred when the linkage specification was
written without braces.  If the last line of xxx.h had been

  extern "C" { void f(); }

the PCH file would have been generated correctly.  Now both forms work.

11/7/97   Abort when a nontype argument is not explicitly specified

An abort could occur when a call explicitly specifies some template
arguments but leaves a nontype template argument unspecified.  This has
been fixed.

  template <class T, int I> struct A { };
  template <class T, int I> void f(A<T,I>);
  int main() {
    A<int,1> a1;
    f<int>(a1);
  }

11/3/97   Abort scanning invalid template argument list

Certain unusual invalid template argument lists could result in an
abort when the template argument list is scanned.  This has been fixed.

  struct A {
    template <class T> operator T();
  };
  int main() {
    A a;
    a.operator operator int int < void > () ; 
  }

11/3/97   Destructions in dead code in conditional expressions

When ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS is TRUE (not the
default), expressions under conditional operators that are known not
to be evaluated are removed.  This removal does not work correctly
when the removed expression contains a destructible temporary.  The
failure to process the destruction properly caused an abort later.
To avoid the problem, the removal is now suppressed in such cases
(i.e., dead code that requires a destruction is left in the expression).

  struct A {
    A();
    ~A();
  };
  int main () {
    0 && (A(), 0);
    1 ? 1 : (A(), 0);
  }

11/1/97   Function type involving variable-length-array parameter

When VLA support is enabled, the routine type of a function that takes a
parameter involving a VLA type is now modified so that its param-type
entry no longer has has_assoc_vla_dimension set.  The VLA information
continues to be recorded for the type of the corresponding parameter
variable.  For instance:

  void f(int i, int (*p)[i]) { ... }

The type of f is as though it had been declared "void f(int, int (*)[*])"
whereas the type of variable entry for parameter p is "int (*)[i]".  This
approach is required because the VLA expression belongs to the function
scope memory region and therefore cannot be part of the "interface" of the
function.

11/1/97   Builtin processing for <stdarg.h>

When the front end is generating C or C++ code as output, the <stdarg.h>
header and its unusual macros have often been a source of difficulties
(because nonstandard language features are often used in the header).
Now, there is a configuration option to treat the <stdarg.h> header
as a builtin and pass the macro references unchanged to the output.
When DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE is TRUE
(which it is, by default, when the C-generating back end is being used
to generate ANSI/ISO C, or when the C++-generating back end is being
used), an #include of <stdarg.h> will not cause reading of the header
file.  Instead, va_list, va_start, va_arg, and va_end are defined
as builtins, scanned specially, and recorded in the IL.  The C-generating
back end and the C++-generating back end then put them out in their
original forms in the generated code, along with an #include of <stdarg.h>.

If you use IL lowering and MAKE_ALL_FUNCTIONS_UNPROTOTYPED is set to TRUE,
this processing is suppressed (because IL lowering will remove the
ellipsis on function definitions), so if you want to use this feature
you'll have to change MAKE_ALL_FUNCTIONS_UNPROTOTYPED to FALSE.

(11/29/97:) If a global-scope type named va_list exists when <stdarg.h>
is included, it will be used as the built-in va_list.  This helps
when headers like stdio.h declare va_list (it's nonstandard, but
it's common).  Also, if a type named __edg_va_list has been defined,
its type is used as the built-in va_list.  If the macro
GUARD_MACRO_FOR_VA_LIST is defined (as a quoted string), the named
macro is defined when va_list is defined.

10/30/97  Spurious error on qualified operator names with explicit
          template arguments

A use of a qualified operator name with an explicit template argument
list resulted in a spurious error.  This has been fixed.

  namespace N {
    template <class T> void operator!=(T,T){}
  }
  class A {};
  template void N::operator!=<A>(A,A);

10/25/97  Internal error from failure to mark routine as returning value
          by copy constructor

An internal error has been fixed that was caused by sometimes failing to
mark a redeclared but undefined routine as returning a value by copy
constructor.  It could occur under various circumstances -- for instance,
when it was necessary to merge default argument specifications:

  struct S { S(const S&); };
  S f(int, int=0);
  S f(int=0, int);       // Bug in forming routine type for f
  int main() {
    S s = f();           // Internal error appeared here
  }

10/22/97  Incorrect source position in IL template entry

With RECORD_TEMPLATES_IN_IL configured to TRUE, an incorrect source position
was sometimes recorded in a_template when the template was declared without
a definition and then redeclared with one.  Note: the decl_position field in
the IL template entry indicates where the template declaration begins (i.e.,
the source position of the "template" keyword); it does not indicate the
position of the template name.

-------------------------------------------------------------------------------
Version 2.37, October 18, 1997

10/18/97  IL version number changed to 2.29

10/17/97  Using offsetof on non-POD classes with usual idiom for offsetof

The usual definition for offsetof is something like

  #define offsetof(s, m) ((size_t)(&(((s *)0)->m)))

When this is used with classes that involve multiple inheritance,
it did not produce the expected results.  Or rather, it produced
the expected results when it was done in executable code, and
surprising results when used in constant contexts.  This behavior
happens to be standard-conforming, since offsetof has undefined
behavior when used with non-PODs.  It is not, however, reasonable
behavior from the programmer's point of view.  This has been corrected
to give the expected results.  The solution involves suppressing
the code that preserves null pointers across casts to base classes
when doing constant casts on addresses that are asserted to be
object addresses, e.g., the left operand of the "->" operator.
In effect, the "0" in the above is treated as a zero address of
an object, and not as a null pointer, and therefore it undergoes
the offset adjustment when cast to a base class.

10/17/97  Failure to destroy local variable once label encountered

In cases where a local variable of a destructible class type is
initialized from the return value of a function call, and a label
declaration appears after the declaration, the local variable was
not destroyed where necessary in code following the label.

  struct B {
    B();
    B(const B&);
    ~B();
  };
  B g(int);
  void f() {
    B st = g(0);
  label:
    g(0);
    // st not destroyed here.
  }	

10/17/97  Use of template keyword in qualified names and class member accesses

The template keyword is now accepted in contexts in which it is used
to specify that a dependent name should be considered to be a
template.  The template keyword is accepted in a qualified name and
following the "." or "->" of a class member access.

  template <class T> void g(T t) {
    t.T::template f<char>(1);
    t.template f<int>(1);
  }

  struct A { template <class T> void f(T); };

  int main() {
    A a;
    g(a);
  }

10/16/97  C++-generating back end: asm-statements in Microsoft mode

The form in which asm-statements are put out by the C++-generating back end
in Microsoft-compatibility mode has been changed to omit the parentheses
and quotation marks:

  __asm xxx ;           // instead of __asm("xxx");

10/16/97  Option to suppress zeroing of variables

IL lowering adds zero-initialization to defined C++ variables so that
they will be considered definitions in C.  This is generally a good thing,
but it may be wasteful for embedded system cross-compilers.
Now there is a configuration option FORCE_VARIABLE_DEFINITION_VIA_ZEROING
and an associated variable force_variable_definition_via_zeroing.
Setting them to FALSE will suppress this zeroing.

10/16/97  Incorrect offset in virtual function table in the presence of
          ambiguous base classes

In some obscure cases involving ambiguous base classes, the offset
in a virtual function table was incorrect and could cause a member
function to be called with the wrong pointer.

  struct A {
    virtual void f() = 0;
  };
  struct B : public A { };
  struct C : public B {
    virtual void g() = 0;
  };
  struct D { int i; };
  struct E : public D, public B {
    void f() {}
  };
  class F;
  F *fptr = 0;
  struct F : public E, public C {
    void f() {} // Gets here with wrong "this" pointer.
    virtual void g() {}
  };
  int main() {
    fptr = new F;
    C *c = fptr;
    c->f();
    return 0;
  }

10/16/97  Driver interface changes

The implementation of some new features necessitated changes in the
interface between the front end, driver, and prelinker.

One instantiation per object mode and the ability to put instantiation
flags in a separate file both make use of a new file called the
"template information" file.  The current "instantiation information"
file has been renamed the "instantiation request" file to make the
names of the files more distinct.  The "template information" file is
used for information that flows from the driver and front end to the
prelinker, while the "instantiation request" file is for information
that flows from the prelinker to the front end.  The default suffix
for the template information file is ".ti".  The default suffix for
the instantiation request file is ".ii" (i.e., it hasn't been changed,
for compatibility reasons).

A new configuration flag named DRIVER_COMPATIBILITY_VERSION has
been added so that the front end can be easily configured to be
compatible with a driver intended to work with an earlier version of
the front end.  For example, if DRIVER_COMPATIBILITY_VERSION is set
to a value less than 237, a template information file will not
be generated, one instantiation per object mode will be disabled, and
the instantiation flags will continue to be part of the generated code.

The DRIVER_COMPATIBILITY_VERSION flag directly or indirectly affects
the default values used for the following driver interface configuration
flags:

	USE_TEMPLATE_INFO_FILE
	INSTANTIATION_FLAGS_IN_TEMPLATE_INFO_FILE
	INSTANTIATION_REQUEST_LINES_RESERVED
	ONE_INSTANTIATION_PER_OBJECT

These flags may be set individually to enable or disable specific
features.  For example, ONE_INSTANTIATION_PER_OBJECT could be
explicitly disabled, as it requires more back end and driver support
than simply placing the instantiation flags in a separate file.  See
the configuration section section of the internal documentation for
more information.

Another feature with a minor impact on the driver is the improved
interface with the prelinker.  This feature simply requires that the
driver recognize the --definition_list_file option, and pass this
option on to the front end.

10/16/97  One instantiation per object file

In a new template instantiation mode, enabled by the command-line
option --one_instantiation_per_object, each compilation produces
several object files: a primary object file plus a separate object
file for each template instantiation (function or static data member).
Having each instantiation in a separate object file is very useful
when creating libraries, because it allows the user of the library to
pull in only the instantiations that are needed.  (This is particularly
desirable because our prelinker may assign a large number of
instantiations to one source file.  Heretofore, we have created
one monolithic object file containing all the instantiations.  Referring
to a single instantiation in that file would have dragged in all the
rest of the instantiations as well.)

The C-generating back end has been updated so that it will generate
multiple C output files in this mode, and the eccp script has been
updated so that it will pass all of the generated C files to the
underlying C compiler.  The resulting object files are placed in a
directory specified by the --instantiation_dir=<name> command-line
option (the default is "Template.dir").  "Real" back ends should
be able to use the information provided to make multiple passes
over the IL to generate multiple object files.

Static variables and functions that are referenced from instantiations
are made external, with names beginning with __STV__ or __STF__,
respectively, so that they are visible from the instantiation
object files.

The implementation of this feature involves maintaining a separate
set of "needed" flags for each object file to be generated,
indicating the things referenced from a single instantiation.
This allows a back end to generate object files that contain only
the entities needed.  The maintenance of these per-instantiation
"needed" flags entails a space and time overhead, though for the
most part only when the feature is enabled.  If you intend never
to use the feature and want to avoid all of the overhead, you
can configure it out by setting ONE_INSTANTIATION_PER_OBJECT to
FALSE.

This feature requires support from the driver used to invoke the
front end.  See the "Driver interface changes" entry above for
more information.  It also requires support in the back end.
For these reasons, the feature is configured off by default,
except when the C-generating back end is used.

10/16/97  Explicit specification of function template arguments

Explicit specification of function template arguments is now fully
implemented.  In version 2.36 explicit function template arguments
were only accepted in declaration contexts.

Now that template arguments can be explicitly specified, it is no longer
a requirement that a parameter be used in the signature of a function
template in a context in which its value can be deduced.  For example,
the following code is now accepted:

  template <class T> void f();  // T not used in function signature
  int main() {
    f<int>();
  }

If a user makes a mistake in the declaration of a function template
he or she may unwittingly declare a template that requires one or more
of its arguments to be explicitly specified.  For example:

  template <class T, class T2> void f(T, T);  // should have been (T, T2)

This template will fail to match any call that doesn't supply an explicit
value for T2.  Because this kind of error is easy to make, a remark is issued
on such declarations.  A warning is issued if a template conversion
operator or template constructor declares a template parameter that is
not used in its function signature.  A warning is issued instead of
a remark because there is no way that such a function can be called.

10/16/97  Template argument deduction processing updated

Template argument deduction has been updated to conform to the draft
standard.  Specifically, "nondeduced" contexts and certain cases
involving differences in cv-qualifiers are now handled properly.
Nondeduced contexts include the qualifier portion of a type specified
as a qualified name.  For example, the A<T> in A<T>::B.  An argument
cannot be deduced from a nondeduced context, but instead uses a value
that is either explicitly specified or deduced elsewhere.  The
following example illustrates the kind of usage that is now accepted
and the kind of usage that was formerly accepted but is now rejected.

  template <class T> struct A {
    struct B {};
  };
  template <> struct A<char> {
    typedef int B;
  };
  template <class T> void f(A<T>, A<T>::B);
  template <class T> void g(A<T>::B);

  int main() {
    A<int> ai;
    A<int>::B aib;

    f(ai, aib);  // valid in standard and nonstandard modes

    g(aib);  // no longer permitted in standard mode

    A<char> ac;
    f(ac, 1);  // now accepted in standard mode
  }

The new deduction rules for qualifiers are enabled and disabled by the
command-line options --[no_]nonstd_qualifier_deduction.  The default
is specified by DEFAULT_NONSTANDARD_QUALIFIER_DEDUCTION.

Function templates with cv-qualified types are now handled properly
by the deduction process.  In the following examples, both calls
were formerly diagnosed as ambiguous.  Both are now accepted.

  template <class T> void f(T&);
  template <class T> void f(const T&);
  struct A {};
  int main() {
    A a;
    f(a);  // Nonconst preferred
    f(1);  // const used, cannot bind lvalue to nonconst reference
  }

10/16/97  Internal error in eliminating unneeded nested template class
          specialization

If (1) unneeded entities were being removed from the IL, (2) source
sequence entries were being generated, and (3) IL lowering was not being
done, then an internal error could occur when an unneeded nested template
class specialization was encountered; now fixed.  Here's an example:

  class A {
    template <class T> class N { ... };
    N<int> *pn;
  };
  template<> class A::N<int> { ... };      // No definition is needed

10/15/97  Source-sequence representation for class template instantiation
          with dependency on member of class being defined

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured
to TRUE, the source-sequence representation of class instantiations
triggered during a class definition presents a dilemma when the template
class is (or is dependent on) a type declared in the enclosing (and not yet
fully defined) class.  Consider the following:

  template <class T> class A { };
  class B {
    template <class T> class N { };
    A<int> a;
    N<int> n;
  };

The source sequence entry for the instantiation of A<int> can float up to
the file-scope, before the definition of B.  But the one for B::N<int>
cannot, since neither B nor B::N has been declared yet.  So it is now
inserted just prior to the declaration of n.  Yet this means the rewrite
produced by the C++-generating back end looks like this:

  template <class T> class A { };
  template <> class A<int> { }
  class B {
    template <class T> class N { };
    A<int> a;
    template<> class N<int> { };             // Invalid C++
    N<int> n;
  };

This points to a limitation in the strategy of representing a class
template instantiation as an explicit specialization -- there is sometimes
no right place to put it out.  Customers using the C++ generating back end
with CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS set to TRUE
should be aware of this dilemma.  Customers using source-sequence entries
in tool applications with no need to generate compilable code should find
this change an improvement.

10/15/97  Bug fix on array rvalues in C mode

Array rvalues were implemented in version 2.36 (see 5/22/97 Changes
entry).  In C mode, some obscure cases involving comma operators
and/or indirection operators were not handled correctly, and produced
an internal error.  Now fixed.

  struct A { int a[5]; };
  void f() {
    int i;
    struct A *p;
    (i, *(struct A *)0).a[1] = 1;
  }

10/15/97  Improved interface with the prelinker

The interface between the front end and prelinker has been modified to
reduce the number of times that the front end must be invoked to
generate the complete set of instantiations needed by a program.

The prelinker generates a "definition list" file that contains a list
of all the entities defined in the object files and libraries that
are being used to create the program.  The front end uses this list
to determine whether any newly required instantiations have already
been defined somewhere else in the program.  If an instantiation
is not already defined elsewhere, it is "adopted" by the file being
compiled.  In many cases, this complete set of instantiations can
be generated with only a single iteration of the prelinker.

This feature requires a minor change in the driver.  The driver must
recognize the --definition_list_file option, and pass it along on to
the front end (without making it part of the instantiation command
line saved in the .ii or .ti file).  If your driver does not recognize
this option, the PL_DEFAULT_USE_DEFINITION_LIST flag should be set to
FALSE when building the prelinker.

10/14/97  Internal error when using precompiled header files

An internal error would occur when using precompiled headers if
the final preprocessing directive to be included in the precompiled
header file included a multi-line comment.  This has been fixed.

  #include "b.h" /*
  */

10/13/97  Ability to put instantiation flags in a separate file

The instantiation flags (i.e., the TIR, CBI, and DNI flags) that are
used for automatic instantiation processing can now be placed in a
separate file instead of being encoded as variables in the generated
object file.  This was done to eliminate the space required to store
the instantiation flags in the object file and in libraries in which
the object file may be placed.

This feature requires support from the driver used to invoke the front
end.  See the "Driver interface changes" entry above for more information.

10/9/97   Equivalent type names found via using-directives

An error is no longer issued if a using-directive lookup finds more
than one name, but all of the names found refer to the same type.

  namespace N {
    typedef int    I;
  }
  using namespace N;
  typedef int    I;
  void f(I);  // no longer an error

10/8/97   Revised module ID generation

The front end generates a module ID, which is appended to certain
names to guarantee that they are unique across an entire program.  The
module ID is made up of the primary source file name and some additional
information (e.g., the mangled name of an external entity defined in
the compilation).  The following changes have been made:

-- Template entities are no longer chosen for the external entity.
   This change was made because some implementations generate
   template instantiations in more than one file.
-- When no external entity is available for use in the module ID, the
   compilation time and current directory are now included.
-- Because the module ID is now used as a component of external names
   in more circumstances, a CRC code is sometimes used in place of the
   additional information described above.  If the additional information
   to be used in the module ID is more than 8 characters, the hexadecimal
   representation of the CRC code is used in its place.

10/8/97   Applying a cv-qualifier to a function type is not allowed in C++

A discretionary error (a remark in Microsoft and cfront compatibility
modes) is now issued when a cv-qualifier is applied to a function type
in C++ mode.  For instance:

  typedef void F(int);
  typedef const F CF;               // Error
  void g(const F *pf) { ... }       // Error

In a related change, a pointer-to-member selection (using the ".*" or
"->*" operator) with a second operand that is a pointer-to-member-function
no longer adds the cv-qualifiers of the first operand to the result
function type.

10/8/97   Spurious error on operator name followed by "<"

In version 2.36, a "<" following an operator name was incorrectly
considered to be the start of a template argument list in certain
cases.  This has been fixed.

  struct A {};
  int operator+(A&, int);
  int main() {
    operator+ < operator+;
  }

10/8/97   Function parameter default argument in template parameter
          declaration

An error is now issued when a function parameter default argument
appears in a template parameter declaration:

  template <void (*pf)(int=0)> void g() { }       // Error

(Before this change, scanning the construct resulted in spurious syntax
errors and occasional internal errors.)

10/8/97   Abbreviated command line options

The front end now accepts abbreviated keyword command line options.
Only as many initial characters as are required to uniquely identify
an option are needed.  For example, "--bo" may be used to specify
the "--bool" option.

10/7/97   Small change to diagnostic output

The algorithm for determining how to display a function name in the
diagnostic output (e.g., with or without its parameter list) has been
fixed to deal with an obscure inconsistency.

10/7/97   Revision to lookup of names in template instantiations

The lookup rules for names referenced in template instantiations have
been updated to more closely reflect what is in the Working Paper
(although they still don't fully reflect the Working Paper rules).
When a template (call it A) is instantiated because of a reference
from another template (call it B), the "referencing namespace" for
template A is the referencing namespace for template B.  Formerly, we
used the definition namespace of template B as the referencing namespace
for template A.  This could result in name lookup failures when such
transitive instantiations are performed.

Prior to this change, the lookup of f from N::h failed.

  template <class T> inline void f(T){}
  namespace N {
    template <class T> inline void f(T,T){}
    template <class T> inline void h(T t){ f(t); }
    template <class T> inline void g(T t){ h(t); }
  }
  int main() {
    N::g(1);
  }

10/6/97   Abort on declaration of pointer to member of type pointer to function

A bug has been fixed that caused the front end to abort when scanning a
declaration of a pointer to member of type pointer to function.

  template < class T > void f11 ( void ( * T :: * ) () ) { } 

10/3/97   INSTANTIATION_INFO_LINES_RESERVED renamed

The "instantiation information" file has been renamed to the
"instantiation request" file.  This was done to distinguish it
from a new file that is generated by the front end called the
"template information" file.  As part of this change the
INSTANTIATION_INFO_LINES_RESERVED flag has been renamed to
INSTANTIATION_REQUEST_LINES_RESERVED.

10/3/97   Spurious parsing error with elaborated type specifier in new
          expression

A spurious error in parsing an elaborated type specifier in a new
expression has been fixed: a "<" is not assumed to introduce a template
argument list unless a template-name has actually been specified.

  struct A { };
  main() {
    new struct A < 0;    // Spurious error is no longer issued
  }

10/3/97   Microsoft_compatibility: __declspec and inheritance kind

In Microsoft compatibility mode, an inheritance-kind specification on a
class declaration (see 4/28/97 entry) may now coexist with __declspec
modifier (or, in 16-bit Microsoft mode, near/far memory attributes).

10/2/97   Some redeclarations of template parameters not detected

Certain kinds of redeclarations of template parameters were not
diagnosed.  Specifically, those in the declarator of a function
template declaration.  This has been fixed.

  template <class T> void T(T);
  template <class T> void f(T T);

10/1/37   Microsoft compatibility: "__asm" is now put out in strings in the
          IL for templates

In Microsoft-compatibility mode, when strings are built to represent token
sequences (see add_token_to_string in lexical.c), "__asm" is put out
instead of "asm".  When RECORD_TEMPLATES_IN_IL is configured to TRUE such
strings are pointed to by IL entries of type a_template.

10/1/97   Spurious "invalid IL file" error in IL display program

When MAINTAIN_NEEDED_FLAGS was configured to FALSE, a spurious catastrophic
error could occur in the IL display program when the IL included an empty
memory region (for a trivial default constructor of a nonaggregate class).

9/29/97   Instantiation problem when using implicit inclusion

In some cases, a file could be implicitly included just so that the
"can be instantiated" flag could be set properly.  This kind of an
implicit inclusion was done after any needed instantiations were
generated.  If such an implicit inclusion resulted in additional
instantiations, an error could result from the fact that those
additional instantiations would not be done.  This has been fixed.

9/29/97   Microsoft compatibility: incorrect diagnostic on branch past
          nonconstant initialization of automatic aggregate variable

In Microsoft C mode, branching past the declaration of an automatic
aggregate variable with a nonconstant initializer would sometimes evoke an
incorrect diagnostic (an error, with an inappropriate message).  Now fixed.

  void f(int i) {
    if (i) goto L2;       // Warning is now issued in Microsoft C mode
    {
      int a[2] = { i, i };
  L2:;
    }
  }

9/29/97   Incorrect routine-name-linkage on class member function type

When the definition of a class member function appeared outside the class
definition but within an extern "C" context, the name linkage on the
routine type was set incorrectly, with the result (if IL lowering was
done) that its name was incorrectly mangled.  This has been fixed.

  class A {
    void f();
  };
  extern "C" {
    void A::f() { }         // name for A::f is now mangled correctly
  }

9/28/97   __STV__ form mangled name for externalized static variables

Static variables made external are now given a mangled name with a
__STV__ prefix.  This is used in the C-generating back end when
generating pcc C, and now for static variables referenced from
instantiations when the one-instantiation-per-object option is used.

9/25/97   Redundant secondary-decl source sequence entry for class template
          instantiation

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured
to TRUE, the source-sequence representation of class instantiations often
involved a redundant secondary-decl source sequence entry (representing
the "partial instantiation") immediately before the primary source sequence
entry for the instantiation.  The extra entry has now been removed,
resulting in cleaner C++ output.  For example,

  template <class T> A { T t; };
  A<int> ai;

used to be transformed by the C++-generating back end as follows (with
the class instantiation represented as an explicit specialization):

  template <class T> A { T t; };
  template<> A<int>;               // Superfluous -- no longer put out
  template<> A<int> { int t; };
  A<int> ai;

9/25/97   Source-sequence representation of nested class instantiations
          triggered during parent class instantiation

When CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured
to TRUE, the source-sequence representation of nested class instantiations
triggered during instantiation of a parent template class was incorrect.
As a result, the generated C++ would not compile.  This has been fixed.

  template <class T> class A {
    class B { ... };       // Instantiation of A<int>::B is triggered by
    B b;                   //   declaration of b before instantiation of
  };                       //   A<int> is completed
  A<int> ai;

9/24/97   Spurious error when a typedef to a template-dependent name is
          used as a base class

A spurious error was issued when a typedef to a template-dependent name
was used as a base class.  This has been fixed.

  template <class T> struct B {};
  template <class T> struct A {
    typedef B<T>::X my_x;
    class C : my_x {};
  };

9/23/97   Source-sequence representation of functions defined within class
          definitions

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is
configured to TRUE, the source-sequence representation of member and friend
functions defined within a non-local class is as though the definition had
actually appeared immediately after the end of the class definition.  This
transformation is reflected in the generated C++; it may be required when
the initial reference to a function template instantiation appears in a
member function body.  For example:

  template <class T> void f(T) { ... }
  class A {
    void f() { f(*this); }
  };

is represented as though the source had contained:

  template <class T> void f(T) { ... }
  class A {
    inline void f();
  };
  template<> void f(A);
  void A::f() { f(*this); }

9/23/97   New representation for template entities in diagnostic output

A new means of representing template entities in diagnostics has been
added.  The new representation is used when distinct template
signatures are enabled.  Now that explicit template argument lists are
accepted, it is possible to have template parameters that are not
included in the function type of instances of a function template.
The new representation makes it possible to see the values of all of
the template parameters, even those that are not included in the
function type.  The new output is similar to the output produced by
the prelinker when using distinct template signatures.

  template <class T> struct A {
    template <int I, class T2> int f(T2){int i; return 0;}
  };
  A<int> ai;
  int x = ai.f<1>('c');

  "ex.c", line 2: warning: variable "i" was declared but never referenced
          template <int I, class T2> int f(T2){int i; return 0;}
                                                   ^
            detected during instantiation of
                "int A<T>::f<I,T2>(T2) [with T=int, I=1, T2=char]" at line 6

9/22/97   IL lowering exception handling for freeing of storage allocated
          in "new"

The cleanup state maintained by IL lowering for exception handling
following the processing of a "new" operation that does the allocation
inline (as opposed to allowing a constructor to do the allocation) has
been improved.  The old cleanup state included the cleanup entry for
freeing the storage even after the end of the full expression containing
the "new".  Since the freeing operation was conditional on a flag that
was properly reset, this was harmless.  But now the cleanup state is
moved off that entry.

9/22/97   Duplicate diagnostic on ctor-initializer with inaccessible
          destructor

Two identical errors were issued on the following when it was compiled with
exceptions enabled; the redundancy has now been eliminated.

  struct A {
    A();
  private:
    ~A();
  };
  struct B {
    A a[3];
    B() : a() { }    // Redundant diagnostics on inaccessible A::~A()
    ~B();
  } b;

9/22/97   Bug in putting out destructor information on ctor-initializer
          for arrays (when exceptions are enabled)

When support for exception handling was enabled, the IL put out to
represent the destructor sequence for partially constructed member arrays
was sometimes incorrect.  Now fixed.

9/22/97   Instantiation of noninline member functions in unnamed namespaces

Noninline member functions in unnamed namespaces should be treated as static
functions for instantiation purposes, but were not.  This could result in
spurious errors in -tnone mode and an instantiation loop in -tused mode.
This has been fixed.

  namespace {
    template <class T> struct A {
      void f();
     };
     template <class T> void A<T>::f() { }
  }

  int main() {
      A<int> ai;
      ai.f();
  }

9/22/97   Missing diagnostic on use of template-id in class using-declaration

A using-declaration is not permitted to name a template-id.  This was
diagnosed for nonmember using-declarations but not for member
using-declarations.  This has been fixed.

9/21/97   DEFAULT_DISTINCT_MANGLING_FOR_TEMPLATES renamed

The DEFAULT_DISTINCT_MANGLING_FOR_TEMPLATES configuration flag has been
renamed to DEFAULT_DISTINCT_TEMPLATE_SIGNATURES, and is now used even
when IL lowering is not done.  In addition to controlling the kind of
name mangling used for templates, it is also used to specify whether
function templates may have template parameters that are not used in
the parameter types of the function template.

9/21/97   Partial lowering of exception handling: cleanup state when
          lifetime of entity overlaps temporaries in inner lifetime

The change made in 2.36 involving the overlaps_temps_in_inner_lifetime
flag was incomplete for the partial-lowering configuration.  The
cleanup_state_to_set_when_starting_destruction field in the
destructible_entity_descr built by IL lowering was not updated for the
last-destroyed of such temporaries.  This is only significant for
back ends that use the destructible_entity_descr built by IL lowering.

IL CHANGE: Also, a new expression node, leck_initialization_completed,
has been added, and it is generated to indicate the point where an
initialization marked with overlaps_temps_in_inner_lifetime has
been fully initialized.  It is generated only when GENERATE_EH_TABLES
is FALSE.

9/21/97   Abort generating exception handling tables for aggregate

An abort in IL lowering, which occurred while generating exception
handling cleanup tables for a static array initialized by a brace-enclosed
list, has been fixed.  The problem only occurred if there were previous
static variables requiring destruction.  This bug was introduced in 2.36.

  struct S {
    S();
    S(const S&);
    S(int);
    ~S();
  } x;
  struct SS {
    S mem;
  };
  SS s1;
  SS s2[2] = {1, 2};

9/21/97   Partial lowering of exception handling: useless destruction
          entry eliminated

A vestigial dynamic initialization entry from the partial aggregate
cleanup for an array is now removed from the IL.  It was unreferenced
except for being on the object lifetime's destructions list.

9/20/97   Cast of address to floating-point type not a constant expression

A cast of an address to a floating-point type is no longer considered
an operation that can be folded at compile time.

  void f(void) { }
  double x = (double)(unsigned)f;  // error

9/20/97   Lowering of member constant variables without definitions

IL lowering now removes the initializer from member constant variables
(static data members initialized within the class) if they are not
defined in the compilation.  Previously, they were not changed, and
the variable after lowering was invalid from a C language point of
view -- a variable with storage class sc_extern should not have an
initializer.

This change fixes a problem that came up in anachronisms mode:
the processing of the anachronism that allows the omission of
the definition of a static data member changes the storage class of
those variables to sc_unspecified.  However, for member constant
variables, that produced a variable with sc_unspecified storage
class and an initializer, which is a full-fledged definition.
If the member constant appears in more than one source file (quite
likely, if it is in a header), one would get link-time "multiply
defined" errors on the variable.

9/20/97   Error on explicit cast of pointer-to-member of derived to
          pointer-to-member of virtual base

An error is now issued (as required by the emerging standard) on
an explicit cast from a pointer-to-member of a derived class to
a pointer-to-member of a virtual base class.

9/19/97   C++-generating back end: parentheses on ctor-init for array

The C++-generating back end now puts out an empty set of parentheses
on a ctor-initializer for an array member.

  struct A {
    A();
    ~A();
  };
  struct B {
    A x[10];
    B();
  };
  B::B() : x() {}

9/18/97   "typename" accepted in functional-notation type conversions

The keyword "typename" is now accepted in functional-notation type
conversions:

  template<class T> void f(T p) {
    int i = typename T::x(0);
  }

9/18/97   Microsoft compatibility: promotion of anonymous union member
          name to scope of containing class

In Microsoft bugs mode the name of an anonymous union member can now be
promoted to the containing class scope even if that name has already been
declared there; a warning is issued.

  struct S {
    int i;
    union { int i; };       // Warning in Microsoft bugs mode
  };

9/18/97   Microsoft compatibility: type qualifiers on function parameters
          affect virtual function overriding

In Microsoft bugs mode, the type qualifiers on the function declarations
(even though they are otherwise removed from the function signature) can
affect whether a derived class function is considered to override a base
class virtual function.  For instance:

  struct B {
    virtual void f(const int);
  };
  struct D : public B {
    void f(int);            // In Microsoft bugs mode D::f does not
  };                        //   override virtual function B::f

IL CHANGE: The qualifiers field in a_param_type, which records the
top-level type qualifiers that are removed when global variable
remove_qualifiers_from_param_types is TRUE, is now set in all cases (i.e.,
no longer just for parameters of functions that have definitions).

9/18/97   Microsoft compatibility: c_plusplus macro not defined

In Microsoft C++ mode, the macro c_plusplus is no longer defined.

9/18/97   Microsoft compatibility: #define or #undef of predefined macro
          gets just a warning

In Microsoft mode, an attempt to #define or #undef a predefined macro
now gets a warning (instead of an error), and the attempt is ignored.
(Actually, the #undef is done; the warning from MSVC++ says that the
#undef is ignored, but it gets done, so we do the same.)

The diagnostics in non-Microsoft mode have been made discretionary errors.

9/18/97   Microsoft compatibility: "$" allowed in identifiers

In Microsoft mode, the "$" character is now allowed by default in
identifiers.

9/18/97   Diagnostic on extra text at end of preprocessing directive is
          now a discretionary error

The diagnostic produced when there is extra text after the expected end
of a preprocessing directive is now a discretionary error, and therefore
can be reduced to a warning.  Note that for many preprocessing directives
(e.g., #endif), the extra text has already been considered harmless, and
a diagnostic on those is issued only in strict mode.

9/17/97   C-generating back end: references to parameters in functions
          for covariant virtual functions

In the surrogate functions generated by the C-generating back end for
covariant virtual functions, references to parameters of the original
function are put out with the names of the parameters in the original
function, but the parameters of the generated function were unnamed.
As a consequence, the generated C code did not compile.  Now, the
parameters of the generated function are given the appropriate names.

9/16/97   Lookup of qualified names in class member accesses

The new "dual lookup" of qualified names in class member accesses is now
implemented.  The B in B::i in the following example is now looked up
both in the context of the expression (i.e., a normal lookup) and in the
class of the left operand of the "." or "->" operator (struct A, in this
example).  A diagnostic is issued if the name is found in both contexts
and the two names found do not refer to the same entity.

  struct A {
    typedef A B;
    int i;
  };
  int main() {
    A       a;
    a.B::i = 1;  // not previously allowed
  }

9/16/97   Abort eliminated on use of incomplete enum in "?" in pcc mode

The following program, which uses an enumerator from an enum within
a "?" operation inside the definition of the enum, no longer aborts
in pcc mode:

  enum {
    E1,
    E2 = 1 ? E1 : E1,
    E3
  };

9/16/97   Microsoft compatibility: __declspec(novtable)

In Microsoft compatibility mode, __declspec(novtable) is now implemented
as an attribute of classes (in C++ mode only).

9/16/97   Microsoft compatibility: calling convention applied to typedef

In Microsoft compatibility mode, support for calling conventions (e.g.,
__stdcall) has been extended to remove the restriction on their use with
typedef types in most cases.  For example:

  typedef void F(int);
  F __stdcall f;         // Error is no longer issued

However, when a typedef introduces a type qualifier on top of a routine
type, the calling convention specification continues to be disallowed.

  typedef const F FC;
  FC __stdcall g;        // Still an error

9/16/97   Microsoft compatibility: __based in a cast operation

Based pointer types are now accepted in cast operations:

  char c[10], *pc = c;
  char __based(pc) *bpc;
  void f() {
    bpc = (char __based(pc) *)4;  // Spurious syntax error eliminated
  }

9/15/97   Microsoft compatibility: __declspec(allocate(...))

In Microsoft compatibility mode, __declspec(allocate(...)) is now
implemented as an attribute of variables with static storage duration.

9/15/97   Microsoft compatibility: __declspec(property(...))

In Microsoft compatibility mode, __declspec(property(...)) is now
implemented as an attribute on nonstatic data members of classes.

9/11/97   Overload resolution tie-breaker processing updated

The handling of "tie-breakers" in overload resolution has been updated
to conform to the draft standard.  The tie-breakers are now checked
"early" (at the same time as other comparisons of the level of match
for a single argument) rather than "late" (at the function level, to
decide between two functions for which all the argument matches look
equally good).

  void f(int *, int);
  void f(const int *, short) {}
  int main () {
    int *p;
    short s;
    f(p, s);  // Should be ambiguous (with "early" tiebreaker)
    return 0;
  }

This behavior is controlled by the variable do_late_ovl_res_tiebreaker,
the configuration macro DEFAULT_DO_LATE_OVL_RES_TIEBREAKER,
and the command line options --late_tiebreaker and --early_tiebreaker.
The appropriate setting is established in strict mode (FALSE), cfront
mode (TRUE), and Microsoft bugs mode (TRUE).

On a related issue, the tie-breaker for adding cv-qualifiers under
a reference type now applies only if both parameters being considered
have reference types:

  void f(int, short) {}
  void f(const int&, char);
  int main () {
    int i;
    f(i, 0);  // Now ambiguous; tie-breaker does not apply
    return 0;
  }

This behavior is controlled by the variable single_ref_qual_ovl_res_tiebreaker
and the configuration macro DEFAULT_SINGLE_REF_QUAL_OVL_RES_TIEBREAKER.
There is, at present, no associated command-line option, but the
appropriate setting is established in strict mode (FALSE) and
Microsoft bugs mode (TRUE).  Cfront mode uses a different
algorithm for this tie-breaker (adjusted slightly for this change)
and the setting of the variable is ignored in that mode.

9/10/97   Microsoft compatibility: __declspec(dllimport) with inline function
          definition

An error is no longer issued on an inline function definition when
__declspec(dllimport) is also specified.  (See entry for 8/13/97)

9/9/97    Template static data member initialization guard code and -tlocal

When TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE is set to TRUE, guard
code is put around initializations of template static data members.
Now, this code is suppressed in -tlocal mode, because in that mode
the static data member is local to the compilation, so no guard code
is needed.

9/6/97    Microsoft compatibility: mutable in a declarator

In Microsoft compatibility mode "mutable" is accepted and ignored when it
appears in a declarator:

  class A {
    void * mutable p;    // Accepted with a warning in Microsoft mode
  };

9/6/97    Warning on nested class or enum declaration with type qualifier

Except in strict ANSI mode an error is no longer issued when a type
qualifier appears on a nested class or enum declaration with no
declarator.  This change is partly for consistency with the handling of
such declarations outside a class definition, and partly for Microsoft
compatibility.  For example:

  struct S {
    const enum E { a,b,c };    // Warning (or error in -A mode)
  };

9/5/97    C++-generating back end: no storage class on function specialization

Specializations are not allowed to contain storage class specifications
(e.g., "static").  The C++-generating back end suppressed the storage
class for specializations in most cases, but not on function
specializations that are definitions.  Now the storage class is
suppressed for those as well.

9/3/97    Source sequence entry for nonstandard friend declaration

The source sequence entry generated for a nonstandard friend declaration
was incorrect when the type specified in the friend declaration was a
typedef name.  This resulted in incorrect output from the C++-generating
back end.  Now fixed.

  class A { };
  typedef A T;
  class B {
    friend T;      // omission of "class" is nonstandard
  };

9/2/97    Missing test for exceeding maximum number of scopes

The front end did not check for overflow when the next scope number was
incremented.  If the scope number exceeded the value that could be
stored in a short, unpredictable behavior, including aborts and
internal errors, could occur.  An overflow test has been added, and
the size of a_scope_number has been changed to a long.

8/25/97   Cost of builtin conversions in overload resolution should ignore
          cv-qualifiers

The determination of the cost of conversions on builtin types in
overload resolution was sometimes incorrect when lvalues with
cv-qualified types were involved.  Now fixed.

  const int i = 1;
  struct X {
    X(const int);
  };
  void operator-(const X&, const int);
  enum E { BIG = 99 } ;
  void f() {
    BIG - i;  // Not ambiguous
  }

8/25/97   C++-generating back end: qualified name changes to deal with
          MSVC++ bugs

Two changes have been made in generation of C++ code by the C++-generating
back end in Microsoft mode to deal with bugs in MSVC++:

  1)  In a ctor-initializer, the name of a virtual base class is
      always put out as an unqualified name.
  2)  In a call of a member function, if a qualified name that requires
      multi-level qualification, e.g., "A::B::C::x", is used,
      the qualified name is put out with a single level of
      qualification, e.g., "C::x".

8/23/97   Temporary in default argument expression inside conditional
          expression destroyed when not constructed

Temporaries in default argument expressions inside parts of expressions
that are conditional should be destroyed only if they were constructed,
i.e., only if the part of the expression that constructs them was
executed.  This was not being done: such temporaries were destroyed
unconditionally, with the consequence that sometimes the destructor
for a class was called for a temporary that was never constructed.
Now fixed.

  struct A {
    A(const char *);
    ~A() ;
  };
  int foo(const A & = "");
  int main() {
    int i = 5;
    return  (i == 5 || foo()) ? 0 : 1; // The temporary is not constructed
                                       // and should not be destroyed
  }

8/21/97   Member class bodies not removed when nonclass template instantiations
          are included in the source sequence list

When source sequence lists are being generated and when nonclass
template instantiations are included in the source sequence lists,
member class bodies were not being removed from the enclosing token
cache.  This would result in spurious errors if the program attempted
to specialize the member class.

8/20/97   Spurious error on instantiation of class with specialized
          static data member

A spurious error was issued if a class containing a specialized static
data member was explicitly instantiated.  Now fixed.

  template <class T> struct A {
    static int i;
  };
  template <> int A<char>::i = 2;
  template class A<char>;

8/20/97   Microsoft compatibility: friend declaration treated as guiding
          declaration

Although the Microsoft compiler does not consider a global scope declaration
of a function to be a guiding declaration, the same declaration used as
a friend declaration is considered to be a guiding declaration.  We now
duplicate this behavior in Microsoft mode.

  template <class T> class A {
    friend void f(A<T>);  // now treated as a guiding decl. in Microsoft mode
  };
  template <class T> void f(A<T>){}
  int main ()
  {
      A<int> a;
      f(a);
  }

8/20/97   Incorrect linkage for members of specialized classes in -tlocal mode

The linkage of specialized classes was incorrectly being affected
by -tlocal mode.  This has been fixed.

  template <class T> struct A {
    void f();
  };
  struct A<int> {
    void f();
    void g() { f(); }
  };

8/20/97   Eliminated "no accessible constructors" diagnostic

The "no accessible constructors" warning has been eliminated because
there are common programming techniques that use such classes.

8/19/97   Spurious error on redundant do_not_instantiate pragma

A spurious error was issued if a program contained more than one
do_not_instantiate pragma for a given entity.  This has been fixed.

  template <class T> void f(T);
  #pragma do_not_instantiate void f(int)
  #pragma do_not_instantiate void f(int)

8/19/97   Missing diagnostic on storage class in explicit specialization

A storage class is not allowed in an explicit specialization
declaration, but was accepted by the front end.  This has been fixed.

  template <class T> void f(T);
  template <> static void f(int) {}

8/17/97   Internal error on declaration of class operator new in a class
          template with a template-dependent base class when exceptions are
          enabled

A bug was introduced in version 2.34 that could cause an internal
error when a template class with a template-dependent base class
contains a declaration of an operator new routine with no matching
operator delete.  For the internal error to occur the front end must
be configured to support placement delete, and exceptions must be
enabled.  Now fixed.

  template <class T> class B : public T {
    void *operator new(unsigned int size, int *p);
  };

8/15/97   Internal error when generating preprocessing output

When preprocessing output is being generated, an internal error
could occur if a macro name immediately preceded a #define.  Now fixed.

  #define f(x) 1
  f
  #define h f(1)

A similar problem was also possible with an #assert or #unassert
directive.

8/15/97   Diagnostic on redeclaration of macro as empty

When a macro is redefined differently, a diagnostic should be issued.
The front end was failing to do so when the new definition is empty.
Now fixed.

  #define x 1
  #define x       /* Now gets diagnostic. */
  #define y(z) z
  #define y(z)    /* Now gets diagnostic. */

8/14/97   Standard conversion after user-defined conversion considered
          in overload resolution

In the context of an initialization, the standard conversions required
after two different user-defined conversions can be used to choose
between the two possibilities (the conversion sequence involving the
better standard conversion is chosen).  This is now implemented.
Formerly, the tie would be broken only when no conversion was
required in one case, and a standard conversion was required in the
other case.  The test case is from [over.ics.rank] of the WP:

  struct A {
    operator short()
  } a;
  int f(int);
  int f(float);
  int i = f(a);     // Calls f(int), because short -> int is
                    // better than short -> float.

8/14/97   Global qualifiers permitted when a namespace or class member is
          defined outside of its namespace or class

The Working Paper now permits a global qualifier to be used in any declarator
in which a qualified name is permitted.  The front end accepted global
qualifiers in all such declarators except when a namespace or class member
(including a member of the global namespace) was defined outside of its
namespace or class.  This has been fixed.

  namespace N {
    void f();
  }
  void ::N::f(){ }

8/14/97   Microsoft compatibility: redeclaration of namespace member permitted

The Working Paper does not permit a namespace member to be redeclared outside
of its namespace, but this is permitted by the Microsoft compiler.  We now
accept such declarations in Microsoft mode.

  namespace N {
    void f();
  }
  void N::f();  // now permitted

8/13/97   Microsoft compatibility: __declspec(dllimport) implies extern

In Microsoft compatibility mode, __declspec(dllimport) now implies extern,
which means a declaration containing __declspec(dllimport) is not a
definition by default, and therefore can be repeated:

  __declspec(dllimport) MEM_POOL shi_MemDefaultPool;
  __declspec(dllimport) MEM_POOL shi_MemDefaultPool;

In addition, variables declared "dllimport" are no longer allowed to be
initialized, and functions declared "dllimport" are no longer allowed
to be defined.

8/13/97   Microsoft compatibility: checking for multiple initializers
          in the presence of anonymous structs

The checking for multiple ctor-initializers initializing several members
of a union (which is an error) did not work correctly in the presence
of anonymous structs (a Microsoft extension).  Now fixed.

  struct C {
    C() : i(0), j(1) { };  // No longer gets an error
    union {
      struct {
        int i;
        int j;
      };
      int k;
    };
  };

8/13/97   C++-generating back end: names of conversion functions generated

In the C++-generating back end, names of conversion functions are now
generated from the result type of the conversion function instead of
using the name stored in the IL entry.  This ensures that all the
special-case processing done on names in the C++-generating back end
is done also for any names referenced in conversion function result types.

8/13/97   Processing of trigraphs in multibyte character mode

The processing of trigraphs (and line splices) after the first trigraph
on an input line, in multibyte character mode, had a bug.  This has
been corrected.  The problem was only visible if either

QUESTION_MARK_CAN_OCCUR_AS_PART_OF_MULTIBYTE_CHAR or
BACKSLASH_CAN_OCCUR_AS_PART_OF_MULTIBYTE_CHAR

was TRUE, which is not required for many character sets.

8/12/97   Spurious invalid covariant return type error

A spurious error would occur when a member function of a nested class
returns a type that is covariant with the return type of the overridden
function, and in which the return type of the overridden function is the
enclosing class type.  This has been fixed.

  struct A {
    virtual A& f();
  };
  struct B : public A {
    struct C : public A {
        virtual B& f();
    };
  };


8/12/97   C++-generating back end, Microsoft compatibility: no qualified name
          on reference to member within class definition

MSVC++ does not allow a use of a qualified name for a class member
within the definition of that class (including inside nested classes),
so the C++-generating back end now uses a simple name for such references.
This is a refinement of the change made on 7/8/97.

8/12/97   Microsoft compatibility: accessibility of base classes

In Microsoft mode, a base class is now considered accessible if one
has member access to the base class.  (This is in addition to the other
reasons for which it might be accessible.)

  class A {
    friend void f();
  };
  class B : private A {};
  void f() {
    B* p = 0;
    A* q = p;  // Accepted in Microsoft mode
  }

8/11/97   Invalid IL for return in C function with cv-qualified class type

A change in 2.36 introduced a bug in C mode: a return of a class value
in a function whose return type is a cv-qualified class type can create
IL that includes an enk_temp_init node, which is valid only in C++ mode.

  struct A {
    int i;
  };
  const struct A f();
  const struct A g() {
    return f();
  }

8/8/97    TARG_SIZE_T_INT_MAX default inappropriate when host long long
          is used as a_host_large_integer

The recent changes to use a_host_large_integer in place of "long" in
various places, to better support the mode where the host "long long" is
used as the container for all target integers, introduced an inappropriate
default for TARG_SIZE_T_INT_MAX.  That has been corrected to match the
default setting chosen for TARG_SIZE_T_INT_KIND.

The current recommendation for #defines to support long long using the
host long long are as follows (assuming a host machine with 32-bit
int and long and 64-bit long long):

#define LONG_LONG_ALLOWED 1
#define INTEGER_VALUE_REPR_IS_A_HOST_INTEGER 1
#define TYPE_FOR_AN_INTEGER_VALUE unsigned long long
#define TYPE_FOR_A_SIGNED_INTEGER_VALUE long long
#define PRINTF_FORMAT_FOR_SIGNED_INTEGER_VALUE   "%lld"
#define PRINTF_FORMAT_FOR_UNSIGNED_INTEGER_VALUE "%llu"
#define PRINTF_FORMAT_FOR_HEX_INTEGER_VALUE      "%llx"
#define MAX_INTEGER_VALUE 9223372036854775807LL
#define MIN_INTEGER_VALUE (-MAX_INTEGER_VALUE-1)
#define MAX_UNSIGNED_INTEGER_VALUE 18446744073709551615ULL
#define HOST_ALIGNMENT_REQUIRED 8

Prior to this latest change, something like the following was also
required:

#define TARG_SIZE_T_MAX ((unsigned int)0xffffffff)

8/1/97    cv-qualifiers preserved on type of lvalue result of assignment
          operation

Assignment operations in C++ return lvalues.  The cv-qualifiers on
such lvalues had inadvertently been dropped.  Now they are preserved.
This was significant only if the cv-qualifiers were "volatile", since the
left operand of an assignment cannot be const-qualified.

  void f(int&);
  void g(int p) {
    volatile int i = 0, j = 0;
    f(p ? i += 1 : i += 0x100);  // Now gets error, as it should
  }

7/31/97   Cast of template-parameter-based expression to bool type

A cast of a template-parameter-based expression to bool type was
rejected during the prototype instantiation of a template.  Now fixed.

  template <bool b> struct B {};
  template <class T> struct A {
    B<bool(T::X)> b;
  };

7/31/97   Implicit conversion of pointer-to-function to void * nonstandard

The implicit conversion of a pointer-to-function to void * was allowed
by the ARM, but it is no longer allowed by the WP.  We now issue an
error in strict mode, and a warning otherwise.

7/29/97   Microsoft compatibility: "constructor call" returns an lvalue

In Microsoft bugs mode, a "constructor call" like X(y) -- which is actually
a functional-notation cast to type X -- is now considered to produce an
lvalue.  This is necessary because MSVC++ allows things like &X(y).

7/28/97   Microsoft compatibility: (expr, 0) considered null pointer constant

In Microsoft mode, an expression of the form (expr, 0), where the second
operand is some form of null pointer constant, is now considered to
be a null pointer constant.  It can therefore be implicitly converted
to a pointer or pointer-to-member type.

7/26/97   Explicit cast of overloaded function of derived class to
          pointer-to-member of base class selects matching function

An explicit cast of an overloaded member function name of a derived
class to a pointer-to-member of a base class thereof now selects
the proper function out of the overload set.

  struct A {};
  struct B : public A {
    void f();
    void f(int);
  };
  typedef void (A::*pmf)(void);
  pmf pfn = (pmf)&B::f;

7/26/97   In static_cast of T1 Derived::* to T2 Base::*, T1 must be T2

The processing for static_cast for pointers-to-members has been slightly
too permissive on casts of pointers to members of derived classes to
pointers to members of base classes.  The underlying type is required
to be the same, but that wasn't checked for.  Now fixed.

  struct A {};
  struct B : public A {
    int i;
  };
  int main () {
    (void)static_cast<float A::*>(&B::i);  // Now gets error
  }

7/25/97   long --> int considered promotion in Microsoft bugs mode

In Microsoft bugs mode, an implicit conversion of long to int is now
considered a promotion instead of a standard conversion.  This matches
the behavior of MSVC++ 4.2 and 5.0 and eliminates an ambiguity on
cases like the following:

  int abs(int);
  double abs(double);
  long f(long j) {
    return abs(j);
  }

7/25/97   Error on typeid(overloaded-function)

An error is now issued for a use of typeid on an overloaded function
or function template.  Formerly, the failure to do this check
resulted in an internal error in mangled_encoding_for_type.

  #include <typeinfo.h>
  void gg();
  void gg(int);
  int main() {
    const std::type_info *p = &typeid(gg);
  }

7/24/97   Unnamed template parameters

Unnamed template parameters are now supported.

  template <class,int> struct A {};
  A<char,1> a1;

7/22/97   Value of enumerator based on expression containing template
          parameters

An enumerator in a template whose value is given by an expression
based on nontype template parameters was incorrectly evaluated as
an error constant during the prototype instantiation, which could
cause errors later when the enumerator value was used.  Now fixed.

7/11/97   IL CHANGE: implicit_step_of_explicit_cast flag in an_expr_node

A new flag, implicit_step_of_explicit_cast, has been added to the
operation variant of an_expr_node.  This is used by the C++-generating
back end to recognize casts to inheritance-related classes that
were generated implicitly to implement part of an explicit cast.
For example, if a C * pointer is cast to an A * explicitly, where C
is derived from B which is derived from A, the generated IL would
have a cast to B * marked with implicit_step_of_explicit_cast, followed
by a cast to A * not so marked.

7/10/97   Microsoft compatibility: asm --> __asm, long long --> __int64

In Microsoft mode, asm statements are now always put out using the __asm
keyword, and __int64 is always put out instead of "long long".

7/10/97   C++-generating back end: pointer-to-member casts for MSVC++ 4.2

MSVC++ 4.2 doesn't like pointer-to-member casts that change both the
base class and the member type, so the C++-generating back end has
been changed to avoid putting out such things when --microsoft_version=1000
or less.

7/10/97   IL CHANGE: microsoft_mode and microsoft_version added to il_header

When MICROSOFT_EXTENSIONS_ALLOWED is TRUE, the values of global variables
microsoft_mode and microsoft_version are now recorded in il_header.

7/10/97   C++-generating back end: "this->" suppressed on function calls

"this->" on a member function call, unnecessary because it's implied,
is now suppressed.  This works around a bug in MSVC++ 4.2. (7/21: do
not do this for explicit calls of constructors, a Microsoft extension.
9/9: Do not do this for explicit calls of destructors. 5/21/99: this is
done only when microsoft_version=1000, because it causes other problems.)

7/8/97    C++-generating back end: representation of partial instantiations

The C++-generating back end now puts out an explicit specialization to
represent a "partial instantiation" -- that is, an instantiation of a
template declaration only, as opposed to a full instantiation that
indicates the definition of the template instance.  The front end records
this information by means of a secondary-declaration source sequence entry
when NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and/or
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE.  For
example, if the latter is TRUE and the original source looks like this:

  template <class T> struct S { ... };
  S<int> *psi;

the generated C++ would be:

  template <class T> struct S { ... };
  template<> S<int>;        // New with this change
  S<int> *psi;

As before, a full specialization of S<int> will be put out elsewhere in
the generated program, once it is needed.  But without this change the
first reference to S<int> would have been preceded its specialization
declaration, yielding invalid C++.

7/8/97    C++-generating back end: reference of nested class to itself

To avoid a bug in MSVC++ 5.0, the C++-generating back end now puts out
a reference to a class within itself as an unqualified name.

7/8/97    C++-generating back end: no default arguments on specializations

Specializations are not allowed to have default arguments.  The
entity that's actually referenced is the primary template, and the
default arguments, if any, should be declared there.  The C++-generating
back end now suppresses default argument expressions on specializations
put out for generated instances.

7/8/97    C++-generating back end: extra "template<>" eliminated

When the front end is configured to use the C++-generating back end,
and source sequence entries for instantiations are enabled by setting
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS and
CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS to TRUE, a
non-template member function or static data member was put out with
an extra "template<>" at the beginning.  Now fixed.

7/7/97    Eliminating unneeded template instances in -tused mode

When source is compiled with both --remove_unneeded_entities and -tused, an
improvement has been made in eliminating unneeded template instances from
the IL that is passed to the back end.  Since -tused mode means an
instantiation is triggered whenever a template instance is referenced, and
since template instances generally have external linkage, such entities
were not removed.  But now if (in -tused mode) a template is instantiated
as a result of a reference that is not itself needed, the template instance
is regarded as a candidate for elimination.  In the following, for example,
if g is never called, then f<int> is not needed:

  template <class T> T f(T t) { return t; }
  inline int g(int i) {
    return f(i);
  }

7/7/97    cfront compatibility: local type in block-extern declaration

In cfront compatibility mode a local type is now permitted in the
declaration of a variable or function with linkage, e.g.,

  void f() {
    struct S { ... };
    extern S *ps;           // No error in cfront mode
  }

7/3/97    Type deduction does not handle member class templates correctly

The type deduction routines were not correctly handling member class templates.
This could result in type deduction failing for a given call, as illustrated
by the following example.  It could also cause a call to incorrectly match
a given template, which would then result in an internal error.  This
has been fixed.

  struct A {
    template<class T> struct B {};
  };
  template<class T> void f(A::B<T>);
  int main() {
    A::B<int> ab;
    f(ab);
  }

7/2/97    cv-qualifier missing in lowered IL for anonymous union reference

A cv-qualifier was missing on an intermediate field selection generated
by IL lowering for an anonymous union reference.  This is probably of
no significance except to those that do scrupulous type checking on
the IL tree.

  struct A {};
  struct B {
    A *f() const;
    union {
      A * ua;
    };
  };
  A *B::f() const { return ua; }  // Field selection for anon union on ua
                                  // was missing cv-qualifier

7/2/97    Bug when template friend declarations refer to nested classes

A template friend declaration that refers to a nested class of a class
template did not correctly handle instances of the nested class that
were created prior to encountering the template friend declaration.
This has been fixed.  The following example resulted in an access error
when compiled in strict mode:

  template<class T> class A {
    struct B { B(); };
  public:
    struct C{ C() { A<char>::B b; } };
    template<class T2> friend class A<T2>::C;
  };
  A<char>::C c1;
  A<int>::C c2;

7/1/97    Predeclaration of structs to allow compilation with old C++ compilers

A few structs in il_def.h, lexical.h, scope_stk.h, and symbol_tbl.h are
now predeclared outside of any other structs.  This allows the front
end source to be compiled with C++ compilers that use nonstandard rules
for the scope in which a struct declaration is injected.

7/1/97    Microsoft compatibility: last line of file can end with backslash

In Microsoft mode, if the last line of a file ends with a backslash,
a warning is now issued instead of an error.

7/1/97    Microsoft compatibility: cv-qualifiers following a comma

Microsoft allows declarations like the following, which are nonstandard:

  int i, const j;

In MSVC++ 2.0, the declared type of j ends up as "const int", and we
duplicated that in Microsoft mode.  In 4.2 and 5.0, however, the invalid
const cv-qualifier is ignored, with a warning.  We now do the same for
--microsoft_version=1000 or greater.

7/1/97    Microsoft C mode: integral <--> pointer implicit conversions

In Microsoft C mode, implicit conversions between pointers and integral
types are now allowed, with a warning.

  long handle;
  int f(void* p) {
    return handle == p;
  }

7/1/97    Microsoft C++ mode: cast of pointer to smaller integer allowed

In Microsoft C++ mode, an explicit cast of a data or function pointer
to a integral type that is smaller than the pointer is now allowed,
with a warning.

6/30/97   C-generating back end: code for mutable reference missing parentheses

The code generated by the C-generating back end for a reference to a
mutable field was sometimes missing a set of parentheses, with the
consequence that it did not compile correctly.

  struct A {
    mutable int x;
  };
  void g();
  void h(const A *f) {
    (g,f)->x = 5;
  }

6/27/97   Internal error on break statement within dependent statement
          in catch clause (cfront mode only)

In cfront mode, an internal error (in connection with object-lifetime
processing) could occur when a break statement appeared as the dependent
statement of an if statement within a catch clause; it was necessary that
the dependent statement not appear within braces.  Now fixed.  Here's an
example:

  void f() {
    for(;;) {
      try { /* ... */ }
      catch (int x) {
        if (x == 0) break;     // cfront-mode internal error is now fixed
      }
    }
  }

6/26/97   Internal error when template qualified destructor name does not
          match the left operand of "." or "->" operator

An internal error would result if an explicit destructor call used a
qualified name in which the type of both the qualifier and the left operand
of the field selection were different instances of the same class template.
This has been fixed.

  template <class T> struct A { };
  int main() {
    A<int>* p;
    p ->A<float>::~A();
  }

6/25/97   Abort on use of anonymous union member in nontype template argument

A use of an anonymous union member of reference type in a nontype
template argument expression (which is an error) resulted in an abort.
This has been fixed.

  static union {
    int &x; 
  };
  template <int* ip> struct A {};
  A<&x> a;

6/25/97   Precedence warning caused by misplaced parenthesis

A coding mistake in templates.c could cause a precedence warning when
building the front end, although the code executed correctly.  This
has been fixed.

6/25/97   Suppressing automatic instantiation of unneeded template instance

If automatic template instantiation is triggered by a reference that proves
to be unneeded, a __TIR__ variable is no longer put out in lowered code
and the instance_required flag is no longer set in the routine or variable
entry.  For example:

  template <class T> void f(T) { }
  template <class T> struct S { static T x; };
  template <class T> T S<T>::x = T(0);
  static void g() { f(S<int>::x); }             // Never referenced

With this change __TIR__ variables are not put out for f(int) or S<int>::x,
since they are only referenced in an unneeded static function.  (This
optimization is only available when MAINTAIN_NEEDED_FLAGS is TRUE and the
source is compiled with --remove_unneeded_entities.)

6/24/97   Internal error in using-directive lookup in error case

An internal error could result when an sk_undefined symbol is included
in a lookup set with an overload set from a namespace made visible
by a using-directive.  This has been fixed.

6/24/97   Microsoft compatibility: function parameter type involving pointer
          or reference to array of unknown bounds

An error is no longer issued in Microsoft C++ mode when a function
parameter type contains a pointer or reference to array of unknown bounds:

  typedef unsigned histogram[][32][32];
  void foo (const histogram *bar);    // No longer an error in Microsoft mode

Controlling whether this check is done is a new global variable,
ptr_to_unknown_bound_array_allowed_in_param_type, which is set to TRUE in
Microsoft and cfront modes and FALSE in strict ANSI mode.  Its default value
is DEFAULT_PTR_TO_UNKNOWN_BOUND_ARRAY_ALLOWED_IN_PARAM_TYPE, defined in
lang_feat.h.

6/24/97   Saving of IL header information when using precompiled headers

Some of the IL header fields were not being correctly reset after
reading a precompiled header file.  This could cause problems if the
memory allocated when a precompiled header file did not exactly match
the memory allocated when the precompiled header file was created.
These problems haven't been observed in our default configuration, but
could occur if memory was allocated as part of the processing of command
line options that do not affect the selection of a precompiled header file.
This is now fixed.

6/24/97   lower_il.c doesn't compile with CHECKING off

A fragment of code in lower_il.c wasn't standard C when CHECKING is
set to FALSE, and therefore might not compile with some C compilers.
Now fixed.

6/23/97   Microsoft compatibility: allow omission of decl-specifiers in C

A warning is now issued (instead of an error) in Microsoft C compatibility
mode for declarations with no decl-specifiers at all -- for example:

  x;              /* Now accepted with a warning in Microsoft C mode */

6/23/97   Invalid IL if conversion operator declaration is first in comma-list

Invalid IL is no longer produced (and internal errors are no longer issued
in IL lowering and elsewhere) when a conversion operator is the first
declaration in a comma-list -- for example:

  struct S {
    operator int(), i;     // A diagnostic is still issued for the missing
  };                       //   type on "i" but the internal error is fixed

6/23/97   Microsoft compatibility: extern inline allowed

By default "extern inline" is now enabled in Microsoft compatibility mode.
This eliminates a spurious error on the following:

  template <void (*fp)()> class C { /* ... */ };
  inline void f() { /* ... */ }
  C<f> c;                  // Error (non-external template argument) is no
                           //   longer issued

6/20/97   Abort or internal error using non-memory mapped PCH files

The routines that read memory regions from a PCH file when not using
memory mapping did not handle NULL mem_region_table entries properly.
This could cause an abort or an internal error.  This has been fixed.

6/19/97   Internal error in partial ordering comparison of deduced array
          bounds

An internal error would occur during the partial ordering comparison of
two function templates when one or both of the templates contained a deduced
array bound.  This has been fixed.

  template <class T, int I> void f(T(&)[I]);
  template <int I> void f(int(&)[I]);
  int main() {
    int a[5];
    f(a);
  }

-------------------------------------------------------------------------------
Version 2.36, June 17, 1997

6/17/97   IL version number changed to 2.28

6/17/97   Explicit specification of template arguments in declarations

Explicit specification of function template argument lists is
supported in declarations, but not yet in expression contexts.  An
explicit template argument list may be specified in an explicit
specialization, an explicit instantiation, or in a friend declaration.
When several templates could potentially generate a given function
signature, an explicit template argument list can be used to specify
the template that is desired.

The ability to specify an explicit template argument list in a friend
declaration is useful when guiding declarations are disabled.  When
guiding declarations are disabled a declaration, such as the friend
declaration of "g" in the example below, declares an unrelated
function.  Note: Guiding declarations have been removed from the
language.  They are enabled by default for compatibility reasons, but
are disabled in strict mode.

  template <class T> void f(T);  // #1
  template <class T> void f(T*); // #2

  template <> void f<int*>(int*);  // specializes #1
  template <> void f<int>(int*);   // specializes #2

  template <class T> void g(T);

  template <class T> struct A {
    friend void f<>(T);
    friend void g(T);  // declares a new function, does not refer to the
                       // template (when guiding declarations are disabled)
  };

6/17/97   Default arguments and nested instantiations

Because of the way in which default arguments and inline function bodies
of functions declared within a class are handled, a spurious error could
occur if an instantiation caused by the delayed scanning of default
arguments resulted in the definition of an inline function or an
instantiation of a function that depends on the existence of a default
argument for which the delayed scanning has not yet been done.  This
has been fixed.

6/17/97   Incorrect cleanup state information in ctor-initializers

When a constructor definition contains a ctor-initializer whose evaluation
creates destructible temporaries, the object lifetime information for
that ctor-initializer did not point to the correct previous initialization
in the parent lifetime.  As a consequence, if an exception is thrown
within the ctor-initializer list, some members constructed earlier
were not destroyed.

  struct A {
    A();
    ~A();
  };
  int f() { throw 0; }
  struct B {
    A a;
    int i;
    B() : i((A(),f())) {}  // Constructed member "a" is not destroyed
  };

6/17/97   Partial lowering of EH -- useless dynamic init entry for freeing
          of storage after array new eliminated

When partial lowering of exception handling is done, special dynamic
initialization entries are left in the IL to indicate freeing of storage
if an exception is thrown before a "new" completes.  For array "new"s,
these are supposed to be eliminated, because the freeing is handled by runtime
routines.  However, in some cases useless entries for arrays were kept.
This was mostly harmless, because the entries were never used, but
now they have been eliminated.

  struct A {
    A();
    ~A();
    void *operator new[](size_t);
  };
  void foo() {
    A* p = new A[3];
  }

6/16/97   Code to indicate EH cleanup state at labels generated by IL lowering

IL lowering generates labels in two cases:

  -- for the epilogue of a destructor;
  -- for a break label for a loop, when the loop test is a condition
     declaration and the loop does not have a break label already.

Code is now inserted after these generated labels to record the exception
handling cleanup state, to make them consistent with all other
(i.e., non-generated) labels.

6/16/97   EH cleanup state at break label in destructor

The cleanup state set at a break label at the top level in a destructor
did not include the destructions of members and base classes to be done
in the destructor wrapper code.  Now fixed.

  struct B {
    B();
    ~B();
  };
  struct A {
    B mem;
    A();
    ~A();
  };
  void throws_exception();
  A::~A() {
    for (int j = 0; j < 5; j++) {
      if (j == 3) { break; }
    }
    // Cleanup state at break label here does not destroy member "mem"
    throws_exception();
  }

6/16/97   IL lowering bug on placement delete processing

An IL lowering bug related to placement delete caused an internal
error on examples like the following because destructible entities
preceding the "new" (e.g., the temporary for f() in this example)
did not get some crucial initial processing.  Now fixed.

  struct X {
    X(int i = 0);
    X(const X& x);
    ~X();
  };
  X f();
  struct C {
    C() { }
    void *operator new(size_t s, float f);
    void operator delete(void *p, float f);
  };
  void g() {
    X b(1);
    (b = f()), new(1.2f) C();
  }

6/16/97   EH cleanup state during destruction of inner-lifetime temporaries

When an initialization is performed, it is sometimes the case that
a block-scope entity is initialized while temporaries created in the
initializing expression are still active.  When those temporaries are
destroyed, the exception handling cleanup state should include the
block-scope entity as well as any remaining inner-lifetime temporaries.
This was not the case.  As a consequence, if an exception was thrown
within a destructor call for such a temporary, the block-scope
entity was not destroyed.  Now fixed.

  struct X {
    X();
    ~X();
  };
  X f(const X&);
  X g();
  int main() {
    const X& r = f(g());  // Cleanup state was wrong during destruction of
                          // temporary for g(): temporary for f() not
                          // destroyed
  }

IL CHANGE: This was implemented, in part, by adding a flag to a_dynamic_init
called overlaps_temps_in_inner_lifetime.  It is set for entities whose
lifetimes overlap that of inner-scope temporaries.  If you use partial
lowering of exception handling constructs, you should change your code
so that entities with this flag set are not destroyed if they are
encountered on the cleanup chain at a point before they have been
initialized.

6/13/97   EH cleanup state after initialization of local static variable

After initialization of a local static variable that is an aggregate,
when partial lowering of exception handling is being done, the cleanup
state incorrectly included the entry to clear the "initialized" flag
for the local static variable.

  struct A {
    A();
    ~A();
  };
  void f() {
    static A a[2];
    // cleanup state here included clearing the initialized flag for "a"
    ...
  }

If full lowering of exception handling is done, if such a local static
aggregate is initialized with a brace-enclosed list, the cleanup state
at the end of the initialization would lose any initializations that
precede the local static variable declaration:

  struct A {
    A(int);
    A();
    ~A();
  };
  struct B {
    A a;
  };
  void f()
  {
    A a;
    static B b = {1};
    // cleanup state here does not include destroying "a"
    ...
  }

6/12/97   Using-declaration that specifies a constructor or destructor

In accord with a recent clarification to the Working Paper, an error is now
issued (instead of a warning) when a using-declaration in a class definition
specifies a base class constructor or destructor.

  class B { B(); ~B(); };
  class D : public B {
    using B::B;           // Error
    using B::~B;          // Error
  };

6/12/97   Spurious error on local-class friend function declaration

When a friend function declaration appears in a local class, a spurious
linkage-conflict error could occur in -A mode.  This bug, introduced
in version 2.34, is now fixed.

  static int f();
  void g() {
    struct X {
      friend int f();      // Spurious error no longer issued
    };
  }

6/11/97   IL lowering of loop conditions: block <--> scope wrong

The lowering of a condition declaration in a loop, where the dependent
statement of the loop has an associated scope, produced incorrect
IL: a block statement pointed to a scope which did not point back to
the block statement.  Now fixed.

  void f() {
    while (int x = 1) {
      int i = 6; 
    }
  }

6/11/97   Escape sequences recognized in #line directive file name strings

Escape sequences are now recognized in the string literals that indicate
the file names in #line directives.  This is required by the ANSI/ISO C
standard.  This contrasts with the header names in #include directives,
where escape sequences continue not to be recognized.  (The ANSI/ISO C
standard leaves that as an implementation choice, and ignoring escape
sequences is what most compilers seem to do.)  The old behavior on
#line directives is preserved when old-style preprocessing is selected.

6/11/97   Overload resolution cv-qualifier tiebreakers in cfront mode

In overload resolution, the tie between two equally-ranked conversions
can be broken by the fact that one of them adds cv-qualifiers that the
other one doesn't.  This tiebreaker test in cfront mode has been changed
to something simpler, which seems to model cfront's behavior better.

6/10/97   Multi-level pointer qualification conversions are exact matches

Pointer conversions that add cv-qualifiers at levels other than the
first in a multi-level pointer are now considered to be exact matches
in overload resolution. Formerly, they were considered standard
conversions.

6/9/97    declared_type field in function parameter variables

When GENERATE_SOURCE_SEQUENCE_ENTRIES is TRUE, the declared_type field in
variables that represent function parameters will now record the type as
declared, i.e., before adjustments such as the decay of array type to
pointer.  (Note: this has not yet been implemented for parameters of
function template instantiations; the template declaration may involve
template parameter types, which are not permitted in the IL.)

6/9/97    EH cleanup state during initializations of file-scope entities

A change made in 2.34 broke the code that sets the cleanup state when it's
used within the generated file-scope initialization routine.  This bug
is not particularly visible since exceptions thrown before all file-scope
variables are initialized will generally cause a call of terminate().

6/9/97    Missing diagnostic on default argument in template instance friend
          declaration

A friend declaration that refers to an instance of a template may not
specify a default argument because the instance does not participate
in overload resolution (only the template does).  This has been fixed.

6/9/97    EH cleanup for partially-constructed aggregates -- no conditional
          flag

The code generated by IL lowering to handle exception handling cleanup on
partially constructed aggregates no longer makes use of a conditional
flag.  This is a slight efficiency improvement, and does not cause a
version-to-version object-code compatibility problem.

Fixed while making this change: a bug in cases where the last initialization
of a destructible entity in an aggregate is followed by a dynamic
initialization of a non-destructible entity which calls a function that
throws an exception:

  struct A {
    A(int n);
    ~A();
  };
  struct B {
    A a;
    int i;
  };
  int f() { throw 1; }
  int main () {
    try {
      B b = {1, f()};  // Cleanup of b.a wasn't done correctly
    } catch (...) {
    }
  }

6/7/97    Cast of class object to same type, plus or minus cv-qualifiers

For a class type for which copy construction is done by bitwise copying,
an expression of that class type cast to the same type, or the same type
with more or fewer cv-qualifiers, is now copied to a temporary.  Formerly,
no copy was made; the original class object was simply accessed with the
new type.  This new behavior is mandated by the Working Paper.  The old
behavior continues in cfront mode.

A related bug was also fixed: when a class expression was cast to the
same type with different cv-qualifiers, the cv-qualification of the result
type was not adjusted.  As a consequence, if the result were used to call
a member function, the wrong function might be called, or an error
might be issued.

  struct B {
    void f() {}
  };
  void f(const B& b) {
    B(b).f();  // No longer an error; B(b) has type "B" now, not "const B"
  }

6/6/97    Using-declarations: abort during error recovery

An abort no longer occurs in the following case, where the name introduced by
a using-declaration is also the name of the class (which is disallowed):

  struct A {
    void f(char*);
    void f(long);
  };
  struct f : public A { 
    using A::f;               // An error is still issued, but an internal
  };                          //   error no longer results

6/6/97    Microsoft compatibility: __declspec and constructor definition

A spurious error is no longer issued when, in Microsoft compatibility mode,
a __declspec modifier appears on the out-of-class definition of a
constructor or destructor.  For example:

  class C {
  public:
     __declspec(dllexport) C();
  };
  __declspec(dllexport) C::C() { }     // Spurious error no longer issued

6/6/97    Spurious error on overloaded friend template functions

A spurious error is no longer issued during the initial scan of a template
with overloaded friend function templates, such as:

  template <class T> class X {
    template <class T2> friend X<T2> func(const X<T2>&);
    template <class T3, class T4> friend T3 func(T3, T4);
  };

6/5/97    Spurious error on namespace template instance friend declaration
          when guiding declarations are disabled

With guiding declarations disabled, a spurious error was issued on a friend
declaration that refers to an instance of a function template declared in
a namespace.  In addition, when guiding declarations are enabled, such
a friend declaration was incorrectly treated as a guiding declaration.

  namespace N {
    template <class T> void f(T);
  }
  class B {
    friend void N::f(int);
  };

6/5/97    INDICATE_CLEANUP_STATE_IN_UNREACHABLE_CODE

Heretofore, when partial lowering of exception handling features was
done, leck_cleanup_state instructions were put out even in unreachable
code, just in case a back end is using them statically to develop a table
of cleanup address ranges.  This functionality is now controlled
by the separate configuration option
INDICATE_CLEANUP_STATE_IN_UNREACHABLE_CODE, whose default definition
gives the same behavior as before.  Also (IL CHANGE), the unreachable
cleanup state instructions now have the new kind
leck_unreachable_cleanup_state.

6/5/97    Microsoft compatibility: local type in block-extern declaration

In Microsoft mode a local type is now permitted in the declaration of a
variable or function with linkage, e.g.,

  void f() {
    struct S { ... };
    extern S *ps;           // No error in Microsoft mode
  }

6/5/97    Microsoft compatibility: relaxed access checking for member types

In Microsoft mode, derived classes are now allowed to access an
inaccessible member type inherited from a base class if the reference is
via an unqualified name.

  class A {
    typedef int I;
  };
  class B : public A {
    I x;      // Accepted now in Microsoft mode (really an error)
    A::I xx;  // Still an error
  };

6/4/97    With multibyte character support enabled, some C characters are
          seen as alphabetic

In some European character sets, some of the character positions for
C punctuation are assigned to alphabetic characters.  For example,
in some German character sets the character position that is ASCII "]"
is "U umlaut".  That means once the setlocale call has been done, "]"
suddenly looks like an identifier character, which causes many strange
errors.  We have changed the initialization of the is_id_char array
to ensure that the problem characters, i.e.,

 [ \ ] ^ { | } ~

are always considered to be non-identifier characters.

6/4/97    Overloading operators on enum operands

Operator functions can now be overloaded on enum types.  Specifically,
it's now valid to declare an overloaded operator function that has
one or more enum-typed parameters and no class-typed parameters.
This feature is enabled and disabled by the command-line options
--[no_]enum_overloading.  DEFAULT_OPERATOR_OVERLOADING_ON_ENUMS
gives the default setting.

(6/12/97:) There are cases like the following that worked previously
and now, according to the current WP, should give an ambiguity error.
We think this suggests a problem with the WP, and we've made equality
and relational operators that have two operands of the same enum
type resolve to the builtin operator as before.

  enum E {E1};
  class A {
    A(E);
    friend int operator==(const A&, E);
  };
  int main() {
    E e;
    e == E1;  // Ambiguous according to WP
  }

6/2/97    Variable length arrays

Support for variable length arrays, as proposed for the new C standard and
specified in WG14/N637 (=X3J11/96-101), has been implemented in C mode.  If
VLA_ALLOWED is configured to TRUE, the feature may be turned on and off by
command line options --vla and --no_vla, which control global variable
vla_enabled.  The extension is not available in C++ mode.

  int f(int n) {
    int a[n];                 /* VLA declaration */
    return sizeof(a);         /* evaluated at run time */
  }

A VLA declaration may appear in a function parameter list or inside the body
of a function.  Only an automatic variable may be a variable length array.
The expression representing the dimension is evaluated at run time, as is
the sizeof operator applied to a VLA object.  A VLA typedef declaration may
appear only within a function.  A VLA declaration using the "[*]" syntax
(indicating an unspecified variable dimension) may appear in function
prototypes but not in function definitions.

IL CHANGE: New flags is_vla and has_assoc_vla_dimension have been added to
a_type.  The type entry itself does not contain a pointer to the associated 
dimension expression, because entities belonging to the file-scope memory
region cannot point to entities belonging to a function-scope memory
region; instead, an entry of type a_vla_dimension is placed on a linked
list pointed to by the routine's IL scope and must be looked up (see
find_vla_dimension in il.c).  A new expression node kind has been added,
enk_runtime_sizeof, along with two new statement kinds: stmk_set_vla_size
and stmk_vla_decl.  Type entries of kind tk_typeref have a new flag: when
has_variably_modified_type is TRUE, there is an stmk_vla_decl statement
that refers to the type and corresponds to a typedef declaration.  Variable
entries have two new flags: when has_variably_modified_type is TRUE, there
is an stmk_vla_decl statement that refers to the variable and corresponds
to a variable declaration; moreover, when is_vla is TRUE, allocation and
deallocation of memory is required for the variable.

The C-generating back end accepts IL containing VLA information and puts out
VLA constructs, so VLA_ALLOWED should be configured to TRUE only if the
underlying C compiler also supports VLAs.  As of this release, the code
output by the C-generating back end is not always valid C, in that
it sometimes has declarations following initializing assignments in
a single scope.  This is judged to be a small problem, since few people
want to read in C and generate C.

6/1/97    pointer_types_have_same_repr macro

A macro pointer_types_have_same_repr can now be defined if an implementation
has different types of pointers and the differences between them are
not completely determined by the type pointed to.  (For example, an
implementation might have 32-bit and 64-bit pointers for any underlying
types, and a language extension to choose the size.)  This new macro
is used in places that compare pointer and reference types for equality,
and can be used to distinguish the different pointer representations.
Note that this is not needed for near/far support, as the near/far
attribute for those cases is attached to the underlying type.

5/30/97   In constructor wrapper code, virtual base class pointers set earlier

In the wrapper code generated around constructors in IL lowering, the code
that sets the virtual base class pointers for an object has been moved
to before the calls of the constructors for the virtual base classes.
(Actually, a copy of the code is done before the calls of the virtual
base class constructors, and another copy is done when the constructor
is called for a subobject, in which case the virtual base class constructors
are not called.)  This is required by the Working Paper, [class.cdtor]
paragraph 2.

5/28/97   Eliminated function static to simplify making the front end
          continue after a catastrophic error

In templates.c, a static variable in process_deferred_instantiation_requests
has been moved to the file scope so that it can be reinitialized by
the routine used to initialize the front end before each translation unit.
This was done to permit the front end to continue compiling files even
after a compilation that terminated abnormally (e.g., via a
catastrophic error).

The same was done for the catastrophe_loop variable in diag_message
(5/29/97).

5/28/97   READ_SOURCE_IN_BINARY_MODE_FOR_MSDOS made default for Microsoft OSs

The default for READ_SOURCE_IN_BINARY_MODE_FOR_MSDOS is now TRUE for
Microsoft operating systems (including Windows 95 and Windows NT).
This allows the front end to deal properly with lines that have
Unix-style line terminators (no carriage return), which might appear
on files accessed over a network.  It also sidesteps a bug in Windows
NT related to using ftell/fseek to save and restore a position in a
file that has such nonstandard line terminators.

5/25/97   Long lifetime temporaries mode: destruction of temporaries on
          fall-through to next switch clause

In long lifetime temporaries mode (including cfront mode), temporaries
are supposed to be destroyed on a goto or label.  This was not being
done when one switch clause flowed into another.  Now fixed.

  struct A { A(); ~A(); A(const A&); };
  void f(A);
  int main () {
    switch (1) {
      case 1:
        f(A());
        // Temporary not destroyed here when long lifetime temps enabled
      default:
        break;
    }
  }

5/23/97   End of token set incorrectly when fetching pp-tokens from cache

When a pp-token was added to a token cache, the end-of-token pointer
was incorrectly set to the null-terminator of the copy of the token
string instead of the actual last character of the token.  This also
caused the token length to be one character too large when the token
was fetched from the cache.  This has been fixed.

5/22/97   Array rvalues are converted to pointer to first element

In C++, unlike in C, an array rvalue is converted to a pointer to its
first element.  This is now implemented.

This conversion is also done in C mode, as an extension.  A diagnostic
is issued in strict C mode.  IL CHANGE: a new expression operator,
eok_lvalue_from_call_result, is used to implement this in C mode.

5/22/97   Missing test for extra text after expected end of #elif

There was no test for extra text after the presumed end of an #elif
preprocessing directive whose expression evaluates to 0, encountered
while skipping lines because of a previous #if or the like.  This was a
problem in particular for an error case like the following, which
attempts to do a cast (not allowed in a preprocessing expression):

  #define X 1
  #ifndef X
  #elif (char)X
  #endif

The #elif expression was seen as "(0)0", and scanning stopped on the
right parenthesis.  That much is as it should be.  However, no error
was issued for the unprocessed final "0".

5/21/97   IL write/read error eliminated, return value optimization

A bug in IL lowering's processing of return value optimization has been
eliminated.  The symptom was an IL write/read internal error when
exception handling is enabled and object lifetime information is
preserved.  The copy constructor call eliminated must require a
default argument that contains a destructible temporary.

  struct A { ~A(); };
  struct S {
    S(const S& str, const A& a = A());
    S();
  };
  S f() {
    S str;
    return str;
  }

5/20/97   &(X::Y) as pointer-to-member in cfront mode

In version 2.35, a change was made such that a reference of the form
"&(X::Y)" is no longer considered to be a pointer-to-member.  However,
it turns out cfront accepts that form, so cfront mode has been changed
to accept it once again.

5/20/97   C++-generating back end: "template<>" prefix on generated instances

When the C++-generating back end is used, and

  NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
     CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS

is TRUE, the generated code contains "specializations" for all the
generated template instances.  These are now generated with the modern-form
"template<>" prefix on them.  The old specialization syntax can be
generated instead by setting
DEFAULT_OLD_SPECIALIZATIONS_FOR_GENERATED_INSTANCES or the variable
old_specializations_for_generated_instances to TRUE.

5/20/97   Conversion of void lvalue to rvalue in C is no longer an error

In C, converting an lvalue with an incomplete type to an rvalue has
undefined behavior.  To date, we have treated this as an error.  However,
to pass the test case associated with the C standards committee's
Defect Report 106, we now allow an lvalue with void type to be converted
to an rvalue.  It remains an error in C++.

5/20/97   IL CHANGE: is_template_class field in a_type

A new bit field named is_template_class has been added to the
class_struct_union variant of the type entry.  This field can be used
to determine whether a class is an instance of a class template or a
class nested within a class template.  Formerly, this field was in the
class symbol supplement and was named is_instance.

5/20/97   Instantiation control interface

A new layer of functions has been introduced in the automatic instantiation
processing to simplify the process of providing an additional or alternative
means of determining whether a given entity should be instantiated in the
current translation units.  The following new functions have been added to
templates.c:

  init_auto_instantiation_information
  entity_should_be_automatically_instantiated
  wrapup_auto_instantiation_information

See the Templates chapter of the internals manual for more information.

5/19/97   Error rather than warning on typeid before inclusion of <typeinfo>

The WP was recently changed so that it is an error to use the typeid
operator before <typeinfo> has been included, so the warning
heretofore issued for this situation has been changed to an error.

5/19/97   No lvalue-to-rvalue conversion on void expressions in C++

In accordance with a recent decision of the standards committee,
in C++ mode void expressions that are lvalues are no longer converted to
rvalues.  "Void expressions" are expressions whose values are discarded,
e.g., statement-level expressions, first operands of the comma operator,
and expressions explicitly cast to void.

  struct A;
  A &f();
  int main () {
    f();  // No longer an error
  }

5/19/97   Missing diagnostic on const member of nested anonymous union

A warning is now issued when an anonymous union has a const member and is
nested within a class for which no constructor is explicitly declared:

  struct S {
    union {
      const int i, j;
    };
  };

5/19/97   Abort with const member of nested anonymous union

An internal error has been fixed (along with a spurious diagnostic) in
processing an anonymous union that has a const member and is nested inside
another union:

  union U {
    union {
      int const A;
    };
  };

5/16/97   Disallow union member with copy assignment operator in cfront 3.0
          mode

Normally a member of a union cannot have a copy assignment operator.  The
following is still accepted in cfront 2.1 mode, but it now gets an error in
cfront 3.0 mode:

  struct S {
    S& operator=(const S&);
  };
  union U { S s; };             // Error, except in cfront 2.1 mode

5/16/97   Abort in cfront mode on anonymous union member with nonstandard
          assignment operator

An abort (with --exceptions --cfront_2.1) has been fixed on the following:

  struct S {
    S& operator=(const S&);
  };
  struct T {
    union {
      S s;             // Only a warning in cfront 2.1 mode
    };
  };
  void main() {
    T u1, u2;
    u1 = u2;          // Abort in generating definition of T::operator=
  }                   //    has been fixed

5/16/97   Diagnostic for defined but unreferenced variable that is initialized
          by constructor call

In most cases a warning is issued if a non-external variable goes
unreferenced; an exception has been that only a remark is put out when
there is an initializer with side effects.  However, this approach has
caused a diagnostic to be issued for use of the idiom in which a variable
of class type is defined simply to force its constructor to be called.  To
avoid what may sometimes be a spurious diagnostic, the front end is now
silent on an unreferenced variable that is initialized by a non-trivial
constructor:

  struct S { S(); };
  static S s;                   // a remark is no longer issued

5/15/97   Microsoft compatibility: Microsoft bugs mode

A new mode called "Microsoft bugs mode" has been added, and some of the
features formerly enabled by Microsoft mode are instead enabled by Microsoft
bugs mode.  Microsoft bugs mode is automatically enabled when Microsoft
mode is used and the configuration flag DEFAULT_MICROSOFT_BUGS is TRUE.
When DEFAULT_MICROSOFT_BUGS is TRUE, Microsoft mode can be enabled without
enabling Microsoft bugs mode through use of the --no_microsoft_bugs
command line option.  Likewise, if DEFAULT_MICROSOFT_BUGS is FALSE,
Microsoft bugs mode can be enabled with the --microsoft_bugs command line
option.  The "External Interface" chapter of the internal documentation
now contains a section that lists features accepted only in Microsoft bugs
mode.

5/15/97   Exception specification ignored diagnostic is now a remark

Exception specifications are ignored in Microsoft bugs mode.  A diagnostic
is issued when an exception specification is encountered.  The diagnostic
has been demoted from a warning to a remark.

5/14/97   Second operand of operators instantiated to expose friend functions

If the second operand of an overloadable operator has a template class
type, the class is now instantiated to expose any friend operator
functions the class declares that might apply.  (Such instantiation
was previously done only on the first operand, to expose member functions
that might apply.)

5/14/97   IL CHANGE: Source position of case labels and default labels in IL

In the IL representation of switch statements, the constants used for
case label values now have their source positions set to the position at
which the case label appears.  In addition, a new field default_position
has been added to the a_switch_clause entry, to indicate the source
position of the default label if there is one.

5/12/97   Exception handling cleanup state in switch clauses

The exception handling cleanup state determined in switch clauses
was sometimes incorrect, with the consequence that if an exception
were thrown during a destructor call, some of the required cleanup
would not be done.

  struct X {
    X(int);
    ~X();
  };
  struct Y {
    Y();
    Y(const Y&p);
    Y(const X&p);
    ~Y();
  };
  Y g();
  void foo() {
    Y y;
    switch(0) {
      case 0:
        {
          Y y1(X(0));  // Cleanup state at destruction of X temp is incorrect
          Y y2 = g();
        }
        break;
      default:
          ;
        break;
    }
  }

5/12/97   Microsoft compatibility: lvalue casts in C++ mode

In Microsoft Visual C++, casting an lvalue to its own type leaves it an
lvalue.  This behavior has been supported for a while.  However, now
(a) this behavior is supported in C++ only in Microsoft bugs mode,
and (b) no IL is generated for the cast (an eok_lvalue_cast operator is
no longer generated); this eliminates some internal error cases.
For example:

  int i;
  int &r = (int)i;  // Got internal error in Microsoft C++ mode

(6/11/97: an additional change was made for the case of casting
an lvalue to the same type but with more or fewer top-level cv-qualifiers.)

5/9/97    Microsoft compatibility: missing closing parenthesis on defined(...)

The Microsoft compiler allows the closing parenthesis on the preprocessor
"defined" operator to be omitted, as in

  #if defined(X

and gives no error.  We now accept this in Microsoft compatibility mode,
and issue a remark.  There are Microsoft headers that exploit this.

5/8/97    Invalid test in find_function_template_member

A test in find_function_template_member used the incorrect variant
of a symbol.  This could result in sporadic internal errors.  This
has been fixed.

5/8/97    Error on use of "this" in a constant expression

An error is now issued on a use of "this" within a constant expression.
The failure to check this heretofore led to internal errors, e.g., on

  struct A {
    void f() { int a[this]; }
  };

5/7/97    int(3.0/1) is nonstandard in integral constant expression

A floating constant is allowed in an integral constant expression
only as the immediate operand of a cast to an integral type.  This was
not correctly checked for a case like "int(3.0/1)".  An error is now
issued in strict mode.

5/7/97    Include of <sys/types.h> in host_envir.h restored

An include of <sys/types.h> from host_envir.h, removed as part of
changes in 2.35 (it didn't seem necessary), has been restored.  Two
customers complained that the front end no longer compiled in their
environments with that #include removed.

5/6/97    Microsoft compatibility: __declspec(uuid("...")) and __uuidof

Microsoft Visual C++ 5.0 adds two new features to deal with IDs
used with an object system called COM.  __declspec(uuid("...")) is used
on declarations of classes to indicate the ID associated with the class.
__uuidof(...) is an expression operator that returns a struct of type
_GUID filled with the proper values to represent the ID associated with
the class type underlying its operand.

5/5/97    a_decl_modifiers_block

The declaration routines that deal with declaration modifiers (e.g.,
the Microsoft __declspec(...) modifier) have, in the past, passed
around a bit set of type a_decl_modifier.  Now, they pass around a
structure of type a_decl_modifiers_block, which includes the
bit set and some additional declaration modifiers that require
more than just a single bit.  This change should make it easier
for our customers to add custom declaration modifiers, but at the
expense of potential incompatibility with changes already made.
This change affects only the way these modifiers are passed around
within the front end; the IL representation of decl_modifiers has
not been changed.  The decl_modifiers field in a_routine, for example,
is still the bit set it has always been.

5/5/97    Instantiation pragmas should not apply to inline functions

When an instantiation pragma (instantiate, do_not_instantiate,
can_instantiate) is used to instantiate (or suppress instantiation of)
all members of a class, inline functions should not be affected.  A
bug was introduced in version 2.32 that caused such pragmas to affect
the instantiation of inline functions.  This has been fixed.

  template <class T> struct A { void f(){} };
  #pragma do_not_instantiate A<int>  // should not affect A<int>::f
  int main() {
     A<int> a;
     a.f(); // should be instantiated here
  }

5/5/97    Disabling alternative tokens in strict mode

It is now possible to disable the recognition of the alternative tokens
(e.g., "not", "and", "<:", etc.) in strict mode by specifying the
--no_alternative_tokens option.  Previously, this option could be specified,
but was ignored in strict mode.

5/2/97    Microsoft compatibility: new __declspec attributes

Support for __declspec(selectany) and __declspec(nothrow) has been added.
The latter is recognized only in C++ mode.

5/2/97    ALLOW_VOID_QUESTION_OPERAND_IN_GENERATED_C

The C-generating back end has always included code to rewrite void
operands of "?" operands as "(operand, 0)" to avoid some bugs in
C compilers.  Formerly, this was done only when generating K&R C,
because pcc has problems with such operands in some cases.  Now, there
is a separate configuration flag for this rewrite, i.e.,
ALLOW_VOID_QUESTION_OPERAND_IN_GENERATED_C.  The default is TRUE iff
C_GEN_BE_GENERATES_ANSI_C is TRUE, which produces the same behavior
as before.

5/2/97    Default diagnostic threshold when listing dependencies or includes

When the --dependencies or --trace_includes command-line option is
specified, the error threshold is changed to error (i.e., warnings
are not put out by default).  As of now, however, this is not done
when --no_preproc_only is also specified.

5/1/97    Microsoft compatibility: suffixes like "i32" on integral constants

The front end now supports suffixes like "i32" on integral constants
in Microsoft mode.  They indicate the size in bits of the constant,
i.e., "15i32" is a 32-bit constant with the value 15.  The unsigned
version is indicated by a "u", as in "15ui32".  Sizes 8, 16, 32, and
64 are supported if integral types with those sizes exist.

5/1/97    Microsoft compatibility: explicit constructor calls

In Microsoft compatibility mode, explicit calls of constructors are
now allowed:

  struct C {
    C();
    C f();
  };
  C C::f() {
    this->C::C();   // Calls constructor on "this"
    return C::C();  // Creates temporary of type C (not same as previous)
  };

5/1/97    Microsoft compatibility: explicit specializations inside a class
          definition

The Microsoft compiler permits a new-style specialization of a member
function template within the class definition, even though this is
not permitted by the Working Paper.  Furthermore, when a constructor
is specialized with a signature that would, for a normal function,
be considered a copy constructor, such a specialization suppresses the
generation of an implicitly declared copy constructor.  The front
end now emulates this behavior in Microsoft mode.

  extern "C" int printf(char *, ...);
  template <class T> struct A {
    A(){}
    template <class T2> A(const T2&);
    template <> A(const A&){ printf("A(const A&) called\n"); }
  };
  A<int> ai;
  A<int> ai2(ai);

4/30/97   C++-generating back end: "extern" on definition of const variable

In C++, the definition of a variable with a const-qualified type is
implicitly static.  To override that, the C++-generating back end now
puts out "extern" on such a definition if necessary.

 extern const int x[] = { 1 };

4/30/96   Microsoft compatibility: diagnostic on inline member function
          that is referenced but undefined

In Microsoft compatibility mode an error is no longer issued when an inline
member function of a nonlocal class is referenced but not defined:

  class A {
    inline int f();           // Only a warning in Microsoft mode
  } a;
  int main() {
    return a.f();
  }

4/29/97   Microsoft compatibility: template argument list following
          constructor name

The Microsoft compiler permits a template argument list to appear following
a constructor name in a constructor definition that appears outside of the
class.  This is now accepted in Microsoft mode.

  template <class T> struct A {
    A();
  };
  template <class T> A<T>::A<T>(){}

4/28/97   Spurious error on extra comma in initializer

An error is no longer issued for the extra comma in the following:

  char str[] = { "abc", };

4/28/97   is_local_to_function flag may be set incorrectly on instantiations
          of templates defined in namespaces

Under certain circumstances the is_local_to_function flag associated with
instances of class or function templates may be set incorrectly.  This
can result problems such as spurious "template argument may not reference
a local type" errors.  This has been fixed.

4/28/97   Microsoft compatibility: support for "inheritance kinds" to allow
          different pointer-to-member representations

In Microsoft-compatibility mode a class declaration may now specify an
"inheritance kind" (single, multiple, or virtual), which is recorded in the
inheritance_kind field of a_class_type_supplement.  For instance:

  class __single_inheritance X;
  int X::* pmx;

This information is recorded in the IL to enable an implementation to
control the representation of pointer-to-member objects for Microsoft ABI
compatibility.

4/25/97   Expansion of __FILE__ as header name

When the macro __FILE__ is expanded in a context that requires a header
name, backslashes are no longer doubled.  This avoids problems on systems
that use "\" as part of file names, when an #include like the following
appears:

  #include __FILE__

4/25/97   Spurious error on instantiation in template declaration

When the instantiation of a class is caused by a reference in a template
declaration, the instantiation of the default arguments and bodies
of friend functions defined within the class was not being handled
properly, and could result in spurious errors, or possibly incorrect
execution.  This has been fixed.

  template <class S> struct A {
    struct B {};
    A(int = S());
  };

  template <class T> void foo(T, A<int>::B);

4/23/97   Microsoft compatibility: default template arguments can be
          redefined

The Microsoft compiler permits a template default argument to be redeclared,
which is not permitted by the Working Paper.  The Microsoft compiler permits
this even when the new value is different from the old one (in which case
the new value is used).  We now emulate this behavior in Microsoft mode.

  template <class T, class T2 = char> struct A;
  template <class T, class T2 = int> struct A {
     T2 t2;  // T2 will have type "int" when the default value is used
  };

4/22/97   Needed flag walk: dynamic_cast source/destination must be pointers
          to complete classes

The "needed" flag walk notes that certain IL operations require completeness
of the underlying class types, and ensures that the associated class
definitions are not removed.  This process did not correctly note
that the dynamic_cast operation requires that its source and
destination types be pointers to complete class types, so class
definitions were sometimes removed even though they were required.
This affected only versions that do not use IL lowering (e.g., those
using the C++-generating back end).

4/22/97   Microsoft compatibility:  long + int is int

The Microsoft Visual C++ compiler, amazingly, considers that an expression
like "long_expr + int_expr" has type "int".  Many, but not all, operators
have the same behavior.  This matters in cases like

  void f(int);
  void f(long);
  int main() {
     long q = 0;
     f(q+1);  // calls f(int)
  }

(5/1/97: this processing has been put under control of the new
Microsoft bugs mode.)

4/21/97   Microsoft compatibility: bool, explicit, and typename are now
          supported by the Microsoft compiler

Version 11.00 of the Microsoft compiler (in Visual C++ 5.0) supports
the bool, explicit, and typename keywords.  These features had been
automatically disabled in Microsoft mode because they were not supported
by the Microsoft compiler.  They are now enabled in Microsoft mode
when the Microsoft version is 1100 or greater.

4/18/97   Missing diagnostic when an operator name is used as a class
          template name

The front end failed to issue a diagnostic on examples such as this one.
This has been fixed.

  typedef int A;
  template <class T2> struct operator A {};

4/17/97   Internal error on use of an undefined symbol created in a base class

When an undefined name is referenced, an sk_undefined symbol is created
to suppress diagnostics on subsequent uses of that undefined name.  An
internal error would occur if a derived class made reference to a name
associated with an sk_undefined symbol in one of its base classes.  This
has been fixed.

  struct B {
    template < int I > class A ;
    A < I >* a;
  };
  struct C : B {
    A < I > a;
  };

4/16/97   Internal error on missing template argument list of member class
          template in field selection operator

An internal error could result when a member class template name is used
in a qualified name in a field selection operator without a template
argument list.  This has been fixed.

  struct A {
    template <class T> struct B {};
  };
  int main()
  {
    A a;
    a.A::B;
  }


4/16/97   Internal error on specialization in invalid context

An internal error could result if a specialization of a member function
template appeared in a class definition, and that class is later instantiated
within another function.  This has been fixed.

  template <class T> struct A {
    template <class U> void f(U);
    template <> void f(long){}
  };
  int main()
  {
    A<int> a;
    a.f(1);
  }

4/14/97   Internal error on end-of-source in template static data
          member parenthesized initializer

An internal error would occur if an end-of-source immediately followed
the opening parenthesis of a template static data member definition.
This has been fixed.

  template <class T> struct A {
    static int i;
  };
  template < class T > int A < T >::i (

4/14/97   Internal error while issuing variable-used-before-set warning

An internal error is no longer issued on the following, in which a default
argument references an unset variable that is a member of an unnamed
namespace:

  namespace {
    extern int i;
  }
  void f(int x = i);      // use of "i" no longer causes an internal error

4/14/97   Microsoft compatibility: uninitialized const variable

In Microsoft compatibility mode, when an uninitialized const variable is
explicitly declared "static", a warning is now issued instead of an error:

  static const int i;         // now a warning in Microsoft mode
  const int j;                // still an error

4/14/97   Internal error on default argument not at end of parameter list
          in a member function declaration

In 2.34, a change was made that eliminated the diagnostic when a default
argument appeared in a member function declaration, but not at the end
of the parameter list.  This could result in an internal error in IL
lowering when processing an invalid call.  This has been fixed.

  struct B {
    int f(int, int = 1, int);
  };
  B b;
  int i = b.f(1);

4/11/97   Internal error when a template that is member of the current class
          is declared as a friend

An internal error could result when a function template that is a member
of a given class is defined within the class and is also declared as
a friend within the class.  This has been fixed.

  template <class Z> struct A {
    template <class U> int f(U) {return 0;}
    template <class T> template <class U> friend int A<T>::f(U);
  };
  A<short> a;
  int i = a.f(37);

4/11/97   A member function template may not be defined in a friend declaration

The front end incorrectly accepted a friend declaration that is used
to define a member function of the class.  This has been fixed.

  template <class Z> struct A {
    template <class U> int f(U);
    template <class T> template <class U> friend int A<T>::f(U) {}
  };

4/10/97   Types declared in parameter declarations in pcc mode

Struct and enum tags introduced in parameter declarations are no longer
injected into the file scope in pcc mode -- that is, in pcc mode the
handling is now the same as in default C mode for the following:

  void f(ps)
  struct S { int i; } *ps;
  { ... }
  struct S s;                 // Now an error in pcc mode

4/9/97    Partially-lowered EH cleanup state determination at unreachable code

When exception handling is partially-lowered, instructions must sometimes
be emitted in unreachable code to indicate the current cleanup state,
for implementations that use the instructions to generate a table.
Formerly, this was done only at the ends of blocks and switch clauses,
which did not handle cases where the source program contains unreachable
code.  Now fixed.

  struct A {A(); ~A(); operator bool();};
  int func() {
    A var1;
    try {
      A var2;
      if (var1) goto label2;
      return 1;
      // Following code is unreachable
      while (var2) {
        label1: ;
      }
    label2:
      if (var2) goto label1;
    } catch (...) { }
    return 0;
  }

4/9/97    Internal error on using-declaration that refers to undefined symbol

An internal error would result when a using-declaration refers to a name
for which an sk_undefined symbol has previously been created.  This has
been fixed.

  int i = T;
  namespace B {
          using ::T;
  }

4/9/97    Internal error when sk_parameter symbol used as an error fill-in

An internal error would result when an sk_parameter symbol was used as
an error message fill-in.  This has been fixed.

  void f ( int A , A<short>);

4/8/97    Internal error after use of an undefined operator function

An internal error could result when an undefined operator function
that is first called by name is later called implicitly through use
of the operator.  This has been fixed.

  struct A {};
  int main() {
    A a;
    operator, +(a, 1);  // internal error processing "a, 1"
  }

4/7/97    EH cleanup state determination at case label with fall-through

In some cases, the exception handling cleanup state determined at a case
label that has a fall-through from a previous case label was wrong, with
the consequence that exception handling cleanup would not be done correctly
if an exception were thrown at that point.  Now fixed.  (5/25/97: the
particular change for this issue was backed out, because it caused a
problem in long lifetime temporaries mode.  The bug remains fixed, due
to other changes made since the original fix.)

  struct A { A(); ~A(); };
  void f(int i) {
     A var1;
     switch (i) {
      case 5:
        i = 1;
      case 2:
      case 3:
        A var2;  // Cleanup state wrong during constructor call here
        break;
     }
  }

4/7/97    Incorrect source position information for template function
          definitions

The source position of a template function definition was incorrect
when the template was first declared and then later defined.  The
position given was the position of the declaration when it should have
been the position of the definition.

4/5/97    Normalization of boolean controlling expressions involving
          template parameters when --no_bool is in effect

A change made in 2.35 introduced a bug in the processing to normalize
boolean controlling expressions based on template parameters during
the prototype instantiation of a template.  For example, the
following got an internal error in extract_constant_from_operand,
now fixed:

  template <class T> struct A
  {
    enum { MIN = sizeof(T) <= 32 ? 31 : 7 } ;
  };

4/5/97    Using type-compatibility routines in "middle ends"

It's sometimes useful for middle ends to be able to use some of the
type-compatibility routines in types.c, e.g., types_are_compatible.
However, there is code in equiv_class_types that uses the assoc_info
pointer to go to the associated symbol entry, and this refers to
freed memory when run from a middle end.  There is code there
to deal with this problem, but it has been controlled by the
USING_KAI_INLINER configuration flag.  That has been changed so
the guard code is always included, so that all middle ends can use
these type-compatibility routines.

4/4/97    Microsoft compatibility: old-style class specialization declarations
          are ignored

Version 11.00 of the Microsoft compiler (in Visual C++ 5.0) ignores
old-style specialization declarations (but not definitions).  The front
end now duplicates this behavior when --microsoft_version=1100 is specified.

  template <class T> struct A {};
  struct A<int>;  // no longer a specialization declaration

4/4/97    Microsoft compatibility: --microsoft_version option

In order to permit the front end to correctly emulate Microsoft
features that vary between versions of the Microsoft compiler, a
command line option has been added to specify the version of the
Microsoft compiler that should be emulated.  The value is specified
using the value of the predefined macro _MSC_VER supplied by the
version of the Microsoft compiler that is being emulated (for example,
1100 corresponds to Visual C++ version 5.0).  The default value is
specified by the DEFAULT_MICROSOFT_VERSION configuration parameter.

4/3/97    Linkage specification processing could refer to freed memory

The processing for linkage specifications saved a pointer into the
scope stack over a period of time when the scope stack might be
reallocated to increase its size.  If such reallocation did occur, the
subsequent references through the pointer might be to freed or
reused memory.  Now fixed.

4/3/97    Microsoft compatibility: user-defined conversions on "?" operator

In Microsoft mode, conversions to class types instead of built-in types
are now favored for the operands of the "?" operator.  That makes cases
like the following not ambiguous in Microsoft mode:

  struct String {
    String(char const *s);
    operator char *();
  };
  String x("goodbye");
  String f(int i) {
    return i ? "hello" : x;
  }

4/3/97    Custom linkage kinds: whether name mangling should be done

A new macro is_name_linkage_kind_subject_to_name_mangling has been
added so that it can be redefined as necessary if entities of any
custom linkage kinds that are added should not be subject to name
mangling.

4/3/97    Cfront 3.0 mode should not be permitted with strict mode

Cfront mode is not compatible with strict mode.  An error was issued
if cfront 2.1 mode and strict mode were both specified, but not when
cfront 3.0 mode and strict mode were both specified.  This has been fixed.

4/3/97    Microsoft compatibility: empty macro arguments ignored

Microsoft-compatibility mode now treats empty macro arguments like
MSVC++ (4.2 and 5.0, at least) does, i.e., it ignores them.

  #define M(a,b) { a, b } 
  int a[2] = M(,,,,,,0, ,1,,);  // Same as M(0,1)

4/3/97    AN_INTEGER_VALUE_IS_LARGER_THAN_HOST_LONG is obsolete

2.35 was changed to provide better support for use of long long to represent
host integers in the routines that manipulate constants.  A consequence of
this change is that the AN_INTEGER_VALUE_IS_LARGER_THAN_HOST_LONG
configuration flag is no longer needed.  However, an obsolete and incorrect
consistency check was left in fe_init.c.  This resulted in a spurious
"AN_INTEGER_VALUE_IS_LARGER_THAN_HOST_LONG in targ_def.h is set wrong"
internal error.  The consistency check has been removed and the references to
this configuration flag have been changed to use
INTEGER_VALUE_REPR_IS_A_HOST_INTEGER instead.

4/1/97    Abort on type-as-subobject generated by IL lowering within
          namespace while generating implicit virtual destructor

In an obscure case involving generation of virtual destructors,
IL lowering generated the type-as-subobject version of a class that
is a member of a namespace in an incorrect way, which caused an
abort later.

3/31/97   Special processing for manifest constant macros eliminated

Macros that are defined to be a simple constant, e.g.,

  #define X 12

have heretofore been given special processing: the first time the
macro was expanded, the constant was converted, and thereafter the
saved value was used instead of rescanning the macro text.

This has proven error-prone, and on the latest report of a bug in this
area, we decided to remove it.  It was intended originally as a
speed optimization, but timing tests show a negligible benefit.

A consequence of this change is that manifest constant macros no longer
appear as IL constant entries on the file scope constants list.
(Member constants promoted out of classes by IL lowering can still
appear on that list.)

3/31/97   Double name mangling on static data member

In some cases, the mangled name for a static data member had double name
mangling.  This could cause a prelinker loop.  Now fixed.

  struct B {static int v[1];};
  int B::v[1];
  template<int* x> struct A {};
  template<int* x> void f( A<x>& cfl ) {}
  int main() {
    A<B::v> clA;
    f(clA);
    return 0;
  }

3/27/97   Internal error in object-lifetime management for default argument

An assertion failure could be provoked when instantiation of a template
function was triggered while processing the default arguments for another
template function instantiation.  Now fixed.  Here's an example:

  template <class T> struct allocator {
    allocator() { }
    ~allocator() { }
  };
  template <class T, class Allocator = allocator<T> > struct list {
    struct list_node { T  data; };
    static int buffer_size () { return sizeof(list_node); };
    void *get_node (int n = buffer_size()) { return 0; }
    list (const Allocator& alloc = Allocator()) {
      get_node(1);
    }
  };
  template <class T, class Allocator> struct vector {
    explicit vector (const Allocator& alloc = Allocator()) { }
  };
  int main() {
    list<vector<char, allocator<void> >, allocator<void> > lvc;
  }

3/26/97   Definition of db_flag_is_set when DEBUG is FALSE

The definition of the macro db_flag_is_set when DEBUG is FALSE is
now FALSE, rather than the previous incorrect empty string.

3/19/97   C-generating back end doesn't compile as standalone

Some calls of db_expression added to c_gen_be.c in 2.35 should have
been enclosed in #if !STANDALONE_UTILITY_PROGRAM/#endif so the code
can be compiled as standalone program.  Now fixed.

3/14/97   Error recovery abort with extern "C" declaration

A null-pointer failure has been fixed on the following:

  extern "C" void f();
  extern "C" int f();

3/8/97   Generated operator= calling base-class operator= that takes
         parameter by value and requires destructor

An internal error has been eliminated for cases where a generated
derived-class operator= function calls a base class operator= function,
and the base class operator= takes its parameter by value and the parameter
is a class type that has a destructor.

  template <class T> struct A {
    ~A();
    void operator=(A<T>);
  };
  struct B {
    A<int> id;
  };
  void foo() {
    B obj1,obj2;
    obj1 = obj2;
  }

3/7/97   Setting "referenced" on static data member specialization

The "referenced" flag was not being set properly on a template static data
member that was explicitly specialized with an initializer and using the
template<> syntax.  (It is a convention in the IL to set the flag on
definitions of externally visible variables whether or not there is
actually a reference in the current translation unit.)  Now fixed.

  template <class T> struct A { static T t; }
  template<> int A<int>::t = 10;        // "referenced" was not set

3/7/97   Function templates incorrectly considered to be ordered

The call of "f(ac, 'c')" in the example below should be ambiguous but
was accepted as a result of a bug in the partial ordering in 2.35.
This has been fixed.

  template <class T> struct A {};
  template <class T> void f(A<T>, T);
  template <class T> void f(A<T>, char);
  int main() {
    A<char> ac;
    f(ac, 'c');
  }

3/5/97   Spurious error when using-declaration refers to extern "C" variable

Spurious errors (complaining that the name has already been declared in
the current scope) have been eliminated in the following:

  namespace N {
    extern "C" int i, j;
  }
  extern "C" int i;
  using N::i;                  // Error is no longer issued
  using N::j;
  extern "C" int j;            // Error is no longer issued

3/5/97   Namespace operator lookup and using-declarations

A bug has been fixed that resulted in a spurious ambiguity error when
importing operator functions into a namespace with a using-declaration.
The bug would occur when a using-declaration names an overloaded set of
operator functions, and the actual call of the operator uses an object
of a derived class declared in the namespace containing the using-declaration
and whose base class is in the namespace in which the operator functions
were initially declared.

  namespace N {
    struct B {};
    B& operator<<(B& os, char c);
    B& operator<<(B& os, const char* c);
  }
  using N::operator<<;
  struct A: public N::B {};
  int main() {
    A a;
    a << "hello";
  }

3/5/97   IL CHANGE: source-sequence-entry pointer in IL entities

For implementations in which GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, the
source_sequence_entry field in the source-correspondence portion of IL
entities no longer points to source-sequence entries that represent
block-extern declarations or (in C mode) implicit function declarations,
even when such declarations are the first in the translation unit.  This
implies that the pointer may be NULL sometimes.  This change fixes an
internal error that appeared in the following when it was compiled with
--remove_unneeded_entities and no IL lowering was being performed:

  static void f() {
    extern void g();
  };
  void h() {
    extern void g();
    g();
  }

3/4/97   Reporting the use of features excluded from Embedded C++

"Embedded C++", a subset of C++ that is intended for embedded applications,
excludes templates, exceptions, namespaces, new-style casts, RTTI, multiple
inheritance, virtual base classes, and "mutable".  Users can now check their
programs for features that are outside this subset by compiling with
--embedded_c++.  A discretionary error is issued for violations.  In
addition, macro __embeddedcplusplus is predefined when the command-line
option is used.  (Note: this turned out to be the wrong macro name:
__embedded_cplusplus is correct.  Changed 7/7/99.)

3/4/97   Extern "C" names found via using-directives

In 2.34, the handling of extern "C" declarations was changed such that
declarations of the same object or function name in different namespaces
were treated as redeclarations of the same entity (e.g., the declarations
of N::f and ::f declare the same function in the example below).  See
the Changes file entry on 2/4/97 for more information.  Even though the
declarations now declare the same entity, an entity could be referenced
using any of the names that refer to that entity (e.g., ::f or N::f).  This
resulted in a problem when more than one of the names was visible as the
result of a using-directive.  Such use would result in a spurious ambiguity
error.  This has been corrected.

  namespace N {
    extern "C" int i;
    extern "C" int f(int);
  }
  extern "C" int i;
  extern "C" int f(int);
  using namespace N;
  int j = i;
  int k = f(1);

-------------------------------------------------------------------------------
Version 2.35, February 28, 1997

2/28/97  IL version number changed to 2.27

2/27/97  IL CHANGE: vacuous destructor call on non-class rvalue

A vacuous destructor (or pseudo-destructor) call of the form "x.X::~X()",
where "x" is an rvalue of a non-class type, is now represented by
an IL expression node with the new operator kind
eok_value_vacuous_destructor_call.  Formerly, it was represented by
a node with operator kind eok_vacuous_destructor_call, but that didn't
provide enough information for the C++-generating back end.  Both
those operator kinds are rewritten by IL lowering, so those using IL
lowering will see no difference.

2/26/97  Macros for adding name linkage kinds

To facilitate maintaining implementation-defined name-linkage kinds, macros
CUSTOM_NAME_LINKAGE_KINDS and CUSTOM_NAME_LINKAGE_KIND_NAMES, along with
the previously provided NUM_BITS_FOR_NAME_LINKAGE, may be defined outside
il_def.h (e.g., in defines.h).  If you add a name-linkage kind that can be
be applied to function types (e.g., because it implies a distinct calling
convention), you should update is_custom_name_linkage_kind_for_rout_type, a
new macro that can also be defined outside il_def.h.  (But note that you
may still need to customize routine_linkages_are_compatible in types.c.)

2/26/97  Name mangling change: nontype template parameters that are
         pointers to members -- show class/namespace membership

When a pointer-to-member-function appears as a nontype template argument
and includes a function name, the cfront mangling scheme includes only
the function name, and not the name of any parent class.  This can cause
some template entities to have duplicate mangled names.  This has
been fixed by including class/namespace membership information in the
name.  The old behavior is provided with ABI_COMPATIBILITY_VERSION < 235,
and when --no_distinct_template_signatures is in effect.

2/25/97  Ambiguous guiding declaration

When compiling with --guiding_decls an error is now issued when more than
one function template matches the function type of the guiding declaration:

  template <class T> void f(T*) {}
  template <class T> void f(T) {}
  void f(int*);                        // Ambiguous guiding declaration

2/25/97  Nontype template arguments whose type depends on a template parameter

A nontype template argument can have a type that depends on a template
parameter, as is the case for the constant "1" in the declaration of
function template f in the example below.  The template matching routines
did not work properly for such cases.  This has been fixed.

  template <class T, T t> struct A { };
  template <class T> void f(A<T,1>);
  void (*fp)(A<int, 1>) = f;

2/25/97  Name mangling: new-form length for class template nontype arguments

In the name mangling change for templates (see Changes entry of 5/10/96),
a new encoding for lengths of literals was introduced to avoid an
ambiguity problem.  The new encoding was not used in the template arguments
for class templates, though, to preserve more compatibility with cfront.
However, it turns out there's a remaining possible ambiguity that
can come up for a class template:

  template<class T, int i> class TA {};
  template <class T> struct TT {
    void func(TA<long, 1>); // func__11TT__tm__2_sF17TA__tm__8_lXCiL11_v
                                                                    ^^problem
  };

So the new length scheme is now used whenever the new template mangling
is used.  The old behavior is of course preserved if ABI_COMPATIBILITY_VERSION
is set to less than 235.

2/24/97  Abort on invalid template friend declaration with global qualifier

An abort would occur on a template friend declaration that refers to a
member of the global scope that is not a template, and that includes a
global scope qualifier.  This has been fixed.

  void f(int);
  struct A {
    template <class T> friend ::f(T); 
  };

2/24/97  Abort on use of template template parameter

The front end does not yet support template template parameters, but
attempts to gracefully provide a diagnostic and continue compilation.
Cases like the following resulted in an abort.  This has been fixed.

  template <template T> struct A { 
    using T::i;
  };

2/24/97  Instantiations that produce unexpected function types

If a name used in a function template declaration changes meaning between
the point at which the function is declared and the point at which the
it is instantiated an internal error could result.  Such cases are now
detected and an error is issued.  In the future, when the new template
name binding rules are implemented, such errors will no longer be possible.

  template < class T > void f(T, const /* implicit int */ A);
  struct A { };
  int main() {
    new (1234, 2345) A;
  }

2/24/97  Incorrect handling of template argument lists with operator names

Template argument lists in which the last argument was an operator new were
not being handled correctly.  This could result in spurious errors
on such cases.  This has been fixed.

  template <void * (*fp)(unsigned int)> class A {};
  A < operator new > a;

2/23/97  Internal error on error recovery -- default argument

An internal error encountered in the following has been fixed:

  struct A {
    virtual void (*pf)(int = 0);  // Error on "virtual" -- no longer aborts
  };

2/23/97  Internal error on error recovery -- virtual function override

An internal error encountered in the following has been fixed:

  class B {
    virtual void f();
  };
  class D : B {
    virtual void f();
    int f;               // Error
    virtual void f();    // Another error -- but no longer aborts
  };

2/21/97  Overaggressive removal of source sequence entries

A bug has been fixed compiling a case like the following with the
C++-generating back end and with --remove_unneeded_entities:

  class A {
    class B *pb;       // First declaration of class B
  };
  extern B * f();      // Subsequent reference means B is still needed

If the body of class A was removed from the IL tree, the type entry for
class B would be retained in the IL but not the corresponding source
sequence entry.  This could sometimes result in an internal error.

2/21/97  Selection of member of overload set to match pointer to member
         of base class

The overload resolution on the following incorrectly concluded that a
member of the overload set could be used as a pointer to member of the
base class.  This now gets the appropriate error.

  struct A {};
  struct B : public A {
    void f(int);
    void f(long);
  };
  typedef void (A::*pmfA)(int);
  pmfA a = &B::f;  // Now gets error

2/21/97  Internal error on "~ operator name"

The use of an operator name in a destructor name resulted in an internal
error.  This has been fixed.

  struct A {
    virtual ~ operator new(); 
  };

2/21/97  No deduction of cv-qualified function types

cv-qualified function types are not allowed, so type deduction for
templates should not produce cv-qualified function types.  The following
case now gets an appropriate error instead of an internal error:

  struct ZZZ {};
  void* xxx(ZZZ);
  template <class T> void f(const T*) {}
  void g() {
    f(xxx); 
  }

2/21/97  Partially-lowered EH: address of local static guard variable

When IL lowering generates partially-lowered code for exception handling,
the addresses of variables are represented by ck_stack_offset constants,
which are supposed to map to some representation of the address of
an auto variable.  However, for the case of a guard variable for
the initialization of a local static variable, the guard variable is
static, and therefore a ck_stack_offset should not be used for it.
This has been changed to take the address of the guard variable and
cast it to the appropriate integral type.  The runtime knows it is
dealing with a guard variable and therefore can treat the integral
value as an address instead of a stack offset.

2/21/97  "void * const" return type for operator new

An error is now issued if an operator new or new[] function is declared
with a return type of "void * const".  This fixes an internal error in IL
lowering.

2/21/97  Error recovery problem: binding reference to error type

On the following case, an error recovery problem caused an abort.
This has been fixed.

  void f(int);
  void f(int&);
  A& p = f;   // "A" is undeclared, abort in recovery

2/20/97  Internal error on ill-formed conversion operator template

An internal error could result if a conversion operator template
contained "friend" in an invalid location in the declaration.
This has been fixed.

  struct A {
    template <class T> operator friend(T);
  };

2/20/97  Incorrect handling of block extern in the presence of using-directives

When looking for a previous declaration that matches a block
extern, the lookup incorrectly considered names that are visible as
result of using-directives.  This caused cases such as the following
to be handled incorrectly.  This has been fixed.

  namespace N {
    void f(short);
  }
  void f(int);
  using namespace N;
  void g() {
    extern  void f(char);
    f('c');  // should call f(char), was calling f(int)
 }

2/19/97  IL CHANGE: a_targ_size_t now has the same type as a_host_large_integer

Formerly, a_targ_size_t, which is used to represent address offsets in the IL,
was defined as an unsigned long.  As a result, is was not possible to
represent offsets larger than 32 bits on systems where an unsigned long
is 32 bits and an unsigned long long type exists to represent larger
values.  a_targ_size_t is now set to the same type used to represent
a_host_large_integer.  Consequently, it is now possible to represent larger
offsets in the IL.

2/19/97  Integer folding and conversion routines did not support host
         integers larger than a host long

Formerly, the integer folding and conversion routines supported operations on
values larger than host long only when INTEGER_VALUE_REPR_IS_A_HOST_INTEGER was
FALSE (i.e., when the simulated integer routines were being used).  It was
possible to configure the front end to use a long long value as the
representation of an_integer_value, but operations that involved converting
integers to floating point and vice-versa would only work on values that could
be represented by a host long.  These routines have been modified to operate on
values whose type is specified by the typedefs a_host_large_integer and
a_host_large_unsigned.  These typedefs are automatically set to
TYPE_OF_AN_INTEGER_VALUE and TYPE_OF_A_SIGNED_INTEGER_VALUE, respectively.

2/19/97  Multibyte characters accepted in source

Multibyte character sequences are now accepted in comments, string
literals, character constants, and header names.  They are not
supported by default: see MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED.
When supported, they are enabled according to
DEFAULT_MULTIBYTE_CHARS_IN_SOURCE_ENABLED and the --[no_]multibyte_chars
command line option.  There are various configuration options; see
host_envir.h (look for MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED).  The usual
configuration uses C library routines like mbtowc and mblen to
decode the multibyte character sequences, thus obtaining the
multibyte character handling appropriate to the host system.
In multibyte character mode, the strings passed to a back end are
still strings of "char", but where appropriate they will contain
multibyte character sequences.

2/19/97  Effect of unnamed non-zero-width bit field on struct's alignment

A new global variable, targ_unnamed_bit_field_affects_struct_alignment, has
been added.  When it is FALSE, an unnamed bit field affects the alignment
of the field that follows it but not of the class/struct as a whole.  This
was already controllable for zero-width unnamed bit fields (see
targ_zero_width_bit_field_affects_struct_alignment), but now it can be
controlled for all unnamed bit fields.  The default value of the variable
is TARG_UNNAMED_BIT_FIELD_AFFECTS_STRUCT_ALIGNMENT, defined targ_def.h;
setting it to FALSE creates an ABI incompatibility with versions 2.32
through 2.34 but restores compatibility with versions prior to 2.32.

2/18/97  Spurious error in template definition containing potential cast

The front end erroneously treated constructs such as "(T::x ...)" as a
cast when implicit_typename is enabled.  This has been fixed.

  template<class T> struct A {
    enum E { e1 = (T::x + T::y) };
  };

2/17/97  Conversion of float to integer when using simulated host integers

When converting from a floating point value to an integer when
AN_INTEGER_VALUE_IS_LARGER_THAN_HOST_LONG is TRUE, the flag that
indicated whether an error occurred in the conversion was not
being set properly.  This resulted in the failure to issue a
diagnostic on cases such as the following, and could also result
in spurious errors for valid conversions.  This has been fixed.

  unsigned long x = -3.0;
  char n[(unsigned long)-3.0];

2/14/97  Setting of result_is_not_used flag with inlining

In some cases when IL lowering was done (and particularly inlining), some
expression nodes had result_is_not_used set even when the result was used
higher up the expression tree.  Now fixed.

2/14/97  Exception not considered caught in catch associated with internal try

The internal try block mechanism added in 2.34 did not correctly handle
cases in which the catch clause associated with the internal try block
exited via an exception (for example, when a placement delete
function exits via an exception).  In such cases, the original exception
was silently abandoned in favor of the new one.  Now, __terminate()
is called, which is the correct behavior.

2/14/97 All instances of member class templates of prototype instantiations
        should be considered nonreal classes

It is possible for an instantiation that looks like a "real" instance
(one for which none of its template arguments is a template parameter)
to be created during the prototype instantiation of the enclosing class
template.  In such cases, the class should be considered to be a nonreal
class because the actual class used during a real instantiation could
be a specialization, so references to that class from elsewhere in the
class template must treat it as nonreal.

Formerly, this example resulted in a spurious error during the prototype
instantiation of class template A.  This example is now accepted.

  template <class TT> struct A {
    template <class T> struct D { };
    struct E : D<long> {
      typename E::EE e2;  // spurious error on this line
    };
  };
  template <> template <> struct A<int>::D<long> {
    struct EE {};
  };
  A<int>::E ae;

2/14/97 IL CHANGE: first_declaration flag in secondary declaration source
        sequence entry; used in C++-generating back end

A new field first_declaration has been added to the secondary declaration
entry of the (optional) source sequence list.  This field is now used
by the C++-generating back end to do a better job of naming classes
in the generated output (the initial declaration can never use a
qualified name).

2/14/97 C++-generating back end: friend functions in namespaces

The C++-generating back end now generates the proper form of the
name of a friend function that is a member of a namespace.

  namespace N {
    struct A {
      friend void f() {}  // Proper qualified name put out
    };
  }

2/13/97 Abort in trim_mem_block when using precompiled header option

The front end could abort when using the precompiled header options.
The abort occurred in trim_mem_block and was caused by the fact that
memory regions associated with trivial default constructors would have
been freed earlier.  This has been corrected.

2/13/97 Instantiations not done in -tused mode when first use is after
        instantiation wrapup has completed

If the first reference to a template entity is from a virtual destructor
generated after instantiation wrapup has completed, the template entity
will not be instantiated when using -tused or -tall mode (it will still
be instantiated when using automatic instantiation).  This has been fixed.

2/13/97 Missing error on type definition in function template return type

No diagnostic was issued when a type definition appeared in the return type
of a function template.  This has been fixed.

  template <class T> const struct X { int i; } f(T);

2/13/97 Error on base-specifier that depends on a template parameter

An error is now issued if a base-specifier depends on a template parameter
in a context other than a prototype instantiation of a class template.
This can only occur in otherwise ill-formed programs.  Note in the
following example (which used to provoke an internal error with exception
handling enabled) that X is not a class template but the return type of
function template f:

  template <class T> struct A;
  template <class T> const struct X : A<T> { int i; } f(T);

2/12/97 Diagnostic on cv-qualifiers on return type of function template

A spurious warning has been eliminated on "useless" top-level cv-qualifiers
on the return type of a function template.  For instance:

  struct S {
    template <class T> operator const T();   // No diagnostic
  } s;
  struct X { };
  int main() {
    X x = s;                                 // No diagnostic
    int i = s;                               // Remark
  }

A spurious warning used to be issued on the template declaration.  The
handling of S::operator const X() is unchanged.  The diagnostic on the
instantiation of S::operator const int() used to be a warning but is
now a remark.

2/12/97 &(A::x) is not a pointer to member

The form "&(A::x)" is no longer accepted as a pointer to member.  This
avoids an internal error on cases like "&(A::x+1)".

2/12/97 Error recovery involving virtual function override

An internal error has been fixed in handling the following error case:

  struct B {
    virtual void f(int);
  };
  struct D : public B {
    virtual void f(x);         // "x" is undefined
    virtual void f(int);
  };

D::f(<error-type>) used to be regarded as an overrider of B::f(int), which
meant there were two overriders, triggering an assertion failure.  Now a
function with error-type parameters is not considered an overrider, and as
a result somewhat different warnings may be issued.

2/12/97 Compilation error in lower_init.c when
        TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE is TRUE

lower_init.c did not compile when TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE
is set to TRUE.  Now fixed.  This bug was introduced in 2.32.

2/12/97 "operator" in a class or enum name

An error is now issued when an operator name appears in an elaborated type
specifier -- "class operator +" or "enum operator int".

2/12/97 Improved diagnostic when ">>" is used to terminate two template
        argument lists

A special diagnostic is now issued when ">>" is used to close two
template argument lists where "> >" is required.  Note that the
special diagnostic can only be issued when the last template argument
is a type argument.  When it is a nontype argument, the ">>" is
considered to be a right shift operator.

  template <class T> struct A {};
  template <class T> struct B {};
  A<B<int>> ab;

2/11/97 Nontype template parameter of type "reference to function"

A nontype template parameter with a type of "reference to function" was
not properly handled in expressions.  Now fixed.

  void f();
  void (&gp)() = f;
  template <void(&fp)()> struct S {
    static void m() {
      fp(); 		// Now accepted
    }
  };
  int main(){ 
    S<f>::m(); 
  }

2/11/97 Incorrect handling of member function template declared inline
        after having been called

If a member function template declared within a class template was
called and then defined as an inline function, the function was being
incorrectly treated as noninline until it was instantiated.  This could
result in an instantiation loop when using the prelinker.  This has
been fixed.

  template <class T> struct A {
    template <class T2> void f(T2);
  };
  int main() {
    A<int> a;
    a.f(1);
  }
  template <class T> template <class T2> void inline A<T>::f(T2){}


2/11/97 Function-local const variable as operand of "?" operator

When a function-local const integral variable appeared as an operand
of a "?" operation, the operation was not always folded to a constant,
which meant sometimes it could not be used as a compile-time constant.

  int main () {
    const int i1 = 1;
    const int i2 = 2;
    const int i3 = i1 ? i2 : i2;  // Previously seen as non-constant
    int a[i3];                    // Gave error previously
  }

2/11/97 IL entry for namespace "std" is now always created

Code has been added to create the namespace "std" -- that is, a namespace
entry is created and added to the namespaces list of the file scope and
the symbol associated with it is created.  However, the symbol is not
added to the symbol table before it is explicitly declared in the source
program; until then it will not be found by name lookup but is available
through global variable symbol_for_namespace_std.

Predeclaring namespace std means it is available for other predeclared
symbols.  For example, an implementation may choose to predeclare as
built-in functions entities that, according to the Working Paper, belong
to namespace std.  See enter_system_specific_predeclared_symbols in
sys_predef.c.

2/11/97 INT_VALUE_PARTS_PER_INTEGER_VALUE when host and target byte sizes
        differ

The computation of INT_VALUE_PARTS_PER_INTEGER_VALUE, which is used when
the largest target integer is larger than the largest host integer,
was incorrect when the number of bits in a byte on the host and target
differed.  This has been fixed.

2/11/97 Concatenation of adjacent string literals

When wchar_t is configured to have the same underlying representation as
char, and when wchar_t is a keyword in C++, the front end erroneously
assigned a type of "array of wchar_t" to the concatenated string in this
example:

  void f(char *);
  int main(void) {
    f("T" "r");
  }

That's now fixed.  As part of this change, the previous behavior of
concatenating adjacent wide and non-wide string literals in C++ when
wchar_t is char and wchar_t is a keyword has been eliminated.  That
is not acceptable behavior under modern C++ rules, because wchar_t is
a distinct type from char even if it has the same representation.

2/11/97 bool and wchar_t not character types

bool and wchar_t (as keywords in C++) are no longer considered character
types even if they happen to have the same representation as a character
type.

  bool x[] = "abc";     // Error even if bool is represented as char
  wchar_t y[] = "abc";  // Error even if wchar_t is represented as char

2/10/97 Stop tokens reset during template instantiation

Error recovery during template instantiation could be affected by the
state of the stop tokens array at the time the instantiation was done.
This could result in poor error recovery, and in some cases error
message loops.  To correct this problem a stack of stop token arrays
is maintained.  The stack is pushed when a template instantiation is
started and popped when the instantiation is complete.  This mechanism
is used elsewhere in the front end in place of the former practice of
saving and restoring the stop token array.

2/10/97 Restrictions on scope associated with a #pragma directive

If in the course of processing a #pragma directive a variable or routine
symbol is entered into the symbol table, it is now entered into the
surrounding scope (rather than the sck_pragma scope associated with the
pragma).  The issue came up in fixing an internal error (in C mode) on the
following:

  void f() { extern int i; }
  #pragma test_immediate i;           // internal error no longer occurs

2/10/97 Warning on unexpected declaration of size_t

A warning is now issued if typedef name size_t or std::size_t is declared
with a type that does not match the type expected by the implementation --
e.g., "unsigned int".  (See TARG_SIZE_T_INT_KIND, defined in targ_def.h,
and global variable targ_size_t_int_kind.)

2/10/97 Microsoft compatibility: exception specifications are ignored

In Microsoft-compatibility mode exception specifications on function
declarators are parsed but ignored (with a warning).  As a result, errors
are no longer issued in Microsoft mode when a function is redeclared with a
different exception specification or when an incomplete type (or pointer or
reference to incomplete type) appears in an exception specification.

2/7/97  Default argument expression dependencies involving nested classes

The error issued on the following (complaining about failing to
provide a default constructor for X::N) has been eliminated:

  struct X {
    struct N {
      N(int i = 0) { }
    };
    X (N n = N()) { }        // an error is no longer issued when scanning
  };                         //   the default argument

The order in which default arguments for member functions should be
processed is not covered by the Working Paper.  We used to handle the
enclosing class first and then the nested classes; with this change, we
process default arguments in the order in which they appear in the class
definition, regardless of how the parent class is nested.  Although some
dependencies will remain, the errors will at least be a bit less surprising
to users; for instance, the following used to be accepted but now gets an
error:

  struct Y {
    struct N {
      N(Y y = Y()) { }      // an error is now issued -- no default
    };                      //   constructor for Y
    Y (int i = 0) { }
  };

2/6/97  Abort during recursive instantiation of function template

An abort has been fixed that could occur when recursive instantiation of a
function template was triggered during the processing the default arguments
of another instance of the same template.  Here's an example:

  template <class T> struct B {
    B(const T& t = T()) { }
  };
  template <class U> struct M  {
    static int id;
    virtual U f() { }
  };
  int  M<B<B<B<char> > > > ::id;

2/5/97  A friend declaration may not declare a partial specialization

The front end incorrectly permitted a friend declaration to declare
a partial specialization.  This has been fixed.

  template <class T> struct A {};
  struct B {
    template <class T> friend struct A<T*>;
  };

2/5/97  A using-declaration may not name a conversion template instance

The front end failed to produce a diagnostic when a using-declaration
named a conversion template instance.  This has been fixed.

  struct A {
    template <class T> operator T();
  };
  struct B : public A {
    using A::operator int*;
  };

2/4/97  ABI_CHANGES_... macros defined even when IL lowering is not used

The several configuration macros with names beginning ABI_CHANGES_FOR_...
are now defined even when IL lowering is not being used.  This is
important because they need to be set to get the associated language
features fully implemented in the front end proper.

2/4/97  Abort on use of invalid conversion operator

An abort could occur when calling a template conversion operator using an
ill-formed type.  This has been fixed.

  struct A { template <class T> operator T*() {return 0;} };
  void f() {
    A a;
    int* p = 0;
    p = a.operator int int*(); 
  }

2/4/97  #pragma directive at end of namespace scope

Pragma processing was not being done correctly just before the closing
brace of a namespace scope, and so cases like the following were getting
spurious errors (because the pragma was being checked after the scope was
terminated).  Now fixed.

  namespace N {
    template <class T> void g(const T &t) { ... }
    #pragma instantiate void g(const int &)     // Spurious error on
  }                                             //   lookup of g is fixed

2/4/97  microsoft_mode: global variable or macro

When MICROSOFT_EXTENSIONS_ALLOWED is TRUE, global variable microsoft_mode
is defined (with an initial value of DEFAULT_MICROSOFT_MODE).  This is not
a change.  However, now when MICROSOFT_EXTENSIONS_ALLOWED is FALSE,
microsoft_mode is a macro name; its value is always FALSE.

2/4/97  Microsoft compatibility: "extern template" suppresses instantiation

In Microsoft mode, an explicit instantiation directive may be prefixed with
the "extern" keyword to suppress the instantiation of the named entity.

  extern template A<short>;  // do not instantiate members of A<short>

2/4/97  Microsoft compatibility: class-key may be omitted on explicit
        instantiation

In Microsoft mode, explicit instantiation directives that name a class
may omit the "class", "struct", or "union" keyword:

  template <class T> struct A {
    void f();
    void g();
  };
  template <class T> void A<T>::f(){}
  template <class T> void A<T>::g(){}
  template class A<int>;  // standard syntax
  template A<char>;       // Microsoft also accepts this form

2/4/97  Spurious error on class member using-declaration eliminated

A spurious error was issued on a class member using-declaration while
attempting to form an overload set involving a member function template.
Now fixed.

  struct A {
    void f();
  };
  struct B : A {
    template <class T> void f(T);
    using A::f;                      // spurious error no longer issued
  };

2/4/97  IL CHANGE: extern "C" declarations in namespaces

Support for declarations of the same extern "C" function or variable in
different namespaces has been added:

  namespace N {
    extern "C" void f();
    extern "C" void g();
  }
  extern "C" void f();               // Redeclaration of N::f
  namespace M {
    extern "C" void g();             // Redeclaration of N::g
  }

Prior to this change N::f and ::f were treated as separate entities whose
external names were in conflict; similarly with N::g and M::g.  Now (as
far as the IL representation is concerned) they are all treated as though
they were declared at file scope: even when an extern "C" routine or
variable is declared within a namespace, it appears on the routines or
variables list of the file scope and its parent.namespace_ptr field is
NULL.

2/3/97  On macro redefinition diagnostic, position of previous definition

The diagnostic issued when a macro is redefined in an incompatible way
now gives the position of the previous definition.

2/3/97  Improved error recovery after an unexpected template argument list

When an identifier is followed by a "<" in a context in which a less-than
sign is not valid, it is now assumed to begin a template argument list
even if the identifier it follows is undefined or names an entity that
is not a template.  This results in clearer diagnostics in most cases.

2/3/97  Fix in recursive macro expansion

When a macro name appears in its own expansion (either directly, or in
the expansion of another macro called by the first), the macro name
is not expanded recursively.  This has been handled correctly by the
front end in almost every case, but not when the expansion was done
in a macro argument whose text was subsequently expanded again.
Now fixed.

  #define p (*p)
  #define px p
  #define mac2(a) px + a
  #define mac(x) mac2(x)
  mac(p) // Correct expansion: (*p) + (*p)

1/31/97 Microsoft compatibility: storage class but no declarator

An error is no longer issued in Microsoft compatibility mode when a
storage class appears on a declaration with no declarator -- e.g.,

  static int;                        // warning in Microsoft mode
  static struct S { int i; };        // warning in Microsoft mode

1/31/97 Missing diagnostic on partial specialization tag kind mismatch

A diagnostic is now issued if the tag kind of a partial specialization does
not match the tag kind of the primary template.

  template <class T> struct A {};
  template <class T> union A<T*> {};

1/31/97 Recognition of predeclared class type_info

A new configuration flag, PRAGMA_DEFINE_TYPE_INFO_IS_REQUIRED, has been
added (see host_envir.h) to indicate whether "#pragma define_type_info"
must precede a declaration of class type_info that is meant to match the
predeclared name.  By default the flag is TRUE unless the C++-generating
back end is being used.

1/31/97 Pseudo destructor calls using type keywords now nonstandard

The Working Paper no longer permits type keywords to be used in pseudo
destructor calls.  Consequently, an error is now issued on such usage in
strict mode.

  int main()   {
    int *p;
    typedef int I;
    p->int::~int();  // no longer permitted
    p->I::~I();      // still allowed
  }

1/30/97 IL lowering: duplicate wrapper routines created for virtual function
        with covariant return type

In some circumstances, IL lowering created two copies of a wrapper routine
needed to interface to a virtual function with a covariant return type.

  extern "C" int printf(char *, ...);
  struct A {
     virtual A* clone(int);
  };
  A* A::clone(int) { return this; }
  struct B: virtual public A {
    virtual B* clone(int);
  };
  B* B::clone(int) { return this; }
  struct C: virtual public A,  public B {
    virtual C* clone(int);
  };
  C* C::clone(int) {
    printf("C:clone() returning this = 0x%x\n", this);
    return this;
  }
  int main() {}

1/30/97 #pragma pack directives and templates

When USER_CONTROL_OF_STRUCT_PACKING is TRUE, the default "pack alignment"
(given by a "#pragma pack" directive or specified on the command line) for
a function template instantiation is now the setting at the point of the
template definition.  (This was already true for class template
instantiations -- see entry for 3/5/96.)  For example,

  #pragma pack(1)
  template <class T> int f(T) {
    struct S { char c; int i; };
    return sizeof(S);
  }
  #pragma pack(4)
  int main() {
    int i = f(0);                    // i = 5, not 8
  }

Moreover, if a #pragma pack directive appears inside a template, it will
no longer affect declarations following the point at which it is
instantiated -- in other words, a #pragma pack directive is sometimes
treated as "local".  Here's an example:

  template <class T> class A {
    :
  #pragma pack(1)
    :
  };
  #pragma pack(4)
  int main() {
    A<int> a;                       // #pragma pack(1) is local to A<int>
    struct S { char c; int i; };    // sizeof(S) == 8, not 5
  }

The same approach is now used for member functions defined within the
class definition, because their bodies are scanned "out of order" relative
to the textual order of the source program.  For example,

  #pragma pack(4)
  struct A {
    int f() {
  #pragma pack(1)                   // #pragma pack(1) is local to A::f
      struct S { char c; int i; };  // sizeof(S) is 5
    }
    int g() {
      struct S { char c; int i; };  // sizeof(S) is 8
    }
  #pragma pack(1)
    int h() {
      struct S { char c; int i; };  // sizeof(S) is 5
    }
  };                                // inline functions are not scanned
                                    //   until here (i.e., not till all
                                    //   members have been declared)

When entering a class or function template instantiation or the definition
of an inline-defined member function, the current pack alignment state is
saved and the appropriate default is set.  Within that context, #pragma
pack directives are treated as "local" and a remark is issued.  When the
instantiation or function body is complete, the original pack alignment
state is restored.

1/30/97 C++-generating back end: typedef name on vacuous destructor call

The C++-generating back end now puts the original typedef name in a non-class
vacuous destructor call, not the underlying type.  This is important because
a recent change to the language makes such destructor calls invalid if
they use a type keyword instead of a type name.

  typedef int T;
  int main() {
    int i;
    i.T::~T();  // Comes out as i.T::~T(), not the now-invalid i.int::~int()
  }

1/30/97 Partial ordering of function templates

Partial ordering of function templates is now implemented.  When several
templates can produce equivalent function signatures, the partial ordering
rules are used to select between the eligible templates.  Formerly, this
example was ambiguous, but with the partial ordering rules, template
#1 is used.

  template <class T> struct A {};
  template <class T> void f(A<T>){return 1;}  // #1
  template <class T> void f(T){return 2;}     // #2
  int main() {
    A<int> a;
    f(a);
  }

1/30/97 IL lowering: const qualifier on "this" parameter type in generated
        wrapper routine for virtual function with covariant return type

The wrapper routines generated by IL lowering as interfaces to virtual
functions with covariant return types had a const mismatch between the
type of the "this" parameter as indicated in the a_param_type list and
the type as indicated in the parameter variable.  (See Changes entry of
7/16/96; this is the same issue, for the wrapper functions.)  The const
qualifier is now correct.

1/29/97 Enumerator with value larger than int range should be error (for now)

The front end has failed to diagnose enumerator expressions whose
values are outside of the int/unsigned int range.  Values in the int
range are okay, and values that are acceptable as unsigned ints but
not as ints are accepted as an extension.  However, values outside
that range should get an error, and didn't.  Now fixed.  From a
practical point of view, this failure had little significance
on many versions, because if int and long have the same size the
only way to get invalid values is to have long long configured
in and use a long long constant.  But on versions with, say,
16-bit integers and 32-bit longs, the problem was easy to provoke.

This is an interim fix: at some point, we will be implementing the
WP rules, which allow enums to have base types larger than int.
But until then, we are following the C and ARM C++ rules, which
limit enums to the int range, and we should be issuing this error.
(And the check will continue to be needed in C mode.)

Failure to detect this error caused a later internal error on the
following case, when "long long" is allowed and is bigger than int
and bigger than 32 bits:

  enum {
    Fosc = 100000000000,
    Ft0 = Fosc/12
  };

On versions with 16-bit ints and 32-bit longs, the same abort can be
gotten with a value of 100000 in the above example.

1/29/97 Specializing a partial specialization of a member template

Formerly, it was not possible to provide a partial specialization of
a member class template that was specialized.  It was also not possible
to specialize a partial specialization of member class template.  These
problems have been fixed.

Partial specialization of specialization of member class template:

  template <class T> struct A {
    template <class T2> struct B {};
  };
  template <> template <class T2> class A<short>::B {};
  template <> template <class T2> class A<short>::B<T2*> {};

Specialization of a partial specialization of a member class template:

  template <class T> struct A {
    template <class T2> struct B {};
    template <class T2> struct B<T2*> {};
  };
  template <> template <class T2> class A<short>::B<T2*> {};

1/27/97 C-generating back end: base types of bit fields in generated code

When ALLOW_NON_INT_BIT_FIELD_BASE_TYPE_IN_GENERATED_C is TRUE (which it
is by default, except when CFRONT_OBJECT_CODE_COMPATIBILITY is TRUE),
the C-generating back end now puts out the base types of bit fields as
they were declared, rather than with the standardized base types "int",
"signed int", and "unsigned int".  For example, a bit field declared
as "unsigned char i:3;" is now put out that way rather than as
"unsigned int i:3;".  The old behavior is available by setting the
option to FALSE.

1/27/97 Bit-field type adjustment in K&R mode

The base type of bit-fields in K&R mode is now adjusted from plain
integral type to the explicitly unsigned version of that type (e.g., from
"int" to "unsigned int").  For example:

  struct S {
    int i:3;
  };

In K&R mode the field entry for "i" has a type of "unsigned int".  This
produces more accurate IL in expressions for which integral promotion is
not performed.

1/27/97 Preprocessor stringizing of wide literals: quotes escaped

When the preprocessor stringizing operation is applied to a wide character
constant or wide string literal, quotes in the token are now escaped.

  #define X(A) #A
  int main() {
    printf("%s\n", X(L"x"));  // Produces string "L\"x\"" now
  }

1/27/97 Initialized incomplete array of char (typedef case)

A spurious error (introduced in version 2.34) is no longer put out when a
character array is declared with a typedef specifying unknown size and
initialized with a string:

  typedef const char MSG[];
  MSG message = "Hello, world";    // Spurious error no longer issued

1/27/97 Checking the return type of operator->()

The return type of operator->() is no longer checked at the point at which
the function is declared but only at the point of use in a class-member
access expression.  (The check of operator->() return types used to be
deferred only for class template members, but now it's deferred for all
operator-> functions.)

  struct A {
    int i;
    int operator->();         // Error is no longer issued here
  } a;
  void f() {
    (void)a->i;               // Error
  };

1/27/97 Building the front end on Windows NT using the Watcom compiler

The Watcom compiler does not currently define the _WIN32 macro.  As a
workaround, basics.h has been modified to set the EDG macro __WIN32__
when using the Watcom compiler on Windows NT.

1/24/97 Lexical data structure: reserved characters eliminated

The underlying data structure for the lexical routines has been changed
to eliminate the need for reserved characters.  A zero byte in the
data structure now introduces a two-byte escape sequence, in which
the second byte indicates whether the escape represents newline,
end-of-line, end-of-token, or end-of-insertion.  Using a two-character
escape sequence for the newline character frees up the newline character
itself ('\n') for use as ATTENTION_MARKER (which needs to be a
single-character escape).

The characters formerly used for ATTENTION_MARKER and END_OF_TOKEN_MARKER
(hex 81 and 82, nominally) are now available as input characters.

An error is now issued if a source line contains a zero character.
Formerly, the input line was silently truncated at that point.

1/24/97 Spurious error in selection of partial specialization

A spurious ambiguity error was issued when selecting between several
partial specializations.  This has been fixed.
  
  template <class T, class U, class Z> struct A {};
  template <class T2> struct A<int, int, T2> {};
  template <class T, class T2> struct A<int, T, T2> {};
  template <class T, class T2> struct A<T, int, T2> {};
  A<int, int, int> a;  // Spurious error during instantiation

1/24/97 Exception specification on predeclared operator delete

An exception specification corresponding to "throw()" is now added to the
entries for predeclared operator delete and operator delete[] when support
for exceptions is enabled.  (An analogous change has not yet been done for
the predeclared operator new functions; this it would also involve
predeclaring namespace std, class std::bad_alloc, and possibly class
std::exception.)

1/23/97 Memory mapping portability change

The map_file_region routine in host_envir.c has been changed to no longer
allocate an additional byte of memory when mapping a file region.  This
was originally done to suppress a warning produced by CodeCenter.  It
has been removed because it causes the unmap operation to fail on some
systems (HP/UX for example).

1/23/97 Microsoft compatibility: linkage specification and storage class

In Microsoft compatibility mode a declaration with a direct linkage
specification (i.e., not part of brace enclosed list of declarations) is
now allowed to have a storage class or "inline".

  extern "C" static void f();          // Now accepted in Microsoft mode
  extern "C" inline void g();          // Now accepted in Microsoft mode

Such cases are now handled as though they had been written with braces --
e.g., the examples are regarded as equivalent, respectively, to

  extern "C" { static void f(); }
  extern "C" { inline void g(); }

1/23/97 Microsoft compatibility: static data member in unnamed class

In Microsoft compatibility mode no diagnostic is issued on a static data
member declared in an unnamed class.

1/23/97 Microsoft and cfront compatibility: return expression in void function

In Microsoft C compatibility mode, a return statement with a return
expression is now permitted in a function with a void return type; a
warning is issued.

In cfront 2.1 mode, only an expression of void type is accepted in a return
statement of a void function.

  void f(int i) {
    return i;            // Now an error in cfront 2.1 mode; no longer an
  };                     //   error in Microsoft C mode
  void g(int i) {
    return (void)i;      // Still allowed in cfront 2.1 mode; no longer an
  };                     //   error in Microsoft C mode
    
1/22/97 Microsoft compatibility: __declspec preceding linkage specification

In Microsoft compatibility mode the following declaration is accepted:

  __declspec(dllimport) extern "C" void f();

However, a warning is issued because (as with the Microsoft compiler)
decl-modifiers preceding a linkage specification are ignored.  In other
words, the above declaration is not equivalent to:

  extern "C" __declspec(dllimport) void f();

1/22/97 Microsoft compatibility: enum types can be used as qualifiers

The Microsoft compiler allows enum types to be used as a qualifier
in a qualified name.  We now duplicate this behavior in Microsoft mode.
As with the Microsoft compiler, only member enumerations are permitted.

  struct A {
    enum E { e1 };
    int f() { return E::e1; }  // Accepted by Microsoft compiler
  };
  enum F { f1 };
  int f() { return F::f1; }    // Not accepted by Microsoft compiler


1/21/97 struct with no named field in C mode

Diagnostics on failing to declare at least one named field when defining a
struct in C mode have been relaxed.  Declaring a struct with no fields at
all remains an error, but if none of the fields declared is named, a
diagnostic is issued only in strict mode.  For example:

  struct A { };            /* Still an error in all C modes */
  struct B { int:1; };     /* Error (or warning) in strict C mode, no
                                diagnostic otherwise */

1/20/97 Incorrect processing of ?: operation in default argument expression
        in template

In a case like the following, involving a ?: operation that tests
a nontype template parameter, the front end incorrectly concluded that
the default argument was not dependent on template parameters and
therefore failed to evaluate it correctly on some instantiations.

  template<int N1, bool N2=((N1>=50)?true:false)>
  struct A {
    A(const char *name, int n2) { int i = N2; }
  };
  int main() {
    A<49> a49("A<49>",0);  // Got wrong value of N2 in instantiation
    return 0;
  }

1/20/97 Cfront and Microsoft compatibility: uninitialized const objects

Several errors on uninitialized const objects have been eliminated in
cfront and Microsoft modes.  First, cases involving an empty class:

  struct A { };
  struct B : A { };
  const B b;                         // Okay in cfront and Microsoft modes

Second, cases involving new-expressions with no initializer (superfluous
in Microsoft mode, since MSVC++ disallows new-expressions involving const
and volatile):

  struct A { virtual void f(); int i; };
  int main() {
    (void)new const A;               // Okay in cfront and Microsoft modes
  }

Third, in Microsoft mode only (since this had already been fixed in cfront
mode -- see entry for 12/17/96):

  struct A { virtual void f(); };
  const A a;                         // Okay in Microsoft mode
  struct B { B(); };
  struct C : public B { int i; }
  const C c;                         // Okay in Microsoft mode

1/20/97 Internal error on default template argument with ? : operator

An internal error would occur when processing a template declaration
with a default template argument containing a ? : operation that was
not in parentheses.  This has been fixed.

  template <int I, int J, int K = (I > J) ? I : J> struct A {};

1/19/97 Microsoft compatibility: sizeof typename, without parentheses

In Microsoft C++ mode, "sizeof typename" may now be used instead of the
standard "sizeof(typename)".

  typedef int I;
  int i = sizeof I;  // sizeof(I) is standard

The typename may not be a type keyword, e.g., "sizeof int" is not allowed.

1/17/97 Microsoft compatibility: C++ variable declared as a zero-length array

In Microsoft C++ compatibility mode a file-scope variable declared as a
zero-length array without an explicit storage class is treated as though
"extern" were present.  This means no error is issued on the following
(because it is not regarded as a definition):

  char s[];           // No longer an error in Microsoft C++ mode.

1/17/97 Microsoft compatibility: last field in class a zero-length array

The cases in which the last field in a class may be a zero-length array in
Microsoft compatibility mode have been expanded.  It used to be permitted
only for "aggregates" (i.e., no constructor, no private fields, no base
classes, etc.); now the only restriction is that the class have no virtual
base classes.  Moreover, the check for "last field" has been repaired to
allow the following:

  struct S {
    int a, b, c[];        // error is no longer issued in Microsoft mode
    void f();
  };

In addition, an error is now issued if a class with a zero-length array
field is declared as a base class:

  class B { ... char[] s; };         // accepted in Microsoft mode
  class D : B { ... };               // error now issued

1/17/97 Invalid pointer in il_header

With elimination of unneeded IL entries enabled, the main_routine pointer
in il_header was not being cleared when main itself was removed from the
IL.  Now fixed.  Here's an example:

  class A {
    friend int main();
  };

1/17/97 Internal error on specialization of invalid template

An internal error could result on an attempt to specialize a class
template containing certain extreme syntax errors.  This has been fixed.

  template <class T> class A {; 
  template <> class A<T*> {};

1/16/97 Microsoft compatibility: __declspec in declarator

In Microsoft mode extended declaration specifiers are now permitted within
a declarator, but they are ignored (and a warning is issued).  For example:

  int * __declspec(dllexport) f();   // "dllexport" is not applied to f
  typedef int * PI;
  PI __declspec(dllexport) g();      // "dllexport" is applied to g

This seems to match how MSVC++ handles these cases: it is only when
__declspec appears among the decl-specifiers that the Microsoft compiler
applies the specified attributes to the entity being declared; otherwise it
parses but ignores the __declspec specifier (usually with no diagnostic).

1/16/97 C and C++ function types should not be distinct in Microsoft mode

The front end was configured to consider C and C++ function types as
distinct types in Microsoft mode, while the Microsoft compiler does
not treat such types as distinct.  This resulted in a spurious "object
of abstract class type is not allowed" error when using some of the
Microsoft header files.  This has been corrected.

1/15/97 Improved diagnostics on invalid use of abstract class

For a invalid use of an abstract class (e.g., declaring an object with
such a class), the diagnostic now includes a supplementary list of the
class's non-overridden pure virtual functions.

1/15/97 Spurious access error on new-style specialization

Examples such as the following resulted in a spurious access error on the
declarator in the specialization.  This has been fixed.

  template <class T> class A {
    T f();
  };
  template<> int A<int>::f();

1/15/97 Change in the way that pragma caches are terminated

The correction needed for the nested pragma problem described below involved
a change in the way that pragma caches are terminated.  Previously, the
pragma token cache was terminated by a tok_newline followed by a
tok_end_of_source.  The tok_newline is no longer included in the pragma
cache.  Pragma processing code that checks for the tok_newline will need
to be changed to check instead for the tok_end_of_source.

1/15/97 Internal error on nested pragma

If, while processing a pragma, the tokens of another pragma were required
to be rescanned, an internal error would result.  This could occur,
for example, when an instantiation pragma results in the use of a token
cache that contains some other pragma.  This has been fixed.

  template<class T> void
  #pragma test_immediate
                        f(T t){ }
  #pragma instantiate void f(int)

1/14/97 Diagnosis of partial specializations in invalid scopes

Certain invalid partial specialization declarations were accepted without
a diagnostic being issued.  The appropriate errors are now issued.
For example, the following partial specialization of N::A is invalid because
such a partial specialization must initially be declared within namespace N.

  namespace N {
    template <class T1, class T2, int I> class A {};
  }
  template <class T, int I> class N::A<T, T*, I> {};

1/13/97 C++-generating back end: source sequence entries for an instantiation
        that appears inside a class template definition

This bug occurred when instantiations were represented in source sequence
lists (that is, CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS
and/or NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was set to
TRUE): the ordering of source sequence entries was incorrect when
instantiations were triggered by a class template definition, with the
result that incorrect code was issued by the C++-generating back end.  For
example:

  template <class T> struct A { T t; };
  template <class T> struct B {
    A<int> s;
  };

Now that the bug has been fixed, the source sequence entry representing the
instantiation of A<int> precedes (rather than follows) the source sequence
entry for the definition of class template B.

1/13/97 Microsoft compatibility: special lookup of template names

In the following example the Microsoft compiler incorrectly finds the
global template instead of the base class member.  We now duplicate
this behavior in Microsoft mode.

  template <class T> struct x {};
  class A {
    int x;
  };
  class B : public A {
    typedef x<int> xi;  // Microsoft compiler finds template ::x
  };

1/13/97 Microsoft compatibility: guiding declarations are disabled

In Microsoft compatibility mode a function declaration that matches a
function template is regarded as an independent function rather than a
"guiding declaration".

1/13/97 Enabling/disabling recognition of "guiding declarations"

Command-line options --guiding_decls and --no_guiding_decls have been added
to control whether a function declaration that matches a function template
is regarded as a "guiding declaration" or an independent function (see also
DEFAULT_GUIDING_DECLS_ALLOWED in lang_feat.h).  For example:

  template void f(T) { ... }
  void f(int);                 // never defined
  int main() { f(0); }

If f(int) is regarded as a guiding declaration, it is an instance of the
template and will be implicitly instantiated if necessary.  If not, there
will be a linker error if the program does not explicitly supply a
definition.  Guiding declarations are described (in other terms) in the
ARM; their elimination is a relatively recent change to the Working Paper.
Guiding declarations are disabled by default in strict-ANSI mode.

When guiding declarations are disabled, a definition of a function that
matches a template is regarded as the definition of an independent
function, not as a specialization of an instance of the template, even if
old-style specializations are enabled.  For example,

  template void f(T) { ... }
  void f(int) { ... }           // old-style specialization?

f(int) is regarded as an instance of the template -- and its definition
is regarded as a specialization -- only if guiding declarations are
enabled.  Thus, it is only if guiding declarations are enabled that this
can get an error for being an ill-formed specialization (i.e., for failing
to use "template<>" syntax) when --no_old_specializations is specified on
the command line.

1/13/97 Internal error or abort on invalid member template constructor

An internal error or abort could result when an invalid member template
constructor was used.  This has been fixed.

  struct A {
    template <class T> A (T) x;
  };
  A a(1);

1/12/97 Abort on type conversion of enumerator with invalid expression

The front end would abort (after a correct error message) if a type
conversion was applied to an enumerator whose value was given by an
invalid expression.  This has been fixed.

  enum { X = Y };  // Error, Y undeclared
  long i = X;  // Abort here on type conversion

1/10/97 Pointer-to-member selection: cv-qualifiers of left operand, rvalue
        result

The pointer-to-member selection operators .* and ->* now add any
cv-qualifiers of the left operand type to the result type (but not in
Microsoft mode):

  struct A {int i;};
  const A ca = {0};
  int main () {
    int A::*pm = &A::i;
    ca.*pm = 1;  // Error, lvalue has type const int
  }

Also, rvalue.*pm now produces an rvalue result (but not in cfront or
Microsoft modes):

  struct A {int i;};
  A f();
  int main () {
    int A::*pm = &A::i;
    (f()).*pm = 1;  // Error, can't assign to rvalue
  }

1/10/97 Microsoft compatibility: keywords with single-underscore prefix

Support for single-underscore versions of Microsoft keywords has been
augmented.  Now _int8, _int16, _int32, and _int64 are recognized; also
_try, _finally, _leave, and _except; also _unaligned and _declspec.
(Support for a number of other Microsoft single-underscore keywords was
already provided.)

1/9/97  Abort when a partial specialization nontype argument is deduced
        from an array bound

The front end would abort when a nontype argument of a partial
specialization was deduced only from an array bound.  This has been fixed.

  template <class T> struct A {};
  template <class T, int N> struct A<T[N]> {
    A(){}
  };
  A<int[10]> a;

1/8/97  Internal error after tentative lookup of invalid template instance

An internal error has been fixed for the following invalid program:

  class A {
    int x;
  };
  class B : public A {
    typedef x<int> a;     // Internal error has been fixed
  };

1/8/97  Partial lowering of EH: cleanup state for partially-constructed
        aggregates

When an aggregate is partially constructed, the EH cleanup state indicates
the destructions to be done for the parts already constructed.  When
GENERATE_EH_TABLES was FALSE, IL lowering was not putting out the
expressions to record the cleanup state after each partial construction.
Now fixed.

1/8/97  Template parameters in elaborated type specifiers

X3J16/WG21 has reaffirmed their previous decision that template parameters
are not permitted in elaborated type specifiers in any circumstances,
including declarations such as "friend class T".  Consequently, the
diagnostic for such use has been promoted from a remark to a warning in
default mode, and to an error in strict mode (-A).

1/8/97   Internal error on IL lowering of covariant return types

In cases where an overriding virtual function had a return type that is
covariant with the functions it overrides in some base classes and not in
others, IL lowering aborted in add_covariant_return_type_entry_routines.
Now fixed.

1/8/97   Partial lowering of EH: cleanup state at switch clauses

When IL lowering is configured to do partial lowering of exception handling
constructs, expression nodes to indicate the cleanup state are inserted
in some extra places (e.g., after transfers of control at the ends of
blocks) to make it easier to build a lookup table instead of setting a
state variable.  A bug in the generation of that code for switch clauses
has been fixed.

1/8/97   Source position on statement generated by IL lowering for return

When it is necessary to generate destructions at a return statement that
looks like

  return expr;

IL lowering transforms the code to

  temp = expr;
  ... call destructors ...
  return temp;

The initial statement (the assignment) formerly had no source position
set.  Now the source position is set to that of the original return
statement.

1/7/97   Abort on redefinition of partial specialization

The redefinition of a partial specialization resulted in an abort.
This has been fixed.

  template <class T> class A {};
  template <class T> class A<T*> {};
  template <class T> class A<T*> {};

1/7/97   Linkage on wrapper routines generated by IL lowering for covariant
         virtual function return types

IL lowering was not correctly setting the linkage on the wrapper routines
it generates to implement covariant virtual function return types.  One
consequence of this, for those who use the needed-flag-dependent
elimination of unneeded IL entities, was the possibility of aborts
in the C-generating back end because the body of the primary overriding
routine had been eliminated but the wrapper routine body was still
present.

A related bug, that caused an abort in node_complete_object_type, has
also been fixed.

1/7/97   Spurious access errors in template class instantiations

If a primary class template was declared using the class keyword and a
partial specialization was declared using the struct keyword, the members
of the partial specialization were incorrectly considered to be private.
This has been fixed.

  template <class T> class A;
  template <class T> struct A<T*> {
    A();
  };
  A<int*> a;

1/6/97   Microsoft compatibility: __asm blocks in template member functions

A bug has been fixed that caused a spurious error to be issued when a
Microsoft __asm block appeared in a member function of a class template.

  template<class T> struct X {
    void f() {
     __asm { int 1 };
    }
  };

1/6/97   Checking for volatile-qualified left operand of bitwise assignment

In strict mode and Microsoft mode, for a class for which no operator=()
is declared, and for which the default generated operator= does bitwise
assignment, an error is now issued on an attempt to assign to a left
operand of cv-qualified type.  const-qualification was always checked for,
so from a practical point of view this change affects assignments to
volatile-qualified operands and to operands qualified with nonstandard
type qualifiers.

1/6/97   Deduction of template conversion function with cv-qualified result

Type deduction for template conversion functions did not allow cases
where the return type was cv-qualified.  Now fixed.

  struct NULL {
    template <class T> operator T*() const { return 0; }
  } NULL;
  int main()
  {
    char *pc = NULL;        // was accepted
    char *const cpc = NULL; // was error, now accepted
  }

1/6/97   Incorrect handling of pragmas in member functions of class templates

If a pragma appeared in a member function of a class template, the pragma
tokens were being discarded following the prototype instantiation of the
class template.  This would result in incorrect handling of the pragmas,
and/or internal errors while processing the pragmas.  This has been fixed.

1/5/97   C++-generating back end: pragmas following prototyped parameter lists

A change made in 2.34 (see Changes entry of 11/25/96) to deal with
macros within prototyped parameter lists broke cases like the following:

  void f(int);
  #pragma unknown

In the output, the pragma came out within the parameter list.  Now fixed.

1/3/97   ABI_CHANGES_FOR_PLACEMENT_DELETE passed to runtime

The value of the ABI_CHANGES_FOR_PLACEMENT_DELETE flag is passed to the
runtime as __EDG_ABI_CHANGES_FOR_PLACEMENT_DELETE when using the
--building_runtime option.

1/3/97   Abort in name mangling with partial specialization of class

A null-pointer-dereference abort could result in some cases when
name mangling was attempted for partially-specialized classes.  Now fixed.

12/22/96 Maintaining "needed" flags: virtual functions with covariant
         return types

The processing to maintain "needed" flags now ensures that the definition
of a class type underlying a covariant return type is kept, i.e., that
that context is one that requires a complete class type.

12/20/96 Removing unneeded IL entities and namespaces

The processing for removing unneeded IL entities (controlled by
MAINTAIN_NEEDED_FLAGS at al.) did not work quite right in the presence
of namespaces, which could cause an IL write/read check internal error.
This abort only occurred, however, when IL lowering was not done.

12/19/96 IL display program did not set f_debug

The IL display program did not initialize the f_debug variable, causing an
abort if the program attempted to produce debug output.  This has been
fixed.

-------------------------------------------------------------------------------
Version 2.34, December 18, 1996

12/18/96 IL version number changed to 2.26

12/18/96 Source sequence entry for namespace declaration

A bug has been fixed that caused the source sequence entry for the macro
in the following fragment to appear before the source sequence entry for
the namespace declaration.  Fixed.

  namespace N {
  #define X Y
  }

12/17/96 Spurious error on declaration and definition of member class
         template within a class template

An error was issued if a member class template was declared and then
later defined within another class template.  This has been fixed.

  template <class T> struct A {
    template <class T2> struct B;
    template <class T2> struct B {};
  };
  A<int> ai;

12/17/96 Default initialization of const variable

A bug has been fixed that was introduced in version 2.33.  Except in -A
mode we issued no diagnostic on the following (which is ill-formed because
class Derived lacks a user-declared default constructor for the default
initialization of const variable d):

  struct Base {
    virtual ~Base () { }
    virtual void f () const { }
  };
  struct Derived : public Base {
    ~Derived () { }
    void f () const { }
  };
  const Derived d;                     // Error was issued only in -A mode
  static void g (const Base& x) { x.f(); };
  int main () { g(d); return 0; }

However, no code was put out to call the compiler-generated constructor,
so that the virtual function table was not initialized and a run-time
abort occurred.  This part of the problem has been fixed.

Moreover, if in general a const variable is not explicitly initialized and
its class has an implicitly declared nontrivial default constructor (and
therefore no user-declared declared default constructor), we have relaxed
the checking introduced in version 2.33: the front end now issues a
discretionary error in -A mode, no diagnostic at all in cfront mode, and a
warning otherwise.

  struct S { virtual ~S(); };
  const S s;                   // Now an error in -A mode and a warning in
                               //   non-cfront mode

12/15/96 Enum types are not treated as integral

In C++ mode (except in cfront-compatibility mode) enum types are no longer
treated as integral types.

Among other things, this means an enumerator with value zero is not
considered to be a null-pointer-constant:

  enum { zero };
  int *p = zero;                  // Now an error in C++

Here's another error that is now diagnosed, since a pointer can be cast
to an integral type, but not to an enum type.

  enum E { /* ... */ };
  void *p;
  E e = static_cast<E>(p);        // Now an error

12/13/96 Partial specialization of class templates

Partial specialization of class templates is now supported.  A partial
specialization is a version of a class template that is used for
instantiations that match the argument list of the partial
specialization.  When an instantiation of the class is required, the
front end selects the partial specialization that most closely matches
the argument list.  If none of the specializations match, the primary
template is used.  If more than one specialization matches, and the
specializations are "unordered" relative to one another, then the
instantiation is ambiguous.

  #include <stdio.h>
  template <class T, class U> struct A        { int i; A() : i(1) {} }; // #1
  template <class T, class U> struct A<T*, U> { int i; A() : i(2) {} }; // #2
  template <class T> struct A<T*, T>          { int i; A() : i(3) {} }; // #3

  A<int, char> a1;  // uses #1
  A<int*, char> a2; // uses #2
  A<int*, int> a3;  // uses #3

  int main()
  {
    printf("%d %d %d\n", a1.i, a2.i, a3.i);  // outputs 1 2 3
  }

A member class template may be partially specialized, but any partial
specializations must be declared within the enclosing class.  The
Working Paper is silent on where such partial specializations may
be declared.  We have chosen this rule pending clarification by
the X3J16/WG21 committee.

The mangled names for partial specializations use a new "__ps__"
prefix that introduces the first of two template argument lists
used on the partial specialization.  The name demangler has been
updated to recognize those as well.

12/12/96 Initialization of local static variables

In accord with a recent change to the Working Paper, initialization of
local static variables by a non-integral constant is again represented in
the IL as a static initialization.  This restores pre-2.33 behavior (see
9/30/96 entry).

12/12/96 Reference to function initialized by overloaded function

As in the similar pointer case, a reference to function can be initialized
to an overloaded function name, and the function that matches the
underlying type is selected.  This is now supported:

  void f(int);
  void f(float);
  void (&r)(int) = f;

12/12/96 Cast of overloaded function to reference type produces lvalue

A cast of an overloaded function name to a reference-to-function type,
which selects the appropriate function from the overload set, now
produces an lvalue for the function.  Formerly, it produced an rvalue
pointer to the function.

  void f(int);
  void f(float);
  void (&r)(int) = (void (&)(int))f;

12/12/96 Microsoft compatibility: binding reference to pointer when there
         are extra cv-qualifiers

Cases like the following, which were formerly accepted as extensions in
cfront mode, are now accepted in Microsoft mode also:

  void f(const char*& k);
  void g() {
    char* p;
    f(p);
  }

12/12/96 C++-generating back end: access specifier on member template

The C++-generating back end now puts out an access specifier on a
member template, if necessary.

12/12/96 Undefined inline virtual functions

The checking for undefined inline virtual functions in non-local classes
has been relaxed (see entry for 9/24/96).  An error is now issued in
strict mode (-A) only.  By default no diagnostic is issued -- except that,
when DO_IL_LOWERING is TRUE, a warning is put out if it is known that a
virtual function table for the class will be generated for the current
translation unit.

12/11/96 Checking exception specifications on reference binding

Exceptions specifications are now checked when binding a reference to
a function:

  void f();
  void ff() throw(int);
  void (&pf3)() throw(int) = f;         // Error
  void (&pf6)() throw() = ff;           // Error

12/11/96 Internal error caused by badly formed IL for aggregate initializer

A bug has been fixed in building the IL to represent the initializer for an
aggregate with a subobject whose type is a class with a destructor but no
constructor.  The problem only appeared when support for exceptions was
enabled and had to do with recording the destructor to be called if an
exception were thrown before the aggregate was completely initialized; the
internal error that resulted appeared during IL-lowering.  Here's an
example:

  struct S {
    int i;
    ~S() { }
  };
  extern int k;
  S d[] = { k, 0 };          // No longer triggers an internal error

12/6/96  Abort with member template for operator=

An abort has been fixed that could occur when a member template was
declared for operator=.  Here's an example that failed when support for
exception handling was enabled:

  template <class X> struct auto_ptr {
    template <class Y> auto_ptr& operator=(const auto_ptr<Y>& a);
    auto_ptr& operator=(const auto_ptr& a);
  };
  struct A { };
  struct B {
    auto_ptr<A> c;
  };                 // No longer aborts when generating copy assignment
                     //   operator for class B

12/5/96  Name lookup for local-class friend declarations

In accord with a recent clarification to the Working Paper, the lookup of
an unqualified name specified by a friend declaration in a local class now
goes no further than the containing function or block scope.  For example:

  class X;
  void f() {
    class Y {
      friend class X;  // Lookup no longer finds ::X, so local class X
    };                 //   is now introduced into scope of function f.
  }

Note: "name injection" (which has recently become obsolete) is still done
when the friend lookup fails; this will be fixed in the future.

12/5/96  extern "C" and implicit int

The diagnostic message has been clarified for declarations like the
following:

  extern "C" f(int);

12/5/96  Implicit int and function parameter declarations

A diagnostic is now issued on the following:

  void f(const *);    // error in strict ANSI C++ mode, warning otherwise

12/5/96  Microsoft compatibility: implicit int on function declarations

There were some cases in which errors were issued in Microsoft
compatibility mode on function declarations with an implicit int return
type.  This has been fixed -- warnings are issued in Microsoft C++ mode,
and remarks in Microsoft C mode.

12/4/96  Microsoft compatibility: spurious warning on friend declaration

A bug was introduced in version 2.33 that in Microsoft compatibility mode
caused spurious warnings to be issued on friend function declarations.
Now fixed.

  struct S {
    friend void f();   // Spurious warning no longer issued
  };

12/4/96  Microsoft compatibility: single line __asm blocks terminated by brace

If a single line __asm block was followed, on the same line, with a right
brace, the right brace was considered part of the __asm.  The Microsoft
compiler considers the brace to terminate the __asm.  This front end has
been corrected to handle this in the same way as the Microsoft compiler.

  void f() { __asm mov eax, fs:[0x10] }

12/2/96  Microsoft compatibility: initializing incomplete array type member

In Microsoft C++ mode the following is now accepted (and an internal
error is no longer issued):

  struct S {
    int i;
    char a[];
  };
  S s = { 0, "Hello" };    // Initialization of s.a used to be allowed only
                           //   in Microsoft C mode; now okay in C++ mode

11/27/96 Exception specifications on pointer-to-member-function declarations

In a follow-up to the changes recorded for 11/6/96, and specifically as
a result of a recent clarification in the Working Paper, exception
specifications are now recorded for the function declarators of top-level
pointer-to-member-function and reference-to-function declarations:

  class A;
  void (A::*pmf)() throw();     // Now accepted
  void f() throw();
  void (&rf)() throw() = f;     // Now accepted

11/26/96 Missing diagnostic on member function with invalid default argument

No diagnostic was issued when a member function of a class template had
default arguments that did not appear at the end of the parameter list.
This has been fixed.

  template <class T> struct A {
    void f(int = 0, int);
  };

11/26/96 Duplicate diagnostic on invalid default argument in friend declaration

A friend function declaration with default arguments that are not at
the end of the parameter list would result in duplicate error messages.
This has been fixed.

  struct A {
    friend void f(int = 0, int);
  };

11/26/96 Warning on return of local variable or temporary

A warning is now issued in more cases when a function returns a reference
that is bound to a local variable or temporary.  Formerly, a warning
was issued only for temporaries, and only when the temporary was created
by the process of binding a reference to non-const.

11/26/96 C++-generating back end: pragma as sole contents of class

The C++-generating back end has been changed so that it does not get an
internal error on a class that contains only a pragma.

11/25/96 Folding of floating-point constant comparisons: unordered and !=

do_fcompare has been changed such that when two floating-point constants
are unordered with respect to one another and the comparison being
performed is "not equal", the result is "true".

11/25/96 Routine name linkage on function template instance

When an instance of a function template was first referenced within an
extern "C" context, the language linkage associated with its type was
incorrectly set to extern "C" (rather than extern "C++").  Now fixed.

  template <class T> void f(T) { }
  extern "C" void g() {
    f(0);                  // The linkage of the type for f(int) is now
  }                        //   set to extern "C++"

11/25/96 C++-generating back end: macro definition in prototyped parameter list

The C++-generating back end got an internal error on a macro definition
within a prototyped parameter list.  Now fixed.

  void f(int x,
  #define Y1 y
  int Y1) {}

11/25/96 Active using-directive information not restored in some cases

In certain cases involving template instantiation the information about
the using-directives that are currently active may not be restored
properly when the instantiation has completed.  This has been fixed.

11/25/96 Warning on for-init difference turned off in strict mode

The warning about a difference of behavior between the old and new
for-init scope rules is now turned off by default in strict mode.

11/25/96 Overload resolution: comparison of non-bitwise class copy

In overload resolution, a non-bitwise class copy that involves a
derived-to-base conversion was not compared properly to another
conversion involving a derived-to-base conversion.  Now fixed.

  struct B {};
  struct I: public B {
    virtual int mbr(const B &) const;
    int mbr(I) const;
  };
  struct D: public I {};
  void fred(D* pd, const D & from) {
    pd->mbr(from); // Was treated as ambiguous; now okay
  }

11/25/96 Default argument on operator()() declaration

The function call operator is now permitted to have default arguments in
strict mode, and so a diagnostic is no longer issued for such cases.

11/20/96 Name mangling problem on nontype template arguments

With the new mangling scheme for template names, there were cases where
the mangled name for a nontype template argument that represents the address
of a function, used in a template argument list in the mangled name of
another function, had extra incorrect mangling.  This had the
additional side effect of causing a prelinker loop on the example
below.  Now fixed.

  double f(double x) { return x; }
  template<class T0, T0 (*F)(double)> class App {};
  template<class T0, T0 (*F)(double)> T0 apply( App<T0,F> ) {
    double x=0;
    return F(x);
  }
  int main()
  {
    App<double,f> a;
    apply( a );
  }

11/19/96 New predefined macros for exceptions, RTTI, and placement delete

New macros are now defined when exceptions, RTTI, and placement delete are
enabled.  The macro names are specified by the configuration flags
MACRO_DEFINED_WHEN_EXCEPTIONS_ENABLED, MACRO_DEFINED_WHEN_RTTI_ENABLED,
and MACRO_DEFINED_WHEN_PLACEMENT_DELETE_ENABLED.  The default values are
__EXCEPTIONS, __RTTI, and __PLACEMENT_DELETE.

11/19/96 Internal error when immediate pragma added to scope with no IL scope

If an immediate pragma appeared in a front end scope with no associated
IL scope (e.g., a template declaration scope), and that pragma was added
to the IL, an internal error would result.  This has been fixed by adding
the IL pragma entry to the nearest enclosing scope with an associated
IL scope.

11/6/96  Checking exception specifications on assignment and initialization

An error is now issued on an assignment or initialization involving
pointer-to-function types when the entity assigned allows exceptions to
be thrown that the object assigned to does not allow.  For example:

  void f1();                  // allows anything to be thrown
  void f2() throw();          // allows nothing to be thrown
  void (*pf)() throw(int);    // *pf only allows an int to be thrown
  int main() {
    pf = f1;                  // Error -- *pf is too restrictive for f1
    pf = f2;                  // Okay
  }

11/6/96  Exception specifications on pointer-to-function declarations

Up to now exception specifications have been ignored on all function
declarators except those belonging to top-level function declarations.
With this change, exception specifications are also recorded for the
function declarators of top-level pointer-to-function declarations (except
when the latter appears in a typedef declaration), and a discretionary
error is issued in other cases.  (Note: exception specifications are
still silently ignored when compiling with --no_exceptions.)

  void (*pf)() throw();               // Okay
  typedef void (*pf2)() throw();      // Error
  void (**ppf)() throw();             // Error

11/4/96  Spurious error on redeclaration of file scope template with the
         same name as a macro

Versions 2.32 and 2.33 issued a spurious redefinition error when a class
template was redeclared using a name that is also a macro name and the macro
was defined after the original declaration of the template.  This has been
fixed.

  template < class T > class A;
  #define A A
  template < class T > class A { };

11/4/96  Support for covariant return type on overriding virtual function

When ABI_CHANGES_FOR_COVARIANT_VIRTUAL_FUNC_RETURN (in host_envir.h) is
configured to TRUE, support is now provided for "covariant" return types
on overriding virtual functions.  That is, the return types of an
overriding and an overridden virtual function are permitted to differ as
long as they are pointer (or reference) to D and B, respectively, where
class D is derived from class B (see Working Paper 10.3 [class.virtual]).

An ABI change is involved because a dynamic adjustment must sometimes be
made to the address that is returned.

IL CHANGE: Two new fields have been added, return_adjustment_base_class
to an_overriding_virtual_function and covariant_return_virtual_override
to a_routine.

If IL lowering is done, this feature is implemented by adding wrapper
functions which are pointed to from virtual function tables in cases
where the overriding function should be called but the interface
(specifically, the return type) must be that of the overridden function.
The mangled names for these wrapper functions begin with __VFE__.

IL CHANGE: The IL representation for a wrapper function is a routine with
overriding_function_for_covariant_return_type and
overridden_function_for_covariant_return_type set appropriately, and
a definition that is simply a return of an enk_result_of_overriding_function
node cast to the proper pointer-to-base-class.  The
enk_result_of_overriding_function node represents the value returned
from calling the overriding function with the arguments passed to the
wrapper.

While the IL representation is a wrapper function, the underlying
implementation need not be.  In fact, for functions with variable-length
argument lists, a wrapper approach may not be feasible.  Instead, a back
end can turn the wrapper routines into entry points of the overriding
function, or duplicate the body of the overriding function within each 
wrapper routine.  The C-generating back end uses the body-duplication
technique.

10/31/96 IL CHANGE: name field added to a_param_type

When RECORD_NAME_IN_PARAM_TYPE_ENTRY (see host_envir.h) is configured to
TRUE, there is a new field, "name", in a_param_type.  If the parameter is
associated with a function that is defined, the name in the param-type
entry is the same as the name in the associated parameter variable.  But
this field now also preserves the name (for use by debuggers, tools, etc.)
even when there is no associated function definition.

10/30/96 Freeing memory for generated trivial default constructors

The definition of a trivial default constructor is sometimes generated
even though it is not added to the IL (see entry for 8/7/96).  However,
when MAINTAIN_NEEDED_FLAGS and MINIMAL_INLINING were both configured to be
FALSE, an internal error could result, due to a failure to free the
associated memory region properly.  This has been fixed.

10/30/96 Incomplete type in exception specification

An error is now issued if an exception specification type is an incomplete
type or a pointer or reference to incomplete type (except cv-qualified
void *).  This is required by a recent Working Paper change (section 15.4
[except.spec] paragraph 1); in addition, it fixes an internal error in IL
lowering.

10/29/96 Missing destructions in the presence of unordered initializations

Since the C++ sequence point rules provide only a partial ordering on
the order of evaluation of expressions, they also provide only a
partial ordering on the order of initializations in expressions.
In some cases involving overloaded function calls, copy constructor
calls, and unordered expressions one or more temporaries were
not destroyed.

  struct A {
    A();
    A(const A&);
    ~A();
  }a ;
  A f();
  void g(A, const A&);
  void g(int, int);
  int main () {
    g(a, f());  // Two temporaries, one not destroyed
                // a and f() unordered with respect to one another
  }

10/29/96 Microsoft-style asm blocks in templates and member functions

Formerly, Microsoft-style asm blocks were not supported in contexts
in which the tokens were cached and rescanned later, which includes
the bodies of member functions and function templates.  The token
caching routines now permit pp-tokens to be cached and rescanned later.
Consequently, asm blocks are now supported in these contexts.

10/29/96 White space and comments within Microsoft-style asm blocks

White space and comments are no longer preserved when converting
Microsoft-style asm blocks into text strings.  This is a consequence
of the changes made to permit asm blocks in templates and member
functions described above.

10/29/96 Improper lowering of stmk_init for local static variables

A change made in 2.33 resulted in stmk_init statements for local static
variables being left in the IL after lowering, which is not proper C
IL.  Now fixed.  (See 9/30/96 change and related partial fix on 10/16/96.)

  void f() {
    static float x = 1.5;    // Dynamic initialization in C++, but can
                             // be lowered to static initialization
  }

10/29/96 Setting of cleanup state on destruction, with promoted temporaries

In a case like the following, where the lifetime of a temporary is extended
because it is bound to a reference, the cleanup state that was set when
beginning destruction of the promoted temporary pointed back to the other
temporary, which would already be destroyed at that point.  This would cause
a problem if an exception were thrown in the destructor.  Now fixed.

  struct X {
    X();
    X(const X&);
    ~X();
  };
  struct Y {
    Y();
    Y(const Y&);
    ~Y();
  };
  X f(Y&);
  Y g();
  int main() {
    const X& r = f(g());  // Destruction of X temporary now has proper
                          // cleanup state.
  }

10/25/96 Spurious ambiguity error on using directive lookup with struct
         name and synthesized overload set

A spurious ambiguity error was issued on the call of A() in the example below.
This occurred when a using-directive lookup resulted in a set of overloaded
functions from the same scope and a struct name that should be hidden.

  namespace N {
    struct A { };
    int A();
    int A(int);
  }
  using namespace N;
  int i = A();

10/23/96 Interaction of cfront mode and --extern_inline

When the command line specifies both cfront-compatibility mode and
extern inline support (and the latter option follows the former), an
internal error is no longer produced.  Instead, inline member functions
now force the class to have external linkage (just as non-inline member
functions have done all along).

10/22/96 Support for placement delete
         (IL CHANGE with partial lowering of exception handling)

Support for placement delete has been added.  This feature allows
declaration of operator delete and operator delete[] functions with
additional parameters.  When a placement new is done, if there is an
operator delete with the same parameter types (ignoring the first
parameter), and if an exception is thrown before the initialization for
the new has completed, the placement operator delete is called to
deallocate the storage.  This is implemented in IL lowering by wrapping
the equivalent of a try block around the initialization.  If an
exception is thrown, this internal try block intercepts it; the
operator delete function is called, and the exception is then rethrown.
In the partial-lowering and no-lowering EH modes, the internal try
block is represented by the new leck_internal_try expression node.

A warning is now issued when exceptions are enabled and a class has a
placement-new declaration but no corresponding placement-delete; when
exceptions are not enabled, a remark is issued that the placement-delete
declaration is useless.

10/17/96 Spurious warning on multi-line template static data member definition

A template static data member whose initializer is spread over several lines
of a file could result in a spurious "parsing restarts here" warning.
This has been fixed.

10/17/96 Incorrect warning on nonconstant shift by address cast to integral

A shift operation with a nonconstant left operand and a right operand that
is an address constant cast to an integral type gave an inappropriate
and confusing warning.  Now fixed.

  extern char addr[];
  int shift1(int size) {
    return size >> (unsigned int) addr;  // No warning now
  }

10/16/96 Object lifetime on initialization of local static variable

An object lifetime was sometimes generated for the initialization of a
local static variable even when the initializer was known to have no side
effects; this has been corrected (in part fixing a problem introduced in
version 2.33 -- see Changes entry for 9/30/96).  For example:

  int i;
  struct S { int x, y, z; };
  void f() {
    static int j = i;           // No object lifetime needed
    static S a = { 0,0,0 };     // No object lifetime needed
    static S b = a;             // No object lifetime needed
  }

In a related change, it is now only when exceptions are enabled that an
object lifetime is created for a local static variable initialization,
even when there are potential side effects from the initialization.

10/15/96 Delete allowed after placement new of array

The WP was recently changed to say that memory allocated through
a "placement" new can be freed through the delete operator.
In practice, such deletes have worked in the past except when the
entity allocated is an array of class type (that case failed because
the size of the array was not recorded at the time of the allocation).
Now, such deletes work properly, thanks to the new runtime routine
__placement_array_new and the new runtime global variable
__array_new_prefix_size.

10/11/96 Checking relaxed on overloaded function declarations

An error complaining that the parameter types are too similar for
overloading is no longer issued on declarations like the following:

  void f(int);
  void f(int&);    // No error -- overload set now contains both functions

As a result, a new error error may now be issued at the point of call:

  int main() {
    int i = 0;
    f(i);          // Error -- both functions match argument list
  }

10/11/96 Subscript checking on multi-dimensional arrays

Subscript checking was not done on subscripts after the first in
multi-dimensional arrays.  Such checking is now done.

  int main () {
    int a[2][3][4];
    a[1][1][4] = 1;  // Gets warning now
  }

10/11/96 Warning on substitution of "double" for "long double" in generated C

When the C-generating back end is used, in the mode that generates K&R C,
a warning is now issued if "double" is substituted for "long double".
The warning is issued only once per generated file.

10/10/96 Improved error recovery for "unrecognized" new[] and delete[]

When array_new_and_delete_enabled is FALSE and new[] or delete[] is
encountered, a clearer error message is issued and parsing proceeds as if
array new and delete actually were supported.

10/10/96 Error on more than one union member in ctor-initializer list

An error is now issued if a ctor-initializer list specifies more than one
member of a union (including anonymous union members):

  union U {
    int i, j;
    U() : i(0), j(0) { }                 // Error is now issued
  };
  struct S {
    union { int i, j };
    S() : i(0), j(0) { }                 // Error is now issued
  };

10/10/96 Failure to destroy temporary in default argument in long lifetime
         temporaries mode

A temporary created in a default argument for a constructor call on a
file-scope initialization with long lifetime temporaries enabled was
not being destroyed.  Now fixed.

  struct X {
    X(const char* other);
    ~X();
  };
  struct Y {
    Y(const X& name="foo");
    ~Y();
  };
  Y y;  // X temporary created here was not destroyed

10/9/96 Misleading error message on overload resolution corrected

A misleading error message came out in some cases where overload resolution
could not find a suitable function, where the object on which the call was
being done is const, and there was a function that would be suitable if
it were const.  The misleading message is no longer issued, and a correct
(generic) error is issued instead.

  struct XX {};
  struct YY {
    virtual XX fx();
    XX fx(const XX&);
    void foo(XX) const;
  };
  void YY::foo(XX xx) const {
    XX xx1 = fx(xx);  // Better error message here
  }

10/9/96 Initializing a char array with a string literal

An error is no longer issued when a field of type array-of-char is
initialized in a ctor-initializer with a string literal:

  struct S {
    char x[3];
    S() : x("ab") { }        // Spurious error eliminated
  };

In a related change, a string literal is now accepted in initializations
that use the "(...)" syntax ("direct" initializations) wherever it would
be accepted with the "=" syntax:

  char x[3]("ab");           // Same as char x[3] = "ab"

10/8/96 IL lowering: small improvement in code on return statement

The code for a return in a function with destructible objects, where
the return expression is constant but not something as simple as a
literal constant, is now improved (it doesn't use a temporary).

  typedef void (*PF)();
  void g();
  struct A {
    ~A();
  };
  PF f() {
    A a;
    return g;  // Doesn't use temporary
  }

-------------------------------------------------------------------------------
Version 2.33, October 2, 1996

10/1/96 IL version number changed to 2.25

10/1/96 IL lowering: two bugs with type-as-subobject of class in namespace

Two bugs have been corrected in IL lowering's processing of the
type-as-subobject class associated with a class that is the last type
in a namespace.  The first problem caused an internal error in
ensure_il_scope_exists, and the second resulted in incorrect generated
code (the type_as_subobject was referenced, but did not appear in
the final IL tree).

9/30/96 Dynamic initialization of local static variable

In C++, when the initializer of a local static variable is a non-integral
constant, the initialization is now represented as dynamic rather than
static, as required by section 6.7 paragraph 4 of the Working Paper.

  void f() {
    static float x = 1.5;    // dynamic initialization in C++
  }

9/30/96 Removing front-end-only types from based-types lists

The based-types lists that are passed to a back end (or to IL lowering) no
longer will include entries for pointer-to-member types that involve
"nonreal" classes or template parameter types; such types do not otherwise
escape from the front end.  For example:

  template <class T> class S { int S<T>::* pmi; ... };
  S<int> s;

The based-type list for "int" will include "int S<int>::*", but
"int S<T>::*" will be removed from the list when front-end processing is
completed.  a_based_type_list_member now has a new field, front_end_only.

9/30/96 Indication of point in throw where exception has been started
        (IL CHANGE if EH partially lowered)

In a throw, the evaluation of the throw expression is considered
to be outside of the throw, but the copy constructor call that copies
the object to the runtime is considered to be inside the throw.
(This is not altogether clear in the WP; the evidence we're going
on is 15.5.1 [except.terminate].  We've also decided that if copy
constructor elision is done, the (non-copy) constructor call that
builds the object is not inside the throw).  The issue of being
"inside" or "outside" the throw is significant because terminate
is called if an exception is thrown while inside another throw.
For cases with non-elided copy constructor calls, with full lowering
of EH features, the point where the exception is considered started
is now marked by a call to the new runtime routine __exception_started.
With partial lowering, the point is marked by a new
enk_lowered_eh_construct/leck_exception_started expression node.
Note that the new marker appears only when necessary, and the throw
itself is considered the start of the exception if the marker is not
present (e.g., for non-class cases).  This change applies only when
using ABI version 2.33 or later.

9/30/96  Microsoft mode disables language features not supported by
         the Microsoft compiler

Use of Microsoft mode now, by default, disables language features
that are not supported by the Microsoft compiler.  These features
can usually be explicitly enabled through the use of command line
options (for example, --bool).

9/29/96  IL lowering of exception handling: freeing storage on new

When an exception is thrown before a "new" has completed, the storage
allocated is supposed to be freed.  This is indicated by a special
dynamic initialization entry that describes the delete call.
When the allocation was not folded into a constructor, the freeing
operation was left on the cleanup list longer than necessary in some
cases, which was not generally harmful in the fully-lowered EH case
(because the cleanup entry has an associated guard variable, which
is cleared when the cleanup no longer needs to be done).  However,
in the partially-lowered EH case this gave misleading information
about the cleanup state.

9/27/96  Conversion costs on built-in operator [] in overload resolution

The standards committee, at the 7/96 Stockholm meeting, revisited the
builtin operator [] problem described in the 1/8/96 entry below, and
made a change.  The change makes the example (with an "unsigned int"
parameter) work as expected, but only on systems where ptrdiff_t is
larger than int (i.e., it's long).  Those who want to write portable
code are now encouraged to use a parameter of type ptrdiff_t:

  struct A {
    A();
    operator int *();
    int operator[](ptrdiff_t);  // Was "unsigned"
  };
  int main() {
    A a;
    a[0];  // Not ambiguous
  }

Because this change does not solve all problems for everyone, the
--special_subscript_cost option continues to be available.

The pointer +, -, +=, and -= operators were changed similarly.

9/27/96  Promotion cost for float operands of builtins in overload resolution

On builtin operators that take a promoted arithmetic operand, a float
operand should be considered to have a "promotion" cost for the promotion
to double.

  struct A {
    operator double();
  } a;
  void operator+(const A&, double);
  int main () {
    a + 1.0f;  // a.operator+(double(1.0f)), not ambiguous
  }

9/27/96  Microsoft compatibility: multi-token type specifiers in cast

Microsoft's MSVC++ allows functional-notation type conversions like
"unsigned int(x)", whereas the WP allows only a single-token type
specifier.  Multi-token cases are now accepted in Microsoft mode.
Also, the Microsoft extension types like __int16 are now accepted in
such casts.

9/27/96  Use of template template parameters could result in abort

Use of template template parameters (which are not yet implemented)
could result in an abort caused by an error recovery problem.  This
has been fixed.

9/26/96  Bug fixed in processing lint NOTREACHED comments

When a lint NOTREACHED comment was the last thing before the closing brace
of a non-top-level block of a function, the NOTREACHED comment was ignored.
A spurious warning complaining that a nonvoid function should return a
value is no longer issued on the following:

  int f(int n) {
    if (n) {
      return 1;
    } else {
      /*NOTREACHED*/
    }
  }

9/26/96  Name mangling for types/variables promoted out of functions

The name mangling for variables and types promoted out of functions
in IL lowering has been changed to make it possible to demangle them
and to permit implementation of extern inline.  The "__Lnn" piece of
such mangled names has been moved to between the local entity name
and the mangled name of the function, instead of at the end, and the
number in the "__Lnn" has been made relative to the function.
(These two changes have no ABI implications, since such names have been,
by definition, internal to a compilation.)  A local variable "j"
in function "f", whose mangled name was formerly something like
"j__f__Fv__L10", now has a mangled name like "j__L2__f__Fv".  The name
demangler has been updated to deal with the new form (it didn't handle
the old form at all).

9/25/96 Scope of an uncaught exception now conforms to the Working Paper

The Working Paper specifies that an exception is "uncaught" from the
time that the object to be thrown is completely evaluated until the time
that the initialization of the catch parameter is complete.  The front
end and runtime have been updated to conform to this definition when using
ABI versions 2.33 and newer.  See the entry below and the runtime Changes
file for more information.

9/25/96 Indication of point in catch clause where exception has been caught
        (IL CHANGE if EH partially lowered)

The point in a catch clause after the parameter has been copied, and
where therefore the exception can be said to be fully caught, is now
marked.  With full lowering of EH features, the point is marked by
a call to the new runtime routine __exception_caught.  With partial
lowering, the point is marked by a new enk_lowered_eh_construct/
leck_exception_caught expression node.

9/25/96 Internal error in IL lowering on binding static reference

When a static reference is bound to an expression that includes a
temporary whose lifetime is not extended to static lifetime, an
internal error was generated.  This bug was introduced in 2.32, though
the behavior before that wasn't correct either (it didn't destroy the
temporary, but on the other hand it didn't get an internal error).

  struct B {
    B(int i);
    ~B();
  };
  struct A {
    A(const B &rB);
    ~A();
  };
  extern const A &a2 = B(2);

9/25/96 Global qualifier on friend declaration inside namespace

When a global qualifier appeared on a friend function declaration and the
class in which it appeared was defined inside a namespace, there was a bug
in the management of sk_extern_routine symbols.  The bug, now fixed, could
result in an internal error -- for example:

  void f();
  namespace N {
    class A {
      friend void ::f();
    };
    void f() { }                  // Internal error is no longer produced
  }

9/25/96 Declaring a predeclared operator new/delete at function/block scope

An internal error used to occur when a function/block scope declaration
specified a predeclared operator new or delete:

  void f() {
    void *operator new(size_t);   // Internal error is no longer produced
  }

9/25/96 Diagnostic on unreferenced function parameters

A new error code, ec_unreferenced_function_param, has been added to report
unreferenced function parameters.  These cases used to be covered by
ec_declared_but_not_referenced, which is also used for other variables;
the new code was introduced to allow the warnings on unreferenced
parameters to be controlled separately.

9/24/96 Undefined inline virtual function

Except in cfront mode, an error is now issued if a virtual function is
declared inline but not defined:

  struct S {
    virtual inline void f();   // Now an error if not defined later in the
  };                           //   current translation unit.

There are three motivations for this change.  First, there was a bug in
failing to issue an error even when the undefined inline virtual function
was subsequently called.  Second, the C-generating back end was putting out
bad C code for the above example.  Third, the error is now required when
compiling with --extern_inline: simply being a virtual function counts as
being "used", and an inline function with external linkage must be defined
in every translation unit in which it is used.  Only a warning is put out
in cfront mode (because cfront itself issues no error), and the IL entry
is modified to produce consistent IL.

9/23/96 Support for "extern inline"

In C++ support for "extern inline" is now available.  This means
-- on nonmember function declarations "extern" and "inline" can appear
   together;
-- "inline" by itself on a nonmember function declaration implies external
   linkage (so that "inline static" must now be used to specify internal
   linkage); and
-- a member function, including an inline function, now takes the linkage
   of the class of which it is a member (which is usually external).

Because an extern inline function must be defined in every translation
unit in which it is used, the practical impact on programs is small:
there are a few diagnostic differences; static local variables are
shared across translation units; and (this part is not implemented yet)
the address of an extern inline function will be the same throughout the
program.  For example:

  class A {
    int f() {               // A::f is an "extern inline" function
      static int i = 0;     // with --extern_inline_allowed there is only
      return ++i;           //   one copy of local "i" in the program
    }
  };

The behavior is controlled by command-line options --extern_inline and
--no_extern_inline; DEFAULT_EXTERN_INLINE_ALLOWED can be set to determine
the default, and strict mode turns extern-inline support on while cfront
mode turns it off.

(9/26/96) IL lowering now promotes local static variables out of extern inline
functions and makes them external, so that all copies of the function
will use the same static variable.  If the static variable is initialized,
the initialization guard variable is also made external.  It has a
mangled name beginning with "__LSG__", followed by the mangled name of the
promoted local static variable.  The name demangler has been updated to deal
with these new mangled names.  The configuration flag LOWER_EXTERN_INLINE
controls the lowering of extern inline functions.

There is still an unimplemented part of extern inline support: if the
address of an extern inline function is taken, it should give the same address
in all compilation units.  But as of now, it gives the address of the
copy of the function in the current compilation unit.  This will be
addressed at some point, but at the moment we're not sure of the
right approach.

9/23/96 Use of typedef names in destructor calls

A typedef that refers to a class may now be used in an explicit destructor
call.  Previously, typedef names were only permitted in pseudo-destructor
calls.

  struct A { ~A(); };
  typedef A X;
  int main() {
    X* p;
    p->~X();  // Now permitted
  }

9/22/96 c_gen_be.c did not compile with CHECKING and STANDALONE_UTILITY_PROGRAM

Due to a change in 2.32, c_gen_be.c did not compile with CHECKING and
STANDALONE_UTILITY_PROGRAM both TRUE.  Now fixed.

9/22/96 Tiebreakers in overload resolution

A patch sent out on 2.31, for a fix made 2/9/96 (see below) for anachronisms
as tiebreakers in overload resolution, broke the tiebreaker test in
a different way.  Now fixed.

  struct X {
    void foo(int*) const;
    void foo(const int*);
  };
  void foo(X *pX, int *pi)
  {
    pX->foo(pi);  // Should be ambiguous; broken by patch on 2.31
  }

9/18/96 Redeclaration of library versions of operator new and delete

If the source program omits the exception specification when redeclaring a
version of operator new and delete, a warning (not an error) is now issued
(except in strict mode).  For example,

  #include "new.h"
  void *operator new(size_t) { ... }  // "throw(std::bad_alloc)" is missing:
                                      //   error with -A, warning otherwise

(This relaxation has been added to be easier on older C++ code, written
before exception handling support was available.)

9/18/96 Microsoft C compatibility: predeclaration of _alloca

In Microsoft C mode _alloca is now predeclared (i.e., a symbol and routine
entry are generated for it).

9/18/96 Overload resolution tiebreaker as applied to inherited conversion
        function

Overload resolution now correctly treats an inherited conversion function
as a member of the derived class when looking for tiebreakers on the
"this" parameter.

  struct A {
    A();
    operator const void* () const;
  };
  struct B : public A {
    B();
    operator void* ();
  };
  extern B b;
  void f(void) {
    int s;
    s = b ? 0 : 1;  // No longer ambiguous
  }

9/17/96 Microsoft compatibility: cases requiring __cdecl calling convention

In Microsoft-compatibility mode a routine that takes a variable number of
arguments (and in general any routine type declared with an ellipsis) now
gets the __cdecl calling convention; this is done even if it was explicitly
declared to get another calling convention.  In addition, main and the
predeclared global operator new and delete routines are assigned __cdecl
calling convention.

9/17/96 External symbols not assumed to have non-null addresses

In the presence or weak external symbols and similar linker magic,
external symbols might have zero addresses.  That might mean that
a test like the following could yield false:

  #pragma weak weak_symbol
  extern void weak_symbol();
  int main () {
    if (weak_symbol) {  // Could be false
    }
  }

Various calls of folding routines have been changed to first check for
symbols that might have zero addresses, so that folding can be suppressed
in such cases.

9/17/96 Internal error on invalid pseudo-destructor call

An internal error resulted from compiling the following invalid code.
This has been fixed.

  typedef int T;
  void f()
  {
    T::~T();
  }

9/17/96 Overload resolution: reference to non-const cannot be bound to result
        of promotion or standard conversion

Overload resolution now recognizes that once a promotion or standard
conversion is applied to an argument the result is an rvalue, and therefore
a reference to non-const cannot be bound to it.  (If the function had been
selected by overload resolution, an error was issued later.  Now, the
function is rejected by overload resolution, which lets a different
function be selected.)

  struct C {};
  struct D : public C {
    C &operator>>(bool &);
  };
  struct A {
    friend C &operator>>(C &, A *&);
  };
  void f() {
    A *pa = 0;
    D d;
    d >> pa;  // No longer gets an ambiguity error
  };

9/16/96 IL for pointer comparisons: avoid dropping cv-qualifiers

When pointers are compared, the cv-qualifiers of the types need not
match up.  In the past, the front end has dealt with such mismatches
by casting one operand to the type of the other.  Now, it casts
both to a common type that contains all the cv-qualifiers of both
operands.  For example:

  const int *p1;
  volatile int *p2;
  p1 == p2;  // was p1 == (const int *)p2
             // now (const volatile int *)p1 == (const volatile int *)p2

This distinction is mostly moot, but it does matter when near/far
pointers are supported: it's important that if a pointer-to-near and a
pointer-to-far are compared, they are compared as pointers-to-far.

9/16/96 Simplify porting of certain directory manipulation routines

The host_envir.c and host_envir.h files have been changed to make
is_absolute_file_name a function instead of a macro, and to use a new macro
named DIRECTORY_SEPARATOR.  These changes are intended to simplify porting of
the front end to systems with different file naming conventions.

9/14/96 Microsoft compatibility: ellipsis in old-style parameter list

In Microsoft C mode a warning is now issued (instead of an error) if an
ellipsis appears in an old-style parameter list declaration:

  void f(x, ...) int x; { }   /* Ellipsis is ignored in Microsoft C mode */

9/13/96 Microsoft compatibility: disambiguation

The Microsoft compiler incorrectly interprets a declaration such as the
following as an object declaration (i.e., "int()" is treated as an
initializer expression).  In Microsoft mode we now interpret declarations
such as this in the same way as the Microsoft compiler.

  int main() {
    int i(int());
  }

9/13/96 Microsoft compatibility: calling conventions allowed/ignored in more
        cases

In Microsoft mode, calling conventions applied to pointer and reference
types are now ignored, with a remark.  Formerly, an error was issued.

  int * __cdecl variable;
  void (* __cdecl ptr_to_func)(void);

9/13/96 Microsoft compatibility: extra #elses ignored

In Microsoft mode, a second #else in the skipped part of an #if is now
ignored, with a warning.

  #if 0
  #if 1
  int x;
  #else
  xxx
  #else  /* Gets warning instead of error. */
  yyy
  #endif
  #endif

9/13/96 Template instantiations that do not produce valid function types

If the names used in a template declaration change meaning between the
time at which a template is declared and the time at which an instantiation
is generated, an abort or internal error could occur.  A diagnostic
is now issued if an instantiation does not result in a valid function
declaration.  Eventually, the new template name binding rules will be
implemented, which will result in the original name being used even if
the name is redeclared after the template has been declared.

  struct x {};
  template <class T> x f (T); 
  int x;
  int i = f(1);

9/13/96 Microsoft compatibility: __STDC__ not defined

The Microsoft Visual C++ compiler does not define the preprocessor
variable __STDC__ when extensions are supported, so the front end has
been changed not to define __STDC__ in Microsoft mode.

9/13/96 Compilation speed problem with extremely large switch statements

In the compilation process for case labels of switch statements, the
front end can exhibit quadratic behavior, which makes for extremely slow
compilation of cases like

  switch (i) {
    case 1:
    case 2:
    case 3:
    ... etc.
    case 30000:
      break;
  }

This has been fixed for the usual case of mostly-ascending case labels.
The quadratic behavior remains for other cases, but since cases this
large tend to be machine-generated, the mostly-ascending optimization
probably deals with most real-world cases.

9/12/96 Microsoft compatibility: storage on friend function declaration

In Microsoft-compatibility mode a friend function declaration can now be
declared with a storage class ("static" or "extern").

9/12/96 Microsoft compatibility: empty enumerator list allowed in C mode

In Microsoft C mode an empty enumerator list is now permitted:

  enum E { };    // Okay in C++ or Microsoft C modes; error otherwise

9/12/96 Microsoft compatibility: support for __int8 and __int16 keywords

In Microsoft-compatibility mode __int8 is recognized as a keyword, with
semantics equivalent to char, as long as there are 8 bits in a char; and
__int16 is also recognized as long as there is a 16-bit integer to which
it can be mapped.

9/11/96 Internal error in get_pointer_offset eliminated

An internal error on the following was eliminated.  The problem involved
selecting a field from a nonreal class in a template instantiation.
There is still a remaining problem, which causes an undeserved error,
but the internal error is gone.

  template <class Key> struct node {
    Key key;
  };
  template <class Key> class set {
  public:
    struct dummy {
      struct node<Key> field;
    };
    static const int i2 = ((int)__INTADDR__(&(((dummy*)0)->field.key)));
  };
  int main( int argc, char * argv[] ) {
    set<int> s;
  }

9/11/96 IL CHANGE for Microsoft object-code compatibility

When MICROSOFT_EXTENSIONS_ALLOWED is TRUE, new field orig_type_kind is
maintained in a_class_type_supplement.  It records the tag kind with which
a class was first declared, in case a subsequent definition should use a
different tag kind.  For example:

  struct S;
  class S { ... };

The type kind recorded in the type entry for S is tk_class, but the
orig_type_kind is tk_struct.  This is needed because the original tag kind
is encoded in the mangled name that MSVC++ puts out.  (Note: this field is
not used by the EDG name mangler; it is provided for implementations that
need to put out Microsoft-ABI-compatible object code.)

9/10/96 Internal error from incorrectly constructed overload set

When a using-directive lookup results in an ambiguity, and the set of
names found includes both a set of overloaded function and a non-function,
the resulting overload set was sometimes constructed improperly.  This
could cause an internal error.  For the error to occur, the namespace
projection symbol must have been created by a previous lookup in which
not all of the names found were functions.  In addition, the first
function added to the lookup set must itself have been an overload set.

9/9/96  Spurious error when deducing array bounds

A bug has been fixed that could cause a spurious error when deducing
a nontype template parameter from an array bound.  This bug would
probably only appear on systems on which pointers are larger than
integers.

9/6/96  C++-generating back end: nonmember using-declarations

The C++-generating back end now puts out code for nonmember
using-declarations.

9/6/96  IL CHANGE: Representation for using-declarations and using-directives

Data structures a_using_directive and a_class_member_using_declaration have
been eliminated.  In their place a_using_decl has been added; it is used to
represent using-directives, class member using-declarations, and nonmember
using-declarations.  With this change, IL entries are now produced for
nonmember using-declarations.

The using_decls field in the scope entry for a class points to a linked list
of class member using-declarations (the class_member_using_decls pointer in
the class type supplement is no longer used).  In file, namespace, function,
and block scopes it points to a linked list that can contain both
using-directives and nonmember using-declarations.

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, source-sequence entries for
nonmember using-declarations are now put out; they were already issued for
class member using-declarations and using-directives.  In addition, when a
using-declaration (either the member or nonmember case) refers to an
overload set, only one using-decl entry in the set is pointed to by an
iek_using_decl source-sequence entry; the rest are on a linked list (see
next_in_overload_set in a_using_decl).

9/4/96  Compilation error eliminated

A compilation syntax error could result in class_decl.c when both CHECKING
and RECORD_TEMPLATES_IN_IL were FALSE.  Now fixed.

9/4/96  Spurious assertion failure -- globally qualified name on friend decl

An internal error is no longer triggered by the following:

  template <class T> void f(T);
  class B {
    friend void ::f(int);
  };

9/4/96  Ambiguous undefined namespace projection symbol causes internal error

An internal error may result when an ambiguous namespace projection symbol
refers to an undefined symbol entry that is created when an undefined
name has been referenced.  This has been fixed.

9/3/96  Default for for-init semantics in Microsoft mode

Because the Microsoft MSVC++ compiler does not yet support the new for-init
scoping semantics, --old_for_init should be the default in Microsoft mode.
MICROSOFT_DEFAULT_USE_NONSTANDARD_FOR_INIT_SCOPE has been added to control
that.

8/29/96 Integral promotion of wchar_t when wchar_t is already a promoted type

When wchar_t was configured as a type that is already a promoted integral
type (e.g., int), the code to do integral promotion left it alone, when
it should have promoted it to the corresponding plain integral type.
As a consequence, cases like the following were falsely diagnosed as
ambiguous:

  void foo(int);
  void foo(long);
  void bar()
  {
    foo(L'a');
  }

8/20/96 C++-generating back end: Abort on cast to typedef pointer type

The C++-generating back end generated an internal error when trying
to process a cast of a pointer to class to a typedef type in a context
where a cast to reference type might be appropriate.  Now fixed.

Also fixed: generating a cast from a pointer to class to another
pointer to class called find_base_class_of, which attempted to
instantiate the derived class.  This was disastrous, happening as
it did during the C++-generating back end.  gen_full_cast has been
changed to use find_direct_base_class_of, which does not attempt
the instantiation.

8/19/96 Internal error while processing deferred instantiations

A bug in the management of symbol lists used for processing of deferred
instantiations could result in an internal error.  This has been fixed.

8/18/96 Truncation/sign extension on integer cast to pointer and back

In some obscure cases where an integral constant is cast to a pointer
type and then back to an integral type, the integral value in the constant
was not properly truncated and/or sign-extended.  This only happened
in versions configured such that some integral type is larger than the
pointer type.  An example that shows the problem on versions that support
long long with a size bigger than "void *" is (int)(void *)-1ll.

8/18/96 Warning on too many arguments in Microsoft C mode

In Microsoft C mode, having too many arguments on a call of a prototyped
function in C mode is now a warning instead of an error.

  void f(int);
  int main () {
    f(1, 2);  /* Warning */
  }

8/16/96 Static data member declared in unnamed class

Except in cfront-compatibility mode, an error is now issued if a static
data member is declared in an unnamed class (or a class nested within an
unnamed class), as required by WP 9.4.2 [class.static.data].

8/16/96 Qualifier on void function return type

In strict ANSI C mode an error (or warning with -a) is issued when a
function definition declares a const or volatile void return type.

8/16/96 Option for K&R usual arithmetic conversion rules on "long"

When DEFAULT_LONG_PRESERVING_RULES is TRUE, or when --long_preserving_rules
is specified, the front end will now use the usual arithmetic conversion
rules specified in K&R I, Appendix A, 6.6, with respect to "long".
These are not the rules used by the pcc compiler.

The significant difference is in the handling of "long op unsigned int" when
int and long are the same size.  The ANSI/ISO/pcc rules say the result is
unsigned long, but K&R I says the result is long (unsigned long did not
exist in K&R I).

  int main() {
    if (0 > (unsigned) 0xffffffff - (long) 1) {
      printf("K&R semantics\n");
    } else {
      printf("ANSI/ISO/pcc semantics\n");
    }
  }

8/15/96 Microsoft compatibility: delete size anachronism allowed

The anachronism of specifying a size on a delete operation is now allowed
in Microsoft mode.

  int main () {
    int *p;
    delete [5] p;
  }

8/15/96 Implicit conversion on delete

An implicit conversion from class to pointer is now allowed on a delete
operator.

  struct A {
    operator void *();
  };
  int main () {
    A a;
    delete a;
  }

8/15/96 Spurious errors on declarations of operator new and delete

In part because no exception specifications are put out on the predeclared
versions of operator new and delete, spurious errors used to be issued on
the following; they have now been eliminated.

  typedef unsigned int size_t;
  namespace std { class bad_alloc; }
  void *operator new(size_t) throw(std::bad_alloc);
  void operator delete(void *) throw();

Suppressing the spurious errors was straightforward, but a full solution
will be more complicated.  For example, we may have to invent a way to add
an exception specification to the predeclared version of operator new that
doesn't require predeclaring std and bad_alloc.

8/14/96 Determining when a class is a aggregate class

WP 8.5.1 [dcl.init.aggr] used to say a class was not considered an
aggregate if it had any nonpublic members; it has been corrected to limit
that to nonpublic nonstatic data members.  The is_class_aggregate flag in
the class symbol supplement is now set according to the new wording.

8/14/96 Indentation on -H output

The -H output (showing files included) is now indented to show the
inclusion depth.

8/14/96 C-generating back end: __cgi initialization routine not emitted if
        not needed

The C-generating back end no longer emits the __cgi initialization routine
if it is not needed.  The __cgi routine is needed only for obscure things
like initialization code for file-scope unions, and it is used only when
generating K&R C.

8/13/96 "K" to indicate extern "C" in mangled name for function type

When c_and_cpp_function_types_are_distinct, function types that have
associated extern "C" linkage now have a "K" following the "F" in the
mangled name for the function type.  Since functions with extern "C"
linkage do not get mangled names, this is visible primarily in
parameters with pointer-to-function type.

8/13/96 Name linkage and enum types

Enum types are now assigned a name linkage using the same logic heretofore
used for classes.  For example, an enum type declared at file-scope now
has C++ name linkage.

8/13/96 Typedef name as name "for linkage purposes" of tagless enum

This feature was implemented in preparing version 2.32 (see 3/21/96 entry)
and then broken before 2.32 was released (an unintended side effect of a
subsequent change -- see 6/12/96 entry).  It now works again.

8/12/96 Functional-notation conversion with () for class with trivial
        constructor

A conversion like "A()", where A is a non-POD class with a trivial
constructor (i.e., it has a generated constructor according to the WP,
but the constructor does nothing, so the front end does not actually
generate it), now leaves the temporary uninitialized (which is the
net effect of a conceptual call of the trivial constructor).  Formerly,
the temporary was zero-initialized.

8/12/96 new with () initializer

A "new" operator with an initializer of (), for a nonclass or POD class
object, now zero-initializes the object created.

8/12/96 Linkage specification as "part of the type"

The new Working Paper rules regarding how a linkage specification is
applied to type declarations (function parameter types, typedefs, members)
have been implemented (see WP 7.5 [dcl.link]).  We intend "routine linkage
specification" to be a code word for "calling convention"; when extern
"XXX" involves a distinct calling convention, these changes are especially
relevant.  The new rules in the Working Paper in effect permit extern "C"
and extern "C++" functions to have different calling conventions.

Among other things, this means that functions can now be distinguished for
purposes of overloading based on the routine linkages associated with their
parameter types:

  typedef void (*PF)();             // Pointer to an extern "C++" function
  extern "C" typedef void (*PCF)(); // Pointer to an extern "C" function
  void f(PF);
  void f(PCF);

Previously, the declaration of f(PCF) was treated as a redeclaration of
f(PF).  Now, the Working Paper says they are two distinct functions.  To
produce this behavior set DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT (in
targ_def.h).  This flag not only affects language issues (overloading,
implicit conversions), but it also has ABI implications, since it controls
whether two function types differing only in their linkage specification
have distinct representations in a mangled name.  In the above example the
name mangling of "void f(PCF)" is distinct from that of "void f(PF)" when
the flag is TRUE, but they will be the same when it is FALSE.

However, getting strict conformance to the Working Paper means that the
possibility of full cfront compatibility is slightly compromised.  Set
DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT to FALSE if compatibility with
cfront is more critical than strict conformance to the standard.  On the
hand, the cfront-compatibility problems can be reduced substantially by
enabling an extension to allow implicit type conversion between pointer to
extern "C" function and pointer to extern "C++" function: setting
IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE (in lang_feat.h) eases
the following incompatibility:

  extern "C" void f();              // f's type has extern "C" linkage
  void (*pf)()                      // pf points to an extern "C++" function
               = &f;                // error under the new rules

With the extension enabled, the implicit conversion is permitted (except in
strict mode) and no error is issued here.  It becomes the default
behavior when DEFAULT_IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_ALLOWED
is configured to TRUE, and it can be controlled from the command line by
--[no_]implicit_extern_c_type_conversion.

Note: IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE should not be
configured to TRUE if C and C++ functions actually do have different calling
conventions -- and unless DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT is
TRUE, it is pointless to do so.

For implementations that support additional linkage specifications that
apply to function types, routine_linkages_are_compatible and
routine_linkages_are_identical should be customized to deal with the
implementation-defined linkage kinds.

8/9/96  Microsoft compatibility: __declspec on constructor declarations

In Microsoft compatibility mode __declspec(...) and __inline are now
accepted on constructor declarations.

8/7/96  Configuration flags for building DOS and Windows versions

Previously, the __MSDOS__ configuration flag was required to be set
not only when building under MS-DOS, but also when building the
front end on Windows NT and Windows 95.  The front end has been
changed so that __MSDOS__ should only be set when building under
MS-DOS.  A new configuration flag named __MICROSOFT_OS__ is automatically
set when either __MSDOS__ or __WIN32__ is set.  This new flag is used
to conditionally compile code that is common to both MS-DOS and
WIN32 environments.

8/7/96  mem_manage.c did not compile in certain configurations

When building a standalone utility program, mem_manage.c would
not compile if USE_MMAP_FOR_MEMORY_REGIONS was TRUE.  This
has been fixed.

8/7/96  Uninitialized objects of const-qualified class type

The Working Paper has recently clarified some rules on when an object of
class type can be "default-initialized" and when an explicit initializer is
required.  These rules apply to variable declarations, new expressions, and
mem-initializers in a constructor definition.  The front end has been
updated to conform with the new rules.  For example:

  class A { int i; virtual void f(); };
  const A x;                             // now an error

Even though A has a nontrivial implicitly-declared default constructor, the
declaration of x is ill-formed -- only a user-declared default constructor
can be called when the initializer is missing on a const variable
declaration.  Similarly with new expressions:

  ... new const A;                       // now an error
  ... new const A();                     // okay: A::A() is called

The first case gets an error because default initialization can only be
done by a user-declared default constructor.  When the "()" syntax is used,
an implicitly-declared default constructor can also be called.

A related change has to do with trivial default constructors.  Because they
are never called, the front end did not generate them.  But that meant some
errors went improperly diagnosed or even undiagnosed.  For example:

  class B { const int i; };
  class D : public B {
    D() { }                              // now an error
  };

The error on the declaration of D::D() is that the default constructor
B::B() cannot be generated because B has a const member.  (We now issue
this error as though B::B() were really being called.  However, trivial
default constructors are so designated because their execution has no
effect, and so no IL is generated to declare, define, or invoke B::B():
trivial default constructors still do not appear in the IL.)

We have thus relaxed diagnostics on the class definition itself:

  class X { const int i; };             // only a warning
  X x;                                  // error on defining X::X()

The warning is that X declares a const member but no constructor to
initialize it.  The error comes when the program tries to use X in a way
that requires the definition of its default constructor.

8/5/96  Mismatch between size and dimension of array for vtable for type_info

The virtual function table generated by IL lowering for type_info had,
in some cases, an array type whose size in bytes did not match the product
of the element size and the number of elements.  Now fixed.

8/1/96  Handling of #pragma directives when creating preprocessed output

Two problems have been corrected in the handling of #pragma directives
when generating preprocessed output:

1. The "expand_macros" and "processing_C_code" flags from the pragma
   description are now respected even when only generating preprocessed
   output.

2. When creating preprocessed output and using the --no_preproc_only
   option pragmas are now included in the preprocessed output.  Formerly,
   they were incorrectly omitted from the output.

8/1/96  Cfront mode disambiguation problem with parameter whose type is
        a function type

In cfront mode, certain declarations that should be considered to be
functions are treated as objects (f2 in the example below).  However,
too many cases were being given this special treatment in cfront mode.
In particular, a function type (f3 in the example below) was incorrectly
being treated as an ill-formed object initializer.  This has been fixed.

  int f;
  extern "C" int f1(void (*f)(void));  // accepted
  extern "C" int f2(int (f)); // object in cfront mode, function in default
  extern "C" int f3(void (f)(void)); // incorrectly considered an object in
                                     // cfront mode

7/31/96 Default initialization of reference member

An error is now issued on a mem-initializer for a reference member when
the expression-list is empty (i.e., which is otherwise the way to
specify default-initialization) -- e.g.,

  struct S {
    int & ri;
    S() : ri() { }      // Error is now issued
  };

7/31/96 Ignoring carriage returns in continuation lines

When IGNORE_CARRIAGE_RETURN_IN_SOURCE is TRUE but
READ_SOURCE_IN_BINARY_MODE_FOR_MSDOS is FALSE, carriage returns were
not ignored in continuation lines.  More precisely, the routine that
reads a source line has two loops, a fast one used if the line contains
no unusual characters, and a slower and more general one entered on
the first appearance of some unusual character (backslash for line
continuation, trigraph, etc.); the code to deal with carriage
return in the second loop is conditional on a #if that tested
the wrong condition.

7/30/96 Some cached tokens not freed for explicit specializations

The declaration token cache and the parameter token cache were
not being freed for new-style explicit specializations.  This
has been fixed.

7/30/96 Incorrect linkage test for template declarations

Template declarations were incorrectly required to have C++ linkage,
or to be declared in an unnamed namespace.  This disallowed the
use of other linkage kinds (in implementations that support them) and
also disallowed internal linkage that results from use of the -tlocal
option.  Now all linkage kinds, except for "C", are permitted.

7/29/96 Making a member function template instance a friend

Version 2.32 did not support friend declarations that refer to member
function template instances.  This occurred because the syntax to be
used was not clear in the Working Paper.  This was clarified during
the July meeting of X3J16/WG21.  The syntax illustrated by example #1
is the form to be used.  The syntax illustrated by example #2 is not
permitted. 

  class A {
    template <class T> void f(T);
  };
  class B {
    friend void A::f(int);  // #1, now permitted
    template <> friend void A::f(int);  // #2, not permitted
  };

7/29/96 Internal error caused by error recovery following invalid template
        argument list

An internal error (in map_token_numbers_to_cache_pointers) could result
when a template argument list follows a type, for which a template
argument list is not permitted, in a member function template declaration
in a class template.

  template <class T> struct A {
    template <class U> A(U<1);  // U cannot have a template argument list
  };
  void f() {}

7/26/96 Internal error on invalid template specialization

The declaration of an invalid template specialization in a scope in
which such a declaration is not permitted could result in an
assertion failure in class_template_declaration.  This has been fixed.

  template <class T> struct A {};
  namespace N {
    template <class T> struct A<int>;
  }

7/26/96 Error recovery on linkage specification

A null-pointer failure no longer results from an ill-formed linkage
specification in which the closing '"' is omitted -- for example:

  extern "C int printf(char *, ...);

7/26/96 Integral promotion on enums when enums smaller than int

Version 2.32 introduced a bug in the processing of integral promotion
of enums when enum_types_can_be_smaller_than_int is TRUE.  A short
enum was promoted to a short non-enum int, instead of the correct
int.  Now fixed.

7/24/96 Source-sequence entry for nonstandard anonymous union

In Microsoft C mode a source-sequence entry was sometimes not being
put out for a nonstandard anonymous struct declaration.  Now fixed.

  // -m --microsoft
  struct S {
    int i;
  };
  struct S2 {
    struct S;      // Source sequence entry is now put out for S (which
  };               //   is a "nonstandard anonymous union")
  ... S2.i ...     // Equivalent to S2.<unnamed-field>.i

(This bug appeared only when both ALLOW_NONSTANDARD_ANONYMOUS_UNIONS and
GENERATE_SOURCE_SEQUENCE_LISTS were configured to TRUE.)

7/19/96 Abort on invalid redeclaration

A bug has been fixed that resulted in an internal error on the following
program (C++ mode only):

  void f(int);
  void f(char);
  extern int f;    // Used to abort determining linkage for variable f

7/18/96 Precompiled header creation

Precompiled headers were not being created when the last declaration
preceding the header-stop point was a namespace declaration, a using
directive, or a using declaration.  Now fixed.

7/17/96 C++-generating back end: bug in is_autonomous_decl

The code in is_autonomous_decl in cp_gen_be.c was missing a test to
exclude enum types before using a field specific to classes.  Depending
on layout, this could cause big problems.

7/17/96 copy_node for rethrow node

copy_node now deals correctly with an enk_throw node with throw_info == NULL.

7/17/96 EXIT_ON_INTERNAL_ERROR

A new configuration flag EXIT_ON_INTERNAL_ERROR can be set to request
an exit() call instead of an abort() call if an internal error occurs.

7/17/96 C-generating back end: output of "const void"

In an attempt to avoid the "const" when putting out

  extern const void x;

(which some C compilers don't like), the C-generating back end did
an overly broad transformation, changing "const void" to "void" in
all cases, which also affected things of type "const void *".  Now,
the transformation is done only on the type of a variable.

7/17/96 Size of empty class when TARG_MINIMUM_STRUCT_ALIGNMENT > 1

A bug has been fixed in computing the size of an (e.g., empty) class when
TARG_MINIMUM_STRUCT_ALIGNMENT is configured to be greater than 1 -- the
size of a class will be adjusted to be no less than its alignment.

7/16/96 IL lowering: missing cast to adjust cv-qualifiers when passing
        argument via a copy constructor to parameter of cv-qualified class type

The code generated by IL lowering to pass an argument via a copy constructor
to a parameter of cv-qualified class type was missing a cast to adjust
the cv-qualifiers on the pointer.  A routine with a type like

  void f(const A);

where A is a class having a copy constructor is rewritten by the front end
to

  void f(A);

because of a C++ language rule (see the configuration switch
DEFAULT_REMOVE_QUALIFIERS_FROM_PARAM_TYPES).  Then, IL lowering adds
a level of indirection, turning the function into

  void f(const A*);

and restoring the cv-qualifier on the pointer.  The arguments generated
by the front end for such a parameter have type "A *", and need to be
cast to "const A*".  Now, they are.  This difference is probably not
significant except to code generators that verify that all type changes
are done explicitly via a cast.

7/16/96 IL lowering should clear modified_within_try_block on return
        optimization variable

When IL lowering performs the return variable optimization, it should
clear modified_within_try_block on the return variable when it clears
the referenced flag.  Without that clearing, when exceptions are
enabled the return variable might be passed as an argument to
__suppress_optim_on_vars_in_try, but the referenced flag is FALSE.
The modified_within_try_block flag is now cleared when appropriate.

7/16/96 Failure to instantiate template for parameter type early enough

The front end failed to instantiate a parameter of template type
early enough when calling a function that was declared but not defined
previously.  As a consequence, in this example a class was passed in
the call, instead of a pointer to the class.

  class B {};
  template <class T> struct A {
    A(T*);
    virtual ~A();   
  };
  void f(A<B>);
  void g() {
    B* b = new B;
    f(b);  // Problem here
  }
  void f(A<B>) {}
  template <class T> A<T>::A(T*) {}
  template <class T> A<T>::~A() {}

7/16/96 const qualifier on "this" parameter type, with IL lowering

When IL lowering generates a_param_type entry for the "this" parameter,
it now puts const in the qualifiers field if appropriate.  When the
C-generating back end is being used, this means the const qualification
on the generated C for declarations of member functions matches that on
the definitions.  The code put out was, strictly speaking, valid ANSI/ISO
C, but some compilers weren't happy with it, and the const difference
was unintended and unnecessary.

Also, a related bug has been fixed: when "restrict" was specified on a
function that has an assignment to "this", the restrict qualifier on
the "this" parameter was inadvertently dropped in the process of dropping
the const qualifier.

7/16/96 Internal error during deferred access checks of namespace members

An internal error would occur when an inaccessible class member of a class
defined in a namespace was defined outside of the namespace.  This has
been fixed.

  namespace X {
    class A {
      class B { B(); };
    };
  }
  X::A::B::B() {}  // Internal error on this declaration

7/15/96 Missing #ifs when PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE is FALSE

lower_init.c was missing some #ifs, with the consequence that the file did
not compile when PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE is FALSE.

7/15/96 Default ANSI/ISO C output when front end compiled by ANSI/ISO C
        compiler

When the C-generating back end is being used, and the front end is being
compiled by an ANSI/ISO C compiler, ANSI/ISO C code is now generated by
default (the default for C_GEN_BE_GENERATES_ANSI_C is now TRUE if
USING_ISO_C is TRUE).

7/14/96 Template deduction from incomplete-typed lvalues

Template argument deduction has incorrectly assumed that if an argument
has an incomplete type, nothing can be deduced.  This is not true when the
parameter type is a reference or in some cases when array --> pointer decay
applies.

  // Case 1
  struct A;
  template <class T> void f(T&);
  void ff(A &a) { f(a); }

  // Case 2.  This case valid only in cfront mode.
  struct A;
  template <class T> void f(T *);
  void ff(A (&a)[]) { f(a); }

7/3/96  Nonstandard anonymous unions/structs: use of named struct

The code for nonstandard anonymous unions/structs (enabled by
ALLOW_NONSTANDARD_ANONYMOUS_UNIONS, e.g., in Microsoft mode) dealt
incorrectly with cases that used a named struct in C mode:

  struct S {
    int i;
  };
  struct S2 {
    struct S;  /* Nonstandard anonymous struct referenced by name. */
  };
  void f(void) {
    struct S s;
    struct S2 s2;
    s.i = 0;
    s2.i = 0;
 }

7/3/96  Microsoft compatibility: size of struct containing just empty array

In Microsoft C mode, the size of a struct containing only an empty array
is set to sizeof(int); that's what the Microsoft compiler seems to do.
However, we accidentally used the size of the host int, not the target int.
Now fixed.

7/2/96  Easier configuration for using host long long for integers

The configuration process for using the host compiler long long as the
internal representation for integers has been made easier.  Thanks
to new macros and #ifndefs, one can enable "long long" and use the
host long long to represent it as follows (for the typical case):

#define LONG_LONG_ALLOWED 1
#define INTEGER_VALUE_REPR_IS_A_HOST_INTEGER 1
#define TYPE_FOR_AN_INTEGER_VALUE unsigned long long
#define TYPE_FOR_A_SIGNED_INTEGER_VALUE long long
#define AN_INTEGER_VALUE_IS_LARGER_THAN_HOST_LONG 1
#define PRINTF_FORMAT_FOR_SIGNED_INTEGER_VALUE   "%lld"
#define PRINTF_FORMAT_FOR_UNSIGNED_INTEGER_VALUE "%llu"
#define PRINTF_FORMAT_FOR_HEX_INTEGER_VALUE      "%llx"
#define MAX_INTEGER_VALUE 9223372036854775807LL
#define MIN_INTEGER_VALUE (-MAX_INTEGER_VALUE-1)
#define MAX_UNSIGNED_INTEGER_VALUE 18446744073709551615ULL

HOST_ALIGNMENT_REQUIRED may also have to be changed (e.g., to 8) if the
alignment for long long is longer than the default.

7/1/96  Microsoft compatibility: incomplete arrays in unions

In Microsoft mode, any member of a union can now be an incomplete array,
and not just the last member.  In non-Microsoft mode, the extension that
allows an incomplete array as the last member of a union has been
removed (it was supposed to apply only to structs/classes).

7/1/96  Microsoft compatibility: [0] in C mode

In Microsoft mode, [0] is allowed as an alternative to the usual [] as
part of the extension that allows a member that is an incomplete array
as the last member of a struct.  The [0] syntax was previously allowed
only in C++ mode; now it is also allowed in C mode.

7/1/96  Microsoft compatibility: void/scalar as operands of "?"

In Microsoft mode, the "?" operator now allows a scalar and a void operand
as the second and third operand.  A warning is issued.

  void f0();
  void f(int i) {
    i ? i : f0();  // Accepted, with a warning
  }

7/1/96  Microsoft compatibility: pointer conversions

In Microsoft C mode, conversions between pointers to different (non-pointer)
types are now allowed, with a warning.

  void f(int *);
  int main () {
    f((float *)0);  /* Okay, with a warning. */
    return 0;
  }

6/30/96 Microsoft compatibility: prototype scopes in C mode

In Microsoft C mode, tags declared in prototype scopes are now entered
in the nearest enclosing file/function/block scope, as in C++.

  void f(struct S *);  /* S entered in global scope. */

This doesn't apply when the tag is defined in the prototype scope.

-------------------------------------------------------------------------------
Version 2.32, June 28, 1996

6/26/96 IL version number changed to 2.24

6/26/96 Non-alternate IL file format address remapping

In the so-called "non-alternate" IL file format, a walk through a
memory region is done after reading it in unless the memory region
is at the same address it had when written out.  However, when
reading a function scope memory region, this optimization should be
done only if the file scope memory region likewise did not move,
and that part of the test was missing.  As a consequence, in some
cases all the pointers to the file scope memory region from a
function scope were not remapped, which would have disastrous
consequences.

6/25/95 Internal error in pcc mode on extern decl of self within function

A bug introduced in version 2.31 produced an assertion failure in pcc mode
when an extern declaration of a function appears within the function
itself.  Now fixed.  Here's an example:

  void f() {
    void f();           // pcc mode internal error no longer occurs
  }

6/20/96 Pointer-to-member-function using typedef

An error is now issued for declaring a pointer-to-member-function using a
typedef for the member type (since the typedef has no implicit-this-param
type).  Here's an example:

  typedef void FC(void);
  struct S;
  FC S::* pmf;             // Error in now issued

This fixes an abort that occurred when attempting to call a function via
the pointer-to-member object.  This is a temporary fix -- eventually this
usage will be supported.

6/19/96 Object lifetime for constructor default arguments evaluated during
        subobject initialization

In ctor-initializer lists and aggregate initializers, it would sometimes
happen that an object lifetime was not being created for a temporary
produced in the evaluation of a default argument on a constructor for a
subobject.  This resulted in an abort in IL lowering.  It is now fixed.
Here's an example:

  struct C {
    C(int);
    ~C();
    operator int();
  };
  struct A {
    A(int = C(1));
    ~A();
  };
  struct B {
    A a[10];
    B(const B&) {}    // Calls A::A() for each element of a -- during
  };                  //   evaluation of the default argument, C::~C() is
                      //   now associated with the proper object lifetime

6/19/96 Determination of which copy constructor was elided for strict-mode
        check now considers whether copy constructor can copy rvalue

When a copy constructor is elided, the WP requires that the copy constructor
that is not used be callable anyway.  This check is done only in strict
mode.  The check has been improved to consider whether a given copy
constructor can copy an rvalue when determining which copy constructor
would have been called.

  struct B {
      B(B&);
      B(const B&);
      B(int);
  };
  int f(B);
  int i = f(B(1));  // No error in strict mode -- B(B&) not selected

6/18/96 Conversions for direct reference binding

When binding a reference, using a conversion function to produce an lvalue
to which the reference can be bound directly is preferable to using
other conversions to initialize a temporary to which the reference is bound
(WP [dcl.init.ref]).  The conversions for direct reference binding are now
given preference.

  struct A {};
  struct B {
    operator A&();
    operator A();
  } b;
  const A &r = b;  // No longer ambiguous: operator A& used

6/18/96 Bug in make_integer_value_mask macro

When INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is FALSE and the host long long
is used to represent target integers, the make_integer_value_mask macro
did not produce the right bit masks.  Now fixed.

6/15/96 Duplicate class-member using-declarations

The restriction on duplicate class-member using-declarations has been
relaxed, pending further clarification in the WP of cases involving
aliasing and virtual base classes.  This means a strict-mode warning is
issued on this sort of case:

  struct B { void f(); };
  struct D : public B {
    using B::f;
    using B::f;           // No longer an error -- warning in strict mode
  };

But it also means this sort of case is handled in a more reasonable way:

  struct V { void f(); };
  struct B1 : virtual public V { };
  struct B2 : virtual public V { };
  struct D : public B1, public B2 {
    using B1::f();
    using B2::f();       // No longer an error -- warning in strict mode
  };

And also this (taken from a test suite):

  struct A { void f(); };
  struct B : public A { };
  struct D : public B {
    using A::f;
    using B::f;          // No longer an error -- warning in strict mode
  };

We also issue an new (unmandated) error when two using-declarations apply
different access specifiers to the same base class member:

  struct A { void f(); };
  struct B : public A { };
  struct D : public B {
    using A::f;          // Makes A::f public in D
  private:
    using B::f;          // Error -- makes A::f private in D
  };

6/14/96 Type decay on conversion functions that return reference to array
        or function

Type decay (array --> pointer or function --> pointer) is now considered
when looking at conversion functions that return a reference.

  typedef int T[10];
  struct A {
    operator T&();
  };
  A a;
  int *const &t = a;  // Now accepted

6/13/96 Conflict between using-declaration and member function declaration

We no longer issue an error when a base-class member function brought in
to a derived class by a using-declaration has the same type as a member
function declared directly in the derived class.  (It now appears that WP
7.3.3 para 13 has a bug: as currently written it applies only to virtual
functions, but it was intended to apply to member functions in general.)
Here's an example:

  struct B {
    void f();
    void g();
  };
  struct D {
    void f();
    using B::f;            // Error is no longer issued
    using B::g;
    void g();              // Error is no longer issued
  };

IL CHANGE: When the using-declaration appears first and is then hidden, as
with the declarations of D::g, the associated IL entry is flagged -- see
the new field "hidden" in a_class_member_using_decl.

6/12/96 Diagnostic on member redeclaration with different access

Reflecting a recent Working Paper change, we now issue a discretionary
error instead of a warning when a member redeclaration is subject to
different access than the original declaration:

  struct S {
    struct N;
  private:
    struct N { ... };     // Error (but still a warning in cfront mode)
  };

6/12/96 Assigning a "name for linkage purposes" to a type

Except in cfront-compatibility mode, the source_corresp.name field of an
unnamed type that is defined in a typedef declaration is no longer filled
in with the typedef name if the declaration appears inside a function:

  void f() {
    typedef struct { ... } S;     // unnamed struct has no linkage and so
  }                               //   gets no "name for linkage purposes"

6/11/96 IL lowering: integral promotions on bool rewrites

When IL lowering rewrites a bool in a context that requires an int in C,
it now adds the proper integral promotions on the operand.

  main () {
    short i= 0;
    if (i) {}  // ((int)i) != 0
    bool b;
    if (!b) {} // !((int)b)
  }

6/10/96 Internal error while generating operator= when base class operator=
        returns value via copy constructor

An internal error, that came up on generation of the operator= function
for a derived class when the base class has an operator= that returns a
class via a copy constructor, has been fixed.

  struct A {
    A(const A&);
    A();
    ~A();
    A operator=(const A&);
  };
  struct B : public A {
    B();
    ~B();
  };
  int main () {
    B b;
    b = b;
  }

6/10/96 More characters used in symbol table hash function

The symbol table hash function to date has used the first character,
last character, and middle three characters of an identifier to generate
the hash for symbol table lookup.  This caused spectacularly bad performance
for generated programs with identifiers like "X000000001", "X000000002",
etc.  The hash function now uses the first three, last three, and middle
three characters.

6/10/96 Microsoft compatibility -- field of type array-of-unknown-size

In Microsoft compatibility mode, the only field of a struct may be of type
array-of-unknown-size, e.g.,

  struct S {
    int a[];       // Accepted in Microsoft compatibility mode (C or C++)
  };

(Previously in Microsoft compatibility mode, the final field of a struct
was permitted to be an array of unknown size as long as it was not the
*only* field.)

Moreover, in the example above the Microsoft C++ compiler determines that
sizeof(S) == 1, whereas its C compiler (apparently) assumes sizeof(S) ==
sizeof(int).  We have also attempted to emulate this mysterious behavior.

6/7/96  IL CHANGE: ck_cast removed, tpck_cast/tpck_sizeof/tpck_alignof added

The ck_cast variant of the IL a_constant entry has been removed.  It was
not being used; we anticipated using it in a particular way, and decided
against it.  In its place, we added a tpck_cast variant under the
ck_template_param variant of a_constant.  We also added variants
tpck_sizeof and tpck_alignof.  These are used to represent yet more
instances of constants whose values are unknown because they are based
on template parameters.  In general, these are front-end-only constants,
so back ends will not have to be changed to accommodate them.

Since these constants appear in the types of function templates, they
also appear in mangled names for templates.  The new operator encodings
"cs", "sz", and "af" have been added to represent cast, sizeof, and
__ALIGNOF__.  (See 5/10/96 entry on new name mangling for templates.)

6/4/96  definition_needed flag for routines

When MAINTAIN_NEEDED_FLAGS is enabled, a definition_needed flag is now
maintained for routines.  (Previously, there was one for classes, but
not for routines.)  It differentiates the cases where a routine is
needed only as a declaration from those where the definition is also
needed.  If you consult the "needed" flag in your back end, you must
also consult this new flag.  This change fixes a bug in the following:

  struct S
  {
  	~S(){}
  };
  void foo() throw(S);

Before this fix, the typeinfo variable for struct S, though marked
as unneeded, had an initial value that includes a pointer to S::~S,
but the definition of the destructor was removed.  This produced
an inconsistency for back ends that do not consult the "needed" flag --
there is a pointer to a static function, but the function has no
definition.

6/1/96  IL CHANGE: destruction of aggregate members on exceptions

Arrays and aggregate classes can be initialized piecewise using the "{}"
form of initialization.  When that is done, if an exception is thrown
while the aggregate is partially constructed, the members or array elements
already constructed must be destroyed.  This is now done.  The new
flag destruction_is_for_partially_constructed_aggregate is set in
dynamic initialization entries that describe partial initializations
that must be undone if an exception is thrown before the complete variable
initialization is completed.

Note that for arrays this problem was only present when some members
are initialized individually, not when the entire array is given
default initialization.

More significantly, array initialization/destruction in the IL can now
be summarized with the phrase "initialize elements, destroy arrays".
That is, whether or not the array is initialized piecewise, or gets
default initialization, or some combination of the two, the destruction
of the array is scheduled as a single operation (which loops calling the
destructor).  In the IL, this is represented by attaching the destructor
pointer to the array initialization instead of each element initialization
(the destructor pointers for the elements are set for the
partial-construction cleanup, as described above).  For most
configurations, this change doesn't fix a bug; it's just necessary
to accommodate the first change described above.  For those using
IL lowering with no lowering of exception handling features, however,
this change provides information that is needed and was missing
previously, i.e., the fact that an entity being destroyed is an
array and the destructor should be repeated for each of its elements.
Those using IL lowering with full or partial lowering of EH features
will not have to change their code; the code and data structures after
lowering is done are upward-compatible with previous versions.

5/31/96 Windows NT portability issues

The code in host_envir.c that reads directory entries has been changed
to use names that are available on a wider variety of NT compilers.
For example, to use _tfindfirst instead of _findfirst.  The _t versions
of the names are typically macros that expand to some other name that
is appropriate for a given environment.

5/30/96 Partial initialization of multidimensional array of class

The correct dynamic-init entries are now produced for cases like this:

  struct S {
    S();
    S(int);
  };
  S s1[2][2] = { 1 };                 // Now correctly represented
  S s2[2][2] = { 1,1,1 };             // Now correctly represented
  S s3[2][2] = { { 1 }, { 1 } };      // Now correctly represented

5/29/96 Declaring a destructor or conversion function with nested declarator

Declarations of a destructor or conversion function using nested-declarator
syntax are now supported:

  struct S {
    int i;
    (~S)();                                 // Now allowed
    (operator int)();                       // Now allowed
  };
  (S::~S)() { }                             // Now allowed
  (S::operator int)() { return i; }         // Now allowed

5/24/96 Minor adjustments to typeid

Two minor changes to typeid:

(1)  When the typeid(type-id) form is used, if type-id is a reference type,
     the typeinfo for the referenced type is returned.
(2)  typeid of an incomplete array type can now be used.

5/24/96 Restarting initialization of local static when exception thrown

When an exception is thrown during the initialization of a local static
variable, the partial initialization done so far is supposed to be
backed out, and then things should be set so that the initialization
is attempted again the next time it is encountered.  This is now done.

To implement this, a new object lifetime (of kind olk_block) has been
attached to the a_local_static_variable_init entry for a dynamic local
static initialization.  This object lifetime surrounds the entire
initialization of the local static variable, and therefore its extent
is exactly the period of time during which the variable is partially
initialized.  The object lifetime is kept only when exceptions are
enabled.

If you use IL lowering, you will find that this new object lifetime
is reattached to the block statement of the "if" statement generated
to guard the initialization of the variable.  A new dynamic initialization,
with is_guard_var_for_local_static_var_init TRUE, is added to that
object lifetime to indicate the cleanup action of resetting the guard
variable to zero if an exception is thrown.  If GENERATE_EH_TABLES
is TRUE, a region table entry for this cleanup is also generated,
with the new flag RDF_GUARD_VAR_FOR_LOCAL_STATIC set to indicate
this special case.

5/22/96 Global qualifier on friend declaration

The 9/12/95 entry describes the addition of an extension that has since
been approved as part of the language, and so a strict mode diagnostic is
no longer issued for a global qualifier on a friend declaration:

  void f();
  namespace N {
    class A {
      friend ::f();         // No longer treated as an extension
    };
  }

5/22/96 Wrap diagnostics option

The options --wrap_diagnostics and --no_wrap_diagnostics enable
and disable a mode in which the text in long diagnostics is not split
into multiple lines of output.

5/17/96 Member templates

Member templates are now supported.  Member templates are class
templates and function templates that are declared within either
a normal class or a template class.  Member templates are a pure
extension (i.e., they don't change the meaning of any valid programs)
so they are always enabled and no command line option is provided
to disable the feature.

  struct A {
    template <class T> T f(T *p) { return *p; }
  };
  int main () {
    int *p = new int(1);
    A a;
    int i = a.f(p);  // Uses A::f(int *)
  }

Member templates can be constructors or conversion functions as well
as "normal" functions.

  struct A {
    template<class T> operator T*() { return 0; }
  } a;
  int f(int *);
  int i = f(a);

Only the new-style specialization syntax is permitted when
providing an explicit specialization for a member template.
Such specializations must be declared in each translation unit in
which the function or class is used, before its first use in that
translation unit.

5/17/96 Default argument on function template redeclaration

A diagnostic is now issued when a default argument appears on a function
template redeclaration -- e.g.,

  template <class T> void f(T, T);
  template <class T> void f(T, T=0);     // Error or warning is now issued

When a reference to the template appears between the initial declaration
and the redeclaration, an error is always issued.  In strict mode (-A) an
error is also issued.  Otherwise, it is accepted as an extension, and a
warning is issued.

This change also fixes an internal error in IL-lowering that occurred when
an instance of the template was generated before the redeclaration was
encountered -- for instance:

  template <class T> void f(T*, T);
  void g() {
    int i = 5;
    f(&i, i);
  }
  template <class T> void f(T*, T=5) { }  // Error is now issued, internal
                                          //   error is avoided
  main() {
    int i = 10;
    f(&i);
  }

5/17/96 New specialization syntax

The Working Paper requires that a new syntax be used to declare
explicit specializations of templates.  This syntax is now supported.
We require the new syntax for member templates.  The old syntax
is still permitted by the default configuration in default mode, and
is disallowed in strict mode (see entry for "Diagnostics on old-style
template specializations" for further information).

The advantages of the new specialization syntax are:

  - A specialization looks different than a declaration of a function
    that is not related to the template.

  - Specializations can be declared as well as defined.

  - Old specializations affected overload resolution (i.e., they were also
    "guiding" declarations).  New specializations have no effect on
    overload resolution.

Under the new language rules, specializations must be declared before they
are referenced, and they must be declared wherever the entity is used
(e.g., it is not permitted for a program to use both the specialized
and nonspecialized version of the same entity).  Except for class
specializations, these violations can be detected when using the
name mangling changes made in version 2.32.

  template <class T> struct A {
    template <class T2> void f(T2);
    template <class T2> struct B {};
  };

  // Definition of member template A<T>::f
  template <class T> template <class T2> void A<T>::f(T2){}

  // Explicit specialization of template A<int>::f 
  template <> template <class T2> void A<int>::f(T2){}

  // Explicit specialization of instance of template A<int>::f(double)
  template <> template <> void A<int>::f(double){}
	
  // Explicit specialization of A<char>
  template <> struct A<char> {};

  template <class T> void glob_func(T);

  // Explicit specialization of glob_func(int)
  template <> void glob_func(int) {}

A new global variable old_specializations_allowed has been added to control
whether an old-style template specialization (i.e., one without the
"template<>" syntax) is accepted.  Its default value is configured by
DEFAULT_OLD_SPECIALIZATIONS_ALLOWED, and it may be adjusted on the command
line by --[no_]old_specializations.  Moreover, it is set to TRUE in
cfront-compatibility mode, and it is set to FALSE in strict ANSI mode
(unless --old_specializations appears on the command line).  When
old_specializations_allowed is FALSE, a discretionary error is issued when
an old-style template specialization is encountered.

5/14/96 referenced flag on template class in instantiation pragma

An instantiation pragma for a class (which really asks for instantiation
of all the functions in the class) now sets the "referenced" flag on the
class.  Without that, the referenced flag would not be set in Foo<float>
in the following.  One consequence of that is that the generated C
code was invalid if MAINTAIN_NEEDED_FLAGS is configured as FALSE.

  template<class T>
  struct Foo {
      virtual T f( T x ) const =0;
      T integrate( T min, T max ) const;
  };
  template<class T>
  T Foo<T>::integrate( T min, T max ) const
  {
      T h = (max - min);
      T sum = f( min ) + f( max );
      return h * sum;
  }
  #pragma instantiate Foo<float>


5/13/96 Failure to find conversion function in template

In cases like the following, the front end failed to instantiate the source
class early enough and therefore failed to recognize that the conversion
function applies.  The problem only came up when the destination type
is also a class, and there are no other conversion functions to that
class type (or, at least, none instantiated at the time the check is
made).

  template <class T> struct A {
    operator T();
  };
  struct B {};
  void f(A<B> &r) {
    B b = r;
  }

5/10/96 No top-level qualifier on implicit_this_param_type

In the unlowered IL for nonstatic member functions, a top-level const
qualifier is no longer applied to the type entry pointed to by the
implicit_this_param_type field of the routine type supplement (although it
does still appear on the variable generated to represent the implicit this
parameter in the function body).  This change will not be noticed by
implementations using IL lowering, since the qualifier is removed in the
lowered IL.

5/10/96 Bug in handling token caches for parenthesized template static data
        member initializations

When a template static data member definition contained a parenthesized
initializer that required disambiguation to determine whether the
declaration declared a function or an object, a bug in the way in which
the token caches were manipulated could cause either an internal
error or incorrect interpretation of the initializer.  The former
would only occur if template strings were being generated.  In the
latter case, one or more qualified names in the initializer could lose their
qualification information (e.g., X<int>::i would be initialized with
f() instead of X<int>::f).  This has been fixed.

  template <class T> struct X {
    static int f();
    static int i;
  };
  template <class T> int X<T>::i(X<T>::f());
  X<int> xi;

5/10/96 New name mangling for templates

In the modern C++ language, instances of templates must be mangled in a way
that preserves the identity of the underlying template.  This becomes
necessary when overloading of function templates and partial specialization
is supported.  We have changed the name mangling for templates
accordingly.  The old mangling is available through the command-line
option --no_distinct_template_signatures, by setting
DEFAULT_DISTINCT_MANGLING_FOR_TEMPLATES to FALSE, or by setting
ABI_COMPATIBILITY_VERSION to something preceding 232.

A few new encodings have been added to the name mangling scheme to
represent new possibilities:

  -- When the new form of mangling is selected, "__tm__" is used instead
     of "__pt__" to mark the beginning of a template argument list.
  -- "ZnZ" represents the first-level template parameter at position n
     (type or nontype).  "Zn_mZ" represents the template parameter at
     position n and nesting depth m (for member templates nested inside
     templates).
  -- Expressions involving constants and nontype template parameters are
     encoded as follows:
       Opl2Z1ZZ2ZO <-- "Z1 + Z2", Z1/Z2 indicating nontype template parameters.
                 ^---- "O" to end the operation encoding.
              ^^^----- Second operand.
           ^^^-------- First operand.
          ^----------- Count of operands.
        ^^------------ Operation, using same encoding as for operator
                       function names.
       ^-------------- "O" for operation.
  -- Arrays whose counts of elements are an expression involving constants
     and nontype template parameters are encoded as
       A_Opl2Z1ZZ2ZO_i <-- array[Z1 + Z2] of int
                     ^---- Element type.
         ^^^^^^^^^^^------ Encoded expression.
       ^^----------------- "A" indicates array, "_" indicates expression
                           for number of elements.
  -- To deal with an ambiguity when a nontype template argument that
     is a literal constant appears last in a function template argument
     list, a new unambiguous encoding for the length of a literal has
     been added.  It encloses the length in underscores whether or not
     the length is a single digit, e.g., "L_1_0" and "L_10_1234567890".
     The old form continues to be used in class template arguments
     (where there is no ambiguity problem) to preserve upward compatibility.

5/10/96 IL CHANGE: new flags in a_routine, a_variable, a_type

New flags related to explicit template specialization have been added to
a_routine, a_variable, and (as a class_struct_union variant) a_type:

  -- is_specialized is TRUE when the definition of a template function,
     template static data member, or template class, respectively, is
     supplied explicitly rather than generated from the associated
     template.

  -- specialized_with_old_syntax is TRUE when the specialization results
     from something other than a "template<>" declaration.

The specific_def flag in a_routine and a_variable has been removed, as
has the is_specific_template_def flag in a_class_symbol_supplement.

In a related change, specialized_with_new_syntax has been added to
a_src_seq_secondary_decl (which is used if GENERATE_SOURCE_SEQUENCE_LISTS
is set to TRUE); this enables the C++-generating back end to distinguish
between specializations and guiding declarations:

  template <class T> void f(T);
  void f(int);                    // guiding declaration
  template<> void f(int);         // specialization

5/9/69  Nonstandard asm declarations within templates 

An error is now issued if a Microsoft-style asm declaration appears inside
a template.  This is a provisional fix of an abort within scan_asm_body.
A future release will include the permanent fix, which will provide
support for such asm declarations within templates.

5/9/96  Abort following error in conversion operator reference

Certain invalid operator references, such as the one below, could result
in an abort or internal error.  This has been fixed.

  struct A { };
  template <class T> struct X {};
  int main () {
    A::operator X();
  }

5/8/96  Cv-qualifier now allowed on new-type-id in strict mode

The restriction that prohibited a cv-qualifier on a new-type-id has been
removed from the Working Paper, and so we no longer issue a strict-mode
diagnostic on the following:

  const int *p = new const int(0);  // No longer disallowed in -A mode

5/8/96  Error recovery abort on field selection fixed

An abort after issuing an error on the following has been fixed:

  template <class T> struct A { };
  void g() {
    A<float> a;
    a.operator A();
  }

5/8/96  Internal error with aggregate initialization of namespace member

The internal error provoked by the following has been fixed:

  namespace N {
    extern char a[];
  }
  char N::a[] = { 0 };

5/8/96  Spurious error in cfront mode on template static data member
        definition with redundant parentheses

A bug has been fixed that caused a spurious error to be issued on
a template static data member definition that contained redundant
parentheses around the declarator.

  template <class T> struct A {
    static int i;
  };
  template <class T> int (A<T>::i) = 0;

5/7/96  Fixed internal error after invalid template static data member

If a class template contained an invalid static data member declaration,
an internal error could result during the instantiation of a class
based on that template.  This has been fixed.

  template <class T> struct A {
    static B<int>* p1;
  };
  template <class T> struct B {};
  A<int> ai;

5/7/96  Cfront compatibility bug: ordering within virtual function table

A cfront-object-code incompatibility has been fixed in connection with
how virtual function numbers are assigned in the routine entries of
virtual member functions that belong to an overload set.  Here's a simple
example:

  class A {
    virtual void f();
    virtual void g();
    virtual void f(int);
  };

We used to assign virtual function numbers (which amounts to assigning
slots in the virtual function table) in strict declaration order.  But
cfront groups overloaded functions together, so that A::f(int) occupies the
second slot and A::g() the third.  When ABI_COMPATIBILITY_VERSION >= 232 we
use an algorithm that produces results that match cfront's; otherwise, the
old behavior is retained.

5/6/96  IL CHANGE: field removed from a_class_type_supplement

The field anonymous_union_object.storage_class is no longer required and
has been removed from a_class_type_supplement.  As a result, the union
anonymous_union_object is no longer needed either and has also been
removed, and anonymous_union_object.field has been renamed
anonymous_union_field.

5/5/96  IL CHANGE: field in a_src_seq_end_of_construct has been renamed

In a_src_seq_end_of_construct "source_position" is now "position"
(relevant only if GENERATE_SOURCE_SEQUENCE_LISTS is configured to TRUE).

5/3/96  IL CHANGE: an_instantiation_directive

an_instantiation_directive has been added to the IL to represent
instantiation directives in source sequence lists.

5/3/96  Template parameters in elaborated type specifiers

X3J16/WG21 has made two decisions regarding the use of template
parameters in elaborated type specifiers.  First, their use was
prohibited in template declarations.  Later, to simplify the rules,
all uses of template parameters in elaborated type specifiers were
prohibited.  It seems likely that the second decision may be reconsidered
because it means that template parameters cannot be the subject of
friend declarations (e.g., "friend class T").  It is fairly clear,
however, that at least the original restriction will remain in place.

To phase in the new rules we have made a change so that elaborated
type specifiers are no longer meaningful when comparing two function
template declarations or in doing template parameter deduction.
Formerly, the following example declared two overloaded functions
named "f", one that could be called with an enum type and one that
could be called with a class type.  Under the new rules, the program
is ill-formed.

Elaborated type specifiers used in template bodies (in a class
definition or function body, for example) may still be used as they
were previously, except that a remark is issued.

  template <class T> int f(enum T);
  template <class T> int f(class T);
  class X {} x;
  enum E {} e;
  int main() {
     f(x);
     f(e);
  }

5/2/96  Macros output by C++-generating back end

The C++-generating back end has been changed so that it will output macros.
It outputs #defines at the end of the generated code, however, so that
they will not affect the already-macro-expanded code otherwise generated.
This comes into play only when RECORD_MACROS_IN_IL is set to TRUE.

5/2/96  Cfront-compatible handling of copy assignment operators

Global variable allow_copy_assignment_op_with_base_class_param has been
added to control whether an assignment operator for class A with parameter
of type "B", "B&", or "const B&" should be viewed as a copy assignment
operator when B is a base class of A.  When it is TRUE, its effect is that
a user-declared A::operator=(const B&) will block the implicit generation
of A::operator=(const A&).  It will be TRUE in cfront-compatibility mode
and FALSE in strict-ANSI and Microsoft-compatibility modes (which fixes a
Microsoft compatibility bug.)  In default mode, the behavior depends on
the value of DEFAULT_ALLOW_COPY_ASSIGNMENT_OP_WITH_BASE_CLASS_PARAM.

5/2/96  Removal of type qualifiers from function parameter types

Whether top-level qualifiers are stripped off function parameter types is
now controlled by global variable remove_qualifiers_from_param_types.
Its value is configured by DEFAULT_REMOVE_QUALIFIERS_FROM_PARAM_TYPES.
(Note: REMOVE_QUALIFIERS_FROM_PARAM_TYPES is no longer used.)

5/2/96  Microsoft compatibility: functions returning classes considered
        to return lvalues

In Microsoft compatibility mode, functions that return values of a class
type are now considered to return lvalues.

  typedef struct {
    float c[4];
  }Color;
  void gl(float *);
  void fl(Color *);
  Color ppp();
  void f() {
    Color c;
    gl(ppp().c);  /* Okay in Microsoft mode. */
    fl(&(ppp())); /* Okay in Microsoft mode. */
  }

4/29/96 Diagnostic issues for a missing type specifier in an explicit
        instantiation

A discretionary error is now issued if an explicit instantiation
directive contains a missing type specifier.  This is done
for both the #pragma form and the standard form.  

4/29/96 Anonymous unions and source-sequence lists

When an anonymous union appears in a non-class scope, its representation in
the source-sequence list now includes an entry for the compiler-generated
variable that is the anonymous-union parent object.  The entry for the
variable immediately follows the end-of-construct entry for the anonymous
union; the anonymous union type entry is still marked as autonomous.

4/29/96 Error recovery bug: internal error during template instantiation

If a nested class member of an anonymous union in a class template had
the same name as the class containing the anonymous union, and the
anonymous union was nested within a template class, an internal
error would result.  This has been fixed.

  template <class T> struct A {
    union { struct A { }; };
  };
  void f() {
    A<double> x;
  }

4/29/96 Error recovery bug in C mode: internal error fixed

In C mode an internal error is no longer triggered while recovering after
the invalid declaration of i in the following:

  char *p;
  void f(void)
  {
  p = calloc(10, sizeof(char));
  int i = 0;
  }

(Note: that the declaration of i begins at column-position 1 is
significant because it keys an error-recovery optimization.)

4/27/96 IL lowering: pointer to dynamic init entry on return not cleared

In the presence of return value optimization, the return_dynamic_init
field of an stmk_return statement was not cleared to NULL.  Back ends
that only understand C IL should of course not be looking at that field,
but it should have been cleared.

4/27/96 Improved output of prototype scope types when generating ANSI/ISO C

When ANSI/ISO C input to the front end is turned into ANSI/ISO C output via
the C-generating back end (admittedly, not something greatly in demand),
the output sometimes removed information on parameter types in an
attempt to deal with a problem with types defined in prototype scopes.
This approach unfortunately caused other problems, so a more comprehensive
solution has now been implemented.

4/26/96 Default on ALLOW_ELLIPSIS_ONLY_PARAM_IN_GENERATED_C to FALSE

The default value for the configuration switch
ALLOW_ELLIPSIS_ONLY_PARAM_IN_GENERATED_C has been changed to FALSE.
This follows the conservative assumption that a function declarator
of "(...)" will not be acceptable to an underlying C compiler when
C code is being generated.

4/23/96 Declaring the current template to be a friend of itself

A bug has been fixed that made it impossible to declare the current
template to be a friend of itself.  This is needed, for example, if
each instance of A is to be a friend of every other instance of A.

  template <class T> class A {
    template <class T2> friend struct A;
  };

4/23/96 struct il_header renamed struct il_header_tag

The struct name il_header has been renamed il_header_tag so that it
does not have the same name as the variable il_header.

4/23/96 EDG_MAIN to set main program name

The macro EDG_MAIN can now be set to establish a different name (i.e.,
other than "main") for the top-level routine of the front end.  This
allows the front end to be called from a higher-level control program.

4/23/96 Bug in generating source-sequence lists for template instances

A bug has been fixed in putting out source-sequence entries for
instantiations of templates that were namespace members -- the entries
were sometimes appearing in the wrong place in the list.  (The problem only
appeared if CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was TRUE.)

4/22/96 IL CHANGE: elimination of class-instantiation placeholder for
        "partially instantiated" template class

A class-instantiation placeholder (that is, a tk_typeref type entry for
which is_placeholder_for_class_instantiation is TRUE and which points to a
template class) is now put out only if the template class is fully
instantiated.

4/22/96 Loop on nested throw

A front end loop on processing nested throw expressions has been fixed.

  struct S {
    S();
    ~S();
  };
  void foo() {
    throw (throw S(),1);
  }
  void bar() {
    throw (throw S(),1);
  }

4/19/96 Diagnostic on array of incomplete class/enum type

In conformance with a recent Working Paper change, a diagnostic is no
longer issued in strict ANSI C++ mode on the declaration of an array of
incomplete class or enum type.

4/19/96 Abort on generating label in IL lowering for exception handling

In some obscure cases, the process of generating a label during IL
lowering for exception handling could cause an abort.  Now fixed.

  struct Foo {
    virtual ~Foo();
  };
  struct Bar {
    virtual ~Bar();
  };
  Foo::~Foo() {
    Bar bar;
    try {}  
    catch (...) {}
  }

4/19/96 C++-generating back end: generating reinterpret_cast

The C++-generating back end now puts out reinterpret_cast for casts that
cannot be written as old-style casts.

  struct A { int i; };
  struct AA { int j; };
  struct B : public AA, A {};
  main () {
    B b;
    A *pa;
    pa = reinterpret_cast<A *>(&b);
    int A::*pma = &A::i;
    int B::*pmb;
    pmb = reinterpret_cast<int B::*>(pma);
    A &r = reinterpret_cast<A &>(b);
  }

4/18/96 Invalid source-sequence entry when removing unneeded IL entries

In the following case a class name is initially introduced in a parameter
declaration of a member function:

  class A {
    void f(class B*);
  };
  class B { };
  int A::f(class B*) { }

There was a bug in generating source-sequence lists if unneeded IL entries
were being removed, and as result incorrect code was put out by the
C++-generating back end.  This has now been fixed.

4/18/96 Conversions for class operands of the "?" operator

As of the Santa Cruz X3J16/WG21 meeting (3/96), conversions are allowed
on class operands of the "?" operator to bring them to other class types.

  struct A {
    operator int();
  } a;
  struct B : public A { } b;
  struct C {
    C(int);
    operator int();
  } c(1);
  struct E;
  struct D {
    D();
    D(E);
  } d;
  struct E {
    E();
    E(D);
  } e;
  main () {
    int x = 1;
    x ? a : a;  // Okay (same type)
    x ? a : b;  // Okay (inheritance-related classes)
    x ? a : x;  // Okay (a.operator int() : int)
    x ? c : x;  // Ambiguous, c.operator int() : int
                //        or                 c : C(int)
    x ? d : e;  // Ambiguous, E(d) : e
                //        or     d : D(e)
  }

4/17/96 C-generating back end: definitions for template array static data
        members

As a rule, the C-generating back end puts out initialization to zero
on variables that are defined but not initialized.  This explicit
initialization makes the variables defined instead of tentatively
defined (in C terms), so that one will get an error if the variable
is defined in more than one translation unit.  This has not been
done for arrays, however, because it can increase the size of the
executable program a lot.  This optimization caused a loop in the
template prelinker, however, for arrays that are static data members
of templates.  For those, the initialization to zero is now forced.

4/16/96 DEFAULT_BRIEF_DIAGNOSTICS

A default initial value for the variable brief_diagnostics is now
provided by DEFAULT_BRIEF_DIAGNOSTICS.  This variable controls the
"brief" output mode for diagnostics, and is also set by the
--[no]brief_diagnostics command-line option.

4/16/96 bool allowed as left operand of compound assignment operator

As of the Monterey X3J16/WG21 meeting, motion 2h, compound assignment
operators like "|=" allow the left operand to have type bool (previously,
that was explicitly disallowed).  Now supported.

  bool b1;
  int main () {
    b1 |= false;  // Okay
  }

4/16/96 reinterpret_cast between related classes should ignore relationship

A reinterpret_cast operation on pointers or pointers to members to
inheritance-related classes should ignore the inheritance relationship
(i.e., the pointer should not be adjusted in the presence of
multiple inheritance).  Also, ambiguity is not significant.

  struct A {};
  struct B1 : public A {};
  struct B2 : public A {};
  struct C : public B1, public B2 {};
  C cvar;
  A& aref_3 = reinterpret_cast<A&>(cvar);     // Okay, ambiguity doesn't matter
  A* aptr_4 = reinterpret_cast<A*>(&cvar);    // Okay, ambiguity doesn't matter

4/11/96 More conversion functions considered when binding to reference

Following WP changes made at the recent Santa Cruz X3J16/WG21 meeting,
we are now looking for conversions to derived classes (in addition to
conversions to the original class) when attempting to bind a reference.

  struct X {};
  struct Y : public X {};
  int operator==(X, X);
  struct Z {
    operator Y();
  };
  Z z1, z2;
  int i = (z1 == z2);  // Now okay

4/9/96  Internal error in using-directive lookup during template instantiation

A bug has been fixed that could cause an internal error to be reported
from add_symbol_to_overload_list when doing a using-directive lookup
in a template instantiation scope.

4/9/96  Bug with qualified lookups with projection symbols pointing to tags

A bug has been fixed that could cause a qualified lookup (either class
qualified or namespace qualified) to find a projection symbol that
points to a tag symbol when a nontag symbol from the same scope should
be returned instead.  This has been fixed.

This bug can occur with both class projection symbols and namespace
projection symbols.  The class case is unlikely to occur in real code
except when the hidden name table is being used (typically so that
the C++ generating back end can be used) because the hidden name
table processing involves additional lookup operations that would
not normally be done.

  namespace N1 { struct A {}; };
  namespace N2 { char A[10]; };
  namespace M {}
  namespace M { using N2::A; using N1::A; }
  int i = sizeof(M::A);

4/9/96  Instantiation forced in dynamic_cast

When the operand or destination type of a dynamic_cast is a pointer
to a template class, the class is now instantiated.

4/9/96  Warning only on too few or too many macro arguments in Microsoft mode

In Microsoft mode, the error of having too few or too many arguments in a
macro invocation now draws only a warning.

4/9/96  Lvalue casts in Microsoft C++ mode

In Microsoft C++ mode, an lvalue of an integral type cast to the same
integral type is now considered still to be an lvalue.  (Lvalue casts
were formerly supported only for C programs in Microsoft mode.)

4/9/96  IL lowering bug when lowering is used for C code in Microsoft mode

In Microsoft C mode, brace-enclosed initializers for a local aggregate can
include expressions (and not merely constants).  If the configuration
switch LOWER_MICROSOFT_NONCONSTANT_AGGREGATE is TRUE, part of IL lowering
is called to lower the aggregate initialization to standard C.  There
was a bug in adjust_field_selection_for_anonymous_union_references that
caused an abort, due to the fact that the class type supplement pointer
is NULL in C mode.

4/8/96  Bug when handling #pragma ident

A null-pointer dereference no longer occurs when a #pragma ident appears
inside a class template definition.

4/8/96  Bitwise copy of volatile-qualified object

Bitwise copying of classes in C++ is an implementation technique; the
C++ language actually defines such copies in terms of generated
trivial copy constructors and copy assignment operators.  Those
generated functions have a reference-to-const-class input parameter,
which means they cannot copy volatile-qualified objects.  This has
now been implemented (that is, such copies now get an error).

  struct X {};
  volatile X vx;
  X x = vx;      // error: cannot copy volatile object

4/6/96  Some bug fixes in bit-field allocation

A new flag, TARG_ZERO_WIDTH_BIT_FIELD_AFFECTS_STRUCT_ALIGNMENT, has been
added.  When it is configured TRUE, the alignment of any zero-width bit
field declaration affects the alignment for the struct as a whole.

When CFRONT_OBJECT_CODE_COMPATIBILITY is TRUE, the following are now
set (for better compatibility with cfront; these changes are suppressed
when ABI_COMPATIBILITY_VERSION <= 231):

  -- TARG_ZERO_WIDTH_BIT_FIELD is now configured to TARG_SIZEOF_INT,
     as a result of which we now match cfront in handling these
     declarations:

       // Assume sizeof(int) is 4
       struct S1 { char a:1, b:2; };      // sizeof(S1) == 4 (used to be 1)
       struct S2 { char a:1; char b; };   // sizeof(S2) == 4 (used to be 2)

  -- New flag TARG_ZERO_WIDTH_BIT_FIELD_AFFECTS_STRUCT_ALIGNMENT is
     configured to TRUE.

Furthermore, when TARG_MICROSOFT_BIT_FIELD_ALLOCATION is TRUE, additional
changes have been made (for better compatibility with the Microsoft
Visual C++ compiler):

  -- TARG_ZERO_WIDTH_BIT_FIELD is now configured to -1 (which means to
     use the underlying type of the bit field declaration as the container
     type).

  -- New flag TARG_ZERO_WIDTH_BIT_FIELD_AFFECTS_STRUCT_ALIGNMENT is
     configured to TRUE.  Moreover, a fix as been made to assure that
     a zero-width bit field has an effect on alignment only when it
     follows a bit-field declaration -- e.g.,

       struct S { char a,b; long :0; };  // no effect: sizeof(S) == 2

  -- A tweak was made in determining bit-field container compatibility:
     two different integral types are considered compatible as long as
     their sizes are the same.

       // assuming sizeof(int) == sizeof(long)
       struct S { int a:1; long b:1; }   // same container is used by both:
                                         //   sizeof(S) == sizeof(int)

4/5/96    /**/ treated as token-pasting operator ## in SVR4 C mode

In SVR4 C mode, the sequence /**/ in a macro definition is now treated
as a token-pasting operation.

  #define SIZEOF(x) sz_/**/x
  #define sz_XWDColor 12
  void Read(int size) { }
  void foo() {
    Read(SIZEOF(XWDColor));  /* Read(12) */
  }

This is used in the X Window System headers.

4/4/96    // comment begun in macro expansion in Microsoft mode

The Microsoft Visual C++ compiler allows the following:

  #define COMMENT /##/
  COMMENT This is ignored

That is, the "//" fabricated in the macro does open a comment.  Ordinarily,
we would just chuckle heartily at this bug, but as it happens, it is used
in some of the MFC headers.  So, we've implemented it in Microsoft mode.

4/3/96    Exception specification on redundant block-extern declaration

A spurious error has been eliminated in the following case:

  void f() throw (int);
  void g() {
    extern void f() throw (int);
    extern void f() throw (int);    // spurious error no longer issued
  }

4/1/96    Protected member access check suppressed for pointer to member in
          Microsoft mode

The Microsoft Visual C++ compiler (version 1.51 at least) does not do the
protected member access check on pointers to members, so that error is now
suppressed in Microsoft-compatibility mode.

  class Base {
  protected:
    void f();
  };
  class Derived : public Base {
    void d();
  };
  void Derived::d() {
    void (Base::*fp)() = Base::f;  // Okay in Microsoft mode
  }

Also, the diagnostic for the special protected member access check has been
made a discretionary error (in all modes).

3/29/96   Abort when not using checking code

A bug has been fixed that would cause an abort to occur in
template_declaration when the front end is built without checking
code.

3/28/96   Virtual function in an unnamed class

An error is now issued if a virtual function is declared but not defined
inside an unnamed class.

3/26/96   Partially-lowered EH instructions: loop on needed-flag IL walk

The code for the partially-lowered exception handling instructions
(leck_...) in walk_entry.h has been fixed.  Formerly, the needed flag
walk could get into an infinite loop.

3/26/96   Loop in IL lowering on local nested class definition outside of
          parent

A loop in IL lowering has been corrected on definitions of nested
local classes outside of their parent classes.  This bug was introduced
in 2.31.

  void f() {
    struct A {
      struct B;
    };
    struct A::B {
    };
  }

3/26/96   Bug in suppressing instantiation flags

When the --suppress_instantiation_flags option was used, __TIR__ symbols
were still being generated for certain virtual functions.  This is now
fixed.

3/25/96   Include search path bug when using implicit inclusion

The include search path entry that represents the directory of the primary
source file was not being updated properly when using implicit inclusion
to include files from both the current directory and one or more other
directories.  This could result in the failure to find a file to be
implicitly included when that file is located in the same directory as
the primary source file, and when a file from another directory was
implicitly included previously.

3/25/96   Support for new for-init declaration scoping rules

Support for the "new" scoping rules for for-init declarations (WP 6.5.3
[stmt.for]) is now provided.  For example,

  int f(int j) {
    int i = 0;
    {
      for (int i = 0; i < j; ++i) { }
      return i;                 // In cfront mode, f returns the value of j,
    }                           //   but the standard says to return 0.
  }

Global variable default_use_nonstandard_for_init_scope determines whether
the standard-conforming or cfront-compatible rules are observed; its
default value is DEFAULT_USE_NONSTANDARD_FOR_INIT_SCOPE, and it may be
controlled from the command line by --old_for_init and --new_for_init.
Moreover, no matter how DEFAULT_USE_NONSTANDARD_FOR_INIT_SCOPE is
defined, the new rules are used by default (i.e., in the absence of a
command-line directive) in strict-ANSI mode, and the old rules are used
by default in cfront-compatibility mode.

Warning: Although code that relied on the old for-init scoping rules will
usually produce compile-time errors when compiled under the new rules,
that is not always the case.  Because this change may silently alter the
behavior of old programs (as in the above example), we have provided a
diagnostic to alert users.  A warning is issued if global variable
warning_on_for_init_difference is TRUE; its default value is
DEFAULT_WARNING_ON_FOR_INIT_DIFFERENCE, and it may be enabled and
suppressed from the command line by --for_init_diff_warning and
--no_for_init_diff_warning.

3/23/96   IL CHANGE: new field for stmk_for statement

The supplement for an stmk_for statement now contains a scope pointer.
When (in C++ mode) the for-init-statement is a declaration, for_init_scope
may be non-null to point to an implicitly generated sck_block scope that
surrounds the entire for-statement.  Unlike typical sck_block scopes, those
generated for for-init declarations will have a null assoc_block pointer.

3/22/96   Bug in setting source-sequence entry for stmk_decl statement

When GENERATE_SOURCE_SEQUENCE_LISTS and RECORD_MACROS_IN_IL were TRUE,
there was a bug in setting the source-sequence pointer in an stmk_decl
statement if a macro appeared in the source.  It is now fixed -- here's a
case that used to be handled incorrectly:

  void f() {
  #define ZERO 0
    static int i = ZERO;
  }

3/22/96   const function call anachronism accepted in Microsoft mode

The anachronism of calling a non-const member function for a const object
is now accepted as an anachronism in Microsoft mode.  (It was formerly
accepted only in cfront 2.1 mode.)

3/21/96   Bug in checking bit-field size

A bug has been fixed in checking the size specified in a bit-field
declaration.  It used to be that no error was issued for specifying a size
that exceeded targ_max_bit_field_size but was less than the size of the
underlying integer type -- for example:

  // Assume an implementation where longs are 32 bits and bit fields may
  //   only hold 16 bits
  struct S {
    long v:20;         // error is now issued
  };

3/21/96   Typedef name as name "for linkage purposes" of tagless enum

In accord with recent changes to 7.1.3 [dcl.typedef], a tagless enum (like
a tagless class) may receive a name for linkage purposes from the typedef
declaration in which it is defined -- for example, in

  typedef enum { e1, e2, e3 } E;

the name recorded in the enum's type entry is now "E".  (This had already
been the behavior when CFRONT_OBJECT_CODE_COMPATIBILITY was configured to
TRUE and ABI_COMPATIBILITY_VERSION was at least 230; it is now done this
way by default.)

3/21/96   Default initialization of fields in aggregate initialization

A bug has been fixed in aggregate initialization: implicit default
initialization of fields is now done in accord with recent changes to 8.5.1
[dcl.init.aggr].  There are two changes in behavior related to this change.
One is that default constructors are now called where they weren't before
-- for example:

  struct S { S(); };
  struct T {
    int i, j;
    S s;
  };
  T t = { 1 , 2 };    // S::S() is now called for initialization of t.s

The other is that an error is no longer issued on a const member that is
default-initialized -- for instance:

  struct S {
    const int i, j;
  };
  S s = { 1 };        // spurious error is no longer issued -- s.j is
                      //   default-initialized to zero

3/9/96    Repackaging of scan_class_definition

Several subroutines have been broken out of scan_class_definition, most
notably scan_class_member.  Maintaining information among the various
routines is simplified by using a_class_state and a_member_decl_info,
which track the current state of the class definition as a whole and of
a given declaration, respectively.  scan_class_member is also called by
class_member_template_declaration.

3/8/96    cv-qualifiers retained on class rvalues in C++

In C++, unlike in C, class rvalues may have cv-qualified types.  These
qualifiers are now retained, which means in some cases overload resolution
will come up with a different (better) answer:

  struct A {
    void g();
    void g() const;
  };
  extern const A ca;
  const A f() { return ca; }
  main () {
    f().g();  // Should pick g() const
  }

This matches the behavior of other compilers better, and matches the
Working Paper.

3/6/96    Warning on inaccessible elided copy constructor eliminated in
          default mode

The warning in default mode about inaccessibility of a copy constructor that
has been optimized away has been eliminated.  This is a check required
in strict mode, but the warning in default mode doesn't seem to add anything.

  struct A {
    A(int);
  private:
    A(const A&);
  };
  A a = 1;  // No warning in default mode about A(const A&) being private

3/6/96    Bug in hidden-name support (friend declaration in local class)

When RECORD_HIDDEN_NAMES_IN_IL set to TRUE (e.g., when the C++-generating
back end is being used), a bug has been fixed in producing hidden-name
information for friend declarations in local classes.  In the following
case, the generated C++ is the same for the two friend declarations -- the
global qualifier is omitted for both because the block-extern declaration
doesn't really hide "f" inside the class bodies.

  void f();
  void g() {
    extern void f();
    class A {
      friend void ::f();
    };
    class B {
      friend void f();
    };
  }

A related problem has also been fixed.  Correct C++ is now generated for
the following:

  void f() {
    int X, Y;
    void Z();
    struct A {
      struct X *p;
      friend struct Y;
      friend struct Z;
    };
    struct X *px;           // generated C++ now includes "struct"
    struct Y *py;           // generated C++ now includes "struct"
    struct Z *pz;           // generated C++ now includes "struct"
  }

3/5/96    Nontype member of nonreal class incorrectly considered to
          have an incomplete type

Cases such as this resulted in a spurious error when not using
implicit typename.  This occurred because the type of T::X was
incorrectly considered to be incomplete.  This has been fixed.

  template <class T> struct A { int n[sizeof(T::X)]; };

3/5/96    #pragma pack and class template instantiation

When USER_CONTROL_OF_STRUCT_PACKING is TRUE, an instantiation of a class
template takes the packing characteristics that are enabled at the point of
the template definition instead of those of the instantiation context:

  #pragma pack(2)
  template <class T> class A { ... };
  #pragma pack(4)
  A<int> x;          // maximum alignment for A<int> members is 2, not 4

3/4/96    C++-generating back end: fix to deal with cfront bug

cfront has a bug in initialization of static data members that are
classes with constructors: it fails to activate the member names for
the class so they can be found as unqualified names.  For example:

  struct A { A(int); };
  struct B {
    static A a;
    static int i;
  };
  int i;
  A B::a = i;  // cfront incorrectly finds the global "i"

The programmer can code around this bug in cfront by using a qualified name
for the member, but when such a program is run through the C++-generating back
end the qualifier is removed (because it is not necessary).  That makes the
output bump into the bug again.  Because of this, the C++-generating back end
has been changed to output qualified names within the initializer for a
static data member initialized via a constructor, even though such qualifiers
are not, strictly speaking, necessary.

3/1/96    Internal error reporting error in invalid class template
          default argument

If an error was diagnosed during the processing of an invalid
default template argument for the first template parameter, an
internal error could occur.  This has been fixed.

  template <int i = i> class A {};
  A<> a;

2/27/96   "explicit" keyword (nonconverting constructors)

The "explicit" keyword is now supported.  A constructor declared "explicit"
is a nonconverting constructor and is not used for implicit conversions.
The command-line options --explicit and --no_explicit turn that feature
on and off.

2/27/96   Copy-initialization more like Working Paper

The Working Paper [dcl.init] indicates that in a copy-initialization of a
class object, if the source type is the same class type as the destination,
or a derived class thereof, only copy constructors should be considered,
and not conversion functions.  Now implemented.

2/26/96   Source position for class template instances

The "declaration position" recorded for instances of class templates is
now the source position of the template itself instead of the source
position of the reference that triggered the instantiation.

2/26/96   >>= and <<= operators: integral promotions not usual arithmetic
          conversions

The >>= and <<= operations are supposed to apply the integral promotions
to their operands, not the usual arithmetic conversions.  The difference
is visible in something like

  long long f(long long t0) {
    t0 = t0 >> 8;  // 1
    t0 >>= 8;      // 2
    return t0;
  }

//1 and //2 should have the same semantics, in particular with regard
to the fact that the constant "8" should not be converted to long long.
But the >>= operator converted the constant to long long.

2/24/96   IL lowering: qualification mismatch nit on constructor call

A cast to adjust the qualification of a pointer type was missing from
the result of a constructor call when it is used in a context that
requires a qualified object.  This will not cause problems in most
back ends, but it's wrong anyway and has been fixed.  The following
example demonstrates the problem when the 2.28 ABI is chosen:

  struct String {
    String(const String&);
    String(const char*);
  };
  extern void f(const String);
  extern const char* p;
  void g() {
    f(p);  // Returned value from String constructor needs cast to make it
           // const before it's passed to f
  }

2/23/96   C++-generating back end: suppress leading "::" on all tag
          declarations

A leading "::" is never allowed on tag declarations.  It is now suppressed
in all cases.

  struct A {
    struct B *B(int) const;  // was put out as struct ::B etc.
  };

2/22/96   Bug with function templates defined outside of their namespace

In 2.31 a bug was introduced that caused an internal error when a function
template declared in a namespace is defined outside of its namespace.
This has been fixed.

  namespace N {
    template <class T> void f(T);
  }
  template <class T> void N::f(T){}
  int main() {
    N::f(1);
  }

2/21/96   Bug in same_type_with_added_qualifiers

same_type_with_added_qualifiers, the routine used to compare types in
cases where qualification conversions are allowed, failed to check that
the underlying class was the same for pointers to members.  As a
consequence, cases like the following were allowed through:

  struct A {};
  struct B {};
  main () {
    int B::*pmb = 0;
    (void)const_cast<int A::*>(pmb);  // Should get error
  }

2/21/96   C++ qualification conversion on pointers is nonstandard in C

C++ allows conversion of one pointer type to another with cv-qualifiers
added at levels other than the top, e.g., "int **" to "const int *const *".
That has been accepted in C as an extension, but it was inadvertently
allowed in strict C mode also.  It no longer is.

2/21/96   IL CHANGE: dik_zero can apply to things other than entire variables

The dik_zero form of initialization in a dynamic initialization entry can
now be used on entities other than entire variables.  This is necessitated
by the change to allow "()" as the initializer for arrays in ctor-initializers
(see 2/16/96 entry).  dik_zero is now also used for scalar entities
in that context.  IL lowering turns dik_zero initialization of scalars
into assignment of zero, and for aggregates it generates a call to a new
runtime routine __memzero.

2/19/96   C++-generating back end: reference casts for casts on lvalues

The C++-generating back end now uses reference casts to represent a cast
on top of an lvalue address for a class object.  This avoids bumping into
an overloaded operator& for the class.

  class B {
    B* operator&();	
  };
  class D : public B {
    float f;
  public:
    float get_f() {return f;}
  };
  main() {  
    B &br = *new D;
    ((D&)br).get_f();  // Output now has reference cast
  }

2/19/96   C++-generating back end: "." vs. "->" on bound function

The C++-generating back end now recognizes the use of a reference variable
in a member function call, and puts out code that avoids bumping into
an overloaded operator&:

  struct A {
    int operator&();
  };
  main () {
    A a;
    A &r = a;
    &r;  // r.operator&(), not (&r)->operator&()
  }

2/19/96   Output of address constants in il_to_str

The routine form_address_constant in il_to_str.c has been reworked to do
a fancier job of putting out the source form of address constants.
This was motivated originally by some C++-generating back end bugs.
As it happens, another change -- suppressing the folding of constant
addressing operations in initializers for entities with static lifetime --
is a better way of dealing with most of those problems, so that has been
done.  But the form_address_constant changes produce nicer-looking output,
so they've been left in.

2/16/96   Default initialization in a ctor-initializer

In accord with a recent change to WP 12.6.2 [class.base.init], base
classes and nonstatic data members are now default-initialized when the
expression-list is omitted in the mem-initializer; this also applies to
members that are arrays.  For instance,

  struct S { S(); };
  struct X {
    int i, ia[10];
    S s, sa[2];
    X() : i(), ia(), s(), sa() { };
  };

Here, the ctor-initializer of X::X() initializes X::i and each element of
X::ia to zero and calls S::S() for X::s and each element of X::sa.

2/15/96   Hidden name table and anonymous unions

When names from an anonymous union are promoted into the surrounding scope
(and RECORD_HIDDEN_NAMES_IN_IL is configured to TRUE), the hidden name
table for that scope is now updated.  This fixes a bug that caused the
C++-generating back end to produce incorrect code for the following:

  static union {
    short x;
  };
  void f() {
    union {
      short x;
    };
    x = 37;
    ::x = 47;
  }

A bug in the C++-generating back end's use of this information was also
fixed.

2/14/96   Conflict between user-declared and predeclared class type_info

When ABI_CHANGES_FOR_RTTI is configured to TRUE, an error is now issued for
a declaration of class type_info that appears in namespace std (or in the
global namespace if RUNTIME_USES_NAMESPACES is FALSE) and is not preceded
by "#pragma define_type_info".

  namespace std {
    class type_info { ... };      // Error -- not recognized as predeclared
  }                               //   type_info because #pragma is missing

This corrects a bug whereby IL lowering created two classes with the same
name.

2/14/96   Defining predeclared class type_info in the wrong namespace

We now issue an error on code that attempts to provide a definition of
the predeclared class type_info in a namespace other than std (or the
global namespace if RUNTIME_USES_NAMESPACES is FALSE). For instance,

  namespace N {
    #pragma define_type_info      // Error -- this pragma may only be used
    class type_info { ... };      //   with std::type_info
  }

2/14/96   IL lowering: problem with template from one namespace instantiated
          first in class in another namespace

Having a template in one namespace that is first instantiated inside a
class in another namespace caused an abort in IL lowering:

namespace X { template<class T> class A {}; }
namespace Y { class B { X::A<int> t; }; }

This was a problem with the handling of placeholder typerefs and is now fixed.

2/13/96   C++-generating back end: no code for implicit casts for array decay

The C++-generating back end no longer puts out casts that implement the
implicit decay of arrays to pointers.

2/13/96   Error on ambiguous operator delete for virtual destructor

If DELETE_CAN_BE_FOLDED_INTO_DTOR is configured to TRUE, an error is now
issued when a virtual destructor is defined (implicitly or explicitly) and
the inherited member operator delete is ambiguous -- e.g.,

  struct A {
    void operator delete(void *);
    virtual ~A();
  };
  struct B {
    void operator delete(void *);
    virtual ~B();
  };
  struct D : public A, public B {
    virtual ~D() { };              // Error -- ambiguous operator delete
  };

(This diagnostic is not mandated by the working paper at this time, but the
problem has recently been added to the core language issues list.  The
error is issued only for virtual destructors, so as to minimize its impact
while the working paper is being clarified; for nonvirtual destructors an
ambiguity error can always be reported when the delete expression is
processed.)

2/12/96   Spurious access errors on definitions of nested classes

Spurious errors were issued when a nested class was defined outside
of the class, and the qualified name used to define the class named
an inaccessible class member.  This has been fixed.

  class A {
    class B {
      class C;
    };
  };

  class A::B::C {};  // spurious error on this line

2/11/96   C++-generating back end: address of lvalue-returning operation

The C++-generating was failing to put out a "&" in front of an lvalue-returning
operation whose address is taken.

  main () {
    int i = 0, j, k;
    int *p = &(i ? j : k);
  }

2/11/96   Virtual function table for type_info duplicated

When a program includes <typeinfo> and therefore has a definition of
type_info, the IL ended up with two (extern) variables for the virtual
function table for type_info, one generated for the source code and
one added by IL lowering for typeid information.  This was not a problem
when generating C code, but it could cause difficulties for back
ends.  Now there's only one.

2/9/96    Anachronisms in overload resolution

The handling of anachronisms as tiebreakers in overload resolution has
been improved.  They were supposed to be considered on every argument,
but in fact were considered only on the first argument.

2/9/96    Access and ambiguity checking on qualified name in elaborated
          type specifier

We now issue an error when a qualified name in an elaborated type
specifier refers to an inaccessible or ambiguous class or enumeration --
for instance,

  class A {
    class B;
  };
  class C {
    friend class A::B;     // Error now issued: A::B is not accessible
  };

The exception is that such an error is not issued on the deferred
definition of a private nested class:

  class A::B { ... };     // Okay

2/6/96    Removal of unneeded object lifetime entries

When unneeded entries are being removed from the IL (see Changes file
entry for 11/22/95), a bug has been fixed to assure that object lifetimes
associated with default argument expressions are removed from the IL tree
when the routines they are associated with are eliminated.

2/6/96    Using a derived class name to access a member of a template
          parameter dependent base class

It is supposed to be possible to access a member of a base class
through use of a qualified name that uses the name of the derived class.
This did not work when accessing a member that is to be supplied in
a template parameter dependent base class.  This has been fixed.

  template <class T> struct B {
    typedef int I;
  };
  template <class T> struct D : public B<T> {
    typename D<T>::I i;  // Formerly, gave a spurious error on this line
  };


2/6/96    "abc"[2] as nonstandard constant expression

An expression that extracts a character from a constant string, e.g.,
"abc"[2], is now accepted as a constant expression in default mode.
This is nonstandard in both C and C++, so it's not accepted in strict
mode.

2/4/96    C++-generating back end: more on anonymous unions

Yet another bug in handling anonymous unions in the C++-generating back end
has been corrected:

  static union {
    struct S {};
  };
  typedef void (S::*Smf)();

2/3/96    Exception specification for implicitly declared member function

When a member function (i.e., a constructor, destructor, or copy assignment
operator) is implicitly declared, an exception specification is formed based
on the exception specifications of corresponding functions of direct base
classes and nonstatic data members of class (or array of class) type, using
the union of the exception specifications of functions that would be called
for subobject construction.  (Though this approach is not yet explicitly
specified in the working paper, it makes good sense and there appears to be
consensus in favor of it.)  For example:

  class X { };
  class Y { };
  class A {
    A() throw (X);
  };
  class B {
    B() throw (Y);
  };
  class D : public A, public B { };  // implicit declaration of
                                     //   D::D() throw (X, Y)

However, when the implicitly declared function is a virtual destructor, the
generated exception specification can violate the constraint on the
exception specification of an overriding virtual function (it must be at
least as restrictive as that of the function it overrides -- see Changes
entry of 1/12/96).  In such cases a warning is issued.  For instance:

  class X { };
  class A {
    virtual ~A() throw (X);
  };
  class B {
    virtual ~B() throw ();
  };
  class D : public A, public B { };  // warning: implicitly declared
                                     //   D::~D() throw (X) is not as
                                     //   restrictive as B::~B() throw ()

2/1/96    Instantiations of templates from namespaces not handled correctly
          in certain cases

Under certain circumstances, an instantiation that takes place while
compiling a function body may improperly be marked as being local
to a function.  This would result in the name being given an incorrect
mangled name by IL lowering.  This has been fixed.

1/31/96   Internal error on maintaining source-sequence list for
          old-style param list

An internal error has been fixed in managing the source-sequence lists
for this rather obscure case, where an omitted parameter appears in a
function prototype nested within an old-style parameter declaration:

  void f(a) int a(int); { ... } 

1/31/96   Internal error or abort on invalid nested class in a class template

2.31 introduced a bug what could cause an abort or internal error when
a program contains an invalid nested class definition.  This has
been fixed.  The following case gets an internal error on version 2.31.
If the indicated line is removed, the internal error changes to an abort.

  template < class T > class B {
    class C :;
    void f(){}  // remove this line to get an abort
  };

1/31/96   Internal error on scan for enk_temp_inits in array new

An array new of a class whose default constructor has default arguments
that cause creation of more than one destructible temporary, done within
a ctor-initializer, caused an internal error.

  struct AA {
    AA(int);
    ~AA();
  };
  struct A {
    A(AA = 0, AA = 0);
  };
  struct B {
    A *p;
    B() : p(new A[10]) {}
  };

1/25/96   IL lowering: ill-formed cast in pointer to member comparison

When the type of a pointer to data member is configured to be some
integral type smaller than int, IL lowering adds casts to do integral
promotions when operations on pointers to data members are turned into
integral operations.  Unfortunately, in one case -- comparisons of
pointers to data members -- the cast generated for the promotion
had two operands.  The link to the second operand should have been
set to null, and now it is.

1/24/96   EH region number type and null region value passed to runtime

The type of the EH region number field and the value of the null region
number are now passed to the runtime using predefined macros when
the --building_runtime option is used.

1/24/96   Do not recognize stringize operator in string literals in pcc mode

In version 2.31 the front end was changed to permit ANSI preprocessing
operators to be used in pcc preprocessing mode.  Because pcc
preprocessing mode expands macros within string literals, a "#" that
appeared in a string literal was now being interpreted as the
stringize operator.  This has now been changed to disable recognition
of the stringize operator within string literals.

1/24/96   Partial lowering of exception handling, when exceptions are disabled

When the front end is configured to do partial lowering of exception
handling, there was one case where leck_cleanup_state operations were 
generated even when exception handling is disabled.  Now suppressed.

1/24/96   Handling of default arguments involving constructor calls

In the following an internal error has been eliminated during processing of
the default argument expression for X::f; instead, we now issue an error
complaining that no default constructor can be found.

  struct X {
    void f(X* = new X);   // internal error eliminated, error now issued
    X(int i = 0);
  };

There is a language issue here: at what point is a constructor like
X::X(int) regarded as a "default constructor"?  The EDG implementation
takes the position that it cannot be treated as a default constructor in a
call context until *after* its default arguments have been scanned.  Here's
an extreme example, which also used to produce an internal error:

  struct X {
    X(X* = new X);        // internal error eliminated, error now issued
  };

1/23/96   Spurious masked-handler warning

A spurious warning is no longer issued when a handler for a derived class
follows a handler for an ambiguous base class:

  struct B { };
  struct X: public B { };
  struct Y: public B { };
  struct D: public X, public Y { };
  void f() {
    try { throw D(); }
    catch (B) { }       // B is an ambiguous base class of D
    catch (D) { }       // Spurious masked-handler warning no longer issued
  }

1/23/96   Bug in creating overload set for assignment operator

A bug has been fixed in how assignment operators are managed; an entry for
the implicitly declared copy assignment operator was not being created and
added to the overload set under certain circumstances.  We now handle this
case correctly:

  struct B {
    B(const float&);
  };
  struct D {
    D(const double& = 0.0);
    D& operator=(const B&);
  } d;
  void f() {
    d = (double)0;    // Ambiguity error now issued --
  };                  //   D::operator=(const B&) or D::operator=(const D&)?

The expression-processing routines were also modified to recognize the
generated function for the bitwise copy assignment operator, and to
generate an assignment to do bitwise copy, instead of a call, if that
function is selected by overload resolution (1/24/96).  Note: this change
is not enabled in cfront mode, where it would introduce incompatibilities
in rare cases.

-------------------------------------------------------------------------------
Version 2.31, January 19, 1996

1/18/96   IL version number changed to 2.23

1/18/96   cv-qualifier adjustment on cast of pointer to class to related class

When a constant pointer to a class is cast to a related (base or derived)
class, conv_pointer_to_whatever failed to deal with a request for
cv-qualifiers on the desired pointer type that are different from those
on the source pointer.  Now fixed.

1/17/96   IL lowering: exception handling code for "try" within constructor

The code generated for a "try" block within a constructor, where the
constructor is configured to do allocation at the beginning if the "this"
parameter passed in is NULL, saved the wrong region number in the
try block, with the consequence that the runtime could not find the
region number when unwinding.

1/17/96   IL lowering: exception handling code for blocks ending with transfer

Two bugs have been fixed in the IL lowering's handling of exception
handling.  They involve a failure to maintain the current cleanup
state properly when (a) a block that does not itself contain destructible
objects, but which has a subblock containing destructible objects, ends
with a goto, return or throw, and (b) a condition in a loop statement
destroys a temporary.

  struct S {
    S();
    S(int);
    operator int();
    ~S();
  };
  extern int i;
  extern void bar(void);
  void foo1(void) {
    S x;
    if (i) {
      { S dummy; }
      return;  // Cleanup state lost because of this
    }
    S y;
    bar();
  }
  void foo2( void ) {
    while( S x = i ) {  // Cleanup state lost because of this
      S y;
      bar();
    }
  }

The incorrect cleanup state could result in a failure to destroy some
objects.

1/17/96   Old style preprocessing allowed in ANSI C and C++ modes

The --old_style_preprocessing option has been added to allow pcc style
preprocessing to be used when compiling an ANSI C or C++ program.

1/17/96   Diagnostic on unrecognized preprocessor keyword in skipped code

The warning previously issued on an unrecognized preprocessor keyword
within a section of the source that is being skipped (e.g., within a
#if <FALSE> section) is now issued only in strict ANSI mode.

1/17/96   Removing instantiation flags from object files

Sometimes, such as when building a library, it is desirable to remove the
instantiation flags (e.g., __TIR__ and __CBI__) from the object files being
used.  If there are a large number of these flags, they can inflate the
size of the library and of executables that are linked with the library.
One solution is to simply compile the object files used to build the
library with the --no_auto_instantiation option.  This doesn't work,
however, if the prelinker is to be used to generate the instantiations
needed by the library.  To solve this problem a new option has been added
to the eccp script (see the utility Changes file) that is used to prelink a
collection of object files.  Another eccp option has been added to request
that, after prelinking is complete, the object files be rebuilt to remove
the instantiation flags.  A new option (--suppress_instantiation_flags) has
been added to the front end to support this driver feature.  This option
causes the .ii file to be processed, but causes the generation of the
instantiation flags to be suppressed.

1/17/96   __vec_cctor_eh

The runtime now includes a version of __vec_cctor (the routine used to
copy an array by calling a copy constructor on each element) called
__vec_cctor_eh.  When exceptions are enabled, IL lowering generates
a call to __vec_cctor_eh for such copies, and that runtime routine
handles the destruction of the already-copied elements if the operation
is cut short by a throw.

1/16/96   Default initialization using constructor with default argument
          that requires destruction

Two bugs have been fixed (one in the front end proper, one in IL lowering)
in the handling of default initialization for a variable or array using
a constructor that has a default argument whose evaluation involves
creation of a temporary that must be destroyed.

  struct T {
    T();
    ~T();
  };
  struct S {
    S( const T& = T() );
    ~S();
  };
  S x;
  S y[2];

1/16/96   Address of register variable allowed in C mode

The address of a register variable may now be taken in C mode (except in
strict error mode).  A warning is issued.  Formerly, this was only
permitted in SVR4 C mode.

1/16/96   ANSI preprocessing operators accepted in pcc preprocessing mode

The ANSI preprocessing operators for stringizing and token pasting are
now accepted in pcc preprocessing mode.

1/16/96   Warning issued when pointer to integer conversion causes truncation

A warning is now issued in C mode when a pointer is converted to an
integer whose type is too small to hold all possible pointer values.
This conversion is not permitted in C++.

1/15/96   Nonstandard initialization of char array

Initialization of a character array by a parenthesized string constant
is now supported in K&R and cfront-compatibility modes -- e.g.,

  char a[] = ("hello");          // Allowed in K&R and cfront modes

1/15/96   #ifndef guards on configuration values for special characters

#ifndef guards have been added to allow implementations to define certain
special character values in defines.h:
  -- VERTICAL_TAB_CHARACTER (in host_envir.h, when USING_ISO_C is FALSE)
  -- TARG_ALERT_CHAR and TARG_VERT_TAB_CHAR (in targ_def.h)
  -- UNUSED_CHAR_POS (in lexical.h)

1/15/96   extern "C" declaration of namespace member

An error is now issued when namespaces (including the global namespace) in
the same translation unit have members that (1) have the same (unqualified)
name and (2) are declared with extern "C" linkage.  (See entry for 11/1/95:
no name mangling on extern "C" variables in namespaces.)  For example:

  extern "C" void f();
  namespace A {
    extern "C" void f();   // New error -- linkage name for A::f conflicts
    extern "C" int x;      //   with that of ::f
  }
  namespace B {
    extern "C" void g() {
      extern int x;        // New error -- linkage name for B::x conflicts
    }                      //   with that of A::x
  }

1/15/96   Cast between pointer-to-object and pointer-to-function in C

A conversion between a pointer-to-object and pointer-to-function no
longer results in a warning in default C mode.  It is still an error
in strict mode, and in default mode if the destination is not
large enough to hold the pointer.

1/15/96   Cast of pointer-to-function to void* in C

A conversion from pointer-to-function to void* no longer results in a
warning in default C mode.  It is still an error in strict mode, and in
default mode if the destination is not large enough to hold the pointer.

1/15/96   Implicit conversion from pointer to integer allowed in SVR4 mode

An implicit conversion from a pointer to an integer, previously
only allowed in pcc mode, is now also permitted in SVR4 C mode.

1/15/96   Too few macro arguments now a warning in pcc and SVR4 modes

A macro invocation with too few arguments now results in a warning
instead of an error in pcc preprocessing mode and in SVR4 C mode.

1/12/96   Exception specification on overriding virtual function

An error (discretionary) is now issued when the exception specification
on an overriding virtual function is not as restrictive as that of the
overridden function.

1/12/96   Name mangling abort on obscure nontype template argument case

The name mangling code for nontype template arguments expected that
on the address of a variable or routine the offset would always be
zero.  This turns out not to be true when the address is cast to a
related class, so the check has been removed.

  struct T {};
  struct U {};
  struct V : public T, public U {};
  template < U* obj > class Template {};
  V            x;
  Template<&x> y;  // Caused internal error

1/12/96   Required diagnostic on nonstandard character at start of macro

Technical Corrigendum 1 for ISO C adds (in 6.8 of the standard) a requirement
for a diagnostic if the first character of the replacement list of an object-
like macro is not one of the characters required by 5.2.1.  Therefore, the
following now gets an error on the dollar sign in strict mode:

  #define THIS$AND$THAT(a, b) ((a) + (b))

1/11/96   Unreported error on case label

The duplicate-case-label error on the following is now reported:

  void f(int i) {
    switch (i) {
      case 0:
      default:
      case 0:;                 // Error, previously unreported
    }
  }

1/11/96   Include file history list now saved in the precompiled header

Formerly, the include file history list was not saved and restored
as part of the precompiled header information.  This could result
in different behavior when precompiled headers are used.  The
include file history list is now saved, correcting this problem.

1/11/96   Clearing the primary source file pointer when using precompiled
          header files

The primary source file pointer in the IL header must be cleared before
the primary source file is reopened when doing precompiled header
processing.  The point at which this is done has been changed so that
the pointer will be NULL for the shorted possible period of time.

1/11/96   Class definitions incorrectly allowed in template friend declarations

Class definitions were erroneously accepted in template friend declarations.
This has been fixed.

1/11/96   Source-sequence entry for enum constant

An obscure bug in the generation of source-sequence entries for enum
constants has been fixed.  It involved the interaction with source-sequence
entries for adjacent macro or pragma declarations.  For example,

  enum E {
    x, y
  #define xx 1
  };

The source-sequence entry for "y" used to follow the entry for "xx"; now
it precedes it.

1/10/96   Adding cv-qualifiers to typedef in C mode

The following is permitted in C++ (the redundant const in the second line is
ignored) but not in ANSI C:

  typedef const int CI;
  const CI x;           /* An error no longer issued in default C mode. */

This used to always elicit an error in C mode.  Now a remark is issued by
default; only in strict-ANSI mode is an error (-A) or warning (-a) put out.

1/10/96   ISO C Normative Addendum 1

The following features from ISO C Normative Addendum 1 have been added:

- digraphs are recognized as tokens in ANSI C mode ("<:", etc.).  Because
  these tokens can cause quiet changes to existing programs, they are
  disabled by default.  The default may be changed by setting the
  configuration flag DEFAULT_ALTERNATIVE_KEYWORDS_ALLOWED.  This configuration
  flag also controls recognition of the alternative tokens in C++ mode.
  They may also be enabled or disabled on the command line using the 
  --alternate_tokens and --no_alternate_tokens command line options.

- __STDC_VERSION__ is defined to 199409L in ANSI C mode

- the iso646.h header file is provided to define macros for the alternative
  spellings for certain operators (e.g., "bitand", "not_eq", etc.)

1/9/96    IL lowering: type on eok_sassign in pointer-to-member-function cast

The code generated by IL lowering for a pointer-to-member-function cast
where the related class offset is nonzero generates an eok_sassign to
copy the pointer to member into a temporary.  The type of that expression
node was pointer to pmf-struct, where it should be simply pmf-struct.

  class A {};
  class B {};
  class D : public A, public B {};
  struct AAA {
    int (D::*B_pmf)();
    AAA(int (B::*aB_pmf)()) : B_pmf(aB_pmf) { }
  };

1/9/96    Nested class names in instantiation directives

The name of a class nested within a class template may now be used as the
argument of an explicit instantiation directive or an instantiation
pragma.  This causes all of the members of the class to be instantiated.
Formerly, only the name of the outermost class could be used.

  template <class T> struct A {
    class B { void f(); };
  };
  template <class T> void A<T>::B::f(){int i;}
  template class A<int>::B;  // Now permitted
  #pragma instantiate A<int>::B  // Now permitted

1/9/96    Support for #pragma pack() fixed

When USER_CONTROL_OF_STRUCT_PACKING is TRUE, the use of the pack pragma
with no arguments once again causes the packing alignment to revert to the
value specified on the command line.  This was broken when support for
"push" and "pop" was added (see Changes file entry of 4/5/95).

1/8/96    --special_subscript_cost

A new command-line option --special_subscript_cost restores the old
weighting of conversions for the integral operand of the [] operator,
to "standard conversion".  This weighting is nonstandard, but it
avoids the ambiguity on code like the following, which has shown up in
many libraries:

  struct A {
    A();
    operator int *();
    int operator[](unsigned);  // No problem if this is a signed type
  };
  int main() {
    A a;
    a[0];  // Ambiguous according to standard, but okay with this option
  }

1/8/96    Using copy constructor in passing class to ellipsis

A new configuration switch USE_CCTOR_TO_PASS_CLASS_TO_ELLIPSIS has been
added to control whether a copy constructor is used in passing a class
object to an ellipsis.  If the switch is TRUE, such arguments are handled
like normal arguments passed to a class-typed parameter, which is to
say the copy constructor is called (or a bitwise copy is done) to copy the
argument to a temporary, and the address of the temporary is passed to
the function.  If the switch is FALSE (the default), the behavior to
date is preserved, which is to pass the class object by value (as in C)
without making a copy beforehand.  The standard makes this case
undefined behavior, so both behaviors are standard-conforming.  The Sun
C++ compiler seems to match the TRUE setting, and cfront matches the
FALSE setting.

1/3/96    Lookup of base-specifiers

Base class specifiers are now looked up in such a way that nonclass
names are not considered.  As a result, the following code, which was
formerly rejected, is now accepted.

  int X;
  class X {};
  template <class T> struct A : X {};

1/3/96    "typename" recognized as a keyword

The typename keyword is now recognized.  The feature is enabled by
--typename and disabled by --no_typename; the default is established by
DEFAULT_TYPENAME_IS_ENABLED.  Because existing code does not make use
of typename, "implicit typename" processing can be enabled for compatibility
purposes.  Implicit typename is enabled by --implicit_typename and
disabled by --no_implicit_typename; the default is established by
DEFAULT_IMPLICIT_TYPENAME_ENABLED.  Recognition of the typename
keyword and the implicit typename processing may both be enabled
at the same time (in fact, this is the default).  This permits
compilation of old code while accepting new code that uses typename.

12/28/95  New predefined macro for array new and delete support

A macro is now defined when array new and delete are enabled.  This
makes it possible to write header files that can conditionally
declare array new and delete.  The macro name is specified by
the configuration flag MACRO_DEFINED_WHEN_ARRAY_NEW_AND_DELETE_ENABLED.
The default value is __ARRAY_OPERATORS.

12/22/95  Access checking in instantiation pragmas

Access checking should be suppressed when scanning instantiation pragmas.
This was done some time ago for pragmas that have the form of a function
declaration, but not for those that accept a simple name.  Access
checking is now suppressed for all instantiation pragmas.

  template <class T> class X {
    void f();
  };
  template <class T> void X<T>::f() {}
  class Y {
    private:
    struct Z {};
  };
  #pragma instantiate X<Y::Z>  // Now accepted

12/22/95  Nonstandard anonymous unions in C mode

Incorrect source-sequence information was being generated for the following
code (which is accepted in Microsoft-C compatibility mode):

  typedef struct { int i, j; } S;
  struct X {
    S;                        // has the effect of adding fields i and j
  };                          //   to struct X (C mode only)

The reference to S in X is now represented in the source-sequence list by
a secondary-declaration entry that points to S.  The bug only appeared
with GENERATE_SOURCE_SEQUENCE_LISTS and ALLOW_NONSTANDARD_ANONYMOUS_UNIONS
configured to TRUE.

12/21/95  Array of incomplete enum type

It is now permitted to declare an array of incomplete enum type in contexts
where an array of incomplete class/struct/union type is allowed:

  extern enum E x[10];         // permitted in default mode, diagnostic
                               //   in strict ANSI mode

The operations permitted on the array are restricted until the enumeration
is defined (e.g., elements may not be addressed).

12/21/95  Explicit instantiation of templates

Explicit instantiation of templates as specified in the Working Paper is
now supported.  The existing instantiation pragmas have been modified to
also accept arguments of the form permitted by the standard explicit
instantiation directives.  Note that because explicit specification of
function template arguments is not yet implemented, a template argument
list may not be specified in an explicit instantiation at this point.

12/21/95  C++/C-generating back end: "unsigned" instead of "unsigned int"

The C++- and C-generating back ends now put out "unsigned" instead of
"unsigned int" in all cases, to make one obscure C++-generating back end
case work correctly:

  p->unsigned::~unsigned();

12/21/95  #pragma once bug with open include files

The #pragma once directive was incorrectly only taking effect once an
include file was closed.  This has been corrected.

12/21/95  C-generating back end: Avoiding &"string" when generating ANSI/ISO C

Some ANSI/ISO C compilers do not like the construct &"string", perhaps
because they believe strings are not lvalues.  The C-generating back end
has been changed to avoid generating that.

12/20/95  C++-generating back end: Only "="-form initializers for conditions

Condition declarations in C++ are limited to using the "=" form of
initialization.  The C++-generating back end now avoids generating
"()"-form initializers for conditions.

12/20/95  C++-generating back end: class qualifier on suppressed-virtual call

When a virtual function is called with a qualified name to suppress
its virtualness, the C++-generating back end now determines the naming
class rather than just using the class of which the function is a member.
This allows some cases with ambiguity or strange accessibility to work.

12/20/95  IL CHANGE: add generated_default_arg to an_expr_node

A flag, generated_default_arg, has been added to an_expr_node to mark a
node that is a copy of a default argument expression pointed to by a
param-type entry.  Such copies are generated whenever a call makes use of
an implicit argument.  This is used by the C++-generating back end to
suppress defaulted arguments on calls (that's necessary because the
default argument expression might refer to things that are inaccessible
at the point of call).

12/20/95  IL CHANGE: anonymous union parent object

The class-type-supplement entry for an auk_variable anonymous union (i.e.,
one whose associated object is a variable) now records the latter's storage
class, which is needed by the C++-generating back end; the field pointer of
an auk_field anonymous union is now a variant field.

12/19/95  C++-generating back end: Address of member of anonymous union

The C++-generating back end now correctly puts out a constant that is the
address of a member of an anonymous union.

  static union {
    float j;
    int i;
  };
  int* p = &i;

12/19/95  C++-generating back end: Leading "::" on friend declaration

In version 2.30 the C++-generating back end was changed to allow a leading
"::" on a friend declaration, because that's now allowed in C++ and it
is needed for some obscure cases involving namespaces.  However, the change
broke the following:

  struct A {
    int f;
    friend void f();  // Came out with leading "::"
  };
  void f() {}

Now fixed.  A similar problem with class friends has also been fixed.

12/19/95  C++-generating back end: cv-qualifiers on parameter types in
          function declarations

Top-level cv-qualifiers on function parameter types are ignored in modern
C++, except on the type of the parameter variable within the function
definition.  The C++-generating back end previously put out function
declarations with the qualifiers removed, and definitions with the
qualifiers present, as in

  struct A {
    void f(const int);  // Was put out as just "int", now "const int"
  };
  void A::f(const int p) {}  // Was put out as "const int", still is.

This was valid C++ by the modern definition, but ran afoul of some
compilers, so now the qualifiers from the definition are put out
in all cases.

12/19/95  C++-generating back end: extern "C" on variable definitions

The source construct

  extern "C" { int i; }

was formerly output by the C++-generating back end as

  extern "C" int i;

which was not correct because the latter is not a definition and the
former is.  Now fixed.

12/19/95  C++-generating back end: Strange for-init declarations

Strange for-init declarations that declare no variable are now handled
correctly by the C++-generating back end.

  main () {
    for (struct A { int i; } ; ; ) {}
  }

12/19/95  Setting depth_in_scope_stack in block scopes

A bug has been fixed in setting the field depth_in_scope_stack for
sck_block scopes.  (The field is used only during front-end processing.)

12/19/95  Typedef to template parameter used in qualified name

A bug has been fixed that caused a spurious error when a typedef
that refers to a template parameter was used in as part of a qualified
name.

  struct A { 
    typedef int size_type; 
  };
  template <class T> struct B {
    typedef T T_type;
    typedef T_type::size_type size_type;  // Spurious error here
  };
  int main()
  {
   B<A> b;
  }

12/18/95  Calculating "reachability" at exit of switch statement

In the following rather obscure case, "reachability" was computed
incorrectly at the end of the switch statement; as a result a spurious
statement-not-reached diagnostic was issued, and, more seriously, the
lowered IL failed to specify the destruction of "x".  Both problems have
been fixed.

  struct S {
    S();
    ~S();
  };
  void f(int i) {
    S x;
    switch(i) {
    {
      case 1:;
      default:;
    }
    }  /* switch */
    i++;                  // Spurious statement-not-reached warning no
  }                       //   longer issued

12/18/95  C++-generating back end: function-local anonymous union

A function-local anonymous union is no longer invariably put out as static;
it now gets the proper storage class (static, auto, or register).

  void foo() {
    union {  // was put out as static
      int k;
    };
  }

12/18/95  Instantiation of template class before checking for operator()

When the left operand of a call has a class type, and the type is a template
class, it is now instantiated before the check for an operator() function.
This bug was made visible by the instantiation change of 8/30/95.

  template <class R, class A>
  struct Func {
    virtual R operator () (A p) const = 0;
  };
  int call_func1(char* s, const Func<int, char const*>* func)
  {
    return (*func)(s); // Got error in version 2.30
  }

12/17/95  Bug in hidden-name support

For implementations using the C++-generating back end (or otherwise with
RECORD_HIDDEN_NAMES_IN_IL set to TRUE), a bug has been fixed in handling
template names that are referenced by means of global qualification.  For
instance, the C++-generating back end now handles this correctly:

  template <class T> void f(T*) { ... }
  struct X {
    void f();
  };
  void X::f() {
    ::f(this);                // "::" is no longer dropped in the
  }                           //   generated C++

12/14/95  Members of class templates need not have definitions when the
          entire class is being instantiated

When a template class name is used in an "instantiate" pragma, all of 
the members of the class are instantiated.  When an instantiation is
requested by a pragma, an error is issued if the body of the member
function is not supplied (making the instantiation impossible).  The
error is now suppressed if the instantiation was requested by an
instantiation of the entire class.  The error is still issued if
the member was specifically named in the instantiation pragma.

  template <class T> struct A {
    A();
    A(const A&);  // Deliberately not defined
  };
  template <class T> A<T>::A(){}
  #pragma instantiate A<int>  // No longer an error
  #pragma instantiate A<int>::A(const A&)  // Still an error

12/13/95  Pointer-to-member template parameters that depend on other template
          parameter types

A bug has been fixed that caused a spurious error to be issued for cases,
like the example below, that contain a pointer-to-member template parameter
whose class type depends on a previous template parameter.

  template <class T, int T::* pm> class A {
    void f();
  };
  template <class T, int T::* pm> void A<T,pm>::f(){}

12/13/95  No longer an error to declare a function inline after it is called

Formerly, it was an error to redeclare a function as inline after it
had been called.  X3J16/WG21 has removed this restriction.  A
remark is now issued in this case.

12/12/95  IL CHANGE: new field in a_statement

A new field, has_empty_else_clause, has been added to a_statement to mark
an "... else ;" construct in C-mode.  This means the IL now distinguishes
between an empty else-statement and an omitted else-statement.

12/11/95  Default handler must be last

An error is now issued (instead of a warning) when the program declares a
default handler that is not last in the list of handlers for a try block.

12/8/95   C++-generating back end: class qualifier correct on class member
          using-declarations

By using the new field class_specified_in_qualifier the C++-generating
back end now produces qualified names in class member using declarations
that have the class qualifier as written in the source code:

  struct A {
	void f();
  };
  struct B : A {};
  struct C : A {};
  struct D : B, C {
    using B::f;    // Both came out
    using C::f;    //   as A::f previously, which was ambiguous
  };

12/7/95   Incorrect handling of default template arguments and default
          function template arguments when template parameter names
          differ between declarations

A bug has been fixed that resulted in spurious errors when default
template parameters were declared across multiple template declarations
using different template parameter names.

  template <class T, class T2, class T3 = T2> struct A;
  template <class U, class U2 = U, class U3> struct A;
  template <class V, class V2, class V3> struct A { };
  A<int, char> a2;
  A<int> a3;

A similar problem existed for template function default arguments.
This has also been fixed.

  template <class T> void f(T*, T*, T*, T* = new T);
  template <class U> void f(U*, U*, U* = new U, U*);
  int main() {
    int *i;
    f(i,i);
  }

12/7/95   Incorrect handling of templates first declared in friend
          declarations

Version 2.30 introduced a bug that caused templates first declared in
a friend declaration to be instantiated improperly if the definition
outside of the class used different template parameter names than
the declaration inside the class.  This has been fixed.

  template <class T> struct A {
    template <class T2> friend void f(T2);
  };
  A<int> ai;
  template <class T3> void f(T3){ T3 t;}
  int main() {
    f(1);  // Spurious error during instantiation
  }

12/7/95   IL CHANGE: new field in a_class_member_using_decl

A new field, class_specified_in_qualifier, has been added to
a_class_member_using_decl.  It indicates how the using-declaration actually
appeared in the source and is used by the C++-generating back end.

12/7/95   Instantiation of template class to look for conversion functions

In cases like the following the front end failed to instantiate a template
class in order to look for conversion functions.  Now fixed.

  template <class T> struct B {
    operator char *();
  };
  extern void f(char *s);
  void g(B<int> *b) {
    f(*b);
  }

12/1/95   Friend class declaration using typedef name (cfront mode)

A bug has been fixed to allow (in cfront-compatibility mode) using a
typedef name in the elaborated type specifier of a friend class
declaration.  This case now works appropriately in cfront mode:

  class A;
  class B {
    typedef class A T;
    friend class T;           // No longer aborts here
  };

12/1/95   Reference to template class no longer causes instantiation

Defining a variable with type reference-to-template-class used to force
instantiation of that class; this was a best guess in the original
implementation of templates, but clarifications in the language definition
now make it an unlikely interpretation.  Here's an example of where
behavior is now different:

  template <class T> class A { };
  extern A<int> a;                   // No instantiation (unchanged)
  A<int> &ra = a;                    // No longer triggers instantiation

(Of course, any subsequent use of ra (or a) that requires the type to be
complete will cause the instantiation to be performed.)

12/1/95   Spurious diagnostics caused by out-of-scope declarations that
	  should be ignored

In ANSI C mode, when SVR4 mode is enabled, an out-of-scope declaration was
incorrectly being considered even when it did not meet the lookup constraints.
This resulted in a spurious diagnostics in cases like the one below.  This
particular case resulted in a warning on versions before 2.30, and resulted
in both a warning and an error on version 2.30.  This has been fixed.

  typedef struct X* Xp;
  extern Xp x;
  struct bar { struct x* a; };
  struct x { int i; };

11/28/95  Bug causing macro and field names to conflict with other names

Version 2.30 introduced a bug that caused a spurious error in some cases
when a macro and some other global scope entity have the same name.  The
same problem occurs with field names and global entities in pcc mode.  This
has been fixed.

  extern void f(int i);
  #define f(x) f2(x)
  void (f)(int i){}

11/27/95  Type of pointer to member in initialization from overloaded
          member function

When a member function is chosen from among several in forming a
pointer to member, if the pointer to member is to a derived class of
the class of the function, the necessary cast to derived was not
done on the constant.  Now fixed.

  struct B {
    int foo() ;
    int foo(int);
  };
  struct D : public B {};
  int (D::*df)() = &B::foo;   // Constant had type int (B::*)() instead
                              // of correct int (D::*)().

11/27/95  Exception handling: RDF_BASE_CLASS_SUBOBJECT flag in region table

The region table entry used for the fully-lowered and partially-lowered
versions of exception handling now contains an RDF_BASE_CLASS_SUBOBJECT
flag that indicates that the object is a base class of the object being
constructed or destroyed in a constructor or destructor.  This is used
by the runtime to control the "complete object" flag passed to destructors.

11/27/95  cfront compatibility: comparisons of pointers to members related by
          virtual inheritance

Cfront allows comparison of pointers to members related by virtual inheritance
even though it does not allow the implicit conversions implied in the
comparison:

  struct A {int j;};
  struct B : public virtual A {int k;};
  void f() {
    int A::*pa = &A::j;
    int B::*pb = &B::k;
    (void)(pa == pb);    // Accepted by cfront, and now by EDG in cfront mode
    int B::*px = pa;     // Gets "sorry, not implemented" from cfront,
                         //   error from EDG
  }

Of course, since it does no adjustment, it sometimes gets the comparison
wrong, as in this case.  We now allow the comparison, but we get it right
(by casting the other operand to the virtual base class and then comparing).

11/25/95  Redundant instantiation of template class

A bug has been fixed that caused the same template class to be
instantiated more than once when a declaration involved a temporarily
incomplete array.  An internal error resulted in some circumstances.
Here's a example:

  template <class T> struct A { T t; A(T); };
  A<int> x = 0;
  A<int> y[] = { 0,0,0 };     // a second instantiation of A<int> is no
                              // longer performed

11/25/95  Bug in hidden-name support

For implementations using the C++-generating back end (or otherwise with
RECORD_HIDDEN_NAMES_IN_IL set to TRUE), a bug has been fixed in the
interaction among namespaces, delayed nested-class definitions, and hidden
names.  For instance, in the following a hidden-name entry is no longer
recorded for CN2:

  namespace Y {
    namespace Z {
      struct C {
        struct CN2;
      };
    };
    struct Z::C::CN2 { };
  }

11/22/95  "Delayed" definition of classes nested within class templates

As with normal classes, it is now possible to define a class nested
within a class template, outside of the class template definition,
as in the following example:

  template <class T> struct A {
    struct B;
  };
  template <class T> struct A<T>::B { };

As part of this change, it is also now possible to specialize a nested
class without specializing the enclosing class.

The language rules for nested classes within templates have been changed
to make such specializations possible.  Formerly, nested classes were
instantiated when the enclosing template was instantiated.  Now, nested
classes are only instantiated when a complete instantiation is
required using the same rules that apply when determining when to
instantiate a normal (e.g., nonnested) template class.

11/22/95  Base specifiers in out-of-class definition of nested classes

Names in base-specifiers of nested classes defined outside of their
enclosing class should be looked up in the scope of the class.  They
were incorrectly being looked up in the scope where the class was
defined.  This has been fixed.

  template <class T> struct C {};
  struct A {
    typedef int X;
    struct B;
  };
  struct A::B : public C<X> {};  // Now finds A::X

11/22/95  Elimination of unneeded IL entries

When MAINTAIN_NEEDED_FLAGS is TRUE, the IL tree can be pruned of unneeded
entries.  This is partially under the control of a new command-line option,
--[no_]remove_unneeded_entities, which is used to set global variables
remove_unneeded_entities (initialized to DEFAULT_REMOVE_UNNEEDED_ENTITIES)
and okay_to_eliminate_unneeded_il_entries.  By default, the IL tree is not
pruned when the C++-generating back end is used.

11/20/95  C-generating back end: obscure problems with qualified array
          typedefs

The C-generating back end removes top-level "const" from the types of
nonstatic data members and initialized variables.  This process did not
work right for variables or data members whose type was given by a
array typedef.

  typedef const int A[4];
  typedef int AA[4];
  struct B {
    volatile A x;  // Cannot use typedef
    A y;           // Cannot use typedef
    const AA z;    // Can use typedef
    AA zz;         // Can use typedef
  } *p;

11/18/95  Fixed loop in IL lowering processing of placeholder typerefs

A bug in the use of placeholder typerefs to guide the process of type
promotion in IL lowering has been fixed.  This came up when typedefs
were used to represent class templates and the templates are members of
namespaces.

  namespace N {
    template <class T> struct P { };
    template <class T> struct R {
      struct S { };  
    };
    template <class T> struct multimap {
      typedef R< P<T> >::S S;
    };
  }
  using namespace N;

  template <class T> class PCn {
    typedef T::S  S;
  };

  template <class T> struct M : private PCn<multimap<int> > { };

  int main()
  {
    M<int> m;
  }

11/18/95  C++-generating back end: "for" statement declaring multiple variables
          where some variable after the first has a non-trivial declarator

The il_to_str processing of the FTO_SUPPRESS_SPECIFIERS option has been
fixed, which allows the C++-generating back end to handle

        for (int i = 37, &j = i;;)

11/18/95  il_to_str output of pointer-to-member type qualifier

The il_to_str output of a class qualifier for a pointer to member, e.g.,
"A::*", formerly used the wrong name output routine, which sometimes
output an elaborated type specifier, as in "class A::*".  Now fixed.
This is significant mainly when using the C++-generating back end
(for everyone else, it's only an aesthetic problem).

11/17/95  Adding declared-but-not-defined types to the types list

The technique for adding types to the list pointed to by scope entries has
been modified to assure that classes that are declared but never defined
appear at a position in the list corresponding to where the first
declaration occurred.  (It used to be that declared-but-not-defined types
appeared at the end of the types list -- they were not added until the
scope they belonged to terminated.)

11/16/95  IL lowering: bug in processing of outside-of-parent definitions
          of classes in a namespace

A bug that caused an internal error on the following has been corrected:

  namespace Y {
    namespace Z {
      struct C {
        struct CN2;
      };
    };
    struct Z::C::CN2 { };
  }

11/16/95  Projection symbols created for symbols that fail lookup criteria

Projection symbols were incorrectly being created for symbols that did
not meet the criteria for the lookup being done.  In the following example,
the lookup of A::A2 was incorrectly creating a projection symbol for X::A,
even though X::A is not a class or namespace symbol.  This resulted in an
error later when py->A() found the projection symbol X::A instead of the
member Y::A.  This has been fixed.

  struct A { typedef int A2; };
  struct X { int A(); };

  struct Y : private X
  {
    int A();
    Y(A::A2);
  };

  void f(Y *py)
  {
    py->A();  // Formerly, gave a spurious error
  }

11/13/95  Added global variable allow_nonstandard_anonymous_unions

This variable, set to TRUE when microsoft mode is enabled and by default
to new configuration flag DEFAULT_ALLOW_NONSTANDARD_ANONYMOUS_UNIONS,
allows better control over when the support for the microsoft extension is
enabled.

11/13/95  Spurious error using elaborated type specifiers in class template

A spurious "invalid redeclaration of B" error was issued on the following
example.  This error occurred when a class template contained more than
one use of an elaborated type specifier referring to a given name.  This
has been fixed.

  template <class T> struct A { 
    friend class B;  
    class B * b;
  };

11/10/95  Internal error with using-declarations

The check for virtual function overriding had a bug introduced by the
2.30 changes -- an internal error is no longer produced by the following
program:

  struct A {
    void f();
    void f(int);
  };
  struct B : public A {
    using A::f;
  };
  struct C : public B {
    void f(int,int);
  };

11/1/95   Name of constructor of an unnamed class

The "name" field in the source correspondence of a routine entry for a
(necessarily compiler-generated) constructor of an unnamed class is
now NULL.  Here's an example:

  struct A {
    struct {
      virtual void f() {}
    } y;
  } x;

11/1/95   No name mangling on extern "C" variables in namespaces

extern "C" variables in a namespace were being mangled.  They shouldn't
be.

  namespace std {
    extern "C" int errno;
  }

11/1/95   Initial value constants for static data member constants

The initial value constants for initialized static data members should
have any source correspondence information cleared (they're unshared
copies of the constant value).  The information was not cleared, with
the consequence that bad ANSI/ISO C was generated for this program:

  namespace Q {
      enum Colors { red = 0, blue, green };
      struct S {
          static Colors const color = blue;  // problem here
      };
      Colors const S::color;
  }

10/31/95  cfront compatibility overload resolution changes

Several changes to provide greater compatibility with cfront in overload
resolution.  These apply only in cfront mode.

(a)  A null pointer constant must be spelled "0" to be convertible to
     a pointer or pointer to member type.  This replaces the change made
     on 4/5/95 ("conversions of class operands to pointer type when
     they are operands of builtin operators").  This change applies only
     in overload resolution determination of the best function;
     elsewhere, null pointer constants with other forms are still accepted.
(b)  In cfront 3.0 mode, when attempting conversions on operands of a
     builtin operator, no attempt is made to convert to pointer or
     pointer to member types if the other operand is a null pointer
     constant and the operator is a relational operator (<, >, <=, or >=).
(c)  Dropping type qualifiers when binding a reference (an anachronism)
     is considered a tiebreaker in overload resolution.

10/31/95  Default on SAME_REPR_INTS_INTERCHANGEABLE_IN_IL

The default for SAME_REPR_INTS_INTERCHANGEABLE_IN_IL in targ_def.h has
been changed to be FALSE except when the C-generating back end is being used
and K&R C is being generated.  The TRUE setting is really the safer
setting, so it's a more appropriate default.

10/30/95  IL CHANGE: unmangled_name in source correspondence

The a_source_correspondence structure now contains (when name mangling is
needed) a field unmangled_name which preserves the original form of the
name of an entity when the name is mangled.  The field is NULL until the
name is mangled.

This was added to deal with some bugs in getting the type name string set
correctly in type_info structures (sometimes the string included mangled
names).

10/30/95  Copying expression containing enk_typeid

copy_expr_tree had a bug with regard to copying expressions containing
enk_typeid nodes.  Now fixed.

  int i;
  void *p = (void *)&typeid(i);  // Got internal error

10/30/95  is_local_to_function set on handler and unnamed parameters

The is_local_to_function flag is now set for unnamed parameters and
for parameters of handler (catch) clauses.

10/26/95  C++-generating back end: default initialization of parts of arrays

The C++-generating back end now correctly handles default initialization
(via constructor) of parts of arrays.

  struct X {
    X(int);
    X();
  };
  X x[4] = {1, X(1)};
  X y[2][3] = {{1}, {}};

10/26/95  // comments not recognized in pcc mode

// comments are now not recognized in pcc mode even if
END_OF_LINE_COMMENTS_ALLOWED_IN_C_MODE is defined as TRUE.

10/25/95  IL lowering: class/namespace membership information now cleared

IL lowering now clears the class/namespace membership information in
the source correspondence entry of entities promoted out of classes
and namespaces.  This makes the IL arguably more correct as C code.
This change can be undone by eliminating the call of clear_parent_information
in lower_il.c.

Some minor bugs in this area were corrected when this change was made:
member constants promoted out of local classes now have their names
mangled, and their is_local_to_function flags cleared; enum constants
promoted out of functions now have their is_local_to_function flags cleared;
member functions promoted out of local classes now have their
is_local_to_function flags cleared.

10/25/95  IL CHANGE: new field defined_outside_of_parent

A new flag has been added to a_routine when GENERATE_SOURCE_SEQUENCE_LISTS
is configured to TRUE: defined_outside_of_parent is TRUE if the routine is
a class member defined outside the class definition or a namespace member
defined outside the namespace definition.

10/25/95  C++-generating back end: mutable

The C++-generating back end now outputs the "mutable" specifier.

10/24/95  Recursive inclusion with -M and --implicit_include options

When using implicit inclusion with source code that was not structured
with implicit inclusion in mind, it was possible to create an
inclusion loop when doing makefile dependency processing using
the implicit inclusion option.  This has been corrected.

10/23/95  Abort in template function declaration containing elaborated type

If the return type of a function template was a template class specified
using an elaborated type specifier, an abort could result.  This
has been fixed.

  template <class T> struct A { };
  template <class T> struct A<T> B(T) { return A<T>; }
  int main() { B(1); }

10/19/95  IL lowering vs. source-sequence lists

In general, you should not configure both DO_IL_LOWERING and
GENERATE_SOURCE_SEQUENCE_LISTS to TRUE, in part because the processing
in IL lowering can invalidate the source sequence information.  A check
has been added to host_envir.h to enforce this policy.

10/19/95  Version number variable in generated C

The C-generating back end now puts out a tentative definition of a
variable that identifies the version number, e.g.,

  int __EDGCPFE__2_30;

This has the secondary benefit of guaranteeing that every generated
C file contains at least one declaration (which is an ANSI/ISO C
requirement).

10/18/95  Specializing member functions of template classes

A member function of a class template may now be specialized even
if the member function was defined in the class.  Also, the linkage
of a specialization no longer depends on whether an out-of-class
definition of the member function included the "inline" keyword.
Only the use of the "inline" keyword in the class definition
itself forces a specialization to be inline.

  template <class T> struct A {
    void f() {}
    inline void g();
    void h();
  };

  template <class T> void A<T>::g(){}
  template <class T> inline void A<T>::h(){}

  // Specialization of A<T>::f only inline if declared as inline.
  // This specialization not previously allowed.
  void A<char*>::f() { }
 inline void A<float*>::f() { }

  // Specialization of A<T>::g always inline.
  void A<char*>::g() { }
  inline void A<float*>::g() { }

  // Specialization of A<T>::h only inline if declared as inline.
  // Formerly, A<T>::h would be inline because the out-of-class definition
  // is inline.
  void A<char*>::h() { }
  inline void A<float*>::h() { }

10/17/95  Namespace handling in walk_declarative_entities_in_scope

walk_declarative_entities_in_scope (an optional routine used by some to
sweep the declarative information in order to generate symbolic debugging
information) has been enhanced to deal with namespaces.

10/16/95  Template member functions given incorrect linkage

A template member function defined as inline outside of the
class definition was given an incorrect storage class and name
linkage kind.

  template <class T> struct A {
    void f();
  };
  template <class T> inline void A<T>::f(){}
  A<int> ai;  // A<int>::f given incorrect storage class/name linkage

10/13/95  Internal error instantiating template friend in namespace

An internal error occurred when a template initially declared in
a template friend declaration within a namespace was instantiated.
This has been fixed.

  namespace N {
    template <class T> struct A {
      template <class T2> friend void f(T2) { }
    };
    A<int> a;
    void g()
    {
      f(1);
    }
  }

10/13/95  IL CHANGE: "needed" flags

When MAINTAIN_NEEDED_FLAGS is configured to TRUE, the "needed" flag in
a_source_correspondence and "definition_needed" in class/struct/union type
entries are defined.  They are provided as an optimization aid, giving more
precise information than the "referenced" flag about whether an entity is
"really" needed.  An entity can end up marked as "referenced" but not
"needed" if, for example, it is only referenced by a function that is never
called.

10/12/95  Configuration flag for Linux changed from __LINUX__ to __linux__

The configuration flag used to indicate that the front end is being
compiled on Linux has been changed to __linux__, which is automatically
set by the version of gcc that comes with Linux.

-------------------------------------------------------------------------------
Version 2.30, October 10, 1995

10/9/95  Namespaces

Namespaces are now supported.  This includes namespace definitions,
namespace alias declarations, "using" declarations and directives, and
new name lookup rules.  The changes on qualified name lookup in
the presence of "using" directives, from the 7/95 standards meeting
(Monterey), are also implemented.  Namespaces are enabled by default (see
DEFAULT_NAMESPACES_ENABLED) except in the cfront modes.  The command-line
options --namespaces and --no_namespaces can be used to enable or
disable the features.

We added two new IL entry kinds (a_namespace, a_using_directive),
and we changed the class_of_which_a_member pointer in the source
correspondence entry (see 6/6/95 entry) and renamed the
an_access_adjustment entry to a_class_member_using_decl (see
8/8/95 entry).

The name mangling for members of namespaces uses the same form as
for class members, and there are no other ABI implications, so this
feature is upward compatible with older versions except for the
introduction of the new keywords "namespace" and "using".

Well, almost: the lookup rules for overloaded operator functions
are now implemented according to the WP, and that means some programs
that do not use namespaces can change meaning (the operator functions
in the global scope overload with the operator functions declared
extern inside a function, instead of being hidden by them).  The old
operator function lookup rules are used when namespaces are turned off.

Name lookup during template instantiations now does something that
approximates the two-phase lookup rule of the WP.  See the external
interface chapter in the internal documentation for details.

We had to guess at some things not well specified by the WP, and in
one case (scope of friend declarations) we decided that we think the WP
is wrong and we implemented something different.  Again, see the
internal documentation for details.

The headers and runtime we provide have also been updated to use
namespaces, or rather, to support two different versions under
control of the preprocessing option __EDG_RUNTIME_USES_NAMESPACES,
which is defined by the front end.

When the runtime is configured to be in the "std" namespace, existing
programs that reference names from the runtime may be affected.  The
--using_std option has been provided to allow most such programs to
be compiled without change.  The --using_std option causes the header
files that declare entities in the "std" namespace to implicitly
do a "using namespace std".  The default behavior is specified by the
configuration flag DEFAULT_IMPLICIT_USING_STD.  The --no_using_std
option may be used to explicitly disable this feature.

10/9/95  near/far memory attributes in Microsoft mode

When MICROSOFT_EXTENSIONS_ALLOWED is TRUE, the front end now supports
near/far memory attributes.  They are supported in 16-bit Microsoft
mode, which is a sub-mode of the normal Microsoft mode.  It can be
enabled by --microsoft_16, or it can be made the default.  New
command line options --far_code_pointers and --far_data_pointers
can be used to control the default sizes of pointers.

near and far are represented as type qualifiers.  They appear in the
IL only when necessary to represent a non-default value.  The default
values are indicated by the far_data_pointers and far_code_pointers
fields in il_header.  Back ends that generate different code for near
and far operations can look at the pointer sizes or can use the
function is_far_type to determine the size of a type considering
qualifiers and defaults (which is useful, for example, in determining
the type of call to make to a function).

10/9/95  Default name-linkage assigned to classes

It used to be that a file-scope class was given internal name-linkage when
it was created, and it (along with its members) was fixed up at the end of
compilation -- based, among other things, on whether it was used in
declaring a function or other entity with external linkage.  This was
consistent with requirements of the ARM, but now the language dictates that
all classes declared at file scope and most declared at namespace scope
have external linkage.  We have changed the default (except in cfront mode)
to be consistent with the following rules:
  -- local classes have no linkage
  -- classes declared inside an unnamed namespace have internal linkage
  -- all other classes have external linkage
The linkage of a class member can now be set as soon as it is declared,
determined in part by the linkage of the class of which it is a member.
The fixup-routine, check_class_linkage, is now called only in
cfront-compatibility mode.

10/9/95  Error recovery problem on cast to class type in constant expression

A cast to a class type in a constant expression no longer produces an
internal error:

  struct A {
    A(int);
  };
  int x[A(1)];

10/7/95  C++-generating back end: extern declaration of static

extern declarations that refer back to existing static variables are
now correctly output by the C++-generating back end.

  static int i;
  extern int i;  // Was put out as "static", which is wrong

10/7/95  C++-generating back end: Nonstandard anonymous unions

The C++-generating back now handles nonstandard anonymous unions (a
Microsoft extension) properly.

10/6/95  Const-qualified variable of empty class type with no initializer

We no longer issue a diagnostic, except in strict-ANSI mode, when a
variable of empty class type is declared const but with no initializer:

  class A { };
  const A a;           // No missing-initializer warning in default mode

10/6/95  Qualifier on parameter variable of template function

A bug has been fixed in setting the qualifiers on the type of the parameter
variable in an instantiated template function.  For example:

  template <class T> T f(const T t) { return ++t; }
  int main() {
    int i;
    (void)f(i);        // Error is now issued on instantiation of f(int):
  }                    //   ++t is illegal because t is const

10/5/95  C++-generating back end: pragmas on dependent statements

A problem in the C++-generating back end has been corrected.  It caused
an abort on handling a pragma bound to the dependent statement of an
if, while, do-while, or for.

10/5/95  Used-before-set warning on variables of empty-class type

We no longer issue a warning when an "unset" variable of empty-class type
is used -- for example:

  class A { };
  A f() {
    A y;
    return y;        // No used-before-set warning
  }

10/5/95  Pragma on dependent statement of loop with condition

A bug has been fixed that related to IL lowering of a pragma bound
to the dependent statement of a while or for loop that has a condition
declaration.

10/3/95  C++-generating back end: Non-member anonymous union member names

The C++-generating back end now puts out the names for members of 
non-member anonymous unions correctly.

  static union {
    typedef int T;
  };
  T x;

10/3/95  C++-generating back end: template friends

The C++-generating back end now deals correctly with template friend
declarations in classes:

  struct A {
    template <class T> friend void f(T) {}
  };

10/2/95  IL CHANGE: Removal of accessible base class IL entry

The accessible base class IL entry is vestigial when ABI_CHANGES_FOR_RTTI
is enabled, because the access for throws is determined at runtime
instead of compile time.  Accordingly, it has been removed in that
configuration.

10/2/95  Casts of bit fields to same type preserved

Previously, a cast of a bit field to the type of the bit field was
thrown away.  However, this is wrong, since the expression with
the cast does not undergo integral promotions in the same way:

  struct A { unsigned int i:5; } a;

  a.i                 // Promotes to int
  (unsigned int)a.i;  // Promotes to unsigned int

This is fixed by preserving the cast in the IL tree.

10/2/95  Use of qualified name in class member declaration

In a class member declaration within a class definition, a qualified name
referring to the current class is permitted on the declarator; this
cfront-compatibility extension was added long ago to deal with code from
older libraries, and a diagnostic was issued in strict ANSI mode.  We now
issue a diagnostic in default mode as well.

  class A {
    A::A() { ... }      // Now a warning in default mode
  };

10/2/95  C++-generating back end: extern "C" on declarations within functions

The C++-generating back end now suppresses extern "C" on declarations
within functions.  extern "C" is not allowed to appear there, and can
be on the IL entry only because of an extern "C" { ... } wrapper around
the entire function.

  extern "C" {
    void f() {
      extern void g();  // Formerly put out with extern "C"
    }
  }

10/2/95  Obscure IL lowering bug causes bad generated C

In a case where a member function was declared, used in a pointer
to member within a function, called, and then defined, the generated
code for the call included a cast to a routine type which was not
lowered and therefore had the wrong number of parameters.  Now fixed.

  struct A
  {
   void h();
   void g();
  };
  void f() {
    void (A::*p)() = &A::h;
  }
  void A::g() { h(); }     // Call pointed to unlowered routine type
  void A::h() {}

10/2/95  Pragma binding with elaborated type specifiers

A bug has been fixed in how a "next-construct" pragma binds when an
elaborated type specifier appears in the declaration of another entity.
This has an impact on this sort of case, for example:

  /*ARGSUSED*/
  struct S *f(int i) { return 0; }    // Diagnostic on unused parameter
                                      //   "i" is no longer issued.

9/27/95  Template instantiation based on unnamed tag

A spurious error (introduced by a change in version 2.28) has been
eliminated: instantiating a template with an unnamed type that has a
name "for linkage purposes" is again allowed:

  typedef struct { ... } S, *PS;
  template <class T> class X { ... };
  X<PS> x;                             // Spurious error no longer issued

9/26/95  Diagnostic on masked handler

A warning rather than an error is now issued when a handler is "masked" by
another handler declaration, as per a recent change in the Working Paper.

9/26/95  Mixing static and nonstatic members in overload set

Except in cfront mode, an error is now issued if two member functions,
one static, the other nonstatic with a function qualifier, have the same
parameter types:

  class A {
    void f(int) const;
    static void f(int);    // Okay in cfront mode, error otherwise
  };

9/24/95  "explicit" recognized as an unimplemented keyword

A diagnostic is now issued in strict mode if "explicit" is used
in any context.

9/22/95  Recognition of constructor declaration

The spurious error has been eliminated and this sort of case is now
handled correctly:

  template <class T> struct A {};
  typedef int I;
  struct A<short> {
    A<long>(I);        // Previously interpreted as an ill-formed
  };                   //   constructor declaration; now accepted as
                       //   declaration of member A<short>::I

9/22/95  Remainder operation bug when using simulated integers

When INTEGER_VALUE_REPR_IS_A_HOST_INTEGER is FALSE (e.g., when
long long operations are being emulated on a host that does not
support long long) the remainder operation may produce incorrect
results when the result value is itself a long long.  This has
been corrected.

9/20/95  Specifying the .ii file name on the command line

The name of the instantiation information (.ii) file to be created/used
by the front end may now be specified using the --ii_file command line
option.  The .ii file should be associated with the generated
object file, so this option makes it simpler to provide drivers that
permit the name of the object file to be specified on the command
line.

9/19/95  Internal error in Microsoft C++ mode using the C generating back end

Examples like the following would result in an internal error in the
C generating back end when compiled in Microsoft mode.  This occurred
because an lvalue cast operation that should only be generated in C mode
was being generated in C++ mode.  This has been fixed.

  void f(int i, int *a, int* b)
  {
    void* p;
    p = i ? (void*)a : (void*)b;
  }

9/19/95  Bug in switch-statement processing

A bug has been fixed in switch-statement processing -- incorrect IL used to
be generated (in C-mode only) for cases like the following:

  void f(int i) {
    switch (i)
    case 0:
    {
       int j = i++;
    case 1:
       j = i++; 
    }
  }

9/15/95  Function template specializations in friend declarations

This sort of case (for which no error was issued in version 2.29 and which
produced an internal error prior to 2.29) is now handled properly:

  template <class T> void f(T) { }
  class A {
    friend void f(long) { }
    friend void f(long) { }     // Already-defined error is now issued
  };

9/13/95  IL CHANGE: flag to mark implicit declaration

A new flag, implicit_decl, has been added to a_src_seq_secondary_decl,
indicating that the entry represents implicit declaration of an extern
function (C-mode).

9/12/95  Global qualifier on friend declaration (extension)

Except in strict ANSI mode we now accept a qualifier on a friend
declaration to designate a file-scope name.  This is to be consistent
with allowing namespace-qualified names in friend declarations:

  void f();
  namespace N { void g(); }
  namespace M {
    class A {
      friend N::g();           // Allowed
      friend ::f();            // Allowed as an extension
    };
  }

9/11/95  C++-generating back end: C mode definition of struct in cast

The C++-generating back end now handles correctly a definition of a
struct in a cast in an initialization in C mode.

  main() {
    int a = ((long)((char *)&((struct{char c; int d;}*)0)->d - (char *)0));
    return a;
  }

9/10/95  C++-generating back end: output of unnamed enums

The C++-generating back end now puts out unnamed enums without names.
Formerly, it gave them generated names, which caused problems in C++
because the generated name was used for linkage purposes by some
compilers (e.g., cfront) in cases like

  typedef enum {a, b} E;

where the typedef name would have been used had the enum been unnamed.
In C mode, unnamed enums are still given generated names so they can
be used in casts related to prototype scopes.

9/8/95   Multiple declarations mixing implicit and explicit extern "C++"

We now allow this behavior (originally disallowed in the ARM):

  void f();                     // Implicitly declared with C++ linkage
  extern "C++" void f();        // Explicit redeclaration is now okay

9/8/95   Inline template function dependencies and the ordering of source
         sequence entries

When source-sequence lists are being generated and are supposed to include
entries representing template function instantiations (i.e., when
NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE) there was
a bug that occurred when one inline-function instantiation was triggered
within another inline-function instantiation: the order sometimes failed to
correspond to the dependency between the two functions.  This has now been
fixed.

9/7/95   Overloading based on linkage specification

A bug has been fixed that caused an internal error when attempting to
overload two functions based on linkage-specifier alone.  For example:

  void f();                 // Implicitly declared as extern "C++"
  extern "XXX" void f();

These are treated as distinguishable members of an overload set, assuming
that support for "XXX" linkage has been added (see a_name_linkage_kind) and
that "C++" and "XXX" linkages are treated as incompatible (see
routine_linkages_are_compatible).

9/7/95   Avoiding trigraphs in generated string and character literals

The il_to_str routines have been changed to avoid accidental output
of trigraphs in string and character literals.  This done by escaping
each "?" character as "\?".  This is not done when generating pcc code.

9/7/95   Condition, object lifetime, and continue statement

A bug has been fixed when a condition declared a destructible object and the
for- or while-loop contained a continue statement: the object's destructor
used to be called twice when the continue statement was executed.  Here's an
example:

  struct S {
    S(int);
    ~S();
    operator int();
  };
  void f() {
    int i = 10;
    while (S s = i--) continue;
  };

9/6/95   Redeclaring a variable name as a function template

An internal error has been fixed for cases like this, where a variable
name is redeclared as the name of a function template:

  int x;
  template <class T> void x(T);   // Now a redeclaration error rather
                                  //   than an internal error

9/3/95   Omission of decl-specifiers in C++ function declaration

In C++ (except in cfront mode) an error (discretionary) is now issued
when no decl-specifiers are specified on a function declaration.

9/2/95   Argument type information in overload resolution diagnostics

Diagnostics produced for overload resolution problems now include the types
of the arguments.

9/1/95   Deduced template function that cannot be called

The following program formerly got an internal error because the front end
assumed that any function generated by template argument deduction
would be callable.  In this case, it isn't, because there is no copy
constructor that can copy the argument.

  struct A { 
    A();
    A(A&);   // Note: no const
  };
  template <class T> void f(T) {}
  int main()
  {
    const A a;
    f(a);
  }

8/31/95  C++-generating back end: extern "C" suppressed on friend declarations

extern "C" is not allowed on friend declarations, so the C++-generating
back end has been changed to suppress it on such declarations.  It will
still come out on the definition of the friend function.

8/30/95  Function types as template parameters

In version 2.26 we made it an error to use a function type as a
template parameter.  X3J16/WG21 decided to permit function types
as template parameters, but prohibit them from being used to
declare a function without using the function declarator syntax.
The front end has been modified to reflect this decision.

The following example illustrates the valid and invalid uses of
a template parameter that has a function type.

  template <class T> struct A {
     T t;     // Error: invalid use of function type
     T* t2(); // okay
   };
  A<int()> a;

8/30/95  Allowing "&..." and, in C mode, "(...)"

The lang_feat.h configuration switches ADDRESS_OF_ELLIPSIS_ALLOWED and
ALLOW_ELLIPSIS_ONLY_PARAM_IN_C_MODE have been renamed
DEFAULT_ADDRESS_OF_ELLIPSIS_ALLOWED and
DEFAULT_ALLOW_ELLIPSIS_ONLY_PARAM_IN_C_MODE.  They are now the initial
values of variables.  The variables are set to TRUE if the --svr4
command-line option is specified.

8/30/95  Instantiation of classes in expression processing

Template classes are instantiated automatically when needed in expression
processing.  Now, they are instantiated on an lvalue to rvalue conversion
instead of when the lvalue is constructed.  This fixes a bug with
calling a function that returns a reference to an uninstantiated template
class, and matches the newer Working Paper specification.

8/29/95  New source files scope_stk.c/h, lookup.c/h

To reduce the size of symbol_tbl.c, some of the symbol table code has
been moved into new files.  scope_stk.c contains scope-stack maintenance
code.  lookup.c contains symbol table lookup code.  scope_stk.h and
lookup.h are new corresponding header files.

8/28/95  C++-generating back end: bug with address of class temporary

A program like the following, which casts a class rvalue to a reference
in order to take its address, got an internal error in the C++-generating
back end.  Now fixed.

  struct A {
    A();
    A(const A& f);
  };
  A g(A& f);
  void m()
  {
    A f;
    A* fp;
    fp = &(A&)(g(f));
  }

8/28/95  Lowering of nonconstant aggregates in Microsoft C mode

Microsoft mode allows a nonconstant aggregate initializer for an auto
variable in C mode.  Now, when LOWER_MICROSOFT_NONCONSTANT_AGGREGATE
is TRUE (which is the default), a piece of IL lowering will be called
in C mode to lower that construct to standard C.

8/27/95  New placeholder typeref for nested classes defined outside of parent

"Placeholder" typeref entries are placed in the IL to give added information
about ordering for type entries.  They are used in IL lowering to
guide the process of flattening class, local, and namespace type lists
into a single file-scope type list.  A new placeholder has been added
to indicate the point of definition of nested classes defined outside of
their parent class.  As with all placeholders, this type looks like
a useless typeref and is ignored in most cases.

8/26/95  Adding linkage kinds

Adding linkage kinds beyond "C" and "C++" has been made easier: there
is now an array name_linkage_kind_names in il_def.h to go along with
the a_name_linkage_kind enumeration.  It is no longer necessary to
modify the code in linkage_specification in decls.c.  Also: the
macros routine_linkages_are_compatible and routine_linkages_are_identical
have been moved from types.c to types.h so they can be used everywhere,
and the il_to_str display routines now display a linkage kind in a
function type (for non-compilable output) if the linkage is not compatible
with the default linkage.

8/25/95  Incomplete array as final field in Microsoft C++ mode

In C, as an extension, it is allowed to declare the final field of a
struct with zero-length array:

  struct S {
    int a,b,c,d[];       // Okay in Microsoft C++ mode
  };

This is now accepted in Microsoft C++ mode as well, as long as the class
type is an "aggregate" (no private members, no constructor, no base
classes, no virtual functions).

In addition, the use of [0] for such cases in place of [], already accepted
in Microsoft C mode, is now accepted in Microsoft C++ mode, too.  That
means the above can be written as:

  struct S {
    int a,b,c,d[0];      // Okay in Microsoft C++ mode
  };

8/25/95  _asm in Microsoft mode

In Microsoft mode, "_asm" is now accepted as a synonym for "asm" or "__asm".

8/24/95  Redundant file inclusion suppression bug

A bug has been fixed that could result in the suppression of the
inclusion of a file that had previously been included, but for
which the include optimization cannot be done.  Certain
preprocessing directives that precede the initial #if test of
the guard code were incorrectly being ignored.

8/24/95  Declaring a member function as a friend of its parent class

An error recovery problem has been fixed when a member function is
declared a friend of its parent class and defined in the friend
declaration -- e.g.,

  class A {
    void f(int);
    friend void A::f() { }    // No longer aborts
  };

8/24/95  Spurious assertion failure

An assertion check, which could have been tripped after an error (but
only when GENERATE_SOURCE_SEQUENCE_LISTS was TRUE), has been removed
from decl_variable.  For example:

  int i;
  typedef int i;
  int i;                     // No longer aborts

8/24/95  IL CHANGE: Two placeholder typeref flags renamed

Two flags indicating placeholder typerefs (used mostly by the C-generating
back end to resolve some thorny ordering issues) have been renamed:

  is_placeholder_for_file_scope_type -->
         is_placeholder_for_class_instantiation

  referenced_by_placeholder_typeref -->
         referenced_by_class_instantiation_placeholder_typeref

The old names became insufficiently specific when other types of
placeholder typerefs were added, and the type referenced can be
in a namespace scope now instead of in the file scope.

8/24/95  Discretionary error on unrecognized preprocessing directive

The error issued for an unrecognized preprocessing directive is now
a discretionary error, which means it can be demoted to a warning or
eliminated by the user.

8/24/95  Nit in support of additional nonstandard linkage kinds

The routine constant_references_non_external_entity has been fixed to
work correctly when additional nonstandard linkage kinds (e.g.,
extern "Ada") are added by our customers.

8/23/95  C-generating back end: mutable

The C-generating back end now accommodates "mutable" by adding extra
casts as necessary on member selections to make the resulting entity
nonconst.  This problem was visible only when generating ANSI/ISO C,
and resulted in generated C code that would not compile.

  struct A {
    mutable int i;
    mutable int b:1;
    A();
  };
  main () {
    const A ca;
    ca.i = 1;
    ca.b = 1;
  }

8/23/95  IL lowering: preservation of more type information on pointers to
         members

IL lowering rewrites pointers to members as a struct (for pointers to
member functions) or an integral type (for pointers to data members).
The rewriting is done by changing the original type entry for the
pointer to member type to a pass-through tk_typeref that points to
the new type.  There is a single new type entry used for all pointers
to member functions, and a single new type entry used for all pointers
to data members.  As a rule, is better to preserve uses of the original
type pointer in operations, because that gives slightly more information
about the original types.  The difference doesn't matter for code
generation, but may matter for generation of symbolic debugging
information.  A few cases in IL lowering have been changed to preserve
the original type pointer in the IL.

  class B { public: int f(); };
  class D : public B { };
  int (D::*xxx)();
  main() { xxx = B::f; }  // Temp for pm constant preserves original type

8/22/95  IL CHANGE: Type in ck_aggregate constants

The type field in ck_aggregate constants is now filled in properly.
Formerly, it was NULL.

8/22/95  %np diagnostic fill-in code

The diagnostic output routines now support an additional fill-in kind,
"%np".  The "p" modifies the basic "%n" ("name") specifier by forcing display
of function parameter types even if the function is not overloaded.
This is used in displaying functions in an ambiguous function call
(in the world of namespaces, some functions that are not overloaded
in their original declaration can be brought into an overload set
via "using" declarations).

8/21/95  C-generating back end: wide string literal constants

The C-generating back end rewrites references to the addresses of wide
string literals as references to variables initialized with the
proper string literal values.  This rewrite process generated bad
C code when the same wide string literal was referenced in more than
one function, because the variable was put out as a local static
in the first function and then used again in the second.  Now fixed.

  void f(wchar_t *);
  void g() {
    f(L"abc");
  }
  void h() {
    f(L"abc");
  }

8/21/95  Object id variable double name mangling for nested classes fixed

In certain cases the object id variable (pointed to from the typeinfo
variable) generated for a nested class had double name mangling in it.
In the following, __TID_Q2_5Space13__Q2_5Space1B is now __TID_Q2_5Space1B:

  class Space {
  public:
          class B {
          public:
                  virtual int f();
          };
          class D: virtual public B {
          public:
                  virtual int g();
          };
  };
  int Space::B::f() { return 0; }
  int Space::D::g() { return 0; }

8/21/95  SVR4-C compatibility bug fixed

An error is no longer issued in SVR4-C mode when a nonprototyped function
definition follows a prototyped declaration with which it is incompatible,
as long as the return types are the same or "interchangeable".  For
example:

  int f(const int *);
  int f(p) int *p; { ... }    // A warning is now issued in SVR4-C mode

8/18/95  Type for bit fields

All bit fields in the front end have been changed to use the typedef
"a_bit_field" instead of "unsigned int" as the base type of the
declaration.  a_bit_field is defined in basics.h, and ordinarily it
is the expected "unsigned int".  However, when the front end is
compiled by a Microsoft compiler, a_bit_field is defined as "unsigned char",
which results in better packing of our structures under the Microsoft
bit-field allocation convention, and therefore less space use.

8/18/95  Instantiation pragma and nested classes

When a template-id is used as the argument of an instantiation pragma
the pragma should apply to all of the members of the class.  A bug
resulted in the pragma applying only to the members of the top
level class and not to the members of any nested classes.  This has
been fixed.

8/17/95  Removing type qualifiers from parameter types, again

The changes to remove or preserve qualifiers on parameter types have been
put under control of the configuration option
REMOVE_QUALIFIERS_FROM_PARAM_TYPES.  It is enabled by default if
ABI_COMPATIBILITY_VERSION is greater than 228 and
CFRONT_OBJECT_CODE_COMPATIBILITY is FALSE.  This differs from the
behavior in the 2.29 release in that qualifiers are not dropped in
2.30 if CFRONT_OBJECT_CODE_COMPATIBILITY is chosen.

8/17/95  CFRONT_OBJECT_CODE_COMPATIBILITY

Starting with release 2.30, CFRONT_OBJECT_CODE_COMPATIBILITY (set
as the "or" of CFRONT_2_1_OBJECT_CODE_COMPATIBILITY and
CFRONT_3_0_OBJECT_CODE_COMPATIBILITY) means, by default, "give me
complete ABI compatibility with cfront."  Language features that
are incompatible with cfront's ABI (e.g., RTTI) are disabled by
default.  They can be enabled explicitly (e.g., by setting
ABI_CHANGES_FOR_RTTI), and the front end will work with such 
a setting, but the ABI in such a version is only cfront-like,
not cfront-compatible.  This new interpretation allows us to make
corrections in cases where we weren't completely compatible with
cfront.  Customers who set ABI_COMPATIBILITY_VERSION >= 230 and who
have CFRONT_OBJECT_CODE_COMPATIBILITY TRUE will get a version that
includes corrections and is therefore more compatible with cfront.
Customers who hold ABI_COMPATIBILITY_VERSION at some older version
number will retain compatibility with our older versions (and
therefore slight mismatches with cfront).

8/14/95  Overflow checking on conversion of floating constants

store_double in float_pt.c has been modified so that it does a more
correct check for overflow on a double --> float conversion when
compiled with an ANSI/ISO C compiler (one with FLT_MAX defined).
Of course, this just makes it a better portable solution; in general,
it's a good idea to review the routines in float_pt.c and customize
them for your environment.

8/13/95  C++-generating back end: bug in computing hidden-name info

The front-end routine that, given a declaration, computes hidden-name
information for that entity and/or other entities of the same, has been
reworked (partly to provide support in conjunction with namespaces), and   
as a result a few bugs have been fixed -- for instance, correct C++ code
is now generated for:

  int main() {
    int A = 27;
    enum A { B=32 };
    enum A o = B;
  }

8/13/95  C++-generating back end: Bug with array --> pointer decay as lvalue

The C++-generating back end has been fixed to deal properly with
array-->pointer decay in lvalues:

  struct A {
    char s[2];
  };
  void m() {
    A *p;
    *p->s = '\0';
  }

8/13/95  C++-generating back end: Hidden name table use

(1)  The C++-generating back end now uses the hidden name table when
     putting out references to nested types (e.g., "class A::B").
(2)  When it installs the hidden name information for a class, it now
     also installs the hidden names from any base classes.
(3)  When putting out a tag reference, the C++-generating back end
     now considers the possibility that a global qualifier may be
     needed (e.g., "class ::A").

8/8/95   IL CHANGE: an_access_adjustment ==> a_class_member_using_decl

Certain entities have been renamed now that access-declarations are just a
deprecated way writing using-declarations within a class definition:
an_access_adjustment is now a_class_member_using_decl, and the field
access_adjustments in a_class_type_supplement is now
class_member_using_decls.

8/8/95   Bug in access check for overloaded functions with access adjusted

Access declarations that adjust access on a set of overloaded functions
were not always properly handled.

  struct A {
  public:
    void f(int);
    void f(float);
  };
  struct B : private A {
  public:
    A::f;
  };
  struct C : public B {
    void g() { f(1); }    // Should be okay
  };

8/8/95   Bug in computing derivations of indirect virtual base classes

In the following example:

  class A { public: int i; }; 
  class B : virtual private A { };
  class C : public B, virtual private A { friend class D; };
  class D : private C {
    void f() { i = 1; };         // spurious error (A::i inaccessible)
  }; 

the error was issued as a consequence of reporting only one derivation of
D's base class A (==>C==>B==>A) and omitting the other (==>C==>A).  (The
spurious error disappeared if the base classes of C were reversed.)  This
bug has been fixed.

8/7/95   Bug in access checking with indirect virtual base classes

A small bug with access checking in the presence of indirect virtual
base classes has been corrected.

  class X { public: int i; }; 
  class A : public X { }; 
  class B : virtual private A { }; 
  class C : virtual private A, public B { friend class D; };
  class D : private C {
    void f() { i = 1; };  // Should be accessible, got error previously
  }; 

8/4/95   Relaxation of restrictions on access-declarations

Access-declarations (see WP [class.access.decl]) are now implemented
identically to base class member using-declarations.  This means fewer
restrictions on the use of access-declarations -- programs previously
ill-formed are now permitted -- but the behavior of previously well-formed
programs should not be affected.  For instance:

  class A {
  public:
    void f();
  protected:
    int i;
  };
  class B : private A {
  public:
    A::i;            // used to be an error (increasing access), now okay
    A::f;            // okay (no change)
    void f(int);     // used to be an error ("f" already declared), now
  };                 //   okay (overload set "f" has two members)

(No compilation mode is provided to re-enable the previous behavior.)

Also, several diagnostic messages, no longer needed, have been marked
"REMOVED" in error_msg.txt.

8/4/95   Missing promotions on IL-lowering-generated pointer-to-data-member
         operations

When the integer kind chosen for pointers to data members is one that
is subject to integral promotions (e.g., unsigned short), some of the
operations on pointers to members (casting, calling, comparing,
dereferencing) did not include the casts necessary to promote the
pointers to data members when they were operands of operators that
force integral promotions (e.g., "+", "==").  The casts have been added.

8/2/95   Definitions now allowed in template friend declarations

The X3J16/WG21 working paper now permits templates to be defined in
friend definitions (previously, only declarations were allowed).
The strict mode diagnostic for template friend definitions has been
removed.

8/2/95   Mangled names for virtual function tables (cfront compatibility)

The mangled names for virtual function tables involving nested classes
have been adjusted to match cfront's name mangling.  For example:

  struct AA { struct A {virtual int f();}; };  // Was __vtbl__Q2_2AA1A, now
                                               //     __vtbl__8Q2_2AA1A

  struct Space {
    struct B {
      virtual int f();  // Was __vtbl__11Q2_5Space1B__Q2_5Space1D, now
                               __vtbl__1B__11Q2_5Space1D
    };
    struct D: virtual public B {
      virtual int g();
    };
  };
  int Space::B::f() { return 0; }
  int Space::D::g() { return 0; }

These changes apply only if CFRONT_OBJECT_CODE_COMPATIBILITY is set, and
only with ABI_COMPATIBILITY_VERSION >= 230.

7/31/95  __declspec on classes in Microsoft mode

The __declspec modifier (a Microsoft extension) is now allowed in the
form that applies to class types, in C++ mode only.  For example:

  class __declspec(dllexport) A {
    // dllexport applies to all members
  };

A decl_modifiers field was added to the IL class type supplement to
contain the modifiers set for the class as a whole, but it should be
noted that those modifiers are also included in the decl_modifiers
field of member functions and static data members.

7/26/95  Source sequence entry for template member function instantiation

A change has been made to assure that a source sequence entry will be
put out for a template member function instantiation when the front end
is configured to put out source sequence entries for its body.

7/25/95  Spurious cfront transitional nested type error

In cfront compatibility mode when CFRONT_2_1_OBJECT_CODE_COMPATIBILITY
is being used, cases like the following result in a spurious
"two nested types have the same name" error.  This has been fixed.

  struct A {
    typedef class { } Y;
  };

7/25/95  Bit-field allocation bug

In certain configurations version 2.29 introduced a bug in computing the
size and alignment of a bit-field container; this has been fixed.  Here is
an example of the effect of the fix:

  struct S {
    char c;
    int flags:10;
  } s;

Assuming default settings for integer sizes and alignments, the size of s
is now 4 (not 3, as before) and its alignment is 4 (not 1).

The bug occurred only when TARG_BIT_FIELD_CONTAINER_SIZE was configured to
zero and when the size of the bit field exceeded the number of bits in a
char, but even then it was usually masked: it had an effect (on the size
and alignment of the class object itself, never on its internal layout)
only in rather unusual cases, such as when there were no other fields
whose alignment requirements would "dominate".  For example, if struct S
defined above had an int or pointer field, the bug would not be noticed.

7/24/95  Memory region problem with IL lowering default_version_of_routine

The routine default_version_of_routine in IL lowering takes a function
having default and/or implied arguments and generates a function that can
be called without arguments and supplies the default and implied
arguments.  There was a bug in that routine that generated the
implied argument expressions for constructors and destructors before
switching into the memory region of the generated function.  If the current
memory region was for another function, the expressions would end up in
one function memory region while the reference was in another.  The following
program demonstrates the problem, though it may or may not abort depending
on the exact layout of memory (it aborted for us when using the
non-alternate file format, but it appeared to work on other versions):

  struct A {};
  struct B : virtual A {};
  B b[2];

7/21/95  Include file names that are also directory names

If, when searching for an include file, a directory was encountered
with the same name as the include file being sought, the front end
would issue an error that the file did not contain source text.  The
front end has been changed so that directories are ignored when searching
for an include file.  If only a directory is found (i.e., there is no
regular file of the specified name in the include search path) the
front end now issues a "could not open source file" error.

7/21/95  Disambiguation of cast followed by field selection

A field selection following a context that requires disambiguation to
determine whether an operation is a cast or an expression was being
interpreted incorrectly.  This has been fixed.

  struct A {A();~A();};
  int main()
  { 
    (A()).~A();  // formerly gave a spurious error
  }


7/19/95  "?" operator with lvalue result

The standards committee clarified last week that a "?" operator yields
an lvalue result only if the operands have the same type BEFORE ANY
IMPLICIT CONVERSIONS.  Those implicit conversions include array -->
pointer and function --> pointer conversions.  Formerly, we tested
for a type match after those conversions (and before the lvalue --> rvalue
conversion).  Now, we test before those conversions.  Also, the test
is now done before any implicit conversions from class types to
built-in types.

7/17/95  Macros that are defined more than once on the command line

A macro defined more than once on the command line was being set to the
first value on the command line.  It is now set to the last value
specified on the command line.  For example

  edgcpfe -DXXX=1 -DXXX=2 t.c

formerly gave XXX the value of 1, but now gives XXX the value of 2.

7/6/95   type_info name strings for nested classes

The RTTI name strings in type_info entries generated for nested classes had
incorrect (partially-mangled) names if the class was not referenced from
any function.  Now fixed.

  struct A {
    struct B {
      struct C {  // Name string for A::B::C was A::__Q2_1A1B::__Q3_1A1B1C
        virtual void f();
      };
    };
  };
  void A::B::C::f() {}

7/5/95   Added is_placeholder_for_namespace_type to a_type

A new variant field, is_placeholder_for_namespace_type, has been added to
a_type.  It identifies a compiler-generated typeref entry on the file-scope
types list that refers to a namespace member type; it indicates the
declaration sequence position of the latter, providing information needed
by IL lowering to get the order right when promoting namespace types to the
file scope.

7/5/95  Repackaging in decls.c

Several repackaging changes have been made to routines in decls.c.  Most
notably, decl_var_or_routine has been divided into decl_variable and
decl_routine.  In addition, some code that had been in decl_var_or_routine
was moved to create_external_symbol_for_linked_entity and to new routine
set_name_linkage, and new routines compute_effective_decl_level and
find_linked_symbol have been broken out of id_linkage.

6/30/95  Error recovery problem with [], == and != operators

In some cases, an error on a [], ==, or != operator could cause an internal
error later.  Now fixed.

  typedef unsigned char cxb[150];
  static cxb rots[24];
  main () {
    if (rots[x] != 0) {}
    if (rots[rots[0]] != 0) {}
    if (rots[(void)*0] != 0) {}
  }

6/29/95  Missing placeholder typerefs

When template classes are instantiated inside other classes, the template
class itself is placed on the file-scope types list, and a placeholder
typeref (with is_placeholder_for_file_scope_type set) is placed on the types
list of the innermost class, to indicate the point at which the instantiation
was done.  That's useful (e.g.) in IL lowering to get the types in the right
order when types are promoted out of classes.  In some cases involving
instantiations in default argument expressions, no placeholder typeref
was put out, which means after IL lowering the types were not in the
"right" order, and as a consequence there could be ordering problems
(and therefore compilation errors) in generated C code.  Now fixed.

6/23/95  Static data member constants in templates

Static data member constants within templates are now treated properly
as constants during the "prototype instantiation" of the template.

  template <class T> struct A {
    static const T k = 15;
    int a[k];  // Got error previously
  };
  A<int> y;

6/23/95  Spurious incomplete type errors on some template parameter based types

Template parameter types are always supposed to be considered 
complete types.  Template parameter types that are members of other
template parameter types (such as T::I in the following example) were
incorrectly considered to be incomplete types.  This has been fixed.

  template <class T> struct A {
    typedef T::I I;
    I i[2];  // Incorrectly said that "I" was an incomplete type
  };

6/22/95  Overloaded function templates as arguments to function templates

An abort has been corrected on the case where a set of overloaded functions,
one of which is a function template, is passed as an argument to a function
template for a parameter that is a pointer to function.

  template <class T> void f(T **) {}
  void f(int) {}
  template <class T> void g(void (*)(T)) {}
  main () {
    g(f);
  }

6/22/95  IL lowering of constructors: improvement to aid minimal inlining

The process of wrapping a constructor inside an "if" statement, done
by IL lowering when the constructor calls "new", has been improved
slightly to avoid the insertion of an extra return statement when the
constructor has destructible local variables.  This allows inline.c to
inline calls to such constructors.

6/22/95  Minimal inlining: inlining of return using copy constructor

inline.c now allows inlining of calls of functions that return their values
via a copy constructor.

6/21/95  C++-generating back end: Pointers to members within member functions

Pointers to members must always have the form of a qualified name, e.g.,
&A::x.  The C++-generating back end unfortunately suppressed the
class qualifier when inside a member function of the class, thinking
it was unnecessary, and thereby produced &x, which is not valid.  Now
fixed by forcing generation of a qualified name for all occurrences
of pointers to members.

6/21/95  Template strings for template static data members

A bug has been fixed that caused template static data members with
brace enclosed initializers to omit the initializer when generating
the template string for the template static data member.  Template
strings are only generated when RECORD_TEMPLATES_IN_IL is TRUE
(usually only when using the C++-generating back end).

6/21/95  C++-generating back end: lvalue casts

Lvalue casts (as in pcc mode) are now output correctly.

6/21/95  C++-generating back end: Implicit casts on lvalue addresses

Implicit casts on lvalue addresses (e.g., to a base class or to adjust
qualification) are now suppressed.  This avoids an internal error
when such a cast appears on top of an enk_temp_init indicating the
address of a temporary.

6/20/95  C++-generating back end: member selections, pointer-to-member
         selections

The C++-generating back end now puts out ".", "->", ".*", and "->*"
operations in a way that avoids extra "&" and "*" operators when references
are involved.  Extra "*" and "&" operations can be a problem if the class
in question overloads those operators.

6/19/95  C++-generating back end: multiple variables declared in for-init

The C++-generating back end now correctly handles multiple declarations
of variables in a for-init, e.g.,

  for (int i = 4, j = 5; i < 10; i++) ...

6/17/95  Bug in dynamic_cast when virtual base class has non-zero offset

It is possible to create a class that does not itself have a virtual
function table pointer, and doesn't share a virtual function table pointer
with a base class, but nevertheless has a base class at a non-zero offset
within it that has a virtual function table pointer.  That base class
makes the outer class polymorphic, which means a dynamic_cast for that
class must use a runtime test.  When dynamic_cast was applied to such
a class, a base class adjustment was missing in a parameter to the
runtime routine, with the result that the base address of the complete
object was miscalculated.

6/16/95  Ambiguous base classes in runtime info with ABI <= 2.28

In ABI versions <= 2.28, the base class information given to the runtime did
not include ambiguous indirect base classes.  Those base classes were
added in 2.29.  Unfortunately, they had been included even when the ABI is
set to <= 2.28.  That doesn't work because it destroys the correspondence
between the base class list and the access string passed in at a throw (the
latter doesn't include the ambiguous indirect base classes).

6/16/95  Access to complicated virtual base classes in runtime base class info

The runtime base class information generated for exception handling and
RTTI contains access information for indirect base classes.  In some
complicated cases involving virtual bases, the access information was
not accurate.  Now fixed.

6/15/95  Complete object type of a typeid

node_complete_object_type has been changed so it can deal with an enk_typeid
node.

6/15/95  Conditional flag for temporary created by conversion from class
         type in conditional operand

The inside_conditional_expression flag was not being set in dynamic
initializations generated for conversions from class types in conditional
operands of &&, ||, and ? operators.  As a result, the temporaries created
in those cases were being destroyed unconditionally rather than only
when created.

6/15/95  Command-line options to turn off disabled features

Command-line options that turn off features are now accepted even when
the features are disabled (meaning they have been configured as turned
off and they can't be turned on).  For example, --no_rtti is now accepted
even when RTTI is disabled.  Others: --no_bool, --no_array_new_and_delete,
--no_wchar_t_is_keyword.

6/14/95  Exception problem with ABI <= 2.28

In version 2.29, typeinfo variables generated by IL lowering for non-class
types are static and unnamed.  When an ABI version of 2.28 or less
is selected, however, they are supposed to be external, named, and
uninitialized.  The "named" part was dropped on the floor in making the
changes, so such variables have been put out with generated names, which
means they are unlikely to match up across compilation units.  As a result,
a throw of an int cannot necessarily be caught in another file with a
catch of an int.  Now fixed, by restoring the names (and also making sure
that duplicate entries are not put out when typeinfo variables are
generated for multiple copies of the same type).

6/13/95  Use of a_scope_pointers_block in a_scope_stack_entry

Since namespace scopes, unlike other scopes, can be closed and then
reopened, some of the information that is normally kept in a scope stack
entry must now persist even after the scope is popped.  Such fields are now
part of a_scope_pointers_block, which is a substructure not only of
a_scope_stack_entry but also of a_namespace_symbol_supplement; macro
assoc_pointers_block_of has been provided to select the proper pointers
block for a given scope stack entry (either the embedded one or the one in
an associated namespace symbol supplement).  For instance, code like this

  var = scope_stack[depth].last_variable;

has been rewritten to use the macro:

  var = assoc_pointers_block_of(&scope_stack[depth])->last_variable;

6/12/95  IL CHANGE: added a_namespace, sck_namespace

A new IL entry, a_namespace, has been added to represent either a namespace
definition or, when the is_namespace_alias flag is TRUE, a namespace alias.
The scope associated with a namespace definition is of kind sck_namespace.

6/7/95   bitfield_to_avoid_codecenter_warnings

In 2.29 a change was made so that these bitfields would not be
included when checking code was turned off.  The way in which
this was done resulted in the extra semicolons after macro expansion
when compiling without checking code.  The macro and references
to the macro have been changed to eliminate the extra semicolons.

6/6/95   Command line options without keywords

If one defined a command-line option via a call of add_option_description,
and specified only a single-letter form and no keyword form (i.e., a null
pointer was passed for the keyword-form string), the command-line
processing routines would abort when processing options defined in
calls of add_option_description following that one.  Now fixed.

6/6/95   Type conversion on constant as template parameter

In some cases, conversions done for nontype parameters of templates could
result in an error constant appearing in the IL, which causes an internal
error in IL lowering.

  template <unsigned short inum1> class foo1 {};
  template <int ONUM1> class foo4 : public foo1<ONUM1> {};

6/6/95   IL CHANGE: class_of_which_a_member has been replaced

As part of the changeover to support namespaces, the field
class_of_which_a_member in a_source_correspondence has been eliminated.
Formerly, a non-NULL class_of_which_a_member pointer was the indication
that an IL entry was a class member; now you should check the new flag
is_class_member.  And when is_class_member is TRUE, the variant field
parent.class_type in the source correspondence substructure will give
the class of which the entry is a member.

A similar change has been made to a_symbol: class_of_which_a_member has
been replaced by is_class_member and variant field parent.class_type.

6/5/95   Redeclaring a function "inline" after it has been called

It used to be an error in all modes when an apparently noninline function
was called and then redeclared "inline" (see WP [dcl.fct.spec]).  Now we
issue a warning by default and a discretionary error in -A mode.

6/4/95   C++-generating back end: extern "C" on definitions

The C++-generating back end now puts out extern "C" on variable and
routine definitions as well as declarations.

6/2/95   Tracking class type uses that require a complete type

record_complete_class_type_needed (currently a stub macro in templates.h)
has been provided to enable an implementation to track uses that require
a complete class type.

5/31/95  Source sequence lists: "autonomous" flag on enum in degenerate
         typedef

The source sequence entry for an enum in a degenerate typedef that doesn't
define a typedef name is now marked as "autonomous".

  typedef enum foobar {foo, bar};
  class Foo { 
    foobar a_foobar;
  };

This affects those using source sequence lists, i.e., primarily those
using the C++-generating back end.

5/31/95  Linkage name on tagless enum defined in a typedef declaration

A tagless class defined in a typedef declaration receives a "name for
linkage purposes" (WP 7.1.3 [dcl.typedef]) -- in
CFRONT_OBJECT_CODE_COMPATIBILITY_MODE that is now the way similar
tagless enum definitions are handled, too:

  typedef enum { a,b,c } E;           // linkage name applied in cfront mode

The source_corresp.name field for the enum type is now "E" (in cfront mode
only; otherwise it is NULL).

Moreover, when CFRONT_OBJECT_CODE_COMPATIBILITY is selected the linkage
name is now applied, for both classes and enums, even when a cv-qualifier
appears in the typedef declaration:

  typedef const struct { int i; } S;  // linkage name applied in cfront mode

There is a tk_typeref type entry named "S" that preserves the const
qualifier -- and (in cfront mode only) a tk_struct type entry that also
has the name "S".  Formerly, this was done only for enums, and the
processing was in lower_name.c.  The processing for all cases is now
in the front end proper.

Note that these changes have an effect on mangled names.  The old
behavior in this area is preserved if ABI_COMPATIBILITY_VERSION is less
than 230.  Some of these changes were done in a second batch completed
8/17/95.

5/31/95  Template function matching bug involving pointer to member functions

A bug in the template matching routines resulted in the two calls of
f being diagnosed as ambiguous.  This has been fixed.

  template <class Ret, class Cls> void f(Ret (Cls::* const &f)());
  template <class Ret, class Cls> void f(Ret (Cls::* const &f)() const);
 
  struct A {
    int f();
    int g() const;
  };

  int main()
  {
    f(&A::f);
    f(&A::g);
  }

5/31/95  Type of template static data members not instantiated when needed

The front end failed to instantiate a template class that was referenced
only as the type of a template static data member.  In the following
example, A<int> was not being instantiated.  This has been corrected.

  template <class T> struct A { int a; };
  template <class T> struct B { static const A<T> ca; };
  template <class T> const A<T> B<T>::ca;
  B<int> b;

5/30/95  Internal error on access determination for virtual base class

An internal error could result on access determination for a virtual
base class where different derivation paths give different access and the
best access is available through a derivation other than the first.

  class A {
  protected:
    void f();
  };
  class B : virtual private A {
  protected:
    A::f;
  };
  class C : virtual private A { };
  class D : public B, public C { };

  main() {
    D d;
    d.f();  // Gets error, then got internal error
  }

5/30/95  Diagnostic on use of "long long"

The diagnostic issued for using "long long" in strict ANSI mode (-A) is
now a discretionary error.  In addition, a new warning in now issued for
printf/scanf format strings containing "%lld", "%llu", etc., in strict
ANSI mode.

5/29/95  Access of multiply declared member type

When a member type (a nested class, a typedef, or an enumeration) is
declared with one access and then redeclared with another, we now ignore
the access of the second declaration and issue a warning.

5/26/95  delete with a pointer-to-const operand

In strict ANSI mode a delete expression with a pointer-to-const operand
used to be an error; now it's allowed, in accord with a recent change to
the Working Paper.

5/26/95  mutable

Support for the mutable keyword has been added.  A new flag, is_mutable,
has been added to a_field.

5/25/95  Incorrect diagnostic in invalid instantiation

If a template parameter dependent base class attempts to use the
derived class in a context that requires a complete type, a
spurious "duplicate base class name" diagnostic may be issued.
This has been corrected, resulting in an appropriate "incomplete
type not allowed" diagnostic as indicated below.

  template <class T> struct A {
    friend void f(T){}  // T must be a complete type
  };
  template <class T> struct X : public A< X<T> > {};
  X<int> x;


5/25/95  "Delayed" definition of nested classes

The definition of a nested class outside its enclosing class is now
allowed in C++.

-------------------------------------------------------------------------------
Version 2.29, May 24, 1995

5/24/95  Exception specification on redeclared function

In certain cases a spurious error was issued when a function with
exception specifications was redeclared -- for instance:

  void f(int = 0) throw(int);
  void f(int) throw(int) { }    // Spurious error (inconsistent exception
                                //   specifications) has been eliminated

5/23/95  New-style casts

The new-style casts are now implemented:

  static_cast<type-id>(expr)
  reinterpret_cast<type-id>(expr)
  const_cast<type-id>(expr)

There is no separate command-line option for disabling these, as it was
judged that these keywords are unlikely to show up in existing code.

No IL changes were required for these.  However, we have delayed
implementing reinterpret_cast between pointers to members of unrelated
classes because that would require an IL change.  That conversion will
be implemented in the next release.

5/23/95  More efficient mechanism for recording array sizes in runtime

When an array is allocated by the new operator, the runtime needs to
record the size of the array so that it can be destroyed correctly
when it is deleted.  A more efficient mechanism for doing this is
now provided.  The old mechanism is still used for ABI versions
earlier than 2.29.  Strictly speaking, the mechanism for recording
this information is not an ABI issue, but the mechanism used can
change the behavior of programs that use certain undefined operations.
See the runtime Changes file for more information.

5/22/95  Cross-reference output for undefined identifier in constant expr

A reference to an undefined identifier in a constant expression now
produces a cross-reference entry for that error reference.

5/20/95  Warning on direct base class with a nonvirtual destructor

The diagnostic reporting that a direct base class has a nonvirtual
destructor is now suppressed in cases where calling the implicitly
generated derived class destructor and calling the base class destructor
are sure to have the same effect.

5/20/95  Checking callability of elided copy constructor on reference binding

When a reference is bound to an rvalue of class type, the WP [dcl.init.ref]
requires that the copy constructor that might have been used be callable.
That is now checked.  A warning is issued except in strict mode.

5/19/95  C++-generating back end: parentheses around initializer expression

The output of the C++-generating back end needed an extra set of parentheses
around a comma expression at the top of a parenthesized initializer:

  int i;
  int *p = new int((2, i));  // Output had only 1 set of parentheses

5/19/95  C++-generating back end: uninstantiated member functions

When the C++-generating back end is used, and it is configured to put
out instantiations of class templates, an internal error occurred
on the attempt to put out the declaration of an uninstantiated
member function of the class.  Now fixed.

5/19/95  Declaring a class a friend of itself

We now issue a warning instead of an error in -A mode when a class is
declared a friend of itself.

5/19/95  Bug in ctor_initializer

A bug has been fixed in ctor_initializer that could cause a null-pointer
failure during IL lowering.  It only appeared when compiling with both
--long_lifetime_temps and --exceptions.

5/19/95  Added support for based pointers in Microsoft mode

When microsoft_mode is TRUE, "__based" is recognized as a keyword in
pointer declarator contexts and the tk_pointer type entry is associated
with a variable entry.  Only the form __based(variable) is recognized,
where variable is of pointer type; the other (16-bit mode) forms are not.
A new variant field, base_variable, has been added to a_type.  Based
pointers are otherwise handled like ordinary pointers and are just passed
through to the back end.

5/18/95  Access checking on conversion functions

Access is properly checked now for conversion functions called for an
object of a derived class.

5/18/95  Branching past initialization of static local variable

No longer is an error issued on branching past dynamic initializations
of static local variables -- it is not justified by the wording in
WP [stmt.dcl], where only automatic variables are mentioned.

5/18/95  Problem with no-exception-lowering in IL lowering

When IL lowering is configured to do no lowering of exception handling
features, and a non-placement "new" operation is lowered, the code
generated sets a conditional flag to request the freeing of the storage
if an exception is thrown before the initialization is finished.
The code did not, however, reset the flag once the initialization is
finished.

  struct A {
    void *operator new(unsigned int);
    A();
  };
  A * p = ::new A;
  int *p = new int(7);

5/18/95  Redeclaring template parameters in nested scopes

An error is now issued in strict mode when a template parameter is
redeclared in a scope nested within a template.  Formerly, only a
warning was issued.  Errors have always been issued when a template
parameter is redeclared in the outermost scope of a template.

  template <class T> struct A {
    void f(int T);  // Now an error in strict mode
    int T;  // Always an error
  };

5/17/95  New global variable stack_referenced_include_directories

Configuration flag STACK_REFERENCED_INCLUDE_DIRECTORIES is no longer used
for conditional compilation; instead it is the default value for new global
variable stack_referenced_include_directories.  This enables running in
different include-file lookup modes based on command line options.  The
variable is always TRUE when microsoft_mode is TRUE (either by default or
because of compiling with --microsoft_mode); otherwise it takes on the
default value.

5/16/95  Inconsistent linkage specifications for variables

The severity of the diagnostic issued for inconsistent linkage
specifications for variables has been increased to a warning (and an error
in -A mode).  (Such inconsistencies for functions continue to be reported
as errors in all cases.)

5/16/95  Setting the IL referenced flag for nested types

The IL referenced flag is no longer automatically set for nested class and
enum types -- except for nested anonymous unions, which (at least for the
time being) continue to be marked as "referenced" at the point of
declaration.

5/16/95  Mixing tag kinds in cfront-compatibility mode

We now permit elaborated type specifiers for a class to mix union and
struct/class tag kinds in cfront compatibility mode:

  union S { int i, j; };
  struct S x;              // Only a warning in cfront mode

5/16/95  Using typedef names in explicit destructor calls

In cfront mode, typedef names may now be used in explicit destructor
calls.

5/16/95  Template argument deduction; references to arrays and functions

In template argument deduction, a parameter will now not be deduced to
be a reference to an array or a reference to function if it isn't that
already.  For example, a parameter of type "const T&" matched up with
an argument that is a character string will be deduced as "char *&"
instead of "char (&)[n]".  On the other hand, if the parameter were
"T (&)[n]", "char (&)[n]" would be deduced.  This doesn't match the
WP precisely (in fact it's wrong according to the WP), but it makes
sense (since references to arrays and functions are pretty unusual)
and is exploited by one of the tests ObjectSpace provides for STL.

5/13/95  Dead expressions under conditional operators are retained

Dead expressions under the conditional operators &&, ||, and ? are
now retained.  For example, "1 ? i : j" is no longer transformed
into simply "i".  This is more in keeping with our general philosophy
of not altering or optimizing the program.  The old behavior can be
gotten by setting ELIMINATE_DEAD_CODE_UNDER_CONDITIONAL_OPERATORS to TRUE.

5/13/95  Spurious used-before-set warning eliminated

A spurious used-before-set warning has been eliminated for cases like
the following:

  main() {
    char* p;
    char* q = "hello";
    (p = q)++;  // Got warning on using p before it is set
  }

5/4/95   operator new[] and operator delete[]

Declarations of operator new[] and operator delete[] are now accepted,
and ::operator new[] and ::operator delete[] declarations are implicitly
generated by the front end.  This requires setting the flag
ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE, which makes some upward-compatible
changes in the ABI: new library routines, __array_new and
__array_delete, are called for some new cases, and new routines for
global "operator new[]" and "operator delete[]" are called for
array allocation and deallocation in general.  If the ABI changes
are turned off, the language features are disabled.  There are also
command-line options --array_new_and_delete and --no_array_new_and_delete,
and the default for those is DEFAULT_ARRAY_NEW_AND_DELETE_ENABLED.

Note: "new[]" and "delete[]" are each treated as three tokens; it is
probably an error in the current working paper [lex.key] that "new[]",
"new<%%>", "delete[]", and "delete<%%>" are included in the
processing-op-or-punc list -- a formal X3J16/WG21 resolution (Boston 2.2)
appears not to have been properly incorporated.

The name mangling codes for new[] and delete[] are "nwa" and "dla",
respectively.  The demangler has been changed to recognize them.

5/12/95  IL CHANGE: Arguments for two-argument delete in unlowered IL

The "arg" field in a_new_delete_supplement used for a delete in the
two-argument form formerly pointed to a list of expressions --
the second was the size.  Now it is just a single expression.  Specifying
the size does not extend well to the "operator delete[]" case, and so
it is now left out of the unlowered IL, and IL lowering generates the
second argument.

5/12/95  Type qualifiers in Microsoft mode

Type qualifiers are now allowed in certain nonstandard places
in Microsoft mode.  For example:

  int i, const j;

The diagnostic for duplicate type qualifiers has been demoted to
a warning in Microsoft C mode.

5/11/95  Diagnostic on uninitialized empty-class object

We used to suppress the diagnostic on failing to initialize a const
object when its type was an empty class; now we issue a warning (or an
error in -A mode).

5/11/95  Diagnostic on typedef redeclaration

The error message issued for attempting to redeclare a typedef name with a
new type now notes the source position of the original declaration.

5/11/95  Removal of top-level cv-qualifiers from function parameter types

Top-level qualifiers are removed from function parameter types (see changes
of 1/16/95 and 1/20/95) only if ABI_COMPATIBILITY_VERSION is greater than
or equal to 229.  In versions before 2.28, the qualifiers were retained
in all modes.  In 2.28, to implement a change in the language definition,
the qualifiers were dropped, but not in cfront mode.  This introduced an
unfortunate name mangling incompatibility in the default mode, and it made
cfront mode and the default mode link-incompatible in some cases.
We've now integrated this change with the ABI_COMPATIBILITY_VERSION
mechanism, and we've made cfront mode work the same as the default mode.
Note that if you set ABI_COMPATIBILITY_VERSION to 228, you get the
behavior we think in retrospect we should have provided in 2.28, not what
the actual 2.28 provided.  Also note that if you set ABI_COMPATIBILITY_VERSION
to 229 or greater, and use cfront mode, the generated code is not link-
compatible with the real cfront; however, that's true for other reasons
too (e.g., extra virtual function tables for RTTI).

5/11/95  Non-null test on pointer on call of user-written operator delete

The change of 1/26/95 has been undone.  It's now clearer that the
!= NULL test must be done by the user-written operator delete.

5/10/95  Use of prototype instantiation vs. nonreal instantiation

The way in which the front end decides whether a reference such
as B<T> refers to the prototype instantiation or a nonreal
instantiation has been improved.  Previously, the front end
would sometimes use the prototype instantiation when a nonreal
one should have been used.  This could result in spurious errors,
as in the following example where the front end complained that
"N" is not a member of "B<T>".

  template <class T> struct B {};
  template <class T> struct A {
    B<T>::N f();
  };
  template <class T> B<T>::N A<T>::f(){}

5/10/95  Use of a local type in a block extern declaration

In C++ mode an error is now issued (instead of a warning) if a class or
enumeration type that is local to a function is used in a block extern
declaration.  Moreover, such use now includes appearing in the type-id-list
of an exception specification.

5/10/95  Block extern variable declaration with initializer in K&R mode

We no longer fail to issue a diagnostic in K&R mode for cases like this:

  void f() {
    extern int i = 0;       // Error now issued in K&R mode
  }

5/10/95  Referenced but undefined member functions

An undefined member function of a local class is now reported as an error
only if it is actually referenced:

  main() {
    struct S {
      void f();       // Error -- referenced but not defined
      void g();       // No error -- never referenced
    } s;
    s.f();
  }

Some bugs have been fixed in this area as well.  The checking of member
functions of unnamed classes and nested classes has been improved, not
only for local classes but also for file-scope classes with member
functions declared "inline".  For instance, in the following an error is
now issued on referenced but undefined inline function S::T::f():

  struct S {
    struct T {
      inline void f();       // Never defined
    } t;
  } s;
  void g() { s.t.f(); }

5/10/95  integer->x in pcc mode

In pcc mode, a selection of the form integer->x, where integer is an
integral-typed expression, is now allowed, so long as there exists a
member "x" or several members "x" all of which have the same offset.
A warning is issued.

5/10/95  References for bad member selections

On a selection a.b or p->b where no "b" exists in the class, an undefined
symbol is now created and an error cross-reference to it is now put out.

5/10/95  Small improvement in inlining

Inlining now allows inlining of functions containing a return statement
that isn't the last statement of a function, so long as it is the last
statement in a block that is the last statement in a block ... that is
the last statement of the top-level block of the function.

5/10/95  Internal error instantiating a template with duplicate definitions

An internal error would result if a set of overloaded functions in a
class template contained a function that was erroneously redeclared.
This has been fixed.

  template <class T> struct A {
    void f(T);
    void f(char);
    void f(T);
  };
  A<int> a1;

5/9/95   Partially-lowered EH code: set cleanup position at unreachable ends
         of blocks

In the partial-lowering modes for exception handling, an instruction
to set the cleanup position is now emitted at the ends of blocks if
the end is unreachable.  This is useful if the leck_cleanup_state
instruction is used by a back end to generate a table of addresses
instead of instructions that update the state.

5/9/95   Nontype template parameters may be used in function templates

Function templates may now make use of nontype template parameters.

  template <int I> struct A {};
  template <int I> void f(A<I>);

5/9/95   for-init declaration marker in source-sequence list

When GENERATE_SOURCE_SEQUENCE_ENTRIES is TRUE and a for-init-statement
consists of a declaration, an end-of-construct entry (pointing to the
stmk_decl statement) is inserted in the source sequence list immediately
after the source-sequence entry that represents the declaration.  This
marker is required in case a for statement has both a for-init
declaration and a condition declaration.

5/9/95   Qualifier problem in generated ANSI/ISO C for reference to array
         with qualified element type

A bug in generation of ANSI/ISO C code produced code that was invalid
in that it required an implicit conversion that is not allowed in C.
This has been fixed by adding a cast.  The error cases involved
arrays with qualified element types that were initialized in a way
that requires executable code, and subsequent binding of a reference
to the array:

  void f()
  {
    int i; i = 1;
    const char a[4] = "abc";
    const char (&r)[4] = a;
  }

5/8/95   Setting the "referenced" flag on volatile variables

The referenced flag in the variable entry is no longer automatically set
on non-defining declarations of variables of volatile-qualified type:

  extern volatile int x;       // Not marked as referenced

5/6/95   New files il_alloc.c and il_alloc.h

Routines relating to the allocation and initialization of IL entities
have been moved out of il.c and into a new file il_alloc.c.  il_alloc.h
contains the associated declarations.

5/2/95   bool

The bool type is now implemented.  bool, true, and false are new keywords.
The feature is enabled by --bool and disabled by --no_bool; the default
is established by DEFAULT_BOOL_IS_KEYWORD.  A preprocessing flag (by
default _BOOL) indicates whether or not the feature is enabled, so
header files can be self-adjusting.

The IL contains a new operator, eok_bool_cast; it is rewritten (as a
"!= 0" test) by IL lowering.  Operations like "!=" return bool, and
IL lowering rewrites that to C form as well.

The name mangling code for bool is "b".

5/2/95   Maximum class size (again) and maximum base class offset

A new configuration flag, TARG_MAX_BASE_CLASS_OFFSET, has been added,
along with its associated global variable, targ_max_base_class_offset.
If the offset at which a base class is allocated within the derived class
exceeds targ_max_base_class_offset, an error is issued.

When TARG_MAX_BASE_CLASS_OFFSET is zero, a very large value is assigned
to targ_max_base_class_offset.  When it is configured to a nonzero value,
that is the value to which targ_max_base_class_offset is set -- except
that, when DO_IL_LOWERING is TRUE, a smaller value will be used, if
necessary, to accommodate the maximum offset value (as implied by
TARG_DELTA_INT_KIND) that may be stored in a virtual function table or
pointer-to-member structure.

A similar computation that was applied to targ_max_class_object_size
(see Changes entry for 2/28) is no longer done -- in other words,
targ_max_class_object_size is no longer adjusted to account for
TARG_DELTA_INT_KIND.

5/1/95   TARG_ALL_POINTERS_SAME_SIZE may now be set to FALSE

You may now configure TARG_ALL_POINTERS_SAME_SIZE to FALSE, but if so
TARG_SIZEOF_POINTER and TARG_ALIGNOF_POINTER are no longer defined and you
will need to look closely at the configuration values that by default are
dependent on them.  Moreover, global variables targ_sizeof_pointer and
targ_alignof_pointer are not defined when TARG_ALL_POINTERS_SAME_SIZE is
FALSE; in their place we now use a new routine, size_of_pointer_to, which
you will need to customize according to the requirements of your target
environment.

5/1/95   Configuring a "pointer to virtual base class" class member

Two new configuration flags, TARG_SIZEOF_PTR_TO_VIRTUAL_BASE_CLASS and
TARG_ALIGNOF_PTR_TO_VIRTUAL_BASE_CLASS, and their corresponding global
variables, are now defined.  They are used to specify the attributes of a
class member that is a "pointer" to a virtual base class; it is up to the
implementation whether such a field is actually of pointer type.

4/30/95  Incomplete array fields in Microsoft C mode

"[0]" may be used in place of "[]" to declare a final field of incomplete
array type in Microsoft C mode -- e.g.,

  struct S { int a,b,c[0]; }     // c[0] is equivalent to c[]

4/29/95  Support for __int32 and __int64 keywords (Microsoft extension)

In Microsoft compatibility mode __int32 and __int64 are recognized as long
as there are integer kinds with exactly the right number of bits to which
they can be mapped.  For example, in some typical configurations __int32
would always be accepted (it would map to ik_int or perhaps ik_long), but
__int64 would be accepted only if LONG_LONG_ALLOWED were TRUE (in which
case it would map to ik_long_long).

4/28/95  Disambiguation of cast vs. expression

Formerly, an expression of the form (A()) was always treated as a cast,
even if no expression followed (in which case an error was issued).
Now, expressions like (A()) are only considered casts if they are
followed by an expression, as in (A())+1.

4/28/95  Disambiguation and Microsoft __declspec modifiers

__declspec modifiers used in a context that requires a lookahead
to disambiguate between a declaration and an expression could result
in the loss of the __declspec modifiers.  This has been corrected.

  int main()
  {
    int(*i)(__declspec(naked) int j);
  }

4/28/95  Function redeclarations in Microsoft C mode

In Microsoft C mode only a warning is issued for redeclaring a function
with an incompatible type.  When this results in two routine entries with
the same name, one will be marked as "superseded" (as in SVR4 C mode).

4/28/95  Alternate versions of Microsoft keywords

_cdecl, _fastcall, _inline, and _stdcall are treated as synonyms for
__cdecl, __fastcall, __inline, and __stdcall.

4/27/95  Default arguments allowed for type template parameters

Type template parameters may now have default template arguments.
Previous template parameter names may be used in the default
argument.  Formerly, only nontype parameters could have default
arguments.

  template <class T = int, class T2 = T> struct A {
    T t;
    T2 t2;
  };
  A<> a;

4/27/95  IL CHANGE: support for condition declarations in C++

Condition declarations in if-, switch-, while- and for-statements are now
supported.  A new expression node kind, enk_condition, has been added,
along with a_condition_supplement and a new scope kind, sck_condition.
IL lowering rewrites these into C form, so those using IL lowering
will not see the new constructs.

4/26/95  Discretionary nonstandard errors

The errors for a nonstandard preprocessing directive and the nonstandard
comma at the end of an enumerator list have been made discretionary errors.

4/25/95  Typeinfo base class lists

The base class lists on typeinfo information (used for exception handling
and RTTI) now include ambiguous base classes even if they are not
direct base classes, and include information on access to the base
classes.

4/25/95  Diagnostic/reference positions on new and operator() calls

The position of diagnostics and symbol references has been changed in
two cases:

(1)  On uses of operator new, diagnostics/references that came out on the
     placement term now come out on the keyword "new".
(2)  On uses of operator(), the call position is now considered to be the
     left parenthesis instead of the position of the class operand preceding
     the left parenthesis.

4/24/95  Diagnostics on exception specifications with --no_exceptions

When exception support is disabled (either as the default or by the command
line option) exception specifications are now ignored (that is, no diagnostic
is issued) when the function is an inline function or the declaration does
not entail a definition.  This allows the same header to be processed either
with or without exception support enabled.

4/22/95  dynamic_cast and typeid

The dynamic_cast and typeid operators (part of RTTI) are now implemented.
There are new IL expression nodes of kind enk_typeid and operator nodes
of kind eok_dynamic_cast.  These are rewritten by IL lowering.
New runtime routines __dynamic_cast, __dynamic_cast_ref, and __get_typeid
are required (and provided in our runtime).

Element [0] of virtual function tables now contains a pointer to the
typeinfo for the complete object class type associated with that virtual
function table.  This makes it possible to determine the type of a
polymorphic class object at runtime.  However, it also means more
instances of virtual function tables are required, because a separate
instance is required for base-class-in-derived-class even if the
derived class does not override any functions in the base class.

ABI_CHANGES_FOR_RTTI must be TRUE if you want to be able to use
these features with IL lowering, and the ABI changes break binary
compatibility, so you'll have to make your own decision about when
and if to make these features available to your users.

4/22/95 __throw_setup

The runtime routine __throw_alloc has been replaced by __throw_setup,
which has one fewer argument.  The access string argument is no longer
required, because the language definition has been changed to allow
simpler access checking for throws at runtime.

4/21/95  Incorrect line numbers when using precompiled headers

If the last preprocessing directive included in a precompiled header file
included continuation lines, line numbers reported by the front end
in diagnostics and __LINE__ directives were incorrect.  This has
been fixed.

  #define X(a) \
                a \
                a \
                a
  int i = __LINE__;  // Incorrect value when using a PCH

4/20/95  Setting autonomous_primary_tag_decl flag in template class

If source sequence lists are being generated, autonomous_primary_tag_decl
is always set to TRUE for a class created from a template instantiation,
regardless of the kind of reference that triggers the instantiation.

4/19/95  Parsing "overload" declarations inside a class definition

A bug has been fixed in parsing a declaration involving the "overload"
keyword (an anachronism) when it appears inside a class definition.

4/19/95  asm statements in Microsoft mode

In Microsoft mode asm statements of the form

  __asm assembly-instruction
  __asm { assembly-instruction-list }

are now supported, where assembly-instruction is unquoted text.

4/19/95  Using "long long" for host integer operations

It is now possible to use integral types larger than a host long
as an_integer_value.  There were a few places in const_ints.c that
assumed that an_integer_value would not be larger than a host long.
These have been eliminated.

4/14/95  Passing configuration information to the runtime

The --building_runtime command line option has been added.  This causes
the front end to create additional predefined macros that represent
target configuration information.  For example, the setjmp jmp_buf
element kind and number of elements are now passed to the runtime
using the predefined macros __EDG_JMP_BUF_ELEMENT_TYPE and
__EDG_JMP_BUF_NUM_ELEMENTS.  The value of ABI_COMPATIBILITY_VERSION
is passed in the macro __EDG_ABI_COMPATIBILITY_VERSION so that the
runtime can automatically configure itself appropriately for a given
version of the front end.

4/13/95  Off-by-one bug in using targ_max_class_object_size

When N was defined to the value of targ_max_class_object_size, the
following was not accepted (but now it is):

  struct S { char x[N]; }

In a related change, the upper limit for targ_max_class_object_size, when
it is computed based on TARG_DELTA_INT_KIND (see target_init in fe_init.c),
will no longer be used to increase the configured value, only to reduce it.

4/13/95  IL CHANGE: superseded_external flag in a_variable and a_routine

Because we now issue warnings instead of errors in SVR4 C compatibility
mode for certain type-incompatible "block extern" declarations, we have
added a new superseded_external flag for the extra variable and routine
entries that result.  Here's an example:

  void f() { extern float x; }
  void g() { extern int x; }       // SVR4-mode warning on incompatible
                                   //   redeclaration.

In this case two variable entries are created for "x", with the first
marked as "superseded".

4/13/95  typeinfo structure changes

The typeinfo structure has been enhanced for use with RTTI.
It now contains the user-visible type_info part and a pointer to
a name string, and the base class specifications have several
additional flags.  The old form is still available by setting
ABI_CHANGES_FOR_RTTI to FALSE (but that will disable RTTI features too).

4/12/95  C-generating back end: address of redeclared function

The C-generating back end now checks, when putting out the address of
a function for an enk_routine_address expression node, that the type
indicated in the node matches the function type.  If it does not,
a cast to the right pointer-to-function-type is inserted.  This is
useful when a routine is declared several times in compatible but
not identical ways, and called in range of several different declarations.

4/12/95  Lvalue casts in Microsoft mode

Lvalue casts are permitted in Microsoft mode (including in C mode casts
involving integral types of unequal size).

4/11/95  Use of incomplete enum type in Microsoft mode

In Microsoft mode an enum type for which no definition has yet been seen
may be used as though it were a complete type -- for example:

  enum E x;                    // Okay in Microsoft mode.
  void f(E e) { return e; }    // Okay in Microsoft mode.

In a related change, targ_enum_types_can_be_smaller_than_int is always set
to FALSE in Microsoft mode; this enables assigning a size -- namely,
sizeof(int) -- to an incompletely defined enum type.

4/11/95  Initialization of incomplete-array fields in Microsoft C mode

If a struct is the top-level type of an object being initialized and was
declared with a final field that is of incomplete array type, that field
can now be initialized in Microsoft C mode:

  struct S {
    int i, j;
    int a[];                   // In C mode: error in strict ANSI mode but
  };                           //   otherwise okay
  struct S x = { 0,0,0,0 };    // Okay in Microsoft C mode -- otherwise, too
                               //   many initializer values.
  struct S y = { 0,0,0 };      // Ditto.

Note:  sizeof(x) == sizeof(y) == 2*sizeof(int).  That is, initializing
x.a as a two-element integer array does not affect the compile-time size
of the object.  Furthermore, the type of x.a continues to be an incomplete
type.

4/7/95   Initialization of auto aggregates in Microsoft C mode

Support is now provided in Microsoft C compatibility mode for initializing
an auto aggregate variable with an initializer list containing nonconstant
initializers -- for instance:

  void f(int i) {
    int a[2] = { i, i+1 };
  }

NOTE: The IL representing this construct is a dik_nonconstant_aggregate
dynamic init entry.  Normally, such entries only appear in unlowered C++
IL.  We intend eventually to add a call to an IL lowering routine (such as
lower_dynamic_init) to represent this construct in ordinary C IL, but for
now back ends will have to deal with it in the unlowered form. [8/28/95:
see LOWER_MICROSOFT_NONCONSTANT_AGGREGATE, set TRUE by default]

4/7/95   Declaring static data members as member constants

A static data member declaration inside its class definition may now
specify an initializer if the member has const integral type (see 9.5.2).
The new is_member_constant flag in a_variable is set for the associated
variable entry.  (Note: a variable representing a static data member may
now have an init_kind of initk_static even though it has not been defined.)

4/6/95   Casts of pointer-to-data-members to related classes

The recent change of representation for pointers to data members (in 2.28)
makes pointers to data members unsigned (even if the same size as
before, i.e., sizeof(short), is selected).  A bit of code generated
by IL lowering to do casts of pointers to data members to related
classes was, as a consequence, adding a very large number in cases
where it was attempting to add a negative offset to such a pointer.
This worked okay if the size of pointers to data members was the same
as int or long, but not if it was the same as short.  The code now
uses a subtraction to adjust the offset in that case.

4/6/95   Bug with default arguments in --long_lifetime_temps mode

Temporaries required in default argument expressions had been
incorrectly made static when --long_lifetime_temps is set.
Now fixed.

4/6/95   Use of "//" as a comment delimiter in C mode

In Microsoft compatibility mode, "//" is now recognized as a comment
delimiter.  In addition, END_OF_LINE_COMMENTS_ALLOWED_IN_C_MODE can be
set to enable such recognition generally in C mode, except when strict
ANSI/ISO C is specified.

4/6/95   ABI_COMPATIBILITY_VERSION

Since we are beginning to add language features that have an effect
on release-to-release binary compatibility, we have added a mechanism
to deal with ABI changes.  If you set ABI_COMPATIBILITY_VERSION to a
version number (e.g., 228 for 2.28), ABI changes made after that version
will be suppressed.  Of course, language features that require those
ABI changes will also be suppressed.  This allows you to delay
all ABI changes and associated language changes to a single release
of your choice in the future.  The default setting of
ABI_COMPATIBILITY_VERSION -- a large value -- requests the latest
version of the ABI at each release.

The first use of this flag is for RTTI: see ABI_CHANGES_FOR_RTTI,
which is enabled for ABI_COMPATIBILITY_VERSION >= 229.

4/5/95   Binding of a next-construct pragma

When a declaration involving an elaborated-type specifier of the form enum
E followed a bind-to-next-construct pragma, the pragma was improperly bound
to the enum type.  This has been fixed.

  enum E { a, b, c };
  #pragma xxx              // "xxx" binds to next construct
  enum E e;                // the pragma now binds to variable e rather
                           //   than to type E.

4/5/95   Enhanced support for #pragma pack

It is now possible to maintain a stack of pack alignment values using
"push" and "pop" with #pragma pack.  The syntax and semantics are
consistent with what is supported by the Microsoft C and C++ compilers.
For example:

  #pragma pack (push, xxx)
  #include "xxx.h"
  #pragma pack (pop, xxx)

which has the effect saving the current pack alignment value, processing
the include file (which may leave the pack alignment with an unknown
setting), and restoring the original value.  This is only available, of
course, when USER_CONTROL_OF_STRUCT_PACKING is TRUE.

4/5/95   Identifier lookup when caching pragma tokens

When caching pragma tokens, identifiers must be looked up, otherwise
it is impossible later to know the name of the identifier that was
scanned.  Formerly, identifiers were only looked up when the pragma
flag processing_C_code_in_pragma was TRUE.  Now, identifiers are
always looked up for pragmas that are saved as token caches.  The
processing_C_code flag is now used to specify whether other processing
specific to C/C++ code should be performed, such as recognition of keywords.

This change should not result in a change in behavior of existing pragmas.
Existing code need only be changed if certain pragmas should not recognize
keywords.

4/5/95   Cfront compatibility: conversions of class operands to pointer type
         when they are operands of builtin operators

A small adjustment in cfront mode: for class operands of builtin operators,
conversions to pointer or pointer to member types are now considered only
if the other operand has a pointer or pointer to member type.

4/4/95   Handling of incompatible routine redeclarations SVR4-C mode

If two otherwise compatible routine declarations differ in their return
types, and if the latter are integral and "interchangeable" (i.e., have
the same size and alignment), a warning rather than an error is issued in
SVR4-C mode.  (This behavior is more restrictive than in version 2.28;
i.e., errors are now issued in more cases.)

4/4/95   Abort in prototype instantiation of invalid class template

A bug has been fixed that could cause an abort during the prototype
instantiation of a class template in which the class name is an invalid
qualified name.

  template <class T> struct A::B {
    B();
  };

4/3/95   #pragma ident in local scope

When #pragma ident and #ident appear inside a function, the constant entry
created for the string is now allocated in the file-scope memory region.

4/3/95   Option name changed: --alternate_tokens is now --alternative_tokens

The name of the command line option, and variables in the front end,
have been changed from "alternate" to "alternative" to match the
wording in the working paper.

4/3/95   Handling of "detected during" prefix in error context messages

Formerly, the "detected during" prefix was hard-coded in error.c.
Now, separate versions of the context messages are supplied: one that
includes the prefix and one that does not.  This was done to simplify
the use of message catalogs for error messages.

4/3/95   IL lowering: conditional flag initialization for expressions
         tested in loops

If the expression tested in a loop requires conditional flags to
control destruction of temporaries created within the expression, the
conditional flags are now initialized at the beginning of the expression,
rather than at the beginning of the scope.  When initialized at the
beginning of the scope, they weren't reset each time around the loop.

4/3/95   Changes for VMS and Open VMS

The VMS specific code has been updated to be compatible with the
more recent versions on VMS C that more closely resemble ANSI C.
We don't have a VMS system on which to test these changes, so please
let us know if you experience any problems with these changes.

3/31/95  Support for Microsoft bit field allocation

When TARG_MICROSOFT_BIT_FIELD_ALLOCATION is configured to TRUE, bit-field
allocation occurs in two steps -- a container of the bit-field type is
allocated, and then the bit field itself is allocated within it.  When
successive bit fields are declared to have the same type, they can share
the same container (if space permits).  When there's not enough room, or if
the declared type changes, a new container is allocated.  By default, this
flag is set when MICROSOFT_EXTENSIONS_ALLOWED is TRUE.

3/31/95  follows_an_exec_statement flag in dynamic init following case label

If the first thing inside a switch is a case label or default label,
and if the first thing following that is an initialized variable declaration,
the dynamic initialization for the variable did not have
follows_an_exec_statement set to TRUE.  It does now.

  switch (l) {
    default:
      int n = 99;
      break;
  }

3/31/95  Type qualifiers on argument to "this" parameter

In some cases, the argument passed to a "this" parameter did not
have exactly the same type as the "this" parameter (it was missing
some type qualifiers).  A cast is now emitted.

3/31/95  PCH files and compiling files in different directories

When determining whether a given PCH file is a candidate for use by
a given compilation, the directory of the primary source file should
have been taken into account, but was not.  This could cause a PCH
file to be used when it actually represented the wrong version of
an included file.  This has been fixed.

3/31/95  Promotion cost of enum --> int on operand to builtin in overload
         resolution

When considering a builtin operator in overload resolution, and given an
enum operand, the cost for the operand is always a promotion, because
the enum --> int promotion must be done to make the operand suitable for
the builtin operator.  2.28 had made the cost an exact match sometimes.
In cfront modes, enums are treated as normal integers.

3/31/95  IL lowering promotion of local entities done after EH tables
         generated

The promotion of local entities out of functions is now done after
the generation of any tables required for exception handling, so
that it is possible, if one wishes, to promote those tables out of the
function.

3/31/95  cp_gen_be handling of default argument for parameter passed via
         copy constructor

The following case, involving a default argument expression for a parameter
passed via a copy constructor, gave an internal error in the C++-generating
back end.  Now fixed.

  struct A {
    A(const A&);
    A(int);
  };
  void f(A p = 0);

3/29/95  Support for __unaligned (Microsoft extension)

When MICROSOFT_EXTENSIONS_ALLOWED is TRUE __unaligned is recognized as a
keyword and accepted as a type qualifier.  There is no special handling
-- it's just passed through to the back end as part of the qualifier set.

3/28/95  Microsoft __try/__finally, __try/__except, and __leave

When MICROSOFT_EXTENSIONS_ALLOWED is TRUE, The Microsoft Structured
Exception Handling statements are recognized.  They have the form

   __try { statements } __finally { statements }
   __try { statements } __except(expr) { statements }
   __leave;

3/28/95  Generating a preprocessed source file with implicit inclusion

Formerly, when generating a preprocessed source file, it was not possible
for the preprocessed source to include implicitly included files that
may be needed for template instantiation purposes.  The new --no_preproc_only
command line option may be used in conjunction with the options that
generate preprocessed output to create a preprocessed output file
as part of performing a full compilation.  This preprocessed output
will include any implicitly included files.

3/28/95  MICROSOFT_KEYWORDS_ALLOWED subsumed into MICROSOFT_EXTENSIONS_ALLOWED

The configuration flag MICROSOFT_KEYWORDS_ALLOWED, which controlled things
like __cdecl, has been eliminated, and the things controlled by that
flag are now controlled by MICROSOFT_EXTENSIONS_ALLOWED.

3/25/95  Abort in strict mode after user error related to nonconst constructor

An abort on the following in strict mode has been corrected:

  struct A {
    A();
    A(A&);   // Note nonconst
    A operator+(A);
  };
  A f(A);
  A f(A a, A b) {return a + b;}
  void bar(A a)
  {
    f(f(f(a)));
  }

This is another existing bug exposed by the change in 2.28 to disallow using
a nonconst copy constructor to copy rvalues.

3/24/95  Handling of invalid PCH directory

Formerly, if an invalid directory name was specified as the argument to
the --pch_dir option an internal error would result when the directory was
accessed.  An error message is now issued instead.

3/24/95  Template instantiations using typedefs from prototype instantiations

A bug has been fixed that could cause either an abort or the generation
of invalid IL if the initial reference to a class template instance
included a template argument that was a typedef defined in a prototype
instantiation.

  template <class T> struct A {
    T t;
  };

  template <class T> struct B {
    typedef int x;
    A<x> a;
  };

3/23/95  Slight improvement in adding indirections

The routine add_indirection_to_node has been generalized by
incorporating some of the special case coding from conv_lvalue_expr_to_rvalue.
One effect of this change is that the following now has an
eok_extract_bit_field instead of the (unusual) combination of an
eok_indirection over an eok_bit_field.

  struct S {
    int n:16;
    virtual void foo();
  };
  void S::foo()
  {
    S s = *this;
  }

3/23/95  Building the front end on SunOS using an ANSI C compiler

A problem has been fixed that could cause compilation errors when
using an ANSI C compiler and header files on a system that requires
compilation with the __BSD__ flag set.  Previously, the __BSD__
flag would result in the definition of macros for memcpy and memcmp.
This is now only done when not using an ANSI C compiler.

3/21/95  Implicit scope for dependent statements in cfront 3.0 mode

Now it is only in cfront-2.1 compatibility mode that the dependent
statement of an if, while, do-while, or for statement does not implicitly
define a scope.  In cfront-3.0 mode, the behavior is now consistent with
standard C++.

  void f() {
    int i;
    if (i)
      for (int i=0; i<10; i++) { }  // Error in cfront 2.1 mode but now
  }                                 //   okay in cfront 3.0 mode

3/20/95  Type compatibility of known- and unknown-bound arrays in C++

Now two array types with the same element type and of known- and
unknown-bounds are considered compatible only for top-level types and only
in the context of redeclarations.  For example,

  extern int a[];
  int a[3];               // still okay
  extern int (*p)[];
  int (*p)[3];            // now an incompatibility error in C++

3/20/95  --nonconst_ref_anachronism

Binding a reference to nonconst class to a class rvalue of the right type
or a derived type thereof, allowed up until version 2.28, and now an
anachronism, can now be allowed and disallowed through command-line
options --nonconst_ref_anachronism and --no_nonconst_ref_anachronism.  The
configuration flag DEFAULT_ALLOW_NONCONST_REF_ANACHRONISM specifies the
default (TRUE in the release).

  struct A {
    A(int);
    A operator=(A&);
    A operator+(const A&);
  };
  main () {
    A b(1);
    b = A(1) + A(2);   // Allowed as anachronism
  }

3/20/95  Checking callability of elided copy constructor

When a copy constructor call is elided, the WP requires that the
elided copy constructor be callable.  We have been checking access,
but we now also check that the copy constructor parameter can be bound
to an rvalue, which is necessary if one were to call the copy
constructor.  This check is only done in strict mode.

  struct A {
    A(A&);
    A(int);
  };
  A a(1);
  A b = 1;   // Error in strict mode
  struct B {
    B(int);
    B(const volatile B&);
  };
  B bb = 1;  // Error in strict mode

3/18/95  Display of qualified version of qualified array type

il_to_str.c has been changed to deal correctly with the display of qualified
versions of typedefs of qualified array types.  This is a refinement
of a change made in 2.28.

  typedef const int A[4];
  void f(volatile A&) {}
  int f;  // Provokes error that displays type of previous f

3/18/95  Putting out ellipsis-only param list in generated C

A new configuration flag, ALLOW_ELLIPSIS_ONLY_PARAM_IN_GENERATED_C, may be
set to TRUE to cause "(...)" to be put out as the parameter list for a
routine with no parameters but with has_ellipsis set to TRUE.

3/17/95  Builtin operators in overloading: subtleties of pointer types

The signatures provided in [over.built] of the WP use pointers to
complete object types and pointers to functions as well as generic
pointers.  The pointer type restrictions are now implemented when
looking for conversion functions to use with operands of builtin
operators.

3/17/95  Indirection through void* in C++

In ISO C, you can write

  void *p; *p;

And it's valid (but *p is not an lvalue).  We've been wondering for some
time whether C++ would follow C in this special case, and we've concluded
that the WP is now clear enough and unlikely to change.  The WP doesn't
have the special case that C has, so the above is an error in C++: you
can indirect through the pointer, but when you convert it to an rvalue
you get an error.

3/16/95  No leading zero in day-of-month in __DATE__

The front end gets the date via ctime for use in __DATE__ and __TIME__.
ctime is allowed the return a two-digit day-of-month with a leading zero,
but __DATE__ requires a space in that position.  If ctime returns
a leading zero, it is now converted to a space in __DATE__.  (Windows
NT has this idiosyncrasy.)

3/15/95  Routine name linkage of compiler-generated functions

All routine types in C++ now start off with a routine_name_linkage of
nlk_cplusplus_external, thereby fixing a bug in how the field was set for
compiler-generated functions.  The default for C routines continues to be
nlk_none.

3/15/95  Internal error due to nonconst copy constructor

As of version 2.28, a copy constructor with a reference to nonconst
parameter cannot copy an rvalue.  This change has exposed a bug
elsewhere that causes an internal error sometimes:

  struct A {
    A();
    A(A&);
    A& operator=(A);
  } a;
  A f();
  main () {
    a = f();  // Error because of nonconst cctor
  }

Now fixed.

3/15/95  Inlining: string literals as arguments

String literal arguments to an inline function now force the use of a
temporary for the inlined parameter.  Formerly, they were treated as
constants, and no temporary was used, but this caused problems because
using the string more than once in generated C code may produce multiple
copies of the string (each with a different address).

3/15/95  Param-type lists are no longer shared

With a change in how composite routine types are formed, it is now a rule
that a param-type list will be pointed to by no more than one routine
type.

3/14/95  Null pointer constants more standard-conforming

Null pointer constants in both C and C++ are limited in the casts and
operations they can contain.  This has been tightened up.  Some obscure
cases like (int)(float)0 are no longer considered null pointer constants.

3/13/95  Preserving "!= 0" in IL lowering

Boolean controlling expressions in "?", "&&", "||", and "!" operators
are defined by the IL as having a "standardized" value; if necessary,
a "!= 0" test is added by the front end to ensure that.  IL lowering
in some cases did transformations that destroyed that guarantee.
Now corrected.

3/13/95  Bug in finding user-defined conversion

A bug has been fixed that resulted in a spurious error on the following:

  struct B { };
  struct D : public B { };
  struct X {
    operator const D&();
  } x;
  const B &r = x;            // Spurious error is no longer issued.

3/13/95  Const-address-taken references for conversion functions

Const-address-taken references in the cross-reference output (added in
2.28) now come out also for conversion function calls.

3/13/95  Reachability of code after "if (1) ..."

The code after an "if" without an "else" is no longer considered reachable
directly from the "if" if the tested expression has a non-zero constant value:

  int f()
  {
    if (1) return 1;
    // No warning about missing return now
  }

3/13/95  Signatures for builtin [] and pointer +/-

The signature for the builtin operators [] and pointer +/- in overload
resolution take a *promoted* integral type for the integer operand, even
though the builtin operators do not do integral promotion.  The signature
with the promoted integral type is what is in the WP, and it's what makes
sense, to avoid ambiguity on something like

  struct A {
    operator[](int);
    operator int*();
  } a;
  short s;
  main () {
    a[s];  // Makes more sense if not ambiguous
  }

3/13/95  Protected conversion function access check

The check for access to a protected conversion function in a base class
gave a spurious error if the base class conversion function was const:

  class A {
  protected:
    operator void*() const;
  };
  class B : public A {
    void foo();
  };
  void B::foo() {
    const B cB;
    (void*)cB;  // Formerly gave spurious error
  }

3/13/95  Symbol reference for mem-initializer

Symbols that appear in a mem-initializer of a constructor definition
are now reported as initializations in the cross-reference output.

-------------------------------------------------------------------------------
Version 2.28, March 2, 1995

3/2/95   IL version number changed to 2.20

3/2/95   Added a new based type kind

btk_unqualified_array_type has been added to a_based_type_kind to identify
(as the based type) an array type to which a type qualifier was applied (to
produce the base type).  Since the qualifier actually went to the element
type, a new array type (= the base type) had been created; for example,
qualifying (int)[3] with const produced (const int)[3].  The original is
now recorded as a based type of the new type, enabling the C++-generating
back end (or a source debugger or other tool) to get back to the original
type -- e.g., to recover typedef names that were lost with the copy.

3/2/95   Specifying the message to be issued for unimplemented keywords

It is now possible to associate an error code with each unimplemented
keyword so that a specific message may be issued for certain keywords.

3/2/95   Brief diagnostics option

The options --brief_diagnostics and --no_brief_diagnostics enable
and disable a mode in which a shorter form of the diagnostic
output is used.  When enabled, the original source line is not
displayed and the error text is not wrapped.

3/1/95   IL CHANGE: new variable flag modified_within_try_block

A new flag, modified_within_try_block, has been added to a_variable.  It is
set for function-local variables that are declared in a scope that contains
a try block and that are then modified inside the compound statement of the
try block.  It is intended to help optimizing back-ends recognize variables
that must (sometimes) be stored immediately after being modified.

When FORCE_STORES_OF_VARS_MODIFIED_IN_TRY_BLOCKS is true (when the
C-generating back end is used, typically), IL lowering uses this flag
to generate code to fool compilers into doing fewer optimizations on
references to such variables.

3/1/95   Internal error after error when generating cross-reference output

An internal error occurred after an error on the following program
compiled in C mode if cross-reference output was generated:

  main () {
    register int i;
    &i;  /* error */
  }

3/1/95   Preprocessing immediate pragma binding kind added

A new pragma binding kind called "preprocessing immediate" has been
added.  This may be used for pragmas that need to be processed
when encountered by the preprocessing routines.

3/1/95   Lvalues required as first operands of builtin operators in overload
         resolution

In overload resolution, the fact that a builtin operator requires an
lvalue for its first operand can now rule out that operator if
the first operand supplied is a class type and there are no conversion
functions that can convert to an appropriate reference type.  Formerly,
conversions to a non-reference type were accepted, which would result
in an error later if the builtin operator was selected as the best
match, or ambiguity if the builtin operator was one of several best
matches.

3/1/95   Minimal inlining in IL lowering

IL lowering can now do inlining of function calls.  This option is
by default enabled when the C-generating back end is being used.
See the configuration flag MINIMAL_INLINING.  The inlining is
supposed to be comparable to what is done by cfront.  We're providing
this only for the convenience of those who need to generate C code
and do not have inlining in their C compilers; it's not supposed
to be anything too fancy.  We'll fix bugs, of course, but we don't
want to do enhancements beyond the cfront level of functionality.

3/1/95   File scope variable definitions in the C generating back end

Formerly, the C generating back end would emit two declarations of any
initialized variables.  This resulted in warnings from the HP C compiler.
The first declaration has been modified to include a storage class of
"extern" to eliminate these warnings.

3/1/95   C generating back end and variable argument lists on HP/UX and SGI

When generating old style parameter lists, the C generating back end now
emits the special va_alist parameter required by HP/UX and SGI.

2/28/95  Cfront 2.1 compatibility: Derived::operator Base()

Ordinarily a conversion operator that converts from a derived class to a
base class is ignored (see WP 12.3.2), after a diagnostic is put out.  This
is appropriate for cfront 3.0 as well, but it turns out that cfront 2.1
actually calls such functions in preference to doing a standard conversion.
We have made a change to emulate that behavior when --cfront_2.1 is used.

2/28/95  Error recovery bug

An internal error is no longer triggered during error recovery in the
following:

  void f() {
    class A {
      virtual void g() { }
    };
    class B : public A {
      void g() { }
      void A::g() { }      // Assertion failure here has been eliminated.
    };
  }

2/28/95  Maximum class size

Global variable targ_max_class_object_size defines the maximum allowable
size of a class, struct, or union; it is checked during class layout
processing.
  
 - When TARG_MAX_CLASS_OBJECT_SIZE is nonzero, targ_max_class_object_size
   has the smaller of TARG_MAX_CLASS_OBJECT_SIZE and the maximum offset as
   implied by TARG_DELTA_INT_KIND; for instance, if TARG_DELTA_INT_KIND is
   ik_short (which is the default) then targ_max_class_object_size is 32K.

 - When TARG_MAX_CLASS_OBJECT_SIZE is zero, targ_max_class_object_size will
   have the same value as targ_size_t_max. (This is equivalent to the
   previous behavior, which means larger classes are allowed, but it also
   means integer overflow errors may be issued during IL lowering if
   TARG_DELTA_INT_KIND is too small.)

2/28/95  Default size of pointers to data members

The default size of pointers to data members has been changed to be the
same size as pointers, which matches cfront's choice of "int *" (but
our implementation is an unsigned integral type).  We were surprised
and embarrassed to discover that we had the wrong size in there; we
thought we *were* compatible with cfront.  If you want to retain
binary compatibility with previous releases, you can change
TARG_SIZEOF_PTR_TO_DATA_MEMBER and TARG_ALIGNOF_PTR_TO_DATA_MEMBER
back to the size/alignment for short.  Note that the various other
offset fields (e.g., the delta field in pointers to member functions)
remain as they were, i.e., short.

2/27/95  Cfront mode: static member function declared with cv-qualifier

Cfront allows function qualifiers on a static member function declarations
under certain circumstances; therefore, we now issue warnings instead of
errors in such cases in cfront mode.  For example:

  class A {
    static int *f() const;           // Now a warning in cfront mode
  };
  int *A::f() const { return 0; }    // Now a warning in cfront mode

2/27/95  IL CHANGE: is_initialization_guard

stmk_if statements and eok_question expression nodes now have a
field is_initialization_guard set if the test being done is the
guard code around the initialization of a variable.  When thread-safe
code is being generated, those tests and the first assignment
within them should be rendered as an atomic test-and-set.

2/27/95  Setting param_value_has_been_changed when address of parameter taken

The param_value_has_been_changed flag in parameter variables is supposed
to be set whenever the address of the parameter is taken.  It wasn't in
a few cases where the address is taken implicitly.  Now fixed.

2/26/95  Old-style parameter lists in C++

When old-style function parameter lists are supported in C++ mode (i.e.,
when anachronism support is enabled, which is by default in cfront
compatibility mode), the internal representation is now that of a
prototyped parameter list.  That is, back ends will never see the
"prototyped" flag in the routine type supplement set to FALSE, nor will
they see "old_style_params_scanned" set to TRUE.  This simplifies some code
(e.g., in types.c) and also fixes some incompatibilities with cfront:

  void f(d) double d { }
  main() {
    f(10);                 // argument used to be left an integer; now it's
                           //   converted to double before it's passed to f
    f((char *)0);          // an error is now issued on this
  }

2/25/96  IL CHANGE: friend information in source sequence lists

When source sequence entries are being generated, friend declarations are
now identified in either of two ways: when the friend declaration is a
primary declaration, defined_in_friend_decl, a new field in a_routine, will
be set; otherwise, friend_decl, a new field in a_src_seq_secondary_decl,
will be set.

2/25/95  IL lowering: type-as-subobject prefix changed to "__SO__"

When a class has virtual base classes, IL lowering creates a version
of the type shorn of those base classes.  This is called the
type-as-subobject for the type.  The name of the type-as-subobject has
been the class name prefixed by "_".  This unfortunately clashed
with the user's name space, so the prefix has been changed to "__SO__".

  struct v {};
  struct _x {} a;
  struct x : public virtual v {};

This has no effect on binary compatibility since these names are internal
to a compilation.

2/25/95  Improved error recovery on too many arguments to macro call

The error recovery on a case like the following is now improved:

  #define a(i) i
  int i = a(1, 2, 3);  // Too many macro arguments

2/24/95  #pragma weak

Support for #pragma weak has been added (when PRAGMA_WEAK_ALLOWED is set).
This is minimal support: the name specified is not looked up, and the
text of the pragma is simply passed on to the back end.

2/24/95  IL CHANGE: linkage specification as a function type attribute

The linkage specification in effect at the point of a function type
declaration is now recorded in the routine type supplement (field
routine_name_linkage).  The front end makes this information available to
the back end in case, for example, different linkages imply different
calling conventions.  It can be necessary to have this information in the
routine type if a call is made through a function pointer or
pointer-to-member.

The only behavior difference to be expected is that an error is no longer
issued for the following:

  extern "C" typedef void FT();

which is now handled identically to:

  extern "C" { typedef void FT(); }

(Note: the routine_name_linkage value does not necessarily correspond to
the name linkage with which an associated function, if any, was declared.
Moreover, it is expected that an implementation that makes use of it will
layer additional functionality on top of it.  For instance, macros
routine_linkages_are_compatible and routine_linkages_are_identical in
types.c might need to be customized.)

2/24/95  Finding out of scope declarations in ANSI C mode

In ANSI C mode, an extension has been added that permits use of
declarations of file scope entities that were declared in a local
scope that is no longer active.  This is disabled in strict mode.

void f1(void) { extern void f(); }
void f2() { f(); /* Using out of scope declaration */ }

2/24/95  SVR4 C compatibility mode

An option has been added to provide additional compatibility with the
SVR4 ANSI C compiler.  The default for this mode may be changed by
setting the configuration flag DEFAULT_SVR4_C_MODE.  This mode may
also be enabled or disabled on the command line using the --svr4 and
--no_svr4 options.  A list of the features supported in this mode may
be found in the External Interface chapter in the internals manual.
This option applies only in C mode (i.e., not in C++ mode).

2/23/95  Internal error instantiation template with uncallable conversion

When a class contains a conversion operator to a base class, the operator
will never actually be used for a conversion.  This change was made to
the front end in version 2.21.  This change caused an internal error
to occur if a class template includes such a conversion operator. This has
been fixed.

  class B {};
  template <class T> struct A : public B {
    operator B();
  };
  template <class T> A<T>::operator B(){}
  A<int> a;

2/23/95  Instantiation of left operand class when checking for operator
         overloading

When checking for operator overloading, if the left operand has a
template type, the type is now fully instantiated.  This is necessary
to ensure that all member functions that might apply are declared.
It's hard to come up with a case where the left operand would not
have been instantiated anyway, but there are some involving functions
returning references to template types, e.g.,

  template <class T> struct Array {
    T & operator[](int);
  };
  template <class T> struct Matrix {
    Array<Array<T> > data;
    Array<T> & operator[](int) /*const*/;
  };
  int main() {
    Matrix<int> m;
    m[0][0] = 0;  // No error now on second [0]
  }

2/20/95  Weighting of conversions between builtins in overload matching

In overload resolution, any conversions required to convert operands
of a builtin operator from one builtin type to another were always given
a weight of "standard conversion" (this is what cfront 2.1 seems to do).
Now, they are given the proper weight -- exact, promotion, or standard
conversion.  The old behavior continues in cfront 2.1 mode.

2/19/95  Determination of "copy assignment operator"

If Base is a base class of Derived, Derived::operator=(const Base&) is
treated by cfront as a copy assignment operator -- that is, its declaration
blocks the implicit generation of Derived::operator=(const Derived&).  In
default mode (as well as cfront mode) we continue to treat it as a copy
assignment operator, but in strict ANSI mode we do not.

Although the cfront-compatible behavior violates both the ARM and the
Working Paper, it is nevertheless depended on by (e.g.) AT&T/Novell-USG's
Standard Libraries.  Some code may get compilation errors in strict mode as
a result of this change, though it will still compile cleanly in default
mode.  Here's an example:

  #include <iostream.h>
  int main(void) {
    istream_withassign i;
    i = cin;
  }

where istream_withassign, derived from istream, has the following
declaration:

  istream_withassign::operator=(istream&);

which, in strict mode, is not treated as a copy assignment operator.  When
istream_withassign::operator=(istream_withassign&) is generated by the
compiler, however, an access error is reported because ios::operator=(ios&)
is private.

NOTE: Eventually, we will probably make default mode work like strict mode,
so you may want to consider making changes to library header files.

2/17/95  Digraph and operator keyword support

The front end now supports C++ digraphs (e.g., <&%, %>, etc.), and
the operator keywords (e.g., bitor, bitand, or, etc.)  Because they
are likely to cause problems for existing programs, the alternate tokens
are disabled by default.  The default may be changed by setting the
configuration flag DEFAULT_ALTERNATE_KEYWORDS_ALLOWED.  They may
also be enabled or disabled on the command line using the 
--alternate_tokens and --no_alternate_tokens command line options.

An example of an incompatibility caused by this feature is:

  template <class T> struct A {};
  typedef int I;
  A<::I> a;   // Interpreted as A{:I> a;

2/17/95  Destructor names containing template parameter lists

Destructor names containing template parameter lists are now accepted.

 template <class T> struct A {
    ~A<T>();
  };

2/16/95  New qualification conversion implemented

The new qualification conversion that allows conversions such as
T** to T const * const * is now implemented.  Currently, this conversion
is only supported at compile time.  The EH runtime has not been
modified to support this conversion yet because such a modification
will require a link incompatible change to the way typeinfo
information is represented.

2/16/95  Name of an unnamed class defined in a typedef declaration

An unnamed class defined in a typedef declaration takes on the typedef
name "for linkage purposes only" (WP 7.1.3 para 5).  Except in cfront
compatibility mode, we now issue an error when such names appear in an
elaborated type specifier (see WP 9.1 para 5):

  typedef struct { int i, j; } S;
  struct S s;                       // Error (except in cfront mode)

2/16/95  IL CHANGE: extension to allow "&..."

If ADDRESS_OF_ELLIPSIS_ALLOWED is TRUE, the expression "&..."  is accepted
in the body of a function for which an ellipsis appears in the parameter
list.  It is needed to support some versions of macro va_start in stdarg.h.
A diagnostic is issued in strict ANSI mode.  To support this extension
enk_address_of_ellipsis has been added to an_expr_node_kind.

2/16/95  Ellipsis in C mode

If ALLOW_ELLIPSIS_ONLY_PARAM_IN_C_MODE is TRUE, an ellipsis may appear by
itself in the parameter list of a function declaration --- e.g., f(...).
A diagnostic is issued in strict ANSI C mode.  (This is already allowed as
standard in C++ mode.)

2/16/95  Binding reference to nonconst to class rvalue no longer accepted

We have had an extension that allows binding a reference to nonconst to
an rvalue of a class type.  This was there with the expectation that
something of that sort would be approved by the standards committee.
That didn't happen, so the extension has been removed.  Well, actually,
we got a little worried about the impact of this one, since most
compilers seem to allow it, so we continue to permit it in non-strict
mode, with a warning.

2/16/95  A reference to const volatile cannot be bound to an rvalue

A recent committee decision makes it illegal to bind a reference to
const volatile to an rvalue.  Now implemented.

2/15/95  Missing ambiguity error

An ambiguity error was not being issued when the first component of a
qualified name was ambiguous.  This has been corrected.

  struct A {
    struct N { static int M(); };
  };
  struct B {
    struct N { static int M(); };
  };
  struct C : public A, public B {
    int f() { return N::M(); }  // ambiguous
  };

2/15/95  Bug in -I- option processing

The -I- option had a bug when more than one directory was specified
by way of -I options preceding the -I- option.

2/15/95  Pragmas in IL template strings

A bug has been fixed that could cause IL template strings to be
constructed improperly when pragmas are used inside a template.
IL template strings are only created when RECORD_TEMPLATES_IN_IL
is TRUE (e.g., when the C++ generating back end is used).

2/15/95  Flag added for pseudo-pragmas

A flag has been added to the pragma kind description that indicates
whether a given pragma kind represents a pseudo pragma.

2/15/95  Support for template friend declarations

Template declarations that declare friend classes or friend functions
are now supported.

  template <class T> struct A {
    template <class X> friend void f(X);
    template <class X> friend struct Z;
  };

2/14/95  Return types of operator new and operator delete

We now issue errors on declarations of operator new() with a return type of
"const void *" and operator delete() with a return type of "const void".

2/14/95  Union member restrictions

An error is now issued whenever a union member's type (or underlying array
element type) is a class with a "nontrivial copy assignment operator" --
e.g.,

  struct A {
    A& operator=(const A&);
  };
  struct B {
    A a;
  };
  union U {
    B b;            // Error is now issued
  };

In this example, B::operator=(const B&) is generated by the compiler, but
it is "nontrivial" because it calls the user-declared copy assignment
operator for A.

2/14/95  Binding a reference to nonconst to an rvalue

Overload resolution now rejects binding a reference to nonconst to
an rvalue.  In the ARM, this was allowed in overload resolution and
then would get an error later if that binding was chosen as the best.
cfront mode is unaffected.

  void f(char &);
  void f(int);
  main () {
    f('a');  // f(int) because f(char &) is rejected.
  }

2/14/95  Aggregate class types

WP 8.5.1 says that an aggregate class has "no private or protected
members".  We previously interpreted this to apply to nonstatic data
members only; in strict ANSI mode we now apply it to all members.

  class X {
    static int i;
   public:
     int j;
  } x = { 0 };        // Error in strict ANSI mode

2/14/95  More on using .init sections in C-generating back end

The C-generating back end can now generate .init sections when generating
ANSI C.  Also, the __link mechanism code generated by IL lowering is
suppressed when a .init section is used.

2/12/95  Dropping type qualifiers when binding a reference

Dropping type qualifiers when binding a reference now disqualifies
an argument match in overload resolution (previously, it would get an
error later if that alternative was selected, but might cause an
ambiguity before then).

  void f(char&);
  void f(short);
  main()
  {
    const char ch = 'c';
    f(ch);  // f(short)
  }

2/12/95  Implicit conversions to pointer-to-member types to match
         builtin operators

User-defined conversions to pointer to member types are now considered for
operands of the ?, ==, and != operators:

  struct A {};
  typedef void (A::*pmf)();
  struct B {
    operator pmf();
  };
  main() {
    B b;
    1 ? b : 0;  // Now accepted
    b == 0;     // Now accepted
  }

2/11/95  Type qualifiers on types of temporaries allocated for reference
         binding in IL lowering

The temporaries allocated by IL lowering when binding references now have
the type qualifiers of the underlying type of the reference.  For example,
in

  const int &r = 2;

the temporary allocated now has type "const int" instead of "int".
This is of very little practical significance, but does avoid a case
in the IL where type qualifiers seemed to be added without an explicit
cast, and it matches the current WP wording more closely.

2/9/95   IL CHANGE: Generalized support of "asm functions"

When ASM_FUNCTION_ALLOWED is TRUE, asm functions are recognized and passed
uninterpreted to the back end.  They are represented in the IL like
ordinary functions, except that they have a storage class of sc_asm and the
function body (pointed to from the associated scope entry) is represented
by an stmk_asm statement; the latter points to a NULL-terminated string
containing the text that appeared in the source.  Comments are removed
unless INCLUDE_COMMENTS_IN_ASM_FUNC_BODY is TRUE.

Furthermore, when ASM_FUNCTION_ALLOWED is TRUE, "__asm" is accepted as a
synonym for "asm".

2/7/95   Address of string as initial value of local static in pcc mode

When the address of a string is the initial value of a static variable
local to a function in pcc mode, the address constant ended up in the
file scope memory region and the (unshared) string constant in the
function scope memory region, which caused IL write/read problems.
This bug was introduced in version 2.27, with the changes for local
static initialization.

  void f() {
    static char *p = "abc";
  }

2/6/95   Binding of immediate and other pragmas to IL entries

It is now possible to bind pragmas with any binding kind to IL
entries.  Formerly, it was only possible to bind next construct
pragmas to IL entries.

2/6/95   Error on throw of abstract class type

An error is now issued for a throw of an abstract class type:

  struct A {
    virtual int f() = 0;
  };
  void f(A &r) {
    throw r;  // Error
  }

2/5/95   Partial IL lowering of exception handling

Exception handling constructs can now be handled three different ways
by IL lowering:
- With DO_FULL_PORTABLE_EH_LOWERING set, all EH constructs are lowered to
  C.  That means code is generated to maintain an EH stack, try/catch are
  fully lowered (using setjmp), throw is fully lowered, cleanup tables
  and typeinfo entries are generated, and __eh_curr_region is maintained.
  This has been the default implementation since we added the EH features.
  This mode is compatible with the C-generating back end and the minimal
  runtime supplied.  Setting DO_FULL_PORTABLE_EH_LOWERING forces the
  setting of GENERATE_EH_TABLES.
- With GENERATE_EH_TABLES set (and DO_FULL_PORTABLE_EH_LOWERING not set),
  the cleanup tables and typeinfo entries are generated, but throw/try/catch
  are retained.  Other low-level executable code is represented as
  enk_lowered_eh_construct expression nodes.  Also, the object address
  table is not maintained, and the handle numbers for entities in the
  cleanup tables use stack offsets represented as ck_stack_offset
  constants.  This mode is very similar to the portable mode, but more
  efficient in not using the object address table.  It also allows the
  back end to redefine or eliminate the separate exception handling stack,
  and to use something other than setjmp for try/catch.
- With neither flag set, no tables are generated (but the object lifetime
  information is preserved), throw/try/catch are retained, and all other
  executable constructs are represented as enk_lowered_eh_construct nodes.
  This mode is intended for back ends that want to handle all the code
  generation for exception handling.  (This mode was formerly controlled
  by DO_LOWERING_OF_EXCEPTION_HANDLING, and was available in version 2.27,
  but the implementation had some holes in that version.)
The statements and expressions attached under exception handling
constructs (e.g., try/catch, throw) are lowered in all modes (as long as
IL lowering itself is done).

2/5/95   Dynamic initialization for throw doesn't indicate destruction

The dynamic initialization for a throw no longer indicates a destruction,
because the runtime is supposed to do the destruction, not the point
of throw.

2/3/95   Asm entries

Entries of type an_asm_entry are now recorded in the scope's asm_entries
list only when they are not associated with an stmk_asm statement (i.e.,
when they are "asm declarations" not "asm statements").  In effect, this
means only asm declarations that appear outside a function scope are on a
list.

2/2/95   C-generating back end initialization of wchar_t array

The wide string literals used in an initialization of a wchar_t array
are now turned into arrays of char.

  main () {
    wchar_t aa[] = L"yyy";
  }

This formerly produced an L"yyy" constant in the output.

2/1/95   Support for #ident and #pragma ident

When IDENT_DIRECTIVE_AND_PRAGMA is TRUE (see lang_feat.h), the #ident and
#pragma ident directives are recognized: in both cases, a pk_ident pragma
entry with a constant pointer identifying the string is added to the IL
(and the C and C++ generating back ends put out #ident directives).

(Note: the #ident directive, which was previously recognized but ignored,
is no longer recognized unless IDENT_DIRECTIVE_AND_PRAGMA is set.)

1/30/95  Support for #pragma pack and --pack_alignment

When USER_CONTROL_OF_STRUCT_PACKING is TRUE (see lang_feat.h), the maximum
alignment of nonstatic data members in a class or struct (the "pack
alignment") may be explicitly specified, either by the --pack_alignment
command-line option or by #pragma pack.  Both take an argument that is a
power-of-2 value within the range defined by TARG_MINIMUM_PACK_ALIGNMENT
and TARG_MAXIMUM_PACK_ALIGNMENT (see targ_def.h).  The default pack
alignment is in effect for all class/struct definitions unless it is
overridden by a #pragma pack(n) directive.  The new setting remains in
effect until it in turn is overridden by another #pragma pack(n) or until
the default pack alignment is restored by #pragma pack().

1/28/95  Template function matching abort

Under certain conditions, an abort could occur in matches_template_type 
when the template parameter type from the template being considered
as a potential match was under a typeref, as would occur if it
were a cv-qualified type.

1/27/95  Warning on call of pure virtual function

A warning is now issued on a non-virtual call of a pure virtual function.

  class C {
    virtual void f() = 0;
    C() {
      f(); // Warning
    }
  };

1/26/95  Non-null test on pointer on call of user-written operator delete

A user-written operator delete is not required to contain a test for
non-NULL (whereas the compiler-supplied one does have to contain that test),
so a "!= NULL" test is required around the delete call in something like
the following:

  struct A {
    void operator delete(void *) { }
  };
  main() {
    A *p = 0;
    delete p;
  }

1/26/95  Ellipsis match allowed on function template

An ellipsis match is now allowed on a function template.  The ARM
disallowed it (it's not an exact match), but recent WPs have removed
that restriction.

  template<class T> void f(T, ...);
  main () {
    short i = 1;
    f(i, i);
  }

1/25/95  Any implicit conversion allowed on non-template parameter of
         function template

All implicit conversions are now allowed on parameters of function templates
that do not involve template parameter types.  The ARM restricts the
conversions allowed, but recent WPs have eliminated those restrictions.

  template<class T> void f(T, int) {}
  struct A {
    operator int();
  } a;
  main () {
    int i = 1;
    f(i, a);  // User-defined conversion on non-template parameter
              // not allowed by ARM, but allowed by WP
  }

1/25/95  Overloaded function as argument to function template

An overloaded function can now be used as the argument to a function
template.

  void f(int);
  void f(int *);
  template<class T> int ff(T, void (*)(T *)) { return 0; }
  main () {
    int i;
    ff(i, f);
  }

1/25/95  Improved error recovery on "?" operator

  char * g() {
    int i = 0;
    return i ? 0 : &undefined; // Gets only one error now.
  }

1/25/95  __builtin_va_alist handling in C-generating back end on Sun

A static variable with the name __builtin_va_alist is no longer mangled
by the C_generating back end configured for a Sun.

1/25/95  Freeing of storage on exception for uninitialized "new"

The freeing_of_storage_on_exception action for a "new" shouldn't
be filled in when the "new" doesn't have initialization.

1/25/95  Ambiguous member functions in operator overloading

Ambiguity on member functions in operator overloading is now diagnosed
correctly (rather than with some other kind of error).

  struct A {int operator++();};
  struct B {int operator++(int);};
  struct C : public A, public B {} c;
  main () {
    c++;  // Gets ambiguity error
  }

1/24/95  Checking return type of operator-> when taking its address

According to WP 14.3.3, the return type of operator-> must be valid if,
among other things, the function's address is taken.  Now checked.

1/25/95  Braces around for-init statement from C-generating back end

The C-generating back end now puts braces around a for-init statement
and its associated "for".  The absence of braces is a problem only when
customer code transforms the IL, but it's a safe change in c_gen_be.c
and useful when transformations are done.

1/24/95  Instantiation of left operand of "="

The underlying type of the left operand of a "=" operator, if a template
class, is now forced to be instantiated.  This is necessary to create
the declaration for the operator= function, if any.

  template<class T> struct A { T i; };
  A<int> & f();
  main () {
    f() = f();  // Formerly got error "expression must be a modifiable lvalue"
  }

1/23/95  Bug in generation of implicitly declared assignment operator

A bug has been fixed in how assignment operators are implicitly declared
-- the problem is when a const-qualified object may be accepted.  For
example, in the following C::operator=(C&) was being created instead of
C::operator=(const C&):

  struct A {
    A& operator=(const A&);
  };
  struct B {
    int i;
    int operator=(int);
  };
  struct C {
    A a;
    B b;
    C();
  } c;
  main() {
    const C x;
    c = x;                      // Spurious error is no longer issued
  }

1/23/95  Compile-time comparison of pointers to data members in unions

The compile-time folding in the following is now done correctly:

  union U {
    int i1;
    int i2;
  };
  main()
  {
    int result = &U::i1==&U::i2;  // Should be 1
    return result;
  }

1/23/95  Template instance flag and automatic instantiation mode

Version 2.27 was setting the instance_required flag for variables
and functions even when automatic instantiation mode was not
being used.  The fact that this flag was set should not actually
make any difference because IL lowering only checks then flag
in automatic instantiation mode.

1/23/95  Spurious access error on class template reference

A bug has been fixed that caused examples such as the following to
produce spurious access errors.

  template <class T> class A {
    class B {
    public:
      B();
    };
  };
  template<class T> A<T>::B::B(){}  // Spurious error on this line

1/20/95  Internal error following syntax error in #pragma directive

A few problems have been fixed that could result in an internal
error in wrapup_rescan_of_pragma_tokens after diagnosing a syntax error.

This is an example of a case that resulted in an internal error:

  template <class T> struct A {};
  template <class T> struct B {
    ~B();
  };
  #pragma instantiate B<A<int>>::~B()

1/20/95  IL CHANGE: qualifiers field in a_param_type

With the change to remove cv-qualifiers from function parameter types (in
noncfront C++ mode), some information was lost that was useful in
generating ANSI C.  That problem has been fixed by adding to the param-type
entry a field in which to record the qualifiers that were removed (that is,
the qualifiers at the declaration where the function was defined).

1/19/95  Template instance required flag for inline functions

Version 2.27 contains a bug that results in the template instance
required flag (TIR) being set for inline functions.  It should
only be set for external functions.  This has been corrected.

1/19/95  Error instead of warning in strict mode on incomplete final line

In strict mode, when the final line of a file ends without a newline,
an error is now issued instead of a warning.

1/19/95  Internal error when flushing tokens after an error in a macro
         invocation

An internal error could occur if, after an error in a macro invocation
has been diagnosed (such as too many arguments), the flush_tokens
routine encounters a construct that could be a class template reference.
This has been corrected.

1/17/95  Internal error in lowering global-scope "new" with exceptions
         enabled in long lifetime temporaries mode

An internal error that occurred for a "new" of a non-class type, or a
class type when allocation is not done by the constructor, in the initializer
of a global-scope variable, with exceptions enabled and long lifetime
temporaries, has been corrected.

  int *p = new int(1);  // No longer aborts

1/16/95  Top-level cv-qualifiers removed from function parameter types

In C++ (except in cfront compatibility mode) top-level const and volatile
qualifiers are removed from function parameter types (see WP 8.3.5 para 3).
They still constitute part of the type of the parameter variable, however.
Note that this has an effect on the mangled names of functions, and
therefore may cause some binary-compatibility problems.

1/16/95  Default argument on declaration of operator delete()

Default argument expressions are now allowed for the second parameter of
an operator delete() declaration.

1/16/95 Name mangling for "long long"

The change to mangle "long long" as "L" (instead of "ll"), which was
reported as having been done on 4/11/94, was in fact done only in
the name demangler (and not lower_name.c; oops).  Now fixed.  This
means, however, that name mangling for "long long" changes now.

1/13/95 Internal error attempting to instantiate what should be a
        nonreal class (found in STL example)

A bug has been fixed that could result in an internal error. Under certain
conditions the front end would attempt to generate an instantiation
of a class for which one of the template parameters is, or contains
another template parameter.  Such classes are supposed to be
created as "nonreal" classes, not actual instantiations.

1/12/95 Symbol reference kind for initializations

A new symbol reference kind, SRK_INITIALIZATION, has been added for
implicit and explicit variable and static data member initializations.  It
is a modifier of SRK_DEFINITION.

1/12/95 Const member with type array-of-class-type

A spurious error is no longer issued when a class with no constructor has a
const member of array type and the underlying array element type is a class
with a constructor.  Here's an example:

  struct S { S(); };
  class A {
    const S s[10];             // Error is no longer issued
  };

Here A::s is initialized by the compiler-generated default constructor
A::A() because S::S() can be called for each of its elements.

1/11/95 Bug in #pragma once handling

The front end was issuing a spurious "extra text after end of preprocessing
directive" error on all #pragma once directives.  This has been fixed.

1/11/95 Recognition of wchar_t as a keyword

In C++, wchar_t is now recognized as a keyword.  This feature may be
enabled or disabled using the --wchar_t_keyword and --no_wchar_t_keyword
command line options.  The default is specified by DEFAULT_WCHAR_IS_KEYWORD
in lang_feat.h.  When wchar_t is a keyword, a preprocessing flag can be
automatically defined by the front end so that a single set of system
headers can be used for both modes.  The lang_feat.h flag
DEFINE_MACRO_WHEN_WCHAR_T_IS_KEYWORD is used to request that such a
macro be defined.  The name of the macro is specified by the
lang_feat.h flag MACRO_DEFINED_WHEN_WCHAR_T_IS_KEYWORD.  By default, a
macro named "_WCHAR_T" is defined.

1/11/95 Implicit inclusion problem introduced in 2.27

Version 2.27 introduced an implicit inclusion bug that would sometimes
cause files to be included after the linkage of classes and their members
had been determined.  This resulted in spurious errors in classes declared
in the implicitly included files.  This has been corrected.

1/11/95 Bug in code to compute CPU time used

A bug was fixed that could cause the CPU time usage to be reported
incorrectly.

1/10/95 Duplicate size and sign specifiers in a declaration

Except in cfront mode, we now issue an error (rather than a warning) when a
declaration has duplicate size or sign specifiers.

1/9/95  Bug in make_temporary_in_scope

A stupid bug introduced in version 2.27 caused some problems in linkage
on variable lists when IL lowering adds temporaries.  Now fixed.

1/6/95  Use of cfront member function typedefs

When (in cfront mode only) a "member function typedef" is declared -- e.g.,
MF in the following code fragment:

  class A;
  typedef void A::MF(int);    // nonstandard typedef declaration

-- we now issue an error if it is used in any context other than to form a
pointer-to-member type:

  MF* pmf;                    // okay -- same as:  void (A::*pmf)(int);
  MF mf;                      // error
  MF a[10];                   // error
  MF f();                     // error
  int i = sizeof(MF);         // error

1/6/95  Repackaging in declaration processing

Some of the code in decl_specifiers has been broken out into new
subroutines combine_type_specifiers and add_type_qualifiers; similarly,
declarator now has a new subroutine, scan_real_declarator_id.

1/6/95  Signal handling on old Unix systems without job control

The code that initializes the signal handlers first ensures that
the interrupt signal is not being ignored before resetting it.
This prevents a background compilation from being terminated by
an interrupt signal intended for a foreground process on older
Unix systems that lack job control.

1/6/95  Template instantiation bug when a template is redeclared

A bug has been fixed that caused template functions to be instantiated
incorrectly when a template was redeclared after being defined, and
when the redefinition used different function parameter names than
those in the function definition.

  template <class T> void f(T t){ T t2 = t;}
  template <class T> void f(T);
  int main()
  {
    f(1);
  }

1/4/95  Consider conversions to pointer for operand of unary "+"

Since the unary "+" operator can take a pointer operand, conversion
functions to pointer types should be considered on operands of unary "+".
Now they are.

  struct A {
    operator int();
    operator int*();
  };
  A a;
  void m()
  {
    +a;  // ambiguous
  }

1/4/95  Missing IL casts in pointer difference

A cast is now generated, if necessary, to bring the two operands of
a pointer difference to a common type.

  struct B {};
  struct D : public B {};
  int f(B *pB, D *pD)
  {
    return pD-pB;  // Cast of pD to B* now generated
  }

-------------------------------------------------------------------------------
Version 2.27, December 22, 1994

12/22/94 IL version number changed to 2.19.

12/22/94 Bugs in exception handling

The object lifetime changes exposed several bugs in exception handling,
which have been corrected:

- On uses of conditional flags, the code that put the address of the
  conditional flag into the object address table was putting the
  address into the slot of the object address table indexed by the region
  table number (rather than the index number for the object address table).
  By coincidence, the runtime was looking for the conditional flag address
  in the same wrong place, so the bugs often cancelled out, particularly
  in small test programs.
- When destroying unordered temporaries, the values placed in
  __eh_curr_region during the destructions were wrong and would
  result in incomplete destructions if an exception was thrown in one
  of the destructors.
- The processing to free storage allocated but not initialized when
  an exception is thrown did not interact correctly with the processing
  for unordered temporaries.
- At the end of a "try" block, the code that popped the EH stack
  frame restored __eh_curr_region from the stack, but it shouldn't have --
  no value was stored there.  Fortunately, there was always a superfluous
  assignment to __eh_curr_region immediately following, so the bad
  value was never used.

12/22/94 Destruction of temporaries in new-initializer when alloc fails

If "operator new" returns NULL, indicating that the allocation for a
new could not be done, the initialization of the storage is suppressed.
Unfortunately, the destructions of any temporaries in that initialization
were not considered conditional, so the destructions would be done
even though the corresponding constructions never were.

12/22/94 Elimination of extra destructor call in switch body

In some cases an extra unreachable destructor call would be placed
inside the body statement of a switch.

12/22/94 Destruction of long-lifetime temporaries on break or continue

Code with the following general form:

  ... A(1) + A(2);  // Some temporaries created
  while (expr) {
    if (expr2) break;
  }

was incorrectly handled in that the temporaries were destroyed on the break
(and therefore destroyed each time around the loop).

12/22/94 Lifetime of temporaries to which a reference is bound

The lifetime of a temporary to which a reference is bound has now been
extended to match the lifetime of the reference.  The problem was most
noticeable for local static references:

  void f() {
    static const A &r = A(1);
  }

Formerly, the temporary was destroyed at the end of the scope, leaving
the reference dangling.

12/22/94 MAKE_ALL_FUNCTIONS_UNPROTOTYPED as variable

The build option MAKE_ALL_FUNCTIONS_UNPROTOTYPED, which controls whether
IL lowering turns all functions into unprototyped functions (for
compatibility with the +a0 mode of cfront), is now selectable at
compile-time.  The setting of MAKE_ALL_FUNCTIONS_UNPROTOTYPED is transferred
to the new variable make_all_functions_unprototyped, which is then tested
in IL lowering.  There is no command-line option to change this setting
(since, basically, we think it's a mistake to make this user-selectable
except after thorough consideration), but having the variable makes it
easy for those who want a command-line option to add one.

12/15/94 Generation of unique externally visible names

Unique external names are generated for the routines used to do
static initialization and destruction, and for "fake statics"
(static variables that need to be put out as extern in K&R mode).

Formerly, the encoding included the compilation date and time,
causing the external name to change from one compilation to the next.
The encoding has been changed (to something based on the file name and
the name of the first defined external entity in the compilation)
so that the generated names will no longer change between multiple
compilations of the same file.

12/15/94 Address-taken references on pointer-to-member of overloaded
         member function

Pointer-to-member references to an overloaded member function now
result in (a) a correct address-taken reference on the cross-reference
output file, and (b) the setting of the address_taken flag in the
routine entry.

12/14/94 Union member of class type with user-defined assignment operator

In cfront mode a warning is now issued (instead of an error) if a union
member is declared to have the type of a class with no constructor or
destructor but for which the user has defined an assignment operator.

12/14/94 Internal error when using nontype function template parameters

An internal error would occur when calling a function template that
has nontype template parameters.  This has been fixed.  Note that
nontype template parameters are not yet supported on function
templates.

  template <int I> int f(int a[I]) { return 0; }
  int g()
  {
    int a[1];
    return f(a);
  }

12/13/94 IL CHANGE: added static_temp to enk_temp_init

The enk_temp_init expression node now has a static_temp flag that
indicates that the temporary must be static (e.g., for a temporary to
which a static reference is bound).

12/13/94 Missing delimiters and error recovery while caching templates

The caching of function template bodies has been improved to prevent
it from silently swallowing the body of subsequent functions when
a delimiter is missing in the template body.  An error may or may
not be issued depending on whether the function is instantiated.

  template <class T> void f(T)
  {
    int i = (1 + 2;
  }

  int main(){}

12/13/94 Incomplete classes nested within anonymous unions

Several bugs have been fixed in how incomplete classes nested within
anonymous unions are handled.  One of the bugs caused an infinite loop in
IL lowering; another produced an internal error.  Moreover, the following
is now processed correctly:

  static union {
    struct S;
    /* ... */
  };
  struct S { /* ... */ };

12/13/94 Storage class of template specializations

Formerly, a template instance would always get the storage class of
the template with which it was associated.  Now the storage
class of a specialization may be different from the template.

It is still not possible to declare (without defining) a function as
having linkage different than the template.  This will be possible
when the new specialization syntax is implemented.

  template <class T> void f(T){}  // Instances are external

  static void f(int){}  // f(int) is static

  static void f(float);  // Storage class on a specific declaration conflicts
                         // with template.  A warning is issued.

12/13/94 Order dependencies in member function rewriting

There was an inconsistency in how we dealt with dependencies between
default argument fixup and function body scanning for inline member
functions:

  struct A {
    static void f(int i = 0);
    void g() { f(); }          // Okay
    struct N {
      void h() { f(); }        // Used to be an error
    };
  };

This has now been fixed: all default argument fixup (for member functions
both of the containing class and of classes nested inside it) is done
before any inline function bodies are scanned.

12/12/94 Bug in processing member function of unnamed nested class

A bug has been fixed in processing a member function of an unnamed nested
class: its default arguments and function body were not handled properly.
Here's an example:

  class C {
  public:
    struct {
      void f() {};
    } s;
  };

The body for S::<unnamed>::f() was not being generated (resulting in a
diagnostic from the linker if it was called).

12/10/94 IL CHANGE: Added an_object_lifetime

A new structure, an_object_lifetime (used only in C++ mode), has been added
to the IL to represent the lifetimes of variables and temporaries.  They
are bound to various IL entities including:
  -- a_scope, to indicate the lifetimes of variables declared in a given
     file, function, or block scope.  (Lifetime entries for static local
     variables require special handling -- see the new field in a_scope,
     lifetime_of_local_static_vars.)
  -- an_expr_node of kind enk_object_lifetime; such an expression node
     can appear (only) as the top node of a full expression.
  -- a_dynamic_init, for temporaries created in dynamic initializations
     involving constructor calls.
(This is a partial list; for additional details, please refer to il_def.h.)

Each dynamic initialization that requires a destruction is entered
on the destructions list of an appropriate object lifetime, thus indicating
that the destruction should be done at the end of that lifetime or on
exit from that lifetime.  That is the point of this change: where before
the IL indicated destructions but gave no indication of when they should
be done (leaving it up to IL lowering or a back end to apply the language
rules), the new representation indicates explicitly the point of
destruction in each case.  This fits better with the general IL principle
that back ends should not have to understand much of the language rules.

Because the front end indicates the time of destruction for all entities,
it now also controls the lifetime of temporaries explicitly.  The short-
lifetime temporaries of the Working Paper are now implemented.  The
old long-lifetime temporaries are still used in cfront compatibility
mode and when --long_lifetime_temps is specified.  --short_lifetime_temps
is also available to request the standard (and, usually, the default)
behavior.

This change was motivated by a desire to provide the information that
formerly was recorded in the cleanup action lists in IL lowering in a
more implementation-independent way, one more suitable for use in
code generation in back ends that want to do a "real" implementation
of exception handling.  See DO_LOWERING_OF_EXCEPTION_HANDLING.

Those who use the unlowered IL may have to make some small changes (notably,
ignoring the enk_object_lifetime expression nodes).  Those using
IL lowering in the default configuration will not, as the object lifetimes
and enk_object_lifetime nodes are used and then removed by IL lowering.

12/10/94 IL CHANGE: removed parent_block and dependent_statement

The fields parent_block in a_label and a_block, and the field
dependent_statement in a_statement have been removed.  They were there
to provide information to IL lowering that is now more readily
available in the object lifetime information.  Let us know if you
were using these fields (I'm sure you will), and we can give you
patches to put them back in for you.

12/10/94 Setting virtual_function_info_base_class with ambiguous base class

A bug has been fixed in setting virtual_function_info_base_class when
the base class in question is ambiguous and one of the derivations
involves a virtual base class.  For example:

  struct A { virtual void f(); };
  struct B : public A { void f(); };
  struct C : public B { void f(); };
  struct D : virtual public C, public B { void f(); } d;

The bug was that the virtual_function_info_base_class pointer in D was
being set to point to the A whose path is ==>C==>B==>A; now it is
correctly set to point to the A whose path is through D's first direct
nonvirtual base class, namely, ==>B==>A.

12/9/94  IL CHANGE: Added implied_break_at_end to a_switch_clause

A new flag, implied_break_at_end, has been added to a_switch_clause to
identify switch clauses that do not terminate in an explicit branch but
implicitly branch to the first statement following the switch statement.

12/7/94  IL CHANGE: Added is_constructor_init to a_dynamic_init

This new flag is set to TRUE if the dynamic init entry is connected to an
entity in a ctor-initializer or dtor-initializer list (i.e., if the dynamic
init entry is pointed to by an entry of type a_constructor_init.).

12/7/94  Template instance required flag set incorrectly

The way in which the template instance required flag in the variable
and routine entries is set has been changed to fix a bug that occurs
if a destructor for a template class is first referenced by a
destructor generated by check_class_linkage (which is called by
fe_wrapup after automatic instantiation processing has been done).

12/1/94  Incorrect dependency when a file both uses and creates a PCH

When a file both uses and creates a precompiled header file, the
front end was incorrectly indicating that the new PCH file was
dependent on the primary source file associated with the PCH file being
used.  This has been fixed.

12/1/94  Setting the type field in proxy class symbols

The type field in symbols for template proxy classes was not being
set.  This did not affect the operation of the front end but
could affect those making use of the symbol table information
for other purposes.

A proxy class is created when a template parameter or nonreal instantiation
is used in a context that requires it to be treated like a real class
(except that any symbol looked up in the proxy class is considered to
have been found).

  template <class T> struct A {
    T::X tx;
  };

12/1/94  Spurious error when comma is missing before ellipsis

In contexts in which the evaluation of default arguments must
be deferred, a spurious error was issued if an ellipsis was used
without a comma separating it from the previous parameter.  This
is now fixed.

  template <class T> void f(T, int = 0 ...);
  class A {
    void f(int = 1 ...);
  };

12/1/94  IL lowering of lvalue-returning operations

In the case where an lvalue-returning "?" or "," operator is under
a cast (e.g., one that adjusts const at some level), the type of the
rewritten "?" or "," was incorrect (it was the type before the adjustment
done by the cast).  Now fixed.

11/30/94 IL CHANGE: Added has_temporary_lifetime to a_dynamic_init

This new flag is set to TRUE if the dynamic init entry represents the
initialization of an expression temporary.

11/30/94 Top-level operations in boolean controlling expressions

The IL has a convention that expressions that are boolean controlling
expressions (e.g., the tested expression in an "if" statement, the
operands of the "&&" operator) are normalized to something that produces
a 0/1 integral value.  If necessary a "!= 0" is added on top of the
expression to ensure that.  There has been a problem with IL lowering
in that regard: some transformations would not preserve that property.
For example, "expr != 0" as a top-level expression could be transformed
into "temp = (expr != 0), destructor-calls, temp".  Now fixed, by
checking again, after any transformations, that the IL convention
is observed, and inserting a "!= 0" if necessary.

11/30/94 Microsoft keyword support

The front end optionally supports certain Microsoft keywords.  The
keywords are recognized when MICROSOFT_EXTENSIONS_ALLOWED is TRUE
and when microsoft_mode is TRUE.  microsoft_mode is TRUE by default
when MICROSOFT_EXTENSIONS_ALLOWED is TRUE.  The default can be changed
by setting DEFAULT_MICROSOFT_MODE to FALSE.  The value of microsoft_mode
can also be specified using the --microsoft and --no_microsoft options.

The keywords recognized are

  __cdecl
  __fastcall
  __stdcall
  __inline
  __declspec

The __declspec modifiers recognized are

  dllimport
  dllexport
  naked
  thread

11/29/94 Branching into a try block

An error is now issued on code that attempts to branch into a try block
from outside it.

11/29/94 Static data member template instantiations

When NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS (formerly
FUNCTION_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS) is TRUE, source
sequence entries will now be generated for instantiations of template
static data members.

Moreover, with the fix of a related problem, cross reference information is
now put out on such instantiations.

11/28/94 IL lowering rewrite of lvalue-returning operations

In some complicated cases, the rewritten version of some lvalue-returning
operations produced by IL lowering had some remaining lvalue operations
in the expression tree.  For example:

   void m() {
     int i;
     ++ ++ ++i;		
   }

The middle "++" used to remain an lvalue-returning operation.

11/23/94 Change in disambiguation for error cases

The disambiguation of a function declarator versus a parenthesized
initializer formerly considered the type of the entity that would be
initialized (and whether a parenthesized initializer could be applied
to such a thing).  This was not correct, since disambiguation is
supposed to be purely syntactic.  As a consequence of this change,
some error cases are now disambiguated differently:

  void f(undefined);

This is now seen as a parenthesized initializer on a declaration of
a variable f, rather than a declaration of a function f.  The variable
has type void, so an error is then issued regarding the variable declaration.

11/18/94 Folding of constant addressing expression in initializer expressions
         for function-local variables

Folding of constant addressing expressions in initializer expressions
for function-local variables is no longer done for non-static variables.
It continues to be done for local static variables.

11/16/94 referenced flag setting on virtual conversion function reference

The referenced flag is now not set on implicit calls of virtual
conversion functions, thus avoiding an error on the following:

  struct A {
     virtual inline operator int() = 0;
  };
  void f(A& aref) {
    (int)aref;
  }

11/16/94 compiler_generated flag set in routines generated by IL lowering

IL lowering now sets the compiler_generated flag in all routine entries
it generates, including those for runtime routines.

11/15/94 IL read determination of primary scope for region

When an IL file using the alternate IL file format is read in,
the primary scope entry for each memory region (the one that goes into
region_scope_entry) has in the past been the highest-numbered entry.
Now, it is entry number 1.  This makes the determination less
sensitive to the order in which the scopes were walked on writing.

11/15/94 Incorrect assignment operator in EH code

Code generated by IL lowering to assign the current exception handling
region number to the try_region_number field in the EH stack frame had
an eok_passign operator instead of eok_iassign.  Now fixed.

11/14/94 IL CHANGE: a_local_static_variable_init

A new IL entry, a_local_static_variable_init, has been created to represent
a dynamic or aggregate-constant initialization of a local static variable.
The variable entry itself (which is in the file scope memory region) cannot
point at its initializer (which is now in the function scope memory region),
and so this construct is used to represent the initialization.  This fixes
a problem in cases like this:

  void f() {
    int i = 0;
    static int j = i;
  }

for which the resulting C++ IL was invalid -- there used to be a file scope
dynamic init for j pointing to a file scope expression that referenced
a function scope variable.  (The bug had been masked by a transformation
done by IL lowering, which copied the expression into the function scope.)

These new entries are always allocated in the function scope memory region
and appear on a list pointed to by a function or block scope.  When one is
used, the associated variable has an init kind of initk_function_local and
does not point directly to its initializer; get_variable_initializer (in
il.c) is provided to deal with such cases -- it returns the actual init
kind and a pointer to the initializer.

11/14/94 Fixed name lookup bug in friend processing

In the following case, the lookup on the friend declaration (with implicit
return type) used to be confused by the presence of "f" in the scope of A;
now it works correctly:

  class A {
    int f(void);          // Declares A::f() 
    friend f(int);        // Declares ::f(int) with implicit return type
  };

11/14/94 Computing virtual function overrides when base class is ambiguous

A bug has been fixed in managing virtual function override lists in the
presence of ambiguous base classes.  For example:

  class A { virtual void f() = 0; };
  class B : public A { void f(); };         // B::f overrides A::f
  class C1 : public B { };
  class C2 : public B { };
  class D : public C1, public C2 { };

In the context of D, the virtual function override list for the derivation
C2==>B==>A is now handled correctly -- previously only the one for
C1==>B==>A was.

10/31/94 Qualifiers on type of lvalue-returning assignments

The IL for lvalue-returning assignments and prefix ++/-- now includes
the proper type qualifiers on the result type.

10/31/94 Qualifiers on type of ++x in C mode

If x is qualified (e.g., volatile int), ++x in C mode now has the qualifiers
dropped as it should.

10/31/94 Qualifiers on type of x++

If x is qualified (e.g., volatile int), x++ now has the qualifiers dropped
as it should.

10/31/94 Type qualifiers on rewrite of lvalue-returning assignment in IL
         lowering

When IL lowering rewrites an lvalue-returning assignment, it now drops any
type qualifiers that were on the type of the assignment node to make it
legal C IL.

10/31/94 Bug in call of overloaded function with incomplete class parameter

An internal error is no longer issued for the following; an error indicating
that the parameter type is incomplete is issued instead:

  class B;
  extern B x;
  struct A {
    void f(B b);
    void f();
  };
  void m()
  {
    A f;
    f.f(x);  // Internal error here now gone.
  }

10/29/94 Bug in synthesizing an implicitly declared copy constructor

When we were generating the body of a copy constructor in ctor_initializer,
the call to select_copy_constructor was not properly taking into account
the qualifiers on the subobject.  Consequently, in this case:

  struct A { A(A&); A(); };          // No A::A(const A&) exists
  struct B { const A a; B(); };      // B::B(B&) is implicitly declared
  B x, y(x);

we not only failed to issue an error while synthesizing B::B(B&), but
we also generated a call to A::A(A&) to copy B::a.  This has now been
fixed.

10/28/94 IL CHANGE: try block and goto/label

A supplement has been added to stmk_try_block.  You can fix the affected
references in your code by the following substitutions:

  variant.try_block.statement --> variant.try_block->statement
  variant.try_block.handlers  --> variant.try_block->handlers

The variant for stmk_goto and stmk_label has been changed so that it is a
struct.  You can fix the affected references in your code by the following
substitution:

  variant.label --> variant.label.ptr

Note, however, that this change should probably be done manually because
the string may come up in other cases (it does in our code: the symbol table
has a variant label field, and the flow description entry does too).

These changes were made to make room for a pointer to an object lifetime
in those kinds of statements, in preparation for the lifetime-of-temporaries
change.

10/27/94 Keyword "restrict" added

Support for keyword "restrict" has been added, consistent with the proposal
for its incorporation into C by NCEG (see X3J11.1 Technical Report 2).  It
is recognized only if RESTRICT_ALLOWED is configured to TRUE.  The
highlights:

  (1) restrict is a new type qualifier, meaning that, in contexts where
      qualifiers are allowed, restrict is treated just like const and
      volatile (except when it is subject to special constraints).

  (2) restrict may only be applied to pointers-to-objects, including
      (with some surprising syntax) function parameter arrays that decay
      to pointers.  For instance:

        const restrict int i = 0;    // Error -- not a pointer
        const int * restrict pi;     // Okay -- restrict-ptr-to-int
        int a[restrict 10];          // Error -- not a pointer
        void f(int a[restrict 10]);  // Okay -- restrict-array-of-int
                                     //   decays to restrict-ptr-to-int

  (3) The semantics of restrict are ignored in the front end -- its purpose
      is to enable optimizations that would otherwise be prevented because
      of possible aliasing.

In C++ mode, restrict has been extended, in accord with the suggestions in
X3J16/92-0057:

  (1) restrict may be used with pointer-to-member types (when what is
      pointed to is a data member, not a member function).

  (2) restrict may be used as a qualifier on a member function, in which
      case it means the this pointer itself (not *this) is restrict
      qualified.

  (3) restrict (unlike const and volatile) may be used with references.

10/27/94 Access checking of file scope function declarations and definitions

There are a number of instances in which access checking of names that
appear in a file scope function declaration, definition, or static 
data member definition, cannot be done when the name is seen, but must
instead wait until additional information about the declaration is available.

In this example, the definition of member function A::f should be able to use
the private return type A::B.  Likewise, the friend declaration should be
able to make use of the befriending class's private types in its signature.
The access checking mechanisms have been modified to allow this kind of
usage.

  class A {
    class B {};
    B f();
    friend B g(B);
  };

  A::B A::f(){ B b; return b;}
  A::B g(A::B b){return b;}

The X3J16/WG21 committee recently voted that such usage should be permitted.

10/25/94 (int)1.5 in integral constant expression

The change made in version 2.26 to allow additional forms of expressions
as integral constant expressions (9/14/94) in non-strict mode
unfortunately broke cases that cast a floating-point constant to
an integral type.  Now fixed.

10/25/94 Promotion of bit fields under MAKE_ALL_FUNCTIONS_UNPROTOTYPED

Unsigned bit fields passed to unsigned parameters are now promoted
correctly by IL lowering (that is, usually not at all) when
MAKE_ALL_FUNCTIONS_UNPROTOTYPED is TRUE.  For example:

  extern void f(unsigned);
  struct BitField {
     unsigned int n : 2;
  } s;
  void sub ()
  {
      f(s.n);  // No cast to int added on argument now
  }


10/25/94 Conversion of Derived<T> to Base<T> on template match in strict mode

The code example shown in the fix of 7/29/94 (below) is now accepted
without error in strict mode as well as in default and cfront modes.
The standards committee recently blessed this particular conversion,
which was not allowed by the ARM.

10/25/94 C++-generating back end output of nested template references

The C++-generating back end output for a nested template reference like

  A<A<int> >

now contains the space shown, to avoid mistaking two ">"s for ">>".

10/24/94 Prelinker, eccp, and .ii file format changes

The instantiation information file (i.e., .ii file) format has
been changed to support some additional options that have been
added to the prelinker and eccp.  The format change adds two
additional lines to the header.  The new lines contain the directory name
in which the compilation was done, and the name of the file compiled.
The name of the file compiled is no longer part of the command line
in the .ii file.  The default value of INSTANTIATION_INFO_LINES_RESERVED
in host_envir.h has been changed from 1 to 3.

An eccp option (--old_ii_format) has been added that preserves the
old behavior.  This option assumes that the front end that is executed
was built with INSTANTIATION_INFO_LINES_RESERVED set to 1.  A new
edg_prelink option has been added that specifies the number of reserved
.ii file lines to be used.  The --old_ii_format option to eccp results
in the -R1 option being passed to the prelinker.  This option allows
the new eccp script and prelinker to be used with an older version
of the front end.  Setting the environment variable EDG_OLD_II_FORMAT to
1 has the same effect as providing the --old_ii_format option.

For additional information on the new eccp and prelinker options,
see the Changes file in the util directory.

10/24/94 Bug when both using and generating a PCH file

A bug has been fixed that resulted in an internal error when both using
and generating a PCH file in a given compilation.  The internal
error would occur with a front end configured to generate an IL file.

10/21/94 Using .init section for startup initialization (C-generating back end)

If USE_INIT_SECTION_IN_GENERATED_C is set to TRUE, the C-generating back
end will emit asm directives that put a call of any startup routine into
the .init section.  This can be used to eliminate the need for "patch"
and "munch".  The code generated is right for Solaris 2.n, but may have
to be changed for other systems.

10/20/94 IL CHANGE: representation of type qualification

Since we have several customers who have added new type qualifiers (i.e.,
beyond const and volatile), we have changed the IL representation of type
qualification to a bit-vector -- see a_type_qualification (defined in
il_def.h).  The variant fields in a_type have been changed (is_const and
is_volatile are no longer used), and related changes have been made in
the interface to make_qualified_type and the internals of several routines
that deal with type qualification.

10/20/94 Internal error after error on "?" operator with class rvalues

An internal error no longer occurs after the (correct) error on compiling
the following:

  struct A {
    A(const char* p);
    A(const A& s);

  };
  class B : public A {};
  extern int a;
  extern B t;
  A s(a==1 ? A("X") : A(a==2 ? t : "Y"));

10/20/94 Destruction list for global/local statics

The runtime cleanup of global and local static variables (and components
thereof) is now handled by building a list of entities that require
destruction.  This produces the proper order of destruction (i.e.,
the reverse of the construction order) for function-local static
variables.  It also eliminates the need for exception-cleanup data
structures for the file scope (since all static entities are covered
by this new list), and the test on destruction when
TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE is TRUE.
A new runtime routine __record_needed_destruction is used to put
the required destruction requests on a list.  The __std__ file-scope
termination routine is no longer needed; the runtime just uses
the list of constructed variables to do the destruction.
The new order of destruction is different from the cfront order in
some obscure cases, but the new order matches the ARM/WP and the
cfront order does not.  We have not provided a way to retain the
old ordering.  However, we have made the runtime continue to deal
with __std__ routines so that new code will be compatible with
previously-generated code and cfront-generated code.

10/19/94 Bug in setting the offset of an indirect base class

A bug has been fixed in setting the offset of an indirect base class that
is the indirect base class of a virtual base class (in cfront layout
compatibility mode only).

10/19/94 Bug in creating virtual function tables

A bug has been fixed in creating virtual function tables: at times the
virtual function number in the routine entry failed to correspond to a
element actually belonging to the vtbl.  (The problem was caused by an
unlikely combination of factors, including ambiguous base classes.)

10/19/94 Error recovery bug in declarator scanning

An internal error has been fixed in continuing from errors on array-of-
ref-type declarations.  Here's an example:

  typedef int (&T[4]);              // Internal error is now fixed

10/18/94 Default args associated with non-function member declarations

A null-pointer bug has been fixed in the delayed scanning of default
arguments when they appear in a declaration of a member that is not a
member function.  For instance,

  struct A {
    typedef void (*pf)(int = x);    // Delayed scan of x is now okay
    void (*m)(int = x);             // Delayed scan of x is now okay
    static void (*s)(int = x);      // Delayed scan of x is now okay
    static int x;
  };
  int A::x = 0;
  void f(int i) { }
  void (*A::s)(int) = &f;
  main() {
    A::pf pf = &f;
    pf();              // Call f via interface from typedef name
    A a;
    a.m = &f;
    (*a.m)();          // Call f via interface from nonstatic data member
    (*A::s)();         // Call f via interface from static data member
  }

10/16/94 Error recovery bug: assertion failure in function template decl

A spurious assertion failure has been eliminated in the cases where a
template parameter does not appear among the arguments of the function
template (causing a diagnostic) and the type matches that of a previously
declared function, e.g.:

  void f(int);
  template <class T> void f(int) { }    // Assertion failure eliminated

10/15/94 Error recovery bug: null ptr in non-file-scope class template decl

A bug has been fixed that caused a null-pointer failure during prototype
instantiation of a class template that is declared inside a function body
and includes a constructor declaration -- for example:

  void f() {
    template <class T> struct S {
      S() { }                            // Null pointer failure is fixed
    };
  }

10/14/94 Assertion failure in explicit destructor call using enum type

A bug has been fixed that caused an internal error when a enum
type was used in an explicit destructor call.

  enum E {};
  int main() 
  { 
    E e; 
    (&e)->E::~E();  // Formerly caused an assertion failure
  } 

-------------------------------------------------------------------------------
Version 2.26, October 13, 1994

10/12/94 Precompiled header processing

The front end can now write out a precompiled header file that captures
the front end state at a point after initial header inclusions, and
in another compilation (with the same initial inclusions) read in that
precompiled header file to regain that internal state quickly.  This
can significantly reduce compilation time for programs that include the
same large initial headers in many files.

The feature requires that users change their code for best results, i.e.,
that they adjust the order of inclusion of header files at the beginnings
of their source files.  Enabling the PCH feature on an arbitrary set of
source files will probably not yield much improvement in compilation
speed and may result in the use of enormous amounts of disk space for
useless PCH files.  Therefore, PCH processing is not enabled by default.
It can be enabled in two modes:

- "Automatic" mode is enabled by the --pch option.  In that mode, the
  front end will generate and use PCH files as it thinks best.  It
  will generate a separate PCH file for each different leading sequence
  that appears in the files compiled, and pick the best of all of the
  available PCH files for reuse when compiling a file.
- "Manual" mode is enabled by the --create_pch and --use_pch options.
  These name a specific PCH file, and the front end uses the file
  indicated.

The --pch_dir option can be used to specify a directory to contain
the PCH files.  The default is the current directory.

#pragma hdrstop can be used to indicate the end of the leading sequence
of inclusions to be considered for PCH optimization.  #pragma no_pch
can be used in individual files for which no PCH file should be generated
or used.

The precompiled header scheme works best on systems that support memory
mapping, but it can be configured to work on systems without such mapping
(see USE_MMAP_FOR_MEMORY_REGIONS).

See the internal documentation for more details.

Please note that if you have local mods to incorporate, and they use local
or global static variables, you may have to register the variables so that
they are properly saved and restored.  See calls of
register_pch_saved_variables for examples.

10/10/94 IL version number changed to 2.18

10/10/94 Version build date and time information

The version.h file now includes variables called build_date and
build_time that contain the date and time at which the front end
was built.  This information is used to determine whether
a precompiled header file was built by a compatible version of
the front end.  As with other global variables, these variables
are defined by the compilation of fe_init.c (so they only change
when fe_init.c is recompiled).

10/10/94 A(x) and (A)x mean the same thing and allow user-defined
         conversions on x

The explicit conversions A(x) and (A)x, with A a class type, should mean
exactly the same thing, and should allow implicit user-defined conversions
to convert x to the type of the parameter of the constructor.  Now, they
do.  Formerly, user-defined conversions were not allowed on the argument

- for A(x) when there were both constructors for A and a conversion
  function that could convert x to A, and
- for (A)x in all cases.

10/7/94  Using copy constructors for derived --> base conversions

The front end now considers copy constructors for derived --> based class
conversions even when the base class allows bitwise copy.  An example:

  struct B;
  struct A {
    A();
    A(B);
  };
  struct B : public A { B(); } b;
  void f(A);
  main () {
    A a (b);  // Has always used the A(B) copy constructor
    A c = b;  // Should use the copy constructor
    f(b);     // Should use the copy constructor
    c = b;    // Should use the copy constructor, then bitwise assign
  }

10/7/94  Fixed bug in processing abstract classes

An internal error (caused by a bug in copy_type) has been fixed -- it
showed up in the following sort of case:

  struct A {
    virtual void f() = 0;
    typedef A (F)();
    F g;                       // Internal error has been eliminated.
  };

10/6/94  C-generating back end: no #define in output

The C-generating back end has been changed to eliminate the only requirement
for preprocessing of the generated C (the macro __trunc, used to truncate 
unsigned bit fields when generating K&R C).

10/6/94  Class scope reactivation for scanning a class member declarator

A bug has been fixed in how the class scope is reactivated and deactivated
in scanning the declarator for a class member outside the class definition.
The scope is now reactivated as soon as the qualified name is seen and not
deactivated until the entire declarator has been scanned.  For example:

  struct A {
    struct X { int i; };
    void (*f())(X);
  };
  void (*A::f())(X) { return 0; }   // X used to be reported as undefined;
                                    //    now it is recognized as A::X.

(Note: there does not seem to any statement in the ARM or working paper
explicitly requiring this approach.  However, it is consistent with
existing practice, with assertions made at X3J16 meetings, and with
Stroustrup, "The C++ Programming Language", 2nd edition, p. 165.)

10/5/94  C++-generating back end: types declared in function declarators in C++

A bug in the C++-generating back end was corrected, avoiding an internal
error on certain obscure cases where a class type was declared in a
function declarator:

  void f(struct A *arg) { }
  struct A { int i; } *p;
  void f()
  {
      f(p);
  }

10/5/94  C++-generating back end: vacuous destructor calls for template classes

The C++-generating back end now puts out vacuous destructor calls for
template classes properly, e.g., as "p->S1<int>::~S1" instead of
"p->S1<int>::~S1<int>".

10/5/94  C++-generating back end: .* operator

The C++-generating back end now handles the .* operator correctly
when the left operand is a temporary.

10/5/94  C++-generating back end: reference initialized to array

The C++-generating back end now puts out the initializer for a
reference to an array correctly in the case where the initializer
is a string constant cast to another char array type.

10/5/94  C++-generating back end: fields of variable anonymous unions

The C++-generating back end now correctly puts out references to fields 
of file-scope anonymous unions.

10/5/94  Output of qualified names involving anonymous unions

The code in cp_gen_be and il_to_str that outputs qualified names has
been changed to deal correctly with anonymous unions.

10/5/94  C++-generating back end: access specifiers in anonymous unions

The output of anonymous unions in the C++-generating back end now
understands that anonymous union members inherit the current access
from the surrounding class, and no access specifiers are generated
within the anonymous union.

10/5/94  C++-generating back end: empty enumerations

Empty enumerations are now output correctly by the C++-generating back
end (where "correctly" means "without a core dump").

10/5/94  IL write: template param types that leak out of the front end

Template parameter types, which are really a front-end-only concept,
can leak out of the front end by appearing in pointers-to-members
on a based types list.  The IL write/read routines issue an internal error
on encountering such things.  The problem had been solved for most
cases by having IL lowering rewrite the offending types on the based
types list.  However, when the C++-generating back end is used, IL
lowering is not done, so the problem remained.  The problem is now fixed
by having the IL write routines write a null pointer in place of any
pointer to a tk_template_param type.

10/4/94  IL lowering: type qualifiers on source argument of generated
         copy constructor call

The source argument to the copy constructor call of B(const B&) in
D(const D&) now has the proper "const" qualifier on the type in the
following:

  struct B {
      B(const B& cob) { }
      B() { }
  };
  struct D : public B {
  };
  void test2()
  {
      D od1;
      D od2 = od1;
  }

10/3/94  Fixed bug in string representation of function template

When RECORD_TEMPLATES_IN_IL is TRUE and entries of type a_template are
created to represent a function template definition, a semicolon is no
longer added at the end of the textual representation (i.e., after the
closing brace).

10/3/94  C-generating back end: code ordering problem with local types
         inside member functions of local classes

An ordering problem in the generated C code for the following has been
fixed:

  void f() {
    struct A {
      void g() { 
        struct B {
          T x;
          B() {}
        };
      };
      typedef int T;
    };
  }

The fix was actually made in IL lowering and involves the new field
promoted_local_types in a_class_type_supplement.

10/1/94  -I- command-line option

The "-I-" command-line option is now supported.  It indicates the point
in the list of -I options where <...> includes should start searching.
That is, #include "xxx.h" searches

1)  Directories on -I directives preceding the -I-, in the order specified;
2)  Directories on -I directives following the -I-, in the order specified;
3)  Standard system include directories, e.g., /usr/include.

#include <xxx.h> will only search 2 and 3.

-I- also suppresses the pushing of the directory of the primary source
file and each include file onto the include search path, i.e., the directories
searched are only those in the list above.  This is useful for viewpathing.

10/1/94  IL lowering: constructing array when default constructor has default
         argument

Some minor problems were corrected in IL lowering, specifically in
default_version_of_routine, which is used to do constructor initialization
on an array when the default constructor has default arguments.  The
following no longer aborts:

  struct D { D(const D&); D(); } d;
  struct V { int i; };
  struct A : public virtual V {
    A(const A &, D = d);
  };
  struct B {
    A aa[100];
    B();
  };
  B b1;
  B b2 = b1;

10/1/94  IL walk of source sequence lists, prototype scope types in C

The IL walk routines have been changed so that when they are walking
IL for a C program, with source sequence lists enabled, they "walk"
instead of "remap" the pointer to a type from a source sequence list.
This avoids an internal error in some exceedingly obscure cases involving
types defined in prototype scopes, e.g.,

  long *(*x)(struct A {int member;}) = ((long *(*)(struct A))0);

9/30/94  ADD_BRACES_TO_AVOID_DANGLING_ELSE_IN_GENERATED_C

ADD_BRACES_TO_AVOID_DANGLING_ELSE_IN_GENERATED_C has been added to
targ_def.h.  It is TRUE to indicate that when generating C or C++ code,
the front end should add extra braces around "if" statements without an
"else" to avoid the "dangling else" problem.  This is necessary only
if customer code modifies the IL statement tree, so the flag is off
by default.

9/30/94  Access errors now discretionary

All access errors have been made discretionary, i.e., they can be suppressed
or demoted to warnings via a command-line option.

9/30/94  Cast as disambiguator for overloaded function

A cast can now be used to select one function out of a set of overloaded
functions:

  void f(int);
  void f(double);
  void (*p)(int) = (void (*)(int))f;

9/29/94  Missing cross-reference entry

A cross reference entry (i.e., a line in the optional cross-reference
information output file) was missing in two cases:

- The operator new function referenced in a new operator:

  void *operator new(unsigned int p) { return 0; }
  struct A { };
  A *p = new A;  // Reference to operator new was missing

- An overloaded member function in a context that disambiguates:

  struct A {
    void f(int);
    void f(double);
  };
  void (A::*pmf)(int) = &A::f;  // Reference to A::f was missing


9/29/94  Nonstandard pointers-to-member-functions

The ARM and the Working Paper insist that the only way to write a pointer
to member function is "&A::f", i.e., the "&" must be explicit and a
qualified name must be used.  Common practice expects "A::f", "&f", and
"f" to work in appropriate contexts, by analogy with normal functions.
The front end allowed the cases without the explicit "&" already.  Now,
it allows the cases without a qualified name.

9/29/94  #pragma hdrstop

Not only has code been added to recognize "#pragma hdrstop", as part of
precompiled header processing, but the directive has also been added to our
own source files.  The typical idiom is:

  #include "fe_common.h"
  #ifdef PCH_PRAGMA_GUARD
  #pragma hdrstop
  #endif /* PCH_PRAGMA_GUARD */
  #include ...

(PCH_PRAGMA_GUARD is provided to avoid diagnostics from compilers that
don't recognize #pragma hdrstop.  Whether or how it is set does not
actually affect the EDG front end's ability to recognize the pragma.)

"#pragma no_pch" is also used occasionally -- it suppresses generation of a
precompiled header file.  It appears in files for which precompiled header
file sharing is impossible.

9/29/94  New header files, new protocol for header file inclusion

Several new header files have been added:

  fe_common.h	-- inclusion of headers common to all .c files
  basic_hdrs.h  -- inclusion of several fundamental headers
  decl_hdrs.h   -- inclusion of headers used by declaration processing files
  expr_hdrs.h   -- inclusion of headers used by expression processing files
  lower_hdrs.h  -- inclusion of headers used by IL lowering files

Most .c files should include fe_common.h as the first #include:

  #include "fe_common.h"
  #include ...

The exception is when most of the headers are included conditionally, in
which case basic_hdrs.h should be first instead, e.g.:

  #include "basic_hdrs.h"
  #if XXX
  #include "fe_common.h"
  #include ...

decl_hdrs.h, expr_hdrs.h, and lower_hdrs.h, when used, are specified
immediately following fe_common.h.

There are two motivations for this change.  First, it gives better control
over the interaction of header file declarations.  Second, grouping the
headers creates opportunities for precompiled header optimization.

9/29/94  --old_line_commands command-line option

A new command-line option, --old_line_commands, works with the C and C++-
generating back ends.  It requests that #line directives in the output
be generated in the style of the output of the Reiser cpp, i.e., as
"# nnn" instead of "#line nnn".

9/29/94  Macros in string literal concatenation

A bug with string literal concatenation has been fixed.  The following
printed "hello" previously:

  #define HELLO "hello"
  main() {
    printf("%s\n", HELLO " there");
  }

9/28/94  Initial #line directives -- C and C++-generating back ends

When the front end is compiling a source file that contains #line
directives, the effective primary source file is something other
than the actual source file.  The C and C++-generating back ends
now begin their output with only a #line for the effective primary
source file.  Formerly, they generated a #line for the actual primary
source file followed immediately by a #line for the effective
primary source file.

9/27/94  Internal error when suppressing a multi-line diagnostic

If a command line option was used to change the severity of
a multi-line diagnostic (such as the overloading diagnostics that
list the set of overloaded functions), an internal error would
result.  This has been corrected.

9/27/94  Implicit inclusion and files that have already been included

The implicit inclusion mechanism will no longer attempt to reinclude
a file that has previously been explicitly or implicitly included.

9/27/94  Implicit inclusion and specializations

The compiler was incorrectly doing an implicit inclusion when
one was not necessary because a specialization had been provided
in the source file being compiled.  This has been fixed.

9/26/94  NEED_NAME_MANGLING without IL lowering

Formerly, lower_name.c did not compile correctly if one set
NEED_NAME_MANGLING to TRUE and DO_IL_LOWERING to FALSE.  That has been
corrected.

9/25/94  Hash for strings/names in looking for shareable constants

The hash algorithm used for strings and names in looking for shareable
constants (see hash_constant) has been improved to avoid some unfortunate
(slow) behavior on machine-generated strings and names.

9/19/94  Macros in IL

RECORD_MACROS_IN_IL can now be set to get IL entries for macros.  These
contain a textual representation of the macro, e.g., a string like
"#define x(a) a+1".  Such entries are useful for symbolic debugging and
for the C++-generating back end.

9/19/94  temp_text_buffer

The dynamically-allocated buffers templ_str_buffer (in templates.c) and
mangled_name_buffer (in lower_name.c) have been replaced by a generic
buffer for short-lived text, temp_text_buffer (in il.c).

9/19/94  Internal error on use of template parameter that references an
         incomplete type

A bug has been fixed that caused an internal error when a template
parameter that refers to a type that is in the processing of being defined
is dereferenced in a virtual inline function of a class template.  From a
language point of view, the point of instantiation of A<Y>::f is not yet
specified.  If the point of instantiation of a member function is
specified to be that of the class of which it is a member, then this
example would be illegal.

The front end has been changed to defer the instantiation of A<Y>::f, so
that Y is complete when the instantiation is done.

  class X { };
  template <class T> class A {
    T *p;
    virtual X f() { return *p; }
  };
  class Y : public X {
    int i;
    A<Y> a;
  };

This example also suggested a related fix: the bitwise copy of *p to type
X (derived --> base) in the return should have caused an error when
processed too early as it was, because the source type was incomplete.
Now it does.

9/19/94  Abort in invalid vacuous destructor call

A bug has been fixed that could cause the compiler to abort during
processing of an invalid vacuous destructor call in which the identifier
following the tilde was either undefined or was not a type name.

  int main() {
    int *p;
    p->~xxx(); 
  }

9/15/94  Return type checking for operator->()

The checking that is done for the return type of an operator-> function is
delayed to the point of call (if any) when the function is a member of a
class generated from a template (but not of an explicitly specialized
template class).  The error message has been improved to use fill-ins.

9/15/94  Reference to virtual destructor in delete

A delete operator for a class with a virtual destructor no longer sets the
referenced flag on the IL entry for the destructor (an overriding function
might be called instead).  If the destructor is a member function of a
template class, it is no longer instantiated because of the delete.

9/14/94  Display of nontype template arguments that are references

The il_to_str routines have been changed so that nontype template arguments
that are references are displayed properly, i.e., as something like
"A<i>" instead of "A<&i>".

9/14/94  --force_vtbl option

A --force_vtbl option has been added.  It's the complement of the
--suppress_vtbl or -V option, and the equivalent of the cfront +e1 option.

9/14/94  Additional constant expressions allowed in integral constant
         expressions

In non-strict mode, addressing expressions that reduce to an integer
constant value are now allowed as operands of casts to integral types
inside integral constant expressions.  This allows some common versions
of offsetof that don't make use of our __INTADDR__ trick.

  #define offsetof(s,m)	(size_t)&(((s *)0)->m)
  struct A {int i, j;};
  int a[offsetof(struct A, j)];  // Now allowed.

9/14/94  Another const tie-breaker tweak

The const tie-breaker processing in overload resolution has been
adjusted yet again to deal with references to pointers.  For example,

  void foo (char*);
  void foo (const char*&);
  main()
  {
	char* cp = 0;
	foo(cp);  // Was ambiguous in 2.25, now foo(char *)
  }

9/13/94  Improper operator generated by IL lowering in pointer-to-member
         comparison

The code generated by IL lowering for a pointer-to-member-function
comparison incorrectly used an integer comparison to compare two
function pointers.  Now fixed.

9/8/94   Source sequence entry on a nonstandard friend declaration

Generation of a source sequence entry and/or cross reference information
may now occur for friend declarations in which the class-key is omitted,
e.g.,

  class A;
  class B {
    friend A;     // Nonstandard decl; formerly xref entry and source
                  //   sequence entry were not put out for such cases
  };

9/8/94   Source sequence entry on instantiation of template function

A source sequence entry is no longer put out for the on-the-fly
instantiation of an inline member function of a class template; it was not
being done correctly, but it shouldn't have been done at all.  (It was only
when FUNCTION_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS was TRUE
that the problem occurred.)  Here's an example:

  template <class T> struct A {
    void f() { }
  };
  void g() {
    A<int> a;
    a.f();             // Source sequence entry is no longer issued here
                       //   for the definition of A<int>::f
  }

9/8/94   Explicit destructor calls using template parameters that
         refer to typedefs (used by STL)

It is now possible to do an explicit destructor call using a template
parameter whose type refers to a typedef, as in the following example:

  struct C {};
  template <class T> struct A {
    typedef C B;
  };

  template <class T> void f(T* t)
  {
    t->~T();
  }
  
  int main()
  {
    A<int>::B ab;
    f(&ab);
  }

9/8/94   Using processing_C_code_in_pragma without expand_macros

It is now possible to set processing_C_code_in_pragma to TRUE
while expand_macros is set to FALSE.  Formerly, this was not possible
because identifiers were only looked up (in preprocessing directives)
when macros were being expanded.

9/8/94   A() when A is a class without a constructor

A functional-notation type conversion of the form A(), where A is a class
without a constructor, is now accepted (this was invalid in the ARM,
but it's valid in the current WP).

9/8/94   IL CHANGE: dik_zero

A dynamic initialization can now have kind dik_zero, which means
"initialize to zero."  It's defined to work the same way as the default
initialization of a static object.  It is used for initializations for
expressions of the form A(), where A is a class without a constructor.
IL lowering eliminates dik_zero, so back ends that run after IL lowering
will see no difference.

9/8/94   Abort when a function type is used as a template static data member

In this example, "a" may be a static data member or a member function
depending on whether or not T is a function type.  The language does
not specify how this should be handled, we have chosen to make this an
error pending clarification by X3J16/WG21.

  template <class T> struct A {
    static T a;
  };
  A<int> x;        // OK
  A<int (int)> y;  // aborted

9/7/94   Order in which different pragma kinds are processed

Formerly, if an immediate pragma was followed by a next construct pragma, the
next construct pragma would be processed first.  This has been changed
so that any immediate pragmas will be processed when
select_curr_construct_pragmas is called. 

9/7/94   Storage class of static template functions

A bug was introduced into version 2.17 that caused static (nonmember)
template functions to be given a storage class of sc_unspecified instead
of sc_static.  This has been fixed.

9/7/94   Qualifiers on function types

If a multiply declared function had a type with a top-level qualifier, the
redeclaration was not properly recognized and an internal error occurred in
trying to create an overload set.  This has now been fixed.  For example:

  typeref void T();
  extern const T f;
  const T f;                   // Internal error has been eliminated

9/7/94   address_taken on routines and variables in IL lowering

IL lowering did not set address_taken on routines passed to __vec_new
and the like, nor on variables whose addresses are placed in exception
handling data structures.  Now it does.

9/6/94   Conversions on template nontype arguments

Recent X3J16/WG21 decisions have made it clear that conversions (other than
user-defined conversions) are allowed on template nontype arguments.  We've
relaxed the checking to conform.  In the process, we fixed a bug demonstrated
by the following test case (in strict mode only):

  template <class T, T x> class A { };
  template <class T> A<T, 0> f(T p);  // Formerly, an error on this line

9/2/94   Access control for nested classes

In all modes except strict mode, nested classes are now given access
to enclosing classes.  This is contrary to the WP/ARM statement that
"Member functions of a nested class have no special access to members
of an enclosing class", but (a) users have asked for that access, and
(b) the standards committee seems to be leaning towards eliminating the
restriction.  In strict mode, we've tightened the access checking
to be exactly what is indicated in the WP.

We've also fixed a bug with access checking from within a local class
inside a member function -- the code there should have access to the
members of the outer class, since the inner class is not a nested class.

9/2/94   "static" with anonymous unions within a class

We used to issue an error message saying that an anonymous union cannot be
a static data member.  Now we complain about an omitted declarator.  This
change also has an effect on error recovery in obscure cases.

9/1/94   Extension to allow nonstandard anonymous unions

It is a misnomer, since it allows anonymous structs and classes as well,
but the extension is controlled by ALLOW_NONSTANDARD_ANONYMOUS_UNIONS,
defined in lang_feat.h.  The extension emulates functionality provided
by Microsoft C and C++ compilers, including the following:
  o anonymous unions are allowed in C mode;
  o classes (C++ only) and structs are also allowed --- that is, their
    members are promoted to the scope of the containing class and looked
    up like ordinary members;
  o they can be introduced into the containing class by a typedef name
    (i.e., they needn't be declared directly, as with true anonymous
    unions); and
  o in C mode a tag may be declared.

Here's an example:

  typedef union { int i, j; } U;
  struct S {
    int k;
    U;                  // Okay; code may refer to S::i and S::j
  };

Among the restrictions: the extension only applies to constructs within
classes, and in C++ mode the anonymous class must be an "aggregate" with
no member functions (user-defined or generated by the compiler).

In C++ the high level (unlowered) IL representation for a true anonymous
union is as it has always been -- i.e., the anonymous parent object is
elided.  But in the IL representation of nonstandard constructs (in both C
and C++) the anonymous parent object is always explicit, and so for those
cases there is no need to rely on fields in the class type supplement.

9/1/94   Added is_anonymous_parent_object to a_field, a_variable

The flag is_anonymous_parent_object has been added to a_variable and
a_field.  (An "anonymous parent object" is the unnamed variable or field
implied by an anonymous union declaration. but the term also applies to
other unnamed objects when ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE.)

In a related change, sk_field symbols no longer have a variant field
pointing to the IL entry for an anonymous union variable; instead they
have a pointer to a symbol for an anonymous parent object (which may be a
field as well as a variable).  Such symbols are not entered directly in
the symbol table -- they have no names -- and the associated IL entries
will have the is_anonymous_parent_object_flag set.

8/31/94  typedefs ignored in determination of conversions for builtin op

Typedefs weren't being ignored in one case dealing with determining
user-defined conversions that apply on built-in pointer operations.
That caused a false ambiguity on the following:

  typedef char CHAR;
  typedef const CHAR *PCC;
  struct A {
     operator PCC() const;
  };
  main() {
    A x;
    const char *p = 0;
    p - x;  // Got false ambiguity.
  }

8/30/94  address_taken flag on lowering-generated init/term routines

The address_taken flag in the routine entries for the initialization and
termination routines generated by IL lowering is now set if pointers
to those routines are placed in a __link variable structure.

8/30/94  (void *)0 == (void *)0 in C mode

A case like the above was not recognized as valid in C mode.  Now fixed.

8/22/94  Fix bug in #unassert

A bug has been fixed that would cause an #unassert directive to
either fail to work properly, or on some systems to cause the compiler
to abort.

-------------------------------------------------------------------------------
Version 2.25, August 19, 1994

8/18/94  IL version number changed to 2.17

8/18/94  const or volatile in new expression

The prohibition of const and volatile qualifiers in a type-specifier-seq of
a new-type-id of a new-expression (WP 5.3.4) was enforced (in strict ANSI
mode) in a way that improperly extended to the parenthesized type-id as
well.  That has been fixed:

  const int *p = new const int;     // Syntax error (in strict ANSI mode)
  const int *q = new (const int);   // Now okay (spurious error used to be
                                         issued in strict ANSI mode)

8/18/94  Suppressing redundant inclusion of header files

The front end now recognizes header files that, if included again,
would have no effect.  The idioms recognized are:

  #ifndef NAME      (or #ifdef)
  ... code ...
  #endif

and

  #pragma once

Note that recognition of "#if !defined(NAME)" is not currently supported.

8/17/94  Source sequence entries for template instantiations

When FUNCTION_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE,
source sequence entries are put out for function template instantiations,
and when CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE
they are put out for class template instantiations.  Defined in
host_envir.h, both flags require GENERATE_SOURCE_SEQUENCE_LISTS to be set.
Both are FALSE by default.

8/17/94  Restriction on type qualifier applied to reference type

We used to issue a warning that the construct was meaningless.  In fact it
now violates the C++ grammar, so we modified the text of the diagnostic
and issue an error in strict ANSI mode.  Undiagnosed by cfront, it is still
accepted with a warning in default mode.

Also, a bug related to this has been fixed.  If one uses a typedef to
circumvent the syntax restriction, the type qualifier is supposed to be
ignored (WP 8.3.2).  A change has been made to do exactly that, and in
general qualifiers will no longer appear on reference types.  For example:

  typedef int & RI;
  const RI x;            // The type for x is now recorded as "reference
                         //   to int" rather than "const reference to int"

8/17/94  Diagnostic severity on missing initializer

A diagnostic of severity es_discretionary_error is now issued for the
following cases in which an initializer is missing:
  o  a variable of class (or array-of-class) type where there are const
     and/or ref members (used to be es_error)
  o  an object this is created by a new expression with a type that is
     -- const qualified (used to be es_warning)
     -- a class (or array of class) where there are const and/or ref
        members (used to be es_error)
Now the cases are handled consistently, but the severities may be reduced
by a command line option.

8/17/94  Diagnostic on "const" or "volatile" in new-expression

In strict ANSI mode we used to issue a warning if "const" or "volatile"
appeared in type-specifier-seq in a new-expression.  The diagnostic now
uses strict_ansi_error_severity, which means it may be an error in -A
mode.

8/16/94  x ? base : derived

A conditional expression that juxtaposes a base class lvalue and a
derived class lvalue is now valid even if the lvalues did not come
from references.  The derived-class operand is converted to the
base class.

8/16/94  &x.f where f is a set of overloaded static member functions

&x.f, where f is a set of overloaded static member functions, is now
accepted.

8/16/94  Function type from typedef in function template definition

An error is now issued if the function type in a function template
definition is a typedef name -- e.g.,

  typedef void (FT)();
  template <class T> class A {
    FT f;
  };
  template <class T> FT A<T>::f { }    // Error is now issued

8/16/94  Deleting a pointer to const

Deleting a pointer to const is now allowed in non-strict mode.

8/16/94  const as a tie-breaker in overload resolution, a tweak

The change for const as a tie-breaker in overload resolution was a little
too broad.  It assumed a conversion that added a type qualifier under a
pointer or reference is always worse that an otherwise equally-weighted
conversion.  Common practice is that that is the case only if one
conversion is a subsequence of the other.

8/16/94  Initialization of variable created to hold pointer-to-member constant

The fix of this problem (7/5/94), related to cases when IL lowering creates
a variable that is initialized to an aggregate value for a pointer-to-
member, had another bug.  Now *really* fixed.

8/15/94  Applying type qualifier to a typedef

A change has been made to make_qualified_type to preserve typedef
information in the type that is returned.  For example:

  typedef const int CI;
  volatile CI x;           // Type recorded for x is now "volatile CI"
                           //   rather than "const volatile int"
  const volatile CI y;     // Type recorded for y is now "volatile CI"
                           //   rather than "const volatile int" (C++
                           //   only -- it's an error in C mode)

8/15/94  Wide character constants with more than one character

A wide character constant like L'ab' contains more information than can be
stuffed in the output wchar_t, and as such is suspect.  However, the C
standard makes such things implementation-defined, and two test suites
that we know of include tests that check that L'ab' is accepted (even
though it has no portable meaning).  We've changed the front end to
issue a warning and discard the extra characters.

8/12/94  Consolidated routines to convert constants and types to string form

Some of our customers have pointed out the embarrassing fact that we
had 5 or 6 different copies of routines that produce output strings for
constants and types.  Embarrassment is a great motivator, so we've
consolidated those routines into one set in il_to_str.c.  Of course,
there are some variations in the output desired in those various cases,
so the consolidated routines have about a zillion option flags.  Still,
it's a big improvement over what was there, and there's a substantial
net savings in lines of code.  The places that had their own routines
and now use the consolidated routines are c_gen_be.c, cp_gen_be.c,
error.c, il_display.c, il.c, and symbol_tbl.c.

8/12/94  Default arguments in function template declarations

A bug has been fixed that would cause a spurious error if the default
argument declarations for a function template were spread among several
declarations.

  template <class T> int f(T t, int i, int j = 3);
  template <class T> int f(T t, int i = 2, int j);
  int main()
  {
    f(10);
  }

8/9/94   Diagnostic on omitted access specifier on base class declaration

A remark (instead of a warning) is now issued when the access specifier
is omitted in a base-specifier declaration.

8/9/94   Cross-reference name display

Fully qualified names are now put out to the cross-reference output file.
Also, template arguments may be displayed for type names and class
qualifiers.

8/9/94   Cross-reference information on undefined names in declarations

We now put out cross-reference information when an undefined name appears
in a declaration, as had already been done for undefined names in
expressions.

8/9/94   Old-style parameter lists in C++

In C++ mode, when anachronism support is turned off, a function parameter
list is now always parsed as a prototyped list, never as an old-style
param list.  This affects how errors are reported -- e.g., if S has
not yet been declared:

  void f(S);      // Error is now issued for undefined name "S" rather than
                  //   for using an old-style param declaration.

8/9/94   Automatic instantiation bug

A bug has been fixed that could cause the automatic instantiation
mechanism to fail.  The problem occurs when a specific declaration
of a template function occurs after the function has already been
instantiated.  This could occur if a subsequent instantiation results
in the instantiation of a class that declares the function as a friend.

8/9/94   Class layout processing

This is just a repackaging of the same functionality: now instead of
allocating nonvirtual base classes early, allocating nonstatic data
members on the fly, and then calling finish_laying_out_class at the end of
the class definition to handle virtual base classes, etc., all class
layout processing has been consolidated in do_class_layout (called at the
end of scanning the class definition).  This will make it more convenient
to customize the way in which classes are laid out.

8/8/94   Using new to create object with uninitialized const or ref fields

An error is now issued (instead of a warning) when new is used, with no
explicit initializer, to create an object with const or ref fields, e.g.,

  class X {
    const int i;
  };                            // Still a warning for "missing" ctor
  void f() {
    X *px = new X;              // Error now issued because px->i is
  }                             //   uninitialized.

8/8/94   C mode: a struct with no named fields

An error is now issued in C mode whenever a struct or union is defined
with no named fields.  The following used to be allowed (it's undefined
behavior in ANSI/ISO C):

  struct S { int:0; };               // Now an error in C mode

As a result of this change, an internal error is now fixed in how the
following is handled:

  struct S { int:1 } s[] = { 0 };    // No internal error in C mode

8/8/94   Bug in disambiguation of function declarators with default arguments

A bug has been fixed that caused the declaration of fptr to be
interpreted incorrectly.

  int i, j;
  int f(int, int);
  int main()
  {
    int (*fptr)(int = i, int = j) = &f;
  }

8/5/94   Specifying the name of the generated C file

A new command line option (--gen_c_file_name) has been added that
enables the driver to provide the file name to be used when
creating a generated C file.

8/2/94   IL CHANGE:  a_template, a_macro

If RECORD_TEMPLATES_IN_IL is TRUE, entries of type a_template are included
in the IL.  They contain a pointer to the textual representation of a
template declaration.  Similarly, entries of type a_macro are put out if
RECORD_MACROS_IN_IL is set; they point to null-terminated strings that
represent #define preprocessor directive.

8/2/94   Freeing of IL memory when multiple source files are compiled

When COMPILE_MULTIPLE_SOURCE_FILES is enabled, and no IL file is
used (i.e., the IL is passed in memory to the back end), the front end
had not been freeing the IL for function scopes between compilations.
It does now.

8/1/94   rvalue . field when rvalue requires a base-class adjustment

"rvalue . field", where "rvalue" is a class rvalue of a derived class
that must be converted to a base class to do the field selection,
was formerly incorrectly considered to be an lvalue.  Now it's an rvalue.

  struct B {int b;};
  struct D : public B {};
  D f();
  int main() {
     int *p = &(f().b);  // Gets error now
  }

7/31/94  Integer --> enum implicit conversions now a cfront 2.1-ism

Integer --> enum implicit conversions, which were formerly considered
an anachronism, are now classified as a cfront 2.1-ism.

7/29/94  Template function matching bug found while compiling STL

A bug has been fixed that caused errors when compiling STL.  The
derived to base<T> conversion that is applied to certain function
template arguments was not being applied when the actual argument
was a nested class.

  template <class T> struct B { };
  template <class T> struct A {
    class AA : public B<T> {};
  };

  template <class T> void g(B<T>);

  template <class T> void f(T t)
  {
    g(t);  // Error on this line before fix
  }

  int main()
  {
    A<int>::AA aa;
    f(aa);
  }

7/28/94  Repackaging of decls.c and class_decl.c

Because decls.c and class_decl.c were getting too large, we have moved
some of their routines to new files:

  disambig.c   -- contains f_is_decl_not_expr and its subroutines.

  decl_spec.c  -- contains decl_specifiers and its subroutines (including
                  class_specifier from class_decl.c).  The associated
                  header file decl_spec.h now contains the definitions of
                  DSI_xxx and DSO_xxx values.

  declarator.c -- contains declarator and its subroutines; declarator.h
                  contains the definitions of DI_xxx and DO_xxx values.

  func_def.c   -- contains function_definition and scan_function_body
                  (with the SFB_xxx definitions moved to func_def.h);
                  it also contains code, formerly in class_decl.c, to
                  produce the IL for compiler-generated function bodies.

7/28/94  New files symbol_ref.c and symbol_ref.h

Routines dealing with symbol references (including the one that puts out
cross reference information) have been moved from symbol_tbl.c to a new
file symbol_ref.c.  Likewise the #defines for SRK_xxx values have been
relocated to symbol_ref.h.  This repackaging should help customers who are
customizing xref support (as well as reduce the size of symbol_tbl.c
a little).

7/27/94  Extra semicolon diagnostic now a discretionary error

In strict ANSI (-A) mode, an extra semicolon is now a discretionary
error, meaning that it may be overridden using a command line option.

7/26/94  Pragmas in classes in C++-generating back end

The C++-generating back end now correctly handles pragmas inside class
definitions.

7/18/94  Possible ordering problem in lowered code for ptr-to-member call

The lowered code for a pointer-to-member call included an adjustment of
a temporary variable in the expression that specifies the function
to be called, and a use of that temporary as an argument to the call.
The order of evaluation of those two expressions is not guaranteed
by the C standard, so we've added another temporary variable and moved
the adjustment code into a comma expression outside the function call.

7/16/94  Internal error in decls.c on constructor declaration

An internal error in decls.c has been corrected.  It occurred on a
constructor declaration when there was a typedef for the class type
with the same name as the class:

  typedef struct A A;
  struct A {
    A() {}  // Internal error here now gone
  };


-------------------------------------------------------------------------------
Version 2.24, July 8, 1994

7/8/94   IL version number changed to 2.16

7/8/94   Incorrect handling of pragmas that begin with the same string

A bug has been fixed that would result in a pragma being incorrectly
interpreted as another pragma that begins with the same characters.
For example, a pragma named "test1" might incorrectly have been interpreted
as "test".

7/8/94   Tag kind resolution for incompletely instantiated template class

The tag kind of an incompletely instantiated template class is now
adjusted to agree with the tag kind of a subsequent class template
definition.  For instance:

  template <class T> class A;      // class template A starts out as "class"
  A<int> *pa;                      // incompletely instantiated A<int> is
                                   //   also marked as "class"
  template <class T> struct A {    // class template A is changed to "struct"
    int i;                         //   -- and now A<int> is changed to
  };                               //   "struct" also.
  main() {
    pa->i = 0;                     // A<int> is instantiated; spurious error
  }                                //   (inaccessible A<int>::i) is no longer
                                   //   issued

7/6/94   Diagnostic on storage class with autonomous tag declaration

An error (but still a warning in cfront mode) is issued when a storage
class appears on an autonomous tag declaration.  For example:

  static class A { };               // Error in default C++ mode

7/6/94   K&R/pcc mode conversion between integers and pointers

In K&R/pcc mode, implicit conversions are now allowed between integers
and pointers even if the integer is smaller than the pointer, and also
in comparisons.  A warning is issued.

  main () {
    char a;
    if (a > "  B ");  /* Okay with warning. */
    a = "  B ";       /* Okay with warning. */
  }

7/5/94   Initialization of variable created to hold pointer-to-member constant

For a case where a pointer-to-member-function constant is used in an
expression, IL lowering creates a dummy variable that is initialized to
the proper aggregate value for the pointer-to-member.  The variable is
then used in the expression.  When such pointers-to-members were used
in constructor mem-initializers, the resulting IL was incorrect, because
it had an automatic variable initialized with a static initialization.
That has been changed to a dynamic initialization.

7/4/94   Argument of class type that allows bitwise copy but has destructor

Arguments of a class type that allows bitwise copy construction but
also has a destructor are now treated like arguments of classes with
"real" copy constructors.  That is, a copy is made, the address of the
copy is passed as the argument, and the destructor is called on the
copy after the call returns.  Formerly, the copy was made by passing
the class object by value, and the destructor was never called.  The old
behavior is preserved in cfront compatibility mode.

7/4/94   Top-level const on lowered routine with modifiable "this"

When assignment to "this" is done within a member function, or when
"this" is modified within a constructor because the "new" operation is
done therein, IL lowering drops the top-level "const" from the "this"
variable.  Now, the "const" is dropped also from the implicit "this"
parameter type attached to the routine type.

6/30/94  Distinguishing a template-id from a declarator-id

A bug has been fixed in declarator processing -- a template-id is no
longer mistaken for a declarator-id.  We now diagnose errors in the
following:

  template <class T> class A {};
  void f(A<int> A<int>);           // error (missing comma) is now issued
  static A<int> A<int>;            // errors (missing identifier, missing
                                   //   semicolon) are now issued

6/30/94  const/volatile as tie-breaker in overload resolution

The way that const/volatile serve as tie-breakers in overload resolution
has been changed.  The new way matches cfront more closely and is also
what Bjarne intended (I asked him).

  struct A {};
  void f(const A*, short);
  void f(A*, int);
  main ()
  {
    A a;
    f(&a, (short)1);  // No longer ambiguous; f(const A*, short) chosen
  }

6/30/94  Last bit in bit vectors for decl_specifiers and declarator

Names have been introduced to identify the last bit defined for the bit
vectors that pass boolean information into and out of decl_specifiers and
declarator.  They are DI_LAST, DO_LAST, DSI_LAST, and DSO_LAST.  They can
be used as the basis for defining additional bits if you want to customize
the interfaces to those routines.

6/30/94  Error on parameter type

In accord with a recent change to WP 8.3.5, we now issue an error on a
function parameter type that involves a pointer or reference to an array
of unknown bounds.

6/29/94  Template abort fixed

Use of a nested class within a nonreal instantiation as a template argument
could result in a compiler abort.  This has been fixed.

  template <class T> struct T1 {
    struct T1A {};
  };

  template <class T> struct T3 { };

  template <class T> struct T2 {
    struct T2A {};
    typedef T1<T2A>::T1A xxx;
    T3<xxx> t3;  // Abort on this line
  };

6/29/94  Overridding the severity of diagnostic messages

Command line options have been added that allow a user to override the
severity of specified diagnostics.  The new severity may only be used to
alter the severity of diagnostics whose original severity is less severe
than an error.  A new severity called discretionary error has been added.
A discretionary error may have its severity altered by the severity
overriding mechanism.

6/29/94  Option to display error numbers

When using the severity overridding mechanism, it is sometimes helpful to
know the error number of a given diagnostic.  The --display_error_number
command line option causes the error number to be displayed as part of the
diagnostic output.

6/29/94  New error message files

As part of the error severity overriding mechanism, the method used to add
and modify error messages has been changed.  Two new files (error_msg.txt
and error_tag.txt) have been added.  A new utility program (mk_errinfo)
translates these files into header files (err_codes.h and err_date.h)
compiled into the front end.  See the comments in the .txt files and the
utilities chapter in the internals manual for more information.

6/29/94 result_is_not_used flag maintenance in IL lowering

A bug in IL lowering has been fixed.  The problem was that some
constructor calls used in field selections were marked with
result_is_not_used TRUE even though the result of the call was used by the
field selection.

6/29/94 cfront compatibility: ptr-to-member-function cast to ptr-to-function

In cfront compatibility mode, it is now legal to cast a constant pointer-
to-member function to a pointer-to-function.  A warning is issued.

  struct A {int f();};
  main () {
    int (*p)();
    p = (int (*)())A::f;  // Okay, with warning
  }

6/29/94 IL CHANGE: name changes related to exception specifications

The names of types defined to support exceptions specifications have been
changed to conform with the usage in the ARM and elsewhere:

  a_throw_specification   ==> an_exception_specification
  a_throw_spec_type       ==> an_exception_specification_type

Also, exception_specification replaces throw_specification to designate
the field in a_routine_type_supplement, and iek_exception_specification
and iek_exception_specification_type now appear as members of the
enumeration an_il_entry_kind.  In addition, some error codes were renamed,
and error messages for the following error codes were reworded:

   ec_redundant_exception_specification_type
   ec_incompatible_exception_specification
   ec_omitted_exception_specification
   ec_exception_specification_not_allowed

6/29/94 IL CHANGE: representation of field offset

The field bit_offset in a_field has been replaced with two fields, offset,
which gives the byte offset of the field, and offset_bit_remainder, which
gives the additional bit count that is to be reckoned in when the offset
of a bit field is computed.  The new fields relate to the old one as
follows:

  offset                = bit_offset / targ_char_bit
  offset_bit_remainder  = bit_offset % targ_char_bit

and therefore:

  for ordinary fields:  offset_bit_remainder = 0
  for bit fields:       0 <= offset_bit_remainder < targ_char_bit

6/28/94 Related class casts folded into constants in initializer expressions

In initializer expressions in C++ that can be constant or nonconstant,
base/derived-class casts are now folded as constant addresses instead
of being rendered as dynamic initializations.

6/28/94 Friend declaration of member function may not be a definition

An error is now issued when a friend declaration of a member function
provides a definition of the function (see WP 11.4 para 5).

6/28/94 Fixed support for elaborated type specifier using a typedef name

There was a bug in our support for using a typedef name in an elaborated
type specifier (a "nonstandard" feature that is available in cfront mode
only) -- the code generated for a case like this is now correct:

  typedef class A T;
  class T *pa;                  // Allowed in cfront mode only

6/28/94 Initialization of static data member of class with private dtor

A spurious error is no longer issued on initializations of a static data
member where the destructor is private.  For example:

  class C {
    C(int);
    ~C();
  public:
    static C c;
  };
  C C::c(1);                   // Spurious error on inaccessibility of
                               //   C::~C() is no longer issued

6/27/94 jmp_buf type as array of long double, if desired

Additional configuration flags have been added to targ_def.h to allow
configuring jmp_buf (the type used by setjmp/longjmp) as an array of
some kind of floating-point type (instead of an array of some integral
type).  This was requested by a customer for a machine where the only
way to get the right alignment for the array was to use an array of
long doubles.

6/27/94 required_buffer_size parameter on decode_identifier

There is now a required_buffer_size parameter in decode_identifier
(the name demangling function), which returns the buffer size needed.
That is useful when a buffer overflow occurs (it tells you how big a
buffer must be allocated to try again).

6/27/94 Specific declaration of inline function template

An error is now issued (rather than an internal error) if an instance of
an inline function template is referenced (and therefore instantiated "on
the fly"), and then a specific declaration appears.  For example:

  template <class T> inline void f(T) { }
  void g() {
    f(1);                    // Causes instantiation of f(int)
  }
  inline void f(int) { }     // Error -- specific definition must precede
                             //   reference when template is "inline"

6/26/94 Explicit cast of pointer to too-small integer okay in C

An explicit cast of a pointer to an integral type that's too small to
contain the pointer is now allowed in C mode.  For example:

  main () {
    short k;
    k = (short) "cc";        // Gets warning instead of error now
  }

6/26/94 Fixed spurious error on initialization of const field with ctor

An error was incorrectly issued on not explicitly mentioning a const field
in a ctor-initializer list even when the field was of class type and the
class has a default constructor.  This has been fixed, as has the related
diagnostic on a class with no user-defined constructor.  For example:

  struct S { S(); };
  class A {
    const S s;
    A() { };                 // Error is no longer issued on failing to
  };                         //   mention s in the ctor-initializer list
  class B {                  // Error is no longer issued on failing to
    const S s;               //   declare a constructor to initialize s
  };

6/25/94 Implicit conversions between pointers to interchangeable types in C++

Implicit conversions between pointers to interchangeable types (e.g.,
"unsigned char *" --> "char *" are no longer allowed in C++ mode.  They are
still allowed in C mode, with a warning.

6/24/94 f().i is, once again, an rvalue

Undoing a change of 5/4/93, f().i is once again an rvalue.  This had been
changed because the standards committee seemed to be reaching consensus
that f().i is an lvalue, but then it went the other way.

6/24/94 IL CHANGE: definition_put_out removed

The field definition_put_out, which was used only by the C++-generating
back end, is no longer needed and has been removed.

6/24/94 IL CHANGE: rout_src_seq_entry_for_default_arg_decl removed

This field, added in version 2.23 to a_param_type (and used only when
GENERATE_SOURCE_SEQUENCE_LISTS was set), is no longer needed.  The
information it provided is now available with the declared_type fields of
a_routine and a_src_seq_secondary_decl.

6/24/94 Obsolete source files removed

A number of files that are no longer used have been removed from the
front end source directory.  trans_lims.h and mem_tables.c have been
removed completely.  getopt.h, which is no longer used by the front end but
is still used by the utility programs, has been moved to the util directory.

6/23/94 IL CHANGE: declared_type in routine and variable entries

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, a new field, declared_type,
appears in a_routine and a_variable.  It refers to the type that the user
specified in the defining declaration of the entity.  This information is
useful to the C++-generating back for reconstructing the original sequence
of declarations, since the ultimate type of a variable or routine could be
a product of several declarations.

6/23/94 Include directory list when using STACK_REFERENCED_INCLUDE_DIRECTORIES

When using stacked include directories, the directory associated with the
primary source file appeared on the list twice.  Also, the directories
associated with implicitly included files were not being removed from
the list.  These problems have been corrected.

6/23/94 Instantiation file suffix list and multiple compilations

The include file suffix list was allocated in front end memory when
it should have been allocated in general memory.  This could
cause compilation failures and/or aborts when compiling
multiple files in a single front-end invocation.

6/22/94 IL CHANGE: break_label and continue_label flags in a_label

break_label and continue_label flags have been added to a_label to identify
labels generated by the front end as targets for gotos generated for
break and continue statements.  The C++-generating back end now uses
those flags to recreate break and continue statements in their original
form.

6/22/94 IL CHANGE: declared_type recorded in a_src_seq_secondary_decl

A new field has been added to entries in a source-sequence list that
represent secondary declarations -- the "declared type".  This is useful for
reconstructing the original source when the type on the entity differs from
the type used in the secondary declaration.  Here's an example:

  typedef void (F)();
  F f;
  void f() { }

The source sequence entry for the first declaration of f points to a
secondary-decl entry that in turn points to the typedef F.

In a related change, a declaration that is not a primary declaration (e.g.,
an extern declaration or a function declaration where no body is provided)
is always represented now with a secondary-decl entry -- it used to be that
the first such declaration was treated as the primary declaration when no
"real" primary declaration appeared later.  (The old convention is still
retained in C mode for tentative variable definitions.)

6/22/94 C++-generating BE: Elimination of unnecessary casts on ptrs-to-members

The C++-generating back end no longer puts out some unnecessary casts on
pointer-to-member constants.  These casts, though correct, tickled a bug in
cfront.

6/22/94 Internal error on class_decl.c checking code fixed

A piece of checking code in class_decl.c was missing a skip_typerefs,
which could cause an internal error on some strange template cases.
Now fixed.

  template <class T> struct A {
      typedef T* p;
  };
  template <class T> struct V {
      typedef A<T> V_A;
      typedef V_A::p I;
      I a;
  };
  main()
  {
  	V<int> v1;
  }


6/20/94 C/C++-generating back end output of small integer constants

The C/C++-generating back ends now output integer constants with types
shorter than int (e.g., short) with a leading cast to get the right
type.  This solves an overloading problem with the output of the
C++-generating back end.

6/20/94 Concatenation of adjacent string literals

The lexical concatenation of adjacent string literals in get_token
is now done is a somewhat different way.  The old technique used
ridiculous amounts of memory for cases that involved thousands of
adjacent strings (seen in a machine-generated program).  The new
technique is more reasonable in its memory use.

6/17/94 Instantiation information file only created when the back end is run

The front end and eccp driver script have been modified to only create
an instantiation information (.ii) file when the back end is run.  In
other words, the creation (or deletion) of the .ii file is suppressed
when there are compilation errors or if one of the "front end only"
options (e.g., --no_il_lowering (-N) or --no_code_gen (-n)) options is used.

6/17/94 cfront 3.0 compatibility mode

A cfront 3.0 compatibility mode is now supported in addition to the
previously supported cfront 2.1 mode.  Cfront 3.0 mode includes a
subset of the features supported by cfront 2.1 mode.  Cfront 3.0 mode is
specified using the --cfront_3.0 command line option.  The External
Interface chapter describes the features supported by each of the
cfront modes.

6/14/94 Invalid template operator function internal error

If the declaration of a template operator function contained an
invalid class qualifier an internal error could result.  This
has been corrected.

  template <class T1, class T2> struct A {
    void operator()(T1);
  };
  template <class T1, class T2> void A<T2, T1>::operator()(T1){}
  //                                   ^^^^^^ should be T1, T2

6/11/94 IL CHANGE: some name hiding is recorded in the IL

When a new configuration flag RECORD_HIDDEN_NAMES_IN_IL is TRUE, certain
hidden names are recorded in a list of entries of type a_hidden_name,
pointed to from an IL scope entry.  The information is intended for use by
the C++-generating back end, so that it knows when it has to use global
qualification or an elaborated type specifier to generate accurate code.
Here are cases in which the entries are created:

  class A { int i; };
  int A = 0;             // class A is hidden by the variable declaration
                         //   but can be unhidden if an elaborated type
                         //   specifier is used.
  void f() {
    int A;               // file scope variable A is hidden but can be
  }                      //   unhidden if a leading "::" is used.

This data structure is used by the C++-generating back end to avoid
leading "::" qualifiers and elaborated type specifiers when they are not
needed.

6/11/94 Change in STAT_FIRST_PARAM_IS_CONST and GETOPT_PARAMS_ARE_NOT_CONST

Formerly these flags were tested using #ifdef tests, so the value to
which they were set was not significant.  These flags are now tested
using #if tests, so they must be set to a TRUE value in order to have
the desired effect.

The default for STAT_FIRST_PARAM_IS_CONST has been changed.  The first
parameter of the stat function is now const by default.

6/11/94 Typedefs preserved on constant types

When a constant is cast to a new type, the typedefs on the type are now
preserved.

6/10/94 Changes in command line option handling

A number of changes have been made in the processing of command
line arguments.

1. The front end now supports keyword options such as --exceptions.

2. A few of the single letter options whose use did not match common
   practice have been eliminated.  Specifically, -O (anachronisms)
   and -S (error output file) are no longer recognized by the
   front end.  The keyword equivalents --anachronisms (or --no_anachronisms)
   and --error_output must be used instead.

3. The single letter options that select the opposite of some default value
   have been modified to select a given behavior regardless of the default
   value.  The affected options are -x (exception handling), -T
   (automatic instantiation), and -B (implicit inclusion).  -O (anachronisms)
   also worked this way, but as described above, -O has been eliminated
   altogether.

   -x now always turns exceptions on and is equivalent to --exceptions.
   --no_exceptions may be used to disable exceptions if exceptions are
   enabled by default.

   -T now always turns automatic instantiation on and is equivalent to
   --auto_instantiation.  --no_auto_instantiation may be used to disable
   automatic instantiation if it is enabled by default.

   -B now always turns implicit inclusion on and is equivalent to
   --implicit_include.  --no_implicit_include may be used to disable
   implicit inclusion if it is enabled by default.

6/10/94 Change in default for support of anachronisms

When compiling C++ code, anachronisms are now disabled by default.

6/8/94  IL CHANGE: originally_unnamed field in class types

originally_unnamed in class types now indicates types that were
originally unnamed.  Most of those remain unnamed, but some get names
from typedefs.  This flag is used by the C++-generating back end to
process cases like

  typedef struct { int A; } A;

6/9/94  Fixed internal error relating to use of pbk_other pragmas

An internal error has been fixed that could come up when a pbk_other
pragma appeared immediately before a declaration in a local scope -- e.g.,

  void f() {
  #pragma xxx                 // "xxx" has a binding kind of pbk_other
    int i;
  }

6/8/94  Error on member function definition in a comma-list

An error is now issued if a function definition appears in a comma-list
within a class definition -- e.g.,

  class A {
    void f(), f(int) { }      // Error on second declaration
  };

6/8/94  Support for comma-list of constructors

An error is no longer issued when a comma-list of constructor declarations
appears in a class definition -- e.g.,

  class A {
    A(), A(int);              // Now allowed
  };

6/7/94  Matching of template member declarations with prototype instantiation

The algorithm used to match declarations found in an instantiation with
the template information recorded in the prototype instantiation
could fail if several declarations were included in a single
macro.  This has been corrected.

  #define THE_PROGRAM template <class T> struct A { \
      operator int(){return 1;} \
      operator char(){return 2;} \
  }; \
  A<int> ai; \
  A<char> ac;

  THE_PROGRAM

6/6/94  Warning on partial or failed virtual function overriding

There are two "suspicious" cases involving function declarations in a
derived class when the name of the function is the same as that of a
virtual function in a base class.

(1) When the base class virtual function is overloaded and the overload
    set is only partially overridden by declarations in the derived class,
    a warning is issued; e.g.,

      class A {
        virtual void f();
        virtual void f(int);
      };
      class B : public A {
        void f();                    // Warning -- partial override
      };

(2) When the base class virtual function is not overridden by a declaration
    in the derived class but another function declaration with the same
    name appears in the derived class, a warning is issued; e.g.,

      class A {
        virtual void f(int);
      };
      class B : public A {
        void f(unsigned int);       // Warning -- was an override intended?
      };

6/6/94  Overload resolution, built-in operators, and typedefs

A bug in overload resolution has been fixed.  Typedefs of a pointer type
could cause a false ambiguity:

  extern "C" void printf( const char*, ... );
  typedef int* Widget;
  struct Foo {
     Widget _data;
     operator Widget() { return _data; }
  };
  int main()
  {
     Widget p = 0;
     Foo*   f = new Foo;
     if ( p == *f ) { // Error here, now fixed.
        printf( "FAIL.\n" );
     }
  }

6/2/94  Cfront compatibility disambiguation regression

In cfront mode, version 2.23 interpreted certain constructs as
function declarations when they should have been interpreted as 
variable declarations with parenthesized initializer (as cfront does).
This has been corrected.

  int f();
  int main()
  {
    int x(char(f()));  // Declares a variable x in cfront mode
    x = 1;
  }

-------------------------------------------------------------------------------
Version 2.23, May 25, 1994

5/24/94  C++-generating back end processes C++

The C++-generating back end now processes C++ as well as C.  It does not
handle templates, and there are some known problems with cases where
the output looks reasonable but means something else when compiled again
(for example, "A()" is put out as "(A())", which suddenly looks like a
cast).  However, it compiles lots of real code correctly.

5/24/94  Overload resolution bug when static & non-static functions compete

When a static and a nonstatic member function compete against one
another in overload resolution, and the static member function wins,
the conversions needed on the arguments were sometimes not done right:

  struct A {operator char*() const;};
  struct B {
    void f();
    static B *f(char *);
  };
  struct C {
    void h();
  };
  void C::h()
  {
    A id;
    // id should be converted to char* using A::operator char*():
    B::f(id);
  }


5/24/94  IL version number changed to 2.15

5/24/94  Cfront-style member function typedef

A bug has been fixed in our support for cfront-compatible member-function
typedef declarations:

  typedef void A::t1(int);      // Still allowed in cfront mode
  typedef void (A::t2)(int);    // Now recognized and allowed in cfront mode

5/24/94  Order of variables on the scope variables list

It used to be that the order of the variables in the linked list pointed to
by the scope entry was strictly that of their appearance in the source.
Now, when a variable that was previously declared (but not defined -- e.g.,
in an extern declaration) is subsequently defined, it is removed from the
variables list and reinserted at the end.  This also applies in C mode to
variables with a tentative definition that are subsequently defined with an
initializer.  Only file-scope variables are subject to such reordering.

5/24/94  Destruction of temporaries created in condition exprs in non-loops

Expression temporaries created in condition expressions of statements
that are not loops (e.g., the condition expression of an "if") are now
destroyed at the end of the expression.

5/23/94  Taking the address of a template function with default arguments

Taking the address of a template function that has default arguments and
later calling the function in such a way that the default arguments
would be used, could result in an internal error.  This has been fixed.

  template <class T> void f(T, T = 1){}
  int main()
  {
    void (*fp)(int,int);
    fp = f;
    f(2);
  }

5/23/94  IL CHANGE: definition of an_access_adjustment

The enumeration an_access_adjustment_kind has been eliminated, and
an_access_adjustment now uses a_tagged_pointer to refer to the entity
affected by an access adjustment declaration.

5/21/94  Operator new and delete

A diagnostic is no longer issued on redeclaring operator new or delete with
static storage class or as inline.  This applies only relative to the
implicit declaration -- not if an explicit declaration has already been
seen.

5/20/94  IL CHANGE: depth_in_scope_stack added to a_scope

The new depth_in_scope_stack field in a_scope, used during front end
processing, is an indication that a given scope is still actively present
in the scope stack.  Once the scope is popped from the stack the field
reverts to its default value NO_SCOPE_DEPTH.

5/20/94  walk_declarative_entities_in_scope

This new routine, included when NEED_DECLARATIVE_WALK is defined,
walks through the declarative entities in a scope and calls a user-supplied
processing routine on each one.  This can be useful to walk the IL
tree to generate symbolic debugging information.

5/20/94  C mode null pointer constants in pointer operations

When, in C mode, an operation has a left operand that is a (void *)0
null pointer constant, and a right operand that is some pointer (not void *),
the front end formerly converted the right operand to the "void *"
type of the left operand.  Now, it makes the types the same by
converting in the other direction.

5/20/94  typeinfo variables put out with virtual function tables

When exception handling is enabled, typeinfo variables are put out
to describe types used in exceptions.  This fix forces a typeinfo
variable to be generated for a class type with external linkage when
a virtual function table for the type is defined, even if there are
no exception references to the type in the compilation.  This is
necessary because there certainly might be exception references to 
the type in some other compilation, and those will assume that the
typeinfo variable was defined where the virtual function table is
defined.

5/20/94  address_taken and reference kind for called pointers-to-members

Formerly, if a pointer-to-member-function was used for the right-hand
expression of a "->*" or ".*" operator, and the result of that operation
was immediately called, the member function's address_taken flag was
not set and the reference kind in cross-reference output was simply
"reference" rather than "address-taken".  That "optimization" proved
confusing, and has been removed.  The address_taken flag is now always
set on any use of a pointer-to-member to a non-virtual member function,
and the reference kind is always "address-taken".

5/20/94  address_taken for static data members

The address_taken flag for static data members is now set exactly like
the flag for normal variables.  Specifically, it is set when the
address of the static data member is taken, even if the address does
not escape from the immediate context where it is used.

5/19/94  address_taken flag on virtual functions

The address_taken flag is now set when the address of a function is
taken to put it into the virtual function table.

5/19/94  Comparison of function pointers in generated C code

C++ allows comparison of function pointers (using <, >, <=, or >=);
C does not.  Accordingly, the C-generating back end now casts function
pointers to unsigned long (or unsigned long long, if that's appropriate)
before comparing them.

5/19/94  C-generating back end output of minimum integers

The smallest integers on two's complement machines are now output
by the C-generating back end in the form (-XXX-1) to make them
standard-conforming and to get the proper type of constant.

5/19/94  Elimination of zeroing of fully-initialized aggregates

Thanks to a new IL flag in the a_variable entry (is_partially_initialized),
IL lowering and the C-generating back end no longer put out a request
to zero a local aggregate if the aggregate is fully initialized.

5/19/94  Elimination of empty block statements generated by IL lowering

When IL lowering rewrites some statements (in particular, stmk_init
statements), it replaces the statement with an empty block statement.
Now, the empty block statements are optimized out in most cases.

5/18/94  Global qualifier on parameter type

Under certain circumstances a globally qualified type name on a parameter
was parsed incorrectly -- e.g.,

  typedef int I;
  class A {
    int operator+(::I);          // Now parsed correctly
  };

5/18/94  Destruction of expression temporaries on goto/at label

IL lowering has always destroyed expression temporaries at labels.
That is now improved by using the new reachable_by_fall_through flag
in the label (see below) to suppress the code when it's not needed.
Also, expression temporaries are now destroyed on forward gotos in the block
in which the temporaries are created (formerly, they were only destroyed
on gotos backward and out of the block).  Note that when the new
standard for temporary lifetime (destroy at end of full expression)
is implemented, the above behavior will remain as the "cfront
compatible" behavior.

5/18/94  IL CHANGE: reachable_by_fall_through added to a_label

A new flag, reachable_by_fall_through, has been added to the a_label
entry.  It indicates whether a label can be reached by flowing into it
from the code immediately preceding.

5/17/94  IL CHANGE: rout_src_seq_entry_for_default_arg_decl

A new field, rout_src_seq_entry_for_default_arg_decl, has been added to
a_param_type (when GENERATE_SOURCE_SEQUENCE_LISTS is TRUE).  If the
parameter has a default argument, the field is set to point to the source
sequence entry for the routine declaration in which the default argument
was declared.  For instance:

  void f(int, int = 0);
  void f(int i, int j) { /* ... */ }

The pointer in the param type entry for the second parameter will point
to the source-sequence entry associated with the first declaration of f.

5/17/94  Declaring a function as a template after it has been called

In examples such as the following, in which a function template is declared
after a specialization of the template has been called, the front end failed
to set the instantiation required flag.  This has been corrected.

  void f(int);
  int main()
  {
    f(1);
  }
  template <class T> void f(T);

5/17/94 Diagnostics when a declarator is missing

In some cases a missing declarator provoked the message, "declaration does
not declare anything", and in others "declaration requires an object name"
was used.  Now the latter message has been eliminated altogether.  Also,
the distinction between a vacuous declaration and a reference with a
missing declarator has been made more carefully, e.g.,

  struct A { };
  struct A;               // vacuous declaration of A -- no diagnostic
  static struct A;        // reference to A in declaring ??? -- warning
  struct A const;         // reference to A in declaring ??? -- warning

5/16/94 Unnamed bit field

An unnamed zero-length bit field is now recognized and parsed correctly
even if the type is not explicitly specified.  For example, we used to
report a syntax error on the following:

  struct A {
    const :0;             // Now accepted
  };

5/15/94 Elimination of extra parentheses in type output

Several pieces of very similar code that generate source-form
representations of types have been reworked to avoid the generation
of unnecessary parentheses in the type declarators.  The pieces
of code are in

-- c_gen_be.c: generation of C code.
-- cp_gen_be.c: generation of C or C++ code.
-- decode.c: demangling of names.
-- il_display.c: display of intermediate language files.
-- error.c: compilation diagnostics.

In the error.c case, the output was already close to right, but the
code has been changed to use the same techniques as in the other files.

5/12/94 select_curr_construct_pragmas and process_curr_construct_pragmas

Calls to these routines have been added throughout declaration and
statement processing.  They are important to mention because of their role
in the automatic handling of "bind-to-next" pragmas (those that have a
specific effect on the construct that immediately follows in the source).
select_curr_construct_pragmas is called at the very start of the
declaration or statement; it fetches the currently pending pragmas and puts
them on a list for the current construct.  process_curr_construct_pragmas
handles each pragma on that list by calling the implementation-defined
processing function (of type a_next_construct_pragma_function) that is
recorded in the corresponding a_pragma_description entry.  The point at
which process_curr_construct_pragmas is called is critical for this style
of pragma use:

  o for statements it is called right after the statement entry is
    allocated (i.e., before subsequent processing, if any, is done);

  o for declarations it is called right after the symbol is bound to the IL
    entity it corresponds to -- even if (as with a class definition or
    variable that has an initializer) more processing remains to be done.

A prototype for this style of pragma use is provided by pk_printf_args and
pk_scanf_args (which implement the __printf_args and __scanf_args pragmas).
The processing function for both is named record_arg_pragma and is called
automatically by process_curr_construct_pragmas.

5/11/94 Source-sequence entries for access declarations

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE source-sequence entries are
now put out for access declarations.

5/11/94 IL CHANGE: an_arg_pragma_kind eliminated

The enumeration an_arg_pragma_kind has been eliminated, and the field
arg_pragma in a_routine_type_supplement now records a value of type
a_pragma_kind.

5/11/94 IL CHANGE: compiler_generated added to a_constructor_init

The flag compiler_generated has been added to a_constructor_init to
distinguish constructor calls that are inserted by the compiler from those
that are explicitly invoked by the source code.

5/10/94 Source-sequence entries for asm declarations

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE source-sequence entries are
now put out for asm declarations.

5/5/94  Support for lint "ARGSUSED", "VARARGS n", and "NOTREACHED" comments

Support for these has been integrated with the new pragma support -- the
global variables (maintained in lexical.c and elsewhere) that indicated
current state have been eliminated, and corresponding pragma kinds have
been added.  As a result several bugs have been fixed and diagnostics may
now be issued, at the option of the implementation.  The routines that
process the pragmas are record_lint_argsused_and_varargs_state (in decls.c)
and check_lint_notreached_state (in statements.c); they provide a prototype
for one style of using pragmas -- at a particular point in the front end to
check whether a given pragma kind is currently active and if so to do the
appropriate processing.

5/4/94  IL CHANGE: is_partially_initialized added to a_variable

The new is_partially_initialized flag in a_variable has been added to
identify variables and static data members (of array or class aggregate
type) that have been initialized but only partially -- that is, the
init_kind field is something other than initk_none but one or more array
elements or fields remains uninitialized (or partially uninitialized).

5/3/94  IL CHANGE: a_pragma

a_pragma has been added to the IL.  Such entries appear on a linked list
pointed to by the new pragmas field in a_scope.  When a pragma is bound to
a particular statement or declarative entity, it will point to it, and (in
lieu of a back-pointer) the new has_associated_pragma flag in a_statement
and a_source_correspondence will be set. The precise location of the pragma
in the source is represented when GENERATE_SOURCE_SEQUENCE_LISTS is TRUE --
a pragma bound to a particular declaration, for example, has its own
source-sequence entry immediately preceding the source-sequence entry
representing the declaration.

Pragma support has been designed to be easily extensible.  A set of pragma
kinds (see a_pragma_kind) is provided, and variant fields may be added to
a_pragma to support new pragma kinds.  The pragma kind may specified so
that automatic processing is done in the front end, or the pragma may be
passed through to the back end in textual form.  The pragma may be bound to
a particular declaration or statement or be of general effect within a
given scope.  Front-end processing, if any, may be immediate or delayed.
The front end may be configured either to reject unrecognized pragmas or to
pass them though in the IL; see INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL.
Detailed guidance on extending pragma support is given in the Pragmas
chapter of the internal documentation.

5/2/94  Inheritance of assignment operators

Under certain circumstance the inheritance of assignment operators was
permitted.  That has been fixed, and the following now gets an error:

  struct A {
    int i;
    void operator=(int ii) { i = ii; }
  };
  struct B : public A { };
  void f() {
    B b;
    b = 0;                  // Error
  }

5/2/94  Cross-reference information on template declarations

The generation of cross-reference information on declarations of templates
and references to template classes has been improved.  For example:

-  Template definitions are properly reported as definitions, not
   declarations.
-  Template definitions of static data members and member functions of
   class templates are no longer omitted from the cross-reference listing.
-  Declarations of template parameters are now reported, as are references
   to them in template declarations; however, references in prototype
   instantiations (like references to other symbols) are not reported.
-  During template instantiation a reference to a template parameter that
   in turn refers to a named type is now reported in the cross-reference
   listing as a reference to the named type; see the new symbol reference
   kind SRK_IMPLICIT_TEMPLATE_ARG.

4/30/94  Minor type qualifier tweaks in IL

The attempt to get "const" put out when generating ANSI C turned up
a number of minor cases where the IL dropped "const" implicitly,
or had type qualifiers on an rvalue.  These were generally in cases
generated by the compiler, often in IL lowering.

-  Calling a non-const member function with a pointer to a const
   object: an explicit cast is required.
-  Assignment to "this", and folding of "new" into a constructor:
   the top-level const on "this" must be dropped.
-  add_to_indirection, this_param_value_expr: type qualifiers must
   be dropped on the rvalue expression created.
-  Executable code generated to do initialization: const must be
   dropped on the lvalue used to refer to the entity being initialized.

4/29/94  Floating point template parameters are no longer allowed

At the 3/94 X3J16 meeting the committee disallowed floating point
template parameters.  The front end now disallows this feature by
default, but it can be enabled by setting a configuration parameter
in lang_feat.h.  When enabled, diagnostics are issued when the
feature is used in strict mode.

4/29/94  Qualifiers missing on conversion operators in diagnostic messages

When a conversion operator symbol was used as a fill-in in a diagnostic
message, any qualifiers associated with the implicit this parameter were not
included in the output.  This has been corrected.

4/28/94  Generating "const" in ANSI C output

The C-generating back end has been changed so that it will generate
"const" in types when generating ANSI C.  Formerly, "const" was always
commented out.  Generating "const" is a bit tricky, since the "const"
must be turned off on variables for which some initialization code
has been rendered as normal executable code (e.g., an assignment
statement).  It is also turned off on members of classes/structs/unions.

4/28/94  Diagnostic on branching over an initialization

By default a warning is now issued instead of an error for branching
over a variable initialization when no destructor is involved; in strict
ANSI mode (-A) an error continues to be put out.  For example:

  struct X { X(); };
  struct Y { Y(); ~Y(); };
  void f(int i) {
      if (i) goto L1;         // error with -A, warning otherwise
      int j = 0;
  L1: if (i) goto L2;         // error with -A, warning otherwise
      X x;
  L2: if (i) goto L3;         // always an error -- Y has a destructor
      Y y;
  L3:;
  }

This policy is implemented both for gotos and for branches to case labels.

4/28/94  Qualified name on member function declarations

A bug has been fixed and the following is now handled correctly:

  class A {
    static A::f();
  };
  
4/27/94  Unions with const and ref members

We used to issue diagnostics on certain unions with one or more members of
const or ref type.  For example, on the following

  union U {
    const int i;
    int j;
  } u;

we would issue a warning that there was no constructor declared that could
initialize j and an error because u has an uninitialized const member.  The
diagnostics are now suppressed, since it is not clear that the language
definition makes such declarations ill-formed.  As far as ref union members
are concerned, they will probably be disallowed by X3J16 anyway; the fate
of const union members is less clear.

4/27/94  IL lowering generation of initk_zero for nonstatic variables

IL lowering now sets the initialization of a nonstatic variable to
initk_zero only if the variable is partially initialized by a
nonconstant aggregate.  If it is fully initialized, the zeroing is
not needed.

4/27/94  Return value optimization

The front end now does return value optimization.  That is,

  struct A {
    A(int);
    A(const A&);
  };
  A f() {
    A a(1);    // Constructed into temp passed by caller
    return a;  // No copy needed
  }

The optimization is done in functions that return a class value using
a copy constructor, and is possible if all return statements in the
function return the same nonstatic local variable.  The front end
proper detects the possibility of doing the optimization, and the
transformation is done by IL lowering.

4/26/94  Inherited overloaded conversion operators

The front end no longer fails when processing inherited overloaded
conversion operators.  Here's an example:

  class A {
    operator int();
    operator int() const;
  };
  class B : public A { } b;
  int i = b;                   // NULL-pointer failure eliminated

4/26/94  Interchangeable types in strict (warning) mode

In strict/issue-warnings mode, integral types are no longer considered
interchangeable simply because they have the same size (e.g., int
and long).  This had been the behavior in strict/issue-errors mode only.

4/26/94  printf/scanf argument checking

A remark is now issued for cases where a printf/scanf argument is
interchangeable with but not compatible with the required type (e.g.,
unsigned long vs. long).  A warning is no longer issued for a pointer
of any type passed for an integer formatting specifier of the right
type (e.g., %lx) in non-strict mode.  A warning is no longer issued for
a pointer of any type passed for a %p formatting specifier.

4/25/94  New file target.c

target.c has been added.  For now it contains only a single function,
check_target_configuration, which can be called both from the compiler and
from stand-alone programs (like the IL display program); it checks for
consistency among target configuration variables and other values.

4/25/94  Two cases involving arrays with qualified member types

(1)  Initialization of a reference to an array with a qualified element
type now deals properly with the qualifiers when it is done as part of
overload resolution.  (2)  Assignment of a pointer to an array with a
qualified element type to a pointer to an array with a more-qualified
element type now works properly.

4/25/94  targ_def.h and target.h -- target configuration

The contents of target.h have been moved into a new file, targ_def.h, and
target.h now contains declarations of global configuration variables that
are initialized with values declared in targ_def.h.  Most of the variables
are new, replacing #define values to control processing throughout the
compiler; they are initialized by those #define values (which are upper-
case versions of the same name).  For instance, targ_little_endian is
initialized by TARG_LITTLE_ENDIAN and all references to the latter have
been replaced by references to the former.  Here is the list of
configuration variables:

  targ_little_endian
  targ_char_bit
  targ_host_string_char_bit
  targ_has_signed_chars
  targ_char_constant_first_char_most_significant
  targ_wchar_t_int_kind and targ_sizeof_wchar_t
  targ_sizeof_short and targ_alignof_short
  targ_sizeof_int and targ_alignof_int
  targ_sizeof_long and targ_alignof_long
  targ_sizeof_long_long and targ_alignof_long_long
  targ_max_bit_field_size
  targ_bit_field_container_size
  targ_plain_int_bit_field_is_unsigned
  targ_enum_bit_fields_are_always_unsigned
  targ_zero_width_bit_field_alignment
  targ_sizeof_pointer and targ_alignof_pointer
  targ_ptrdiff_t_max, targ_ptrdiff_t_min, and targ_ptrdiff_t_int_kind
  targ_size_t_max and targ_size_t_int_kind
  targ_sizeof_float and targ_alignof_float
  targ_sizeof_double and targ_alignof_double
  targ_sizeof_long_double and targ_alignof_long_double
  targ_sizeof_ptr_to_data_member and targ_alignof_ptr_to_data_member
  targ_sizeof_ptr_to_member_function and targ_alignof_ptr_to_member_function
  targ_sizeof_virtual_function_info and targ_alignof_virtual_function_info
  targ_enum_types_can_be_smaller_than_int
  targ_right_shift_is_arithmetic
  targ_minimum_struct_alignment
  targ_jmp_buf_num_elements
  targ_jmp_buf_element_int_kind

This change enables implementations to permit users to reconfigure the
target characteristics when they invoke the compiler.  There was already
some support along these lines: TARG_HAS_SIGNED_CHARS was used to define
global variable targ_has_signed_chars, and the default setting could then
be overridden by invoking the compiler with the -s or -u option.  The
option of extending this technique to other configuration settings is now
available.

Furthermore, the TARG_xxx macros are #undef'ed after their use as
initializers.  To accommodate implementations with private code that is
broken by this change, the macros may be redefined to refer to the
corresponding targ_xxx variable (see MAKE_TARG_NAMES_REFER_TO_VARIABLES in
target.h).

4/25/94  defines.h -- a file for specifying configuration parameters

A new file named defines.h has been added.  defines.h is intended to
be used to specify configuration parameters as an alternative to
using compiler command line options.  This allows the sharing of a
single Makefile between several versions of the compiler.  Each version
would simply have its own version of the defines.h header file.  The
defines.h file shipped with the front end is an empty file (except
for comments).

4/25/94  Elimination of trigraphs

Formerly, the front end used trigraphs in error directives used to
diagnose incorrectly set configuration parameters.  The trigraphs
were used to prevent spurious errors from old-style preprocessors that
don't recognize the "#error" directive.  Unfortunately, they drew
warnings from some ANSI C compilers.  Therefore, the "??=error" has
been changed to "#error" indented by one space.  This prevents
errors when compiling with old-style preprocessors, which require
preprocessing directives to begin in the first column.

4/21/94  Name mangling for local nested types

Name mangling for local nested types now avoids a double mangling problem:

  void f() {
    struct A {
      struct B { int i; };
    };
    A::B ab;
    extern void g(A::B); // Was g__FQ2_5A__L113__Q2_5A__L11B
                         // Now g__FQ2_5A__L11B
    g(ab);
  }

4/20/94  Empty initializer list

Formerly treated as an extension in C++, an empty initializer list in
aggregate initialization is no longer treated as nonstandard -- e.g.,

  struct A { };
  A a[2] = { {}, {} };     // Diagnostic in strict ANSI mode eliminated

4/20/94  Casting to a reference type using a conversion function

Casting a class value to a reference to a different class, where a
conversion function of the first class is available to do the conversion,
now uses the conversion function.  Formerly, the code generated was
just a pointer cast.

4/20/94  Cfront layout compatibility

A bug that resulted in an internal error has been fixed.  Now the data
section offset is set correctly for a virtual base class that is not
embedded but is the direct base class of a complete base class.  Here's an
example:

  class V { };                       //         V
  class A: public virtual V { };     //         |
  class B { };                       //     B   A
  class C: public B, public A { };   //      \ /
  class D: public C { };             //       C
  main() {                           //       |
    D d;                             //       D
  }

Now the offset of V-in-D is computed correctly.  (Note: this bug appeared
only when when CFRONT_OBJECT_CODE_COMPATIBILITY was configured to TRUE.)

4/20/94  Operands of "?" operator in C++ mode

The second and third operands of a "?" operator in C++ mode are treated
specially if they have the same type (e.g., no usual arithmetic
conversions are done).  The check for the "same type" now compares
the type after any implicit transformations, e.g., array --> pointer
or lvalue --> rvalue.  This is significant if one operand has a
type qualifier but the other does not.

4/20/94  Internal error during processing of #pragma instantiate

A change made in version 2.22 resulted in an internal error when an
instantiate pragma contained an invalid operator name.  This has been
fixed.

  template <class T> struct A {};
  #pragma instantiate A<int>::operator

4/20/94  Symbol reference kind flags on declarations

A new routine, record_symbol_declaration, has been added (replacing
f_mark_defined and f_mark_declared), with the change that a bit vector of
type a_symbol_reference_kind can be passed to it to provide finer control
over the information available for cross-reference output (thereby giving
for declarations the functionality previously provided for references).
With new flags SRK_FRIEND and SRK_TENTATIVE_DEF, it is now possible, for
example, to report a declaration as specifically a friend declaration in
the cross-reference listing.

4/19/94  Overload resolution: overloaded function pointer --> void *

An internal error was formerly issued when an overloaded function
pointer was matched against a void * parameter in overload resolution.
This is now fixed (and gives an error).

  void g();
  void g(int);
  void f(void *);
  void f(const char *);
  main () {
    f(g);  // Caused internal error, now gets proper error
  }

4/18/94  Empty translation unit

A diagnostic is no longer issued in C++ when a translation unit contains
no declarations.

4/18/94  IL Change -- autonomous tag declarations

When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, there is a new flag in a_type
which may be set for class/struct/union and enum types.  When the primary
declaration of a type (usually the definition) is a freestanding
declaration (i.e., not part of the declaration of another entity), then
autonomous_primary_tag_decl is TRUE.  A similar flag, autonomous_tag_decl,
has been added to a_src_seq_secondary_decl.

4/18/94  Template class parameter instantiated to check for conversions

A function parameter that is a partially-instantiated template class is
now fully instantiated as part of overload resolution analysis so that any
constructors of the class are visible to be used as conversion functions.

  template <class X> struct test {
    test(int);
  };
  void f(test<float>);
  main(){
    f(1); //1 must be converted to test<float>
  }

4/18/94  Overload resolution -- some exact matches versus templates

The overload resolution algorithm has been modified slightly to allow
non-template functions called with exact but less desirable matches to
compete against template functions:

  template <class T> void f(const T&) {}
  void f(int) {}
  void f(const int&) {}
  main() {
    int a;
    f(a);  // Was ambiguous, now chooses f(int)
    return 0;
  }

4/15/94  Tentative variable definitions vs. redeclarations

A bug has been fixed (C mode only) to properly distinguish, at the point
at which cross-reference information and source sequence entries are
generated, among tentative variable definitions, actual definitions, and
redeclarations.  For example:

  /* In C mode only. */
  int a;                 /* Tentative definition. */
  int a = 0;             /* Actual definition. */
  int a;                 /* Redeclaration (but used to be treated for xref
                            and source-sequence output as though it were a
                            definition). */

4/12/94  Source position in cross reference entry

The cross reference source position on a qualified name appearing as a
type in a declaration has been corrected.

4/12/94  Name mangling for entities promoted out of functions

The names of types and local static variables promoted out of functions
are now mangled as "name__function__Lnn", where "name" is the entity
name, "function" is the mangled name of the function, and "nn" is
a number identifying the scope (used to distinguish the various
block scopes within the function).  This change allows us to turn
off the _seq_col_ prefix on file-scope names in generated C code.
The new mangling is also compatible with what cfront generates (but
the "nn" number is usually different).

4/12/94  is_bit_field_expr bug (in exprutil.c)

A missing test has been added to is_bit_field_expr.  Without it, the
front end was sometimes using random data as a pointer.  This bug was
introduced in version 2.21.

4/11/94  Name mangling for type "long long"

Type "long long" has to date been mangled as "ll".  Unfortunately, this
does not work well in parameter lists, e.g., "f__Fll" could indicate one
"long long" parameter or two "long" parameters.  Therefore, we have
changed the encoding for "long long" to "L", which is apparently used
for that purpose in some enhanced versions of cfront.

4/11/94  Name mangling for local class names

Names of local classes, formerly mangled by preceding the encoding
of the class name by "Lnn__", are now mangled by appending "__Lnn"
to the class name itself.  This is closer to what cfront does, though
still not exactly the same (cfront also puts the mangled name of the
function in there).  The point of the change is that the new mangled
form is more amenable to demangling.

  void f() {
    struct A { int i; } a;
    extern void g(A);
    g(a);  // Old mangled name: g__FL1__1A
           // New mangled name: g__F5A__L1
           // cfront mangling:  g__F12A__f__Fv__L1
  }

This has very little practical significance, since local names in
external function signatures are almost always an indication of a
coding mistake.

4/10/94  Qualified array types

In terms of the IL representation, to say in C mode that type T is
qualified is to say there is a tk_typeref marked with a qualification that
is "on top of" (i.e., points to the type entry for) T.  In C++ mode,
however, a type T is also qualified if it is an array type whose
underlying element type is qualified.  This distinction is now explicit in
the implementations of macros is_qualified_type, is_const_qualified_type,
and is_volatile_qualified_type; type_or_element_type_const_qualified has
been eliminated.

4/8/94   Cross-reference positions on qualified name references

In qualified name references like x::y in an expression, the position
indicated in the cross-reference entry for "y" has been the position of
"x" (actually, the position of "x::y", that being the position of "x").
That has been changed to the proper position.

4/8/94   Name demangler

A new utility program called edg_decode has been added.  When compiled
as a program, it works as a filter to do name demangling, much like the
similar cfront utility does.  It can alternatively be compiled as
a function that can be called to do name demangling from within a
program.  Note: it demangles external entity names only; it doesn't
handle internal names.

4/8/94   The lint ARGSUSED directive

Two bugs have been fixed in our support of the ARGSUSED directive, which
controls whether remarks are issued on unused function parameters.  First,
The presence of the directive on a member function defined within the
class definition has the expected effect:

  class A {
    /* ARGSUSED */
    void f(int i) { }            // No diagnostic is issued on i
  };

Second, the lifetime of the directive is limited to that of the
immediately following declaration and no longer extends to the next
function definition:

  /* ARGSUSED */
  void g();
  void f(int i) { }             // Diagnostic is now issued on i

4/8/94   IL lowering name mangling of nontype template arguments

The name mangling for nontype template arguments that are pointers to
members for virtual functions has been changed to conform to the cfront
convention.  Formerly, we encoded the "offset" part of the __mptr triplet
in the last position of the encoding, e.g., "4" in

  LM0_L11_4

The last position is now always simply "0", which is apparently (in the
cfront encoding) a way of saying "there's no function" rather than a place
where the offset should be indicated.  This change potentially introduces
a binary incompatibility problem with object code produced via previous
versions of the EDG front end, but that seems unlikely given how obscure
this case is.

4/6/94   Duplicate size and sign specifiers

We used to issue an error on duplicate sign and size specifiers ("unsigned
unsigned", "short short", etc), but now we put out a warning by default and
an error only in -A mode; in cfront mode no diagnostic is issued at all
(except for "long long" when LONG_LONG_ALLOWED is not set).

4/6/94   Cfront compatibility in disambiguation 

Cfront treats the declaration

  int a(int());

as a declaration of an object initialized with the value int(), which
evaluates to zero.  In cfront mode, we duplicate this behavior.  The
correct interpretation (used when not in cfront mode) is as a declaration
of a function taking an argument whose type is "function taking no
arguments returning int".

4/6/94   Cfront mode Internal error declaring types in anonymous unions

The declaration of a nested type in an anonymous union resulted in an
internal error in cfront compatibility mode when the compiler was built
with CFRONT_2_1_OBJECT_CODE_COMPATIBILITY enabled.

  static union {
    enum E {ee};
  };

4/6/94   Elaborated type specifier using a typedef name

In cfront-compatibility mode an elaborated type specifier for a class,
struct, or union is now allowed to refer to a typedef name.  Thus the
following code, ill-formed according to ARM 7.1.3 but accepted by cfront,
is permitted when -b is used:

  typedef class A B;
  class B;                        // Okay in cfront-compatibility mode
  class B *pa;                    // Okay in cfront-compatibility mode

Note: the typedef declaration and the declaration involving the elaborated
type specifier must be in the same scope.  Moreover, a class definition
is not allowed:

  typedef class A B;
  class B { };                    // No change -- redeclaration error

4/4/94   Diagnostics connected with abstract classes

The following ill-formed program is now diagnosed correctly:

  class A {
    A f();                       // Error: returns an abstract class
    virtual void g() = 0;
  };

In addition, two new error messages were added to complain about arrays
of abstract classes and parameters of abstract class type.
    
4/4/94   Reworking of disambiguation routines

The routines used to resolve declaration vs. expression ambiguities
have been reworked to better handle some unusual cases that were
not previously handled correctly.

4/1/94   Overflow check in constant pointer addition/subtraction

In an example like the following:

  x = ((unsigned long) &end) - 0xfff0000000000000;

the overflow check is now suppressed (since the operation is unsigned).

3/31/94  Vacuous enum declarations in strict ANSI mode

The handling of the following case is now different in strict ANSI mode
and in default mode:

  enum E { e1, e2 };
  void f() {
    enum E;                     // New diagnostic in strict ANSI mode
    enum E e;                   // Now okay in strict ANSI mode, but still
  }                             //   an error in default mode

In default mode, the vacuous enum declaration is still treated as a
forward declaration of a local type; no diagnostic is issued.  Until now,
the only difference in strict ANSI mode was that a warning or error was
issued complaining that a forward-declared enum is nonstandard, but now
the "enum E;" declaration is treated as a reference to the global E, and
the diagnostic complains about the missing declarator.

Consequently, in default mode the declaration of e is ill-formed, since no
local E has yet been defined.  That used to be the case in strict ANSI
mode as well, but now, since E is global E, the declaration of e is legal.

3/30/94  Function definition with omitted declaration-specifiers

The following declarations, in which the declaration-specifiers are
missing and the declarator begins with a token other than an identifier,
are now parsed correctly:

  *f() { return 0; }           // Spurious error eliminated
  (g)() { return 0; }          // Spurious error eliminated

3/30/94  Enum declaration with omitted declarator

In strict ANSI mode a diagnostic is now issued on an enum declaration with
an omitted declarator, for example:

  enum E { e1, e2, e3 };
  enum E;                     // Warning/error in strict ANSI mode

That is, it is a declaration that "declares nothing", since the declarator
is missing.  (In default mode such a declaration continues to be treated
as a redeclaration of the enum type.  Thus, in the cross reference output
the second declaration is reported as a reference to E in strict ANSI mode
but as a non-defining declaration in default mode.)

3/30/94  Constant folding done in not-evaluated expressions

Constant operation folding is now done in not-evaluated expressions.
It is necessary to detect null pointer constants like the one in the
following:

    1 ? "x" : (1-1);

Any errors or warnings detected while doing the folding are not
issued, however.

3/30/94  Recognizing a label with same name as a type in C mode

A bug (which appeared only in C mode) has been fixed in which a label
statement had not been not recognized as such when the label name was the
same as a type name.  For example:

  typedef int T;
  void f() {
  T:;                        // Spurious error eliminated
  }

3/28/94  Storage-class-not-first diagnostic

Except in strict ANSI mode a remark is now issued (instead of a warning)
when the storage class specifier is not first among the declaration
specifiers, e.g.,

  int static i;              // Now a remark unless in strict ANSI mode

3/28/94  Void function parameter type

In C mode an error is now issued on a void function parameter type (as
was already the case in C++ mode).

3/28/94  C-mode abstract declarator in function param declaration

In C mode a diagnostic (complaining about a useless declaration) was
incorrectly issued on the following:

  void f(struct {int i;});    // Spurious warning/error no longer issued

3/28/94  Typedef declaration in function parameter list

A fix has been added to correct a recent change that had caused the
following to go undiagnosed:

  void f(typedef int);        // Error now issued (again)

3/28/94  Name mangling tweaks

Names generated for base class special fields (e.g., virtual base class
pointers), type-as-subobject versions of class types, and virtual function
tables now encode nested type names properly.  This matters only in
very bizarre test programs.

3/27/94  Error recovery on missing semicolon after a type definition

Cases like the following are treated under the heading "dangling type
specifier":

  class A { /* ... */ }         // Missing semicolon
  class B { /* ... */ };

In general, it is better to complain about a missing semicolon than about
the second "class" corrupting the declaration specifiers on the first
line.  The code to deal with such cases has been simplified and made less
bug prone.  As a result, for example, the following is now handled
correctly:

  class A {
    void f();
  };
  class B : public A {
    struct N { int i, j; } f;    // B::f is no longer confused with A::f
  };

3/26/94  C-mode extension for last field of a struct

In C-mode the last field of a struct is allowed (as an extension) to be an
array of unknown size.  There was a bug that permitted an array of
incomplete element type as well, but that is now fixed.  For example:

  struct A {
    int x;
    struct A a[1];    // Error now in C mode.
  };

3/26/94  Name lookup error on declarator in member function

A spurious error is no longer issued on declarators in a member function
that redeclare a member name, as in the following:

  struct A {
    void f();
    void g();
  };
  void A::f(void) {
    enum { e1, e2 } g;     // Spurious error no longer issued on g
  }

3/25/94  IL CHANGE: fields removed from a_block, a_statement

Fields final_source_sequence_entry and last_declaration, very recently
added to a_block and a_statement, respectively, have been removed.  The
former is no longer needed now that end-of-construct markers have been
added to the source sequence lists.

3/24/94  IL CHANGE: 2 fields pointing to source sequence entries eliminated 

Two fields, recently added, have been eliminated: last_declaration, a
variant field of a_statement, and final_source_sequence_entry, in a_block.
(Note: the original changes and this one are of interest only to
implementations in which GENERATE_SOURCE_SEQUENCE_LISTS is configured to
TRUE.)

3/23/94  IL CHANGE: nested function prototype scopes

When a function prototype scope has nested within it another function
prototype scope for which an IL scope entry is needed, e.g.,

  void f(int (*pf)(struct A { int i; })) { /* ... */ }

the IL scope entry of the inner scope is now recorded on the scopes list
of the IL scope entry for the containing scope.  In the example (which is
valid in C mode only) an IL scope entry is required for the inner scope
because a struct is defined in that scope; the scope that is created is
placed on the scopes list of the outer scope's IL entry.  Note that the
latter would not have been created otherwise.

Note: as a consequence of this change, it is no longer the case that an IL
scope entry's having a non-NULL scopes pointer implies that it is a
function or block scope.

3/23/94  Elaborated types in function template parameter lists

An elaborated type specifier, when used in a parameter declaration
in a function template, now helps determine whether a template matches
a given function call.  This feature fixes a bug in which an internal
error could occur when an integer type is incorrectly considered as a
match for an enum type, as in this example:


  template <class T> void f(enum T){}
  enum E {e1, e2};
  int main()
  {
    f(1);
  }

This example now results in an error because the function call does not
match a function template.

3/23/94  Class qualifier missing from class types in error messages

The class qualifier was omitted when class types were displayed in
error messages.  This example now produces the proper output.

  struct C {};
  struct A {
    struct C {};
  };

  C* cp;
  A::C* acp = cp;

3/22/94 Macro mark_declared

The macro mark_declared was defined incorrectly.  It is now fixed to call
f_mark_declared, as intended.

3/22/94 C-generating back end processing of local and prototype scope types

The C-generating back end now promotes all local types to the file scope
in the generated C code to avoid problems with extern declarations inside
functions that make use of local types.  Types in nested prototype scopes
are also being promoted to file scope (formerly, only the types in
top-level prototype scopes were being promoted).

3/21/94 IL CHANGE: a reworking of source sequence lists

A number of changes have been made to the way source-sequence lists are
generated.  Most important is the elimination of "proxies" and the use
instead of "sublists" (see a_src_seq_sublist) to deal with source-sequence
entries for file scope entities that are part of the function-scope list.
In addition, the ends of class and enum definitions and statement blocks
are indicated in the source-sequence list by markers (see
a_src_seq_end_of_construct).  Finally, classes no longer have their own
source sequence lists; instead, the source-sequence entries for class
members appear on the file scope list (or on a function scope sublist),
bounded by the entry for the class itself and the entry marking the end of
the class definition.  Unnamed class and enums are recorded in the source
sequence list.

The other IL change, besides the new structs a_src_seq_sublist and
a_src_seq_end_of_construct, is the addition of a pointer to a linked list
of the former in a_scope.  The new field, called src_seq_sublist_list, is
used in function scopes only.  (Of course, these IL changes are visible
only when GENERATE_SOURCE_SEQUENCE_LISTS is configured to TRUE.)

3/21/94 IL CHANGE: an_orphan_il_list renamed a_scope_orphaned_list_header

The IL entry called an_orphan_il_list has been renamed
a_scope_orphaned_list_header, an assoc_routine field has been added
to the entry, and the field in il_header that points
to the list of such entries has been renamed scope_orphaned_list_headers.
The list of entries is also now built in forward order instead of
reverse order of source appearance.

3/21/94 Constant expressions inside not-evaluated expressions

The expression processing routines have been changed so that constant
expressions inside not-evaluated expressions are always evaluated.
This avoids an internal error on the following:

  int i = sizeof(int[1+1]);

A previous change to scan_intaddr_operator (2/21/94) is subsumed
by this change, and has been backed out.

3/16/94 C-generating back end output formatting

The C-generating back end has been changed so that it does not begin
a new line for an item with no known position (it continues on the
current line instead).  Also, line wrapping is suppressed during generation
of preprocessing directives (see disable_line_wrapping).

3/16/94 Disambiguation regression

Release 2.22 incorrectly tried to interpret the indicated line as a
declaration instead of an expression.

  struct A {
    int a;
  };
  typedef A* P;
  int t[23] = {0};
  void f()
  {
    P(t[0])->a = t[1];  // Spurious error
  }

3/16/94 Fixed C mode name lookup bug

In C mode, the indicated line was incorrectly finding the field name T
instead of the global typedef.

  typedef int T;

  struct S {
    int T;
    T mbr;	/* OK, was a spurious error */
  };

3/15/94 C-generating back end output of integer cast to pointer type

When generating ANSI C, the C-generating back end now outputs integral
constants cast to pointer types as unsigned constants.

3/14/94 Setting address_taken on using address of class rvalue

address_taken is now set on "arg" in the following:

   struct A {
	A(int);
        int f();
   };
   int func(A arg) {return ((A)arg).f();}


3/4/94  Missing diagnostic on structure redefinition in C mode

The front end failed to issue a diagnostic on this incorrect usage.
The resulting IL caused an internal error in the IL read/write routines.

  struct A {
    struct A { int a1; } a2;
  } a3;

3/3/94  Class layout -- improved cfront compatibility

A bug was fixed that resulted in an internal error while building the
constructor wrapper for a class in cfront layout-compatibility mode.
Here's the class declaration for the case -- it was in generating C::C()
that the problem showed up:
                                              //       Tv
                                              //      / \
  struct Tv {};                               //     L   Rv
  struct L : virtual public Tv {};            //      \ /
  struct Rv : virtual public Tv {};           //       A
  struct A : public L, virtual public Rv {};  //       |
  struct B : public A {};                     //       B
  struct C : public B {};                     //       |
                                              //       C

In addition, several changes were made to improve compatibility with USL's
cfront in the area of class layout.  These changes had mainly to do with
how virtual base class data sections are laid out -- determining when they
are embedded in other base classes and deciding which to use when there's
a choice of several.  (Note that these changes are visible only when
CFRONT_OBJECT_CODE_COMPATIBILITY is TRUE.)

3/1/94  Missing diagnostic on incorrectly formed pointer to member declaration

The front end failed to issue a diagnostic on this kind of usage.  This
resulted in an internal error in IL lowering.  This has been corrected.

  int ::*x;

3/1/94  Omission of the declarator on a field declaration

Treatment of the following in C mode has been changed:

  struct S {
    char a;
    int;
    char b;
  };

In pcc mode the "int;" declaration is just ignored; it used to affect the
layout of the struct, but not any more.  Otherwise in C mode, a warning
(or in -A mode an error) is issued.  (In C++ mode an error is always
issued.)  As a result of this change, the only unnamed fields that appear
in the IL are unnamed bit fields.

3/1/94  Static function called from automatically instantiated function

The compiler generated a spurious error when a static template function
was called from an external template function that was in turn instantiated
by the automatic instantiation mechanism.  This has been corrected.

  template <class T> static void f(T){}
  template <class T> void g(T t)
  {
    f(t);
  }

  int main()
  {
    int i = 1;
    g(i);
  }

3/1/94  Declaring an object of void type

In C++ mode an error is now issued when an extern variable is declared to
have void type.

2/28/94  Fixed spurious error on virtual function overriding

In the following case, in which dominance needs to be taken into account
in computing virtual function overriding, we used to issue a spurious
error:

  //     A virtual A::f()
  //    / \
  //  AA   B B::f()
  //    \ / \
  //     BB  C C::f()
  //      \ /
  //       D
  struct A  { virtual void f(); };
  struct AA : public virtual A  { };
  struct B : public virtual A  { void f(); };
  struct BB : public virtual B, public virtual AA { };
  struct C : public virtual B  { void f(); };
  struct D : public virtual BB, public virtual C { };

We used to complain that A::f() was overridden in D by both C::f() and
B::f().  But B::f() is "dominated" by C::f().  Now we get it right.

-------------------------------------------------------------------------------
Version 2.22, February 26, 1994

2/24/94  IL version number changed to 2.14

Changes (details below): unnamed bit fields appear on field list;
is_bit_field flag in field entry; is_this_parameter flag in variable
entry; contains_try_block flag in routine entry; stmk_decl statement
to indicate position of declarations in statement sequences (only when
source sequence entries are selected, which is not the default);
final_source_sequence_entry pointer for blocks; pcc_compatibility_mode
flag in il_header.

2/24/94  IL lowering handling of cast of pointer-to-member-function

The code for a cast of a pointer-to-member-function to another pointer-
to-member-function, which is a no-op after IL lowering, now preserves
the proper destination type, which means if one calls the result of
the cast one calls a function of the right type.

2/24/94  Declarations involving incomplete class types

A declaration may involve an incomplete class type -- e.g.,

  struct A;
  typedef A array_of_A[10];  // Okay in C++, allowed as in extension in C
  A f();
  void g(A);

Only when the class is finally defined can the declarations be completed.
For example, once A is defined, the array size of array_of_A can be
computed and, if appropriate, the routine_calling_method flag for f can be
set, as can the arg_transfer_method_flag for g's parameter.  The strategy
for accomplishing this has been improved (see the dependent-type-fixup
list associated with each class); as a result several cases have been
fixed in which the flags were not set properly.  For example:

  struct A;
  typedef A FT();
  extern A f();
  struct A { A(const A&); };
  main() {
    (void)(*((FT*)f))();    // The code put out to call f is now correct
  }

In addition, we now handle this case correctly:

  struct A;
  typedef struct A arr1[5];
  typedef arr1 arr[6];      // Size of arr is now computed correctly
  struct A { int i; };

2/23/94  Address of void variable an error only in C++ and strict C mode

The error on the following, added in the previous release, has been
removed in non-strict C mode:

  extern void v;
  &v;  /* Error, "v" is not an lvalue. */

2/23/94  Checking for missing arguments at the end of a printf/scanf

The check in a printf/scanf for remaining formatting specifiers for which
there are no arguments, which was broken many releases back, works
once again.

  #include <stdio.h>
  void n()
  {
    printf("%s %d\n", "foo");  // Gets a warning once again
  }

2/23/94  Recursion loop in overload resolution fixed

Overload resolution had an infinite recursion loop when a copy constructor
was sought for a class and the class had more than one constructor, one
of which is a constructor with more than one argument, with the first
argument being the class type (e.g., "A(A, int)").  Now fixed.

2/23/94  IL lowering computation of anonymous union pointer-to-member offset

IL lowering now correctly computes the offset for a pointer-to-data-member
for a member that is inside an anonymous union.

2/23/94  Bug with compiler-generated assignment operators

A bug has been fixed in the code produced when a compiler-generated
assignment operator has to call an assignment operator for a base class or
field -- specifically, a cast node is produced over the source expression
if required.  Here's an example:

  struct A { };
  struct B : public A {
    operator=(const A&){}
  };
  struct C {
    B b;
  };

Now, when C::operator= is generated, the parameter passed in the call to
B::operator= is cast to an A.

2/22/94  Enum values larger than int in strict ANSI warning mode

Examples such as this were incorrectly causing an error to be issued
in -a mode where only a warning is appropriate.

  enum E {ee = 0x80000001};

2/22/94  static member function and inherited virtual function

We now issue an error if a static member function seems to override a
virtual function from a base class, e.g.:

  class A {
    virtual void f(int);
  };
  class B : public A {
    static void f(int);      // Now an error is issued.
  };

We used to assume that there was a type mismatch between A::f and B::f
because the implicit this parameters do not match.

2/22/94  address_taken flag set more often by IL lowering

IL lowering now sets the address_taken flag on variables whose address
is used in initialization code.  In particular, this means class objects
initialized through a constructor.  When the address_taken flag is set,
if the variable's storage class is "register" it is changed to "auto",
which avoids bad generated C for the following case:

  struct A { int i; A(int ii) : i(ii) { } };
  int f() {
    register A x(1);
    return x.i;
  }

2/21/94  Base class cast on operator()

When an operator() function is called, the pointer to the object now
has a base class cast if necessary.

2/21/94  Access checking of template parameters

A spurious access error was issued when a template parameter
that points to a private nested type was used in a qualified name.
This has been corrected.

  template <class T> struct A {
    T t;
    T::Cnest tc;  // We incorrectly said that T was not accessible
  };
  
  class B {
    class Bnest {
      public:
      class Cnest {};
    };
    A<Bnest> ab;
  };

2/21/94  Function linkage in -tlocal mode

An interaction between automatic instantiation and -tlocal mode caused
functions that should have been given static linkage to be given
external linkage instead.  This has been fixed.

2/21/94  -tlocal mode and automatic instantiation

The prelinker requires that generated instantiations be given external
linkage.  To prevent prelinker failures, the front end has been
modified to disable automatic instantiation when -tlocal mode is used.
If your prelinker works with functions with static linkage you will
need to undo this change.

2/21/94  throw of expression with void type is an error

A throw of an expression with void type is now diagnosed as an error.

2/21/94  __INTADDR__ in not-evaluated expression

Using __INTADDR__(expr) in a not-evaluated context (e.g., sizeof)
no longer causes an internal error.

2/19/94  IL change: the type of a routine may be a typedef

The type entry pointed to by a routine entry may now represent a typedef
(as long as the routine is undefined).  This was the intent all along,
but a bug in make_routine caused a skip_typerefs to be done when the
type was being bound to the routine entry.  Here's an example:

  typedef void (F)(int);
  extern F f;             // routine "f" now points to a tk_typedef type

2/18/94  Generating makefile dependency information using implicit inclusion

When generating makefile dependency information (using the -M option)
in implicit template inclusion mode (-B) the front end searches for
a related source file for each header file that is included.  If a
related source file is found, it is treated as if it were included
immediately following the original header file.  This is done so
that complete makefile dependency information can be generated.
Previously, the -M option would not include the source (e.g., .c)
files that contain template definitions.  In -M mode the front end
only performs preprocessing.  As a result it must search for related
source files for all header files, not only those that contain
template definitions used by the program.  This may result in
the front end indicating a dependency on a given file where no
such dependency actually exists.

2/18/94  ANSI C code generation from C-generating back end

The C-generating back end can now be configured to generate ANSI C instead
of K&R C.  See the flag C_GEN_BE_GENERATES_ANSI_C in target.h.
This change involved an almost-complete rewrite of c_gen_be.c;
in the process, the Fortran-specific code has been removed, and
annotation output is no longer controlled by a build option (it
is still controlled by a command-line option).  In both K&R C
and ANSI C generation modes, the output now contains #line directives.

2/17/94  Detection of instantiation loops in -tall mode

In -tall mode it is possible for the compiler to be required to generate
a very large or possibly infinite set of instantiations even though
the program does not actually require the instantiations.  This kind
of instantiation loop was not detected by the compilers existing
checks for recursive instantiations.  An error is now issued for
programs such as this one.  A new configuration parameter called
MAX_UNUSED_ALL_MODE_INSTANTIATIONS has been added to lang_feat.h to
control this feature.

  template <int i> class A {
  public:
    void f() {
      A<i+1> a;
    };
  };
  void g()
  {
    A<1> a;
  }

2/16/94  IL change: new field in a_routine_type_supplement

A new field, suppress_diagnostic_on_incomplete_return_type (intended for
front-end use only), has been added to a a_routine_type_supplement.  As a
result, an error is issued only on the first call to a function with an
incomplete return type.

2/16/94  Error message change for incomplete return types

Two messages, "a function may not return an incomplete type" and "a
function with an incomplete return type may not be called", have been
consolidated: the new message reads: "function return type is incomplete".

2/16/94  Separate file for system specific predefined macros and assertions

To simplify the maintenance of versions of the compiler targeted for
different systems, a file called sys_predef.c has been added.  Code that
initializes system specific predefined macros and assertions should be
placed in this file.

2/16/94  Redefinition of __STDC__ in C++ mode

In C++ mode it is now possible to redefine the value of the __STDC__
predefined macro.

2/16/94  Redefinition flag for macros

A flag has been added to the macro entry that specifies whether
the macro can be redefined.  This provides the ability to
create predefined macros whose values can later be redefined.

2/16/94  Redefinition of macros on the command line

A bug has been fixed that allowed the -D command line option to
redefine the value macros.

2/15/94  Eliminated warnings from Novell/USL C compiler

Some changes have been made to eliminate warnings concerning operations
whose semantics have changed from K&R C to ANSI C.  For example, 
whether the right operand of a shift operation affects the type of the
result of the operation.

2/14/94  Improved speed of conversion from sequence number to file and line

The routine that converts from a sequence number to a file name and line
number now caches information about the most recent search to
improve the speed of subsequent conversions of neighboring lines.

2/14/94  Assertion failure in cfront mode

The following incorrect usage resulted in an assertion failure when
compiling in cfront (-b) mode (in which a "." can be used in place of
"::" in qualified names).

  typedef int x;
  int main()
  {
  	int i;
  	i = x.a;
  }

2/14/94  Spurious internal error

Certain incorrect usages of the keyword "template" could give a
spurious "typedef of template not yet implemented" error.  This has
been corrected.

  struct A {};
  typedef struct B {
    A template;
  } T;

2/14/94  Missing error on redefinition of hidden tag name

An error is now diagnosed for this incorrect usage:

  struct A {
    struct B {};
    short B;
    struct B {};  // Error
  };

2/14/94  Scanning type conversion operator names

When a type conversion operator appears as part of a qualified name,
the type is first looked up in the class specified by the qualified name.

  struct A {
    enum E {};
    operator E();
  };

  void f()
  {
    typedef A::E (A::*pmf)();
    pmf p = &A::operator E;  // Should find A::E
  }

2/14/94  Setting "can be instantiated" flag for static data members

In implicit inclusion mode the template definition file was not
being implicitly read to determine whether a template static data
member could be instantiated.  This could cause the automatic
instantiation mechanism to fail to instantiate a static data member
resulting in a link error.  This has been fixed.

2/11/94  Name mangling change to avoid Tn with n > 9

Name mangling in IL lowering has been changed so that it will never
generate a "Tn" with n > 9.  That's to avoid ambiguous names when
the "Tn" is followed by something that begins with a digit.  Without
this change, for example,

  struct A {};
  void f(int, int, int, int, int, int, int, int, int, int, int, long, long, A)
  {}

would produce "T121A" as part of the mangled name, which could be
read as "T1 21A" or "T12 1A".  This change also affects the second
number in the "Nmn" construct.  The change is disabled when
CFRONT_OBJECT_CODE_COMPATIBILITY is true.

2/11/94  Pointer-to-member types preserved in result of lowered cast

The code produced by IL lowering for a pointer-to-member related class
cast now preserves the original type pointer in the result.  This
avoids an internal error when such a cast is the first operand of
a pointer-to-member call operator.  This should make no difference
to a back end, as the new type is a typedef of the old type.

2/11/94  Proper error handling on pointer-to-member type in expression

An internal error is no longer given when a pointer-to-member pointer
declarator appears at an inopportune time in an expression:

  struct S {int i;};
  void f()
  {
    new int (S::*);  // Error on S::*
  }

2/11/94  Referenced flag of class set in lowering of constructor/destructor

When the body of a constructor or destructor is processed in IL lowering,
the referenced flag of the class is now set to TRUE.  It was almost
always set already, but it wasn't for a case like

  struct A {virtual ~A() {}};
  struct B : public A {B(); B(int i) {}};

2/11/94  Ordering of types output from the C-generating back end

The C-generating back end makes two passes through each type list
and puts out some types on each pass the get the output ordering
right.  One problem, which shows up only when ANSI C is being
generated, has been corrected: typedefs are now output on the
second pass to avoid some forward reference problems.

2/10/94  Type casts in constructor and destructor calls from IL lowering

Constructor and destructor calls generated by IL lowering now cast the
object pointer to the right class type if necessary, i.e., if it is
instead a pointer to the associated type-as-subobject.  This change
avoids warnings from underlying C compilers when generating ANSI C
code.

2/2/94   C-generating back end generation of unreferenced labels

The C-generating back end now puts out a ";" at the point where the
definition of an unreferenced label is suppressed.  That avoids
bad generated C for the following:

  main () {
    for (;;) lab:;
  }

2/1/94   IL change: new flag in a_field

A new flag, is_bit_field, has been added to a_field.  It was necessitated
by the recent inclusion of unnamed bit fields in the IL -- since they may
have zero length, the check of bit_size != 0 is no longer sufficient to
distinguish a bit field from an ordinary field.

2/1/94   Assignment and comparison of different function pointer types

Assignment and comparison of different function pointer types (an extension)
is no longer allowed in C++ mode.  This example is still allowed
in C mode but is now an error in C++ mode.

  void f(int);
  int main(void)
  {
    void (*p)() = &f;
  }

1/31/94  Source sequence entries for return statements

In return statements that have an associated expression, the source sequence
entry for the return statement is now generated before any source sequence
entries for the expression.  (Source sequence entries are configured out
by default.)

1/31/94  IL change: field entries for unnamed fields.

An unnamed bit field is now represented in the IL by an actual field entry
rather than by a gap in the offsets of the surrounding fields.  The same
holds for other unnamed fields (which are supported in pcc mode only).
Unnamed fields are recognizable from the NULL name pointer in the source
correspondence substructure.  Note that back ends must now ignore those
fields, especially when pairing up initializer values with members of
a struct being initialized.

1/31/94  Changes to facilitate message catalogs

A number of changes have been made to simplify the task of using a message
catalog for the storage of error messages.  Command line errors are now
accessed using a message code, the message codes for certain error
messages are no longer conditionally compiled, and error.c no longer
contains error messages whose text differs in C and C++ mode (different
error codes are now used).

1/31/94  Undefined result if times() should fail

If the times() function (used with the -# option to get CPU time
information) returned an error status the CPU time returned by
get_cpu_time was undefined.  The return value is now set to zero

1/27/94  Recognition of new keywords

Remarks are issued when any of the new keywords that have been added by
X3J16/WG21, but are not yet implemented in the front end, are encountered
in a source program.  In strict mode a strict ANSI diagnostic is issued.
The diagnostics will be eliminated when support for the features that use
the keywords are implemented; until then these strings are treated as
identifiers.

Diagnostics are not issued for wchar_t, bool, true, and false because most
current usage of these names will be compatible with the new language
feature, when implemented.  Issuing diagnostics on the use of these names
would probably not be useful.

1/27/94  IL change: contains_try_block flag in routine entry

The IL routine entry now contains the flag contains_try_block which is set
to TRUE if the routine definition contains any "try" blocks.  This can be
helpful in suppressing certain optimizations relating to local variables
which would interact badly with the setjmp/longjmp used to implement
exception throws.

1/27/94  address_taken flag restored to pre-2.21 meaning

In version 2.21, the address_taken flag for variables was changed so
that it is set only if the address of the variable is taken AND the
address "escapes," i.e., it can get out of the immediate context where
it is used and get stored into a pointer or the like.  This turned out
to be unfortunate for several reasons: (1) for things that naturally
live in registers (e.g., parameters), the new meaning doesn't tell
you whether the item needs a "home" in memory; (2) when you cast the
address of a variable to a pointer to a different type as a way to
access the bits of the variable in a different way, the generated
code probably wants to take the address of the variable, but the
address_taken flag doesn't get set because the address didn't escape.
The following example illustrates both cases:

  float foo(int k)
  {
    return *(float *) (&k);
  }

The second problem could be solved by refining the processing for
casts, but it seems most people have a preference for the simpler
meaning of address_taken, so it's been changed back to the way
it was.

1/25/94  Abort when using preprocessed source and implicit inclusion

An abort has been fixed that occurred when compiling a previously
preprocessed source file while using the -B (implicit inclusion) option.

1/24/94  const variable is not null pointer constant in cfront mode

In cfront compatibility mode, a const variable with value zero is not
considered a null pointer constant when matching a pointer argument of an
overloaded function.

1/24/94  IL change -- local type declared in function prototype

A new flag, declared_in_function_prototype, is set in a type entry when it
represents a local type declared or defined in a function prototype; this
applies in C mode only, since in C++ a type declared in a function
prototype is not a local type but belongs to the file scope.

1/24/94  IL change -- variable for implicit "this" parameter

A new flag, is_this_param, is set in a variable entry when it represents
an implicit "this" parameter.

1/22/94  Implicit return value from main()

In C++, if control reaches the end of the main() routine, and main() has
an integral return type, it is treated as if a "return 0;" statement were
executed.  This was approved by X3J16/WG21 at the 11/93 meeting.

This behavior has been extended to all main() routines with integral
return types.  Except for the case explicitly sanctioned by the C++
working paper, a diagnostic message is issued.

1/20/94  Default file suffixes under MS-DOS

The default object file suffix for MS-DOS has been changed from .o to .obj.

1/19/94  Cross-reference info on access declarations

Cross-reference information and/or source sequence entries are now put out
for access declarations (when required).

1/18/94  C++-generating back end added

A new "back end" has been added that can write out C++ or ANSI C.
It is intended for those who wish to do source-to-source transformations.
Source sequence entries must be enabled to use it, because it aims to
produce output in the same order as the source.

1/17/94  Source sequence entries for blocks and switch clauses

Source sequence entries are now generated for block statements and
for case/default labels.
 
1/15/94  IL walk code for new-delete supplement

The IL walk code in walk_entry.h for the new-delete supplement should
walk the "arg" field as a list (because it can be in a placement "new").
Fixed.

1/14/94  Dummy version of virtual_dtor_should_be_generated_for_class

When IL lowering is configured out, a dummy version of
virtual_dtor_should_be_generated_for_class is now generated, which always
returns TRUE.  Formerly, one would get a link-time error because the
routine was missing.  That was intentional, as it forced one to think
about what the right answer is in one's application, but it tended to
cause panic.  Now, one will not get an error, but one may still want to
decide whether the answer TRUE is the most appropriate one.  It's
the answer that causes the most error checking (because the virtual
destructor will always be generated, so any errors in generating
it will be detected in every compilation).

1/13/94  Change in handling of the source line index used for error processing

The error handling routines maintain, for each input file, a table of
file positions associated with source line numbers within the file.
These routines have been modified to reduce the number of ftell calls
executed, and to provide a more uniform distribution of index entries
when compiling very large input files (files with more than a few thousand
lines).

1/13/94  Compilation timing information

A command line option (-#) has been added that causes the compiler
to display execution time statistics.

This is difficult to do in a way that is completely portable so
host_envir.c may need to be adjusted for some systems.

Systems with ANSI C compliant runtime systems that support the 
clock() function should work properly.  If your system uses
the UNIX times() function instead of clock(), and the values
returned by times() are not in increments of 1/60th of a second,
then you will need to set CLOCK_FREQUENCY to the appropriate value.

1/12/94  Access declaration applied to overloaded function

Under certain circumstances we failed to issue an error when an access
declaration was applied to an overloaded function with nonuniform
access.  That bug has been fixed.  For example:

  class A {
  public:
    void f();
  private:
    void f(int);
  };
  class B : private A {
  public:
    A::f;                   // Error is issued consistently
  };

1/11/94  Optimization of next_token routines

The routines next_token and next_two_tokens have been optimized
to use the cached token information when it is available.  Also,
a special lexical lookahead routine has been written to eliminate
the most of the next_two_token calls when scanning simple identifiers.

1/11/94  Multiple inline definitions of friend function

An error is now issued when a friend function is defined more than once
within a given class.  For instance,

  class A {
    friend void f() { }
    friend void f() { }    // Redefinition error is now reported
  };

1/10/94  Operator functions with erroneous operators

Handling has been improved when the operator in an operator function is
erroneous or missing.  For example, an internal error is no longer
produced when this program is compiled:

  struct A {
    operator?(int);
  };

1/10/94  Ellipsis in parameter list of an operator function

An error is now issued when the parameter list of an operator function
declaration contains an ellipsis -- except for operator()() and operator
new(), in which ellipsis is permitted as long as at least one parameter is
explicitly declared.  For instance:

  struct A {
    operator int(...);               // Error
    A *operator->(...);              // Error
    void operator()(int, ...);       // Okay
  };
  int operator +(A&, int, ...);      // Error

1/10/94  Handling of "overload" anachronism

We now treat "overload" as a token -- this is more consistent with
cfront's behavior -- but it is now recognized only in cfront compatibility
mode.  The text of the diagnostic has also been changed.  Now, when cfront
mode is not enabled, "overload" is just another identifier.

1/9/94   Diagnostics on type declaration within function prototype scope

For old-style parameter lists, a change has been in how diagnostics are
issued on declarations that do not declare a parameter in a function
prototype scope.  This includes a slight rewording of the text for error
code ec_decl_should_be_of_param.

1/5/94   Access declarations involving hidden and ambiguous names

An error is now issued on an access declaration for which the unqualified
name is ambiguous in the context of the class in which the access
declaration appears; in other words, an access declaration may not be
used to resolve an ambiguity.  For example:

  struct A { int i; };
  struct B { int i; };
  struct C : private A, private B {
    A::i;          // Invalid access declaration: "i" is ambiguous
  };

Also, errors are issued more consistently if an access declaration refers,
albeit with a qualified name, to a member hidden by another declaration.
For example:

  struct A { int i; };
  struct B : public A { int i; };
  struct C : private B {
    A::i;          // Invalid access declaration: B::i hides A::i
  };

These diagnostics may be somewhat controversial, since they are not
required by the ARM.  However, they are justified by viewing an access
declaration exclusively as a means to control the access of an inherited
member.

1/5/94   Routine names changed for improved portability

The names of two routines have been changed because they were not
unique within the first 31 characters.

1/4/94   Name mangling for member constants

Member constants (e.g., enumerators) now have their names mangled when
appropriate.  This was not necessary when generating old-style C, because
the C-generating back end eliminated the enum constants, but it is
necessary when generating ANSI C, and it's more correct.

1/4/94   Definition of compiler-generated virtual destructor

A bug has been fixed in handling the definitions of compiler-generated
virtual destructors of local classes and nested classes -- the bodies of
such functions were not generated under certain circumstances.  For
example, a linker error might occur in a case like this:

  struct A {
    virtual ~A() { }
  };
  struct B {
    struct N : public A { };
  };
  B::N *pbn = new B::N;

1/4/94   Mangled name for virtual function table for ambiguous base class

The mangled name for the virtual function table for a direct nonvirtual
base class having the same name as a nondirect virtual base class now
contains an extra "__A" so that the two virtual function tables will
not have the same name.

1/3/94   Integral promotion of bit fields

Integral promotion of bit fields now uses the bit_field_is_signed flag
from the field entry instead of the signedness of the bit field's base type.

1/3/94   Instantiation pragma error messages

When an instantiation pragma references an entity for which a specialization
has already been provided a more descriptive error message is now issued.

12/23/93 Referenced flag on virtual destructors used only in delete/new

Virtual destructors used only in an array delete, or in an array new
with exceptions enabled, now cause the referenced flag in the destructor
to be set.

-------------------------------------------------------------------------------
Version 2.21, December 21, 1993

12/20/93 IL version number changed to 2.13

12/20/93 Parsing a throw specification

Some bugs have been fixed in parsing a throw specification.  For instance,
we no longer abort on invalid code such as:

  void f() throw(int(0)) { }

12/20/93 Cross-reference information on implicitly called functions

A cross-reference listing entry is now generated for functions that are
called implicitly, such as constructors, destructors, and user-defined
conversion functions.  They are not specially marked in the listing
provided by default, but the symbol-reference-kind bit vector includes a
new flag, SRK_IMPLICIT, to mark such calls.

12/20/93 User-defined global operator new()

A bug has been fixed whereby, under certain circumstances, a user
definition of global operator new was not put out because its IL
referenced flag had not been set properly.

12/20/93 Array --> pointer and function --> pointer on builtin operators

Array --> pointer and function --> pointer transformations are now
considered when trying implicit conversions to match builtin operators.

12/20/93 Division by zero warning using simulated integers

Expressions such as 0/0 produced "divide by zero" warnings when using
host integers but not simulated integers.  Warnings are now issued
in both modes.

12/19/93 address_taken flag in variables and routines

An address_taken flag has been added to the routine entry.  The
address_taken flag in variables is now set more precisely: in a
case like "a[1] = 1" the address_taken flag of "a" is no longer
set.  Some errors on taking the address of a bit field that were
formerly missed are now caught:

  struct A {int i:8;} a;
  int i = 1;
  void f() {
    &(i ? a.i : a.i);  // error caught now
  }

12/18/93 Pointers to interchangeable types not interchangeable in strict mode

In strict mode, pointers to interchangeable types (e.g., "int *" and
"unsigned int *") are no longer considered interchangeable.

12/17/93 Initialization of arrays with elements of class type

A bug has been fixed in initializing arrays of unspecified size whose
elements are empty classes.  For instance, the following used to loop
indefinitely; now we issue an error on the invalid initial value:

  class A { };
  A a[] = { 0 };                // error

A related fix has to do with initializing arrays with elements of
nonaggregate class type -- trying to initialize an element with a
brace-enclosed list is now reported as an error, e.g.:

  class B { int i; B(); };      // user-defined ctor ==> nonaggregate
  B b[2] = { { 0 }, { 0 } };    // error
  
12/17/93 C-generating back end output of types

The C-generating back end now outputs typedefs instead of the underlying
type for typedefs of pointer and routine types.

12/17/93 Conditional flags in IL lowering

Three bugs related to generation of conditional flags in IL lowering have
been fixed:

(1)  -x mode no longer aborts on compiling a program that requires a
     conditional flag for a global scope initialization.
(2)  The initialization of conditional flags is now done at the nearest
     preceding label if there is one.
(3)  Initialization code in the file-scope initialization routine
     to put the address of a conditional flag required in the first
     initialization in the routine into the object address table in -x
     mode is now put before the first initialization instead of after it.

12/16/93 "signed" in error diagnostic messages

Explicitly signed int (e.g., "signed int" rather than just "int") is
no longer displayed as "signed int" in error diagnostics.  It's
just "int" now.

12/16/93  __vec_new_eh called even with exceptions disabled

A bug caused the runtime routine __vec_new_eh to be called in some
cases even when exceptions are disabled.  For example:

  struct A {
    A();
    ~A();
  } a[100];

12/16/93  Check for double --> float conversion overflow

The check in float_pt.c for overflow or underflow on conversion of
a double constant to float falsely detected a problem in some cases.
That has been fixed.  However, it is still the case that such checking
is hard or impossible to do in a portable way, and the new check is
just as convoluted as the old one.  You may want to do something
better but more machine-specific on this check.

12/16/93  Determining the signedness of bit fields

It had been that when TARG_PLAIN_INT_BIT_FIELD_IS_UNSIGNED was TRUE a
plain "int" on a bit field declaration was turned into an unsigned int.
This behavior has been extended to other integral types, "char", "short",
"long", and "long long", and is now activated in cfront compatibility mode
as well.

12/16/93  Function template for operator new()

We now issue an error on declaring a function template for the
one-parameter version of operator new().  This is because it cannot be
overloaded.  The same restriction had already been in place for operator
delete().

12/16/93 Change in name of prelinker options

The names of some of the nm format options of the edg_prelink command
have been changed.

The nm format option for Solaris has been changed from SVR4 to Solaris
because we learned that the Solaris format is actually different from
the standard SVR4 format.

The M88K option has been renamed to SVR4 because it more closely matches
the standard SVR4 nm output.

12/15/93  Allocation-cleanup for exception handling

When a "new" allocation is done outside of a constructor, the address
recorded to allow a "delete" of the storage if an exception is thrown
was missing one level of indirection.

12/15/93  Sharing of virtual function table instances

In a case like the following, base classes can now share a single
instance of a virtual function table:

  struct A {
    virtual int f();
  };
  struct B : public A {
    virtual int f();
  };
  struct C : virtual public B {
    virtual int f();
  };

Formerly, we generated a virtual function table for A in C and one for
B in C, but they're really the same and can be shared.  Now they are.

12/15/93  Virtual function table problem in non-cfront-compatibility mode

In non-cfront-layout-compatibility mode, IL lowering would abort
while trying to generate virtual function tables if the most-derived
class contained no virtual function declarations but still had an
effect on the virtual function tables for its base classes:

  struct W {
    virtual int f() = 0;
    virtual int g() = 0;
  };
  struct A : public virtual W {
    int f();
  };
  struct B : public virtual W {
    int g();
  };
  class C : public A, public B { };

12/15/93  IL change: shares_virtual_function_info added to a_base_class

A new field, shares_virtual_function_info, has been added to a_base_class.
When it is TRUE the base class and a class derived from it share the same
virtual function info block (e.g., the same vtbl; it is used in IL
lowering to avoid creating superfluous vtbl entries).

12/15/93  Fixed bug in name mangling

Having a type qualifier above an unnamed class, an unnamed enum, or a
function type in a parameter list resulted in a truncated mangled name:

  typedef const struct {} *P;
  extern void f(int, P, const char *);
  typedef const enum {e} *E;
  extern void g(E, const char *);
  typedef int (F)(int);
  typedef const F *PF;
  extern void h(PF, const char *);
  main () { &f; &g; &h; return 0; }

12/14/93  Vacuous destructor call combining typedef and type keyword

A bug has been fixed that resulted in an internal error when a
vacuous destructor call contained a typedef name in the class qualifier.

  typedef char cc;
  void f()
  {
    char* p;
    p->cc::~char();
  }

12/14/93  Specific declaration of template function using a typedef name

A bug has been fixed that resulted in an abort when instantiating a
template function for which a typedef name was used as the routine type in
the specific declaration.  For example:

  template <class T> void f(T){}
  typedef void F(int);
  F f;                   // Specific declaration uses typedef name
  int main()
  {
    f(1);                // Instantiation of f(int) now works
  }

12/13/93  In C mode, tentative definition with incomplete type

In C mode we now issue an error when a tentative definition of a variable
with internal linkage appears with an incomplete type, even if the type
is later completed.

12/10/93  Ordering of types with types-as-subobjects promoted out of classes 

A bug in IL lowering's promotion of types out of classes has been fixed.
Formerly, when a template reference was moved to the right place in the
file-scope types list relative to types promoted out of classes, the
type-as-subobject version of the type would not be moved also.  That
resulted in type ordering errors in generated C code.

  struct V {};
  template <class T> struct A {};
  template <class T> struct B : public virtual V { A<T> a; };
  struct C { B<int> b; };

12/10/93  Spurious error eliminated

We no longer issue a spurious syntax error for the following case:

  class A { /* ... */ } A[2];

12/10/93 Lowering of destructor routine types in calls

In cases where a virtual destructor was called between the point where the
destructor was declared and the point where it was defined, the function
pointer used in the virtual call would not have the implicit extra "int"
argument.  That is now corrected.

12/10/93  IL Change:  two flags added to a_routine_type_supplement

Flags assoc_routine_is_ctor and assoc_routine_is_dtor have been added to
a_routine_type_supplement.  They are TRUE for routine types created for
constructors and destructors, respectively, and will be set even if
a routine entry has not yet been bound to the type.

12/10/93 Spurious "class may not have a template argument list" error

A bug has been fixed that caused a spurious error in the following example:

  struct XX {};
  struct A {
    int XX;
  };
  int main()
  {
    A a = {1};
    int i = 0;
    if (a.XX < 1) i = 2;  // Spurious error on this line
    return i;
  }

12/10/93 Leading "::" allowed in member selections

A leading "::" is now allowed on the member name following a "." or
"->" operator.  For example, "p->::A::x".  This was approved by
X3J16/WG21 at the 3/93 meeting.

12/9/93  Expression temporaries destroyed at labels

Temporaries generated in expressions are now destroyed at labels.  This
avoids the eventuality of destroying the temporaries at the end of the
scope in cases where they were never constructed.

  struct A {A(); ~A();};
  void m() {
    goto lab2;
    lab1: A();
          // Temporary for A() is destroyed here
    lab2:;
  }

12/9/93  Implicit conversions on expressions inside []

Implicit conversions are now considered for the second operand of the []
operator (the one inside the brackets) and for the expression inside the
brackets in a new-type, e.g., "new A[n]".

12/9/93  Walking of IL tree when using non-alternate file format

A bug was fixed in the handling of shared a_param_type lists (i.e., one
list pointed to by several routine type supplements) when the file format
selected is the "non-alternate" file format.  Formerly, an internal error
was reported from ptr_remap_function.

12/9/93  IL lowering: conditional flags for global scope expressions

Conditional flags for temporaries constructed within conditional operators
in global scope expressions are now correctly allocated as global-scope
variables so they will survive into the file-scope termination routine.
The following formerly provoked an abort:

  struct A {A(int); ~A();};
  int x;
  static A a = (x==0 ? A(1) : A(2));

12/4/93  Dynamic initialization of pointer-to-member-function in aggregate

IL lowering no longer generates an error constant in an aggregate constant
after lowering a constant that is a pointer-to-member-function dynamic
initialization (ck_dynamic_init).

12/1/93  C-generating back end outputs extern void variable as char

The C-generating back end now outputs a void variable as type char.

12/1/93  Void variable is not an lvalue

The following now gets an error:

  extern void v;
  &v;  /* Error, "v" is not an lvalue. */

12/1/93  (void *)0 cases in C mode

Two bugs related to the following in C mode have been corrected:

  void (*func_ptr) ();
  int i;
  void m() {
    func_ptr = 0 ? ((void*) 0) : func_ptr;
  }

One problem was that (void *)0 was not recognized as a null pointer
constant when it appeared in a not-evaluated portion of an expression;
the second problem was that standard conversions were not preferred
to nonstandard ones when reconciling the operands of a pointer operation,
which meant an inappropriate warning was issued in non-strict C mode.

12/1/93  New IL representation for base class derivations

A new structure, a_base_class_derivation, has been added to represent a
derivation from the derived class to a given base class.  Nonvirtual base
classes point to exactly one such entry, but virtual base classes point to a
linked list of one or more, where each identifies a different derivation
path.

This approach, which preserves information about all the paths to a
virtual base class (and not just the preferred one, as before), enabled us
to fix an obscure bug in checking for "dominance" and solves some problems
in unusual cases involving differing access to virtual base classes along
different paths to the virtual base class.

Quite a bit of code was changed to deal with the new data structure.
Nevertheless, the change is largely invisible to those using IL lowering,
since operations on base classes and the like are rewritten in C.

12/1/93  Name mangling for unnamed enums

There is now a mangled name representation (_Enn) for unnamed enums.
Previously, a case that needed such a thing provoked an internal
error.  For example:

  typedef enum {a} *P;
  void f(P x) {}


12/1/93  Error now issued if an unnamed enum is used as a template argument

An error is now issued if a template argument has a type containing
an unnamed enumeration.

  template <class T> void f(T) {}
  int main()
  {
    enum { e1};
    f(e1);
  }

11/30/93  Setting decl_position in IL entry

A recently introduced bug that sometimes caused the decl_position field
in an IL entry to be set incorrectly has been fixed.

11/30/93 Spurious errors using elaborated types with template parameters

In this example the elaborated type specifier "union U" was finding the
global U instead of the template parameter U.  This has been corrected.

  union U { };
  template <class U> inline void f(U u)
  {
    U *uptr = (union U*)(&u);
  }
  union U2 { } u2;
  int main() 
  {
    f(u2);
  }

11/24/93 No unreachable code warning on unreachable "{"

An "unreachable code" warning is no longer issued for a "{" that is not
reachable.  If there is code within the block, it will provoke the
diagnostic.

11/24/93 Access checking on overloaded function referenced by qualified name

When an overloaded function was referenced by qualified name, and there
are ambiguous base classes, an access error could be erroneously given.
This has been fixed.

  struct A {struct B {int bmf() int bmf(int);};};
  struct D : virtual public A, public A::B { };
  struct E : public A::B { };
  struct X : public D, public E {
    void mf() {D::bmf();} // Gave error
  };

11/23/93 Fixed abort on vacuous destructor field selection error

An abort no longer occurs on a vacuous destructor reference in which the
left operand has an error:

  void m() {
    struct X { typedef int T; }
    px->X::T::~T();  // "px" undefined; caused abort
  }

11/23/93 Improved error diagnosis for invalid class template member function

A more descriptive error message is now issued when an attempt is made to
define a member function declared in a base class.

  template <class T> struct B {
    void f();
  };
  template <class T> struct D : public B<int> {};
  template <class T> void D<T>::f(){}  // Error

11/23/93 Nondefining declaration of a member function of a class template

An error is now diagnosed for the following incorrect usage:

  template <class T> struct A {
    void f();
  };
  template <class T> void A<T>::f();  // Error

11/22/93 Use of a bit-vector for symbol reference information

The enum a_symbol_reference_kind has been replaced with a bit vector of
type a_symbol_reference_kind, and a series of #defines has been added to
symbol_tbl.h to define the bits in the set.  Some kinds of symbol
references are now represented by a combination of bits -- for example,
the former srk_use_and_modif (used, e.g., for increment operations) is now
represented as a reference (i.e., the SRK_REFERENCE bit is set) where both
the SRK_USE and SRK_MODIFICATION bits are also set.

This change was made for implementations that need to track reference
information in greater detail than is done by default: it should be fairly
straightforward to define (and maintain) additional bits in the bit vector
and to extend the cross reference output accordingly.

11/22/93 result_is_not_used flag on operands of "?" and ","

The result_is_not_used flag is now TRUE on operands of "?" and "," operations
only if the "?" or "," operation has void type.

11/22/93 Function definition when the function type comes from a typedef

An internal error has been fixed that occurred in scan_function_body in
the error case in which a function definition is declared with a type from
a typedef.  For example,

  typedef void F(unsigned);
  F f { /* ... */ }               // Internal error fixed
  class X {
    static F g { /* ... */ }      // Internal error fixed
    friend F h { /* ... */ }      // Internal error fixed
  };

11/22/93 Error recovery while processing template class static data members

An internal error could occur while processing an invalid static data
member declaration in during the instantiation of a template class.  This
has been corrected.

  struct A {
    int x;
  };
  template <class T> struct B : public A {
    static A::x;
  };
  B<int> b;

11/18/93 Spurious errors in -tall mode

When using the "all" instantiation mode the front end would attempt to
instantiate a function during the instantiation of a template class.  This
would fail if the function used the template class in a way that requires
the class to be a complete type.  The instantiation is now deferred until
the class is complete.

  template <class T> struct A {
    inline friend A<T> operator+(const A<T>&, const A<T>&);
  };
  template <class T> inline A<T> operator+(const A<T>& x, const A<T>& y)
  {
    return x;
  }
  int main()
  {
    A<int> a;
  }

11/17/93 Problem with non-alternate file format

Because IL lowering did not clear the pointers in a class scope when it
promoted the members out of the class, there would sometimes be internal
errors while walking the IL tree.  The problem has been fixed by clearing
the pointers.

11/17/93 Instantiation pragmas not at global scope

Using instantiation pragma at scopes other than the global scope did not
work in all cases.  This has been corrected.

11/17/93 Instantiating members of an incomplete class

The following case was accepted without issuing an error.  Attempts to
instantiate members of an incomplete class were detected.

  template <class T> class A;
  #pragma instantiate A<int>

11/17/93 Disallow default argument in a #pragma function declaration

An error is now issued if a default argument appears on a function
declaration within a #pragma, e.g.,

  template <class T> void f(T) {}
  #pragma instantiate void f(int = -59)                 // Error
  template <class T> class X {
    void f(int);
  };
  #pragma do_not_instantiate void X<int>::f(int = -31)  // Error

11/17/93 Friend class declaration with typedef name

An internal error has been fixed for the case in which a (nonstandard)
friend class declaration uses a typedef name rather than the actual class
name.  For example:

  class A;
  typedef A TA;
  class B {
    friend TA;       // Nonstandard friend declaration accepted
  };

However, an error is issued if the typedef name refers to a cv-qualified
class type.

11/17/93 Constructor for member in mem-initializer-list

An internal error has been fixed in an obscure case involving constructor
initialization of a class member specified in a mem-initializer-list.

11/17/93 Diagnostic when instantiating a member of a class specialization

An error should have be issued when an attempt is made to instantiate a
member of a class specialization.  An error was being diagnosed when
the "#pragma instantiate A<unsigned char*>::f" syntax was used, but not
when the declaration style syntax was used.

  template <class T> struct A {
    void f();
  };
  struct A<unsigned char*> {
    void f();
  };
  void A<unsigned char*>::f() {}
  #pragma instantiate void A<unsigned char*>::f()


11/17/93 Name lookup in instantiation pragmas

Under certain conditions names were not looked up properly when
processing instantiation pragmas.  This could result in an internal
error or a spurious error while processing the pragma.

  typedef unsigned char* T;
  typedef void T2;
  template <class T> void ft(T) {}
  #pragma instantiate T2 ft(T)

11/16/93 Restrictions on target type of conversion operator

A warning is now issued on declaring a conversion operator whose target
type is either a (possibly cv-qualified) base class of the class of which
the operator is a member or a reference to such a base class; as required
by a post-ARM change to the Working Paper, the warning states that the
declaration, though permitted, will not be used in explicit or implicit
type conversions.  In addition, an error is issued when the target type is
(possibly cv-qualified) void, in accord with a pending change to the
Working Paper, agreed to at the Boston meeting.  For example:

  class Base { };
  class Derived : Base {
    operator Derived();      // Was an error, now a warning
    operator Base();         // Now a warning
    operator Base&();        // Now a warning
    operator void();         // Now an error
  };

11/16/93 Abort while processing invalid instantiation pragma

A bug has been fixed that can cause an abort when scanning an
instantiation pragma containing a declaration that names a
function but is not a function declarator.

  template <class T> struct A {
    void f();
  };
  #pragma instantiate void A<int>::f

11/16/93 Name mangling of large nontype template arguments

The mangled name for numeric quantities in nontype template arguments
now includes an underscore after the length of the numeric string if
the length is greater than 9.  This avoids ambiguities when the length
is immediately followed by a digit of the literal value.

11/16/93 Display of float constants

The default print width for float constants in fp_to_string in
float_pt.c has been changed to 9.  double and long double constants
are still printed with a width of 18.

11/16/93 Member constant types

Member constants (an extension) are no longer restricted to integral
types but are now permitted to be of any scalar type.

11/15/93 Variable definitions not tentative in C++

IL lowering now changes all variables that have sc_unspecified storage
class and no initialization to have initk_zero initialization.  That
implies that the variable is a "real" definition instead of a
"tentative" definition.

11/15/94 Unreferenced const variables and inline functions in header file

A diagnostic is no longer issued on unreferenced const variables and
inline functions that are defined in a header file.  This is to be more
supportive of replacing #defines with the corresponding C++ idiom.

11/15/94 Cross-reference info on items in ctor-initializer list

mark_referenced is now called for base classes and members that appear in
a ctor-initializer list.

11/15/94 Referenced flag for types implicitly declared in a cast

A bug has been fixed to assure the IL referenced flag is set when a type
is implicitly declared in a cast -- here's a case (legal in C mode only)
that used to be missed:

  void * vp;
  int main() {
    ((struct { int i; } *)vp)->i = 0;
  }

11/15/94 Referenced flag for template static data members

The referenced flag for template static data members initialized
using default initialization was not being set properly under
certain conditions.  This has been fixed.

  template <class T> struct A {
    static int x;
  };
  template <class T> int A<T>::x;

11/14/93 Abort with -x on file-scope termination routine

A bug has been fixed that caused an abort in IL lowering or in
the C-generating back end for source files that require a file-scope
termination routine but no file-scope initialization routine.
This occurs only with exceptions enabled.

  struct A { ~A(); };
  main()
  {
    A a0;
    static A a1;
    return 0;
  }

11/14/93 Transformations on arguments of user-defined conversions

Array --> pointer-to-array and function --> pointer-to-function
transformations were done when not appropriate in some extremely odd cases:

  struct A {
    A(int (&)[3]);
    A(const A&);
  };
  void g(A);
  void g(float);
  main () {
    int arr[3];
    g(arr);      // Got error; okay now
    return 0;
  }

11/13/93 Static data members with incomplete types

In the following, the static data member was changed to an external
definition because of the anachronism that allows a static member
never to be defined.  That resulted in bad generated code.

  struct X;
  struct Y {
    static X x;
  };

The anachronism transformation is now suppressed when the static data
member has an incomplete type.

-------------------------------------------------------------------------------
Version 2.20, November 4, 1993

11/04/93 Default arguments on a friend function in a class template

A bug has been fixed that produced spurious errors in cases where default
arguments appear on a friend function declaration within a class template
declaration -- e.g.,

  template <class T> class X {
    friend void g(T, T* = 0);
  };
  template <class T> void g(T, T) { /* ... */ }

11/04/93 Function declared a friend in a class template

A very obscure bug was fixed that resulted in an internal error.  It
occurred with a template function that was also a friend declared within
a class template -- something like this:

  template <class T> class X {
    friend X<T> f(T*);
  };
  template <class T> X<T> f(T*) { /* ... */ }

The problem occurred if, during the processing to define f, the return
type X<T> was instantiated and resulted in a redeclaration of f.

11/04/93 Class specific operator delete may not be instantiated

Under some highly unusual circumstances it is possible for a
class specific operator delete routine to not be instantiated when
one is needed.  This is been corrected.

11/04/93 Loop reading the instantiation information file

On systems where chars are unsigned by default it is possible for
read_info_file to loop because the return value of getc is stored in
a char.  This has been corrected.

11/02/93 IL CHANGE -- an_accessible_base_class

Entries of type an_accessible_base_class are created as part of exception
handling support.

11/02/93 Name mangling for pointers to member functions

The name mangling done by IL lowering for pointers to member functions
was missing one detail -- if the function type is "const" or "volatile"
that was not indicated in the encoding.

  struct A {};
  void f(void (A::*pmf1)(double));       // f__FM1AFd_v
  void g(void (A::*pmf2)(double) const); // g__FM1ACFd_v (was missing "C")

11/01/93 Error on defining a friend function in a local class

An error is issued on an attempt to define a nonmember friend function
within the definition of a local class -- for example:

  void f() {
    class A {
      void g() { };  // Error -- wrong scope in which to define a function
    };
  }

11/01/93 Storage class checking for function templates

Some bugs have been fixed in the how storage class and linkage consistency
is enforced between a function template and its instances.  For example:

  extern int f(double);
  template <class T> inline int f(T) { return 0; }

where a warning is now issued to the effect that f(double), an instance
of an inline template function (and therefore requiring static storage
class), was declared extern.  (Note: X3J16 is reviewing the whether
"inline" and "extern" are incompatible attributes of a function -- the
resolution of this question may invalidate the current behavior.)

11/01/93 Error handling in vec_new

If vec_new is unable to obtain memory for either the requested storage
or for its own book keeping purposes it will now return NULL.  Previously  
the return value was unpredictable.

10/29/93 Destruction of expression temporaries after simple switch

A bug in IL lowering has been fixed.  The bug involved missing destructor
calls for temporaries created in expressions when a switch statement with
no associated scope appeared between the creation of the temporary and the
end of the scope.  For example:

  struct A {
    A(int);
    ~A();
    operator int();
  };
  void f()
  {
    switch (A(87)) {  // Temporary never destroyed
      default:
        break;
    }
  }

10/28/93 Include file search order -- new default behavior

It used to be that, by default, the primary include search directory was
the directory of the primary source file, except in pcc mode, where it was
whatever directory the current input file belonged to.  With this change the
pcc-mode behavior (which is the approach that predominates on UNIX systems)
has become the default, and the former default behavior is no longer
supported.  Support has also been added for a stack model, as employed in
Microsoft C compilers -- see STACK_REFERENCED_INCLUDE_DIRECTORIES, defined
in lang_feat.h.

Since behavior in this area is left "implementation defined" by the ANSI C
standard, implementations can modify push_primary_include_search_dir and
pop_primary_include_search_dir in host_envir.c to meet the requirements of
particular environments.

10/27/93 IL CHANGE -- New field in a_source_file

A new field, name_as_written, has been added to a_source_file.  It is
required for the implicit inclusion feature in automatic template
instantiation.

10/25/93 Disambiguating expressions and declarations

A bug has been fixed so that the following is now parsed correctly:

  new (int (*[10])())

10/25/93 Spurious error on undefined static function

An error is no longer issued on the following:

  static int f();
  int i = sizeof(f());      // Only reference to f() in translation unit

In other words, a diagnostic is required only when an undefined static
function is actually called or has its address taken.

10/24/93 Check for declaring a function "inline" after calling it

We now issue an error if a function is defined as inline after it is
called.  This used to be done only for member functions, but now it
is also done for nonmember functions, e.g.,

  int f();
  int g() { return f(); }
  inline int f() { /* ... */ }     // Now an error

for template functions, e.g.,

  template <class T> int f(T);
  int g() { return f(0); }
  template <class T> inline void f(T) { /* ... */ }       // Now an error

and member functions of template classes, e.g.,

  template <class T> class A { public: static int f(); };
  int g() { return A<int>::f(); };
  template <class T> inline int A<T>::f() { /* ... */ }   // Now an error

10/24/93 Diagnostic severity on superfluous semicolon in class definition

It is now a warning by default and an error only in strict ANSI mode if a
superfluous semicolon appears in a class definition (other than after a
function body, where it is ignored) -- e.g.,

  class A {
    int i;;           // No longer an error (except in strict ANSI mode)
  };

10/24/93 IL Lowering type promotion reworked

The algorithm for promoting members out of classes in IL lowering
has been reworked.  Formerly, in some very obscure cases involving
templates, the types on the types lists would be in an order that
would not work right when generating order-dependent output, e.g.,
C code.  This may have been invisible to true back ends.  One should
note that types now come out more in source order.  For example:

  struct A {
    typedef int B;
    struct C {
      typedef int D;
    };
  };

Formerly, the types came out in the order D, B, C, A.  Now they come out
in the order B, D, C, A.  That is, they are in source order if one
considers the position of class definitions to be the closing brace.

One tricky aspect of this processing depends on the new flags added to
a_type.

10/24/93 IL CHANGE -- new flag in a_type for placeholder typerefs

A placeholder typeref is an entry that appears on the types list of a
non-local class scope and that points to a class type; the latter always
represents an instantiation of a class template and is on the types list
of the file scope.  The placeholder typeref is marked by a new flag in the
type, is_placeholder_for_file_scope_type; and the template class it points
to is marked by referenced_by_placeholder_typeref.  This information is
used in IL lowering type promotion.

10/22/93 Bug in overload resolution fixed

When a conversion could be done both via a constructor and via a
conversion function, the relative goodness of argument matches was
not compared correctly.

10/21/93 Code after a throw is unreachable

The front end now recognizes that code following a throw is unreachable.
It recognizes only the simplest case, however:

  throw 1;   // Unreachable after this
  x ? throw a : throw b  // Not unreachable after this


10/20/93 Cast of 0 to pointer type allowed in nontype template argument

A cast of a null pointer constant (0) to a pointer or pointer-to-member
type is now allowed in a template nontype actual argument.

  template<char *P> class T {};
  struct A {};
  template<int A::*P> class TT{};
  T<(char *)0> x;      // Now okay
  TT<(int A::*)0> xx;  // Now okay

10/20/93 Increase in number of include files that may be opened at once

The constant MAX_INCLUDE_FILES_OPEN_AT_ONCE has been increased from
3 to 8.  This is a more reasonable value for virtually all systems
and may improve compilation speed slightly.  Note that, as ever, this
is not an upper limit on the maximum depth of include file nesting.
The definition of this value has also been moved from lexical.c to
host_envir.h.

10/20/93 Fixed confusing error on static data members

A confusing error message resulted when the definition of the static data
data member looked like a function declaration.  For instance,

  struct S {
    static int a;
  };
  int S::a(int);       // Better message is now issued

10/19/93 Exception specification on main()

An diagnostic is issued if an exception specification appears on main().

10/19/93 Explicit destructor calls using template parameters

The front end now supports explicit destructor calls using the name of
a template parameter as the destructor name.

  template <class T> inline void dest(T& t)
  {
    t.~T();
    (&t)->T::~T();
  }
  struct A {};
  struct B {
    ~B(){}
  };

  int main()
  {
    A a;
    B b;
    dest(a);  // Class with no destructor
    dest(b);  // Class with destructor
    dest(1);  // Nonclass
    return 0;
  }

10/18/93 Restriction on inheritance: class X cannot inherit an X

A change has been made to find_projected_symbol to deal with cases like
this:

  class A {
    typedef int B;
  };
  class B : public A {
    B* p;                // p is "ptr-to-B", not "ptr-to-int"
  };

The justification is that a B cannot be added to class B by inheritance
because that name is reserved for the constructor.

10/18/93 Sign extension of pcc mode integer constants when long long allowed

If the front end is configured to allow integers larger than long,
some large constants in pcc mode were not sign extended properly
and therefore did not compare correctly against other constants.

10/15/93 Bug in computing alignment of a class

The alignment requirements of an unnamed bit field are no longer factored
in when computing the overall alignment for a class.  For instance:

  class A {
    char a;
    int :0;   // force alignment of next field to multiple of 4.
    char b;
  };

Before the change the alignment and size of A were computed to be 4 and 8,
respectively; now we say the alignment is 1 and the size is 5.  (This
behavior assumes default settings of certain configuration constants in
target.h, including CFRONT_OBJECT_CODE_COMPATIBILITY = TRUE).

10/15/93 Orphan lists for block scopes

The generation of orphan lists for block scopes is now done at the end
of the function scope to give IL lowering a chance to add local types
and static variables in block scopes.

10/14/93 IL CHANGE: assoc_handler field in a_scope

The scope entry associated with a handler now contains a pointer to the
corresponding handler entry.  The parameter variable (also pointed to from
the handler entry) appears on the scope's nonstatic_variables list.

10/14/93 Fixed bug involving ambiguous base classes

This bug, sometimes resulting in an internal error, was occasioned by an
ambiguity in which a class was both a direct and an indirect base class of
a given derived class -- sometimes the offset of the direct base class was
incorrectly computed.

10/14/93 Tokenizing of numbers in pcc mode preprocessing

In code like the following, preprocessed in pcc mode, the "a"
of "1a" is no longer seen as a separate token.

  #define a 7
  int i = 1a;  /* "a" not replaced. */

10/12/93 edg_prelink supports the nm output of additional systems

The edg_prelink utility has been modified to accept the nm output
of additional systems and now support:

	SunOS (the default)
	Solaris 2.x
	SGI
	Motorola 88000 SVR4
	HP/UX

SunOS is the only version that has been extensively tested at this point.
Support for the other formats was added using small samples of nm output
that were provided to us.

Refer to the comments in edg_prelink.c and edg_prelink.h to select the
nm format and command line options that are most appropriate for the
system that you are using.

10/12/93 Order of types on type list when IL lowering does type promotion

When IL lowering promotes types to the file-scope types list, they
now end up in the order of original source definition.  This was
more or less true in the past, but not always.  For example:

  struct OUTER {
    class C {};
    TMPL<C> x;
  };

Formerly, the types ended up in the order TMPL<C>, OUTER, C.  Now they
appear in source order (C, TMPL<C>, OUTER).

10/12/93  Declaration sequence numbers

The support for declaration sequence numbers has been extended and
modified.  They are now put out on all declarations.  Moreover, they are
now put out on a per-file basis rather than on a per-scope basis.  In
other words, the first declaration in the source program is assigned
declaration sequence number 1, the next (whatever its scope) gets 2, and
so on.  This enables comparisons between scopes regarding which of two
declarations came first in the source program.

10/12/93 IL CHANGE: dynamic init entries

Two dynamic init kinds, dik_member_copy and dik_base_class_copy, have been
combined and generalized as dik_bitwise_copy; entries of this kind are now
used not only in the memberwise copying done by a copy constructor but
also for the initialization of a parameter for an exception handler.
A related change was to rename the field is_copy_constructor_for_subobject
a_dynamic_init to is_copy_constructor_with_implied_source.

10/11/93 Definition vs. declaration in cross-reference output

A defining declaration is represented by "D" in the cross-reference list,
whereas a declaration that is not a definition is now represented by "d".
(Part of this change involved moving the call to mark_declared out of
enter_symbol and adding a new routine, mark_defined; now they are invoked
in contexts in which distinction between defining and nondefining
declarations can be made.)

10/8/93 Reference initialization cases

The diagnostics on two cases have been changed:

(1)  A reference to non-const can be initialized by something that
     requires an implicit conversion but no "temporary":

       struct C {
         operator A&();
       } c;
       A &r1 = c;  // Now okay

(2)  A reference to non-const initialized with a class rvalue now
     gets no diagnostic in default mode (still a warning or error in
     strict mode):

       struct A {
         A();
       } a;
       A &r2 = fa();  // Error only in strict mode

10/8/93  address_taken on temporaries generated by IL lowering

The address_taken flag is now set (as it should be) for the temporary
generated in the following:

  const int &r = 3.0;

10/8/93  Source sequence list

Various changes were made to implement a source sequence list, which may
be produced by setting GENERATE_SOURCE_SEQUENCE_LISTS in host_envir.h to
TRUE.  The lists are pointed to by the scope entries associated with the
file scope, each function scope, and (in C++ mode only) each class scope.
Entries on the lists point to an IL entry (e.g., a variable or a
statement), and the IL entries point back to a source sequence entry.  The
lists have both next and previous pointers.  Walking the lists provides a
representation, down to statement granularity, of the order in which
declarations, statements, etc., appear in the source program.

10/6/93  Change in handling of instantiation information file

Formerly, the driver was responsible for extracting the instantiation
list from an instantiation information file and passing the name
of the file containing the extracted list to the front end.

The front end has been modified to read the instantiation list
directly from the list file, skipping over the first N lines that
are considered to be reserved for use by the driver and prelinker.
The number of lines to be skipped is defined by a configuration
parameter.  The prelinker has also been modified to use this parameter.
The eccp script has been updated accordingly.

10/4/93  Incorrect error output for types defined in template parameters

The error position information provided when a type definition appears
in a template parameter was not set correctly.  This could result in
missing or incorrect error position information appearing in the
error output.

  template <struct A { } T> struct B;

10/4/93  Spurious error on nested class in template instantiation

A spurious error has been eliminated on cases in which (1) a nested class
with a non-inline member function appears within a class template and (2)
the code calling for the instantiation of the template appears inside a
function.  For example:

  template<class T> class A {
    class N { void f(); };
  };
  template <class T> void A<T>::N::f() { };
  int main() {
     A<int> x;        // Spurious error no longer issued on A<int>::N::f
  }

10/3/93  Checking of unreferenced/unused symbols at end of scope

The diagnostic on an unreferenced parameter is now a remark instead of a
warning; and a warning is now issued on a (non-reference) parameter that
is set in the body of the function but never used.  In addition, several
messages have been modified a little -- e.g.,
  old:  variable "xxx" declared and never referenced
  new:  variable "xxx" was declared but never referenced

10/1/93  Spurious or redundant error on calls to operator new and delete

Spurious and/or redundant errors (complaining about ambiguity or
inaccessibility) have been eliminated on certain calls to member operator
new and delete.

10/1/93 Warnings on typedef declarations with no declarator

We now issue a warning on typedef declarations with no declarator even
if the type is a declaration (or even a definition) of a class or enum.
For instance:

  typedef struct S { int i; };     // Warning is now issued
  typedef struct T;                // Warning is now issued
  typedef enum E { e1, e2, e3 };   // Warning is now issued
  typedef enum { e = 100 };        // Warning is now issued

9/29/93  Cross-reference output for overloaded function call

The cross-reference output line for a call of an overloaded function
formerly indicated "A", for address-taken.  It now indicates the
correct "R" for referenced.

9/28/93  Interaction between automatic inclusion and -tused and -tall

A bug has been fixed that would, under certain conditions, result in
compilation errors when implicit inclusion was used with the -tused
or -tall instantiation mode.

9/15/93  New symbol reference kind

srk_error was added to the enumeration a_symbol_reference_kind to
represent errors in which the kind of reference is indeterminate.  The
corresponding cross reference output uses "E" (for error).

9/26/93  Dropping type qualifiers in C mode

A bug introduced a few releases back has been fixed.  Because of it,
some rvalues were allowed to keep qualified types.  An example is the
following, which got an error in C mode:

  typedef struct Bar { int a; } Bar;
  typedef struct Foo {Bar a;} Foo  ;
  extern void bar(const Bar);
  void foo(const Foo f) {
        bar(f.a);  /* Was error here. */
  }

9/21/93  Cross-reference output separator

The separator character between fields in the cross-reference output
is now a tab instead of a blank.  This was documented as changed in
that way on 12/15/92, but somehow the change was not made.

9/20/93  Catastrophic error recursion

Under certain conditions it is possible for the compiler to generate
a catastrophic error during the processing of an earlier catastrophic
error.  This condition is now detected and an appropriate diagnostic
is issued.

9/20/93  Spurious error on runaway recursive instantiation

The front end would sometimes issue a second error message when
it encountered a runaway recursive function instantiation.  This
has been corrected.

9/19/93  Internal error on function template call with incomplete type

There is no longer an internal error on a call of a function template
with an argument that has an incomplete type:

  struct A *p;
  template<class T> void f(T);
  void m() { f(*p); }

9/18/93  Reference information always maintained in expression routines

Reference information for symbol references is now maintained always
(formerly, it was only maintained if cross-reference information was
requested).  The information is now needed always to allow diagnosis of
uses of variables before they are set.  Several data structures, routines,
and variables in expr.c, exprutil.c, and overload.c were renamed.

9/16/93  Qualified names that use template parameters in elaborated types

Formerly, the declaration of b2 would cause an error to be issued.  This
usage is now accepted.

  template <class T> struct A {
    T           t1;
    class T     t2;
    T::B        b1;
    class T::B  b2;	// Was rejected
  };

  struct B1 {
    struct A {};
    struct B {};
  };
  A<B1> b1;

9/15/93  New symbol reference kinds

Two new enumeration values were added to a_symbol_reference_kind to
represent nonmodifying references to the value of an object (srk_use) and
references that are uses and modifications in a single operation
(srk_use_and_modif).  The latter is used to represent increment operations
and the like.  These enable better cross reference output, with new codes
"U" (for "used") and "C" (for "changed" -- an admittedly feeble
approximation of "used and modified in one operation").

9/14/93  Suppressing the used-before-set warning

The "-j" command line option may be used to suppress used-before-set
warnings on local automatic variables.  The front end's algorithm for
detecting such uses is conservative and is likely to miss some cases that
an optimizer with sophisticated flow analysis could detect; thus, an
implementation might choose to suppress the warnings from the front end
when optimization has been requested but to permit them when the optimizer
is not being run.

9/13/93  Declaration sequence numbers

A limited implementation of declaration sequence numbers has been added.
Sequence numbers are assigned on a per-scope basis, except that block
scopes share the sequence with the function scope containing them.  This
means, for example, that each variable and label declared within a
function is assigned a unique number, beginning at 1 and incremented with
each new declaration.  The number is stored in a new field in a_symbol.
The declaration sequence numbers of two symbols can be compared to
determine which appeared first in the program.

For the time being this capability is only incompletely implemented --
except for labels, defined variables, and named types, symbols should not
be assumed to have valid declaration sequence numbers.  (However, the
status quo is sufficient for the algorithm that determines whether a
used-before-set warning should be issued.)

9/9/93   Diagnostic on variable used before set

A warning is now issued if an automatic variable local to a function is
used before it is set.  The warning is not put out if a label or the start
of an unclosed loop intervenes between the declaration and the use, since
it is possible that the variable is set in code that has not yet been seen
but that will actually be executed first at run time.  For example:

  void f() {
    int i;
      :
   L:
     int j;
     ++i;          // No warning -- i may be set later.
     ++j;          // Warning -- j cannot have been set yet.
       :
   }

A diagnostic is also issued at the end of the declaration scope of a
variable if it has been set but never used; this applies to both static
and automatic local variables and to file-scope static variables as well.
The diagnostic is a remark if the variable is declared in an included file
and a warning otherwise.

9/9/93   New flags in a_variable

For variable entries representing function parameters two new flags are
now maintained: param_value_has_been_changed is set if the parameter is
assigned to or has its address taken, and param_used_more_than_once is set
if there is more than one use of the parameter.  The flags may be useful
for inlining.

9/9/93   IL lowering: virtual function tables

The definition of the virtual function table can now be put out for an
externally-linked class that is unreferenced.

9/3/93   Yet another IL change to support exception handling

An enk_throw expression node, which represents a throw expression, now
points to an object of type a_throw_supplement, which contains pointers
to a type and to a dynamic-init entry.

9/3/93   Branching into a handler

We now issue an error on a branch into an exception handler.

9/3/93   Generic function pointer type used by IL lowering changed

The generic function pointer type used by IL lowering (for example,
as part of the pointer-to-member-function struct) has been changed from
int (*)() to void (*)().  This should not have any effect on back ends,
since the type is always cast before it is used.

9/2/93   Global variable exceptions_enabled

The global variable exceptions_disabled and the configuration constant
DEFAULT_EXCEPTIONS_DISABLED have been renamed to exceptions_enabled and
DEFAULT_EXCEPTIONS_ENABLED, respectively.  The logic of the code that uses
them has also been modified, needless to say.

9/2/93   IL for switch statements with non-top-level case labels

In some very convoluted cases involving case labels that are not
at the top level in the switch, the IL generated for switch statements
was incorrect.  That has been corrected.

8/30/93  Automatic instantiation information variables changed to type char

The variables generated by automatic instantiation to record information
about entities that might be instantiated in a compilation now have type
char (instead of int), which saves some space in the executable program.

8/29/93  Jumping past initializing declarations

We now issue a diagnostic (an error in C++ mode, a warning in C mode) on a
goto or switch statement that produces a transfer of control that bypasses
an initializing declaration, as required by ARM 6.7.  (However, to be
consistent with cfront 2.1, only a warning is issued in cfront
compatibility mode for jumping over an initialization in a switch
statement.)

8/27/93  Large unsigned values for enumerations

In non-strict mode, values that the C standard defines as large unsigned
values are now allowed as enumerator values if they "fit" in an int.
Warnings are issued for suspicious cases.

                             /* When ints are 32 bits: */
  enum a {w = -2147483648};  /* No warning */
  enum b {x = 0x80000000};   /* No warning */
  enum c {y = 0x80000001};   /* No warning */
  enum d {z = 2147483649};   /* Warning */

8/26/93  Local const variables treated as constants

Local constant variables are now properly treated as constants when
used in constant operations:

  const int MaxChunk = 8;
  main(){
    const int MaxStep = 8;
    const int MaxCount = MaxChunk/MaxStep;
    float addr[MaxCount]; // No error anymore
  }

8/25/93 Type display in diagnostics

A couple of bugs in displaying types in diagnostic messages have been
fixed.  For example, the types of x and y are now displayed correctly in
the error message on line 3:

  const int * const *x;
  typedef int(*F)(int);
  F y = x;                // Error -- type mismatch on initialization

8/24/93 Ambiguity error on mem-initializer

We now issue an error when the reference of a mem-initializer in a
ctor-initializer is ambiguous.  This can occur when the type of a direct
nonvirtual base class is the same as that of an indirect virtual base
class, e.g.,

  class A { A(int); /* ... */ };
  class B : virtual public A { /* ... */ };
  class C : public A, public B {
    C() : A(0) { }                          // Which base class A?
  };

8/23/93 Local typedefs in template arguments

When a template argument involves a typedef name that is defined locally
within the scope of a function, that typedef name is now stripped from the
type in the IL representation (wherever it appears in the type tree).
This is because a template class has visibility outside the scope of the
local typedef name.  This change is also manifest in diagnostics that
display the type.  For instance:

  template <class T> class A { A(int); };
  void f() {
    typedef int *PI;
    A<PI> x;
  }

where the error message on the declaration of x will now complain that no
default constructor exists for class "A<int *>".  (Nonlocal typedef names
are not stripped off, however.)

-------------------------------------------------------------------------------
Version 2.19, August 19, 1993

8/19/93 IL display utility display of unprintable characters

Unprintable characters are now displayed correctly by the IL display
utility on host computers with signed characters.  Formerly, they
were put out as very large octal constants.

8/18/93 Automatic Template Instantiation

Automatic template instantiation is now supported.  A complete
prototype implementation of a linker feedback mechanism is provided.
This mechanism includes new functionality in the front end, modifications
to the eccp driver script, and a new tool called edg_prelink which
is run before the linker to provide the necessary instantiations.

Partial support is also provided for an environment in which a given
compilation generates all of the instantiations referenced by that
translation unit.  This mechanism requires that the linker be
able to discard all but one definition of each template entity.
The main component of the front end that is provided to support
this is a mechanism that ensures that each static data member
of a template class is initialized only once.

Automatic instantiation is enabled by default and may be disabled
using the -T command line option.  The default is specified by 
a configuration parameter in the lang_feat.h file.

Please see the internal documentation for additional information.

8/18/93 Implicit inclusion of template definition files

Applications that use templates and that were written in an
environment that uses cfront 3.0 typically include header
files that declare class and function templates but do not
include the source files that provide the definitions of
noninline functions and static data members.  The implicit
include features allows such applications to be compiled without
the need to add explicit includes of the template definition files.
The template definition files needed to compile a given program
will be automatically included.  This requires a file naming
convention similar to the one employed by cfront.  Implicit
inclusion is disabled by default and may be enabled using the
-B command line option.  The default is specified by a configuration
parameter in the lang_feat.h file.

Please see the internal documentation for additional information.

8/16/93 Declaring nonlocal variable or function with a local type

A warning is now issued in C++ mode if a nonlocal variable or function is
declared using a local type -- e.g.,

  void f() {
    struct S { };           // Local type S
    extern S *x();          // Warning
    extern void y(S&)       // Warning
    extern S z;             // Warning
  }

The warning also is issued for noninline friend functions declared within
a local class.

8/16/93 Instantiating return type of template function

When a template class type was the return type of a template function, it
sometimes failed to be instantiated when the function itself was
instantiated and an internal error resulted.  This has now been fixed.

8/16/93 Spurious error on label defined in function template

We no longer issue a spurious error on cases like this:

  template <class T> inline void f(T) { L: return; }
  void g(int i) {
  L: f(i);                // f(int) is instantiated in place; g's L
                          //   should not conflict with f's L.
  }

8/16/93 Array --> pointer and function --> pointer transformations

The array to pointer and function to pointer implicit transformations
are now done more accurately.  Formerly, they were never done when
initializing a reference, and always done otherwise.  This did not
accommodate some strange cases like the following:

  void ff();
  void g(char *const &r);
  void g(float);
  void i(void (*const (&r2))());
  void i(float);
  void m() {
    g("abc");  // Now okay
    i(ff);     // Now okay
  }

8/16/93 Guard code around template static data member initializations

A new flag TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE has been added
to target.h.  When it is set to TRUE, IL lowering will place "guard"
code around the initialization and destruction code for static data
members of templates.  This is necessary if template instantiation
resolution is done by instantiating everything and then having the
(specially-modified) linker discard duplicate copies of instantiated
routines.  Static data members are a problem in such a scheme because
the initialization/destruction code is generated in startup/termination
routines, and is undifferentiated from other code in those routines.
With the guard code, a flag is used to indicate that initialization
or destruction has already been done.  After any one instance of the
code does initialization or destruction, all other instances will do
nothing.

8/15/93 function-notation cast of nothing to void

The expression "void()" used to produce an internal error.  It no longer
does.

8/14/93 Copy constructors on template function calls

An internal error is no longer issued for cases like the following
(where a copy constructor is needed in calling a template function):

  struct String {
    String();
    String(const String&);
  };
  template <class T> T* f(T);
  void m() {
    String s;
    f(s);  // No internal error now
  }

8/14/93 IL CHANGE: initk_zero initialization kind for variables

The IL for dynamically-initialized static variables is changed by IL
lowering so that the initialization is actually done by generated
statements and expressions.  Formerly, after the transformation the
variable was marked as requiring no initialization.  However, this
caused problems, because it makes it impossible to distinguish a
tentative definition of a variable from a "real" definition, and
that is important if the definition appears in a library.  Now,
a variable that is defined but for which all initialization has been
rendered as code is given the initialization kind initk_zero, which
means "statically initialize to zero".

8/13/93 push_input_stack repackaged

A new routine, open_file_for_input, has been broken out of
push_input_stack, and calls to push_input_stack have been replaced by
calls to open_file_and_push_input_stack.  Moreover, new functionality has
been added to open_file_for_input to permit suffix replacement, as
required for the implicit inclusion feature of automatic template
instantiation.

8/13/93 Member function as argument to function template

The following no longer causes an internal error:

  struct A {void f() {}};
  template <class T> int foo(T) {return 1;}
  void m()
  {
    foo(A::f);  // No internal error anymore
  }

This is an extension relative to the ARM.

8/11/93 Linkage of enumeration types

An enumeration type declared at file scope is now given external linkage
if it is used to form the type of an externally linked function or
variable, in the definition of an externally linked class, or as a
template argument.  (This goes beyond what the ARM specifies but is
implicit.)

8/11/93 Destruction of temporaries created in loop test expressions

Temporaries created in loop test and increment expressions are now
properly destroyed each time around the loop.

8/11/93 IL lowering: destructor calls for temps in constructor wrappers

Proper destructor calls are now generated to destroy temporaries
created within constructor wrapper code.

8/10/93 Name mangling for float nontype arguments

In name mangling for float nontype arguments, the names generated are
now shorter (the trailing zero digits in the constant's representation
have been removed from the mangled name).

8/10/93 Operations allowed in nontype template arguments

Casts and other operations on arbitrary arithmetic types are now allowed
in nontype template arguments.  Pointer operations continue to be forbidden.

8/10/93 TARG_HOST_STRING_CHAR_BIT

We now provide limited support for configurations where the target
character is bigger than the host character.  The limitation is that
individual characters of string literals are still stored as host characters,
and therefore their values are limited to the host character range.
Warnings are issued for attempts to specify constants that cannot be
accurately represented.

8/9/93  Eliminated extraneous calls of coalesce_template_class_reference

A change (first released in version 2.17) was made to provide better
diagnostics when a template argument list follows something that is
not a class template name.  The change involved calling
coalesce_template_class_reference to check for this condition.  The
code has been improved to only do the call in cases that could
potentially be errors.  The extra calls resulted in a significant
degradation in speed of the compiler (several percent).  This change
eliminates the performance degradation.

8/9/93  IL lowering: rewriting of lvalue-returning operations

IL lowering now correctly rewrites lvalue-returning operations (assignments,
prefix ++/--, and "?" and "," operations) even when some of their operands
are bit fields or have register storage class.  Rewriting these things
in C terms requires duplicating parts of the expression tree.  Those who
are ambitious and want to handle these things directly in a back end
can disable this rewriting -- see LOWER_LVALUE_RETURNING_OPERATIONS
in target.h.

8/9/93  IL CHANGE: lvalue-returning "?" and "," operators

Lvalue-returning "?" and "," operators now have the flag
returns_lvalue_instead_of_usual_rvalue set.

8/7/93  Cross-reference output

Some minor bugs were fixed.  The symptom of the bug was that some
references to arrays came out as "address-taken" where in fact
"modified" or "referenced" was more accurate.

8/6/93  Folding of constant addressing expressions to constants in the IL

Constant addressing expressions that appear as initializer expressions
in C++ mode are (once again) folded to constant entries and rendered
as static initializations.

8/6/93  Additional IL changes to support exception handling

A new entry, a_throw_spec_type, was added, and the enumeration
a_throw_spec_kind has been eliminated.  Now "throws anything" is
represented by a NULL throw_specification pointer in the
routine-type-supplement; "throws nothing" is represented by a NULL
throw-spec-type pointer in the throw-specification entry; and "throws
this particular exception" is represented by a throw-spec-type entry.

8/5/93  Error recovery on functional-notation cast

Error recovery has been improved on functional-notation casts with
no arguments, e.g., T().

8/5/93  Message reworded

The message about an invalid destination type for a cast has been reworded
from

  type of cast must be arithmetic, pointer, or void

to

  cast to type "type" is not allowed

8/5/93  IL lowering: reusable copies of expressions

In a number of cases, IL lowering must make a copy of an expression
that can be reused.  That is, the reusable copy must have the same value
as the original expression but must not cause any side effects of the
first expression to be done again.  This can always be achieved by
copying the original expression to a temporary and then using the
temporary, but many simple cases don't need that rewriting.  The
routine make_reusable_copy handled this, deciding when a temporary
was needed.  However, in some cases involving array new's, assignments
returning lvalues, and pointer-to-member-function comparisons,
it did not use a temporary but should have, because although the
expression reused did not have side effects it might depend on the
values of program variables that might have changed between
the point of original use and the point of reuse.  For those cases,
a temporary is now used.

8/5/93  Type declared in parameter declaration (C mode)

A bug has been fixed in how a type declared in a parameter list is handled
in C mode.  The type, though allocated in the file scope memory region, is
now placed on the types list of the prototype scope, both for prototyped
and old-style function declarations.  (In C++ mode, by contrast, the type
appears on the types list of the file scope.)  For example:

  void f(p) struct x *p; { }
  void g(struct y *p) { }

In C mode the types x and y now appear on the types lists of the prototype
scope entries for f and g, respectively.  (In C++ mode there is no change
from previous behavior: both x and y appear on the types list of the file
scope.)

8/4/93   new of variable-sized array of incomplete type

An error is now detected on the following:

  struct A;
  void m() {
    int i = 1;
    new A[i];  // Error
  }

8/4/93   const variable with value 0 allowed as null pointer constant

A const-valued int variable with value 0 should, in our opinion, be
allowed as a null pointer constant.  We formerly failed to allow it
as such in overload resolution.  That is now fixed.

  struct A {};
  void f(char *);
  void f(A);
  const int i = 0;
  void m() {
    f(i);  // Allowed now.
  }

8/4/93   Promotion of unsigned char when sizeof(int)==sizeof(char)

If sizeof(int)==sizeof(char), unsigned char should be promoted to
unsigned int under ANSI integral promotion rules.  Now it is.

8/2/93  IL CHANGE: Added stmk_for statement

A new statement kind, stmk_for, and an associated data structure,
a_for_loop, have been added to the IL to represent "for" statements.
Formerly, an stmk_while statement was used to represent "for" statements.
The for-init statement and increment expression are no longer put out
independently -- they are part of the new statement.

7/31/93  IL CHANGE: Widening of bit field extractions now more explicit

On the eok_value_bit_field and eok_extract_bit_field operators, the
node type is now always the base type of the bit field; formerly, it
could be some different integral type, usually the type of the bit field
after integral promotion.  This was an IL shorthand to avoid the need
for an additional cast after the extraction, but the shorthand is now
felt to be undesirable.  The immediate problem was that casting on
such extractions was always done simply by setting the node type, which
meant that intermediate narrowing steps were lost (a cast to a small
size followed by a cast to a large size looked just like a cast to the
large size).  That bug could be solved, perhaps by allowing only one
type conversion by way of the shorthand, but even that began to seem
contrived, so the whole mechanism was removed.

7/30/93  IL lowering: better code for access to virtual base classes

The code generated to access virtual base classes that are nested
within other virtual base classes now uses a single pointer indirection to
get to the final virtual base class instead of going stepwise through
the pointers to all the intervening virtual base classes.

7/30/93  Fixed bug in assignment of base class offsets

In cfront object code compatibility mode there was an obscure bug in
assigning offsets to deeply nested classes that were also ambiguous.  It
has now been fixed.

7/29/93  No warning that vacuous destructor call has no effect

The warning about expressions that have no effect is now suppressed
for vacuous destructor calls, e.g.,

  p->int::~int();

since those are explicit ways of saying "do nothing".

7/29/93  C-generating back end output of gaps in structures

The C-generating back end has been changed so that it outputs large
gaps in structures as a single char array instead of many 8-bit bit fields.

7/29/93  IL lowering: code generation error

An optimization in the code generation for constructor calls resulted
in the constructor call being dropped when it appeared inside a conditional
operator (like "?") and a flag is set to indicate that a destructor must
be called later.

  struct sss { sss(); ~sss(); sss(const sss &); };
  sss foo () {return sss();}
  void m() {
    int t = 1;
    sss loc = t ? sss() : foo();
  }

7/22/93  Exception handling IL support

The pointer to a_throw_specification has been moved from a_routine to
a_routine_type_supplement.

7/9/93   cfront compatibility: extra macro arguments are just a warning

In cfront compatibility mode, extra arguments in a macro invocation
are now a warning instead of an error.

7/9/93   Internal error on cast to class type in constant expression

An internal error is no longer issued on a cast to a class type that
appears within a constant expression in C++.

6/30/93  Name lookup in classes whose base classes depend on template
         parameters.

We now allow template definitions to reference names that may not be
defined until a real instantiation is done.  The declarations in
class template A of member "a" and "b" were already accepted.  The
declaration of "c" was rejected even though a specific definition of
B<T> could be supplied that would make an instantiation of A possible.
The error test on "X::Z" is now deferred until a real instantiation is
attempted.

Class templates with bases classes that are template parameters has
been supported with limitations.  Most of these limitations have
been eliminated by this change.  In class template C the checking
of names such as X and X::Y is deferred until a real instantiation
is attempted.

  template <class T> struct B {
    struct X {
      struct Y {};
    };
  };

  template <class T> struct A : public B<T> {  // Example 1
    X  a;
    X::Y  b;
    X::Z  c;	// Not an error until a real instantiation is done
  };

  template <class T> struct C : public T {  // Example 2
    X  a;
    X::Y  b;
  };

  C<B> a;

6/30/93  Using qualified names to reference members of class templates

A bug has been fixed that would cause an error on the reference
to AT::I in the example below.  The problem was caused by
treating A<T> as a "prototype instantiation" when it should have
been treated as a "nonreal" instantiation.

  template <class T, class T2> struct AA {
    typedef const T& I;
  };
  template <class T> struct A : public AA<T, int> { };
  template <class T> struct B {
    typedef A<T> AT;
    typedef AT::I I;
  };
  B<int> b;

6/28/93  Redundant type qualifiers

Restrictions on redundant type qualifiers in C++ mode have been relaxed.
For instance:

  typedef const int CI;
  const CI x = 0;          // Error in C mode, no diagnostic in C++ mode
  const const int y = 0;   // Error in C mode, warning in C++ mode (or
                           //   an error in -A strict ansi mode)

6/27/93  Command line option to disable support for exception handling

A command line option ("-x") has been added to control whether support for
C++ exception handling is enabled.  The default behavior is set by
configuration constant DEFAULT_EXCEPTIONS_DISABLED (which would typically
be FALSE).  When "-x" is used the global flag exceptions_disabled is set
to the opposite value.

6/22/93  Type qualifiers on a cast to pointer to qualified class type

On a cast of a pointer to a class type to a pointer to a base type,
forced by an explicit cast or by a implicit conversion for initialization,
the type qualifiers on the result type are now those of the destination
type and not those of the source type.

6/21/93  FULL_SOURCE_POS_IN_IL_STATEMENT

A new configuration flag FULL_SOURCE_POS_IN_IL_STATEMENT has been added
to host_envir.h.  When it is TRUE, each IL statement contains a full
source position (sequence number and column number) instead of just
a sequence number.  The default is FALSE.

IL CHANGE: the fields seq_number, break_seq_number, and final_seq_number
(in a_statement, a_switch_clause, and a_block, respectively) have
been renamed position, break_position, and final_position.  This
renaming applies even if the default of FALSE is used.

6/18/93  Modified IL for exception handling support

The following have been added to the intermediate language:
  - statement kind stmk_try_block,
  - expression node kind enk_throw,
  - new data structures a_handler and a_throw_specification
  - in a_type: new flag used_in_exception
  - in a_routine: new pointer throw_specification
  - in a_scope: new variant field (for sck_block) parameter

-------------------------------------------------------------------------------
Version 2.18, June 18, 1993

6/17/93  Complex references of template parameters and nonreal classes

Prior to this change, template parameters were not allowed in
certain contexts.  We now support

  - template parameters in qualified names such as T::X::Y;
  - nonreal classes in qualified names such as A<T>::X::Y;
  - expressions involving template parameters as array bounds
    and as nontype arguments of other templates in contexts such as
    the declarations of member functions (such expressions could already
    be used in the bodies of template functions);
  - template nontype parameters whose types depend on other nontype
    parameters (we already supported nontype parameters that depended
    on other type parameters)

The changes include the creation of several different kinds of
tk_template_param types and ck_template_param constants,
changes to the type comparison and type traversal routines to
handle the new type and constant kinds, and changes to the
expression routines to deal with the new constant kinds.

6/17/93  Member constants must be of integral type

The member constant extension, already documented as restricted to
integral types, is now coded that way, too.  Examples:

  class A {
    const int i = 10;           // Okay -- equivalent to "enum { i = 10 };"
    const double d = 1.0;       // Error -- not an integral type
    int A::* const pi = &A::i;  // Error -- not an integral type
  };

6/17/93  Restrictions on nontype template arguments

Nontype template arguments are now scanned either (a) as integral
constant expressions, if the corresponding parameter is integral, or
(b) as a new expression kind (ek_template_arg), which disallows all
operators except & and sizeof.

6/16/93  Error on parameters of type void in C++ mode

An error is now issued if a function parameter is declared to have type
void.

6/16/93  Name mangling for nested typedefs

The names of typedefs defined within classes are now mangled correctly.

6/15/93  Recursive template instantiation bug fixed

During recursive instantiation of a template the template parameters
were not being reset to the proper value when returning to the
original instantiation.  This has been fixed.

6/11/93  Setting of break_seq_number

break_seq_number, which gives the sequence number of the break statement
(if any) at the end of a switch clause, is now set correctly (i.e., it
is left NULL) for the first clause in

  void f(int arg1, int arg2) {
    switch (arg1) {
      case 1:
        if (arg2 == 0) break;
        /*FALLSTHRU*/
      case 2:
        arg2 = 1;
    }
  }

6/10/93  Display of typedef names in diagnostic messages

Some bugs have been fixed to correct the display of typedef names in
diagnostic messages.  Problem cases involved pointer and reference
types, const qualifiers, and qualified names.

6/8/93  "void" dumped as "void" by C-generating back end

"void" is now dumped as "void" instead of "char" in the C-generating
back end.  "char" was used because some very old C compilers do
not accept "void".  We've decided we need not reach that far back.
The return types of generated startup routines have likewise been changed
to void.

This change is compatible with cfront in +a1 (ANSI C output) mode; the
old change was compatible with +a0 mode.  In practice, it should make no
difference.

6/7/93 Variable size array representation

tk_array type entries have a new flag, is_variable_size_array, on the
basis of which the element count is specified either by a literal value
(as before) or a new field, element_count_expr, a pointer to an expression 
node.  This is used for array types based on template parameters.  (Note
that this is an IL change that will affect back-end code.)

6/7/93 Template parameter constant representation

ck_template_param constants now come in three flavors (see
a_template_parameter_constant_kind).  One is used for simple template
parameter identifiers, e.g.,

  template <int I> class A {
    int a[I];
  };

where a template-param constant represents "I".  Another is used for
expressions involving template param constants, e.g.,

  template <int I> class A {
    static char s[I+1];
  };
  template <int I> char A<I>::s[I+1] = { 0 };

where a template-param constant represents "I+1".  The third is used
for member constants of template parameters, e.g.,

  template <class T> class A {
    int a[T::k];
  };

where "T::k" is represented by a template-param constant (because, during
prototype instantiation, "k" is assumed to be a member of "T" and a
constant).

6/7/93 Template parameter type representation

tk_template_param type entries have a new field that points to a descriptor
(of type a_template_param_type_descr) that is created when the template
parameter is used in a context that requires a class.  It enables improved
handling of cases like this:

  template <class T> void f(T::X);

where "T" must be a class type and "X" can be entered (and later looked up
again) as a member type of "T".

In addition, a field was added to discriminate among simple template
parameter types, types that are members of template parameter types, and
types that are the types of a nontype member of a template parameter type
(see a_template_param_type_kind).

6/7/93 Cfront compatibility change for scopes on dependent statements

Consider

  int f(int i) {
    if (i) for (int j = 1; j <= 10; j++) {}
    return j;
  }

In recent editions of the Working Paper, the dependent statement of the
"if" has an associated scope, as if the "for" were enclosed in {}.  The
reference to "j" in the return is an error because no "j" exists at that
point.  In the ARM and in cfront 2.1, no implicit scope is created; the ARM
says the reference to "j" in the return statement is an error because it is
outside of the dynamic scope of the variable, but cfront 2.1 accepts the
program.  With this change, the front end does not create the implicit
scope in cfront mode, and therefore approximates the cfront 2.1 behavior.
If the dependent statement is a declaration, an error is issued.

6/7/93 Cfront compatibility change for friend functions in class definitions

Cfront 2.1 does not correctly look up names in friend functions that are
inside class definitions.  In this example function f should refer to the
versions of a1, a2, e1, f1, and f2 that are defined in the class definition.
Instead, cfront uses the global definitions.  In cfront compatibility
mode we now handle this as cfront does.
  
  int a1;
  int a2;
  int e1;
  void f1();
  void f2();
  class A {
    enum E {e1,e2};
    int a1;
    static int a2;
    void f1();
    static void f2();
    friend void f()
    {
      int i1 = a1;      // cfront uses global a1
      int i2 = a2;      // cfront uses global a2
      int i3 = e1;      // cfront uses global a3
      f1();             // cfront uses global f1
      f2();             // cfront uses global f2
    }
  };


6/2/93 Using "." for qualification

Cfront allows "." to be used in place of "::" in qualified names.
Cfront refers to this as an anachronism even though it is not included
in the ARM list of anachronisms.  This feature is now supported in
cfront compatibility mode.  A warning is issued.

  struct A {
    static int i;
  };

  int main()
  {
    int i;
    i = A.i;   // Equivalent to A::i
  }

6/2/93 Useless function parameter declaration

A warning (or error in strict ANSI mode) is reported on cases like this:

  void f( struct { int i; } );

This will only come up in C mode, since it's already an error in C++ mode.

6/1/93 Cfront compatibility changes

(1) A function qualifier is now accepted (and ignored) on a constructor
    or destructor in cfront compatibility mode, e.g.,

      class A { A() const; };              // Warning in cfront mode

    (This is permitted by cfront 2.1 but is an error in cfront 3.0.)

(2) A non-member operator= is allowed (as an anachronism), e.g.,

      class A { };
      A operator=(A&, A&);                 // Warning in cfront mode

    (This is flagged as an anachronism by cfront 2.1 but is an error in
    cfront 3.0.)

(3) A parameter of type "const void *" is allowed (but treated as "void *")
    on operator delete() in cfront compatibility mode, e.g.,

      void operator delete(void *);
      void operator delete(const void *);  // Treated as a redeclaration
                                           // in cfront mode

    (This is permitted by cfront 2.1 but is an error in cfront 3.0.)

6/1/93 Diagnostics on compiler-generated assignment operators

The user may not rely on the compiler to generate a default assignment
operator for a class with const or ref members (ARM 12.8).  The
diagnostics for reporting this problem have been improved.

5/27/93 Inherited names in declarators

We used to issue a confusing error message when an inherited name appeared
as the declarator name in an out-of-line member function definition or in
a friend declaration.  The appropriate error is now put out.  Here's an
example:

  class A {
    void f();
  };
  class B : public A { };
  void B::f() { }          // Appropriate error is now issued
  class C {
    friend void B::f();    // Appropriate error is now issued
  };

5/27/93 Pointless friend declaration

A warning (or in strict ANSI mode an error) is now issued on a friend
declaration that refers to a member function of the "befriending" class.
For instance:

  class A {
    void f();
    friend void A::f();      // Warning now issued
    friend class A;          // Warning now issued
  };

In addition, an error was missed that is now reported:

  class A {
    friend void A::f();      // Error -- no A::f
  };

5/26/93 Elaborated-type-specifier using template param name (again)

The use of a template parameter in an elaborated type specifier is once
again permitted, as long as the kind (class, struct, union, or enum)
matches that of the template argument.  This reverses a change of 4/22
and restores previous behavior.  For instance,

  template <class T> class A {
    struct T t;     // Error no longer issued
  };
  A<int> a2;        // Error (as before) -- "struct int"
  struct B {};
  A<B> a1;          // Error no longer issued -- "struct B"

(The ARM is not clear about this, but it now appears that the standards
committee will endorse using template parameters in elaborated types, at
least in some contexts, since support for "friend class T;" is important.)

5/26/93 Fixed bug in detecting parenthesized initializer

The code that distinguishes a parenthesized initializer in a variable
declaration from a parameter list in a function declaration has been
modified to handle this case correctly:

  void (*pf)() (0);        // same as:  void (*pf)() = 0;

5/23/93 Abort fixed in vacuous destructor handling

An abort could occur when scanning a vacuous destructor references
using a typedef name in a nonqualified name.

  typedef int T;
  void f()
  {
    T t;
    t.~T();
  }

5/20/93 Non-aggregate base class with no default constructor

A superfluous warning has been eliminated when a class is declared that
requires generation of a default constructor but has a nonaggregate base
class that lacks a default constructor.  An error is still issued at the
point where the default constructor for the derived class is actually
generated.

5/19/93 Incorrect warning no longer issued

A warning about a temporary being used for the initial value of a ref to
non-const is no longer issued for:

  struct A {
      A(A &s);
      A();
  };
  struct B {
      int insert(A);
      int insert(int);
      int foo() { A ns; return insert(ns); }
  };

5/18/93 Fixed infinite loop bug

The following caused an infinite loop while recovering from an error
in the left operand of a "->" operator where an operator-> may apply.
Now fixed.

  struct B { int i; };
  struct A {
    B * operator-> ();
  } a1, a2;
  void m() {
    (a1+a2)->i = 1;
  }

5/17/93 Taking the address of a bit field

A new configuration flag ADDR_OF_BIT_FIELD_ALLOWED has been added.
When it is set to TRUE, one may take the address of a bit field
if its size and alignment match one of the integral types.  A warning
is issued.

-------------------------------------------------------------------------------
Version 2.17, May 17, 1993

5/14/93 Diagnostic on initializing an aggregate without an initializer list

In C++ mode an error is now issued if an array is initialized other than
with a brace-enclosed initializer list.

In pcc mode it is possible to initialize an aggregate by simply providing
the value for the first field or array element.  For example:

  int a[4] = 1;      // Okay in pcc mode -- same as "int a[4] = { 1 };"

As an extension this is also allowed as the default in ordinary C mode --
though a strict ANSI diagnostic may be issued.  It used to allowed in C++
mode also (though only for arrays) but now it is an error.

5/14/93  Tag names first used in an argument list inside a template class

In this example struct X is now entered in the global scope
only during a real instantiation.  Prior to this change it was entered
in the global scope during prototype instantiation.

  template <class T> struct A {
    friend void f(struct X x);
  };

5/14/93 Improved error on invalid use of a template argument list

A more specific error is now issued when a template argument list
follows a type name that is not a class template name.

5/13/93 Uninitialized const objects created by operator new

The logic used for detecting uninitialized const objects ("const objects"
in a sense that includes aggregate objects containing const components) is
now applied to objects created by operator new as well as to declared
variables.  The defining declaration of a const variable produces an error
in C++ when there is no initializer.  However, only a warning is issued on
an uninitialized const object created by new; this is because this area of
the language is not yet well defined (though we believe it will eventually
be an error).  Examples:

  typedef const int T;
  T i;                         // error -- uninitialized const variable
  T* pi = new T;               // warning -- uninitialized const object

  struct S { const int j; };   // warning -- const "j" but no constructor
  S s;                         // error -- uninitialized const member
  S* ps = new S;               // warning -- uninitialized const member

5/13/93 Warning on nonstandard preprocessing directives

A warning/error is now issued in -a/-A mode for #assert, #unassert,
#ident, and #alias.

5/13/93 Further size_t_arg changes

Some missing calls of size_t_arg were added, and some unnecessary calls
were removed.

5/12/93 TARG_UCHAR_MAX, TARG_SCHAR_MAX, and TARG_SCHAR_MIN deleted

Those constants are no longer needed are were removed from target.h

5/12/93 Pointless comparisons of unsigned to negative constants

A warning is now issued for pointless comparisons of unsigned values
with negative constants:

  unsigned short us;
  void m() {
    if (us == -1) {}  // warning
  }

5/12/93 Pointless comparison of unsigned to 0

One of the cases warned about as a pointless comparison of an unsigned
value against zero was wrong, and one case that should have provoked
a warning did not.  They now work right:

  unsigned int ui;
  void m() {
    0 <= ui;   /* pointless */
    0 >= ui;   /* okay */
  }

5/11/93 Type qualifier applied to reference type

A warning is issued now when a reference type is qualified.

5/11/93 il_entry_kind_names array

Two different pieces of code that converted an IL entry kind into a
string describing the kind have been replaced by an array il_entry_kind_names
in il.h.

5/10/93 Pure virtual function allowed in local class

We now allow a pure virtual function in a local class; we used to issue
an error, based on a (probably) too strict reading of ARM 9.8.

5/10/93 Types in conversion compatibility messages

Diagnostics issued for type compatibility mismatches for arguments,
nontype template arguments, default argument expressions, and initializers
now indicate the source and destination types.

5/10/93 Operand cast to reference type is subject to reference conversions

The result of a cast to a reference type is now considered to have come
from a reference and is subject to reference conversions when used as
an operand of the "?" operator.

5/7/93  Type declarations in anonymous unions

Types defined in anonymous unions are now "promoted" to the same scope as
members are.

5/7/93  New routine scan_function_body

Common processing done in function_definition, inline_function_definition,
and instantiate_template_function is now handled by a new routine,
scan_function_body.

5/7/93  il_read uses normal mem_manage allocation routines

il_read.c (IL file reading) has been changed to use the normal
allocation routines of mem_manage.c instead of its own malloc
wrapper.

5/6/93  Change to overload resolution involving template functions

The algorithm that selects the best function during overload resolution
now handles template functions more generally.  In particular, when
the extensions that allow inexact matches on parameters involving
template parameter types are used, the cost of the conversions is
now considered in evaluating the template function.

  struct B {};
  struct D: public B {};
  template <class T> int f(T, B*) { return 1; }
  int f(int, B*) {return 2; }
  void m() {
    D* p;
    int i = f(1, p);  // Picks non-template function
  }

5/6/93  Fix to conversion subsequence checking in overload resolution

  void f(int);
  void f(const int&);
  void m() {
    const int i = 1;
    f(i);  // Now diagnosed as ambiguous
  }

5/5/93  Incorrect argument transfer method used for template functions

Under certain circumstances a template function or member function of
a template class could be generated based on an incorrect
argument transfer method flag.  This has been corrected.

5/4/93  Error on pure specifier

A pure specifier may only appear as the token sequence "= 0".  We now
issue an error on cases like "= 00".

5/4/93  Calls of virtual functions from constructors and destructors

Calls of virtual functions of a class from within the constructor or
destructor of that class are now recognized as being non-virtual
(ARM 12.7).  Formerly, they were generated as virtual calls.  With
the way the virtual function tables were set up, this change should
cause no difference in behavior, but the new code is more efficient.

5/4/93  rvalue.member is an lvalue in C++

According to ARM 5.2.4, if a nonstatic data member is selected from an
rvalue class, the result is an lvalue.  This is different from C.
This is still not clear in the X3J16/WG21 WP, but there seems to be
some consensus on this point in the committee discussions.

  struct A {int i;};
  A f();
  main () {
    f().i = 1;  // Okay
    return 0;
  }


5/3/93  Point at which virtual function table is set in constructor wrapper

The virtual function table pointer in a class is now set before the
members of the class are initialized.  The order of the code in constructor
wrappers is now:

  - Initialize virtual base classes.
  - Initialize direct non-virtual base classes.
  - Set virtual function table pointer.
  - Initialize members of the class.

This produces better results when virtual functions of the class are called
while the members are being initialized.

4/30/93  Bug in enum constant linked list

A bug has been fixed in the construction of the linked list of enum
constant entries.  In this example an endless loop was created:

  enum E { a, b, c=a };     // Circular linked list eliminated

4/30/93  Improved checking for conversions for operands of built-in operators

The checking for conversions that will convert class type operands of
operators to types appropriate for the built-in versions of those operators
has been improved to consider pointer-to-member types.

4/29/93  OLD_STYLE_PREPROCESSING_IN_CFRONT_MODE

A new flag OLD_STYLE_PREPROCESSING_IN_CFRONT_MODE has been added to
lang_feat.h.  When TRUE, it forces old-style preprocessing when
compiling C++ in cfront compatibility mode.  The default is FALSE,
which is the previous behavior.

4/29/93  Pointers to virtual base class data sections

In a_base_class the field pointer_offset is now defined for all virtual
base classes, not just for direct base classes, and pointer_base_class may
be non-NULL for both direct and indirect virtual base classes.  See the
commentary in il_def.h for a precise description of how these fields are
used and how they interact with each other.  There were some bugs in this
area in "default" layout mode -- as opposed to the layout used for cfront
object code compatibility.  Those bugs have been fixed.

4/28/93  Spurious error on extern redeclarations

A spurious error was sometimes issued when an array was defined and then
redeclared with an incomplete type.  Here's an example:

  static int a[10];
  extern int a[];              // Spurious error no longer issued

4/28/93  result_is_not_used flag in IL expression nodes

There is now a flag result_is_not_used in expression nodes, which is
TRUE for void expressions (those whose values are not used further).
This can be useful in optimizing the generated code.  IL lowering
makes use of the flag in one case.

4/28/93  Use of unimplemented reserved words

Use of try, catch, and throw now cause a strict ANSI diagnostic
to be issued in strict ANSI mode.

4/28/93  Minimum alignment requirements for class/struct/union objects

A new configuration constant, TARG_MINIMUM_STRUCT_ALIGNMENT, has been
added to match the alignment of objects of class, struct, and union type
to the requirements of the target environment.

4/27/93  Memory leak involving param-id entries

Sometimes param-id entries were not being returned to their available
list after they were no longer needed.  This has been corrected.

4/27/93  Access declarations involving conversion operators

When a conversion operator was mentioned in an access declaration, the
conversion-list-entry was not being created.  This bug has been fixed.

4/27/93  No access control on base class cast for "this" of conversion

  class base {public: operator int();};
  class derived : private base {
    public:
        base::operator int;     // adjust access to 'base::operator int'
  };
  void m() {derived de; int i = int(de);} // No error


-------------------------------------------------------------------------------
Version 2.16, April 27, 1993

4/27/93  IL version number changed to 2.08.

4/26/93  Pointer-to-member constant IL representation changed

Pointer-to-member constants in the intermediate language now have
a base class pointer instead of a class pointer to indicate casts
that have been applied to the pointer to member.  The former
representation could not provide full information in the presence
of ambiguous base classes.  This change is invisible to those
using IL lowering.

4/26/93  Pointer-to-member and null pointer constants in diagnostics

Pointer-to-member and null pointer constants as arguments of templates
are now displayed correctly when shown in diagnostic messages.

4/26/93  Default argument on declaration of operator new()

Default argument expressions are now allowed for the second and
subsequent parameters of an operator new() declaration.

4/26/93  exprutil.c broken up

The code in exprutil.c has been split into exprutil.c and overload.c
(overload resolution and conversions).

4/25/93  IL lowering code broken up

The code in lower_il.c (formerly a 12,000 line file) has been split into
lower_il.c, lower_name.c (for name mangling code), and lower_init.c (for
initialization, new/delete, and constructor/destructor code).

4/24/93  Bug in computing base class offsets

A bug has been fixed in computing the base class offsets of deeply
layered ambiguous base classes which have several ambiguous base classes
on their derivation lists.  Here's an example that manifested the
problem:
                           //      X   X   X   X
  class X { };             //      |   |   |   |
  class A : X { };         //      A   B   A   B
  class B : X { };         //       \ /     \ /
  class C : A, B { };      //        C       C
  class D : C { };         //         \     /
  class E : C { };         //          D   E
  class F : D, E { };      //           \ /
                           //            F

We now get the offsets right for all four instances of base class X in
derived class F.

4/23/93  fp_hash routine

A new routine fp_hash has been added to float_pt.c.  It contains the
code that was in hash_constant in il.c to develop a hash constant from
a floating-point value.  The code has been moved to float_pt.c because all
code that accesses the internal representation of a floating-point
constant should be there.  The code in eq_constants in il.c that compares
floating-point constants has been changed to use fp_compare for similar
reasons.

4/23/93  Bug in computing base class offsets

A bug has been fixed in computing the base class offset of certain
nonvirtual indirect base classes that were themselves base classes of
virtual base classes; it was a problem in "cfront object code
compatibility" mode only.

4/22/93  cfront compatibility mode extension for pointers-to-members

Type qualifiers on the "this" parameter may now be dropped in
initializations and assignments of pointers to member functions:

  struct A { void f() const; };
  void (A::*fp)() = &A::f;        // allowed as an extension

4/22/93  Elaborated-type-specifier using template param name

Reversing a modification made 2/23/93 the use of a template parameter
in an elaborated type specifier is now reported as an error, both during
prototype instantiation and during real instantiations, even when the
parameter type is a class type.  For instance,

  template <class T> class A {
    struct T t;     // Error now issued
  };
  A<int> a2;        // Error (as before) -- "struct int"
  struct B {};
  A<B> a1;          // Error now issued -- even though "struct B"

The ARM is not clear about whether the new errors are appropriate.
However, conversations with key members of the standards committee
indicate that this is the direction in which the standard is going.

4/22/93  Bug in constructor wrapper code (IL Lowering)

A bug in the code generated to access virtual base classes in constructor
wrappers has been fixed.  The problem was that an uninitialized pointer
to a virtual base class was used in determining the address of another
virtual base class.

  class Object {};
  class Link : public virtual Object {};
  class QLink : public Link {};
  class AllLink : public Link {};
  class Vehicle : public AllLink, public QLink {};
  class LandVeh : public virtual Vehicle {};
  LandVeh lv;

The bad code was in the constructor for LandVeh.  This problem only
occurred with very complicated virtual base class interactions, and only
when cfront layout compatibility is chosen (which is the default when we
ship the front end).

4/21/93  Bug in computing base class offsets

A bug in the management of base classes has been fixed.  It could only
show up when a nonvirtual base class appeared multiple times in the
derivation graph, as in the following:

  class Link { /* ... */ };
  class X : public Link { /* ... */ };
  class Y : public Link { /* ... */ };
  class D : public X, public Y { /* ... */ };

Here, for instance, one result of the bug was that the offset of one
of the Link base classes in D (the one accessed along the path
==>Y==Link) was not being computed correctly, and consequently the
delta value in its virtual function table was not being set properly.

4/20/93  Optimization of return via copy constructor

In functions that return their values via a copy constructor call,
an explicit constructor call as the return expression is now recognized
as an optimizable case and a superfluous copy constructor call is no
longer generated:

  struct A {
    A(const A&);
    A(int);
  };
  A f() { return A(1); } // No copy constructor call


4/20/93  Diagnostics on invalid operations on enum types

Prefix and postfix increment and decrement and compound assignment
operations applied to enum types now yield diagnostics:

  enum E {a, b, c};
  int main()
  {
    E e = a;
    e++;
    ++e;
    e += 1;
    e = 1;
  }

These are now only accepted as anachronisms.

4/19/93  Linkage on nested classes

A bug has been fixed affecting how linkage was set on members of nested
classes.  For example,

  class A {
    class B {
      static int i;      // A::B::i is now marked as externally linked
    };
  };

4/19/93  IL lowering generates dtor calls on goto to label before init

Proper destructor calls are now generated on a goto backward to a label
preceding some initializations in the same block.

  struct A { ~A(); A(int); };
  void m() {
    label:
      A x(1);
      goto label;  // should destroy x
  }


4/18/93  Optimization: extra temporaries/copy constructor calls avoided

Cases that involved generation of a temporary and then a copy constructor
call to copy that temporary to another temporary or to a variable being
initialized now avoid the extra copy constructor call:

  struct A {
    A(const A&);
    A(int);
  };
  void f(A);
  A g();
  A x = A(1);  // No temp/cctor call
  A y = g();   // No temp/cctor call
  void m() {
    f(A(1));  // No cctor call
    f(g());   // No cctor call
  }

4/16/93  "const void" function return type

A remark is now issued instead of a warning.

4/15/93  New IL form for returning class via copy constructor

Routines that return a class value via a copy constructor no longer
have a return_value_pointer_variable indicated in the function
scope entry.  Instead, the return operation is described by a
dynamic initialization entry which is attached under a new
variant form of the stmk_return statement.  This change is
invisible to those using IL lowering.

4/15/93  Diagnostics on noninitialization of const/ref members

The severity and form of diagnostics issued in connection with the
noninitialization of const and ref members has been modified.

(1) An error is now issued (instead of a warning) on a nonaggregate
    class with const or ref members and no user-defined constructor.
    For example:

      class A {
      private:            // "private" member ==> not an aggregate
        const int i;
      };                  // Error (used to be a warning)

(2) An error is now issued (instead of a warning) when an object of
    an aggregate class with const or ref members is declared with
    implicit initialization.  For example:

      class A {
        const int i;
      };                  // Warning (as before)
      A a1 = { 0 };       // Okay (as before)
      A a2 = a1;          // Okay (as before)
      A a3;               // Error (used to be a warning)

(3)  An error is now issued (instead of a warning) when the ctor-
     initializer list in a constructor definition for a class with
     const or ref members fails to specify initialization for all the
     const or ref members in the class.  For example:

     class A {
       const int i;
       A() { }            // Error (used to be a warning)
     };

4/14/93  Routine calling method flag for template functions

This flag may have been set incorrectly under certain circumstances
for template functions and member functions of template classes.  The
flag is now set correctly.

4/14/93  New kind of IL dynamic initialization entry

A new kind of dynamic initialization entry (dik_call_returning_class_via_cctor)
has been added to allow initialization by a routine that returns a class
object via a copy constructor.  This is now used in place of adding
an explicit additional argument to the call in the unlowered IL.
The enk_temp_init node has also been changed so that it returns the
address or value of the temporary always instead of an arbitrary
expression.  This avoids the need to name the class temporaries in
unlowered IL.  All these changes are invisible to those using IL
lowering.

4/13/93  IL lowering for array initializations in aggregates

The code generated by IL lowering to do initialization of array elements
that are part of nonconstant aggregates is now correct.

4/13/93  Ellipsis arguments in function template declarations

When doing overload resolution for function templates arguments
were incorrectly considered to match an ellipsis argument.  Also,
a function declaration that differs from the template declaration
only by the presence or absence of an ellipsis argument was incorrectly
considered to be a specific declaration or definition.  These problems
have been corrected.  The result is that an ellipsis argument can
be declared in a function template declaration, but there is no way to
supply an actual argument in an ellipsis position in a call to a template
function.

4/13/93  Parameter names in abstract declarators

The handling of parameter names in abstract declarators has been made
similar to that in real declarators -- a parameter name can be referenced
in a subsequent parameter declaration (e.g., in a sizeof expression) and
duplicate parameter names are reported as errors.  Examples:

  void (*pf1) (int x, int array[sizeof(x)]);   // Now supported
  void (*pf2) (int x, int x);                  // Now reported

4/9/93  More information about friend declarations in the IL

Two new fields, friend_routines and friend_classes, have been added to the
class type supplement to identify the routines and classes that were
declared as friends of the given class.  This may be useful for symbolic
debugger support.  (Until now the friend information was only maintained
"backwards", with the class in which the friend declaration appears
recorded in the befriending_class field of the routine entry or class upon
which friendship was conferred.)

4/8/93  Spurious diagnostic on typedef declarations

A warning (or in strict ANSI mode an error) is no longer issued on a
typedef declaration without a declarator when the type declaration
declares a tag name or defines an enumeration.  For example:

  typedef struct S { int i; };     // No diagnostic
  typedef struct T;                // No diagnostic
  typedef enum E { e1, e2, e3 };   // No diagnostic
  typedef enum { e = 100 };        // No diagnostic
  typedef struct { int i; };       // Warning is still issued

4/8/93  Setting is_instantiation

The is_instantiation flags in the routine and variable entries
were not being set for functions and static data members generated
from templates.  This has been corrected.

4/8/93  Warning on missing expression in ctor-initializer

Now, when a nonclass field is being initialized in a ctor-initializer and
the init-expression is missing, a warning is issued.  Here's an example:

  class A {
    int i;
    A() : i() { }       // Warning is now issued for empty "()"
  };

The ARM is not clear enough to justify issuing an error, though that is
what cfront does.  This is probably a bug in the document.

4/8/93  Member function instantiations in tim_none mode

A bug has been fixed that caused member functions to be instantiated
even in tim_none mode.  This could cause multiple definition errors
when linking programs.

4/8/93  Abstract uninstantiated template classes

We now detect uses of abstract template classes even when they have not
yet been instantiated (as long as the template upon which they will be
based has been defined).  For instance, an error is now issued for this:

  template <class T> class A {
    virtual T f() = 0;            // pure virtual ==> A<T> is abstract
  };
  extern A<int> x;                // A<int> need not be instantiated, but
                                  //   error is still appropriate

4/7/93  Invalid parameter for copy constructor

It used to be that an error was always issued when a constructor had a
parameter whose type was that of the class being constructed.  Now the
error is issued only for copy constructors -- not only for cases like
A::A(A), but also for less likely cases like A::A(A,int=0), A::A(A&,A=0),
and A::A(A&,int=0,A=0).  The first is mentioned explicitly in the ARM
(12.1), but the reasons for disallowing it apply equally well to the
others.  On the other hand, we no longer issue an error for A::A(A,int) or
A::A(A&,A).

4/7/93  Unnamed types as function template arguments

Errors are now diagnosed for template function references when
for which a template parameter references an unnamed type.
For example,

  template <class T> void f(T) {}
  struct {} a;
  static union {} b;
  int main()
  {
    f(a);
    f(b);
  }

4/7/93  Local types as function template arguments in inline functions

Formerly, local types could be used as function template arguments if
the function template was declared inline.  Local type references
are now prohibited in all function template references.  This was
changed in anticipation of this rule being adopted by X3J16/WG21.

4/6/93  Constructor name in class template

In class template A<T> a constructor may be designated by A() or A<T>(),
but A<int>() is disallowed -- it is reported as an invalid constructor
name.  Similarly, in the body of the specific definition of A<int> a
constructor may only be designated by A() or A<int>().

4/6/93  File-scope incomplete array with static storage class

In C mode an incomplete array declared at file scope with static storage
class and never completed (i.e., never provided with a dimension) is now
treated the way a file-scope incomplete array of unspecified storage
class is -- it is given a default dimension of 1.  (In C++ mode,
however, an error is still issued.)

4/6/93  Pointer-to-member operands for "&&", "||", and "!" operands

The operands of the "&&", "||", and "!" operators are now allowed to
be pointers to members.  This was added in a recent draft of the
X3J16/WG21 Working Paper.

4/6/93  Error diagnosis for template operator and conversion functions

Errors are now diagnosed for invalid operator functions and conversions
functions that are generated from function templates.  Formerly,
cases such as the following were incorrectly accepted:

  template <class T> void* operator !(T) { return 0;}
  int main()
  {
    int i;
    operator !(i);  // Error - first operand must be a class type
  }

4/6/93  Reference to const initialized from bit field

The following is now accepted:

  struct A { int i:1; } a;
  const int &r = a.i;

A temporary is generated.  Formerly, this gave an error (cannot take the
address of a bit field).  This new behavior is not specified by the ARM,
but it makes sense, and cfront does it that way.

4/6/93  Diagnostic on storage class with class/enum declaration

The default is now to issue a warning when a storage class is declared
with a class, struct, union, or enum declaration.  An error is still
issued in -A mode.

4/6/93  Rounding mode hooks for IEEE floating point

The floating-point folding routines have been given a parameter
"depends_on_rounding_mode" which can be used by the routine to return
an indication that the result of the operation depends on the rounding
mode.  This is used to suppress the folding of such operations in
non-constant contexts.  The standard routines supplied by EDG do
not ever set the flag; it's just a hook provided for those who have
their own IEEE floating-point emulation library.

4/6/93  Error during nested instantiation

A bug has been fixed that could cause spurious errors, and possibly
an internal error, when a member function defined inside a class template
is instantiated while instantiating another member function of the same class
that was also defined inside the class.  For example,

  template <class T> struct A {
    void f1(){}
    virtual void f2()
    {
      f1();  // f1 will be instantiated while f2 is being instantiated
      A<T> xx;
    }
  };

  A<int> a;  // Causes virtual inlines to be instantiated

4/5/93  Class template with the same name as a template parameter

An error is now issued if a class template has the same name as a
template parameter.

  template <class T> class T {};  // Error

4/5/93  Nontype template parameters of reference type

These now work correctly.  For example:

  template <int& I> struct A {
     void f() {int j = I;}
  };
  int j;
  A<j> b;


4/5/93  Error checking for template static data members

An error is now issued if the template definition of a static
data member does not match the declaration in the class definition.
For example,

  template <class T> struct A {
    static int i;
  };

  template <class T> long A<T>::i = 1;	// Error - should be "int" not "long"

4/5/93  Template definition of operator delete prohibited

An error is now issued for a template definition of the global operator
delete.

4/5/93  Constructor access in default initialization of static data member

A bug has been fixed that caused a spurious access error when a private
constructor was called for default initialization of a static data member.
Here's an example:

  class A {
  private:
    A();
    static A a;
  };
  A A::a;                   // Spurious error no longer issued

4/5/93  Default argument bug

The default arguments that appear in a list of member function declarators
are now processed properly.  There used to be a bug in handling the
default argument token caches on all but the last function in the list.

  class A {
    void f(int = 0),        // default arg expression is no longer lost
         g(int = 1);                  
  };

4/5/93  Generating body for default assignment operator

A bug existed in generating the body for a default assignment operator in
a derived class when it needs to call a user-defined assignment operator
of a base class but the latter takes as an input argument an object of a
base class of its own.  For example:

  class A { };
  class B : public A {
  public:
    B& operator=(A&);      // Serves as copy assignment operator for B
  };
  class C : public B { };
  C x, y;
  void f() { x = y; }      // A spurious error used to be reported during
                           //   generation of C::operator=(C&)

Not only has the spurious error been eliminated, but there was also a
null-pointer abort that has also been fixed.

4/5/93  IL lowering problem with destructor calls in init of local static

Destructor calls for temporaries needed within the once-only initialization
of a local static variable are now issued within the "if" that prevents
the initialization from being done more than once.

4/5/93  Template parameter list error diagnosis

Errors are now issued when a template parameter list is inconsistent
with a previous declaration.  For example,

  template <class T> class A;
  template <int I> class A {};  // Error

4/5/93  Merging default values from template parameter lists

It is now possible to supply additional default values for template
parameters on subsequent declarations.  For example,

  template <int J, int K, int L> class A;
  template <int J, int K, int L = 1> class A { ... };
  template <int J, int K = 2, int L> void A<J,K,L>::f() {}
  template <int J = 3, int K, int L> int A<J,K,L>::i = 1;

4/4/93  IL lowering problem with pointer-to-member-function constants

Formerly, when IL lowering processed pointer-to-member-function constants
in a generated file-scope initialization or termination routine, it
allocated some constant entries in the wrong memory region, which caused
an internal error during IL writing/reading.  Now corrected.

4/2/93  Taking the address of a member function without "&"

It is now legal (except in strict mode) to take the address of a member
function without using "&", as in

  struct A { int f(); };
  int (A::*p)() = A::f;  // Now OK

This extension is accepted by cfront and is widely used in code.

4/2/93  Template specific definitions not at global scope

We now issue an error for specific definitions of a class templates
that are defined in a local or nested (i.e., nonglobal) scope.

  template <class T> class A {};
  void f()
  {
    struct A<int> {};  // Error
  }
  struct B {
    struct A<char> {}; // Error
  };

4/2/93  Linkage of inline template functions

The storage class and linkage of inline nonmember template functions was
not set correctly.  This has been fixed.

3/31/93 Error positions on bit-field diagnostics

The diagnostics issued for bit-field declarations now have more accurate
error positions.

3/31/93 Zero-length bit fields with names

Illegal by default, zero-length named bit fields are accepted in cfront
compatibility mode.  Since cfront's support of such declarations appears
to be accidental (there are various bugs), our support is minimal -- a
warning is issued, the name is ignored (that is, it is not entered into
the symbol table), and the bit-field is treated as though no name had been
supplied.

3/31/93 Static data member template with parenthesized initializer

Template static data member definitions with parenthesized initializers
are now supported.

  template <class T> struct A {
    static int i;
  };
  template <class T> int A<T>::i(sizeof(T)*10);  // Now supported

3/31/93 Unreferenced template static data members

When a template static data member definition is instantiated the
IL referenced flag is now set.  Previously, an instantiation
generated for an unreferenced static data member (in "-tall" mode,
for example) may not have been put out by the back end because
the referenced flag was not set.

3/31/93 Initialization of references to const arrays

The code that deals with initialization of references has been changed
so that it deals correctly with this case:

  typedef float Mat[3];
  Mat b;
  const Mat &a = b;

This case is complicated by the fact that the const on an array type
goes on the array element type instead of the array type.

3/30/93 Generation of bodies for virtual destructors

The automatic generation of bodies for virtual destructors is no longer
done while the class is being scanned.  Instead, it is done at the end of
the translation unit (i.e., once it is known whether there will be a
virtual function table to which its address must be added).

3/30/93 fp_negate routine added

A new routine fp_negate has been added to float_pt.c.  Formerly, negation
of floating-point constants was done by subtracting from zero, which did
not work with IEEE floating point.

3/29/93  Scanning array dimension in static data member declaration

The dimensions of an static data member array declaration are now scanned
in the scope of the parent class.  For instance, this case is now handled
correctly:

  class A {
  public:
    static const int size;
    static int array[];
  };
  const int A::size = 4;
  int A::array[size] = { 0, 1, 2, 3 };   // "size" is A::size

3/29/93  Improved support for operator declarations

We no longer permit operator-name declarators in certain contexts -- e.g.,

  void f(int operator+);

Moreover, an internal error is no longer produced on the following:

  extern void * operator new[](size_t);

3/29/93  Cfront compatibility in disambiguation

Contrary to the requirements of the ARM cfront treats the declaration of
x in following:

  class A { A(int); };
  double d;
  A x(int(d));          // variable or function declaration?

as the declaration of a variable initialized by a constructor call rather
than as that of a function taking an integer argument and returning an A.
We still follow the ARM by default in such cases, but now we handle it the
way cfront does in cfront-compatibility mode.

3/29/93  Local variables and class templates with the same name

The lookup for a name followed by a "<" has been changed from
a class lookup to a normal lookup.  Before this change case 1 was
accepted and case 2 was rejected.  Now case 1 is rejected and case
2 is accepted.

  template <int i> struct A {
    struct B {};
  };
  int main()
  {
    int  A;
    int  j;
    A<1>::B  b1;         // Case 1
    if (A < 1) j = 2;    // Case 2
  }

3/29/93  Default arguments containing template references

Default arguments for which token caches are built (for member
functions and for function templates) were not scanning template
references properly.  This example now works correctly.

  template <class T, class T2> struct A {};
  struct B {
    void f(A<int,int>* = new A<int,int>, int = 1) {}
  };

3/29/93  Error recovery when flushing code containing template references

The code flushes to a matching delimiter was not handling template
references correctly.  This has been corrected.

3/26/93  No temporary used when conversion function initializes reference

Initialization of references has been changed so that when a conversion
returning a reference is used to initialize a reference, no temporary
is used:

  struct B {B(const B&);};
  struct A {operator B&();} a;
  void f(B);
  void m () { 
    f(a);         // No copy constructor used after conversion function
  }

3/26/93  Abort in error message processing when message contains %

The error message routines were not properly handling messages
with embedded percent signs (which are used for error message
fill-ins).  This has been corrected.

-------------------------------------------------------------------------------
Version 2.15, March 24, 1993

3/24/93 Abort in class template declaration with nonreal base class

In certain unusual cases the front end aborted when a class template
had a base class specifier that was a nonreal class, e.g.,

  template <class T, int I> class A { /* ... */ };
  template <class T> class B : public A<T,0> { /* ... */ };

The failure, which occurred during prototype instantiation, is now fixed.

3/23/93 Diagnostic on linkage conflict

Now in default mode a remark is issued (instead of a warning) when
there the linkage specified in a declaration is inconsistent with that
of a previous declaration.  Note that an error or warning is still
issued in strict ANSI mode.

3/23/93 Diagnostic on duplicate friend declaration

Now a remark is issued (instead of a warning) on duplicate friend
declarations.

3/23/93 IL walk routines speeded up

The routines that walk the intermediate language tree have been speeded
up.  This was accomplished largely by moving a lot of code from il_walk.c
out to a new file walk_entry.h, and then compiling it twice with
different macro settings so as to avoid a lot of extra testing during
processing.

3/22/93 Spurious errors in initialization of arrays

Spurious errors are no longer issued on (1) initialization of a const
array of unspecified size, e.g.,

  const int a[] = { 1, 2, 3 };

and (2) initialization of const array with too few initializers, e.g.,

  const int a[3] = { 1, 2 };

3/22/93 C-generating back end no longer outputs useless code

The annotation comments and the code for unreferenced entities formerly
output by the C-generating back end (within comments or #if 0/#endif)
are no longer put out by default.  In versions generated with debugging
code, any debug request on the command line (e.g., -d0) will cause the
generation of the annotations and unreferenced code.  In the default case,
however, the generated C is now much smaller and (if you can believe it)
even more cryptic, and compilation using the C-generating back end is
quite a bit faster.

3/19/93 Change of page size in internal documentation

The page size in the LaTeX-form internal documentation has been changed;
it's now wider and taller, so more fits on a page.  The document is
also formatted in two-sided mode, since it's gotten too big to be
printed one-sided.

3/19/93 Rework of il_walk_flag and entry number prefix

Several things relating to walking the IL tree and writing IL to/reading
IL from a file have been cleaned up.

(1)  The entry number that preceded IL entries in the alternate file
format is now defined as a struct called an_il_entry_prefix.  The
prefix is present (though perhaps in smaller form) even when the
non-alternate file form is used.
(2)  The il_walk_flag in the source_correspondence struct has been
moved into the prefix.  This gets rid of the need for code to handle
several messy problems in initializing the il_walk_flag correctly.
(3)  There is a new separate walk flag for IL lowering in the prefix.
(4)  There is a file_scope flag in the prefix that in_file_scope now uses.
(This is much more efficient, and was the principal motivation for this
change.)
(5)  The next-orphan pointer preceding file-scope IL entries is now
allocated *before* the entry prefix.
(6)  String IL entries now have a prefix after they've been read back
in (previously, they had no prefix-equivalent preceding the entry once
they were read back in).

3/16/93 Spurious error on specific definition of template function

A spurious "referenced-but-not-defined" error was sometimes being issued
because the "referenced" flag was being set incorrectly in symbols for
specific definitions of template functions.  Here's an example:

  template <class T> void f(T) { }
  void f(int);                      // Spurious error no longer issued

3/15/93 Fix in access checking for protected members

The access checking for protected members mandated by ARM 11.5 had
a bug -- it was applied to members that had protected access in
the derived class, not in the original declaration.  That has been fixed.

  class X { public: int a; };
  class Y2 : protected X {};
  class Z2 : public Y2 {
    void f(Y2* py2);
  };
  void Z2::f(Y2* py2) {
    py2->a = 7;    // Was error, now okay
  }

3/5/93  Casting class non-lvalues to a reference type

The checking for explicit casts to reference types has been relaxed
to allow casting of a non-lvalue class to a reference type.  It's
not entirely clear that the ARM allows this case, but since it
says "object" and not "lvalue" it's reasonable to allow non-class
lvalues.

3/3/93  Lexical special characters moved

The special characters END_OF_TOKEN_MARKER and ATTENTION_MARKER used
by the lexical routines have been moved to 0x81/0x82.  These values are
better for ISO 8859 and EUC, and happen to avoid a test failure in the
Perennial C++ suite.  However, for full internationalization these
special characters should be removed altogether, and we will probably
do so at some later date.

3/3/93  Uninitialized const or ref field of aggregate class object

In C++ mode we now issue an error when a class object that is an
"aggregate" (ARM 8.4.1) and that has const or ref nonstatic data members
is declared without an initializer.  The error is also issued when there
is partial initialization but at least one const or ref field if left
uninitialized, or when an array of such class objects is only partially
initialized.  (In C mode we continue to issue a warning on such cases.)

3/3/93  Cleanup of use of <ctype.h> macros

All uses of the <ctype.h> macros (e.g., isalpha) in the front end code
have been changed slightly to make them work properly in the presence of
non-ASCII input characters on systems where plain "char" is signed.
The changes are all on the order of changing

  isalpha(ch)

to

  isalpha((unsigned char)ch)

The macro isascii is no longer used (it was defined by basics.h for
systems that don't have it).

3/3/93  Allow const/volatile qualifier on new-type-name

The syntax of ARM 5.3.3 does not permit a type qualifier on new-type-name,
but that was probably an oversight (comment by Stroustrup at an X3J16
meeting).  Now, instead of reporting an error, we allow the qualifier and
(pending a change to the language definition) issue a warning in strict
ANSI mode.

3/3/93  Error on illegal function qualifier

An error is now issued on all illegal function qualifiers -- e.g., when a
static member function is declared to be "const".  Before a warning was
issued in some cases.

3/3/93  Disambiguation -- param list vs. arg list

In response to what seems to be prevailing practice (and in the absence of
decisive guidance from the ARM), we have changed our approach to
disambiguating a list that could be either an argument list in a
constructor call or a parameter list in a function declaration.  If
necessary, we now look beyond the first list item in attempting to resolve
the ambiguity.  Consider this example:

  class A { /* ... */ };
  static int i, j;
  A x(int(i));            // still interpreted as a function declaration
  A y(int(i),0);          // now interpreted as declaration of a variable
                          //   with constructor initialization
  A z(int(i),int(j));     // still interpreted as a function declaration

In the declaration of "y" we used to reason that "int(i)" could be either
a declaration or an expression and so must be a declaration; consequently
"y" was taken to be function, and an error was issued on the second
"parameter".  Now, we keep looking at subsequent items in the list until
the ambiguity is resolved or the end of the list is reached.  In the case
of "y" the ambiguity is resolved by the second item in the list, which
cannot be a declaration.  If the end of the list is reached without
resolution (as in the declaration of "z"), the ambiguity is resolved in
favor of a declaration.

3/3/93  Divide by zero when multiplying by (unsigned long)0

Folding of a constant expression containing an unsigned multiply
by zero caused a divide by zero error.  This error would occur only
when using host integers to represent target integer values.

  void f(void)
  {
    (unsigned long)1 * (unsigned long)0;
  }

2/26/93  Check type of extra argument for postfix incr/decr operator

The type of the extra argument in declarations of postfix operator++ and
operator-- is now being checked; an error is issued if it is not "int"
(ARM 13.4.7).

2/26/93  Prefix ++ and -- returning lvalues

The prefix ++ and -- operators now return an lvalue in C++ mode,
as they should.  The flag assignment_returns_lvalue in the IL expression
entry has been renamed returns_lvalue_instead_of_usual_rvalue so that
it can apply to this case as well.

2/26/93  Redeclaring a class template as a tag

An error is issued if the name of a class template is redeclared to be
a tag name in the same scope.

  template <class T> struct A {};
  enum A {};

2/25/93  Error on self-targeted conversion operator

Enforcing a restriction that appears in Working Paper 12.3.2 (but not in
the ARM), an error is now issued when class X contains a user-defined
conversion operator that converts to X (with or without type qualifiers)
or to X&.

2/25/93  Invalid argument list on template member definition

The error handling has been improved for definitions of members of class
templates in which an incorrect template argument list is supplied.  For
example,

  template <class T> struct A {
    void f();
  };
  template <class T> A<int>::f(){}

2/25/93  Bug in sizeof applied to overloaded function or operator

If sizeof was applied to an expression involving an overloaded function
or operator, the sizeof was determined on the basis of an unset variable
and was therefore probably wrong.  Also, the intermediate language
created included an error type, which might be the visible symptom of
this problem.

2/25/93  Functions called in not-evaluated expressions

When functions are called in not-evaluated expressions (e.g., in sizeof),
the referenced flag on the function is now not set.  Also, the function
is not instantiated if it is a template function, nor is it generated
if it is a compiler-generated function like a destructor.

2/24/93  Inconsistent linkage specifications for variables

We used to issue a warning when a variable was redeclared with a
different linkage specification.  Now it's a warning in strict ANSI mode
only and a remark otherwise.  Here's an example:

  extern char *strlist[32];
  extern "C" {
    extern char *strlist[];        // Now a remark by default
  }

2/24/93  Redeclaration of template parameters

An error is issued if a template parameter name is redeclared in a class
template or function template.  This is only considered to be an error if
the redeclaration occurs in the outermost scope of the template.  If a
parameter name is redeclared in an inner scope of a template a warning is
issued.

Note that a redeclaration in a member function inside the template
definition gives an error so that functions are treated consistently
whether the body appears in the class definition or outside the class
definition.

  template <class T> struct A {
    int T;                               // error
    void f() { int T;}                   // error
    void g();
    struct B {
      int T;                             // OK (warning)
    };
  };
  template <class T> void g() { int T;}  // error
  template <class T> void f(T)
  {
    int  T;                              // error
    {
      int T;                             // OK (warning)
    }
  }

2/24/93  Dynamic-init entries appear only at file scope

add_to_dynamic_inits_list has been modified to add a dynamic-init entry
at the file scope only.  This confirms the existing convention.

2/23/93  Bug with member function linkage in "local" instantiation mode

Whereas in local instantiation mode noninline member functions of
compiler-generated template classes have internal linkage, it was
incorrect to apply this rule to user-defined template classes as well.
This resulted in spurious errors, e.g.,

  template <class T> class Y {};
  struct Y<char> {
    Y();
    ~Y();
  };
  Y<char> yc;

for which the compiler complained that Y<char>::Y() and Y<char>::~Y)()
are referenced but not defined.

With this fix user-defined template classes (and their noninline member
functions and static data members) are given external linkage even in
local instantiation mode.

2/23/93  Elaborated-type-specifier using template param name

An elaborated type specifier involving the name of a template parameter
was processed incorrectly during prototype instantiation of class
templates -- e.g.,

  template <class T> class A {
    struct T t;                     // Spurious error no longer issued
  };

This construct is now scanned during prototype instantiation as though
the class-key were omitted.

2/23/93  Recursive instantiations involving functions and static data members

The end-of-compilation processing of instantiations has been modified
to enable detection of additional cases of runaway instantiations.

This is an example that uses a noninline function template.  The
instantiations had been generated serially which made detection of
the recursion difficult.  Instantiations requested during the
end-of-compilation processing are now generated on the fly which
allows the recursion to be detected.

  template <class T> void f(T x)
  {
    f(&x);
  }
  int main()
  {
    char    c;
    f(c);
  }

2/23/93  Reworking of expression kind in expression-processing routines

The ubiquitous "expression_kind" parameter in the expression routines
has been replaced by an expression_kind field in the expression stack
and some macros to reference it.  Also, the ek_not_evaluated expression
kind has been replaced by ek_sizeof and a separate "evaluated" flag
is now maintained.

2/23/93  Limit on recursive instantiation of inline functions

The front end limits apparent "runaway" recursion in the instantiation
of inline functions -- for instance:

  template <int i> class A {
  public:
    void f() {
      A<i+1> a;
      a.f();
    }
  };
  main()
  {
    A<1> a;
    a.f();
  }

This example used to cause a runaway instantiation of class A<1>...A<n>.
Now that we only instantiate inline functions when they are referenced
the recursion actually occurs during instantiation of the inline
function "f()".  A<1>::f instantiates A<2> and then calls A<2>::f which
instantiates A<3> and then calls A<3>::f, and so on.  Now, after the number
of recursive instantiations of a given function template exceeds a
configurable value (MAX_PENDING_INSTANTIATIONS), an error is issued and
the recursion is halted.

2/23/93  Tag names first used in an argument list inside a template class

In this example struct X should be entered in the global scope bug was
not.  This has been corrected.

  template <class T> struct A {
    friend void f(struct X x);
  };

2/23/93  Improved error recovery when scanning template arguments

Error recovery has been improved when too many template arguments are
supplied.

  template <class T> class A {
    void f();
  };
  void A<int, 1>::f(){}

2/23/93  Incorrect error message given for incomplete type

Cases such as this were giving an incorrect error message.  Instead
of saying "incomplete type not allowed" the message "B is not a class
name" was issued.  This has been corrected.

  class X;
  int X::B::* pmi;

2/23/93  Constant-valued variables in "?" and "," operators

The values of constant-values variables are now substituted for the
variables even inside "?" and "," operators:

  const long aa = 10;
  const long bb = 24;
  void m()
  {
    long i;
    i = ((i < 0) ? aa : bb);  // constant values substituted
  }

2/22/93  Support for cfront name lookup bug

Cfront 2.1 has a bug that causes a global identifier to be found when
a member of a class or one of its base classes should actually be found.
This bug is emulated in cfront compatibility mode.  A warning is issued
when, because of this feature, an incorrect lookup is performed.

This feature is supported only in cfront compatibility mode and only
when the CFRONT_GLOBAL_VS_MEMBER_NAME_LOOKUP_BUG flag in lang_feat.h is
TRUE.

The following code illustrated an instance in which the bug occurs:

  struct B   {
    void func(const char*);  // Needs to be here
  };
  struct D : public B {
  public:
    D();
    void Init(const char* );
  };
  struct func {
    func( const char* msg);
  };
  D::D() { }
  void D::Init(const char* t)
  {
    new func(t);
  }

For the bad lookup to occur:

  1. A member in a base class must have the same name as an identifier at
     the global scope.  Any member kind is OK -- it can be a function,
     static static data member, or nonstatic data member.  Member type
     names don't apply because a nested type will be promoted to the
     global scope by cfront which disallows a later declaration of a type
     with the same name at the global scope.

  2. The declaration of the global scope name must occur between the
     declaration of the derived class and the declaration of either an
     out-of-line constructor or destructor.

  3. No other member function definition -- even one for an unrelated class
     may appear between the destructor and the offending reference. This
     has the effect that the bad lookup applies to only one class at any
     given point in time.

2/22/93  Disallow const/volatile qualifier on operator new and delete

An error (instead of a warning) is now issued when a type qualifier is
specified on an operator new or delete declaration, e.g.:

  class X {
    void* operator new(size_t) const { /* ... */ };      // Error
  };

2/22/93  Incomplete types in class template definitions

An error is now reported if an incomplete type (other than one that is
or involves a template parameter) is used to declare a data member in
class template declaration.  (It used to be that the error was
suppressed during prototype instantiation, on the assumption that the
type might become complete by the time the first real instantiation is
done.)  For example:

  class A;
  template <class T> class B {
    A a;                        // Error issued on incomplete type A
    T b;                        // No error -- T is template param
  };
  class A { /* ... */ };        // Definition appears to late

We do not believe the ARM provides clear guidance on this matter, but a
paper by Stroustrup et al. (X3J16 document 92-133, Nov 1992), which
deals with name binding, may be read to imply support for this behavior,
and it is likely that the standard will incorporate the approach
described there.

A corollary is that an undefined instance of a class template may not
appear in the template definition, since it cannot in principle be
instantiated until after the template definition is completed, unless a
user definition is provided.  For example:

  template <class T> class A;
  class A<int> { /* ... */ };
  template <class T> class A {
    A<int> ai;                   // Okay -- A<int> is already defined
    A<double> di;                // Error -- A<double> is incomplete
  };

2/22/93  Fixed bug in cfront transitional nested type handling

In cfront compatibility mode an error was being issued if a nontype
entity was declared at file scope after a type was designated as
being a "semivisible" nested type.  The error should only be issued
when the entity is a type name.

  struct X {
    struct Y {};
  };
  int Y;

2/22/93  Casting to a template parameter type

Casting to a template parameter type within a template is now allowed:

  template<class T, T X> struct S {
    int a[(T)X];  // Now allowed
  };
  S<int, 10> ss;

2/19/93  Fixed bug with subscript as operand of "?" lvalue

The following provoked an internal error:

  struct String { String(const String&); String(); } object;
  template <class Type> struct Array {
    Type *ia;
    Type init() { return (ia) ? ia[1] : (Type) object; }
  };
  void test () {Array<String> SA; SA.init ();}

2/19/93  Default values for template parameters

Default values may now be provided for template parameters.  Defaults
may be specified for any nontype parameter, including those whose types
involve other template parameters.

2/19/93  Use of template parameter as the type of a nontype parameter

The use of a template parameter as the type of a nontype parameter was
allowed, but there was no support for using a template parameter as part
of a type in a nontype parameter declaration.  For instance,

  template <class T, T i> struct A {};     // Allowed
  template <class T, T* i> struct A {};    // Previously unsupported

The second example caused an internal error.

Now template type parameters may be used in arbitrarily complex
declarations of template nontype parameters.

2/19/93  Reachability of code following "while" and "for" loops

The reachability of code following "while" and "for" loops was
determined wrong when the loop is unreachable but contains a label:

  int     main(void)
  {
    int     i;
    goto label;
    for (i = 0; i < 10; i++) {
  label:
      foo();
    }  /* for */
    /* This is reachable; return should be generated. */
  }  /* main */

2/19/93  Use of typedef name to specify an empty parameter list

As an extension in both C and C++ modes (accompanied by a warning in
strict ANSI mode) we now allow a typedef name bound to void type to
specify an empty parameter list, in place of the keyword "void".  For
instance, this program is accepted:

  typedef void T;
  T f(T) { }        // Declares "void f()"; warning in strict ANSI mode
  int main()
  {
    f();            // Error no longer issued for "too few arguments"
  }

2/19/93  Bug in scanning type qualifier lists

A bug has been fixed to correctly parse a type qualifier list that is
followed by what appears to be type specifier.  For instance, the following
is now processed correctly:

  typedef int * const I;
  typedef int * const I;        // Spurious error no longer issued on "I"

2/19/93  Virtual function overridden in a class template

Virtual functions overridden in a class template where the return type
involved a template argument were not handled properly during prototype
instantiation.  Spurious errors have been eliminated on programs of this
sort:

  class A {
    virtual int f();
  };
  template <class T> class B {
    virtual T g();
  };
  template <class T> class C : public A, public B<T> {
    T f();                     // No error during prototype instantiation
    int g();                   // No error during prototype instantiation
  };

Errors will still be reported during real instantiations of C (except
C<int>).

2/18/93  Change in representing "error locators" and "error symbols"

An error locator and an error symbol can now point to a symbol header
that specifies the name of an associated identifier.  This permits a
diagnostic message to display the name actually specified in the user's
code instead of "<error>" or "<error>::X".

02/18/93  Error recovery for self-referential template references

Cases such as these caused internal errors because a real instantiation
was being attempted before the prototype instantiation had been
completed.  This has been corrected.

  template <class T> struct A {
    A<int> a;
    void f();
  };
  template <class T> struct B : public B<int> {};

02/17/93  Error recovery when scanning a template class reference

Certain error cases caused an incorrectly formed symbol locator to
be created which later caused an internal error.  This has been
corrected.

  template <class T, int i> class A {
  public:
    void f();
  };
  template <class T, int i> void A<class T, int (i>::f(){}

02/15/93  Using a specific definition as an incomplete type

Use of a specific definition of a class template inside its definition
in a context in which a complete type is required caused an internal
error.  This has been corrected.

  template <class T> struct A {};
  struct A<int> {
    A<int> i;
  };

-------------------------------------------------------------------------------
Version 2.14, February 12, 1993

2/18/93  Bug in argument widening done in IL lowering

The argument widening done when MAKE_ALL_FUNCTIONS_UNPROTOTYPED is true
did not work for file-scope function calls, as in

  int f(float);
  int i = f(1.5f);

The argument was not widened.  It is now.  (This patch was incorporated into
the release retroactively.)

2/15/93  Error recovery on ambiguous conversions

Error recovery when a function or built-in operator is selected in overload
resolution and an argument thereof requires a conversion that is ambiguous
has been fixed.  It was broken by the recent change to remember the
conversion required in that case.  (This patch was incorporated into
the release retroactively.)

2/12/93  IL version number changed to 2.06

2/11/93  Reworking of representation of conversions in expression routines

The routines in exprutil.c that deal with conversions have been reworked
so that information on user-defined conversions is represented by
an entry of type a_user_conv_descr.  This change allows the preservation
of the conversion information deduced during overload resolution so
that it can be used when converting the arguments of the chosen
function.  Formerly, that information was thrown away and then deduced
again, which made the process slower.

2/11/93  Local types as arguments to template functions

Local types are disallowed as template-based arguments to noninline
template functions.  While there is no such explicit prohibition in
the ARM, it seems only logical that there be no way for an
out-of-line function to have access to a local type.

2/10/93  Friend function with inline definition in template class

Support for inline definition of friend functions declared in a class
template is now provided; likewise default arguments are allowed.
However, since a friend declaration is not an implicit template
declaration, errors will appear during class instantiations if the
function type signature is invariant.  For example:

  template <class T, T N> class A {
    static int i;
    friend void f(int j = 0) { i = j; }
    static T t;
    friend void g(T tt = N) { t = tt; }
  };
  A<char, 1> c1;
  A<int, 3> a3;        // Error on redefinition of f, but g is okay --
                       //   overload set includes g(int) and g(char)

2/10/93  Conversion functions in template classes

Support for conversion functions in template classes has been added:

  template <class T> struct S {
    operator T();       // Spurious error has been eliminated
  };

2/10/93 Default arguments in function templates

Default arguments are now supported in function templates including
default arguments for parameters whose types involve template
parameters.  One of the consequences of this change is that
param_type entries may now have the has_default_arg field set to
TRUE while the default_arg_expr field is NULL.  Consequently,
the has_default_arg field should always be used to check for the
presence of a default argument.

2/9/93  Instantiation of inline member function of template class

A member function of a template class defined within the class
definition is now instantiated at the point of first reference rather
than when the template class is instantiated.  This delays errors (and
may eliminate certain spurious errors) in cases like this:

  template <class T> struct S {
    void f() { T t; t = 1; }
  };
  class A { };
  int main()
  {
    S<A> s;              // No error on instantiation of S<A>
    s.f()                // Error on instantiation of S<A>::f
  }

2/8/93  Static member may not be an anonymous union

An anonymous union within a class definition is prohibited from being
a static member.

2/8/93  Added pragma scope kind

A new scope kind sck_pragma has been added for front-end use only; no IL
scope entries will be created with this kind.  This scope is used while
pragmas are being scanned to allow symbols in template declaration
scopes to be hidden.

2/5/93  * pointer-to-void is not an lvalue

The result of indirecting through a pointer to void is now represented
immediately as an rvalue.

  void *pv;
  *pv;

*pv is legal but is not an lvalue.

2/5/93  Added a_template_instance

This data structure has been added for template processing, unifying and
replacing a_function_instantiation_entry, a_static_data_member_def, and
a_template_definition.

Briefly, template-instances fit in to the symbol table in the following
way.  Each symbol representing a template function (i.e., an instance of
a function template) or a member function or static data member member
of a template class contains a pointer to one of these template-instance
entries.  An instance entry for a template function contains a pointer
to the function template symbol on which it is based.  The instance
entry for a member function or static data member of a template class
contains a pointer to the corresponding member function or static data
member symbol of the prototype instantiation of the class template.

Instance entries appear on lists belonging to the templates they are
based on.  They also appear on the instantiation_required list, which
is scanned when the end of the source program is reached to put out
all required function bodies and static data member definitions.

2/5/93  Accessing a private base class destructor (cfront compatibility)

The destructor of a derived class may implicitly call the private
destructor of a base class.  This is typically an error, but in cfront
mode this is reduced to a warning.  For example:

  class A {
    ~A();
  };
  class B : public A {
    ~B();
  };
  B::~B(){}    // Usually an error

2/5/93  Change in default instantiation mode

It is expected that most applications will use the pragma mechanism
for instantiation of noninline functions.  Consequently, the default
value for the instantiation mode option has been changed from "local"
to "none".  This means that no out-of-line functions will be instantiated
unless a pragma requesting an instantiation is present.

2/5/93  Instantiation pragmas

Instantiation of template functions and static data members can now be
more easily controlled through two new pragmas.  The pragmas are

  #pragma instantiate xxx
  #pragma do_not_instantiate xxx

The "instantiate" pragma is used to force the instantiation of a function
or static data member.  The "do_not_instantiate" suppresses an
instantiation and is useful when an instantiation should not be
generated because a specific definition of the function or static
data member will be supplied in another compilation unit.

2/5/93  Conversion functions to reference types used in more cases

Conversion functions to reference types are now considered as possibilities
in getting to the underlying type, e.g., a conversion function to
"const int &" will be considered when trying to create an "int" (the
qualifiers get dropped when the lvalue returned from the conversion
function is converted to an rvalue).

2/4/93  list_position fields in IL definition

The two list_position fields in the IL definition (for template types
and constants), formerly declared of type "int", are now "unsigned long".
These fields are not significant outside of the front end.

2/4/93  Instantiation of functions whose pointer-to-member address is taken

Taking the pointer-to-member address of a member function now causes
it to be instantiated if necessary.

2/2/93  Incomplete types from function prototypes not on types list

In C mode an incomplete type that is declared in a function prototype
that is not immediately followed by a function definition was not
being added to the types list of the function prototype scope.
It is unlikely that this would actually create any problems, but has
been corrected to keep the IL representation as consistent as possible.

1/29/93 Explicit signedness flag for bit fields

The IL a_field entry now has a field bit_field_is_signed that indicates
the signedness of the bit field.  It's necessary for enum bit fields,
where the signedness of the enum may not match what's required for the
bit field.  For integral non-enum bit fields, the field type (as always)
has the same signedness as the bit field.

1/29/93 Fixed bug in checking for qualified name with template reference

A bug has been fixed that could cause a name that is both a class name
and a nonclass name to incorrectly use the class name version when the
name is followed by a "<".

  struct t;
  extern long t;
  void f()
  {
    t < 0;
  }


1/29/93 Fixed bug in disambiguation algorithm

A bug has been fixed in the code that determines whether to interpret
a declaration as the declaration of an object with a parenthesized
initializer or as a function declaration.  The problem appeared in
rather obscure cases involving typedefs and pointer or reference
types.  We now handle this case correctly:

  typedef int T[1];
  T a;
  T &b(a);

Before b was taken to be a function taking an integer argument and
returning a ref-T; now it is interpreted a variable of type ref-T with
an initializer.  (See ARM 8.1.1, 6.8.)

1/29/93 Conversion of pointers to more-qualified version

The conversion of a pointer type to another pointer type that has more
type qualifiers on levels other than the first, e.g., "int **" -->
"const int**", which was already allowed in certain cases as an
extension, has been broadened to allow addition of type qualifiers
on array element types, e.g., "int (*)[5]" --> "const int (*)[5]".
In cfront compatibility mode, a warning is no longer issued for
these cases.

1/28/93 IL representation of enum types changed

The IL representation of enum types has been changed; see the enum_info
union in a_constant.  The new representation allows compatibility checking
to distinguish distinct empty enumerations from one another in C++.

1/28/93 Pointer to member addresses and protected members

The interaction of protected members and pointer to member addresses is
not well specified.  We have implemented what we believe will ultimately
be adopted by X3J16/WG21 based on discussions of this subject that have
taken place to date.  The pointer-to-member address of a protected member
may only be obtained using a qualified name containing the name of the
derived class, not using the name of the base class.  For example:

  class B { protected: int i; };
  class D : public B { void mf()};
  void D::mf() {
    int B::* pmi1 = &B::i;        // error - protected member
    int D::* pmi2 = &D::i;        // OK
  }

Using "&A::i" is illegal since it would allow "i" to be updated by saying
"a.*pmi1".  "pmi2" cannot be used with an object of type "A" without
the use of an unsafe cast.  This access check is disabled in cfront mode.

1/28/93 Protected member access checking for implicitly called functions

Implicit calls to protected constructors and destructors should only be
permitted for objects of a derived class with protected access (ARM 11.5).
The access control check was not being done in some cases.  These cases
now give the appropriate errors.

  class A {
  protected:
    A(){}
  };
  class B : public A {
    B(){
      A a;  // Error now being diagnosed
    }
  };

1/27/93 Instantiation of new/delete routines

When new/delete routines are folded into a constructor/destructor,
the new/delete routine is now instantiated.

1/27/93 Non-default new routine in class

When a class has a class-specific new routine but no class-specific
default (one-argument) new routine, the constructor wrapper code
generated by IL lowering now generates no code to call a default
new routine.  Formerly, it called the global new routine.

1/27/93 Overload distinguishability of function templates

The overload distinguishability test for function templates has been
relaxed.  Formerly, things like

  template <class T> void f(T);
  template <class T> void f(T *);

were rejected as too similar on the grounds that for some types they could
both match.

1/26/93 Reduced severity of access errors for types in cfront mode

Cfront does not check the accessibility of types.  For compatibility,
in cfront mode access errors for types have been reduced in severity
from errors to warnings.

1/25/93 Member function typedef extended to use within a class declaration

The member function typedef feature that has been provided in cfront
compatibility mode has been extended to work for typedefs within
class declarations (see 1/13/93 "Member function typedef" for more
information about this feature).

Cfront treats these typedefs differently.  The first is treated as
a special "member function typedef" while the second is treated as
a normal static member function typedef.  We now duplicate cfront's
behavior for this case.  The behavior in normal (noncfront) mode is
not affected.

  struct A {
    typedef void A::T(int);  // nonstandard typedef
    typedef void T2(int);    // standard typedef
  };

1/25/93 Fixed bug with elaborated type name inside a template declaration

In the following example the declaration of "i1" was incorrectly
introducing a new type named "A" instead of using the current
instantiation of the template.

  template <class T> struct A {
    int i1[sizeof (struct A*)];  // These two statements
    int i2[sizeof (struct A<T>*)];  // should be equivalent
  };

1/25/93 Declaration of tags first seen in a template declaration

A bug has been fixed that caused an error to be produced for this code:

  template <struct X* xptr> struct A {};
  struct X {};
  X  x;
  A<&x> *a;

"X" was being considered local to the scope of the template declaration
and is now considered to be declared at file scope.

1/22/93 Aggregate initializer scanning clean-up

The code in decl_inits.c that scans {...} initializers has been reworked
slightly.

-------------------------------------------------------------------------------
Version 2.13, January 22, 1993

1/22/93 Empty initializer lists supported

An empty initializer list ("{}") can be used in C++ for aggregate
initialization.  A warning or error is issued in strict ANSI mode.  Note
that this change partially supersedes the previous change described
in the entry for 1/15/93.

1/21/93 "called" flag in routine entries

There is now a "called" flag in routine entries.  This is useful to
the front end in detecting cases where a routine is declared, called,
and then defined as inline.  The existing "referenced" flag would not
do because it is also set when the address of the function is taken.

1/21/93 New IL version number

The new IL version number is 2.05.

1/20/93 Improved error messages for template functions

The parameter list of template functions is now displayed in
error messages.  Previously, only the function name was displayed.

1/19/93 Explicit destructor calls for types without destructors

The front-end now support explicit destructor calls of the form:

  p->A::~A();
  p->int::~int();

for classes that have no destructors and for nonclass types.  We
refer to this type of destructor call as a "vacuous destructor call".
A new expression operator "eok_vacuous_destructor_call" has been
added to represent this construct in the IL.

1/19/93 Fixed bug in use of qualified type name inside a class declaration

This case was incorrectly complaining that the qualified name "A::B" is
not allowed. 

  struct A {
    struct B {};
    A::B ab;
  };


1/19/93 Warning on base class with no default constructor

When a default constructor needs to be generated for a class, its base
classes (those that require constructor initialization) must also have a
default constructor.  A warning is now issued on the class declaration
when this condition is not satisfied, to supplement the error that is
issued when the default constructor is actually generated.

1/18/93 Fixed bug in assigning access to anonymous union members

The names specified in an anonymous union that appears within a class
definition are now marked with the access specifier appropriate to their
position within the containing class.

1/18/93 Fixed bug with type qualifiers on function template arguments

The following is now handled correctly:

  template<class T> void f(const T *p) {}
  int main()
  {
    const volatile int i = 0;
    volatile int j;
    f(&i);                    // okay
    f(&j);                    // error
  }

1/18/93 Checking for function templates that are too similar

There is now an error check for function templates that are too similar
or that differ only in return type, e.g.,

  template <class T> void f(T){}
  template <class T> int f(T){}

1/18/93 Fixed pointer-to-member-function bug

A bug has been fixed in representing the type of the implicit "this"
parameter on the routine type entry in certain unusual cases where a type
tree has more than one pointer-to-member type -- e.g., we now get the
type right for pmf in the following:

  void (A::* (B::* pmf))();

1/15/93 Initialization of "empty" class objects

A special case is made for the initialization of objects defined with the
type of a class that has no nonstatic data members and no constructor.

  (1) When an empty class object is declared "const" but not "extern", no
      explicit initializer is required, despite the wording in ARM 7.1.6;
      rather, since there is no syntax for explicitly initializing such an
      object, an implicit initialization is deemed to occur.  For example:

        const struct A { } a;    // const variable "a" is implicitly
                                 //   initialized

  (2) The attempt to initialize an empty class object with an initializer
      list produces an error even when the list contains no initializers,
      e.g.,

        struct A { } a = { };    // initializer list is not allowed

1/15/93 Classes used in template arguments have external linkage

An inference from ARM 3.2 and 14.2 is that a class used as a template
argument has external linkages.  Code to support that requirement has
been added.

1/15/93 Error on use of a local type as a template argument

An inference from ARM 14.2 is that a class or enum type defined within
the scope of a function (a "local type") cannot be used as a template
argument.  Such cases are now detected and an error is issued.

1/15/93 Error on out-of-range float constants

store_double in float_pt.c has been enhanced so that it generates
an error when a conversion from a double to a float fails.  This change
is just to improve the front end's performance in demos; as always,
the floating-point routines are just demo versions, and not suitable for
use in production compilers.  This particular change is even less
production-worthy than the rest of the code.  For one thing, it's very
slow.

1/14/93 Reference conversions on operands of "?" operator

Reference conversions are now done on the second and third operands of
a "?" operator if necessary to bring them to a common type.

1/14/93 Improved code for pointer-to-member calls

The code generated by IL lowering for pointer-to-member calls has been
improved for the case where the class involves has no virtual functions.

1/13/93 Member function typedef (cfront compatibility)

Cfront supports the following declarations:

  struct A { void f(int); };
  typedef void A::T(int);    // nonstandard typedef declaration
  T *pmf = &A::f;            // nonstandard ptr-to-member declaration

where "T" is construed to name a routine type for a nonstatic member
function of A that takes an int argument and returns void.  Its use is
restricted to a nonstandard pointer-to-member declaration.  The last two
declarations are thus equivalent to a single standard pointer-to-member
declaration:

  void (A::* pmf)(int) = &A::f;

Support for this construct has been added in cfront compatibility mode.  A
warning is always issued on the typedef declaration.  An error is issued on
an attempt to use the "member function typedef" name in a function
declaration.

1/13/93 Loosening of matching on function template overload resolution

Two cases:

  (1)  Extra type qualifiers under a reference are allowed.

         template <class T> void f(const T &p) {}
         void m() {int i; f(i);}

  (2)  Parameters that do not involve template types are allowed to
       have trivial conversions and/or a cast to a base class.

         struct A {};
         struct B : public A {} *p;
         template<class T> void f(T, A*);
         void m() {f(1, p);}

Both of these are forbidden by the ARM, and both are allowed by cfront
3.0.1.  The second is required to make overloading of the iostream
library work for template types.

1/12/93 Error message for redeclaration of a tag with the wrong tag kind

We now issue a more explicit error for code such as:

  struct A;
  union A;

Previously, we simply complained about an invalid redeclaration of the
name "A".

1/12/93 Qualified names allowed in elaborated types

In November, 1992 X3J16/WG21 voted to allow qualified names in
elaborated types.  We now support this feature.  For example:

  struct A {
    struct B {};
  };
  struct A::B  b;


1/12/93 C-generating back end output of bit fields

The C-generating back end now outputs all signed bit fields as "int"
and all unsigned bit fields as "unsigned int", instead of outputting
the base type used in the declaration.  This is particularly important
for enum bit fields.

1/12/93 Bug in nested class name mangling

Another bug in nested class name mangling has been fixed.  This one was
visible with three or more levels of nesting:

  struct A {struct B {struct C {static int i;};};} a;

1/12/93 IL for new and delete changed

The IL representation for new and delete has been changed.  enk_new_init
has been removed.  An expression node of kind enk_new_delete, with a
supplement of type a_new_delete_supplement, is now used to represent
all new and delete operations.  This change makes the IL more truthful
when the allocation or deallocation is folded into a constructor or
destructor.  It makes the representation cleaner in general.

1/10/93 Name mangling in base class names (for template cases)

The names of the fields generated by IL lowering for base classes and
pointers thereto are now mangled names if necessary.  This is necessary
for some convoluted cases involving templates.

1/9/93 Bug in error detection/recovery for p->::x

An error is now issued for the above case.  Formerly, the front end
aborted.

1/7/93 Error when a tag name is later declared as a class template

We now issue an error for cases such as:

  struct A;
  template <class T> struct A {};

1/7/93 Bug in IL lowering generation of constructor wrappers

A problem in generating the code to initialize the pointers to
virtual base classes has been corrected.  This caused Suite++
test 124p35 to rely on uninitialized memory, and sometimes fail.

1/7/93 Unused part of float constants zeroed

When float constants are stored into IL constant entries, the part
of the floating-point representation array not filled by the float
value is now zeroed each time it is stored.  This can avoid the problem
of failing to recognize that two float constants are the same because
of uninitialized background information.

1/7/93 Bug in IL lowering of pointer to member operations

A sequencing problem in IL lowering related to lowering of pointer to
member types has been corrected.  The bug caused an internal error
from pm_class_type.

1/7/93 Union/nonunion mismatch in referring to template class

We now issue an error for cases like this, where "union" is mixed with
"struct" or "class":

  template <class T> union U { /* ... */ };
  class U<int> { /* ... */ };

1/6/93 A function template may not have the name "main"

A function template named "main" is not explicitly prohibited in the
ARM, but disallowing it is consistent with the restrictions in section
3.4.

1/6/93 Bug in resolution of pointer to overloaded function

A bug that caused an internal error on the following has been fixed:

  template <class T> void f(T){}
  void *p = f;

1/6/93 Error on type definition within function return type

We have long dealt with the obvious case in which a class or enum
definition appears within the return type of a function type declaration,
which is an error in C++ (ARM 8.2.5):

  struct S { int i; } *func ();

We now issue an error in some related but more obscure cases as well:

  struct S { int i; } (*func_ptr) ();
  struct S { int i; } (*func_ptr_type) ();

1/6/93 Static data members that are anonymous unions

Static data members that are anonymous unions are disallowed.  They are
not prohibited by the ARM, but neither is there an obvious way to
implement them at is consistent with the requirement that static data
members be defined outside the class declaration.

1/6/93 Improved access checking of declarators

The routines that scan and coalesce generalized identifiers have
been improved to fix some remaining spurious access errors that
were being generated.  The changes include the elimination of
the class qualifier structure and the addition of the information
that had been in the class qualifier to the symbol locator.

1/6/93 IL lowering bug

In lower_expr in IL lowering, a piece of code checked the
assignment_returns_lvalue flag in an expression node and then did
a transformation to an rvalue assignment.  In some cases (in particular,
a cast of a pointer-to-member-function to another pointer-to-member-function
type), the expression node at that point was no longer an operation
node, so that flag was in effect undefined.  An internal error
was sometimes issued.

1/5/93 Wording changes on some diagnostic messages

Several messages were modified slightly in the interests of consistent
wording -- e.g., "XXX not allowed" was changed to "XXX is not
allowed".

1/5/93 Uninitialized const and ref members of class object

We now do a better job of detecting cases where an aggregate class
object, initialized by a brace-enclosed list of initializers that
runs out before the final member is seen, is left with uninitialized
const-qualified or reference members.  For instance:

  struct A { int i; int j; const int k; };
  A a = { 0, 0 };            // k is not initialized

A warning is now issued on the declaration of "a" -- this was missed
before.  Note that warnings but no errors are issued for this example;
we believe this program is valid based on what is explicitly specified
in the ARM.

1/4/93 Elaborated type specifier involving template parameter name

An elaborated type specifier involving a template parameter name is
interpreted as though the template arg where directly present in the
source construct.  (In other words, the relationship between template
param and template arg is understood in terms of a macro-substitution
model rather than a typedef model.)  For example, in the following:

  struct A { /* ... */ };
  struct B { /* ... */ };
  template <class T> class C {
    friend class T;
    class T m;
  };
  C<A> x;
  C<B> y;
  C<int> z;

when C<A> is instantiated, struct A is becomes a friend of C<A>, and
C<A>.m is of type A; similarly, struct B is a friend of C<B>, and C<B>.m
is of type B.  However, an error is issued on the instantiation of C<int>,
since "class int" is not legal.

An alternative interpretation would have been to inject a class T at file
scope; that single class would have been friend to C<A>, C<B>, and C<int>,
and the types of C<A>.m, C<B>.m, and C<int>.m would all be the same.

The language definition currently offers no guidance for deciding between
the alternatives.  Cfront issues an error for using a template parameter
name in an elaborated type specifier.

12/22/92 Bug in && and || operator processing

The processing of operands of && and || has been fixed to deal with
the case where the first operand is an array:

  static char xxx[] = "xxx";
  void f() {if (xxx && *xxx) {}}

Formerly, this got an internal error.

12/21/92 READ_SOURCE_IN_BINARY_MODE_FOR_MSDOS

A new configuration switch READ_SOURCE_IN_BINARY_MODE_FOR_MSDOS has been
added to host_envir.c.  When it is set (under MS-DOS), source files
are read as binary files, and carriage return and control-Z are
handled by the front end instead of the host C runtime library.

12/18/92 Template definition of a static data member of a template class

Template support has been enhanced to support template definitions of
static data members of template classes.  For example:

  template <class T> class X { static int i; };
  template <class T> int X<T>::i = 0;

The effect is a compiler-generated definition of an actual static data
member corresponding to X<T>::i whenever X<T> is instantiated.  As with
function templates, a specific definition is also permitted and takes
precedence over a template-based definition.  Defining static members of
template classes, though not discussed in the ARM, is described in the
X3J16/WG21 working paper (section 14.6 para 2).

12/18/92 Change in hashing for shared constants

The hashing algorithm used to search the shared constants table has been
changed so that it does not depend on any addresses.  While using addresses
as part of the hash works well from a hashing point of view, it has
the undesirable property that it makes the order of the shared
constants in the IL highly dependent on the host machine, which means
the same version of the front end compiled on two different hosts
will generate different IL and perhaps different object code on those
two machines.

12/17/92 Names of unnamed classes generated by IL Lowering

The names generated in IL lowering for unnamed classes (e.g., _C12345)
are now generated from a seed number.  Previously, they were generated
from the address of the class, which meant that the result of compilation
could vary from host to host.

12/17/92 Default signedness of enum bit fields

The configuration flag TARG_ENUM_BIT_FIELDS_ARE_ALWAYS_UNSIGNED has been
added to target.h.  When it is FALSE, enum signedness is determined
as it has been heretofore; when it is TRUE (the new default setting),
all enum bit fields are made unsigned (even if the enum contains negative
values).  This behavior is required by several ABI standards.

12/16/92 Testing pointers to members in "if" statements etc.

Pointers to members can now be used as boolean controlling expressions
in "if", "while", "do-while", and "for" statements, and as the first
operand of a "?" operator.  Conversion functions that will convert
an operand in such a position to a pointer to member will also be
found.  This is in accordance with the latest working paper from
X3J16/WG21.

12/16/92 Instantiation must be done to determine class relationships

In the following, the class S<int> need not be instantiated simply because
there is a pointer to it.  However, in order to determine the legality
of "q = p", and in order to determine the offset to be used in generating
code for that statement, one must instantiate S<int> to find out that
it has A as a base class.

  class A {};
  template <class T> class S : public A { };
  S<int> *p;
  A *q;
  main () {
    q = p;
    return 0;
  }

12/15/92 C-generating back end processing of wide character strings

The C-generating back end has been changed so that whenever the
address of a wide character string is required the string is
placed in a static temporary variable and the variable is used in
place of the string.  This ensures that the alignment of the
string is correct.

12/15/92  Tab separator in cross-reference output

The fields in each line of cross-reference output are now separated
by tabs rather than blanks.  This solves the problem caused by
C++ names that contain embedded blanks, e.g., "operator new".

12/15/92  Implicit type specifier on function

In C++ mode the diagnostic issued on functions with an implicit return
type is now a remark instead of a warning.  This matches the behavior in
C mode.

12/14/92  Dependencies in scanning member function default arg expressions

In delayed_scan_fixup_for_class all default argument expression are now
scanned first, and only then are the inline function bodies scanned.
This assures that calls within the inline functions bodies are handled
no matter what the order of declaration.  For example:

  class A {
    int f() { return g(); }        // Error no longer issued on calling g
                                   //   with no arguments
    int g(int i = 1) { return i; }
  };

Note that the ARM does not address this sort of order dependency;
however, the new behavior is consistent with that of cfront for this
program.  On the other hand, dependencies within default argument
expressions remain problematic.  For example, this still produces an
error:

  class A {
    static int f(int i = g()) { return i; }
    static int g(int i = 1) { return i; }
  };

12/14/92  Integral promotions on enum types

When they undergo integral promotions, C++ enum types now lose their
enum identity, i.e., they end up being a normal integral type (typically,
"int") rather than that type tagged as being an "enum".  This was
always a problem, but is more visible now that the default enum layout
has been changed to "int" rather than smaller integral sizes.

12/11/92  Better handling of errors in old-style parameter declarations

Several changes were made to improve error reporting in old-style param
declarations:

(1)  void f(x)
       struct S { int i; };  // Error now issued in C++ mode, and warning
                             //    no longer issued in pcc mode.
       struct S x;
     { /* ... */ }

(2)  void f()
       int i;                // In C mode: now reported as an invalid
     { /* ... */ }           //    param decl rather than a syntax error

12/11/92 Bug in overflow checking in constant folding

The overflow checking in subtract_mixed_signed_integer_values in
const_ints.c has been corrected.  Formerly, it gave an overflow on
a case like

   char *p = (char *)5 - 1;

This routine is only used for pointer subtraction, so this bug only
came up in unusual cases like the above.

12/9/92  Inexact match on nontype template arguments

In non-strict mode, in a reference to a class template, the argument
corresponding to a non-type parameter is now allowed to require a
promotion or standard conversion.  The ARM requires an exact match.

  template<float F> class S {};
  S<2.0> x;  // Now okay: double-->float

This is an extension.

12/9/92  Type of startup/termination routine (cfront compatibility)

The return type of the startup/termination routines generated by
IL lowering is now "char" for cfront compatibility (cfront uses "char"
instead of "void" to avoid problems with old C compilers).  The types
of the pointers in the __link structure have been updated accordingly.

12/9/92  Overloading involving old-style function declarations

To produce behavior that is compatible with cfront in distinguishing
redeclarations from overloading when old-style functions are involved,
old-style parameter declarations are now scanned before the function name
is looked up in the symbol table, and the type compatibility check has
been modified slightly.

The effect of these changes is that in C++ old-style functions are subject
to overloading very nearly as though they were declared with function
prototypes.  This behavior is not conditional upon cfront compatibility
mode but is rather treated as part of the support for the anachronism of
old-style function declarations.

Note however that, to be consistent with cfront, the default argument
promotion required by C for old-style params is not applied in C++ to do
the type compatibility check (though it is still done in the call).  As a
result the following is legal overloading of f:

  int f(x) int x; { return x; }
  int f(x) char x; { return x; }  // f is overloaded

But another consequence is that the following legal C code, in which f is
simply redeclared, is interpreted in C++ as requiring overloading:

  int f(int);
  int f(x) char x { return x; }   // f is redeclared in C, overloaded in C++

12/8/92  Special handling of "no return value" diagnostic from main

Failure to return a value from main, when main is declared as a non-void
function, is no longer considered a strict ANSI violation in C++ mode.  A
warning is still issued.

12/8/92  Access checking on declarators

Access errors for qualified names used in declarators are no longer
issued.  This is necessary to allow out of line definitions of member
functions of private classes.  Access checking is still done in all cases;
however, the decision whether to issue an access error is now delayed
until we know how the qualified name is being used.

12/8/92  Relaxation of pointer-to-function type checking

The comparison and assignment in the following are now allowed, with a
warning (this turns out to be needed for the OSF source):

  int (*fn1)();
  void (*fn2)();
  main() {
    if (fn1 == fn2) fn2 = fn1;
  }

12/7/92  Error on odd pointer "-" case

An error is now issued for the following case.  It's odd in that in C
the types pointed to are compatible even though the second one is
an incomplete type.

  int (*p)[3];
  int (*q)[];
  main () {p - q; return 0;}

12/4/92  Strict ANSI C mode errors on pointer coercions

In strict ANSI C mode (-A), nonstandard cases where a null pointer
constant, a "void *" pointer, or a pointer to function is considered
compatible with another pointer, or where a pointer to a complete
type is considered compatible with a pointer to an incomplete type,
now issue warnings instead of warnings.

12/4/92  Strict ANSI mode error on "useless declaration"

The diagnostic issued on declarations which define nothing and have no
declarator is now given error severity in strict ANSI mode (-A); it
remains a warning otherwise.

12/4/92  Use of a parameter name as an identifier in a function

In cfront mode and in pcc mode an identifier used as function
parameter may be redeclared within the function.  A warning is
issued.  For example:

  void f(int x)
  {
    char x;
  }

In cfront mode, "int x" may be used before the declaration of "char x".

12/4/92  Referencing template class member type in function template

Template support has been enhanced to permit references to member types
of template classes in the declaration of function templates -- for
example:

  template <class T> class A {
    class B {
      class C { /* ... */ };
    };
    enum E { /* ... * };
  };
  template <class T> void f(A<T>::B &b) { /* ... */ }
  template <class T> void f(A<T>::B::C &c) { /* ... */ }
  template <class T> void f(A<T>::E e) { /* ... */ }

12/4/92  Strict ANSI C mode error on cast between function and data pointers

In strict ANSI C mode (-A), an error instead of a warning is now issued
for explicit conversions between pointers to functions and pointers
to data.

12/4/92  In strict ANSI mode, errors on integer overflows

In strict ANSI C or C++ mode (-A), integer overflows in folding operations
now yield errors rather than warnings regardless of the setting of the
TARG_NO_ERROR_ON_INTEGER_OVERFLOW configuration flag.

12/3/92  Speed optimization in constant sharing

The hash used in looking for shareable constants has been improved to
avoid long lists in certain unlikely cases.

12/3/92  Speed optimization in IL lowering

The scanning of orphaned entries in IL lowering has been improved to avoid
very slow processing when the types lists are very large.

-------------------------------------------------------------------------------
Version 2.12, December 1, 1992

12/1/92  Redeclaration of typedef in derived class bug fixed

When the same name is defined in a typedef in a derived class and
a base class, a spurious error was being issued.  To fix this a 
new lookup routine called curr_scope_id_lookup has been added.

12/1/92  Structured statement stack reallocation bug fixed

A bug was fixed in the reallocation of the structured statement
stack.  This could occur if there were more than 30 levels of
nested structured statements.

12/1/92  Instantiation command line options

Command line options have been added to control the instantiation
of template functions and member functions of template classes.
The -t option specifies a template instantiation mode.

12/1/92  Change of default in enum layout

The default for the configuration flag
DEFAULT_ENUM_TYPES_CAN_BE_SMALLER_THAN_INT has been changed to FALSE,
which forces allocation of enums as ints.  This change was made to
avoid surprising new customers (some people find small enums surprising);
admittedly, the change may surprise some existing customers.  It was also
necessary for cfront compatibility -- cfront puts out enums as ints.

12/1/92  Type set in ck_dynamic_init constant entries in IL

ck_dynamic_init constant entries had a NULL type pointer, which was
contrary to the documentation.  They now have a type.

11/30/92 Abort in pcc mode fixed

In pcc mode, an enum bit-field whose type promotes to unsigned int
used as the second or third operand of a "?" operator would
cause an internal error in keep_enum_in_result_type:

  enum X {A, B, C=127};
  struct Y {enum X x: 8; enum X y: 7;};
  int f(int i, struct Y *p, struct Y *q) {return i ? p->x : q->y;}

That is now fixed.

11/27/92 Type qualifier on new-type-name

In cfront compatibility mode the following is now accepted:

  int *pi = new const int;

(ARM 5.3.3 para 3 explicitly prohibits const and volatile in the type
specifiers of a new-type-name construct, but cfront accepts it.)

11/27/92 Limit on recursive instantiation of template classes

The front end limits apparent "runaway" recursion in the instantiation
of templates classes -- for instance:

  template <int I> struct S {
    S<I+1> x;
  };
  S<0> s;

where the instantiation of S<0> forces the instantiation of S<1> which
forces the instantiation of S<2>, and so on.  Now, after the number of
recursive instantiations of a given class template exceeds a configurable
value (MAX_PENDING_INSTANTIATIONS), an error is issued and the recursion
is halted.

11/25/92 Fixed bug in cfront-compatible class layout

An obscure case involving virtual base classes was being handled
incorrectly when cfront-compatible class layouts were being generated;
it sometimes resulted in an internal error.  The fix involved a change
to fixup_embedded_virtual_base_classes.

11/25/92 Fixed error recovery problem with operators

In the declarations of overloaded operators the parameters and, where
appropriate, return type are now checked before the symbol for the
operator is entered into the symbol table.  This keeps operator
functions with invalid type signatures out of the symbol table and
improves lookup, overload resolution, and error recovery in certain
cases.

11/25/92 Additional context information added to error output

Additional context information is supplied for errors encountered
during the instantiation of template classes, template functions, and
member functions of template classes.  Additional information is also
supplied for errors encountered while generating functions implicitly
created by the compiler (i.e., compiler-generated constructors,
destructors, and assignment operators).

11/25/92 IL lowering changes all functions to unprototyped (as as option)

For full cfront compatibility, IL lowering now changes all functions
to unprototyped (when CFRONT_OBJECT_CODE_COMPATIBILITY is TRUE).  This
produces the same result that cfront does when cfront generates old-style
functions in its C output.  Arguments in function calls are widened
where necessary.

11/24/92 Remark issued for unreferenced variable with constructor

Formerly, variables with dynamic initialization side-effects (e.g.,
with constructors or destructors) did not cause a diagnostic to be
issued if a variable was declared but never referenced.  A remark
is now issued.

11/21/92 Abort in overload resolution fixed

Formerly, when an overload resolution case was undecidable because
of an error, when converting to a class type, the front end would
sometimes abort.  For example:

  class Base {
  public:
    Base ( Base& );
    Base ( int );
  };
  void bar () {Base b2 = (Base)100000000000000000000000;}

This is now fixed.

11/20/92 Template definitions of member functions of class templates

Support has beed added for out-of-line definitions of member functions
of class templates; both template definitions and specific definitions
are allowed.  For example:

  template <class T> class A {
    void f(T&);
  };
  template <class T> void A<T>::f(T& t) { /* ... */ }
  void A<int>::f(int& t) { /* ... */ }

11/20/92 Subscript checking made more discriminating

Subscript checking is now done only when the object underlying a
pointer is clearly discernible.  That is, even if the array type is
known, no subscript-out-of-range warnings are generated unless the
underlying object is known.

11/18/92 Improved error detection on conversion operators

An error was not being detected in the following case:

  class A {
    int operator int();          // Error detected
    int* operator int*();        // Error not detected
  };

This has been fixed by making decl_specifiers return a tk_unknown
type when it recognizes a constructor, destructor, or conversion
operator, and adding code in declarator to deal with the cases better.

11/18/92 Folding of 64-bit integers

const_ints.c has been fleshed out with a full set of routines for
doing integer constant folding when the target integers can be larger
than the host integers (e.g., 64-bit long long on a 32-bit host).
The routines also handle the usual case where a host integer can be
used to hold all target integers.  folding.c has been extensively
modified to use these routines.

11/16/92 Fixed bug in name lookup in ctor-initializer

When looking up the member or base class name in a constructor
initializer constructor parameters were incorrectly given visibility.
A new lookup option (IDL_SKIP_CURR_FUNCTION_SCOPE) has been added to
normal_id_lookup and a new lookup mode (ilm_ctor_initializer_name)
has been added to coalesce_and_lookup_generalized_identifier.  These
lookup flags support a new type of lookup that ignores symbols
from the innermost function scope.  ctor_initializer has been changed
to use the new lookup mode.

11/16/92 Fixed bug with typedef'd base class name in ctor-initializer

A bug has been fixed in handling base class references in ctor-initializer
lists.  A spurious error used to be issued when the name identifying the
base class was a typedef name, e.g.:

  typedef class A { public: A(int); } X;
  class B : public X { B(int i) : X(i) { } };

11/16/92 Destructor always called to do deallocation

Formerly, if ASSIGNMENT_TO_THIS was false, a "delete" for a class was
done by calling the destructor and then calling the delete routine.
Now, the destructor is always called, and it always does the deallocation,
because that's the only way to get the right delete routine called and
to get the size parameter right on the two-operand delete case.

11/16/92 Enumerations commented out in C-generating back end output

An #if 0/#endif pair is now put out around enumerations put out by
the C-generating back end.  The declarations are not actually needed,
since the enum type and the enumerator constants are replaced by the
underlying type and values where used.  This change is needed to
avoid conflicts on enumerator constants in template classes.

11/14/92 "Prototype instantiation" of class templates

At the point of definition, a class template is scanned (1) to detect
those syntactic and semantic errors that are not dependent on specific
template arguments and (2) to record member names, as required for
out-of-line template definitions of member functions and static data
members.  The result of this scan is referred to as a "prototype
instantiation" and is distinguished from "real instantiations", i.e.,
instantiations based on real template arguments.

11/14/92 Subscript checking on negative subscripts

Warnings are now issued in nonconstant contexts for negative subscripts
where it's clear what the underlying array type is.

11/13/92 Remark on invalid tokens during macro expansion

The warning on invalid tokens encountered during macro expansion has
been reduced to a remark.

11/13/92 Goto to label of enclosing function

In a case like the following, the label in the outer function is
now not seen from the inner function.  Formerly, it was seen and used,
which caused an abort later.

  void f() {
    label1:;
    class A {
      void g() { goto label1; }
    };
  }

11/13/92 int_kind_is_signed

The function int_kind_is_signed, formerly in const_ints.c, has been
changed to an array defined and initialized in il_def.h.

11/10/92 Function template declared "inline"

The inline keyword is now accepted on a function template declaration.

11/10/92 Diagnostics on nonstandard friend class declarations

The diagnostics issued for nonstandard friend class declarations have been
refined.  Whether an error, a warning, or a remark is put out depends on
whether the compiler is invoked in normal mode, cfront compatibility mode,
or strict ANSI mode; and also on whether it is a declaration that
introduces a new class name or mentions a previously declared name.

11/10/92 C_ANACHRONISMS_ALLOWED

The C anachronisms of appendix A, section 17 of K&R I, i.e.,

  (1)  Reversed-form compound assignment operators:
         i =- 1;
  (2)  Omitted "=" in initialization:
         int i 1;

have been put under control of the flag C_ANACHRONISMS_ALLOWED in
lang_feat.h.  The option is *off* by default, which means the
default language dialect is changed.  We did this because these features
are no longer supported in the Sun bundled cc.

11/10/92 Pointers to incomplete arrays allowed in pointer operations

When the configuration flag PTR_TO_INCOMP_ARRAY_ARITHMETIC_ALLOWED is
TRUE (and it is FALSE by default), pointers to incomplete arrays are
allowed in pointer addition, subtraction, and subscripting.  If the
flag is turned on, the back end must be able to deal with the
resultant operations on pointers to zero-length types.

11/10/92 C-generating back end temporaries in proper scope

The C-generating back end now generates temporaries in the scope in
which they are needed.  This fixes an obscure bug with the following code:

  main () {
    int i;
    switch (1) {
      struct {int i;} s1, s2;
      case 1:
        i = (i ? s1 : s2).i;
    }
    { struct {int i;} s1, s2;
        i = (i ? s1 : s2).i;
    }
    return 0;
  }

The cases above need temporaries for the rvalue field selections, but
the types for the temporaries are only available in the inner blocks. 

11/10/92 Improved wording of global qualifier name error

The message issued when a global qualifier is used where it one is not
allowed has been changed to "global-scope qualifier (leading "::") is
not allowed".

11/10/92 C-generating back end processing of odd switch statements

A bug in the C-generating back end having to do with generating C code
for very odd switch statements has been fixed.

11/10/92 Folding of pointer difference

The folding of pointer difference of constant addresses has been
corrected so that it deals correctly with negative results.

11/10/92 Token-wise handling of pcc compound assignment operator variants

The variant forms of compound assignment operators allowed in pcc mode

  i + = 1;  /* Embedded space */
  i =- 1;   /* Reversed */

are now handled at the token level in expression processing instead of
at the lexical level.  This solves a problem with the following:

  main() {
    int i=-1;
  }

which got a warning followed by an error.

11/9/92 Cleaner allocation of IL entry number and orphan pointer

When the alternate file format is used for the IL, each IL entry in
memory is preceded by space for an IL entry number.  The allocation
of that number now preserves the alignment specified by
HOST_ALIGNMENT_REQUIRED.  Ditto for the allocation of the next-orphan
pointer that precedes file-scope IL entries.

11/9/92 Fixed bug in handling nonstandard friend declarations

Nonstandard friend declarations of previously declared unions were not
handled in the same manner as classes and structs.  The following
(supported as an extension for compatibility with cfront) is now handled
properly:

  union U { /* ... */ };
  class X { friend U; /* ... */ };

11/9/92 pcc mode comment fix

A fix was made in skip_white_space in lexical.c to avoid an internal
error when in pcc mode the beginning of a multi-line comment appeared
at the end of a line containing a macro expansion.

11/9/92 Subscript reference through volatile pointer causes side effect

A change was made to recognize the side effect in the following:

  void foo2(volatile int * p) { *(p+1);}

Formerly, a warning was issued because the expression appeared to be
pointless.

11/9/92 Error recovery on incompatible operands

A change was made to avoid an internal error on

  int foo(int);
  int gg(float);
  main () {
    if (foo > gg) {}
    return 0;
  }

-------------------------------------------------------------------------------
Version 2.11, October 29, 1992

10/29/92 long long support

When the configuration flag LONG_LONG_ALLOWED is TRUE, the front end
supports the "long long" and "unsigned long long" data types, and
constants of those types (suffixes "ll" and "ull").

At the moment, the integer constant handling has not been upgraded
to handle constants larger than the host long, so this feature
has certain limitations.

10/28/92 Handling of type qualifiers on reference initialization

The handling of type qualifiers on reference initializers was tweaked
yet again to deal with a case like

  volatile int i;
  const float &r = i;

The fact that "i" has excess qualifiers is moot, since it has the wrong
type and must be converted to float anyway.  Formerly, an error was
issued.

10/27/92 Minor c_gen_be.c changes for constants

c_gen_be has been changed so that (a) it always casts unsigned constants
to an unsigned type and (b) it masks unprintable characters in strings
so that they are printed correctly even if they appear negative.

10/27/92 New identifier scanning routines

The routines that scan class qualifiers and identifiers have been
reworked to provide a more flexible interface.  The token kinds
tok_class_qualifier and tok_ptr_to_member have been added to allow
these constructs to be represented as pseudo-tokens.  A new data
structure "a_class_qualifier" has been added to describe a
class qualifier or pointer to member token.  Several routines have been
eliminated and replaced with new versions.  The following routines
have been replaced:

        Old Routine                     New Routine
  ------------------------------   -----------------------------------------
  get_class_qualifier              is_generalized_identifier_start
  get_qualified_name               coalesce_generalized_identifier
  get_normal_id_or_qualified_name  coalesce_and_lookup_generalized_identifier

10/27/92 Template support

Substantial changes have been made over the past six weeks to introduce
support for templates.  Much of the new code is in templates.c and
templates.h.  Changes to the symbol table and the IL have also been made
(new symbol kinds sk_class_template and sk_function_template; new type
kind tk_template_parameter; new structs a_template_symbol_supplement,
a_function_instantiation_entry, a_template_arg; etc.).  Additional
changes related to template support will be tracked in this log.

10/27/92 Fixed bug in processing function declarators in C-mode

A bug was fixed in declarator for cases in which a function returns a
pointer-to-function type; some other conditions were required for the
problem to show up, including compiling in C-mode.  The following no
longer provokes an internal error:

  void (*f(int i))(int i, int j) { return 0; }

10/22/92 const_ints.c and const_ints.h added

Two new files have been added.  They will contain routines that manipulate
the internal representation of integer constants.  This is in preparation
for the changes to support 64-bit integers on a 32-bit host.  Places
that used to refer directly to the integer_value field of a_constant
now call some routine in const_ints.c.

10/21/92 Fixed bug in IL lowering code for multi-dimensional array new

The code generated by IL lowering for a multi-dimensional array new
had an incorrect number of elements in the call of __vec_new.

10/21/92 Bringing pointer-to-member operands of "?" to a common type

The code that brings such operands to a common type has been added.

10/21/92 Fixed bug in detection of "dangling type specifiers"

A bug has been fixed in the code that tries recognize missing semicolon
errors in cases like this (where we refer to the second "A" as a "dangling
type specifier"):

  class A { /* ... */ }
  A x;

The bug caused spurious errors to be issued in certain cases, e.g.:

  typedef int T;
  struct S {
    enum { a,b,c } T;    // Spurious error no longer issued
    enum { d,e,f } S;    // Spurious error no longer issued
  };

10/21/92 Error on static data member definition with no type specifier    

We used to issue a warning when the decl specifiers were omitted in a
static data member definition; it is now treated as an error.

10/20/92 Internal error in function_definition

An error recovery bug has been fixed in function_definition -- it appeared
with the definition of a function whose type is given by a typedef, e.g.,

  typedef int FF(int);
  FF f;                         // Okay
  FF g { return 0; }            // Error

The error was diagnosed properly, but an internal error occurred further
down the line.  In addition, we discovered that the analogous error was
not being diagnosed for member functions with inline definitions, e.g.,

  typedef int FF(int);
  class A {
    FF f;                       // Okay
    FF g { return 0; }          // Error
  };

This bug has also been fixed.

10/19/92 TARG_NULL_IS_ALL_BITS_ZERO

The configuration flag TARG_NULL_IS_ALL_BITS_ZERO has been added to target.h.
When it is set, the front end assumes that an integer zero of the right
size (e.g., NULL) passed to an unprototyped parameter of pointer type
is not a problem, and no warning is issued.

10/19/92 Code reachability tracking reworked

The tracking of code reachability in statements.c has been reworked to
deal with the following:

  int foo(int which)
  {
    switch(which) {
    default:
        return(0);
    }
    /* NOTREACHED */ /* TEMPORARY until cases get added */
    return(1);
  }

Formerly, this gave a warning on the return(1) in spite of the
NOTREACHED comment.

10/17/92 Warning on conditional test of constant address

When the expression tested in an if, while, or the like is a constant
address, a warning is now issued.  Formerly, this was a remark, which
is appropriate when the expression is a constant integer.  However,
a constant address case is much more suspect.

10/17/92 cfront 2.1 compatible nested class name mangling 

When running in cfront compatibility mode, the names of nested classes 
are now mangled the same way that cfront 2.1 does it.  That is, in
some cases the nested form ("Q2_1A1B") is not used.  See the flag
CFRONT_2_1_OBJECT_CODE_COMPATIBILITY.

10/17/92 Fix of bug in folding of "%" operator

The folding of smallest-integer % -1 on a two's complement machine
used to result in a warning.  It now returns simply the correct
result, which is well-defined and equal to zero.

10/16/92  Fixed bug in name mangling

Sometimes when nested classes were used, the mangled names were wrong
(they had the nesting information repeated).

10/15/92  Bug on constructor with ellipsis-only parameter list

A bug in the following was fixed:

  struct A {A(...){}};
  int main() {A a(1);}

Formerly, this caused an internal error.

10/14/92  Overload resolution for function templates

Overload resolution is now done for function templates when they appear
in function calls and in contexts requiring a pointer to a function.

10/13/92  Fixed bug in overload_distinguishable

There was a bug in overload_distinguishable that caused the loop to end
prematurely when checking a new routine's type against the types in a list
of overloaded functions.  The only effect of the bug was a failure to
diagnose certain rather obscure errors.  It is now fixed.

10/8/92  Support for cfront "transitional model" nested types

The cfront 2.1 "transitional model" for nested types, in which a nested type
is promoted to file scope unless a type of the same name already exists at
file scope, has been added.  This affects name mangling and also restricts
the way in which that name can be used later on in a program.

To support this the field "use_cfront_transitional_nested_type_name_mangling"
has been added to the IL type structure.  Two new configuration switches
have been added to specify the version of cfront with which the generated
object code should be compatible: CFRONT_2_1_OBJECT_CODE_COMPATIBILITY and
CFRONT_3_0_OBJECT_CODE_COMPATIBILITY.  The existing switch is now set
to the logical OR of these two switches.

This feature is only enabled when CFRONT_2_1_OBJECT_CODE_COMPATIBILITY
is TRUE and cfront compatibility mode (-b) is enabled.

10/4/92  Fixed loop on error diagnosis

If a source file containing both #line directives and #include directives
contained an error, the error diagnosis routines could loop while trying
to retrieve the source line to be printed.  Fixed.

10/1/92  Fixed error recovery bug with pointer-to-member types

When there is no class named "A", a declaration like

  int A::* pmi;

used to result in an internal error.  That has been fixed by making the
type created for pmi an error type (rather than a ptr-to-member type that
points to an error type).

10/1/92  is_function_scope_tag field removed

The field is_function_scope_tag, a variant field in a_type for
tk_typeref, is no longer used and has been eliminated from the IL.

10/1/92  Name mangling for unnamed enumerations

For a case like

  typedef enum {a, b} E;

the name of the enumeration as mangled by IL lowering is now taken
from the typedef.

9/30/92  Reference initialization of pointers in cfront mode

In cfront compatibility mode, a reference to a pointer type may now
be initialized from a pointer value without use of a temporary even
when the reference pointer type has additional type qualifiers above
those present in the pointer value.  For example,

  int *p;
  const int *&r = p;  // No temporary used

9/30/92  Extension for compatibility of prototyped/old-style functions

The configuration switch PROTOTYPED_INT_ARGS_PASSED_LIKE_UNPROTOTYPED
has been added.  When it is TRUE, it is assumed that integer arguments to
prototyped functions are passed the same way as integer arguments to
unprototyped functions, i.e., they are widened to something like "int",
for example by being passed in a register.  This sounds like a target-
configuration switch, but it really controls a language issue.
When the switch is TRUE, something like

  void f(char);
  void f(c) char c; {}

is accepted in normal (non-strict) mode.  ANSI C says the two declarations
above are not compatible, because an argument to the old-style function
must be widened, whereas the argument to the prototyped function may or may
not be widened depending on the implementation.  If we can say "this
implementation always does widening," the two declarations can be
considered compatible.

9/30/92  void * interconvertible with pointers to functions

In non-strict C mode, a pointer to void may be converted to or from
a pointer to function.  A warning is issued.

9/30/92  Relaxation of interchangeable-types check

In non-strict mode, same-sized integer types are now considered
interchangeable.  Interchangeability applies to printf/scanf arguments,
old-style function arguments, and to compatibility of pointer types
(with a warning).  One typical effect of this change is to make
"int *" and "long *" compatible for assignment and for comparisons
(with a warning).

9/30/92  close_il_output_file

Change to avoid calling fclose with a NULL pointer when the IL file
has been closed prematurely because of an error.

9/29/92  referenced flag for virtual function table variables

The referenced flag for virtual function tables (created by IL
lowering) is now set more correctly.

9/28/92  IL changes to support templates

A new data structure a_template_arg has been added to the IL, and
a_class_type_supplement contains a pointer to a list of them.  This is
required by back ends to construct names for template classes.

New scope kinds sck_template_declaration and sck_template_instantiation
have been introduced for front-end use only; no IL scope entries will be
created with these kinds.  Similarly, a new type kind, tk_template_param,
has been introduced, but it is for front-end use only and will not appear
in the IL.

9/28/92  Duplicate typedef

An error (rather than a warning) is now issued for duplicate typedef
declarations in strict ANSI C mode when the typedef name remains bound
to the same type.

9/28/92  Initialization of arrays of C-style structs in C++ mode

Spurious errors were issued for code of this sort:

  struct x { char *a; int b; };
  struct x xa[] = { "a", 1, "b", 2, "c", 3 };

The bug has been fixed by checking whether the element type is an
aggregate class (ARM 8.4.1) and not looking for a constructor if it is.

However, there is an interesting side effect from this change.  Consider
the following:

  struct S { int a, b; } x { 1, 2};
  S y = x;                            // Still allowed
  S z[] = { x, y };                   // No longer allowed

S is an aggregate class, and so the initialization of y is legal (ARM
8.4.1 para 3).  But an error is now issued on the initialization of z,
since the two initial values are applied to z[0].a and z[0].b rather than
to z[0] and z[1].  The language definition is weak on initializing arrays
of class objects (see also ARM 12.6.1, which, however, only deals with
classes with constructors), but a check of several other C++ compilers
shows that our new behavior is consistent with prevailing practice.

9/28/92  Error on bad hex/octal character in strict ANSI mode

A too-large hex or octal escape in a character constant or string
literal now causes an error instead of a warning in -A mode.

9/27/92  Two-argument delete routines

The IL generated now passes the second argument (giving the size) when
a two-argument delete routine is called.

9/27/92  IL for comma expressions with lvalues as the second operand

The C++ IL generated for expressions like

  (a, b)

(where b is an lvalue) formerly looked liked

  *(a, &b)

because in C++ mode the conversion from lvalue to rvalue is done on
the whole comma expression instead of its second operand.  That case
is now optimized back to the original form.

9/27/92  Definition of virtual function tables of unreferenced classes

IL lowering has been changed so that the definitions for virtual function
tables for unreferenced non-external classes are put out.  Previously,
the definition was not created, which left the virtual function table
variable an extern variable.  If the back end chose to generate
the code for the (unreferenced) constructor or destructor, it would
make reference to the extern virtual function table and get a linkage
error.

9/26/92  Error on incomplete enum type

The error on an incomplete enum declaration in strict ANSI mode,
inadvertently dropped at some point, has been restored.

9/26/92  Size of empty enumeration

The size determination for an empty enumeration in C++ mode now
respects the setting of enum_types_can_be_smaller_than_int.

9/26/92  Composite type of int f(int) and int f(const int) again

Interpretation #13 from X3J11 indicates that the composite should
drop the type qualifiers.  The change of 7/24/92 used the union
of the type qualifiers.

-------------------------------------------------------------------------------
Version 2.10, September 22, 1992

9/22/92  read_logical_source_line processing at end of file

read_logical_source_line's processing at end of file was changed
so that the current source line modifications are not cleared until
the next line is actually read.  Formerly, if the last line in
the file was displayed for an error detected after the end of file
has been read, trigraphs in the line were shown in non-trigraph
form.

9/22/92  Trigraphs now recognized in C++ mode

Trigraphs were formerly recognized only in C mode.

9/22/92  Buffering of error output

The routine line_buffer_error_output_file, added recently, has been
removed again (it turns out some of our customers' systems do not
have setvbuf).  Instead, we changed the error output routines to
write out the source line in chunks instead of one character at a
time, thus eliminating the inefficiency that pushed us towards
this change in the first place.

9/21/92  IL walk problem with shared types

A problem with shared types that are used, thrown away, and then used
again in IL lowering, eventually causing an internal error (IL write-read
error) is now corrected.  This only happened on very small contrived
examples.

9/21/92  Restriction on conversion functions

An error is now issued on declaring a conversion function that is not a
nonstatic member function.

9/21/92  Fixed bug in handling arrays with a very large element count

This declaration, for instance, is now handled correctly:

  int a[(unsigned)-1];

In addition, recovery from array-too-large errors has been improved.

9/21/92  Error on attempt to delete a pointer to a function

9/21/92  Error on strict C++ mode void return from non-void function

Formerly, this was a warning.

9/21/92  Error on strict ANSI mode type incompatibility

Assigning a pointer to an unsigned type to a pointer to the corresponding
signed type (or vice-versa) now gives an error in -A mode.  It formerly
gave a warning.

9/20/92  C++-style comments preserved in preprocessor output in -C mode

9/15/92  Small change to overload resolution

A one-line change to determine_arg_match_level in exprutil.c to
drop type qualifiers.

-------------------------------------------------------------------------------
Version 2.09, September 15, 1992

9/15/92  IL version number changed to 2.02

The IL is different from the last release, but only in a very minor
way -- field constructor_or_destructor in a_type has been deleted.
Also: under a non-default configuration option, the field scope_depth
has been added to a_source_correspondence.

9/15/92  Recording the scope depth in IL entities

The front end can be configured to track the scope depth at which IL
entities are declared.  The field, conditionally incorporated in
a_source_correspondence, is scope_depth, and the flag that controls its
presence is RECORD_SCOPE_DEPTH_IN_IL in host_envir.h.

9/15/92  Error recovery on pcc mode macro recursion

The error recover on the following program compiler in pcc mode has been
improved:

  #define a a a
  a

Formerly this would issue errors about macro recursion until it hit the
error limit.

9/14/92  Initialization of static data member with incomplete type

Some problems in error diagnosis and error recovery have been fixed.
In the process it has become clear that there is no restriction against
arrays of incomplete types in C++ declarations, though a type must of
course be complete at the point of a defining declaration.  For instance,
the following is now handled properly:

  struct A {
    static A x[];
    A(int);
  };
  A A::x[] = { 0, 1, 2 };

9/14/92  Name mangling on extern "C" functions with C++ names

IL lowering now does partial name mangling on C++ special functions
(operator functions, etc.) that have extern "C" linkage.  Without
this mangling, the names are not valid C names.

9/14/92  Added subsequence checking in overload resolution

Overload resolution now takes into account conversion sequences that
are subsequences of others when determining the best match for each
argument.

9/13/92  Fixed bug in error recovery -- access adjustment declarations

Fixed an internal error bug produced when an access adjustment
declaration contained an invalid qualified name.  For instance, the
following is now handled correctly:

  class A { public: int x;};
  class B : private A { public: A::y; };   // y is not a member of A

9/13/92  New error on static data member definitions

If the type of a static data member is still incomplete at the point of
its defining declaration, an error is issued.

9/13/92  Fixed bug in choosing base class assignment operator

For a compiler-generated assignment operator the front-end must choose
the correct base class assignment operators to call.  There was one
obscure (and possibly controversial) case in which the selection failed
to detect an ambiguity, e.g.:

  class A {
  public:
    A();
    A& operator=(A);
    A& operator=(const A&);
  };
  class B : public A { };
  B a, b;
  int main()
  {
    a = b;             // Error in trying to create operator=(const B&)
  }

When the body for operator=(const B&) is created an error is now issued
in select_assignment_operator: both operator=(A) and operator=(const A&)
are equally appropriate.

9/13/92  Removed change on overload resolution cost

The change of 8/15/92, which made a base class cast on the "this"
parameter free when calling an operator function, has been backed
out.  As was suspected then, the change is not supported by the language
definition.

9/13/92  Diagnostic for base class with nonvirtual destructor

A diagnostic is issued on a base class that has a nonvirtual destructor.
This follows a suggestion in the commentary for ARM 12.4, pp. 277-78,
but since such code could reflect a conscious design choice, a remark is
put out instead of a warning.

9/11/92  Fixed bug with qualifiers on classes in conversions

Compiling the following no longer causes a loop:

  struct X {
    X(const X&);
    X(int);
  };
  void f(volatile X, char *, int);
  void f(const volatile X&, double, int);
  int main()
  {
    X x(4);
    f(x, "2", 2);  // loop here
  }

9/11/92  Improved virtual function table pointer setting in destructors

Destructor wrapper code generated in IL lowering now sets virtual
function table pointers of base classes that have virtual function
pointers even if the derived class does not have virtual functions.
The following case now works.  The behavior is disabled in cfront
compatibility mode.

  extern "C" printf(char *,...);
  struct A {
    virtual void f() {printf("A::f\n");};
    A() {}
    ~A() {}
  };
  struct B : public A {
     B() {}
    ~B() {f();}  // Should call A::f according to ARM 12.7
  };
  struct C : public B {
    void f() {printf("C::f\n");};
  } c;
  main () { return 0;}

9/10/92  Configuring alignment requirements for zero-width bit fields

TARG_ZERO_WIDTH_BIT_FIELD_ALIGNMENT has been added to target.h; it allows
the compiler to be configured to handle a zero-width bit field using
either a predetermined alignment (as required in cfront compatibility
mode) or the alignment of the integral type specified in the declaration.

9/9/92  Changed names of runtime routines

The following runtime routine names were changed for cfront compatibility:

  _vec_new       to __vec_new
  _vec_delete    to __vec_delete

Also changed, for consistency:

  _vec_cctor     to __vec_cctor

9/9/92  __ALIGNOF__ enhanced

__ALIGNOF__ can now take an argument that is an expression; the
expression is unevaluated, and the value of __ALIGNOF__(expression)
is the alignment value for the expression's type.

9/8/92  Error on dropping type qualifiers in initialization of reference

The incompatibility error for dropping type qualifiers on a reference
initialization, previously removed, has been reinstated with a specific
error message.  A specific error message has also been added for the
error of initializing a reference to non-const with something that
does not have the right type, when anachronisms are not allowed.

9/8/92  Fixed bug in generating body for default assignment operator

When a base class had assignment operators for both const and nonconst
objects, the compiler-generated assignment operator for a const object in
the derived class was not invoking the correct base class assignment
operator.  It's now fixed, so that this example works correctly:

  struct B {
    B& operator=(const B&);
    B& operator=(B&);
  };
  struct D : public B { };
  void f(const D* pd)
  {
    D d;
    d = *pd;      // Correct code is now generated for operator=(const D&)
  }

8/28/92  Interaction between late recognition of copy constructors and
         initialization by bitwise copy

A bug was fixed associated with this kind of code:

  struct S {
    S();
    S(const S&, int);
  };
  S::S(const S& s, int i = 0) { /* ... */ }
  S x, y = x;

The flag construction_by_bitwise_copy_allowed was not being cleared at the
definition of S::S(const S&, int) -- namely, at the point it was recognized
to be a copy constructor.  A consequence was that the initialization of y
was done without invoking a copy constructor.  The flag is now set, the
copy constructor is used, and, incidentally, an ambiguity error is now
issued, since the compiler had been obliged to generate S::S(const S&)
before the other constructor "became" a copy constructor.

8/25/92  Linkage conflicts

An error (instead of a warning) is now issued on linkage conflicts when the
-A command line option is used to specify strict ANSI mode (that is, when
strict_ansi_error_severity is es_error).

8/25/92  Improvements in error detection

Previously unrecognized errors are now issued for semantic errors in
certain linkage specification declarations.  For instance,

  extern "C" typedef int INT;    // error
  extern "C" inline void f();    // error

However, no diagnostics are issued (and the linkage specification is
ignored) when braces are used:

  extern "C" {
    typedef int INT;             // okay
    inline void f();             // okay
  }

-------------------------------------------------------------------------------
Version 2.08, August 25, 1992

8/25/92  IL version number changed to 2.01.

8/21/92  Handling of type qualifiers in reference initializations changed

Formerly, if a reference had fewer type qualifiers on its underlying
type than the value from which it is being initialized, an error was issued.
Now, that case just falls through to the attempt to use a temporary for
the initial value, which will get an error if the reference is to a
non-const type.

In cfront compatibility mode, a reference to a non-const type may be
initialized from a value that is a const-qualified version of the same
type, but only if the value is the result of selecting a member from a
const class object or a pointer to such an object.

8/19/92  Incomplete type in parameter declaration

An error is now issued when a parameter of a function definition is
declared with an incomplete type.

8/19/92  Fixed bug in overload discrimination

The following case involving overloaded static/nonstatic member functions
now works correctly:

  struct A {
    static void f(int);
    void f();
  };
  struct B {
     void g() { A::f(1); }
  };

8/19/92  Handling of -b, -O and -V options

The cfront compatibility option (-b) now implies C++ mode.  The 
option to enable/disable anachronisms (-O) and the option to suppress
definition of virtual function tables (-V) are now only allowed in C++ mode.

8/19/92  CFRONT_OBJECT_CODE_COMPATIBILITY

This flag replaces CFRONT_CLASS_LAYOUT_COMPATIBILITY.  Defined in
target.h, it controls whether the front end puts out IL for object code
in an environment where cfront compatibility is required.  When this
flag is FALSE the resulting object code may be somewhat more compact.

8/16/92 Sharing of virtual function tables/pointers

Pointers to virtual function tables are now shared between classes
and their base classes, where possible.  The virtual function tables
themselves are also shared.  This is an optimization that reduces
the size of many classes, and also is necessary for cfront compatibility.

8/15/92 Different name for initialization routine generated by c_gen_be

The file-scope initialization routine generated by c_gen_be has been
renamed __cgi__xxxx, where xxxx is the module name.  It was formerly
__xxxx_file_scope_inits, which could confuse the AT&T patch utility
when the module name began with "link": the routine looked like
a __link variable and was patched.

8/15/92 Base class cast not counted in argument match cost for operator

When matching operands of an overloaded operator to a member function,
any required cast of the "this" operand to a base class is not counted
as a standard conversion.  The reasoning is that the function being
referred to is really the one inherited into the derived class; iffy
from an ARM point of view, but sort of sensible, and needed for an NIH
case.

8/15/92 Array size of [0] allowed in new

A constant array size of zero is now allowed in a new-type.

8/11/92 Virtual function tables static when can't tell if needed

When the heuristic used to decide whether or not to define a virtual
function table cannot tell whether or not the table should be generated,
the table is now defined (as before) and made static (it was formerly
external).

8/6/92  Strict ANSI violations can be reported as warnings or errors

Strict ANSI violations are reported as errors when the -A command line
option is used and as warnings when the -a option is used.

8/6/92  Anachronisms can be enabled/disabled via a command line option

A new command line option (-O) has been added to enable or disable
acceptance of anachronisms.  The default value is supplied by a
configuration parameter.  The command line option negates the default
value.  Anachronisms produce warnings when enabled and errors when
disabled.

8/6/92  Cfront compatibility mode changes

A new command line option (-b) has been added to enable certain features
that are accepted by cfront 2.1.  The following describe the changes made
for cfront mode:

    - Casts to array type are now allowed only in cfront mode.  A warning
      is issued.
    - A friend declaration that omits the class name now causes a warning to
      be issued in normal mode.  A remark is issued in cfront mode.
    - Use of a qualified name in a member declaration now causes a warning
      to be issued in normal mode.
    - An operator()() function with default arguments now causes a warning
      to be issued in normal mode.
    - A value may be supplied on the return statement in a function with a
      void return type in cfront mode.  A warning is issued.

See also the 8/4/92 changes for "const anachronism restricted to
cfront mode", "Special handling of void * in cfront compatibility mode",
and "Reference parameters in cfront compatibility mode".

8/6/92  Member function redeclarations are disallowed once again

The extension to allow member function redeclarations has been removed.
(It was added originally on the basis of a misreading of cfront behavior.)
However, the code that effectively merges two member function declarations
has been left in to avoid a degradation in error recovery.

8/6/92  Bug with very long diagnostic messages fixed

There was a bug in add_string_to_segment in error.c that showed up when
a segment was extended to accommodate an especially long diagnostic
insert.  It is now fixed.

8/5/92  Friend declarations of new and delete

A bug has been fixed that caused a spurious error on a friend
declaration of an operator new() or operator delete() function.

8/4/92  const anachronism restricted to cfront compatibility mode

The anachronism that allows a non-const function to be called with a
const object is now accepted only in cfront compatibility mode.  As before,
a warning is issued.

8/4/92  Special handling of void * in cfront compatibility mode

In cfront compatibility mode, a qualified version of "void *", e.g.,
"const void *", is now allowed to be converted to "void *".
There is a case in the NIH libraries that depends on this.

8/4/92  Reference parameters in cfront compatibility mode

In cfront compatibility mode, when a reference parameter is initialized
from something that requires a standard conversion that's not class-related,
the cost of the conversion is now considered to be a user-defined
conversion rather than the correct standard conversion.  This duplicates
a bug in cfront 2.1 that happens to be exploited in the NIH libraries.

8/4/92  Bug with class operands to "?" fixed

The change in version 2.07 that enabled use of conversion functions
on the second and third operands of a "?" operator inadvertently
broke the case where those two operands have the same class type but
different qualifiers.  That's now fixed.

8/3/82  Copy construction by bitwise copy

The existence of a compiler generated copy constructor is no longer
sufficient to prevent copy construction by bitwise copy.  Previously, if a
class was found to have any copy constructor, the flag
construction_by_bitwise_copy_allowed in a_class_symbol_supplement was
cleared, thereby assuring that a constructor would always be called to do
copy construction.  Now, that applies only when a class has a user
declared copy constructor.

Also, a copy constructor is now used to pass a parameter or return a
value from a function only if bitwise copy construction is not allowed.

7/30/92  Change overload resolution algorithm

The overload resolution algorithm was changed to match the ARM algorithm
exactly (well, as exactly as one can match an incomplete specification).
This fixes some minor problems, notably one case that comes up in the
NIH libraries.

7/29/92  Optionally allow dollar signs in identifiers

Dollar signs are now allowed in identifiers when the -$ option is
specified on the command line.  The default value for the option is
specified in a new configuration file named lang_feat.h.  The lexical
routines in lexical.h have been modified to accept the dollar sign.
In strict ANSI mode a warning is issued the first time a dollar sign
used in an identifier.

As described above, a new configuration include file called lang_feat.h
has been provided to define parameters that define the source language
accepted.  ASSIGNMENT_TO_THIS_ALLOWED has been moved from target.h to
lang_feat.h. 


7/27/92  Accept function scope declarations of static functions

Code such as:

void f()
{
  static int y();
}

was accepted only in pcc mode.  It is now accepted in all C modes
except strict ANSI mode.

This is now a warning (in strict ANSI mode) instead of an error.

7/24/92  Handle parameter types with type qualifiers better

Fixed a bug that gave an error on the following:

  typedef char * caddr_t;
  int foo(const caddr_t );
  int foo(i) const caddr_t i; {}

Also fixed a bug that gave an error on the following:

  int f(const int); int f(int);

See the ANSI C standard, 3.5.4.3.  This case is a little strange in that
the C standard says the parameter types are compatible, but does not
give a rule for forming the composite type.  We used the union of the
type qualifiers (but it doesn't really matter).

7/22/92  Change _vec_new et al for cfront compatibility

The calls to allocate, deallocate, construct, and destruct class array
elements have been changed so that they are compatible with the
cfront runtime.  _vec_new is called to allocate and/or construct an
array, and _vec_delete is called to deallocate and/or destruct an array.
_vec_cctor remains as it was; it implements at feature that cfront 2.1
gives a "sorry, not implemented" for.

7/20/92  Dynamic initialization of local static variables

Fixed a bug where the dynamic init entry for a local static variable was
allocated in the local memory region but pointed to from the file scope
memory region.  With this change the data structure of a_dynamic_init
was modified when the kind is dik_nonconstant_aggregate -- there is
no longer a dynamic_inits_list field.

7/20/92  Handling of assignment-suppressing character "*" in scanf

The "*" assignment-suppression character in scanf strings is now
correctly handled.

7/17/92  Correct type output for member function types.

The type formatting in error.c was corrected to display "const" or
"volatile" if a member function was so declared.

7/11/92  Reread source lines for diagnostics.

Support was added to print source lines that are not in the current logical
source line as part of diagnostics.  To facilitate easy recovery of previous
source lines, an index of file positions is built as the source file is
originally read (read_logical_source_line() in lexical.c).

7/10/92  Functions return class objects like cfront

For cfront compatibility, functions that return class objects now do
so through a caller-supplied pointer only if the class has a copy
constructor.  Previously, the fact that the class had base classes or
defined member functions would also force the more complicated
calling sequence.

7/10/92  Added break_seq_number to switch clause

The IL entry a_switch_clause now has a field break_seq_number that gives the
source line sequence number for the "break" statement for the clause,
if any.  This is helpful in generating symbolic debugging information.

7/9/92   Bits flipped in implicit destructor arguments

For cfront compatibility, the bits in the implicit argument passed
to destructor calls have been flipped.  The 0x1 bit now means "free
storage," and the 0x2 bit now means "complete object."

7/9/92   Pointer-to-member operations lowered to inline code

For compatibility with cfront, pointer-to-member operations are now
lowered to inline code instead of to runtime routine calls.  The
runtime routines _pmf_cast, _pdm_cast, _pmf_eq, and _pmf_ne have
been deleted.

7/9/92   __pure_virtual_called

For compatibility with cfront, slots of virtual function tables that
refer to pure virtual functions now point to the runtime routine
__pure_virtual_called.

7/8/92   Virtual base class layout made compatible with cfront

The allocation of the storage for virtual base classes within their
derived classes, and the location and number of pointers to those
virtual base classes, has been made compatible with cfront.  Some parts
of this change result in wasted space in class layouts; those parts
have been made conditional on the flag CFRONT_CLASS_LAYOUT_COMPATIBILITY
(which is *on* by default, so turn it off if you don't want to waste
space and don't care about cfront compatibility).

Note the new IL fields data_section_base_class, pointer_base_class,
and complete_subobject in the a_base_class entry.

7/8/92   Bug in field selection in C mode corrected

In C mode, if a field selection was followed by a #if, as in

    if (p->a.b
  #if XYZ
        || f()
  #endif
              ) {

there would be an abort in scan_field_selection_operator.  Fixed.
This did not occur in C++ mode.

7/8/92   Virtual function tables made compatible with cfront

Two changes were made to the representation of virtual function tables
created by IL lowering:

  (1)  The [0] entry of the table is skipped, and a zeroed entry
       is added at the end of the table.
  (2)  The entry type in the array is now the same struct used for
       pointers to member functions, i.e., it has three fields instead
       of the two actually required.

7/8/92   __dummy field no longer generated by C-generating back end

The __dummy field formerly generated by the C-generating back end
for empty structures (so they would not be empty) is no longer generated.
Code already in place generates a padding bit-field at the end of
such structures, and that's all that is required.

7/6/92   Conversion function result is already a temporary

In some cases where a value must be converted into a temporary,
the result of calling a conversion function (already in a temporary)
was then copied to another temporary.  This was not only unnecessary
but could result in errors if the copy constructor required to do the
copy was inaccessible.  The superfluous copy is no longer done.

7/6/92   IL lowering bug with bit fields corrected.

IL lowering no longer gives an internal error when processing a class
that has both bit fields and virtual base classes.

-------------------------------------------------------------------------------
Version 2.07, July 2, 1992

7/1/92   Error is now issued on taking the address of a constructor
         or destructor.

6/30/92  Multiple message diagnostic capability added

The functionality of error.c has been expanded to generate multiple
message diagnostics.  New interfaces have the format xxx_start_error,
pos_xxx_start_error, xxx_add_diag_info and end_error().  They permit
displaying lists of objects -- e.g., to report ambiguities.

6/30/92  Type compatibility

A new macro has been added, types_are_strictly_compatible, and the
interface to f_types_are_compatible modified, to provide a mode in type
compatibility checking where an error type is compatible with no other
type, even another error type.  This was required to be sure the
following case is handled correctly:

  class A { A(A); A(int); };

An error is issued on the first constructor declaration; if type int
were compatible with error type, then the second declaration would be
treated as an attempt to redeclare existing function A::A rather than as
the declaration of a new instance of overloaded function A::A.

6/29/92  Check for conversions on first operand of "?" operator.

User-defined conversions are now checked for on the first operand of the
"?" operator.

6/26/92  Class with no constructor but const or reference members

A warning is now issued when a class is declared with nonstatic data
members of const-qualified or reference type but no user-defined
constructor.

6/26/92  Compiler-generated functions created on explicit references

Compiler-generated functions (operator= and destructor) are now created
when invoked explicitly, not just when invoked implicitly.

6/25/92  Error now issued for reference to local variable in default
         argument expression.

The following is now correctly diagnosed:

  void f()
  {
    int i;
    extern void g(int x = i);  // error
  }

6/25/92  Bug fix -- initialization of signed/unsigned char array with
         string.

A bug was introduced along with the wide-character changes of version 1.25
of the C front end.  It disallowed the following perfectly legal program:

  unsigned char x[] = "hello";

6/24/92  Name for conversion operator

The name associated with a conversion operator is now "operator T",
where "T" is a type-name (i.e., comprising type specifier(s), including
qualifiers, and optional abstract declarator).  Thus the name pointed to
from the source_corresp.name field of an sfk_conversion routine entry
will contain at least one blank and possibly other characters that
usually aren't permitted in identifiers (asterisks, ampersands,
parentheses, brackets).

6/24/92  Warning on delete of pointer to incomplete class.

A warning is now issued on a delete of a pointer to an incomplete class,
because it's not possible to know in such a case whether or not the
class has a destructor that's supposed to be called.

6/23/92  Implemented copy of array of classes using copy constructor.

  struct A { A(); A(const A&); };
  struct B { A a[2]; };
  B b;
  B bb = b;

The copy of B::a in the generated copy constructor for B must use a copy
constructor to copy each element of a.  Previously, this caused a
segmentation violation.  (cfront gives "sorry, not implemented".)

6/22/92  Fixed bug in setting storage class on multiply-declared functions.

In the following case:

  static void f();
  void f() { /* ... */ }

the function is now marked as internally linked with a storage class of 
"static".  Before, it was given external linkage and "unspecified"
storage class.

6/19/92  Support for "asm declarations".

"asm" is now treated as a keyword (both in C++ and non-ANSI C mode).  An
asm "declaration" (at file scope) and an asm "statement" (at function or
block scope) are scanned by asm_declaration, a new function.  Some new
IL support has been added: entries of type an_asm_entry are created and
placed on a list pointed to from the current scope, and the asm entry
points to the asm string; statements of kind stmk_asm now point to an
asm entry rather than directly to an asm string.

6/17/92  Recognition of new keywords -- temporary.

Warnings are issued when "catch", "template", "throw", and "try" are
encountered in a source program.  The warnings will be eliminated when
support for templates and exceptions is added; until then these strings
are treated as identifiers.

6/16/92  Fixed bug in default arg expression processing in member function
         declarations.

The function prototype scope is reactivated and its parameter symbols are
reentered before default argument expressions in class member function
declarations are scanned.  This fixes bugs such as the failure to report
the error in the following:

  class A {
    static int i;
    void f(int i, int j = i);
  };

6/15/92  Added new sk_parameter symbols to fix bug in default arg
         expression processing.

Symbols of a new kind, sk_parameter, are now created in the function
prototype scope when parameter declarations are processed; they are used
in detecting the appearance of parameter names in default argument
expressions (prohibited in ARM 8.2.6).  Consequently, the previously
undetected error in the following declaration is now reported:

  static int i;
  void f(int i, int j = i);

When a function body is present, sk_parameter symbols from the function
prototype scope are turned into sk_variable symbols in the function
scope.

6/12/92  Symbol names are not available when STANDALONE_UTILITY_PROGRAM.

Conditional compilation added to suppress symbol name expansion when
error.c is part of a utility program.

6/5/92  Added protected member access check of ARM 11.5.

Access control checking has been enhanced to do the checking mandated
by ARM 11.5.

6/5/92  Subscript checking disabled for arrays dimensioned [1].

A warning is no longer issued for out-of-range subscripts on
arrays with size 1, on the assumption that a size of 1 means there's
some trickery going on.

6/5/92  Implicit casts identified.

The flag compiler_generated in an_expression is now set to indicate
compiler-generated casts.

6/5/92  Constant address expressions not folded to address constants.

In nonconstant expressions, constant addressing expressions are now
always kept in expression form rather than in constant address form.  
That provides more information for aliasing analysis.

6/5/92  Added support for various diagnostic message fill-ins.

Support was added to allow type and symbol names to be inserted in
diagnostic messages.  Many error calls were changed and many error
messages were reworded to take advantage of this feature.

6/4/92  Destructor inheritance disallowed.

A bug was fixed in the creation of projection symbols so that now
destructors cannot be inherited (ARM 12.4).

6/4/92  Routine referenced flag for virtual functions.

The referenced flag in the routine entry for a virtual function is
now not set on a call unless the virtual-ness of the routine is
suppressed by using a qualified name.  The referenced flag is still
set in IL lowering when the virtual function table is generated.

6/4/92  Errors on implicit calls of functions with incomplete return types.

Routines in expr.c, exprutil.c, il.c, and class_decl.c were changed
to add checking for incomplete return types on implicitly-generated
function calls.

6/4/92  Set address_taken flag on virtual function table variables.

IL lowering now sets the address_taken flag on virtual function table
variables.

6/3/92  Improved error checking of constructor and destructor parameter
        declarations.

We now issue an error on a non-NULL param list for a destructor and on a
param type for a constructor that is the same, except for qualifiers, as
the type of the object to be constructed (e.g., error on X::X(X) is now
reported).

6/3/92  Added support for the nested class anachronism.

The nested class anachronism in ARM 18.3.5 has been added as part of the
name lookup algorithm in normal_id_lookup.  A search for qualifying
nested classes is resorted to only if no symbol is found by the normal
lookup procedure; this occasionally results in behavior that is different
from cfront's (e.g., cfront will prefer a nested class in an inner scope
to a name from an outer scope).  A warning is issued when a "semivisible"
nested class is used.  No attempt is made to duplicate other diagnostics
issued by cfront; only uses of the feature consistent with ARM 18.3.5
are supported.

6/1/92  Fixed bug in computing offsets for zero-length unnamed bit field.

The bug caused too much padding to be added.

6/1/92  Special handling of ":" in a class declaration when context is
        a "new" expression.

In a class declaration a colon following a tag name generally introduces
a base class list.  However, in an expression context it can also belong
to a ?: operator.  For instance,

  struct S { int a; };
  void f(int flag) {
    struct S *ps = flag ? new struct S : 0;
  }

This program is now parsed correctly.

5/29/92  Permit name of field to be same as name of class of which it is
         a member.

This change, based on ARM 9.2, deals with a murky part of the language
that has been much debated in X3J16.  For the time being we have made
the change in such a way as to provide compatibility with C but not
much more: a nonstatic data member with the same name as its class is
allowed only in a class for which no constructor is declared.  No
other member may be so named.

5/28/92  Fixed bugs in processing main() declarations.

Overloading of main() is no longer possible.  Static and inline
specifiers on main() are disallowed (except in C mode, where a static
function named "main" is permitted).  If main() is mentioned in a
friend declaration, inline definition is disallowed.

5/27/92  Extension to allow member function redeclaration.

As an extension (bypassing a restriction in ARM 9.2) we now issue only a
warning on multiple declarations of a member function within a class
definition.  We impose the following restrictions: accessibility must not
be changed; static member functions cannot be redeclared as nonstatic and
vice versa; nonvirtual member functions cannot be redeclared as virtual.
On the other hand, if either declaration specifies "inline", the routine
entry is so marked, and there is support for merging default argument
declarations (as per ARM 8.2.6).

5/26/92  Added checks for inaccessible or ambiguous operator new() and
         delete() member functions in constructor and destructor wrappers

These checks are required only when support for the assignment-to-this
anachronism is activated.  For example:

  class A {
    void* operator new(size_t);   // private operator new()
  public:
    A();                          // force compiler to generate B::B()
  };
  class B : public A { };
  B b;                            // no access to A::operator new()

5/26/92  Added some warnings

We now issue warnings on classes with
   - one or more virtual functions but nonvirtual destructor
   - operator new() but no operator delete() and vice versa
   - all private constructors and no friend declarations

-------------------------------------------------------------------------------
Version 2.06, May 22, 1992

5/21/92  Fixed bug with virtual destructors.

When IL lowering rewrites a "delete" as a destructor call, it must handle
the case where the pointer is NULL.  The test is inside the destructor.
However, when the destructor is virtual, the pointer cannot even be used
to look in the virtual function table if it is NULL, so an extra test
for non-NULL is needed around the virtual call.

5/21/92  Bug fix: operator new and delete functions may no longer be
         specified virtual.

5/21/92  Diagnosing redeclaration errors with access declarations.

The rule that allows a tag name to coexist in the same scope with another
(nontype) object of the same name has been interpreted to apply to access
declarations as well.  For example, this is now supported:

  class A { public: int s; };
  class B : private A {
    public:
      struct s { int i; };
      A::s;              // allowed, because struct and object may coexist
  };

5/21/92  Extension to allow cast to array type

A cast to an array type is treated as a cast to a pointer to the array
element type.  A warning is issued.  This matches a "feature" of cfront 2.1
which is used in the NIH libraries.

5/21/92  Fixed referenced flag/definition of virtual function tables.

The variables for virtual function tables generated by IL lowering
are now marked as referenced, and their contents are defined, only
if the associated class is referenced.

5/19/92  Fixed bug with compiler-generated virtual destructors.

The body for a compiler-generated virtual destructor is now created at the
point of declaration of the class of which it is a member.  Since virtual
destructors are not necessarily referenced directly (but rather through
the virtual function table) and since compiler-generated functions are
typically created "on demand" at the first point of reference, the bodies
of compiler-generated virtual destructors were sometimes not generated at
all; this led to linker errors.

5/19/92  Fixed some bugs and filled some holes in compiler-generated
         assignment operators.

Assignment by bitwise copy is no longer allowed for classes with ref or
const fields.  Also, an error is now issued if the compiler is called upon
to generate an assignment operator for a class with ref or const fields,
since (in accord with ARM 12.8) a user defined assignment operator is
required.  However, the function is generated anyway so the error appears
only at the first point of use.

5/19/92  Fixed handling of access adjustments in access control

have_proj_access_to_symbol in symbol_tbl.c became
have_access_across_derivation; fixed a bug in access control for members
whose access has been adjusted by an access declaration and which are then
inherited in a derived class.

5/19/92  Fixed a bug in detecting illegal initialization of classes with
         private or protected fields.

ARM 8.4.1 says that only certain class objects ("aggregates") can be
initialized with a brace-enclosed list.  We were too liberal before, but
an error is now issued for this kind of initialization:

  class A { private: int i; } a = { 1 };

The ARM refers to "private or protected members", but we have applied the
restriction only to fields (which seems in accord with the intent if not
the letter of 8.4.1).

5/19/92  Fixed bugs in interaction between multiple inheritance and abstract
         base classes.

For the following case class D is no longer marked as abstract and the
virtual function tables for the base classes of D are constructed
properly:

  struct V { virtual void f() =0; };
  struct B : public virtual V { void f() { } };
  struct C : public virtual V { };
  struct D : public B, public C { };

5/18/92  Empty macro argument now gives warning only in strict ANSI mode.

5/18/92  Fixed bugs with copy constructors and virtual base classes.

Two fixes in IL lowering: the implied arguments in copy constructor
calls for classes having virtual base classes are now in the right place
(before the source pointer); in copy constructor calls generated for
virtual base classes in front-end generated copy constructors, the
source argument now has the proper base class selection.

5/18/92  Fixed bug that caused internal error in function_definition.

The problem occurred when duplicate parameter names appeared in a function
definition -- e.g., void f(int i, int i) { /* ... */ }.

5/18/92  Return added to end of constructor/destructor for assignment-to-this.

enclose_routine_in_if in lower_il.c was changed so that it adds a return
statement to the end of a constructor or destructor when it encloses the
body of the routine in an "if" in the assignment-to-this case.

5/11/92 Fixed bug in array initialization when default constructor is
        needed for some elements.

When an array of elements requiring constructor initialization is only
partially accounted for in a brace-enclosed list, the remaining elements
must be initialized by the default constructor -- e.g.,

  class A { A(); A(int); /* ... */ } a[4] = { 0, 1 };

A::A() was not being called for a[2] and a[3]; now it is.

5/11/92  Fixed bug that caused internal error in corresponding_base_class.

The problem sometimes appeared when a virtual base class itself had
indirect base classes that declared virtual functions that were
overridden in a class derived from the virtual base class.

5/11/92  Fixed virtual function table pointer problem.

When a compiler generated virtual destructor was the only virtual
function in a class, the field to be used for the pointer to the virtual
function table was not being allocated.  That bug is now fixed.

5/11/92  Base classes list formed in depth-first left-to-right order.

A design flaw has been fixed such that the base classes list for a class  
is now put out in strict depth-first left-to-right order.  Thus a direct
base class appears following its own base classes in the list, not
ahead of them, as before.

5/11/92  Extended standard conversions for pointers-to-members.

It is now legal to convert implicitly from a "X A::*" to a "const X A::*".
That is, one can add type qualifiers to the type referenced by a pointer
to member.  That is not specifically allowed by the ARM, but there's a
Suite++ test that wants it, and the behavior is sensible by analogy with
the corresponding pointer case (ARM 4.6, 5.17, 8.4).

5/8/92   Fixed bug in virtual function table generation/use in IL lowering.

Previously, virtual function tables were not generated for
virtual base classes if the derived class had no virtual functions.
This caused virtual function calls to go to the wrong routine.

5/8/92   Changed name mangling of virtual function tables to more closely
         match cfront.

5/8/92   Fixed bug that caused internal error in node_complete_object_type.

Problem appeared when a virtual function was called for a class object
created by a function call and requiring destruction later.

5/8/92   Fixed bug that resulted in incorrectly built virtual function
         tables.

Problem appeared in derived class D when a virtual function was
overridden in base class B and the original function was a member of a
base class of a virtual base class from which B was derived.

5/7/92   Apply user-defined conversions on 2nd and 3rd operand of "?".

5/7/92   Fixed bug in IL lowering of virtual destructor calls.

Implicitly-generated calls of virtual destructors were not put
out as virtual calls.

5/7/92   Bug in overloaded "+" operator resolution with conversion functions

A case like

  a + 1

where there is a conversion function that will convert "a" to an integer
type was incorrectly diagnosed as ambiguous, because int(a) + pointer(1)
was thought to be a second possible interpretation.

5/7/92   Address of overloaded static member function is a normal pointer

It was considered to be a pointer to member, with the usual result being
an error about mismatched types.

5/7/92   Allow empty initializer for a field in a ctor-initializer list

This used to be disallowed with a complaint about "i()":

  class A { int i; A() : i() { } };

5/6/92   Improve ambiguity checking

This change fixes a bug where a static data member (or a member type or a
member constant) was considered ambiguous by virtue of belonging to two
distinct base classes -- this even though only a single object, type, or
enumeration was involved.  (See the example at bottom of p. 203 of the ARM.)

Consider for instance:
  struct A { /* ... */ };            //       A       A
  struct B : A { /* ... */ };        //        \     /
  struct C : A { /* ... */ };        //         B   C
  struct D : B, C { /* ... */ };     //          \ /
                                     //           D
a reference to a static data member of A within the context of class D
is not considered ambiguous.

The code now treats static member functions the same way, though there is
some doubt about this.  The ARM does not clearly require it, nor does it
prohibit it.

5/5/92   Added symbols for ::operator new and ::operator delete to symbol
         table as part of initialization

Before this change these symbols (and their routine entries) were
created on demand when a new or delete expression was encountered:

  int *pi = ::new int;

The bug was that this approach did not work if the first use of the
operator was an explicit call, for instance:

  int *pi = (int *)::operator new(sizeof(int));

5/5/92   Support for member arrays requiring assignment operator functions
         in generated assignment operator functions.

Formerly, the following gave an internal error:

  struct A {
    A operator=(const A&);
  };
  struct B {
   A a[5][7];  // B::operator= must call A::operator= for each element.
  };
  main ()
  {
    B b, c;
    b = c;
  }

5/4/92   Support for access declarations of overloaded functions

Prior to this change, compiling a program that contained an access
adjustment of an overloaded function resulted in an internal error (in
new_access_adjustment).  That has been fixed, along with some minor bugs
in processing access declarations.

-------------------------------------------------------------------------------
Version 2.05, April 30, 1992

First official release.
