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