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