[Bug c++/65579] [C++11] gcc requires definition of a static constexpr member even though it is not odr-used

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Mar 9 18:39:00 GMT 2016


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65579

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |msebor at gcc dot gnu.org
      Known to fail|                            |4.9.3, 5.3.0, 6.0

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
Re-confirmed with today's top of trunk (6.0) and all prior supported versions
that implement constexpr.  See below.

The difference between the template and non-template case is the readonly bit
that's set on the 's' field when S is an ordinary struct.  The bit is clear
when S is a template.  The bit gets set in the c_apply_type_quals_to_decl()
function in c-family/c-common.c called from  the cp_apply_type_quals_to_decl()
function defined in cp/typeck.c.  The latter function executes the following
condition just before calling c_apply_type_quals_to_decl().  COMPLETE_TYPE_P
(type) is false when S is a (specialization of a template), causing the
TYPE_QUAL_CONST to clear.

  /* Avoid setting TREE_READONLY incorrectly.  */
  /* We used to check TYPE_NEEDS_CONSTRUCTING here, but now a constexpr
     constructor can produce constant init, so rely on cp_finish_decl to
     clear TREE_READONLY if the variable has non-constant init.  */

  /* If the type has (or might have) a mutable component, that component
     might be modified.  */
  if (TYPE_HAS_MUTABLE_P (type) || !COMPLETE_TYPE_P (type))
    type_quals &= ~TYPE_QUAL_CONST;

  c_apply_type_quals_to_decl (type_quals, decl);

When S is made complete by this point (e.g., by causing S<int> to be
instantiated, say by declaring an object of the type), the bit stays set and
the test program links. 

The c_apply_type_quals_to_decl() function the does the following:

  if ((type_quals & TYPE_QUAL_CONST)
      || (type && TREE_CODE (type) == REFERENCE_TYPE))
    /* We used to check TYPE_NEEDS_CONSTRUCTING here, but now a constexpr
       constructor can produce constant init, so rely on cp_finish_decl to
       clear TREE_READONLY if the variable has non-constant init.  */
    TREE_READONLY (decl) = 1;

The comments referencing constexpr suggest that TREE_READONLY should perhaps be
set here and then cleared in cp_finish_decl.

$ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc
-B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc++ z.c
template <typename>
struct S {
    int i;
};

struct T {
    static constexpr S<int> s = { 1 };
};

int main()
{
    return T::s.i;
}
/tmp/ccqP3dAP.o: In function `main':
z.c:(.text+0x6): undefined reference to `T::s'
collect2: error: ld returned 1 exit status


More information about the Gcc-bugs mailing list