Bug 81525 - [7 Regression] Invalid codegen with constexpr variable template
Summary: [7 Regression] Invalid codegen with constexpr variable template
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.1.0
: P2 normal
Target Milestone: 7.3
Assignee: Jason Merrill
URL:
Keywords: rejects-valid, wrong-code
Depends on:
Blocks:
 
Reported: 2017-07-23 16:56 UTC by Louis Dionne
Modified: 2019-06-15 00:36 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-09-11 00:00:00


Attachments
Rejects-valid testcase (1.50 KB, text/plain)
2017-09-11 12:02 UTC, Jonathan Wakely
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Louis Dionne 2017-07-23 16:56:12 UTC
The following code prints

    i = 0
    N = 0

when it should print

    i = 0
    N = 1

This seems to be a regression since GCC 7, although I am not sure exactly
which minor version introduced it. The problem only triggers when 'N' is
constexpr, when it is assigned from a variable template, and when we go
through enough templates (randomly making functions not templates seems
to fix the issue). The code is (sorry, I reduced a lot but could not
reduce further):

    #include <iostream>

    template <int i>
    struct integral_constant {
      constexpr operator int() const { return i; }
    };

    template <int i>
    constexpr integral_constant<i> int_{};

    template <typename F>
    void with_index(F f) {
      f(integral_constant<0>{});
    }

    template <typename Dummy>
    void print(Dummy) {
      constexpr auto N = ::int_<1>;
      (void)N; // otherwise we get [warning: variable 'N' set but not used]
               // this may be a hint that something is wrong

      auto f = [&](auto i) {
        std::cout << "i = " << static_cast<int>(i) << std::endl;
        std::cout << "N = " << static_cast<int>(N) << std::endl;
      };

      with_index(f);
    }

    int main() {
      ::print(0);
    }


Live example with GCC 6.3.0: https://wandbox.org/permlink/lclToxN6mnRAS3ol
Live example with GCC 7.1.0: https://wandbox.org/permlink/AUqaHBYlsfwHLUrU
Live example with GCC trunk: https://wandbox.org/permlink/8wxi8MqrS03MbujE

This bug report was lifted from a failure in Boost.Hana's test suite [1],
with the relevant original code being [2]. This is quite worrisome as this
breaks mundane constexpr-utilizing code in a nasty way.

[1]: https://travis-ci.org/boostorg/hana/jobs/256518824#L7663
[2]: https://github.com/boostorg/hana/blob/e50749/example/tutorial/tag_dispatching.cpp#L72-L85
Comment 1 Jakub Jelinek 2017-07-24 08:42:48 UTC
Started with r239267.
Simplified testcase:
template <int i> struct A { constexpr operator int () const { return i; } };
template <int i> constexpr A<i> a{};
template <typename F> void foo (F f) { f (A<0>{}); }
template <typename T>
void bar (T) { constexpr auto N = a<1>; auto f = [&] (auto i) { static_assert (static_cast<int>(N) == 1, ""); }; foo (f); }
int main () { bar (0); }
Comment 2 Jason Merrill 2017-08-07 19:07:47 UTC
The bug is that GCC is replacing the auto with the implicit template argument of the generic lambda.
Comment 3 Jason Merrill 2017-08-09 19:22:21 UTC
Author: jason
Date: Wed Aug  9 19:21:49 2017
New Revision: 250999

URL: https://gcc.gnu.org/viewcvs?rev=250999&root=gcc&view=rev
Log:
	PR c++/81525 - wrong constant value with generic lambda

	* pt.c (tsubst_decl) [VAR_DECL]: Avoid clobbering auto.
	(tsubst_copy) [VAR_DECL]: Handle auto.

Added:
    trunk/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/pt.c
Comment 4 Jason Merrill 2017-08-09 20:18:27 UTC
Author: jason
Date: Wed Aug  9 20:17:55 2017
New Revision: 251001

