public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/53638] New: static_assert handling behavior ignores template specializations
@ 2012-06-11 20:40 sbraeger at knights dot ucf.edu
  2012-06-11 21:14 ` [Bug c++/53638] " redi at gcc dot gnu.org
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: sbraeger at knights dot ucf.edu @ 2012-06-11 20:40 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53638

             Bug #: 53638
           Summary: static_assert handling behavior ignores template
                    specializations
    Classification: Unclassified
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: sbraeger@knights.ucf.edu


The current behavior of static_assert when inside a template definition is to
detect and attempt to evaluate the assert during the parser stage, before any
instantiations.  (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52809) 

"A static_assert declaration that does not depend on template parameters will
be
detected and reported while parsing the template, before any instantiation.
This is OK because such a template would have no valid instantiation, which
immediately renders the program ill-formed."

It is my opinion that this is not true.  It is possible that the template might
have valid specializations that occur later on in the compilation unit, making
it impossible to determine whether or not it is possible to construct an
instantiation of the template when parsing.

The relevant part of the standard says this " Refer to 14.6p8 in the spec

If no valid specialization can be generated for a template definition, and that
template is not instantiated, the template definition is ill-formed, no
diagnostic required.
"

This seems at first to imply that the current behavior is legal.  However, the
current behavior evaluates the static_assert and emits a message EVEN if valid
specializations CAN still be generated for a template definition.

Consider this code:

template<bool a>
struct s {
    static_assert(0, "uhoh");
};

template<>
struct s<false> {

};

s< false > q;  

This should compile, because s<false> is a valid specialization of s, meaning
that s<a> does not get instantiated.  However, on gcc 4.5.1 and gcc 4.7, we get

prog.cpp:3:5: error: static assertion failed: "uhoh"

Strangely, because of this behavior, we can 'fix' it by making the constant
expression dependent on a, even if we know it will always be false

template<bool a>
struct s {
    static_assert(a!=a, "uhoh" );
};

template<>
struct s<false> {

};

Compiles. 

The current behavior of GCC in this case MAY be conformant with spec, but it
seems to go against the intent of the spec even if it doesn't go against the
letter.  It also makes it difficult to use static_assert in certain
metaprogramming applications(like the example above, which could be used to
evaluate if a metafunction returned true).  Also, as bug 52809 demonstrates, it
is confusing to users.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/53638] static_assert handling behavior ignores template specializations
  2012-06-11 20:40 [Bug c++/53638] New: static_assert handling behavior ignores template specializations sbraeger at knights dot ucf.edu
@ 2012-06-11 21:14 ` redi at gcc dot gnu.org
  2012-10-05 13:37 ` paolo.carlini at oracle dot com
  2023-02-18 21:19 ` cvs-commit at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: redi at gcc dot gnu.org @ 2012-06-11 21:14 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53638

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-06-11 21:14:25 UTC ---
(In reply to comment #0)
> It is my opinion that this is not true.

It is true.

>  It is possible that the template might
> have valid specializations that occur later on in the compilation unit, making
> it impossible to determine whether or not it is possible to construct an
> instantiation of the template when parsing.

No it isn't. You can generate valid instantiations from a *different* template
definition, but the wording is in terms of template definitions, not templates.


> The relevant part of the standard says this " Refer to 14.6p8 in the spec
> 
> If no valid specialization can be generated for a template definition, and that
> template is not instantiated, the template definition is ill-formed, no
> diagnostic required.
> "

It specifically says "for a definition". The primary definition of a template
is a definition, an explicit specialization provides a different definition. 
If a valid instantiation can be generated from the second definition that
doesn't change the fact that if no valid instantiation can be generated for the
primary definition then that primary definition is ill-formed.


> This seems at first to imply that the current behavior is legal.  However, the
> current behavior evaluates the static_assert and emits a message EVEN if valid
> specializations CAN still be generated for a template definition.
> 
> Consider this code:
> 
> template<bool a>
> struct s {
>     static_assert(0, "uhoh");
> };
> 
> template<>
> struct s<false> {
> 
> };
> 
> s< false > q;  
> 
> This should compile, because s<false> is a valid specialization of s, meaning
> that s<a> does not get instantiated.

No, the primary template is a template definition but no valid specialization
can be generated from it. The explicit specialization is a second definition,
its existence doesn't change the fact the primary definition cannot ever be
used (also the explicit specialization hasn't even been seen when the primary
definition is first parsed.)

>  However, on gcc 4.5.1 and gcc 4.7, we get
> 
> prog.cpp:3:5: error: static assertion failed: "uhoh"

And also on clang++ and EDG.

> Strangely, because of this behavior, we can 'fix' it by making the constant
> expression dependent on a, even if we know it will always be false
> 
> template<bool a>
> struct s {
>     static_assert(a!=a, "uhoh" );
> };

That is a bit strange at first sight, but actually that doesn't fix anything,
that definition is still ill-formed because no valid instantiation can be
generated from it.  It would be conforming for a compiler to reject that
program, but it's not required to (it's "ill-formed, no diagnostic required.")

