c++templatesnamespacesusingcompiler-bug

Does a using namespace directive make names usable in inlined functions?


Consider declaring an unconstrained ns::operator*. After using namespace ns in block scope and calling a function foo<T>, clang uses ns::operator* when reading the iterators of a range-based loop inside foo. There are no other types from ns involved, so ADL should result in no candidates.

In the following example, static_assert fails with the message:

error: static assertion failed due to requirement 'std::is_same_v<const int &, const custom_type &>'

The assembly code shows that ns::operator* is used by clang. The assertion passes for gcc and msvc!

namespace ns {

template <typename T>
constexpr auto operator*(T&& /*value*/) {
    struct custom_type {};
    return custom_type{};
};

}  // namespace ns

template <typename T>
constexpr void foo() {
    std::vector<T> vec{};
    for (const auto& curr : vec) {
        static_assert(std::is_same_v<const T&, decltype(curr)>);
    }
}

int main() {
    using namespace ns;
    foo<int>();
}

Here's a godbolt link: https://godbolt.org/z/z5vf48Mda.

I'm not able to reproduce the problem by invoking operator* inside foo manually. Additionally, the assertion passes for clang when foo is not templated or not constexpr. It's as if clang inlines foo<T> and therefore treats ns::operator* as a valid candidate. I'm almost sure that clang is broken, because the problem only occures when using range-based loops.

Is either clang or gcc/msvc correct, or are we dealing with unspecified/undefined behaviour?


Solution

  • There seems to be a bug in Clang. The using namespace ns in main shouldn't have any effect on the lookup in foo and it should be impossible to find ns::operator* in foo by any form of lookup.

    Your observations suggest to me that there is a bug in how lookup is handled in range-for loops (which have some special lookup rules).

    Inlining functions is a compiler optimization under the as-if rule. It never has impact on the behavior or well-formedness of a program. It shouldn't affect lookup in any way.