Skip to content

[Clang] Unexpected results from __reference_{constructs,converts}_from_temporary #114344

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

Open
frederick-vs-ja opened this issue Oct 31, 2024 · 1 comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" question A question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

Comments

@frederick-vs-ja
Copy link
Contributor

frederick-vs-ja commented Oct 31, 2024

It seems that the following static_assert's should pass, but Clang currently rejects them (link).

static_assert(!__reference_constructs_from_temporary(void(&&)(), void()), "Normal function is treated as lvalue.");
static_assert(!__reference_converts_from_temporary(void(&)(), void()), "Normal function is treated as lvalue.");
static_assert(!__reference_constructs_from_temporary(void(&)(), void()), "Normal function is treated as lvalue.");
static_assert(!__reference_converts_from_temporary(void(&&)(), void()), "Normal function is treated as lvalue.");
static_assert(__reference_constructs_from_temporary(int&&, const int), "const int is adjusted to int");
static_assert(__reference_converts_from_temporary(int&&, const int), "const int is adjusted to int");
  • Per [expr.type]/2, "const int prvalue" needs to be adjusted to "int prvalue", so there shouldn't be cv-qualification dropping and the binding to temporary object should be valid.
  • For the (normal) function case, as decltype(std::declval<Fun>()) is Fun& when Fun is a normal function type, the reference binding should be valid. But despite the binding being valid or not, there can never be a temporary and thus the traits should report false.

This probably doesn't block the library implementation of P2255R2 because workaround can be easily implemented.


Moreover, the results of these traits is a bit unclear to me for the following cases (link):

struct Abstract {
  virtual void fun() = 0;
};

static_assert(__reference_constructs_from_temporary(Abstract&&, Abstract), "The code is so abstract.");
static_assert(__reference_converts_from_temporary(Abstract&&, Abstract), "The code is so abstract.");

static_assert(__reference_constructs_from_temporary(int(&&)[], int[]), "Array-of-unknown-bound prvalue?");
static_assert(__reference_converts_from_temporary(int(&&)[], int[]), "Array-of-unknown-bound prvalue?");

It seems that the abstractness of the class should be ignored in the spirit of P0929R2 (so Clang is giving correct results for the Abstract case), but this doesn't seem clear in the current standard wording.

The case for int[] is really weird as there's no prvalue of type T[].

CC @cjdb @cor3ntin @timsong-cpp

@frederick-vs-ja frederick-vs-ja added question A question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead! clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Oct 31, 2024
@llvmbot
Copy link
Member

llvmbot commented Oct 31, 2024

@llvm/issue-subscribers-clang-frontend

Author: A. Jiang (frederick-vs-ja)

It seems that the following `static_assert`'s should pass, but Clang currently rejects them ([link](https://www.godbolt.org/z/7Wec34cnT)).
static_assert(!__reference_constructs_from_temporary(void(&amp;&amp;)(), void()), "Normal function is treated as lvalue.");
static_assert(!__reference_converts_from_temporary(void(&amp;)(), void()), "Normal function is treated as lvalue.");
static_assert(!__reference_constructs_from_temporary(void(&amp;)(), void()), "Normal function is treated as lvalue.");
static_assert(!__reference_converts_from_temporary(void(&amp;&amp;)(), void()), "Normal function is treated as lvalue.");
static_assert(__reference_constructs_from_temporary(int&amp;&amp;, const int), "const int is adjusted to int");
static_assert(__reference_converts_from_temporary(int&amp;&amp;, const int), "const int is adjusted to int");
  • Per [[expr.type]/2](https://eel.is/c++draft/expr.type#2), "const int prvalue" needs to be adjusted to "int prvalue", so there shouldn't be cv-qualification dropping and the binding to temporary object should be valid.
  • For the (normal) function case, as decltype(std::declval&lt;Fun&gt;()) is Fun&amp; when Fun is a normal function type, the reference binding should be valid. But despite the binding being valid or not, there can never be a temporary and thus the traits should report false.

This probably doesn't block the library implementation of P2255R2 because workaround can be easily implemented.


Moreover, the results of these traits is a bit unclear to me for the following cases (link):

struct Abstract {
  virtual void fun() = 0;
};

static_assert(__reference_constructs_from_temporary(Abstract&amp;&amp;, Abstract), "The code is so abstract.");
static_assert(__reference_converts_from_temporary(Abstract&amp;&amp;, Abstract), "The code is so abstract.");

static_assert(__reference_constructs_from_temporary(int(&amp;&amp;)[], int[]), "Array-of-unknown-bound prvalue?");
static_assert(__reference_converts_from_temporary(int(&amp;&amp;)[], int[]), "Array-of-unknown-bound prvalue?");

It seems that the abstractness of the class should be ignored in the spirit of P0929R2 (so Clang is giving correct results for the Abstract case), but this doesn't seem clear in the current standard wording.

The case for int[] is really weird as there's no prvalue of type T[].

CC @cjdb @cor3ntin @timsong-cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" question A question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!
Projects
None yet
Development

No branches or pull requests

2 participants