xref: /llvm-project/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp (revision 76bbbcb41bcf4a1d7a26bb11b78cf97b60ea7d4b)
1 //===--- EasilySwappableParametersCheck.cpp - clang-tidy ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "EasilySwappableParametersCheck.h"
10 #include "../utils/OptionsUtils.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/RecursiveASTVisitor.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 #include "clang/Lex/Lexer.h"
15 #include "llvm/ADT/SmallSet.h"
16 
17 #define DEBUG_TYPE "EasilySwappableParametersCheck"
18 #include "llvm/Support/Debug.h"
19 #include <optional>
20 
21 namespace optutils = clang::tidy::utils::options;
22 
23 /// The default value for the MinimumLength check option.
24 static constexpr std::size_t DefaultMinimumLength = 2;
25 
26 /// The default value for ignored parameter names.
27 static constexpr llvm::StringLiteral DefaultIgnoredParameterNames = "\"\";"
28                                                                     "iterator;"
29                                                                     "Iterator;"
30                                                                     "begin;"
31                                                                     "Begin;"
32                                                                     "end;"
33                                                                     "End;"
34                                                                     "first;"
35                                                                     "First;"
36                                                                     "last;"
37                                                                     "Last;"
38                                                                     "lhs;"
39                                                                     "LHS;"
40                                                                     "rhs;"
41                                                                     "RHS";
42 
43 /// The default value for ignored parameter type suffixes.
44 static constexpr llvm::StringLiteral DefaultIgnoredParameterTypeSuffixes =
45     "bool;"
46     "Bool;"
47     "_Bool;"
48     "it;"
49     "It;"
50     "iterator;"
51     "Iterator;"
52     "inputit;"
53     "InputIt;"
54     "forwardit;"
55     "ForwardIt;"
56     "bidirit;"
57     "BidirIt;"
58     "constiterator;"
59     "const_iterator;"
60     "Const_Iterator;"
61     "Constiterator;"
62     "ConstIterator;"
63     "RandomIt;"
64     "randomit;"
65     "random_iterator;"
66     "ReverseIt;"
67     "reverse_iterator;"
68     "reverse_const_iterator;"
69     "ConstReverseIterator;"
70     "Const_Reverse_Iterator;"
71     "const_reverse_iterator;"
72     "Constreverseiterator;"
73     "constreverseiterator";
74 
75 /// The default value for the QualifiersMix check option.
76 static constexpr bool DefaultQualifiersMix = false;
77 
78 /// The default value for the ModelImplicitConversions check option.
79 static constexpr bool DefaultModelImplicitConversions = true;
80 
81 /// The default value for suppressing diagnostics about parameters that are
82 /// used together.
83 static constexpr bool DefaultSuppressParametersUsedTogether = true;
84 
85 /// The default value for the NamePrefixSuffixSilenceDissimilarityTreshold
86 /// check option.
87 static constexpr std::size_t
88     DefaultNamePrefixSuffixSilenceDissimilarityTreshold = 1;
89 
90 using namespace clang::ast_matchers;
91 
92 namespace clang::tidy::bugprone {
93 
94 using TheCheck = EasilySwappableParametersCheck;
95 
96 namespace filter {
97 class SimilarlyUsedParameterPairSuppressor;
98 
99 static bool isIgnoredParameter(const TheCheck &Check, const ParmVarDecl *Node);
100 static inline bool
101 isSimilarlyUsedParameter(const SimilarlyUsedParameterPairSuppressor &Suppressor,
102                          const ParmVarDecl *Param1, const ParmVarDecl *Param2);
103 static bool prefixSuffixCoverUnderThreshold(std::size_t Threshold,
104                                             StringRef Str1, StringRef Str2);
105 } // namespace filter
106 
107 namespace model {
108 
109 /// The language features involved in allowing the mix between two parameters.
110 enum class MixFlags : unsigned char {
111   Invalid = 0, ///< Sentinel bit pattern. DO NOT USE!
112 
113   /// Certain constructs (such as pointers to noexcept/non-noexcept functions)
114   /// have the same CanonicalType, which would result in false positives.
115   /// During the recursive modelling call, this flag is set if a later diagnosed
116   /// canonical type equivalence should be thrown away.
117   WorkaroundDisableCanonicalEquivalence = 1,
118 
119   None = 2,           ///< Mix between the two parameters is not possible.
120   Trivial = 4,        ///< The two mix trivially, and are the exact same type.
121   Canonical = 8,      ///< The two mix because the types refer to the same
122                       /// CanonicalType, but we do not elaborate as to how.
123   TypeAlias = 16,     ///< The path from one type to the other involves
124                       /// desugaring type aliases.
125   ReferenceBind = 32, ///< The mix involves the binding power of "const &".
126   Qualifiers = 64,    ///< The mix involves change in the qualifiers.
127   ImplicitConversion = 128, ///< The mixing of the parameters is possible
128                             /// through implicit conversions between the types.
129 
130   LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue =*/ImplicitConversion)
131 };
132 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
133 
134 /// Returns whether the SearchedFlag is turned on in the Data.
135 static inline bool hasFlag(MixFlags Data, MixFlags SearchedFlag) {
136   assert(SearchedFlag != MixFlags::Invalid &&
137          "can't be used to detect lack of all bits!");
138 
139   // "Data & SearchedFlag" would need static_cast<bool>() in conditions.
140   return (Data & SearchedFlag) == SearchedFlag;
141 }
142 
143 #ifndef NDEBUG
144 
145 // The modelling logic of this check is more complex than usual, and
146 // potentially hard to understand without the ability to see into the
147 // representation during the recursive descent. This debug code is only
148 // compiled in 'Debug' mode, or if LLVM_ENABLE_ASSERTIONS config is turned on.
149 
150 /// Formats the MixFlags enum into a useful, user-readable representation.
151 static inline std::string formatMixFlags(MixFlags F) {
152   if (F == MixFlags::Invalid)
153     return "#Inv!";
154 
155   SmallString<8> Str{"-------"};
156 
157   if (hasFlag(F, MixFlags::None))
158     // Shows the None bit explicitly, as it can be applied in the recursion
159     // even if other bits are set.
160     Str[0] = '!';
161   if (hasFlag(F, MixFlags::Trivial))
162     Str[1] = 'T';
163   if (hasFlag(F, MixFlags::Canonical))
164     Str[2] = 'C';
165   if (hasFlag(F, MixFlags::TypeAlias))
166     Str[3] = 't';
167   if (hasFlag(F, MixFlags::ReferenceBind))
168     Str[4] = '&';
169   if (hasFlag(F, MixFlags::Qualifiers))
170     Str[5] = 'Q';
171   if (hasFlag(F, MixFlags::ImplicitConversion))
172     Str[6] = 'i';
173 
174   if (hasFlag(F, MixFlags::WorkaroundDisableCanonicalEquivalence))
175     Str.append("(~C)");
176 
177   return Str.str().str();
178 }
179 
180 #endif // NDEBUG
181 
182 /// The results of the steps of an Implicit Conversion Sequence is saved in
183 /// an instance of this record.
184 ///
185 /// A ConversionSequence maps the steps of the conversion with a member for
186 /// each type involved in the conversion. Imagine going from a hypothetical
187 /// Complex class to projecting it to the real part as a const double.
188 ///
189 /// I.e., given:
190 ///
191 ///    struct Complex {
192 ///      operator double() const;
193 ///    };
194 ///
195 ///    void functionBeingAnalysed(Complex C, const double R);
196 ///
197 /// we will get the following sequence:
198 ///
199 /// (Begin=) Complex
200 ///
201 ///     The first standard conversion is a qualification adjustment.
202 /// (AfterFirstStandard=) const Complex
203 ///
204 ///     Then the user-defined conversion is executed.
205 /// (UDConvOp.ConversionOperatorResultType=) double
206 ///
207 ///     Then this 'double' is qualifier-adjusted to 'const double'.
208 /// (AfterSecondStandard=) double
209 ///
210 /// The conversion's result has now been calculated, so it ends here.
211 /// (End=) double.
212 ///
213 /// Explicit storing of Begin and End in this record is needed, because
214 /// getting to what Begin and End here are needs further resolution of types,
215 /// e.g. in the case of typedefs:
216 ///
217 ///     using Comp = Complex;
218 ///     using CD = const double;
219 ///     void functionBeingAnalysed2(Comp C, CD R);
220 ///
221 /// In this case, the user will be diagnosed with a potential conversion
222 /// between the two typedefs as written in the code, but to elaborate the
223 /// reasoning behind this conversion, we also need to show what the typedefs
224 /// mean. See FormattedConversionSequence towards the bottom of this file!
225 struct ConversionSequence {
226   enum UserDefinedConversionKind { UDCK_None, UDCK_Ctor, UDCK_Oper };
227 
228   struct UserDefinedConvertingConstructor {
229     const CXXConstructorDecl *Fun;
230     QualType ConstructorParameterType;
231     QualType UserDefinedType;
232   };
233 
234   struct UserDefinedConversionOperator {
235     const CXXConversionDecl *Fun;
236     QualType UserDefinedType;
237     QualType ConversionOperatorResultType;
238   };
239 
240   /// The type the conversion stared from.
241   QualType Begin;
242 
243   /// The intermediate type after the first Standard Conversion Sequence.
244   QualType AfterFirstStandard;
245 
246   /// The details of the user-defined conversion involved, as a tagged union.
247   union {
248     char None;
249     UserDefinedConvertingConstructor UDConvCtor;
250     UserDefinedConversionOperator UDConvOp;
251   };
252   UserDefinedConversionKind UDConvKind;
253 
254   /// The intermediate type after performing the second Standard Conversion
255   /// Sequence.
256   QualType AfterSecondStandard;
257 
258   /// The result type the conversion targeted.
259   QualType End;
260 
261   ConversionSequence() : None(0), UDConvKind(UDCK_None) {}
262   ConversionSequence(QualType From, QualType To)
263       : Begin(From), None(0), UDConvKind(UDCK_None), End(To) {}
264 
265   explicit operator bool() const {
266     return !AfterFirstStandard.isNull() || UDConvKind != UDCK_None ||
267            !AfterSecondStandard.isNull();
268   }
269 
270   /// Returns all the "steps" (non-unique and non-similar) types involved in
271   /// the conversion sequence. This method does **NOT** return Begin and End.
272   SmallVector<QualType, 4> getInvolvedTypesInSequence() const {
273     SmallVector<QualType, 4> Ret;
274     auto EmplaceIfDifferent = [&Ret](QualType QT) {
275       if (QT.isNull())
276         return;
277       if (Ret.empty())
278         Ret.emplace_back(QT);
279       else if (Ret.back() != QT)
280         Ret.emplace_back(QT);
281     };
282 
283     EmplaceIfDifferent(AfterFirstStandard);
284     switch (UDConvKind) {
285     case UDCK_Ctor:
286       EmplaceIfDifferent(UDConvCtor.ConstructorParameterType);
287       EmplaceIfDifferent(UDConvCtor.UserDefinedType);
288       break;
289     case UDCK_Oper:
290       EmplaceIfDifferent(UDConvOp.UserDefinedType);
291       EmplaceIfDifferent(UDConvOp.ConversionOperatorResultType);
292       break;
293     case UDCK_None:
294       break;
295     }
296     EmplaceIfDifferent(AfterSecondStandard);
297 
298     return Ret;
299   }
300 
301   /// Updates the steps of the conversion sequence with the steps from the
302   /// other instance.
303   ///
304   /// \note This method does not check if the resulting conversion sequence is
305   /// sensible!
306   ConversionSequence &update(const ConversionSequence &RHS) {
307     if (!RHS.AfterFirstStandard.isNull())
308       AfterFirstStandard = RHS.AfterFirstStandard;
309     switch (RHS.UDConvKind) {
310     case UDCK_Ctor:
311       UDConvKind = UDCK_Ctor;
312       UDConvCtor = RHS.UDConvCtor;
313       break;
314     case UDCK_Oper:
315       UDConvKind = UDCK_Oper;
316       UDConvOp = RHS.UDConvOp;
317       break;
318     case UDCK_None:
319       break;
320     }
321     if (!RHS.AfterSecondStandard.isNull())
322       AfterSecondStandard = RHS.AfterSecondStandard;
323 
324     return *this;
325   }
326 
327   /// Sets the user-defined conversion to the given constructor.
328   void setConversion(const UserDefinedConvertingConstructor &UDCC) {
329     UDConvKind = UDCK_Ctor;
330     UDConvCtor = UDCC;
331   }
332 
333   /// Sets the user-defined conversion to the given operator.
334   void setConversion(const UserDefinedConversionOperator &UDCO) {
335     UDConvKind = UDCK_Oper;
336     UDConvOp = UDCO;
337   }
338 
339   /// Returns the type in the conversion that's formally "in our hands" once
340   /// the user-defined conversion is executed.
341   QualType getTypeAfterUserDefinedConversion() const {
342     switch (UDConvKind) {
343     case UDCK_Ctor:
344       return UDConvCtor.UserDefinedType;
345     case UDCK_Oper:
346       return UDConvOp.ConversionOperatorResultType;
347     case UDCK_None:
348       return {};
349     }
350     llvm_unreachable("Invalid UDConv kind.");
351   }
352 
353   const CXXMethodDecl *getUserDefinedConversionFunction() const {
354     switch (UDConvKind) {
355     case UDCK_Ctor:
356       return UDConvCtor.Fun;
357     case UDCK_Oper:
358       return UDConvOp.Fun;
359     case UDCK_None:
360       return {};
361     }
362     llvm_unreachable("Invalid UDConv kind.");
363   }
364 
365   /// Returns the SourceRange in the text that corresponds to the interesting
366   /// part of the user-defined conversion. This is either the parameter type
367   /// in a converting constructor, or the conversion result type in a conversion
368   /// operator.
369   SourceRange getUserDefinedConversionHighlight() const {
370     switch (UDConvKind) {
371     case UDCK_Ctor:
372       return UDConvCtor.Fun->getParamDecl(0)->getSourceRange();
373     case UDCK_Oper:
374       // getReturnTypeSourceRange() does not work for CXXConversionDecls as the
375       // returned type is physically behind the declaration's name ("operator").
376       if (const FunctionTypeLoc FTL = UDConvOp.Fun->getFunctionTypeLoc())
377         if (const TypeLoc RetLoc = FTL.getReturnLoc())
378           return RetLoc.getSourceRange();
379       return {};
380     case UDCK_None:
381       return {};
382     }
383     llvm_unreachable("Invalid UDConv kind.");
384   }
385 };
386 
387 /// Contains the metadata for the mixability result between two types,
388 /// independently of which parameters they were calculated from.
389 struct MixData {
390   /// The flag bits of the mix indicating what language features allow for it.
391   MixFlags Flags = MixFlags::Invalid;
392 
393   /// A potentially calculated common underlying type after desugaring, that
394   /// both sides of the mix can originate from.
395   QualType CommonType;
396 
397   /// The steps an implicit conversion performs to get from one type to the
398   /// other.
399   ConversionSequence Conversion, ConversionRTL;
400 
401   /// True if the MixData was specifically created with only a one-way
402   /// conversion modelled.
403   bool CreatedFromOneWayConversion = false;
404 
405   MixData(MixFlags Flags) : Flags(Flags) {}
406   MixData(MixFlags Flags, QualType CommonType)
407       : Flags(Flags), CommonType(CommonType) {}
408   MixData(MixFlags Flags, ConversionSequence Conv)
409       : Flags(Flags), Conversion(Conv), CreatedFromOneWayConversion(true) {}
410   MixData(MixFlags Flags, ConversionSequence LTR, ConversionSequence RTL)
411       : Flags(Flags), Conversion(LTR), ConversionRTL(RTL) {}
412   MixData(MixFlags Flags, QualType CommonType, ConversionSequence LTR,
413           ConversionSequence RTL)
414       : Flags(Flags), CommonType(CommonType), Conversion(LTR),
415         ConversionRTL(RTL) {}
416 
417   void sanitize() {
418     assert(Flags != MixFlags::Invalid && "sanitize() called on invalid bitvec");
419 
420     MixFlags CanonicalAndWorkaround =
421         MixFlags::Canonical | MixFlags::WorkaroundDisableCanonicalEquivalence;
422     if ((Flags & CanonicalAndWorkaround) == CanonicalAndWorkaround) {
423       // A workaround for too eagerly equivalent canonical types was requested,
424       // and a canonical equivalence was proven. Fulfill the request and throw
425       // this result away.
426       Flags = MixFlags::None;
427       return;
428     }
429 
430     if (hasFlag(Flags, MixFlags::None)) {
431       // If anywhere down the recursion a potential mix "path" is deemed
432       // impossible, throw away all the other bits because the mix is not
433       // possible.
434       Flags = MixFlags::None;
435       return;
436     }
437 
438     if (Flags == MixFlags::Trivial)
439       return;
440 
441     if (static_cast<bool>(Flags ^ MixFlags::Trivial))
442       // If the mix involves somewhere trivial equivalence but down the
443       // recursion other bit(s) were set, remove the trivial bit, as it is not
444       // trivial.
445       Flags &= ~MixFlags::Trivial;
446 
447     bool ShouldHaveImplicitConvFlag = false;
448     if (CreatedFromOneWayConversion && Conversion)
449       ShouldHaveImplicitConvFlag = true;
450     else if (!CreatedFromOneWayConversion && Conversion && ConversionRTL)
451       // Only say that we have implicit conversion mix possibility if it is
452       // bidirectional. Otherwise, the compiler would report an *actual* swap
453       // at a call site...
454       ShouldHaveImplicitConvFlag = true;
455 
456     if (ShouldHaveImplicitConvFlag)
457       Flags |= MixFlags::ImplicitConversion;
458     else
459       Flags &= ~MixFlags::ImplicitConversion;
460   }
461 
462   bool isValid() const { return Flags >= MixFlags::None; }
463 
464   bool indicatesMixability() const { return Flags > MixFlags::None; }
465 
466   /// Add the specified flag bits to the flags.
467   MixData operator|(MixFlags EnableFlags) const {
468     if (CreatedFromOneWayConversion) {
469       MixData M{Flags | EnableFlags, Conversion};
470       M.CommonType = CommonType;
471       return M;
472     }
473     return {Flags | EnableFlags, CommonType, Conversion, ConversionRTL};
474   }
475 
476   /// Add the specified flag bits to the flags.
477   MixData &operator|=(MixFlags EnableFlags) {
478     Flags |= EnableFlags;
479     return *this;
480   }
481 
482   template <typename F> MixData withCommonTypeTransformed(const F &Func) const {
483     if (CommonType.isNull())
484       return *this;
485 
486     QualType NewCommonType = Func(CommonType);
487 
488     if (CreatedFromOneWayConversion) {
489       MixData M{Flags, Conversion};
490       M.CommonType = NewCommonType;
491       return M;
492     }
493 
494     return {Flags, NewCommonType, Conversion, ConversionRTL};
495   }
496 };
497 
498 /// A named tuple that contains the information for a mix between two concrete
499 /// parameters.
500 struct Mix {
501   const ParmVarDecl *First, *Second;
502   MixData Data;
503 
504   Mix(const ParmVarDecl *F, const ParmVarDecl *S, MixData Data)
505       : First(F), Second(S), Data(std::move(Data)) {}
506 
507   void sanitize() { Data.sanitize(); }
508   MixFlags flags() const { return Data.Flags; }
509   bool flagsValid() const { return Data.isValid(); }
510   bool mixable() const { return Data.indicatesMixability(); }
511   QualType commonUnderlyingType() const { return Data.CommonType; }
512   const ConversionSequence &leftToRightConversionSequence() const {
513     return Data.Conversion;
514   }
515   const ConversionSequence &rightToLeftConversionSequence() const {
516     return Data.ConversionRTL;
517   }
518 };
519 
520 // NOLINTNEXTLINE(misc-redundant-expression): Seems to be a bogus warning.
521 static_assert(std::is_trivially_copyable_v<Mix> &&
522                   std::is_trivially_move_constructible_v<Mix> &&
523                   std::is_trivially_move_assignable_v<Mix>,
524               "Keep frequently used data simple!");
525 
526 struct MixableParameterRange {
527   /// A container for Mixes.
528   using MixVector = SmallVector<Mix, 8>;
529 
530   /// The number of parameters iterated to build the instance.
531   std::size_t NumParamsChecked = 0;
532 
533   /// The individual flags and supporting information for the mixes.
534   MixVector Mixes;
535 
536   /// Gets the leftmost parameter of the range.
537   const ParmVarDecl *getFirstParam() const {
538     // The first element is the LHS of the very first mix in the range.
539     assert(!Mixes.empty());
540     return Mixes.front().First;
541   }
542 
543   /// Gets the rightmost parameter of the range.
544   const ParmVarDecl *getLastParam() const {
545     // The builder function breaks building an instance of this type if it
546     // finds something that can not be mixed with the rest, by going *forward*
547     // in the list of parameters. So at any moment of break, the RHS of the last
548     // element of the mix vector is also the last element of the mixing range.
549     assert(!Mixes.empty());
550     return Mixes.back().Second;
551   }
552 };
553 
554 /// Helper enum for the recursive calls in the modelling that toggle what kinds
555 /// of implicit conversions are to be modelled.
556 enum class ImplicitConversionModellingMode : unsigned char {
557   ///< No implicit conversions are modelled.
558   None,
559 
560   ///< The full implicit conversion sequence is modelled.
561   All,
562 
563   ///< Only model a unidirectional implicit conversion and within it only one
564   /// standard conversion sequence.
565   OneWaySingleStandardOnly
566 };
567 
568 static MixData
569 isLRefEquallyBindingToType(const TheCheck &Check,
570                            const LValueReferenceType *LRef, QualType Ty,
571                            const ASTContext &Ctx, bool IsRefRHS,
572                            ImplicitConversionModellingMode ImplicitMode);
573 
574 static MixData
575 approximateImplicitConversion(const TheCheck &Check, QualType LType,
576                               QualType RType, const ASTContext &Ctx,
577                               ImplicitConversionModellingMode ImplicitMode);
578 
579 static inline bool isUselessSugar(const Type *T) {
580   return isa<AttributedType, DecayedType, ElaboratedType, ParenType>(T);
581 }
582 
583 namespace {
584 
585 struct NonCVRQualifiersResult {
586   /// True if the types are qualified in a way that even after equating or
587   /// removing local CVR qualification, even if the unqualified types
588   /// themselves would mix, the qualified ones don't, because there are some
589   /// other local qualifiers that are not equal.
590   bool HasMixabilityBreakingQualifiers;
591 
592   /// The set of equal qualifiers between the two types.
593   Qualifiers CommonQualifiers;
594 };
595 
596 } // namespace
597 
598 /// Returns if the two types are qualified in a way that ever after equating or
599 /// removing local CVR qualification, even if the unqualified types would mix,
600 /// the qualified ones don't, because there are some other local qualifiers
601 /// that aren't equal.
602 static NonCVRQualifiersResult
603 getNonCVRQualifiers(const ASTContext &Ctx, QualType LType, QualType RType) {
604   LLVM_DEBUG(llvm::dbgs() << ">>> getNonCVRQualifiers for LType:\n";
605              LType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand RType:\n";
606              RType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << '\n';);
607   Qualifiers LQual = LType.getLocalQualifiers(),
608              RQual = RType.getLocalQualifiers();
609 
610   // Strip potential CVR. That is handled by the check option QualifiersMix.
611   LQual.removeCVRQualifiers();
612   RQual.removeCVRQualifiers();
613 
614   NonCVRQualifiersResult Ret;
615   Ret.CommonQualifiers = Qualifiers::removeCommonQualifiers(LQual, RQual);
616 
617   LLVM_DEBUG(llvm::dbgs() << "--- hasNonCVRMixabilityBreakingQualifiers. "
618                              "Removed common qualifiers: ";
619              Ret.CommonQualifiers.print(llvm::dbgs(), Ctx.getPrintingPolicy());
620              llvm::dbgs() << "\n\tremaining on LType: ";
621              LQual.print(llvm::dbgs(), Ctx.getPrintingPolicy());
622              llvm::dbgs() << "\n\tremaining on RType: ";
623              RQual.print(llvm::dbgs(), Ctx.getPrintingPolicy());
624              llvm::dbgs() << '\n';);
625 
626   // If there are no other non-cvr non-common qualifiers left, we can deduce
627   // that mixability isn't broken.
628   Ret.HasMixabilityBreakingQualifiers =
629       LQual.hasQualifiers() || RQual.hasQualifiers();
630 
631   return Ret;
632 }
633 
634 /// Approximate the way how LType and RType might refer to "essentially the
635 /// same" type, in a sense that at a particular call site, an expression of
636 /// type LType and RType might be successfully passed to a variable (in our
637 /// specific case, a parameter) of type RType and LType, respectively.
638 /// Note the swapped order!
639 ///
640 /// The returned data structure is not guaranteed to be properly set, as this
641 /// function is potentially recursive. It is the caller's responsibility to
642 /// call sanitize() on the result once the recursion is over.
643 static MixData
644 calculateMixability(const TheCheck &Check, QualType LType, QualType RType,
645                     const ASTContext &Ctx,
646                     ImplicitConversionModellingMode ImplicitMode) {
647   LLVM_DEBUG(llvm::dbgs() << ">>> calculateMixability for LType:\n";
648              LType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand RType:\n";
649              RType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << '\n';);
650   if (LType == RType) {
651     LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Trivial equality.\n");
652     return {MixFlags::Trivial, LType};
653   }
654 
655   // Dissolve certain type sugars that do not affect the mixability of one type
656   // with the other, and also do not require any sort of elaboration for the
657   // user to understand.
658   if (isUselessSugar(LType.getTypePtr())) {
659     LLVM_DEBUG(llvm::dbgs()
660                << "--- calculateMixability. LHS is useless sugar.\n");
661     return calculateMixability(Check, LType.getSingleStepDesugaredType(Ctx),
662                                RType, Ctx, ImplicitMode);
663   }
664   if (isUselessSugar(RType.getTypePtr())) {
665     LLVM_DEBUG(llvm::dbgs()
666                << "--- calculateMixability. RHS is useless sugar.\n");
667     return calculateMixability(
668         Check, LType, RType.getSingleStepDesugaredType(Ctx), Ctx, ImplicitMode);
669   }
670 
671   const auto *LLRef = LType->getAs<LValueReferenceType>();
672   const auto *RLRef = RType->getAs<LValueReferenceType>();
673   if (LLRef && RLRef) {
674     LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. LHS and RHS are &.\n");
675 
676     return calculateMixability(Check, LLRef->getPointeeType(),
677                                RLRef->getPointeeType(), Ctx, ImplicitMode)
678         .withCommonTypeTransformed(
679             [&Ctx](QualType QT) { return Ctx.getLValueReferenceType(QT); });
680   }
681   // At a particular call site, what could be passed to a 'T' or 'const T' might
682   // also be passed to a 'const T &' without the call site putting a direct
683   // side effect on the passed expressions.
684   if (LLRef) {
685     LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. LHS is &.\n");
686     return isLRefEquallyBindingToType(Check, LLRef, RType, Ctx, false,
687                                       ImplicitMode) |
688            MixFlags::ReferenceBind;
689   }
690   if (RLRef) {
691     LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. RHS is &.\n");
692     return isLRefEquallyBindingToType(Check, RLRef, LType, Ctx, true,
693                                       ImplicitMode) |
694            MixFlags::ReferenceBind;
695   }
696 
697   if (LType->getAs<TypedefType>()) {
698     LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. LHS is typedef.\n");
699     return calculateMixability(Check, LType.getSingleStepDesugaredType(Ctx),
700                                RType, Ctx, ImplicitMode) |
701            MixFlags::TypeAlias;
702   }
703   if (RType->getAs<TypedefType>()) {
704     LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. RHS is typedef.\n");
705     return calculateMixability(Check, LType,
706                                RType.getSingleStepDesugaredType(Ctx), Ctx,
707                                ImplicitMode) |
708            MixFlags::TypeAlias;
709   }
710 
711   // A parameter of type 'cvr1 T' and another of potentially differently
712   // qualified 'cvr2 T' may bind with the same power, if the user so requested.
713   //
714   // Whether to do this check for the inner unqualified types.
715   bool CompareUnqualifiedTypes = false;
716   if (LType.getLocalCVRQualifiers() != RType.getLocalCVRQualifiers()) {
717     LLVM_DEBUG(if (LType.getLocalCVRQualifiers()) {
718       llvm::dbgs() << "--- calculateMixability. LHS has CVR-Qualifiers: ";
719       Qualifiers::fromCVRMask(LType.getLocalCVRQualifiers())
720           .print(llvm::dbgs(), Ctx.getPrintingPolicy());
721       llvm::dbgs() << '\n';
722     });
723     LLVM_DEBUG(if (RType.getLocalCVRQualifiers()) {
724       llvm::dbgs() << "--- calculateMixability. RHS has CVR-Qualifiers: ";
725       Qualifiers::fromCVRMask(RType.getLocalCVRQualifiers())
726           .print(llvm::dbgs(), Ctx.getPrintingPolicy());
727       llvm::dbgs() << '\n';
728     });
729 
730     if (!Check.QualifiersMix) {
731       LLVM_DEBUG(llvm::dbgs()
732                  << "<<< calculateMixability. QualifiersMix turned off - not "
733                     "mixable.\n");
734       return {MixFlags::None};
735     }
736 
737     CompareUnqualifiedTypes = true;
738   }
739   // Whether the two types had the same CVR qualifiers.
740   bool OriginallySameQualifiers = false;
741   if (LType.getLocalCVRQualifiers() == RType.getLocalCVRQualifiers() &&
742       LType.getLocalCVRQualifiers() != 0) {
743     LLVM_DEBUG(if (LType.getLocalCVRQualifiers()) {
744       llvm::dbgs()
745           << "--- calculateMixability. LHS and RHS have same CVR-Qualifiers: ";
746       Qualifiers::fromCVRMask(LType.getLocalCVRQualifiers())
747           .print(llvm::dbgs(), Ctx.getPrintingPolicy());
748       llvm::dbgs() << '\n';
749     });
750 
751     CompareUnqualifiedTypes = true;
752     OriginallySameQualifiers = true;
753   }
754 
755   if (CompareUnqualifiedTypes) {
756     NonCVRQualifiersResult AdditionalQuals =
757         getNonCVRQualifiers(Ctx, LType, RType);
758     if (AdditionalQuals.HasMixabilityBreakingQualifiers) {
759       LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Additional "
760                                  "non-equal incompatible qualifiers.\n");
761       return {MixFlags::None};
762     }
763 
764     MixData UnqualifiedMixability =
765         calculateMixability(Check, LType.getLocalUnqualifiedType(),
766                             RType.getLocalUnqualifiedType(), Ctx, ImplicitMode)
767             .withCommonTypeTransformed([&AdditionalQuals, &Ctx](QualType QT) {
768               // Once the mixability was deduced, apply the qualifiers common
769               // to the two type back onto the diagnostic printout.
770               return Ctx.getQualifiedType(QT, AdditionalQuals.CommonQualifiers);
771             });
772 
773     if (!OriginallySameQualifiers)
774       // User-enabled qualifier change modelled for the mix.
775       return UnqualifiedMixability | MixFlags::Qualifiers;
776 
777     // Apply the same qualifier back into the found common type if they were
778     // the same.
779     return UnqualifiedMixability.withCommonTypeTransformed(
780         [&Ctx, LType](QualType QT) {
781           return Ctx.getQualifiedType(QT, LType.getLocalQualifiers());
782         });
783   }
784 
785   // Certain constructs match on the last catch-all getCanonicalType() equality,
786   // which is perhaps something not what we want. If this variable is true,
787   // the canonical type equality will be ignored.
788   bool RecursiveReturnDiscardingCanonicalType = false;
789 
790   if (LType->isPointerType() && RType->isPointerType()) {
791     // If both types are pointers, and pointed to the exact same type,
792     // LType == RType took care of that. Try to see if the pointee type has
793     // some other match. However, this must not consider implicit conversions.
794     LLVM_DEBUG(llvm::dbgs()
795                << "--- calculateMixability. LHS and RHS are Ptrs.\n");
796     MixData MixOfPointee =
797         calculateMixability(Check, LType->getPointeeType(),
798                             RType->getPointeeType(), Ctx,
799                             ImplicitConversionModellingMode::None)
800             .withCommonTypeTransformed(
801                 [&Ctx](QualType QT) { return Ctx.getPointerType(QT); });
802     if (hasFlag(MixOfPointee.Flags,
803                 MixFlags::WorkaroundDisableCanonicalEquivalence))
804       RecursiveReturnDiscardingCanonicalType = true;
805 
806     MixOfPointee.sanitize();
807     if (MixOfPointee.indicatesMixability()) {
808       LLVM_DEBUG(llvm::dbgs()
809                  << "<<< calculateMixability. Pointees are mixable.\n");
810       return MixOfPointee;
811     }
812   }
813 
814   if (ImplicitMode > ImplicitConversionModellingMode::None) {
815     LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. Start implicit...\n");
816     MixData MixLTR =
817         approximateImplicitConversion(Check, LType, RType, Ctx, ImplicitMode);
818     LLVM_DEBUG(
819         if (hasFlag(MixLTR.Flags, MixFlags::ImplicitConversion)) llvm::dbgs()
820             << "--- calculateMixability. Implicit Left -> Right found.\n";);
821 
822     if (ImplicitMode ==
823             ImplicitConversionModellingMode::OneWaySingleStandardOnly &&
824         MixLTR.Conversion && !MixLTR.Conversion.AfterFirstStandard.isNull() &&
825         MixLTR.Conversion.UDConvKind == ConversionSequence::UDCK_None &&
826         MixLTR.Conversion.AfterSecondStandard.isNull()) {
827       // The invoker of the method requested only modelling a single standard
828       // conversion, in only the forward direction, and they got just that.
829       LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Implicit "
830                                  "conversion, one-way, standard-only.\n");
831       return {MixFlags::ImplicitConversion, MixLTR.Conversion};
832     }
833 
834     // Otherwise if the invoker requested a full modelling, do the other
835     // direction as well.
836     MixData MixRTL =
837         approximateImplicitConversion(Check, RType, LType, Ctx, ImplicitMode);
838     LLVM_DEBUG(
839         if (hasFlag(MixRTL.Flags, MixFlags::ImplicitConversion)) llvm::dbgs()
840             << "--- calculateMixability. Implicit Right -> Left found.\n";);
841 
842     if (MixLTR.Conversion && MixRTL.Conversion) {
843       LLVM_DEBUG(
844           llvm::dbgs()
845           << "<<< calculateMixability. Implicit conversion, bidirectional.\n");
846       return {MixFlags::ImplicitConversion, MixLTR.Conversion,
847               MixRTL.Conversion};
848     }
849   }
850 
851   if (RecursiveReturnDiscardingCanonicalType)
852     LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. Before CanonicalType, "
853                                "Discard was enabled.\n");
854 
855   // Certain kinds unfortunately need to be side-stepped for canonical type
856   // matching.
857   if (LType->getAs<FunctionProtoType>() || RType->getAs<FunctionProtoType>()) {
858     // Unfortunately, the canonical type of a function pointer becomes the
859     // same even if exactly one is "noexcept" and the other isn't, making us
860     // give a false positive report irrespective of implicit conversions.
861     LLVM_DEBUG(llvm::dbgs()
862                << "--- calculateMixability. Discarding potential canonical "
863                   "equivalence on FunctionProtoTypes.\n");
864     RecursiveReturnDiscardingCanonicalType = true;
865   }
866 
867   MixData MixToReturn{MixFlags::None};
868 
869   // If none of the previous logic found a match, try if Clang otherwise
870   // believes the types to be the same.
871   QualType LCanonical = LType.getCanonicalType();
872   if (LCanonical == RType.getCanonicalType()) {
873     LLVM_DEBUG(llvm::dbgs()
874                << "<<< calculateMixability. Same CanonicalType.\n");
875     MixToReturn = {MixFlags::Canonical, LCanonical};
876   }
877 
878   if (RecursiveReturnDiscardingCanonicalType)
879     MixToReturn |= MixFlags::WorkaroundDisableCanonicalEquivalence;
880 
881   LLVM_DEBUG(if (MixToReturn.Flags == MixFlags::None) llvm::dbgs()
882              << "<<< calculateMixability. No match found.\n");
883   return MixToReturn;
884 }
885 
886 /// Calculates if the reference binds an expression of the given type. This is
887 /// true iff 'LRef' is some 'const T &' type, and the 'Ty' is 'T' or 'const T'.
888 ///
889 /// \param ImplicitMode is forwarded in the possible recursive call to
890 /// calculateMixability.
891 static MixData
892 isLRefEquallyBindingToType(const TheCheck &Check,
893                            const LValueReferenceType *LRef, QualType Ty,
894                            const ASTContext &Ctx, bool IsRefRHS,
895                            ImplicitConversionModellingMode ImplicitMode) {
896   LLVM_DEBUG(llvm::dbgs() << ">>> isLRefEquallyBindingToType for LRef:\n";
897              LRef->dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand Type:\n";
898              Ty.dump(llvm::dbgs(), Ctx); llvm::dbgs() << '\n';);
899 
900   QualType ReferredType = LRef->getPointeeType();
901   if (!ReferredType.isLocalConstQualified() &&
902       ReferredType->getAs<TypedefType>()) {
903     LLVM_DEBUG(
904         llvm::dbgs()
905         << "--- isLRefEquallyBindingToType. Non-const LRef to Typedef.\n");
906     ReferredType = ReferredType.getDesugaredType(Ctx);
907     if (!ReferredType.isLocalConstQualified()) {
908       LLVM_DEBUG(llvm::dbgs()
909                  << "<<< isLRefEquallyBindingToType. Typedef is not const.\n");
910       return {MixFlags::None};
911     }
912 
913     LLVM_DEBUG(llvm::dbgs() << "--- isLRefEquallyBindingToType. Typedef is "
914                                "const, considering as const LRef.\n");
915   } else if (!ReferredType.isLocalConstQualified()) {
916     LLVM_DEBUG(llvm::dbgs()
917                << "<<< isLRefEquallyBindingToType. Not const LRef.\n");
918     return {MixFlags::None};
919   };
920 
921   assert(ReferredType.isLocalConstQualified() &&
922          "Reaching this point means we are sure LRef is effectively a const&.");
923 
924   if (ReferredType == Ty) {
925     LLVM_DEBUG(
926         llvm::dbgs()
927         << "<<< isLRefEquallyBindingToType. Type of referred matches.\n");
928     return {MixFlags::Trivial, ReferredType};
929   }
930 
931   QualType NonConstReferredType = ReferredType;
932   NonConstReferredType.removeLocalConst();
933   if (NonConstReferredType == Ty) {
934     LLVM_DEBUG(llvm::dbgs() << "<<< isLRefEquallyBindingToType. Type of "
935                                "referred matches to non-const qualified.\n");
936     return {MixFlags::Trivial, NonConstReferredType};
937   }
938 
939   LLVM_DEBUG(
940       llvm::dbgs()
941       << "--- isLRefEquallyBindingToType. Checking mix for underlying type.\n");
942   return IsRefRHS ? calculateMixability(Check, Ty, NonConstReferredType, Ctx,
943                                         ImplicitMode)
944                   : calculateMixability(Check, NonConstReferredType, Ty, Ctx,
945                                         ImplicitMode);
946 }
947 
948 static inline bool isDerivedToBase(const CXXRecordDecl *Derived,
949                                    const CXXRecordDecl *Base) {
950   return Derived && Base && Derived->isCompleteDefinition() &&
951          Base->isCompleteDefinition() && Derived->isDerivedFrom(Base);
952 }
953 
954 static std::optional<QualType>
955 approximateStandardConversionSequence(const TheCheck &Check, QualType From,
956                                       QualType To, const ASTContext &Ctx) {
957   LLVM_DEBUG(llvm::dbgs() << ">>> approximateStdConv for LType:\n";
958              From.dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand RType:\n";
959              To.dump(llvm::dbgs(), Ctx); llvm::dbgs() << '\n';);
960 
961   // A standard conversion sequence consists of the following, in order:
962   //  * Maybe either LValue->RValue conv., Array->Ptr conv., Function->Ptr conv.
963   //  * Maybe Numeric promotion or conversion.
964   //  * Maybe function pointer conversion.
965   //  * Maybe qualifier adjustments.
966   QualType WorkType = From;
967   // Get out the qualifiers of the original type. This will always be
968   // re-applied to the WorkType to ensure it is the same qualification as the
969   // original From was.
970   auto QualifiersToApply = From.split().Quals.getAsOpaqueValue();
971 
972   // LValue->RValue is irrelevant for the check, because it is a thing to be
973   // done at a call site, and will be performed if need be performed.
974 
975   // Array->Pointer decay is handled by the main method in desugaring
976   // the parameter's DecayedType as "useless sugar".
977 
978   // Function->Pointer conversions are also irrelevant, because a
979   // "FunctionType" cannot be the type of a parameter variable, so this
980   // conversion is only meaningful at call sites.
981 
982   // Numeric promotions and conversions.
983   const auto *FromBuiltin = WorkType->getAs<BuiltinType>();
984   const auto *ToBuiltin = To->getAs<BuiltinType>();
985   bool FromNumeric = FromBuiltin && (FromBuiltin->isIntegerType() ||
986                                      FromBuiltin->isFloatingType());
987   bool ToNumeric =
988       ToBuiltin && (ToBuiltin->isIntegerType() || ToBuiltin->isFloatingType());
989   if (FromNumeric && ToNumeric) {
990     // If both are integral types, the numeric conversion is performed.
991     // Reapply the qualifiers of the original type, however, so
992     // "const int -> double" in this case moves over to
993     // "const double -> double".
994     LLVM_DEBUG(llvm::dbgs()
995                << "--- approximateStdConv. Conversion between numerics.\n");
996     WorkType = QualType{ToBuiltin, QualifiersToApply};
997   }
998 
999   const auto *FromEnum = WorkType->getAs<EnumType>();
1000   const auto *ToEnum = To->getAs<EnumType>();
1001   if (FromEnum && ToNumeric && FromEnum->isUnscopedEnumerationType()) {
1002     // Unscoped enumerations (or enumerations in C) convert to numerics.
1003     LLVM_DEBUG(llvm::dbgs()
1004                << "--- approximateStdConv. Unscoped enum to numeric.\n");
1005     WorkType = QualType{ToBuiltin, QualifiersToApply};
1006   } else if (FromNumeric && ToEnum && ToEnum->isUnscopedEnumerationType()) {
1007     // Numeric types convert to enumerations only in C.
1008     if (Ctx.getLangOpts().CPlusPlus) {
1009       LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Numeric to unscoped "
1010                                  "enum, not possible in C++!\n");
1011       return {};
1012     }
1013 
1014     LLVM_DEBUG(llvm::dbgs()
1015                << "--- approximateStdConv. Numeric to unscoped enum.\n");
1016     WorkType = QualType{ToEnum, QualifiersToApply};
1017   }
1018 
1019   // Check for pointer conversions.
1020   const auto *FromPtr = WorkType->getAs<PointerType>();
1021   const auto *ToPtr = To->getAs<PointerType>();
1022   if (FromPtr && ToPtr) {
1023     if (ToPtr->isVoidPointerType()) {
1024       LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. To void pointer.\n");
1025       WorkType = QualType{ToPtr, QualifiersToApply};
1026     }
1027 
1028     const auto *FromRecordPtr = FromPtr->getPointeeCXXRecordDecl();
1029     const auto *ToRecordPtr = ToPtr->getPointeeCXXRecordDecl();
1030     if (isDerivedToBase(FromRecordPtr, ToRecordPtr)) {
1031       LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived* to Base*\n");
1032       WorkType = QualType{ToPtr, QualifiersToApply};
1033     }
1034   }
1035 
1036   // Model the slicing Derived-to-Base too, as "BaseT temporary = derived;"
1037   // can also be compiled.
1038   const auto *FromRecord = WorkType->getAsCXXRecordDecl();
1039   const auto *ToRecord = To->getAsCXXRecordDecl();
1040   if (isDerivedToBase(FromRecord, ToRecord)) {
1041     LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived To Base.\n");
1042     WorkType = QualType{ToRecord->getTypeForDecl(), QualifiersToApply};
1043   }
1044 
1045   if (Ctx.getLangOpts().CPlusPlus17 && FromPtr && ToPtr) {
1046     // Function pointer conversion: A noexcept function pointer can be passed
1047     // to a non-noexcept one.
1048     const auto *FromFunctionPtr =
1049         FromPtr->getPointeeType()->getAs<FunctionProtoType>();
1050     const auto *ToFunctionPtr =
1051         ToPtr->getPointeeType()->getAs<FunctionProtoType>();
1052     if (FromFunctionPtr && ToFunctionPtr &&
1053         FromFunctionPtr->hasNoexceptExceptionSpec() &&
1054         !ToFunctionPtr->hasNoexceptExceptionSpec()) {
1055       LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. noexcept function "
1056                                  "pointer to non-noexcept.\n");
1057       WorkType = QualType{ToPtr, QualifiersToApply};
1058     }
1059   }
1060 
1061   // Qualifier adjustments are modelled according to the user's request in
1062   // the QualifiersMix check config.
1063   LLVM_DEBUG(llvm::dbgs()
1064              << "--- approximateStdConv. Trying qualifier adjustment...\n");
1065   MixData QualConv = calculateMixability(Check, WorkType, To, Ctx,
1066                                          ImplicitConversionModellingMode::None);
1067   QualConv.sanitize();
1068   if (hasFlag(QualConv.Flags, MixFlags::Qualifiers)) {
1069     LLVM_DEBUG(llvm::dbgs()
1070                << "<<< approximateStdConv. Qualifiers adjusted.\n");
1071     WorkType = To;
1072   }
1073 
1074   if (WorkType == To) {
1075     LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Reached 'To' type.\n");
1076     return {WorkType};
1077   }
1078 
1079   LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Did not reach 'To'.\n");
1080   return {};
1081 }
1082 
1083 namespace {
1084 
1085 /// Helper class for storing possible user-defined conversion calls that
1086 /// *could* take place in an implicit conversion, and selecting the one that
1087 /// most likely *does*, if any.
1088 class UserDefinedConversionSelector {
1089 public:
1090   /// The conversion associated with a conversion function, together with the
1091   /// mixability flags of the conversion function's parameter or return type
1092   /// to the rest of the sequence the selector is used in, and the sequence
1093   /// that applied through the conversion itself.
1094   struct PreparedConversion {
1095     const CXXMethodDecl *ConversionFun;
1096     MixFlags Flags;
1097     ConversionSequence Seq;
1098 
1099     PreparedConversion(const CXXMethodDecl *CMD, MixFlags F,
1100                        ConversionSequence S)
1101         : ConversionFun(CMD), Flags(F), Seq(S) {}
1102   };
1103 
1104   UserDefinedConversionSelector(const TheCheck &Check) : Check(Check) {}
1105 
1106   /// Adds the conversion between the two types for the given function into
1107   /// the possible implicit conversion set. FromType and ToType is either:
1108   ///   * the result of a standard sequence and a converting ctor parameter
1109   ///   * the return type of a conversion operator and the expected target of
1110   ///     an implicit conversion.
1111   void addConversion(const CXXMethodDecl *ConvFun, QualType FromType,
1112                      QualType ToType) {
1113     // Try to go from the FromType to the ToType with only a single implicit
1114     // conversion, to see if the conversion function is applicable.
1115     MixData Mix = calculateMixability(
1116         Check, FromType, ToType, ConvFun->getASTContext(),
1117         ImplicitConversionModellingMode::OneWaySingleStandardOnly);
1118     Mix.sanitize();
1119     if (!Mix.indicatesMixability())
1120       return;
1121 
1122     LLVM_DEBUG(llvm::dbgs() << "--- tryConversion. Found viable with flags: "
1123                             << formatMixFlags(Mix.Flags) << '\n');
1124     FlaggedConversions.emplace_back(ConvFun, Mix.Flags, Mix.Conversion);
1125   }
1126 
1127   /// Selects the best conversion function that is applicable from the
1128   /// prepared set of potential conversion functions taken.
1129   std::optional<PreparedConversion> operator()() const {
1130     if (FlaggedConversions.empty()) {
1131       LLVM_DEBUG(llvm::dbgs() << "--- selectUserDefinedConv. Empty.\n");
1132       return {};
1133     }
1134     if (FlaggedConversions.size() == 1) {
1135       LLVM_DEBUG(llvm::dbgs() << "--- selectUserDefinedConv. Single.\n");
1136       return FlaggedConversions.front();
1137     }
1138 
1139     std::optional<PreparedConversion> BestConversion;
1140     unsigned short HowManyGoodConversions = 0;
1141     for (const auto &Prepared : FlaggedConversions) {
1142       LLVM_DEBUG(llvm::dbgs() << "--- selectUserDefinedConv. Candidate flags: "
1143                               << formatMixFlags(Prepared.Flags) << '\n');
1144       if (!BestConversion) {
1145         BestConversion = Prepared;
1146         ++HowManyGoodConversions;
1147         continue;
1148       }
1149 
1150       bool BestConversionHasImplicit =
1151           hasFlag(BestConversion->Flags, MixFlags::ImplicitConversion);
1152       bool ThisConversionHasImplicit =
1153           hasFlag(Prepared.Flags, MixFlags::ImplicitConversion);
1154       if (!BestConversionHasImplicit && ThisConversionHasImplicit)
1155         // This is a worse conversion, because a better one was found earlier.
1156         continue;
1157 
1158       if (BestConversionHasImplicit && !ThisConversionHasImplicit) {
1159         // If the so far best selected conversion needs a previous implicit
1160         // conversion to match the user-defined converting function, but this
1161         // conversion does not, this is a better conversion, and we can throw
1162         // away the previously selected conversion(s).
1163         BestConversion = Prepared;
1164         HowManyGoodConversions = 1;
1165         continue;
1166       }
1167 
1168       if (BestConversionHasImplicit == ThisConversionHasImplicit)
1169         // The current conversion is the same in term of goodness than the
1170         // already selected one.
1171         ++HowManyGoodConversions;
1172     }
1173 
1174     if (HowManyGoodConversions == 1) {
1175       LLVM_DEBUG(llvm::dbgs()
1176                  << "--- selectUserDefinedConv. Unique result. Flags: "
1177                  << formatMixFlags(BestConversion->Flags) << '\n');
1178       return BestConversion;
1179     }
1180 
1181     LLVM_DEBUG(llvm::dbgs()
1182                << "--- selectUserDefinedConv. No, or ambiguous.\n");
1183     return {};
1184   }
1185 
1186 private:
1187   llvm::SmallVector<PreparedConversion, 2> FlaggedConversions;
1188   const TheCheck &Check;
1189 };
1190 
1191 } // namespace
1192 
1193 static std::optional<ConversionSequence>
1194 tryConversionOperators(const TheCheck &Check, const CXXRecordDecl *RD,
1195                        QualType ToType) {
1196   if (!RD || !RD->isCompleteDefinition())
1197     return {};
1198   RD = RD->getDefinition();
1199 
1200   LLVM_DEBUG(llvm::dbgs() << ">>> tryConversionOperators: " << RD->getName()
1201                           << " to:\n";
1202              ToType.dump(llvm::dbgs(), RD->getASTContext());
1203              llvm::dbgs() << '\n';);
1204 
1205   UserDefinedConversionSelector ConversionSet{Check};
1206 
1207   for (const NamedDecl *Method : RD->getVisibleConversionFunctions()) {
1208     const auto *Con = dyn_cast<CXXConversionDecl>(Method);
1209     if (!Con || Con->isExplicit())
1210       continue;
1211     LLVM_DEBUG(llvm::dbgs() << "--- tryConversionOperators. Trying:\n";
1212                Con->dump(llvm::dbgs()); llvm::dbgs() << '\n';);
1213 
1214     // Try to go from the result of conversion operator to the expected type,
1215     // without calculating another user-defined conversion.
1216     ConversionSet.addConversion(Con, Con->getConversionType(), ToType);
1217   }
1218 
1219   if (std::optional<UserDefinedConversionSelector::PreparedConversion>
1220           SelectedConversion = ConversionSet()) {
1221     QualType RecordType{RD->getTypeForDecl(), 0};
1222 
1223     ConversionSequence Result{RecordType, ToType};
1224     // The conversion from the operator call's return type to ToType was
1225     // modelled as a "pre-conversion" in the operator call, but it is the
1226     // "post-conversion" from the point of view of the original conversion
1227     // we are modelling.
1228     Result.AfterSecondStandard = SelectedConversion->Seq.AfterFirstStandard;
1229 
1230     ConversionSequence::UserDefinedConversionOperator ConvOp;
1231     ConvOp.Fun = cast<CXXConversionDecl>(SelectedConversion->ConversionFun);
1232     ConvOp.UserDefinedType = RecordType;
1233     ConvOp.ConversionOperatorResultType = ConvOp.Fun->getConversionType();
1234     Result.setConversion(ConvOp);
1235 
1236     LLVM_DEBUG(llvm::dbgs() << "<<< tryConversionOperators. Found result.\n");
1237     return Result;
1238   }
1239 
1240   LLVM_DEBUG(llvm::dbgs() << "<<< tryConversionOperators. No conversion.\n");
1241   return {};
1242 }
1243 
1244 static std::optional<ConversionSequence>
1245 tryConvertingConstructors(const TheCheck &Check, QualType FromType,
1246                           const CXXRecordDecl *RD) {
1247   if (!RD || !RD->isCompleteDefinition())
1248     return {};
1249   RD = RD->getDefinition();
1250 
1251   LLVM_DEBUG(llvm::dbgs() << ">>> tryConveringConstructors: " << RD->getName()
1252                           << " from:\n";
1253              FromType.dump(llvm::dbgs(), RD->getASTContext());
1254              llvm::dbgs() << '\n';);
1255 
1256   UserDefinedConversionSelector ConversionSet{Check};
1257 
1258   for (const CXXConstructorDecl *Con : RD->ctors()) {
1259     if (Con->isCopyOrMoveConstructor() ||
1260         !Con->isConvertingConstructor(/* AllowExplicit =*/false))
1261       continue;
1262     LLVM_DEBUG(llvm::dbgs() << "--- tryConvertingConstructors. Trying:\n";
1263                Con->dump(llvm::dbgs()); llvm::dbgs() << '\n';);
1264 
1265     // Try to go from the original FromType to the converting constructor's
1266     // parameter type without another user-defined conversion.
1267     ConversionSet.addConversion(Con, FromType, Con->getParamDecl(0)->getType());
1268   }
1269 
1270   if (std::optional<UserDefinedConversionSelector::PreparedConversion>
1271           SelectedConversion = ConversionSet()) {
1272     QualType RecordType{RD->getTypeForDecl(), 0};
1273 
1274     ConversionSequence Result{FromType, RecordType};
1275     Result.AfterFirstStandard = SelectedConversion->Seq.AfterFirstStandard;
1276 
1277     ConversionSequence::UserDefinedConvertingConstructor Ctor;
1278     Ctor.Fun = cast<CXXConstructorDecl>(SelectedConversion->ConversionFun);
1279     Ctor.ConstructorParameterType = Ctor.Fun->getParamDecl(0)->getType();
1280     Ctor.UserDefinedType = RecordType;
1281     Result.setConversion(Ctor);
1282 
1283     LLVM_DEBUG(llvm::dbgs()
1284                << "<<< tryConvertingConstructors. Found result.\n");
1285     return Result;
1286   }
1287 
1288   LLVM_DEBUG(llvm::dbgs() << "<<< tryConvertingConstructors. No conversion.\n");
1289   return {};
1290 }
1291 
1292 /// Returns whether an expression of LType can be used in an RType context, as
1293 /// per the implicit conversion rules.
1294 ///
1295 /// Note: the result of this operation, unlike that of calculateMixability, is
1296 /// **NOT** symmetric.
1297 static MixData
1298 approximateImplicitConversion(const TheCheck &Check, QualType LType,
1299                               QualType RType, const ASTContext &Ctx,
1300                               ImplicitConversionModellingMode ImplicitMode) {
1301   LLVM_DEBUG(llvm::dbgs() << ">>> approximateImplicitConversion for LType:\n";
1302              LType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand RType:\n";
1303              RType.dump(llvm::dbgs(), Ctx);
1304              llvm::dbgs() << "\nimplicit mode: "; switch (ImplicitMode) {
1305                case ImplicitConversionModellingMode::None:
1306                  llvm::dbgs() << "None";
1307                  break;
1308                case ImplicitConversionModellingMode::All:
1309                  llvm::dbgs() << "All";
1310                  break;
1311                case ImplicitConversionModellingMode::OneWaySingleStandardOnly:
1312                  llvm::dbgs() << "OneWay, Single, STD Only";
1313                  break;
1314              } llvm::dbgs() << '\n';);
1315   if (LType == RType)
1316     return {MixFlags::Trivial, LType};
1317 
1318   // An implicit conversion sequence consists of the following, in order:
1319   //  * Maybe standard conversion sequence.
1320   //  * Maybe user-defined conversion.
1321   //  * Maybe standard conversion sequence.
1322   ConversionSequence ImplicitSeq{LType, RType};
1323   QualType WorkType = LType;
1324 
1325   std::optional<QualType> AfterFirstStdConv =
1326       approximateStandardConversionSequence(Check, LType, RType, Ctx);
1327   if (AfterFirstStdConv) {
1328     LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Standard "
1329                                "Pre-Conversion found!\n");
1330     ImplicitSeq.AfterFirstStandard = *AfterFirstStdConv;
1331     WorkType = ImplicitSeq.AfterFirstStandard;
1332   }
1333 
1334   if (ImplicitMode == ImplicitConversionModellingMode::OneWaySingleStandardOnly)
1335     // If the caller only requested modelling of a standard conversion, bail.
1336     return {ImplicitSeq.AfterFirstStandard.isNull()
1337                 ? MixFlags::None
1338                 : MixFlags::ImplicitConversion,
1339             ImplicitSeq};
1340 
1341   if (Ctx.getLangOpts().CPlusPlus) {
1342     bool FoundConversionOperator = false, FoundConvertingCtor = false;
1343 
1344     if (const auto *LRD = WorkType->getAsCXXRecordDecl()) {
1345       std::optional<ConversionSequence> ConversionOperatorResult =
1346           tryConversionOperators(Check, LRD, RType);
1347       if (ConversionOperatorResult) {
1348         LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Found "
1349                                    "conversion operator.\n");
1350         ImplicitSeq.update(*ConversionOperatorResult);
1351         WorkType = ImplicitSeq.getTypeAfterUserDefinedConversion();
1352         FoundConversionOperator = true;
1353       }
1354     }
1355 
1356     if (const auto *RRD = RType->getAsCXXRecordDecl()) {
1357       // Use the original "LType" here, and not WorkType, because the
1358       // conversion to the converting constructors' parameters will be
1359       // modelled in the recursive call.
1360       std::optional<ConversionSequence> ConvCtorResult =
1361           tryConvertingConstructors(Check, LType, RRD);
1362       if (ConvCtorResult) {
1363         LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Found "
1364                                    "converting constructor.\n");
1365         ImplicitSeq.update(*ConvCtorResult);
1366         WorkType = ImplicitSeq.getTypeAfterUserDefinedConversion();
1367         FoundConvertingCtor = true;
1368       }
1369     }
1370 
1371     if (FoundConversionOperator && FoundConvertingCtor) {
1372       // If both an operator and a ctor matches, the sequence is ambiguous.
1373       LLVM_DEBUG(llvm::dbgs()
1374                  << "<<< approximateImplicitConversion. Found both "
1375                     "user-defined conversion kinds in the same sequence!\n");
1376       return {MixFlags::None};
1377     }
1378   }
1379 
1380   // After the potential user-defined conversion, another standard conversion
1381   // sequence might exist.
1382   LLVM_DEBUG(
1383       llvm::dbgs()
1384       << "--- approximateImplicitConversion. Try to find post-conversion.\n");
1385   MixData SecondStdConv = approximateImplicitConversion(
1386       Check, WorkType, RType, Ctx,
1387       ImplicitConversionModellingMode::OneWaySingleStandardOnly);
1388   if (SecondStdConv.indicatesMixability()) {
1389     LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Standard "
1390                                "Post-Conversion found!\n");
1391 
1392     // The single-step modelling puts the modelled conversion into the "PreStd"
1393     // variable in the recursive call, but from the PoV of this function, it is
1394     // the post-conversion.
1395     ImplicitSeq.AfterSecondStandard =
1396         SecondStdConv.Conversion.AfterFirstStandard;
1397     WorkType = ImplicitSeq.AfterSecondStandard;
1398   }
1399 
1400   if (ImplicitSeq) {
1401     LLVM_DEBUG(llvm::dbgs()
1402                << "<<< approximateImplicitConversion. Found a conversion.\n");
1403     return {MixFlags::ImplicitConversion, ImplicitSeq};
1404   }
1405 
1406   LLVM_DEBUG(
1407       llvm::dbgs() << "<<< approximateImplicitConversion. No match found.\n");
1408   return {MixFlags::None};
1409 }
1410 
1411 static MixableParameterRange modelMixingRange(
1412     const TheCheck &Check, const FunctionDecl *FD, std::size_t StartIndex,
1413     const filter::SimilarlyUsedParameterPairSuppressor &UsageBasedSuppressor) {
1414   std::size_t NumParams = FD->getNumParams();
1415   assert(StartIndex < NumParams && "out of bounds for start");
1416   const ASTContext &Ctx = FD->getASTContext();
1417 
1418   MixableParameterRange Ret;
1419   // A parameter at index 'StartIndex' had been trivially "checked".
1420   Ret.NumParamsChecked = 1;
1421 
1422   for (std::size_t I = StartIndex + 1; I < NumParams; ++I) {
1423     const ParmVarDecl *Ith = FD->getParamDecl(I);
1424     StringRef ParamName = Ith->getName();
1425     LLVM_DEBUG(llvm::dbgs()
1426                << "Check param #" << I << " '" << ParamName << "'...\n");
1427     if (filter::isIgnoredParameter(Check, Ith)) {
1428       LLVM_DEBUG(llvm::dbgs() << "Param #" << I << " is ignored. Break!\n");
1429       break;
1430     }
1431 
1432     StringRef PrevParamName = FD->getParamDecl(I - 1)->getName();
1433     if (!ParamName.empty() && !PrevParamName.empty() &&
1434         filter::prefixSuffixCoverUnderThreshold(
1435             Check.NamePrefixSuffixSilenceDissimilarityTreshold, PrevParamName,
1436             ParamName)) {
1437       LLVM_DEBUG(llvm::dbgs() << "Parameter '" << ParamName
1438                               << "' follows a pattern with previous parameter '"
1439                               << PrevParamName << "'. Break!\n");
1440       break;
1441     }
1442 
1443     // Now try to go forward and build the range of [Start, ..., I, I + 1, ...]
1444     // parameters that can be messed up at a call site.
1445     MixableParameterRange::MixVector MixesOfIth;
1446     for (std::size_t J = StartIndex; J < I; ++J) {
1447       const ParmVarDecl *Jth = FD->getParamDecl(J);
1448       LLVM_DEBUG(llvm::dbgs()
1449                  << "Check mix of #" << J << " against #" << I << "...\n");
1450 
1451       if (isSimilarlyUsedParameter(UsageBasedSuppressor, Ith, Jth)) {
1452         // Consider the two similarly used parameters to not be possible in a
1453         // mix-up at the user's request, if they enabled this heuristic.
1454         LLVM_DEBUG(llvm::dbgs() << "Parameters #" << I << " and #" << J
1455                                 << " deemed related, ignoring...\n");
1456 
1457         // If the parameter #I and #J mixes, then I is mixable with something
1458         // in the current range, so the range has to be broken and I not
1459         // included.
1460         MixesOfIth.clear();
1461         break;
1462       }
1463 
1464       Mix M{Jth, Ith,
1465             calculateMixability(Check, Jth->getType(), Ith->getType(), Ctx,
1466                                 Check.ModelImplicitConversions
1467                                     ? ImplicitConversionModellingMode::All
1468                                     : ImplicitConversionModellingMode::None)};
1469       LLVM_DEBUG(llvm::dbgs() << "Mix flags (raw)           : "
1470                               << formatMixFlags(M.flags()) << '\n');
1471       M.sanitize();
1472       LLVM_DEBUG(llvm::dbgs() << "Mix flags (after sanitize): "
1473                               << formatMixFlags(M.flags()) << '\n');
1474 
1475       assert(M.flagsValid() && "All flags decayed!");
1476 
1477       if (M.mixable())
1478         MixesOfIth.emplace_back(std::move(M));
1479     }
1480 
1481     if (MixesOfIth.empty()) {
1482       // If there weren't any new mixes stored for Ith, the range is
1483       // [Start, ..., I].
1484       LLVM_DEBUG(llvm::dbgs()
1485                  << "Param #" << I
1486                  << " does not mix with any in the current range. Break!\n");
1487       break;
1488     }
1489 
1490     Ret.Mixes.insert(Ret.Mixes.end(), MixesOfIth.begin(), MixesOfIth.end());
1491     ++Ret.NumParamsChecked; // Otherwise a new param was iterated.
1492   }
1493 
1494   return Ret;
1495 }
1496 
1497 } // namespace model
1498 
1499 /// Matches DeclRefExprs and their ignorable wrappers to ParmVarDecls.
1500 AST_MATCHER_FUNCTION(ast_matchers::internal::Matcher<Stmt>, paramRefExpr) {
1501   return expr(ignoringParenImpCasts(ignoringElidableConstructorCall(
1502       declRefExpr(to(parmVarDecl().bind("param"))))));
1503 }
1504 
1505 namespace filter {
1506 
1507 /// Returns whether the parameter's name or the parameter's type's name is
1508 /// configured by the user to be ignored from analysis and diagnostic.
1509 static bool isIgnoredParameter(const TheCheck &Check, const ParmVarDecl *Node) {
1510   LLVM_DEBUG(llvm::dbgs() << "Checking if '" << Node->getName()
1511                           << "' is ignored.\n");
1512 
1513   if (!Node->getIdentifier())
1514     return llvm::is_contained(Check.IgnoredParameterNames, "\"\"");
1515 
1516   StringRef NodeName = Node->getName();
1517   if (llvm::is_contained(Check.IgnoredParameterNames, NodeName)) {
1518     LLVM_DEBUG(llvm::dbgs() << "\tName ignored.\n");
1519     return true;
1520   }
1521 
1522   StringRef NodeTypeName = [Node] {
1523     const ASTContext &Ctx = Node->getASTContext();
1524     const SourceManager &SM = Ctx.getSourceManager();
1525     SourceLocation B = Node->getTypeSpecStartLoc();
1526     SourceLocation E = Node->getTypeSpecEndLoc();
1527     LangOptions LO;
1528 
1529     LLVM_DEBUG(llvm::dbgs() << "\tType name code is '"
1530                             << Lexer::getSourceText(
1531                                    CharSourceRange::getTokenRange(B, E), SM, LO)
1532                             << "'...\n");
1533     if (B.isMacroID()) {
1534       LLVM_DEBUG(llvm::dbgs() << "\t\tBeginning is macro.\n");
1535       B = SM.getTopMacroCallerLoc(B);
1536     }
1537     if (E.isMacroID()) {
1538       LLVM_DEBUG(llvm::dbgs() << "\t\tEnding is macro.\n");
1539       E = Lexer::getLocForEndOfToken(SM.getTopMacroCallerLoc(E), 0, SM, LO);
1540     }
1541     LLVM_DEBUG(llvm::dbgs() << "\tType name code is '"
1542                             << Lexer::getSourceText(
1543                                    CharSourceRange::getTokenRange(B, E), SM, LO)
1544                             << "'...\n");
1545 
1546     return Lexer::getSourceText(CharSourceRange::getTokenRange(B, E), SM, LO);
1547   }();
1548 
1549   LLVM_DEBUG(llvm::dbgs() << "\tType name is '" << NodeTypeName << "'\n");
1550   if (!NodeTypeName.empty()) {
1551     if (llvm::any_of(Check.IgnoredParameterTypeSuffixes,
1552                      [NodeTypeName](StringRef E) {
1553                        return !E.empty() && NodeTypeName.ends_with(E);
1554                      })) {
1555       LLVM_DEBUG(llvm::dbgs() << "\tType suffix ignored.\n");
1556       return true;
1557     }
1558   }
1559 
1560   return false;
1561 }
1562 
1563 /// This namespace contains the implementations for the suppression of
1564 /// diagnostics from similarly-used ("related") parameters.
1565 namespace relatedness_heuristic {
1566 
1567 static constexpr std::size_t SmallDataStructureSize = 4;
1568 
1569 template <typename T, std::size_t N = SmallDataStructureSize>
1570 using ParamToSmallSetMap =
1571     llvm::DenseMap<const ParmVarDecl *, llvm::SmallSet<T, N>>;
1572 
1573 /// Returns whether the sets mapped to the two elements in the map have at
1574 /// least one element in common.
1575 template <typename MapTy, typename ElemTy>
1576 bool lazyMapOfSetsIntersectionExists(const MapTy &Map, const ElemTy &E1,
1577                                      const ElemTy &E2) {
1578   auto E1Iterator = Map.find(E1);
1579   auto E2Iterator = Map.find(E2);
1580   if (E1Iterator == Map.end() || E2Iterator == Map.end())
1581     return false;
1582 
1583   for (const auto &E1SetElem : E1Iterator->second)
1584     if (E2Iterator->second.contains(E1SetElem))
1585       return true;
1586 
1587   return false;
1588 }
1589 
1590 /// Implements the heuristic that marks two parameters related if there is
1591 /// a usage for both in the same strict expression subtree. A strict
1592 /// expression subtree is a tree which only includes Expr nodes, i.e. no
1593 /// Stmts and no Decls.
1594 class AppearsInSameExpr : public RecursiveASTVisitor<AppearsInSameExpr> {
1595   using Base = RecursiveASTVisitor<AppearsInSameExpr>;
1596 
1597   const FunctionDecl *FD;
1598   const Expr *CurrentExprOnlyTreeRoot = nullptr;
1599   llvm::DenseMap<const ParmVarDecl *,
1600                  llvm::SmallPtrSet<const Expr *, SmallDataStructureSize>>
1601       ParentExprsForParamRefs;
1602 
1603 public:
1604   void setup(const FunctionDecl *FD) {
1605     this->FD = FD;
1606     TraverseFunctionDecl(const_cast<FunctionDecl *>(FD));
1607   }
1608 
1609   bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
1610     return lazyMapOfSetsIntersectionExists(ParentExprsForParamRefs, Param1,
1611                                            Param2);
1612   }
1613 
1614   bool TraverseDecl(Decl *D) {
1615     CurrentExprOnlyTreeRoot = nullptr;
1616     return Base::TraverseDecl(D);
1617   }
1618 
1619   bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr) {
1620     if (auto *E = dyn_cast_or_null<Expr>(S)) {
1621       bool RootSetInCurrentStackFrame = false;
1622       if (!CurrentExprOnlyTreeRoot) {
1623         CurrentExprOnlyTreeRoot = E;
1624         RootSetInCurrentStackFrame = true;
1625       }
1626 
1627       bool Ret = Base::TraverseStmt(S);
1628 
1629       if (RootSetInCurrentStackFrame)
1630         CurrentExprOnlyTreeRoot = nullptr;
1631 
1632       return Ret;
1633     }
1634 
1635     // A Stmt breaks the strictly Expr subtree.
1636     CurrentExprOnlyTreeRoot = nullptr;
1637     return Base::TraverseStmt(S);
1638   }
1639 
1640   bool VisitDeclRefExpr(DeclRefExpr *DRE) {
1641     if (!CurrentExprOnlyTreeRoot)
1642       return true;
1643 
1644     if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
1645       if (llvm::find(FD->parameters(), PVD))
1646         ParentExprsForParamRefs[PVD].insert(CurrentExprOnlyTreeRoot);
1647 
1648     return true;
1649   }
1650 };
1651 
1652 /// Implements the heuristic that marks two parameters related if there are
1653 /// two separate calls to the same function (overload) and the parameters are
1654 /// passed to the same index in both calls, i.e f(a, b) and f(a, c) passes
1655 /// b and c to the same index (2) of f(), marking them related.
1656 class PassedToSameFunction {
1657   ParamToSmallSetMap<std::pair<const FunctionDecl *, unsigned>> TargetParams;
1658 
1659 public:
1660   void setup(const FunctionDecl *FD) {
1661     auto ParamsAsArgsInFnCalls =
1662         match(functionDecl(forEachDescendant(
1663                   callExpr(forEachArgumentWithParam(
1664                                paramRefExpr(), parmVarDecl().bind("passed-to")))
1665                       .bind("call-expr"))),
1666               *FD, FD->getASTContext());
1667     for (const auto &Match : ParamsAsArgsInFnCalls) {
1668       const auto *PassedParamOfThisFn = Match.getNodeAs<ParmVarDecl>("param");
1669       const auto *CE = Match.getNodeAs<CallExpr>("call-expr");
1670       const auto *PassedToParam = Match.getNodeAs<ParmVarDecl>("passed-to");
1671       assert(PassedParamOfThisFn && CE && PassedToParam);
1672 
1673       const FunctionDecl *CalledFn = CE->getDirectCallee();
1674       if (!CalledFn)
1675         continue;
1676 
1677       std::optional<unsigned> TargetIdx;
1678       unsigned NumFnParams = CalledFn->getNumParams();
1679       for (unsigned Idx = 0; Idx < NumFnParams; ++Idx)
1680         if (CalledFn->getParamDecl(Idx) == PassedToParam)
1681           TargetIdx.emplace(Idx);
1682 
1683       assert(TargetIdx && "Matched, but didn't find index?");
1684       TargetParams[PassedParamOfThisFn].insert(
1685           {CalledFn->getCanonicalDecl(), *TargetIdx});
1686     }
1687   }
1688 
1689   bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
1690     return lazyMapOfSetsIntersectionExists(TargetParams, Param1, Param2);
1691   }
1692 };
1693 
1694 /// Implements the heuristic that marks two parameters related if the same
1695 /// member is accessed (referred to) inside the current function's body.
1696 class AccessedSameMemberOf {
1697   ParamToSmallSetMap<const Decl *> AccessedMembers;
1698 
1699 public:
1700   void setup(const FunctionDecl *FD) {
1701     auto MembersCalledOnParams = match(
1702         functionDecl(forEachDescendant(
1703             memberExpr(hasObjectExpression(paramRefExpr())).bind("mem-expr"))),
1704         *FD, FD->getASTContext());
1705 
1706     for (const auto &Match : MembersCalledOnParams) {
1707       const auto *AccessedParam = Match.getNodeAs<ParmVarDecl>("param");
1708       const auto *ME = Match.getNodeAs<MemberExpr>("mem-expr");
1709       assert(AccessedParam && ME);
1710       AccessedMembers[AccessedParam].insert(
1711           ME->getMemberDecl()->getCanonicalDecl());
1712     }
1713   }
1714 
1715   bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
1716     return lazyMapOfSetsIntersectionExists(AccessedMembers, Param1, Param2);
1717   }
1718 };
1719 
1720 /// Implements the heuristic that marks two parameters related if different
1721 /// ReturnStmts return them from the function.
1722 class Returned {
1723   llvm::SmallVector<const ParmVarDecl *, SmallDataStructureSize> ReturnedParams;
1724 
1725 public:
1726   void setup(const FunctionDecl *FD) {
1727     // TODO: Handle co_return.
1728     auto ParamReturns = match(functionDecl(forEachDescendant(
1729                                   returnStmt(hasReturnValue(paramRefExpr())))),
1730                               *FD, FD->getASTContext());
1731     for (const auto &Match : ParamReturns) {
1732       const auto *ReturnedParam = Match.getNodeAs<ParmVarDecl>("param");
1733       assert(ReturnedParam);
1734 
1735       if (find(FD->parameters(), ReturnedParam) == FD->param_end())
1736         // Inside the subtree of a FunctionDecl there might be ReturnStmts of
1737         // a parameter that isn't the parameter of the function, e.g. in the
1738         // case of lambdas.
1739         continue;
1740 
1741       ReturnedParams.emplace_back(ReturnedParam);
1742     }
1743   }
1744 
1745   bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
1746     return llvm::is_contained(ReturnedParams, Param1) &&
1747            llvm::is_contained(ReturnedParams, Param2);
1748   }
1749 };
1750 
1751 } // namespace relatedness_heuristic
1752 
1753 /// Helper class that is used to detect if two parameters of the same function
1754 /// are used in a similar fashion, to suppress the result.
1755 class SimilarlyUsedParameterPairSuppressor {
1756   const bool Enabled;
1757   relatedness_heuristic::AppearsInSameExpr SameExpr;
1758   relatedness_heuristic::PassedToSameFunction PassToFun;
1759   relatedness_heuristic::AccessedSameMemberOf SameMember;
1760   relatedness_heuristic::Returned Returns;
1761 
1762 public:
1763   SimilarlyUsedParameterPairSuppressor(const FunctionDecl *FD, bool Enable)
1764       : Enabled(Enable) {
1765     if (!Enable)
1766       return;
1767 
1768     SameExpr.setup(FD);
1769     PassToFun.setup(FD);
1770     SameMember.setup(FD);
1771     Returns.setup(FD);
1772   }
1773 
1774   /// Returns whether the specified two parameters are deemed similarly used
1775   /// or related by the heuristics.
1776   bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
1777     if (!Enabled)
1778       return false;
1779 
1780     LLVM_DEBUG(llvm::dbgs()
1781                << "::: Matching similar usage / relatedness heuristic...\n");
1782 
1783     if (SameExpr(Param1, Param2)) {
1784       LLVM_DEBUG(llvm::dbgs() << "::: Used in the same expression.\n");
1785       return true;
1786     }
1787 
1788     if (PassToFun(Param1, Param2)) {
1789       LLVM_DEBUG(llvm::dbgs()
1790                  << "::: Passed to same function in different calls.\n");
1791       return true;
1792     }
1793 
1794     if (SameMember(Param1, Param2)) {
1795       LLVM_DEBUG(llvm::dbgs()
1796                  << "::: Same member field access or method called.\n");
1797       return true;
1798     }
1799 
1800     if (Returns(Param1, Param2)) {
1801       LLVM_DEBUG(llvm::dbgs() << "::: Both parameter returned.\n");
1802       return true;
1803     }
1804 
1805     LLVM_DEBUG(llvm::dbgs() << "::: None.\n");
1806     return false;
1807   }
1808 };
1809 
1810 // (This function hoists the call to operator() of the wrapper, so we do not
1811 // need to define the previous class at the top of the file.)
1812 static inline bool
1813 isSimilarlyUsedParameter(const SimilarlyUsedParameterPairSuppressor &Suppressor,
1814                          const ParmVarDecl *Param1, const ParmVarDecl *Param2) {
1815   return Suppressor(Param1, Param2);
1816 }
1817 
1818 static void padStringAtEnd(SmallVectorImpl<char> &Str, std::size_t ToLen) {
1819   while (Str.size() < ToLen)
1820     Str.emplace_back('\0');
1821 }
1822 
1823 static void padStringAtBegin(SmallVectorImpl<char> &Str, std::size_t ToLen) {
1824   while (Str.size() < ToLen)
1825     Str.insert(Str.begin(), '\0');
1826 }
1827 
1828 static bool isCommonPrefixWithoutSomeCharacters(std::size_t N, StringRef S1,
1829                                                 StringRef S2) {
1830   assert(S1.size() >= N && S2.size() >= N);
1831   StringRef S1Prefix = S1.take_front(S1.size() - N),
1832             S2Prefix = S2.take_front(S2.size() - N);
1833   return S1Prefix == S2Prefix && !S1Prefix.empty();
1834 }
1835 
1836 static bool isCommonSuffixWithoutSomeCharacters(std::size_t N, StringRef S1,
1837                                                 StringRef S2) {
1838   assert(S1.size() >= N && S2.size() >= N);
1839   StringRef S1Suffix = S1.take_back(S1.size() - N),
1840             S2Suffix = S2.take_back(S2.size() - N);
1841   return S1Suffix == S2Suffix && !S1Suffix.empty();
1842 }
1843 
1844 /// Returns whether the two strings are prefixes or suffixes of each other with
1845 /// at most Threshold characters differing on the non-common end.
1846 static bool prefixSuffixCoverUnderThreshold(std::size_t Threshold,
1847                                             StringRef Str1, StringRef Str2) {
1848   if (Threshold == 0)
1849     return false;
1850 
1851   // Pad the two strings to the longer length.
1852   std::size_t BiggerLength = std::max(Str1.size(), Str2.size());
1853 
1854   if (BiggerLength <= Threshold)
1855     // If the length of the strings is still smaller than the threshold, they
1856     // would be covered by an empty prefix/suffix with the rest differing.
1857     // (E.g. "A" and "X" with Threshold = 1 would mean we think they are
1858     // similar and do not warn about them, which is a too eager assumption.)
1859     return false;
1860 
1861   SmallString<32> S1PadE{Str1}, S2PadE{Str2};
1862   padStringAtEnd(S1PadE, BiggerLength);
1863   padStringAtEnd(S2PadE, BiggerLength);
1864 
1865   if (isCommonPrefixWithoutSomeCharacters(
1866           Threshold, StringRef{S1PadE.begin(), BiggerLength},
1867           StringRef{S2PadE.begin(), BiggerLength}))
1868     return true;
1869 
1870   SmallString<32> S1PadB{Str1}, S2PadB{Str2};
1871   padStringAtBegin(S1PadB, BiggerLength);
1872   padStringAtBegin(S2PadB, BiggerLength);
1873 
1874   if (isCommonSuffixWithoutSomeCharacters(
1875           Threshold, StringRef{S1PadB.begin(), BiggerLength},
1876           StringRef{S2PadB.begin(), BiggerLength}))
1877     return true;
1878 
1879   return false;
1880 }
1881 
1882 } // namespace filter
1883 
1884 /// Matches functions that have at least the specified amount of parameters.
1885 AST_MATCHER_P(FunctionDecl, parameterCountGE, unsigned, N) {
1886   return Node.getNumParams() >= N;
1887 }
1888 
1889 /// Matches *any* overloaded unary and binary operators.
1890 AST_MATCHER(FunctionDecl, isOverloadedUnaryOrBinaryOperator) {
1891   switch (Node.getOverloadedOperator()) {
1892   case OO_None:
1893   case OO_New:
1894   case OO_Delete:
1895   case OO_Array_New:
1896   case OO_Array_Delete:
1897   case OO_Conditional:
1898   case OO_Coawait:
1899     return false;
1900 
1901   default:
1902     return Node.getNumParams() <= 2;
1903   }
1904 }
1905 
1906 /// Returns the DefaultMinimumLength if the Value of requested minimum length
1907 /// is less than 2. Minimum lengths of 0 or 1 are not accepted.
1908 static inline unsigned clampMinimumLength(const unsigned Value) {
1909   return Value < 2 ? DefaultMinimumLength : Value;
1910 }
1911 
1912 // FIXME: Maybe unneeded, getNameForDiagnostic() is expected to change to return
1913 // a crafted location when the node itself is unnamed. (See D84658, D85033.)
1914 /// Returns the diagnostic-friendly name of the node, or empty string.
1915 static SmallString<64> getName(const NamedDecl *ND) {
1916   SmallString<64> Name;
1917   llvm::raw_svector_ostream OS{Name};
1918   ND->getNameForDiagnostic(OS, ND->getASTContext().getPrintingPolicy(), false);
1919   return Name;
1920 }
1921 
1922 /// Returns the diagnostic-friendly name of the node, or a constant value.
1923 static SmallString<64> getNameOrUnnamed(const NamedDecl *ND) {
1924   auto Name = getName(ND);
1925   if (Name.empty())
1926     Name = "<unnamed>";
1927   return Name;
1928 }
1929 
1930 /// Returns whether a particular Mix between two parameters should have the
1931 /// types involved diagnosed to the user. This is only a flag check.
1932 static inline bool needsToPrintTypeInDiagnostic(const model::Mix &M) {
1933   using namespace model;
1934   return static_cast<bool>(
1935       M.flags() &
1936       (MixFlags::TypeAlias | MixFlags::ReferenceBind | MixFlags::Qualifiers));
1937 }
1938 
1939 /// Returns whether a particular Mix between the two parameters should have
1940 /// implicit conversions elaborated.
1941 static inline bool needsToElaborateImplicitConversion(const model::Mix &M) {
1942   return hasFlag(M.flags(), model::MixFlags::ImplicitConversion);
1943 }
1944 
1945 namespace {
1946 
1947 /// This class formats a conversion sequence into a "Ty1 -> Ty2 -> Ty3" line
1948 /// that can be used in diagnostics.
1949 struct FormattedConversionSequence {
1950   std::string DiagnosticText;
1951 
1952   /// The formatted sequence is trivial if it is "Ty1 -> Ty2", but Ty1 and
1953   /// Ty2 are the types that are shown in the code. A trivial diagnostic
1954   /// does not need to be printed.
1955   bool Trivial = true;
1956 
1957   FormattedConversionSequence(const PrintingPolicy &PP,
1958                               StringRef StartTypeAsDiagnosed,
1959                               const model::ConversionSequence &Conv,
1960                               StringRef DestinationTypeAsDiagnosed) {
1961     llvm::raw_string_ostream OS{DiagnosticText};
1962 
1963     // Print the type name as it is printed in other places in the diagnostic.
1964     OS << '\'' << StartTypeAsDiagnosed << '\'';
1965     std::string LastAddedType = StartTypeAsDiagnosed.str();
1966     std::size_t NumElementsAdded = 1;
1967 
1968     // However, the parameter's defined type might not be what the implicit
1969     // conversion started with, e.g. if a typedef is found to convert.
1970     std::string SeqBeginTypeStr = Conv.Begin.getAsString(PP);
1971     std::string SeqEndTypeStr = Conv.End.getAsString(PP);
1972     if (StartTypeAsDiagnosed != SeqBeginTypeStr) {
1973       OS << " (as '" << SeqBeginTypeStr << "')";
1974       LastAddedType = SeqBeginTypeStr;
1975       Trivial = false;
1976     }
1977 
1978     auto AddType = [&](StringRef ToAdd) {
1979       if (LastAddedType != ToAdd && ToAdd != SeqEndTypeStr) {
1980         OS << " -> '" << ToAdd << "'";
1981         LastAddedType = ToAdd.str();
1982         ++NumElementsAdded;
1983       }
1984     };
1985     for (QualType InvolvedType : Conv.getInvolvedTypesInSequence())
1986       // Print every type that's unique in the sequence into the diagnosis.
1987       AddType(InvolvedType.getAsString(PP));
1988 
1989     if (LastAddedType != DestinationTypeAsDiagnosed) {
1990       OS << " -> '" << DestinationTypeAsDiagnosed << "'";
1991       LastAddedType = DestinationTypeAsDiagnosed.str();
1992       ++NumElementsAdded;
1993     }
1994 
1995     // Same reasoning as with the Begin, e.g. if the converted-to type is a
1996     // typedef, it will not be the same inside the conversion sequence (where
1997     // the model already tore off typedefs) as in the code.
1998     if (DestinationTypeAsDiagnosed != SeqEndTypeStr) {
1999       OS << " (as '" << SeqEndTypeStr << "')";
2000       LastAddedType = SeqEndTypeStr;
2001       Trivial = false;
2002     }
2003 
2004     if (Trivial && NumElementsAdded > 2)
2005       // If the thing is still marked trivial but we have more than the
2006       // from and to types added, it should not be trivial, and elaborated
2007       // when printing the diagnostic.
2008       Trivial = false;
2009   }
2010 };
2011 
2012 /// Retains the elements called with and returns whether the call is done with
2013 /// a new element.
2014 template <typename E, std::size_t N> class InsertOnce {
2015   llvm::SmallSet<E, N> CalledWith;
2016 
2017 public:
2018   bool operator()(E El) { return CalledWith.insert(std::move(El)).second; }
2019 
2020   bool calledWith(const E &El) const { return CalledWith.contains(El); }
2021 };
2022 
2023 struct SwappedEqualQualTypePair {
2024   QualType LHSType, RHSType;
2025 
2026   bool operator==(const SwappedEqualQualTypePair &Other) const {
2027     return (LHSType == Other.LHSType && RHSType == Other.RHSType) ||
2028            (LHSType == Other.RHSType && RHSType == Other.LHSType);
2029   }
2030 
2031   bool operator<(const SwappedEqualQualTypePair &Other) const {
2032     return LHSType < Other.LHSType && RHSType < Other.RHSType;
2033   }
2034 };
2035 
2036 struct TypeAliasDiagnosticTuple {
2037   QualType LHSType, RHSType, CommonType;
2038 
2039   bool operator==(const TypeAliasDiagnosticTuple &Other) const {
2040     return CommonType == Other.CommonType &&
2041            ((LHSType == Other.LHSType && RHSType == Other.RHSType) ||
2042             (LHSType == Other.RHSType && RHSType == Other.LHSType));
2043   }
2044 
2045   bool operator<(const TypeAliasDiagnosticTuple &Other) const {
2046     return CommonType < Other.CommonType && LHSType < Other.LHSType &&
2047            RHSType < Other.RHSType;
2048   }
2049 };
2050 
2051 /// Helper class to only emit a diagnostic related to MixFlags::TypeAlias once.
2052 class UniqueTypeAliasDiagnosticHelper
2053     : public InsertOnce<TypeAliasDiagnosticTuple, 8> {
2054   using Base = InsertOnce<TypeAliasDiagnosticTuple, 8>;
2055 
2056 public:
2057   /// Returns whether the diagnostic for LHSType and RHSType which are both
2058   /// referring to CommonType being the same has not been emitted already.
2059   bool operator()(QualType LHSType, QualType RHSType, QualType CommonType) {
2060     if (CommonType.isNull() || CommonType == LHSType || CommonType == RHSType)
2061       return Base::operator()({LHSType, RHSType, {}});
2062 
2063     TypeAliasDiagnosticTuple ThreeTuple{LHSType, RHSType, CommonType};
2064     if (!Base::operator()(ThreeTuple))
2065       return false;
2066 
2067     bool AlreadySaidLHSAndCommonIsSame = calledWith({LHSType, CommonType, {}});
2068     bool AlreadySaidRHSAndCommonIsSame = calledWith({RHSType, CommonType, {}});
2069     if (AlreadySaidLHSAndCommonIsSame && AlreadySaidRHSAndCommonIsSame) {
2070       // "SomeInt == int" && "SomeOtherInt == int" => "Common(SomeInt,
2071       // SomeOtherInt) == int", no need to diagnose it. Save the 3-tuple only
2072       // for shortcut if it ever appears again.
2073       return false;
2074     }
2075 
2076     return true;
2077   }
2078 };
2079 
2080 } // namespace
2081 
2082 EasilySwappableParametersCheck::EasilySwappableParametersCheck(
2083     StringRef Name, ClangTidyContext *Context)
2084     : ClangTidyCheck(Name, Context),
2085       MinimumLength(clampMinimumLength(
2086           Options.get("MinimumLength", DefaultMinimumLength))),
2087       IgnoredParameterNames(optutils::parseStringList(
2088           Options.get("IgnoredParameterNames", DefaultIgnoredParameterNames))),
2089       IgnoredParameterTypeSuffixes(optutils::parseStringList(
2090           Options.get("IgnoredParameterTypeSuffixes",
2091                       DefaultIgnoredParameterTypeSuffixes))),
2092       QualifiersMix(Options.get("QualifiersMix", DefaultQualifiersMix)),
2093       ModelImplicitConversions(Options.get("ModelImplicitConversions",
2094                                            DefaultModelImplicitConversions)),
2095       SuppressParametersUsedTogether(
2096           Options.get("SuppressParametersUsedTogether",
2097                       DefaultSuppressParametersUsedTogether)),
2098       NamePrefixSuffixSilenceDissimilarityTreshold(
2099           Options.get("NamePrefixSuffixSilenceDissimilarityTreshold",
2100                       DefaultNamePrefixSuffixSilenceDissimilarityTreshold)) {}
2101 
2102 void EasilySwappableParametersCheck::storeOptions(
2103     ClangTidyOptions::OptionMap &Opts) {
2104   Options.store(Opts, "MinimumLength", MinimumLength);
2105   Options.store(Opts, "IgnoredParameterNames",
2106                 optutils::serializeStringList(IgnoredParameterNames));
2107   Options.store(Opts, "IgnoredParameterTypeSuffixes",
2108                 optutils::serializeStringList(IgnoredParameterTypeSuffixes));
2109   Options.store(Opts, "QualifiersMix", QualifiersMix);
2110   Options.store(Opts, "ModelImplicitConversions", ModelImplicitConversions);
2111   Options.store(Opts, "SuppressParametersUsedTogether",
2112                 SuppressParametersUsedTogether);
2113   Options.store(Opts, "NamePrefixSuffixSilenceDissimilarityTreshold",
2114                 NamePrefixSuffixSilenceDissimilarityTreshold);
2115 }
2116 
2117 void EasilySwappableParametersCheck::registerMatchers(MatchFinder *Finder) {
2118   const auto BaseConstraints = functionDecl(
2119       // Only report for definition nodes, as fixing the issues reported
2120       // requires the user to be able to change code.
2121       isDefinition(), parameterCountGE(MinimumLength),
2122       unless(isOverloadedUnaryOrBinaryOperator()));
2123 
2124   Finder->addMatcher(
2125       functionDecl(BaseConstraints,
2126                    unless(ast_matchers::isTemplateInstantiation()))
2127           .bind("func"),
2128       this);
2129   Finder->addMatcher(
2130       functionDecl(BaseConstraints, isExplicitTemplateSpecialization())
2131           .bind("func"),
2132       this);
2133 }
2134 
2135 void EasilySwappableParametersCheck::check(
2136     const MatchFinder::MatchResult &Result) {
2137   using namespace model;
2138   using namespace filter;
2139 
2140   const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("func");
2141   assert(FD);
2142 
2143   const PrintingPolicy &PP = FD->getASTContext().getPrintingPolicy();
2144   std::size_t NumParams = FD->getNumParams();
2145   std::size_t MixableRangeStartIndex = 0;
2146 
2147   // Spawn one suppressor and if the user requested, gather information from
2148   // the AST for the parameters' usages.
2149   filter::SimilarlyUsedParameterPairSuppressor UsageBasedSuppressor{
2150       FD, SuppressParametersUsedTogether};
2151 
2152   LLVM_DEBUG(llvm::dbgs() << "Begin analysis of " << getName(FD) << " with "
2153                           << NumParams << " parameters...\n");
2154   while (MixableRangeStartIndex < NumParams) {
2155     if (isIgnoredParameter(*this, FD->getParamDecl(MixableRangeStartIndex))) {
2156       LLVM_DEBUG(llvm::dbgs()
2157                  << "Parameter #" << MixableRangeStartIndex << " ignored.\n");
2158       ++MixableRangeStartIndex;
2159       continue;
2160     }
2161 
2162     MixableParameterRange R = modelMixingRange(
2163         *this, FD, MixableRangeStartIndex, UsageBasedSuppressor);
2164     assert(R.NumParamsChecked > 0 && "Ensure forward progress!");
2165     MixableRangeStartIndex += R.NumParamsChecked;
2166     if (R.NumParamsChecked < MinimumLength) {
2167       LLVM_DEBUG(llvm::dbgs() << "Ignoring range of " << R.NumParamsChecked
2168                               << " lower than limit.\n");
2169       continue;
2170     }
2171 
2172     bool NeedsAnyTypeNote = llvm::any_of(R.Mixes, needsToPrintTypeInDiagnostic);
2173     bool HasAnyImplicits =
2174         llvm::any_of(R.Mixes, needsToElaborateImplicitConversion);
2175     const ParmVarDecl *First = R.getFirstParam(), *Last = R.getLastParam();
2176     std::string FirstParamTypeAsWritten = First->getType().getAsString(PP);
2177     {
2178       StringRef DiagText;
2179 
2180       if (HasAnyImplicits)
2181         DiagText = "%0 adjacent parameters of %1 of convertible types are "
2182                    "easily swapped by mistake";
2183       else if (NeedsAnyTypeNote)
2184         DiagText = "%0 adjacent parameters of %1 of similar type are easily "
2185                    "swapped by mistake";
2186       else
2187         DiagText = "%0 adjacent parameters of %1 of similar type ('%2') are "
2188                    "easily swapped by mistake";
2189 
2190       auto Diag = diag(First->getOuterLocStart(), DiagText)
2191                   << static_cast<unsigned>(R.NumParamsChecked) << FD;
2192       if (!NeedsAnyTypeNote)
2193         Diag << FirstParamTypeAsWritten;
2194 
2195       CharSourceRange HighlightRange = CharSourceRange::getTokenRange(
2196           First->getBeginLoc(), Last->getEndLoc());
2197       Diag << HighlightRange;
2198     }
2199 
2200     // There is a chance that the previous highlight did not succeed, e.g. when
2201     // the two parameters are on different lines. For clarity, show the user
2202     // the involved variable explicitly.
2203     diag(First->getLocation(), "the first parameter in the range is '%0'",
2204          DiagnosticIDs::Note)
2205         << getNameOrUnnamed(First)
2206         << CharSourceRange::getTokenRange(First->getLocation(),
2207                                           First->getLocation());
2208     diag(Last->getLocation(), "the last parameter in the range is '%0'",
2209          DiagnosticIDs::Note)
2210         << getNameOrUnnamed(Last)
2211         << CharSourceRange::getTokenRange(Last->getLocation(),
2212                                           Last->getLocation());
2213 
2214     // Helper classes to silence elaborative diagnostic notes that would be
2215     // too verbose.
2216     UniqueTypeAliasDiagnosticHelper UniqueTypeAlias;
2217     InsertOnce<SwappedEqualQualTypePair, 8> UniqueBindPower;
2218     InsertOnce<SwappedEqualQualTypePair, 8> UniqueImplicitConversion;
2219 
2220     for (const model::Mix &M : R.Mixes) {
2221       assert(M.mixable() && "Sentinel or false mix in result.");
2222       if (!needsToPrintTypeInDiagnostic(M) &&
2223           !needsToElaborateImplicitConversion(M))
2224         continue;
2225 
2226       // Typedefs might result in the type of the variable needing to be
2227       // emitted to a note diagnostic, so prepare it.
2228       const ParmVarDecl *LVar = M.First;
2229       const ParmVarDecl *RVar = M.Second;
2230       QualType LType = LVar->getType();
2231       QualType RType = RVar->getType();
2232       QualType CommonType = M.commonUnderlyingType();
2233       std::string LTypeStr = LType.getAsString(PP);
2234       std::string RTypeStr = RType.getAsString(PP);
2235       std::string CommonTypeStr = CommonType.getAsString(PP);
2236 
2237       if (hasFlag(M.flags(), MixFlags::TypeAlias) &&
2238           UniqueTypeAlias(LType, RType, CommonType)) {
2239         StringRef DiagText;
2240         bool ExplicitlyPrintCommonType = false;
2241         if (LTypeStr == CommonTypeStr || RTypeStr == CommonTypeStr) {
2242           if (hasFlag(M.flags(), MixFlags::Qualifiers))
2243             DiagText = "after resolving type aliases, '%0' and '%1' share a "
2244                        "common type";
2245           else
2246             DiagText =
2247                 "after resolving type aliases, '%0' and '%1' are the same";
2248         } else if (!CommonType.isNull()) {
2249           DiagText = "after resolving type aliases, the common type of '%0' "
2250                      "and '%1' is '%2'";
2251           ExplicitlyPrintCommonType = true;
2252         }
2253 
2254         auto Diag =
2255             diag(LVar->getOuterLocStart(), DiagText, DiagnosticIDs::Note)
2256             << LTypeStr << RTypeStr;
2257         if (ExplicitlyPrintCommonType)
2258           Diag << CommonTypeStr;
2259       }
2260 
2261       if ((hasFlag(M.flags(), MixFlags::ReferenceBind) ||
2262            hasFlag(M.flags(), MixFlags::Qualifiers)) &&
2263           UniqueBindPower({LType, RType})) {
2264         StringRef DiagText = "'%0' and '%1' parameters accept and bind the "
2265                              "same kind of values";
2266         diag(RVar->getOuterLocStart(), DiagText, DiagnosticIDs::Note)
2267             << LTypeStr << RTypeStr;
2268       }
2269 
2270       if (needsToElaborateImplicitConversion(M) &&
2271           UniqueImplicitConversion({LType, RType})) {
2272         const model::ConversionSequence &LTR =
2273             M.leftToRightConversionSequence();
2274         const model::ConversionSequence &RTL =
2275             M.rightToLeftConversionSequence();
2276         FormattedConversionSequence LTRFmt{PP, LTypeStr, LTR, RTypeStr};
2277         FormattedConversionSequence RTLFmt{PP, RTypeStr, RTL, LTypeStr};
2278 
2279         StringRef DiagText = "'%0' and '%1' may be implicitly converted";
2280         if (!LTRFmt.Trivial || !RTLFmt.Trivial)
2281           DiagText = "'%0' and '%1' may be implicitly converted: %2, %3";
2282 
2283         {
2284           auto Diag =
2285               diag(RVar->getOuterLocStart(), DiagText, DiagnosticIDs::Note)
2286               << LTypeStr << RTypeStr;
2287 
2288           if (!LTRFmt.Trivial || !RTLFmt.Trivial)
2289             Diag << LTRFmt.DiagnosticText << RTLFmt.DiagnosticText;
2290         }
2291 
2292         StringRef ConversionFunctionDiagText =
2293             "the implicit conversion involves the "
2294             "%select{|converting constructor|conversion operator}0 "
2295             "declared here";
2296         if (const FunctionDecl *LFD = LTR.getUserDefinedConversionFunction())
2297           diag(LFD->getLocation(), ConversionFunctionDiagText,
2298                DiagnosticIDs::Note)
2299               << static_cast<unsigned>(LTR.UDConvKind)
2300               << LTR.getUserDefinedConversionHighlight();
2301         if (const FunctionDecl *RFD = RTL.getUserDefinedConversionFunction())
2302           diag(RFD->getLocation(), ConversionFunctionDiagText,
2303                DiagnosticIDs::Note)
2304               << static_cast<unsigned>(RTL.UDConvKind)
2305               << RTL.getUserDefinedConversionHighlight();
2306       }
2307     }
2308   }
2309 }
2310 
2311 } // namespace clang::tidy::bugprone
2312