Bug 90165 - std::variant constructs wrong alternative
Summary: std::variant constructs wrong alternative
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 8.3.1
: P3 normal
Target Milestone: 8.4
Assignee: Jonathan Wakely
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2019-04-18 21:54 UTC by Jonathan Wakely
Modified: 2019-05-07 15:52 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work: 9.0
Known to fail: 8.3.0
Last reconfirmed: 2019-04-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2019-04-18 21:54:30 UTC
#include <variant>
#include <stdio.h>

struct none { none() = delete; };
struct any { template <typename T> any(T&&) {} };

int main()
{
  std::variant<none, any> v(std::in_place_type<none>);
  std::variant<none, any> v2(std::in_place_index<0>);
  printf("constructed alternatives %zu and %zu\n", v.index(), v2.index());
}

This program should be ill-formed, but instead compiles and outputs:

constructed alternatives 1 and 1
Comment 1 Jonathan Wakely 2019-04-19 00:08:49 UTC
The variant(T&&) constructor is being selected by overload resolution, because we talk to apply this constraint:

remove_­cvref_­t<T> is neither a specialization of in_­place_­type_­t nor a specialization of in_­place_­index_­t,
Comment 2 Jonathan Wakely 2019-04-23 12:41:14 UTC
(In reply to Jonathan Wakely from comment #1)
> because we talk to apply this constraint:

s/talk/fail/
Comment 3 Jonathan Wakely 2019-04-23 12:48:54 UTC
Author: redi
Date: Tue Apr 23 12:48:18 2019
New Revision: 270509

URL: https://gcc.gnu.org/viewcvs?rev=270509&root=gcc&view=rev
Log:
PR libstdc++/90165 constrain variant(T&&) constructor

Also refactor some constraints slightly to be more readable.

	PR libstdc++/90165
	* include/std/variant (variant::__not_self): New helper for the
	is_same_v<remove_cvref_t<T>, variant>==false constraints.
	(variant::__to_type_impl): Remove.
	(variant::__to_type): Add default argument to check pack size, instead
	of using __to_type_impl.
	(variant::__accepted_type): Add default argument using __not_self.
	(variant::__is_in_place_tag, variant::__not_in_place_tag): New helpers
	for variant(T&&) constructor constraint.
	(variant::variant(T&&)): Use __not_in_place_tag in constraints.
	Extract __accepted_type into a named template parameter for reuse in
	other constraints and in the exception specification.
	(variant::variant(in_place_type_t<T>, Args&&...))
	(variant::variant(in_place_type_t<T>, initializer_list<U>, Args&&...))
	(variant::variant(in_place_index_t<T>, Args&&...))
	(variant::variant(in_place_index_t<T>, initializer_list<U>, Args&&...))
	(variant::operator=T&&)): Remove redundant && from trait arguments.
	* testsuite/20_util/variant/compile.cc: Check variant(T&&) constructor
	isn't used for in_place_type or in_place_index arguments.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/std/variant
    trunk/libstdc++-v3/testsuite/20_util/variant/compile.cc
Comment 4 Jonathan Wakely 2019-04-23 12:49:59 UTC
Fixed on trunk so far.
Comment 5 Jonathan Wakely 2019-05-07 15:47:09 UTC
Author: redi
Date: Tue May  7 15:46:36 2019
New Revision: 270966

URL: https://gcc.gnu.org/viewcvs?rev=270966&root=gcc&view=rev
Log:
PR libstdc++/90165 constrain variant(T&&) constructor

Backport from mainline
2019-04-23  Jonathan Wakely  <jwakely@redhat.com>

	PR libstdc++/90165
	* include/std/variant (variant::__is_in_place_tag)
	(variant::__not_in_place_tag): New helpers for variant(T&&)
	constructor constraint.
	(variant::variant(T&&)): Use __not_in_place_tag in constraints.
	* testsuite/20_util/variant/compile.cc: Check variant(T&&) constructor
	isn't used for in_place_type or in_place_index arguments.

Modified:
    branches/gcc-8-branch/libstdc++-v3/ChangeLog
    branches/gcc-8-branch/libstdc++-v3/include/std/variant
    branches/gcc-8-branch/libstdc++-v3/testsuite/20_util/variant/compile.cc
Comment 6 Jonathan Wakely 2019-05-07 15:52:33 UTC
Fixed for 8.4 too.