Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsitency between variable decltype(auto) in variables and templates #47136

Closed
yeah-boi mannequin opened this issue Oct 11, 2020 · 6 comments
Closed

Inconsitency between variable decltype(auto) in variables and templates #47136

yeah-boi mannequin opened this issue Oct 11, 2020 · 6 comments
Labels
bugzilla Issues migrated from bugzilla c++17 clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party

Comments

@yeah-boi
Copy link
Mannequin

yeah-boi mannequin commented Oct 11, 2020

Bugzilla Link 47792
Version trunk
OS All
CC @hubert-reinterpretcast,@zygoloid

Extended Description

Consider the following program:

#include
#include <type_traits>

template<decltype(auto) N>
void f()
{
std::cout << std::is_same_v<decltype(N), int> << std::endl;
}

int main()
{
const int i = 0;

f<i>();

decltype(auto) N = i;
std::cout << std::is_same_v<decltype(N), const int> << std::endl;

}

When compiling it with -std=c++17 -pedantic-errors and the running it the following is outputed:

1
1

This means that the two decltype(auto) deductions behaved differently since they deduced different types ( N = int and N = const int ). I expect them to behave the same way.

Note that gcc gives the expected result ( N = const int for both deductions ).

Link to compiler explorer (clang to the left, gcc to the right):

https://godbolt.org/z/Y5Yc7M

@hubert-reinterpretcast
Copy link
Collaborator

It's not clear that GCC's behaviour is the intent of the committee.

Refer to N4861 subclause 13.2 [temp.param] paragraph 6 regarding top-level cv-qualifiers. The wording does not appear to remove cv-qualification from deduced types, but that is not clearly intended.

@hubert-reinterpretcast
Copy link
Collaborator

This demonstrates that Clang does not retain a separation based on the type of the non-type template parameter:
template struct Q {
static int q;
};

template int Q::q;

template <decltype(auto) N>
constexpr int &f() {
class A;
return Q::q;
}

int main() {
static int x;
const int &i = x;
int &j = x;
static_assert(&f() == &f()); // not expected to pass
}

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Oct 11, 2020

It seems to me that the behavior in comment#0 is a GCC bug. Per [temp.param]p6,

"The top-level cv-qualifiers on the template-parameter are ignored when determining its type."

and per [temp.type]p1,

"Two template-ids are the same if
[...]
their corresponding non-type template-arguments are template-argument-equivalent (see below) after conversion to the type of the template-parameter"

so f and f<0> name the same template specialization (whereas GCC treats them as distinct). Given that, the only possible consistent interpretation of the rules is that N has type (non-const) int in that template specialization.

(I don't think the wording is entirely clear on this -- especially the ordering between [temp.arg.nontype]p1 and [temp.param]p6 seems unclear -- but I also don't think we meant to introduce template parameters with cv-qualified types as part of decltype(auto) parameters.)

But according to the same rules, comment#2 does demonstrate a bug.

The comment#2 issue is fixed in the frontend in 849c605. But similar cases will still fail at runtime, due to ABI issue itanium-cxx-abi/cxx-abi#47.

@yeah-boi
Copy link
Mannequin Author

yeah-boi mannequin commented Oct 12, 2020

It seems to me that the behavior in comment#0 is a GCC bug. Per
[temp.param]p6,

"The top-level cv-qualifiers on the template-parameter are ignored when
determining its type."

and per [temp.type]p1,

"Two template-ids are the same if
[...]
their corresponding non-type template-arguments are
template-argument-equivalent (see below) after conversion to the type of the
template-parameter"

so f and f<0> name the same template specialization (whereas GCC treats
them as distinct). Given that, the only possible consistent interpretation
of the rules is that N has type (non-const) int in that template
specialization.

(I don't think the wording is entirely clear on this -- especially the
ordering between [temp.arg.nontype]p1 and [temp.param]p6 seems unclear --
but I also don't think we meant to introduce template parameters with
cv-qualified types as part of decltype(auto) parameters.)

But according to the same rules, comment#2 does demonstrate a bug.

The comment#2 issue is fixed in the frontend in
849c605. But similar cases will still fail
at runtime, due to ABI issue
itanium-cxx-abi/cxx-abi#47.

Thanks for the explanation. I have sent a bug report to gcc now (with a different example program):

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

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
@llvmbot llvmbot added the confirmed Verified by a second party label Jan 26, 2022
@mizvekov
Copy link
Contributor

Fixed by 27f9b0c

@EugeneZelenko EugeneZelenko added the clang:frontend Language frontend issues, e.g. anything involving "Sema" label Oct 28, 2022
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 28, 2022

@llvm/issue-subscribers-clang-frontend

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla c++17 clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party
Projects
None yet
Development

No branches or pull requests

4 participants