llvm / llvm-project

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

Friended struct with concept gives different output in clang/gcc/MSVC #58833

Open danakj opened 1 year ago

danakj commented 1 year ago

GCC bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107544

I don't know which compiler is right, but all three give a different output.

https://godbolt.org/z/7Pq3eWhc8

#include <compare>
#include <concepts>
#include <iostream>

template <class T>
concept HasTag = requires {
    T::Tag;
    requires std::same_as<decltype(T::Tag), const bool>;
};

template <class T>
struct check_tag final {
    static constexpr bool value()
        requires(!HasTag<T>)
    {
        return false;
    }

    static constexpr bool value()
        requires(HasTag<T>)
    {
        return T::Tag;
    };
};

struct S {
   private:
    template <class T>
    friend struct check_tag;
    static constexpr bool Tag = true;
};

int main() {
    std::cout << HasTag<S> << "\n";
    std::cout << check_tag<S>::value() << "\n";
}

Clang output (the concept sees private data if used in friend):

0
1

GCC output (the concept always sees private data):

1
1

MSVC output (the concept never sees private data):

0
0
danakj commented 1 year ago

This should be labeled for C++20

llvmbot commented 1 year ago

@llvm/issue-subscribers-c-20

danakj commented 1 year ago

The GCC bug mentions https://cplusplus.github.io/CWG/issues/2589.html however it's not clear that caching is the problem in this case. Reordering the uses of the HasTag concept does not change the output.