URL: https://gcc.gnu.org/viewcvs?rev=251001&root=gcc&view=rev
Log:
	PR c++/81525 - wrong constant value with generic lambda

	* pt.c (tsubst_decl) [VAR_DECL]: Avoid clobbering auto.
	(tsubst_copy) [VAR_DECL]: Handle auto.

Added:
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C
Modified:
    branches/gcc-7-branch/gcc/cp/ChangeLog
    branches/gcc-7-branch/gcc/cp/pt.c
Comment 5 Jason Merrill 2017-08-09 20:29:16 UTC
(In reply to Jason Merrill from comment #4)
> Modified:
>     branches/gcc-7-branch/gcc/cp/ChangeLog
>     branches/gcc-7-branch/gcc/cp/pt.c

Reverted for now, as 7.2 is frozen.
Comment 6 Sven C. Dack 2017-08-24 08:13:22 UTC
A quick reminder that 7.2 has been released and that you probably want to put the patch back in.
Comment 7 Jonathan Wakely 2017-09-11 12:02:11 UTC
Created attachment 42155 [details]
Rejects-valid testcase

This rather complex testcase was auto-reduced and provided on IRC. It fails with current gcc-7-branch and compiles OK (with warnings) on trunk and gcc-6-branch.

It was fixed on trunk by r250999, so presumably would be fixed on the gcc-7-branch by re-applying r251001 now that the branch is unfrozen.
Comment 8 Aldy Hernandez 2017-09-13 16:44:56 UTC
Author: aldyh
Date: Wed Sep 13 16:44:25 2017
New Revision: 252364

URL: https://gcc.gnu.org/viewcvs?rev=252364&root=gcc&view=rev
Log:
	PR c++/81525 - wrong constant value with generic lambda

	* pt.c (tsubst_decl) [VAR_DECL]: Avoid clobbering auto.
	(tsubst_copy) [VAR_DECL]: Handle auto.

Added:
    branches/range-gen2/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C
Modified:
    branches/range-gen2/gcc/cp/ChangeLog
    branches/range-gen2/gcc/cp/pt.c
Comment 9 Jason Merrill 2017-09-18 18:37:19 UTC
Author: jason
Date: Mon Sep 18 18:36:47 2017
New Revision: 252941

URL: https://gcc.gnu.org/viewcvs?rev=252941&root=gcc&view=rev
Log:
	PR c++/81525 - wrong constant value with generic lambda

	* pt.c (tsubst_decl) [VAR_DECL]: Avoid clobbering auto.
	(tsubst_copy) [VAR_DECL]: Handle auto.

Added:
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C
Modified:
    branches/gcc-7-branch/gcc/cp/ChangeLog
    branches/gcc-7-branch/gcc/cp/pt.c
Comment 10 Jason Merrill 2017-10-04 15:37:40 UTC
Author: jason
Date: Wed Oct  4 15:37:09 2017
New Revision: 253414

URL: https://gcc.gnu.org/viewcvs?rev=253414&root=gcc&view=rev
Log:
	PR c++/81525 - broken handling of auto in generic lambda.

	* pt.c (tsubst_decl) [VAR_DECL]: Use strip_innermost_template_args.

Added:
    trunk/gcc/testsuite/g++.dg/cpp1y/lambda-generic-auto1.C
    trunk/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4a.C
      - copied, changed from r253410, trunk/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/pt.c
    trunk/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C
Comment 11 Jason Merrill 2017-10-04 15:38:55 UTC
Author: jason
Date: Wed Oct  4 15:38:24 2017
New Revision: 253415

URL: https://gcc.gnu.org/viewcvs?rev=253415&root=gcc&view=rev
Log:
	PR c++/81525 - broken handling of auto in generic lambda.

	* pt.c (tsubst_decl) [VAR_DECL]: Use strip_innermost_template_args.

Added:
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp1y/lambda-generic-auto1.C
Modified:
    branches/gcc-7-branch/gcc/cp/ChangeLog
    branches/gcc-7-branch/gcc/cp/pt.c
Comment 12 Jason Merrill 2017-10-04 17:52:33 UTC
Fixed.