llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.64k stars 11.37k forks source link

Explicit template instantiation rejected when the template is found via `using namespace` #81019

Open abbeyj opened 6 months ago

abbeyj commented 6 months ago

The following code is accepted by GCC, ICC, and MSVC but is rejected by clang with the error error: explicit instantiation of 'N::C' must occur in namespace 'N'.

namespace N {
    template <typename T>
    class C {
    };
}

using namespace N;

template class C<int>;

It is my understanding that rejecting this code used to be the correct behavior according to the standard. See https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#275 , specifically "If the name declared in the explicit instantiation is an unqualified name, the explicit instantiation shall appear in the namespace where its template is declared."

However this language was eventually removed by https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html which is going to be part of C++23.

See also #54150

https://godbolt.org/z/KMY7Me9Es

llvmbot commented 6 months ago

@llvm/issue-subscribers-clang-frontend

Author: James Abbatiello (abbeyj)

The following code is accepted by GCC, ICC, and MSVC but is rejected by clang with the error `error: explicit instantiation of 'N::C' must occur in namespace 'N'`. ```C++ namespace N { template <typename T> class C { }; } using namespace N; template class C<int>; ``` It is my understanding that rejecting this code used to be the correct behavior according to the standard. See https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#275 , specifically "If the name declared in the explicit instantiation is an unqualified name, the explicit instantiation shall appear in the namespace where its template is declared." However this language was eventually removed by https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html which is going to be part of C++23. See also #54150 https://godbolt.org/z/KMY7Me9Es
dwblaikie commented 6 months ago

I believe clang is correct here, the C++20 spec states:

"If the name declared in the explicit instantiation is an unqualified name, the explicit instantiation shall appear in the namespace where its template is declared or, if that namespace is inline (9.8.1), any namespace from its enclosing namespace set."

AaronBallman commented 6 months ago

I'm reopening this because P1787 was adopted as a defect report, so the changes are expected to apply to C++20 as well (they apply as far back as the feature support exists).

shafik commented 6 months ago

@abbeyj note that godbolt now has EDG: https://godbolt.org/z/7j6Mnfxe9

jensmaurer commented 6 months ago

... and EDG also accepts the example code according to your godbolt link, so the intro sentence should have read "is accepted by GCC, EDG, and MSVC". Does that change much?

shafik commented 6 months ago

... and EDG also accepts the example code according to your godbolt link, so the intro sentence should have read "is accepted by GCC, EDG, and MSVC". Does that change much?

No, folks often use icc as a stand in for edg, so just letting the OP know in case.