The base patch only deals with strict (canonical) type equality, which is merely a subset of all the dangerous function interfaces that we intend to find. In addition, in the base patch, canonical type equivalence is not diagnosed in a way that is immediately apparent to the user.
This patch extends the check with two features:
- Proper typedef diagnostics and explanations to the user.
- "Reference bind power" matching.
Case 1 will tell the user the common type of "SomeIntegerType" and "SomeOtherIntegerType" is "int" or "my_int" and "int" are the same. This makes the (otherwise, through CanonicalType desugaring already handled and diagnosed, but not explained) typedef case obvious to the user without having to invoke code comprehension tools.
Case 2 is a necessary addition because in every case someone encounters a function f(T t, const T& tr), any expression that might be passed to either can be passed to both. Thus, such adjacent parameter sequences should be matched. This is specifically modelled for const& only, as any other pair combination from "value, ref, qualified ref, rref" have some broad value category in which some actual swap of the arguments at a call would be a compiler error. (E.g. f(int, int&) and f(2, Val) breaks if swapped, similarly how rrefs cannot bind lvalues, etc.) This case broadens the result set, but only with the most dangerous and "Please think about this and refactor..." case.
(Note, that Case 2 does not model things like f(int, std::reference_wrapper<const int>).)
Due to the cases above always being a problem (and there isn't a good enough reason to say typedefs should not be diagnosed, everyone hates the weak typedef...), I decided not to make matching these configurable.
This patch also serves as a proof-of-concept on how I wish the check to evolve over some more subsequent patches, which all aim to introduce user-toggleable modelling.