Repository navigation
[BUG] UFCS disable [[nodiscard]] #305
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
In the current implementation of cppfront (aa70d09), the following code:
t2 : type = {
public x : *int;
operator=:(out this, p : *int) = {
x = p;
}
ptr1: (inout this, p : *int) -> *int = std::exchange(x, p);
}
ptr_ext: (inout o : t2, p : *int) -> *int = std::exchange(o.x, p);
main :() = {
n := 42;
a : t2 = (n&);
m := 24;
a.ptr1(m&); // no warning
ptr_ext(a, m&); // warning: ignoring return value of function declared with 'nodiscard' attribute
a;
}Generates (skipping boilerplate):
class t2 {
public: int* x;
public: explicit t2(cpp2::in<int*> p)
: x{ p }
#line 4 "../tests/bug_ufcs_disable_nodiscard.cpp2"
{
}
#line 4 "../tests/bug_ufcs_disable_nodiscard.cpp2"
public: auto operator=(cpp2::in<int*> p) -> t2& {
x = p;
return *this;
#line 6 "../tests/bug_ufcs_disable_nodiscard.cpp2"
}
public: [[nodiscard]] auto ptr1(cpp2::in<int*> p) -> int* { return std::exchange(x, p); }
};
[[nodiscard]] auto ptr_ext(t2& o, cpp2::in<int*> p) -> int* { return std::exchange(o.x, p); }
auto main() -> int{
auto n {42};
t2 a {&n};
auto m {24};
CPP2_UFCS(ptr1, a, &m);// no warning
ptr_ext(a, &m); // warning
std::move(a);
}And when compile with cpp1 compiler (clang++-14 in my case):
../tests/bug_ufcs_disable_nodiscard.cpp2:19:5: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
ptr_ext(a, &m); // warning
^~~~~~~ ~~~~~
1 warning generated.
Only one unused result is identified - CPP2_UFCS(ptr1, a, &m); generates no warning.
The issue is caused by CPP2_UFCS() macros are eventually lambdas called in-place (Immediately Invoked Function Expressions). The lambda has no [[nodiscard]] attribute - this is already proposed: P2173R0. I have checked on my compiler - I modified the macro to (notice that [[nodiscard]] is added after the capture list):
#define CPP2_UFCS(FUNCNAME,PARAM1,...) \
[&][[nodiscard]](auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
if constexpr (requires{ std::forward<decltype(obj)>(obj).FUNCNAME(std::forward<decltype(params)>(params)...); }) { \
return std::forward<decltype(obj)>(obj).FUNCNAME(std::forward<decltype(params)>(params)...); \
} else { \
return FUNCNAME(std::forward<decltype(obj)>(obj), std::forward<decltype(params)>(params)...); \
} \
}(PARAM1, __VA_ARGS__)And the result is:
../tests/bug_ufcs_disable_nodiscard.cpp2:17:5: warning: an attribute specifier sequence in this position is a C++2b extension [-Wc++2b-extensions]
CPP2_UFCS(ptr1, a, &m);// no warning
^
include/cpp2util.h:651:4: note: expanded from macro 'CPP2_UFCS'
[&][[nodiscard]](auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
^
../tests/bug_ufcs_disable_nodiscard.cpp2:17:5: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
CPP2_UFCS(ptr1, a, &m);// no warning
^~~~~~~~~~~~~~~~~~~~~~
include/cpp2util.h:657:2: note: expanded from macro 'CPP2_UFCS'
}(PARAM1, __VA_ARGS__)
~^~~~~~~~~~~~~~~~~~~~~
../tests/bug_ufcs_disable_nodiscard.cpp2:19:5: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
ptr_ext(a, &m); // warning
^~~~~~~ ~~~~~
3 warnings generated.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
JohelEGP commentedon Mar 28, 2023
And implemented because it was accepted, as shown by the result that follows it.


JohelEGP commentedon May 1, 2023
There's already macros for annotating functions in
cpp2util.h, so I think you can make a PR for this.filipsajdak commentedon May 6, 2023
I guess that it will not be accepted until MSVC does not have support for that.
JohelEGP commentedon May 6, 2023
It's OK. That's why they're macros.
hsutter commentedon May 29, 2023
For this one, I'm not sure what the right resolution is. We could make the UFCS macros unconditionally expand to include
[[nodiscard]]on compilers that support that. But then a function that has a discardable result (which Cpp2 doesn't yet support authoring) would gain a[[nodiscard]]. That may not be such a bad thing -- it could be viewed as an improvement when using most Cpp1 functions from Cpp2. Thoughts?(General note: I'm distracted with the upcoming WG21 Varna meeting and will be slow to follow up on issues/PRs until after that.)
hsutter commentedon Jun 12, 2023
On the eve of the Varna meeting, I've made enough progress on this question over the past couple of weekends that I now think I have an answer, for which I've:
Thanks everyone! I look forwarding to picking up on handling PRs in 2-3 weeks after we all recover from the WG 21 Varna meeting...
JohelEGP commentedon Jun 13, 2023
The Wiki's
Home.mdsays"Cpp2
[[nodiscard]]" rather than"Cpp1
[[nodiscard]]" like the linked article.This isn't the case for parameters.
I've been wondering how Cpp2 should support unnamed parameters and function type-ids.
The simplest design would have
_to discard a parameter's name.And maybe require parameters of function type-ids to have discarded names.
See also 3 different design suggestions that support
unnamed parameters (by literally omitting the identifier)
and function type-ids:
<const>or<in>in function template arguments #456 (comment) with special grammar to achieve that for type-ids.<const>or<in>in function template arguments #456 (comment) is like the above,but only function type parameters can be unnamed,
and
(in: type)is ambiguous.Shouldn't this link to #231 instead?
Add mandatory explicit discard, closes hsutter#305
Add mandatory explicit discard, closes hsutter#305