-
Notifications
You must be signed in to change notification settings - Fork 403
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
iox-#1394 iox-#1196 Address Axivion and clang-tidy findings for cxx::function_ref
#1456
iox-#1394 iox-#1196 Address Axivion and clang-tidy findings for cxx::function_ref
#1456
Conversation
cxx::function_ref
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/function_ref.inl
Outdated
Show resolved
Hide resolved
5fcd3c6
to
bbcf4c2
Compare
Codecov Report
@@ Coverage Diff @@
## master #1456 +/- ##
==========================================
+ Coverage 78.75% 78.76% +0.01%
==========================================
Files 379 379
Lines 14477 14477
Branches 2012 2012
==========================================
+ Hits 11401 11403 +2
+ Misses 2436 2435 -1
+ Partials 640 639 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
|
cxx::function_ref
cxx::function_ref
757e67e
to
1840354
Compare
cxx::function_ref
cxx::function_ref
@@ -15,15 +15,15 @@ | |||
// | |||
// SPDX-License-Identifier: Apache-2.0 | |||
|
|||
// AXIVION DISABLE STYLE AutosarC++19_03-A16.2.3 : <type_traits> is included |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I have no idea what this is suppressing and why a <type_traits>
makes it safe again. Could you elaborate this a little bit more detailed. With other warnings it is most of the time more clear since they are directly above the line which has the "warning" and one sees the context but in this case it could be easily also a cut&paste failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is about type_traits
from STL being used but only included indirectly. I think the proper fix is to include it directly, as is customary in C++.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@elfenpiff @MatthiasKillat For <type_traits>
we have our trampoline type_traits.hpp
which adds some type traits missing in C++14. I re-phrased the justification.
public: | ||
~function_ref() noexcept = default; | ||
|
||
function_ref(const function_ref&) noexcept = default; | ||
|
||
function_ref& operator=(const function_ref&) noexcept = default; | ||
function_ref& operator=(const function_ref&) & noexcept = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you add a reference here? Was it a warning? Should we do this for all copy assignments?
So this rule forbids code like:
std::move(a) = b;
Which is valid and well defined but on the first glimpse weird. But take a look at this here
template<typename T>
void initializeSomeArgs(T&& args) {
std::forward<T>(args) = someT;
}
Here we take args
as universal reference (so sometimes also as rvalue reference) and would like to assign a new value to it.
Why should we forbid that? What kind of error can possible originate from that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@elfenpiff In the example you provided it can have outside effect, depending on the type it is instantiated with so anything can go wrong but this is no reason not to allow since this holds for any references or pointers.
While it will not be useful often (or at all) for function_ref
, I do not see it should be required to restrict the assignment operator to lvalues.
@mossmaurice Edit: I thought about this. For function_ref
there is probably no good use case to assign to rvalues so it is fine to prohibit this explicitly. Same for all other places where I mentioned it.
It should not be done for all classes without considering their purpose, but it is rarely useful I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@elfenpiff That's due to AUTOSAR rule A12-8-7
. Indeed
std::move(a) = b;
is weird and does not make sense. You can find more examples in the AUTOSAR document.
For your 2nd example, I suppose if it is needed in some cases, we should explicitly define foo& operator=(const foo&) &&
and if desired call operator=() &
from there explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If both implementations (&&
and &
) exist and are identical it does not make sense to distinguish. Only if one should not exist (as here) or if they both exist but are different.
It is fine if we only have one like here.
namespace iox | ||
{ | ||
namespace cxx | ||
{ | ||
template <class ReturnType, class... ArgTypes> | ||
template <typename CallableType, typename> | ||
// AXIVION Next Line AutosarC++19_03-A12.1.2 : Members are initialized in the same manner, NSDMI with nullptr is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In what manner are the members initialized? What does NSDMI mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.cppstories.com/2015/02/non-static-data-members-initialization/
But I think this Axivion suppression is probably not the right way, @saif-at-github may know more (should it suppress the next Construct instead?). I do see any members in the next line and am not sure what this rule is about or why there is an issue.
Ideally there is nothing to suppress here, I cannot the any problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@elfenpiff https://www.giybf.com 🙃
@MatthiasKillat Correct, I switchted it to Next Construct
.
The rule just says either init via the : m_foo(foo)
or inline via Type m_foo{defaultValue}
, but don't mix things as you might forget it in another c'tor. However, doing it explicitly in both ways, is the best IMHO.
: m_pointerToCallable(const_cast<void*>(reinterpret_cast<const void*>(std::addressof(callable)))) | ||
// AXIVION Next Line AutosarC++19_03-A15.4.4 : Lambda not 'noexcept' as callable might throw |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this argument the call operator must be noexcept
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
15-4-4 states that "A declaration of non-throwing function shall contain noexcept specification.". I have no problem with that. However, any function that might throw cannot have this specificier, which means any user-defined function cannot. Hence I do not see why Axivion should complain unless it is better analyzing whether a function can throw or not than the compiler.
And even modern compilers are in general not able to do this in general, non-trivial cases (like this one). Not sure the rule is useful to enforce with this tool for this reason. If the tool produces too many false positives/negatives it is useless for this rule (while the rule itself makes sense).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@elfenpiff I don't get this, the operator()()
is already noexcept
.
@MatthiasKillat Correct, we need to monitor that.
@@ -15,15 +15,15 @@ | |||
// | |||
// SPDX-License-Identifier: Apache-2.0 | |||
|
|||
// AXIVION DISABLE STYLE AutosarC++19_03-A16.2.3 : <type_traits> is included |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is about type_traits
from STL being used but only included indirectly. I think the proper fix is to include it directly, as is customary in C++.
#ifndef IOX_HOOFS_CXX_FUNCTION_REF_HPP | ||
#define IOX_HOOFS_CXX_FUNCTION_REF_HPP | ||
|
||
// AXIVION Next Line AutosarC++19_03-A16.2.2 : Needed for Expects and Ensures macros |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the problem here? Does it not recognize that something from this header is used? (maybe because it is a macro?) ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MatthiasKillat AFAIU Axivion does not detect that the macro from requires.hpp
is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dislike that tool failure results in these suppression comments.
-1 for the tool I guess
public: | ||
~function_ref() noexcept = default; | ||
|
||
function_ref(const function_ref&) noexcept = default; | ||
|
||
function_ref& operator=(const function_ref&) noexcept = default; | ||
function_ref& operator=(const function_ref&) & noexcept = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@elfenpiff In the example you provided it can have outside effect, depending on the type it is instantiated with so anything can go wrong but this is no reason not to allow since this holds for any references or pointers.
While it will not be useful often (or at all) for function_ref
, I do not see it should be required to restrict the assignment operator to lvalues.
@mossmaurice Edit: I thought about this. For function_ref
there is probably no good use case to assign to rvalues so it is fine to prohibit this explicitly. Same for all other places where I mentioned it.
It should not be done for all classes without considering their purpose, but it is rarely useful I think.
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/function_ref.inl
Outdated
Show resolved
Hide resolved
auto f = reinterpret_cast<ReturnType (*)(ArgTypes...)>(target); | ||
m_functionPointer([](void* target, ArgTypes... args) -> ReturnType { | ||
using PointerType = ReturnType (*)(ArgTypes...); | ||
// AXIVION Next Construct AutosarC++19_03-A5.2.4 : Type-safety ensured by casting from type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type safety is ensured by the fact we only pass functions with this type as target
, i.e. they are convertible.
This is entirely under the control of the class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mossmaurice I still find the justification lacking here, hence my comment about the reason.
Without extra knowledge of how it works, I could not infer it from the justification.
More precisely
the class design ensures a cast to the actual type of target
Signed-off-by: Simon Hoinkis <[email protected]>
Signed-off-by: Simon Hoinkis <[email protected]>
Signed-off-by: Simon Hoinkis <[email protected]>
1840354
to
c9c54dd
Compare
@elfenpiff @MatthiasKillat @elBoberido The combination of
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. I think some justifications wrt. type erasure are not quite clear and need some detail/rewording.
public: | ||
~function_ref() noexcept = default; | ||
|
||
function_ref(const function_ref&) noexcept = default; | ||
|
||
function_ref& operator=(const function_ref&) noexcept = default; | ||
function_ref& operator=(const function_ref&) & noexcept = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If both implementations (&&
and &
) exist and are identical it does not make sense to distinguish. Only if one should not exist (as here) or if they both exist but are different.
It is fine if we only have one like here.
, m_functionPointer([](void* target, ArgTypes... args) -> ReturnType { | ||
// AXIVION Next Construct AutosarC++19_03-A5.2.4, CertC++-EXP36 : Type-safety ensured by casting from type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mossmaurice I still think the justification is not accurate/understandable. type erasure should be mentioned.
iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/function_ref.inl
Outdated
Show resolved
Hide resolved
auto f = reinterpret_cast<ReturnType (*)(ArgTypes...)>(target); | ||
m_functionPointer([](void* target, ArgTypes... args) -> ReturnType { | ||
using PointerType = ReturnType (*)(ArgTypes...); | ||
// AXIVION Next Construct AutosarC++19_03-A5.2.4 : Type-safety ensured by casting from type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mossmaurice I still find the justification lacking here, hence my comment about the reason.
Without extra knowledge of how it works, I could not infer it from the justification.
More precisely
the class design ensures a cast to the actual type of target
Signed-off-by: Simon Hoinkis <[email protected]>
ffd5a26
to
16fd6c2
Compare
Signed-off-by: Simon Hoinkis [email protected]
Pre-Review Checklist for the PR Author
Changelog updated in the unreleased section including API breaking changesiox-#123-this-is-a-branch
)iox-#123 commit text
)git commit -s
)task-list-completed
)Notes for Reviewer
AUTOSAR
warnings with Axivioncxx::function_ref
Expects
not considered will be addressed as part of ErrorHandling concept with user defined actions #1032 by @MatthiasKillatTodo
M7-1-2
: Shall constness of 'target' be changed?A2-7-3
andA14-5-2
Checklist for the PR Reviewer
Post-review Checklist for the PR Author
References