The solution is to not write it like that.
A more sensible definition would be:

template<bool a>
struct s {
    static_assert(!a, "uhoh");
};

Or even just 

template<bool a> struct s;

(Though the static assertion does give the option of a nicer message.)

> template<>
> struct s<false> {
> 
> };
> 
> Compiles. 
> 
> The current behavior of GCC in this case MAY be conformant with spec, but it

It definitely is. Read 14.6p8 again.  It doesn't matter if the template is
never instantiated, it's ill-formed.

> seems to go against the intent of the spec even if it doesn't go against the
> letter. 

I don't see how it goes against the intent -- the standard clearly says a
template definition from which no valid specialisation can be generated is
ill-formed.

Your primary template is such a definition. So it's ill-formed.

> It also makes it difficult to use static_assert in certain
> metaprogramming applications(like the example above, which could be used to
> evaluate if a metafunction returned true).

So make it dependent, or leave the primary template undefined.

The alternative is to change three major compilers to accommodate a highly
questionable style of metaprogramming that the standard says is ill-formed.
Don't do it.

> Also, as bug 52809 demonstrates, it
> is confusing to users.

It doesn't demonstrate that at all, it just asserts it.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/53638] static_assert handling behavior ignores template specializations
  2012-06-11 20:40 [Bug c++/53638] New: static_assert handling behavior ignores template specializations sbraeger at knights dot ucf.edu
  2012-06-11 21:14 ` [Bug c++/53638] " redi at gcc dot gnu.org
@ 2012-10-05 13:37 ` paolo.carlini at oracle dot com
  2023-02-18 21:19 ` cvs-commit at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-10-05 13:37 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53638

Paolo Carlini <paolo.carlini at oracle dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID

--- Comment #2 from Paolo Carlini <paolo.carlini at oracle dot com> 2012-10-05 13:37:04 UTC ---
Closing.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/53638] static_assert handling behavior ignores template specializations
  2012-06-11 20:40 [Bug c++/53638] New: static_assert handling behavior ignores template specializations sbraeger at knights dot ucf.edu
  2012-06-11 21:14 ` [Bug c++/53638] " redi at gcc dot gnu.org
  2012-10-05 13:37 ` paolo.carlini at oracle dot com
@ 2023-02-18 21:19 ` cvs-commit at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2023-02-18 21:19 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:9944ca17c0766623bce260684edc614def7ea761

commit r13-6133-g9944ca17c0766623bce260684edc614def7ea761
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Feb 10 16:16:45 2023 -0800

    c++: static_assert (false) in template [DR2518]

    For a long time, people have expected to be able to write
    static_assert (false) in a template and only have it diagnosed if the
    template is instantiated, but we (and other implementations) gave an error
    about the uninstantiated template because the standard says that if no
valid
    instantiation of the template is possible, the program is ill-formed, no
    diagnostic required, and we try to diagnose IFNDR things when feasible.

    At the meeting last week we were looking at CWG2518, which wanted to
specify
    that an implementation must not accept a program containing a failing
#error
    or static_assert.  We also looked at P2593, which proposed allowing
    static_assert in an uninstantiated template.  We ended up combining these
    two in order to avoid requiring implementations to reject programs with
    static_assert (false) in uninstantiated templates.

    The committee accepted this as a DR, so I'm making the change to all
    standard modes.  This behavior was also conformant previously, since no
    diagnostic was required in this case.

    We continue to diagnose non-constant or otherwise ill-formed conditions, so
    no changes to existing tests were needed.

            DR 2518
            PR c++/52809
            PR c++/53638
            PR c++/87389
            PR c++/89741
            PR c++/92099
            PR c++/104041
            PR c++/104691

    gcc/cp/ChangeLog:

            * semantics.cc (finish_static_assert): Don't diagnose in
            template context.

    gcc/testsuite/ChangeLog:

            * g++.dg/DRs/dr2518.C: New test.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-02-18 21:19 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-11 20:40 [Bug c++/53638] New: static_assert handling behavior ignores template specializations sbraeger at knights dot ucf.edu
2012-06-11 21:14 ` [Bug c++/53638] " redi at gcc dot gnu.org
2012-10-05 13:37 ` paolo.carlini at oracle dot com
2023-02-18 21:19 ` cvs-commit at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).