Consider this example:
#include <type_traits> using std::is_same; bool top() { return is_same<char, int>::value || is_same<char, long>::value; }
We can see that the value static members are different, but in fact,
they refer to the same VarDecl entity. It is because both is_same
class instances inherit from the common false_type class, which
actually owns the value member.
The alpha.core.IdenticalExpr Static Analyzer checker actually warns
for this, since it only checked if the referred Decls are the same.
Interestingly, the clang-tidy misc-redundant-expression also reports
this is for the exact same reason, so I'm fixing both of them at the same
time.
This patch fixes this by checking if the Decls are the same and if they
are it will try to acquire the nested namespace specifier as a type and
compare them as well. If they are inequal, that means that the
spelling of the nested namespace specifiers actually differed, this
it's likely to be a false-positive.
I'd like to note that the checker/check was actually right about that
the expressions were semantically equal in that given context, however,
we still don't want these reports in general.
We could introduce checker options to finetune this behavior if needed.
PS: According to the code coverage of the test, all touched parts are
completely covered.
Thanks David Rector (@davrec) for the idea on the cfe-dev forum:
https://lists.llvm.org/pipermail/cfe-dev/2021-November/069389.html
This function should probably either be made into a lambda private to areEquivalentDeclRefs(), or renamed to make clear it does not apply generically to all NNS's.
Part of the reason is that this is only implemented for type NNS's. But the more important reason is that, when either a) !Left || !Right, or b) !Left->getAsType() || !Right->getAsType(), this returns true, since (presumably*) this gives us the desired behavior within areEquivalentDeclRefs(), despite that in general a null NNS should probably not be considered the same as a nonnull NNS.
(*Is this indeed the desired behavior? Probably should add some tests that check qualified DeclRefExprs against unqualified DeclRefExprs, to be sure.)