1 //===--- EasilySwappableParametersCheck.cpp - clang-tidy ------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "EasilySwappableParametersCheck.h"
10 #include "../utils/OptionsUtils.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/RecursiveASTVisitor.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 #include "clang/Lex/Lexer.h"
15 #include "llvm/ADT/SmallSet.h"
17 #define DEBUG_TYPE "EasilySwappableParametersCheck"
18 #include "llvm/Support/Debug.h"
20 namespace optutils
= clang::tidy::utils::options
;
22 /// The default value for the MinimumLength check option.
23 static constexpr std::size_t DefaultMinimumLength
= 2;
25 /// The default value for ignored parameter names.
26 static constexpr llvm::StringLiteral DefaultIgnoredParameterNames
= "\"\";"
42 /// The default value for ignored parameter type suffixes.
43 static constexpr llvm::StringLiteral DefaultIgnoredParameterTypeSuffixes
=
67 "reverse_const_iterator;"
68 "ConstReverseIterator;"
69 "Const_Reverse_Iterator;"
70 "const_reverse_iterator;"
71 "Constreverseiterator;"
72 "constreverseiterator";
74 /// The default value for the QualifiersMix check option.
75 static constexpr bool DefaultQualifiersMix
= false;
77 /// The default value for the ModelImplicitConversions check option.
78 static constexpr bool DefaultModelImplicitConversions
= true;
80 /// The default value for suppressing diagnostics about parameters that are
82 static constexpr bool DefaultSuppressParametersUsedTogether
= true;
84 /// The default value for the NamePrefixSuffixSilenceDissimilarityTreshold
86 static constexpr std::size_t
87 DefaultNamePrefixSuffixSilenceDissimilarityTreshold
= 1;
89 using namespace clang::ast_matchers
;
95 using TheCheck
= EasilySwappableParametersCheck
;
98 class SimilarlyUsedParameterPairSuppressor
;
100 static bool isIgnoredParameter(const TheCheck
&Check
, const ParmVarDecl
*Node
);
102 isSimilarlyUsedParameter(const SimilarlyUsedParameterPairSuppressor
&Suppressor
,
103 const ParmVarDecl
*Param1
, const ParmVarDecl
*Param2
);
104 static bool prefixSuffixCoverUnderThreshold(std::size_t Threshold
,
105 StringRef Str1
, StringRef Str2
);
106 } // namespace filter
110 /// The language features involved in allowing the mix between two parameters.
111 enum class MixFlags
: unsigned char {
112 Invalid
= 0, ///< Sentinel bit pattern. DO NOT USE!
114 /// Certain constructs (such as pointers to noexcept/non-noexcept functions)
115 /// have the same CanonicalType, which would result in false positives.
116 /// During the recursive modelling call, this flag is set if a later diagnosed
117 /// canonical type equivalence should be thrown away.
118 WorkaroundDisableCanonicalEquivalence
= 1,
120 None
= 2, ///< Mix between the two parameters is not possible.
121 Trivial
= 4, ///< The two mix trivially, and are the exact same type.
122 Canonical
= 8, ///< The two mix because the types refer to the same
123 /// CanonicalType, but we do not elaborate as to how.
124 TypeAlias
= 16, ///< The path from one type to the other involves
125 /// desugaring type aliases.
126 ReferenceBind
= 32, ///< The mix involves the binding power of "const &".
127 Qualifiers
= 64, ///< The mix involves change in the qualifiers.
128 ImplicitConversion
= 128, ///< The mixing of the parameters is possible
129 /// through implicit conversions between the types.
131 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue =*/ImplicitConversion
)
133 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
135 /// Returns whether the SearchedFlag is turned on in the Data.
136 static inline bool hasFlag(MixFlags Data
, MixFlags SearchedFlag
) {
137 assert(SearchedFlag
!= MixFlags::Invalid
&&
138 "can't be used to detect lack of all bits!");
140 // "Data & SearchedFlag" would need static_cast<bool>() in conditions.
141 return (Data
& SearchedFlag
) == SearchedFlag
;
146 // The modelling logic of this check is more complex than usual, and
147 // potentially hard to understand without the ability to see into the
148 // representation during the recursive descent. This debug code is only
149 // compiled in 'Debug' mode, or if LLVM_ENABLE_ASSERTIONS config is turned on.
151 /// Formats the MixFlags enum into a useful, user-readable representation.
152 static inline std::string
formatMixFlags(MixFlags F
) {
153 if (F
== MixFlags::Invalid
)
156 SmallString
<8> Str
{"-------"};
158 if (hasFlag(F
, MixFlags::None
))
159 // Shows the None bit explicitly, as it can be applied in the recursion
160 // even if other bits are set.
162 if (hasFlag(F
, MixFlags::Trivial
))
164 if (hasFlag(F
, MixFlags::Canonical
))
166 if (hasFlag(F
, MixFlags::TypeAlias
))
168 if (hasFlag(F
, MixFlags::ReferenceBind
))
170 if (hasFlag(F
, MixFlags::Qualifiers
))
172 if (hasFlag(F
, MixFlags::ImplicitConversion
))
175 if (hasFlag(F
, MixFlags::WorkaroundDisableCanonicalEquivalence
))
178 return Str
.str().str();
183 /// The results of the steps of an Implicit Conversion Sequence is saved in
184 /// an instance of this record.
186 /// A ConversionSequence maps the steps of the conversion with a member for
187 /// each type involved in the conversion. Imagine going from a hypothetical
188 /// Complex class to projecting it to the real part as a const double.
193 /// operator double() const;
196 /// void functionBeingAnalysed(Complex C, const double R);
198 /// we will get the following sequence:
202 /// The first standard conversion is a qualification adjustment.
203 /// (AfterFirstStandard=) const Complex
205 /// Then the user-defined conversion is executed.
206 /// (UDConvOp.ConversionOperatorResultType=) double
208 /// Then this 'double' is qualifier-adjusted to 'const double'.
209 /// (AfterSecondStandard=) double
211 /// The conversion's result has now been calculated, so it ends here.
214 /// Explicit storing of Begin and End in this record is needed, because
215 /// getting to what Begin and End here are needs further resolution of types,
216 /// e.g. in the case of typedefs:
218 /// using Comp = Complex;
219 /// using CD = const double;
220 /// void functionBeingAnalysed2(Comp C, CD R);
222 /// In this case, the user will be diagnosed with a potential conversion
223 /// between the two typedefs as written in the code, but to elaborate the
224 /// reasoning behind this conversion, we also need to show what the typedefs
225 /// mean. See FormattedConversionSequence towards the bottom of this file!
226 struct ConversionSequence
{
227 enum UserDefinedConversionKind
{ UDCK_None
, UDCK_Ctor
, UDCK_Oper
};
229 struct UserDefinedConvertingConstructor
{
230 const CXXConstructorDecl
*Fun
;
231 QualType ConstructorParameterType
;
232 QualType UserDefinedType
;
235 struct UserDefinedConversionOperator
{
236 const CXXConversionDecl
*Fun
;
237 QualType UserDefinedType
;
238 QualType ConversionOperatorResultType
;
241 /// The type the conversion stared from.
244 /// The intermediate type after the first Standard Conversion Sequence.
245 QualType AfterFirstStandard
;
247 /// The details of the user-defined conversion involved, as a tagged union.
250 UserDefinedConvertingConstructor UDConvCtor
;
251 UserDefinedConversionOperator UDConvOp
;
253 UserDefinedConversionKind UDConvKind
;
255 /// The intermediate type after performing the second Standard Conversion
257 QualType AfterSecondStandard
;
259 /// The result type the conversion targeted.
262 ConversionSequence() : None(0), UDConvKind(UDCK_None
) {}
263 ConversionSequence(QualType From
, QualType To
)
264 : Begin(From
), None(0), UDConvKind(UDCK_None
), End(To
) {}
266 explicit operator bool() const {
267 return !AfterFirstStandard
.isNull() || UDConvKind
!= UDCK_None
||
268 !AfterSecondStandard
.isNull();
271 /// Returns all the "steps" (non-unique and non-similar) types involved in
272 /// the conversion sequence. This method does **NOT** return Begin and End.
273 SmallVector
<QualType
, 4> getInvolvedTypesInSequence() const {
274 SmallVector
<QualType
, 4> Ret
;
275 auto EmplaceIfDifferent
= [&Ret
](QualType QT
) {
279 Ret
.emplace_back(QT
);
280 else if (Ret
.back() != QT
)
281 Ret
.emplace_back(QT
);
284 EmplaceIfDifferent(AfterFirstStandard
);
285 switch (UDConvKind
) {
287 EmplaceIfDifferent(UDConvCtor
.ConstructorParameterType
);
288 EmplaceIfDifferent(UDConvCtor
.UserDefinedType
);
291 EmplaceIfDifferent(UDConvOp
.UserDefinedType
);
292 EmplaceIfDifferent(UDConvOp
.ConversionOperatorResultType
);
297 EmplaceIfDifferent(AfterSecondStandard
);
302 /// Updates the steps of the conversion sequence with the steps from the
305 /// \note This method does not check if the resulting conversion sequence is
307 ConversionSequence
&update(const ConversionSequence
&RHS
) {
308 if (!RHS
.AfterFirstStandard
.isNull())
309 AfterFirstStandard
= RHS
.AfterFirstStandard
;
310 switch (RHS
.UDConvKind
) {
312 UDConvKind
= UDCK_Ctor
;
313 UDConvCtor
= RHS
.UDConvCtor
;
316 UDConvKind
= UDCK_Oper
;
317 UDConvOp
= RHS
.UDConvOp
;
322 if (!RHS
.AfterSecondStandard
.isNull())
323 AfterSecondStandard
= RHS
.AfterSecondStandard
;
328 /// Sets the user-defined conversion to the given constructor.
329 void setConversion(const UserDefinedConvertingConstructor
&UDCC
) {
330 UDConvKind
= UDCK_Ctor
;
334 /// Sets the user-defined conversion to the given operator.
335 void setConversion(const UserDefinedConversionOperator
&UDCO
) {
336 UDConvKind
= UDCK_Oper
;
340 /// Returns the type in the conversion that's formally "in our hands" once
341 /// the user-defined conversion is executed.
342 QualType
getTypeAfterUserDefinedConversion() const {
343 switch (UDConvKind
) {
345 return UDConvCtor
.UserDefinedType
;
347 return UDConvOp
.ConversionOperatorResultType
;
351 llvm_unreachable("Invalid UDConv kind.");
354 const CXXMethodDecl
*getUserDefinedConversionFunction() const {
355 switch (UDConvKind
) {
357 return UDConvCtor
.Fun
;
363 llvm_unreachable("Invalid UDConv kind.");
366 /// Returns the SourceRange in the text that corresponds to the interesting
367 /// part of the user-defined conversion. This is either the parameter type
368 /// in a converting constructor, or the conversion result type in a conversion
370 SourceRange
getUserDefinedConversionHighlight() const {
371 switch (UDConvKind
) {
373 return UDConvCtor
.Fun
->getParamDecl(0)->getSourceRange();
375 // getReturnTypeSourceRange() does not work for CXXConversionDecls as the
376 // returned type is physically behind the declaration's name ("operator").
377 if (const FunctionTypeLoc FTL
= UDConvOp
.Fun
->getFunctionTypeLoc())
378 if (const TypeLoc RetLoc
= FTL
.getReturnLoc())
379 return RetLoc
.getSourceRange();
384 llvm_unreachable("Invalid UDConv kind.");
388 /// Contains the metadata for the mixability result between two types,
389 /// independently of which parameters they were calculated from.
391 /// The flag bits of the mix indicating what language features allow for it.
392 MixFlags Flags
= MixFlags::Invalid
;
394 /// A potentially calculated common underlying type after desugaring, that
395 /// both sides of the mix can originate from.
398 /// The steps an implicit conversion performs to get from one type to the
400 ConversionSequence Conversion
, ConversionRTL
;
402 /// True if the MixData was specifically created with only a one-way
403 /// conversion modelled.
404 bool CreatedFromOneWayConversion
= false;
406 MixData(MixFlags Flags
) : Flags(Flags
) {}
407 MixData(MixFlags Flags
, QualType CommonType
)
408 : Flags(Flags
), CommonType(CommonType
) {}
409 MixData(MixFlags Flags
, ConversionSequence Conv
)
410 : Flags(Flags
), Conversion(Conv
), CreatedFromOneWayConversion(true) {}
411 MixData(MixFlags Flags
, ConversionSequence LTR
, ConversionSequence RTL
)
412 : Flags(Flags
), Conversion(LTR
), ConversionRTL(RTL
) {}
413 MixData(MixFlags Flags
, QualType CommonType
, ConversionSequence LTR
,
414 ConversionSequence RTL
)
415 : Flags(Flags
), CommonType(CommonType
), Conversion(LTR
),
416 ConversionRTL(RTL
) {}
419 assert(Flags
!= MixFlags::Invalid
&& "sanitize() called on invalid bitvec");
421 MixFlags CanonicalAndWorkaround
=
422 MixFlags::Canonical
| MixFlags::WorkaroundDisableCanonicalEquivalence
;
423 if ((Flags
& CanonicalAndWorkaround
) == CanonicalAndWorkaround
) {
424 // A workaround for too eagerly equivalent canonical types was requested,
425 // and a canonical equivalence was proven. Fulfill the request and throw
427 Flags
= MixFlags::None
;
431 if (hasFlag(Flags
, MixFlags::None
)) {
432 // If anywhere down the recursion a potential mix "path" is deemed
433 // impossible, throw away all the other bits because the mix is not
435 Flags
= MixFlags::None
;
439 if (Flags
== MixFlags::Trivial
)
442 if (static_cast<bool>(Flags
^ MixFlags::Trivial
))
443 // If the mix involves somewhere trivial equivalence but down the
444 // recursion other bit(s) were set, remove the trivial bit, as it is not
446 Flags
&= ~MixFlags::Trivial
;
448 bool ShouldHaveImplicitConvFlag
= false;
449 if (CreatedFromOneWayConversion
&& Conversion
)
450 ShouldHaveImplicitConvFlag
= true;
451 else if (!CreatedFromOneWayConversion
&& Conversion
&& ConversionRTL
)
452 // Only say that we have implicit conversion mix possibility if it is
453 // bidirectional. Otherwise, the compiler would report an *actual* swap
455 ShouldHaveImplicitConvFlag
= true;
457 if (ShouldHaveImplicitConvFlag
)
458 Flags
|= MixFlags::ImplicitConversion
;
460 Flags
&= ~MixFlags::ImplicitConversion
;
463 bool isValid() const { return Flags
>= MixFlags::None
; }
465 bool indicatesMixability() const { return Flags
> MixFlags::None
; }
467 /// Add the specified flag bits to the flags.
468 MixData
operator|(MixFlags EnableFlags
) const {
469 if (CreatedFromOneWayConversion
) {
470 MixData M
{Flags
| EnableFlags
, Conversion
};
471 M
.CommonType
= CommonType
;
474 return {Flags
| EnableFlags
, CommonType
, Conversion
, ConversionRTL
};
477 /// Add the specified flag bits to the flags.
478 MixData
&operator|=(MixFlags EnableFlags
) {
479 Flags
|= EnableFlags
;
483 template <class F
> MixData
withCommonTypeTransformed(F
&&Func
) const {
484 if (CommonType
.isNull())
487 QualType NewCommonType
= Func(CommonType
);
489 if (CreatedFromOneWayConversion
) {
490 MixData M
{Flags
, Conversion
};
491 M
.CommonType
= NewCommonType
;
495 return {Flags
, NewCommonType
, Conversion
, ConversionRTL
};
499 /// A named tuple that contains the information for a mix between two concrete
502 const ParmVarDecl
*First
, *Second
;
505 Mix(const ParmVarDecl
*F
, const ParmVarDecl
*S
, MixData Data
)
506 : First(F
), Second(S
), Data(std::move(Data
)) {}
508 void sanitize() { Data
.sanitize(); }
509 MixFlags
flags() const { return Data
.Flags
; }
510 bool flagsValid() const { return Data
.isValid(); }
511 bool mixable() const { return Data
.indicatesMixability(); }
512 QualType
commonUnderlyingType() const { return Data
.CommonType
; }
513 const ConversionSequence
&leftToRightConversionSequence() const {
514 return Data
.Conversion
;
516 const ConversionSequence
&rightToLeftConversionSequence() const {
517 return Data
.ConversionRTL
;
521 // NOLINTNEXTLINE(misc-redundant-expression): Seems to be a bogus warning.
522 static_assert(std::is_trivially_copyable
<Mix
>::value
&&
523 std::is_trivially_move_constructible
<Mix
>::value
&&
524 std::is_trivially_move_assignable
<Mix
>::value
,
525 "Keep frequently used data simple!");
527 struct MixableParameterRange
{
528 /// A container for Mixes.
529 using MixVector
= SmallVector
<Mix
, 8>;
531 /// The number of parameters iterated to build the instance.
532 std::size_t NumParamsChecked
= 0;
534 /// The individual flags and supporting information for the mixes.
537 /// Gets the leftmost parameter of the range.
538 const ParmVarDecl
*getFirstParam() const {
539 // The first element is the LHS of the very first mix in the range.
540 assert(!Mixes
.empty());
541 return Mixes
.front().First
;
544 /// Gets the rightmost parameter of the range.
545 const ParmVarDecl
*getLastParam() const {
546 // The builder function breaks building an instance of this type if it
547 // finds something that can not be mixed with the rest, by going *forward*
548 // in the list of parameters. So at any moment of break, the RHS of the last
549 // element of the mix vector is also the last element of the mixing range.
550 assert(!Mixes
.empty());
551 return Mixes
.back().Second
;
555 /// Helper enum for the recursive calls in the modelling that toggle what kinds
556 /// of implicit conversions are to be modelled.
557 enum class ImplicitConversionModellingMode
: unsigned char {
558 ///< No implicit conversions are modelled.
561 ///< The full implicit conversion sequence is modelled.
564 ///< Only model a unidirectional implicit conversion and within it only one
565 /// standard conversion sequence.
566 OneWaySingleStandardOnly
570 isLRefEquallyBindingToType(const TheCheck
&Check
,
571 const LValueReferenceType
*LRef
, QualType Ty
,
572 const ASTContext
&Ctx
, bool IsRefRHS
,
573 ImplicitConversionModellingMode ImplicitMode
);
576 approximateImplicitConversion(const TheCheck
&Check
, QualType LType
,
577 QualType RType
, const ASTContext
&Ctx
,
578 ImplicitConversionModellingMode ImplicitMode
);
580 static inline bool isUselessSugar(const Type
*T
) {
581 return isa
<AttributedType
, DecayedType
, ElaboratedType
, ParenType
>(T
);
586 struct NonCVRQualifiersResult
{
587 /// True if the types are qualified in a way that even after equating or
588 /// removing local CVR qualification, even if the unqualified types
589 /// themselves would mix, the qualified ones don't, because there are some
590 /// other local qualifiers that are not equal.
591 bool HasMixabilityBreakingQualifiers
;
593 /// The set of equal qualifiers between the two types.
594 Qualifiers CommonQualifiers
;
599 /// Returns if the two types are qualified in a way that ever after equating or
600 /// removing local CVR qualification, even if the unqualified types would mix,
601 /// the qualified ones don't, because there are some other local qualifiers
602 /// that aren't equal.
603 static NonCVRQualifiersResult
604 getNonCVRQualifiers(const ASTContext
&Ctx
, QualType LType
, QualType RType
) {
605 LLVM_DEBUG(llvm::dbgs() << ">>> getNonCVRQualifiers for LType:\n";
606 LType
.dump(llvm::dbgs(), Ctx
); llvm::dbgs() << "\nand RType:\n";
607 RType
.dump(llvm::dbgs(), Ctx
); llvm::dbgs() << '\n';);
608 Qualifiers LQual
= LType
.getLocalQualifiers(),
609 RQual
= RType
.getLocalQualifiers();
611 // Strip potential CVR. That is handled by the check option QualifiersMix.
612 LQual
.removeCVRQualifiers();
613 RQual
.removeCVRQualifiers();
615 NonCVRQualifiersResult Ret
;
616 Ret
.CommonQualifiers
= Qualifiers::removeCommonQualifiers(LQual
, RQual
);
618 LLVM_DEBUG(llvm::dbgs() << "--- hasNonCVRMixabilityBreakingQualifiers. "
619 "Removed common qualifiers: ";
620 Ret
.CommonQualifiers
.print(llvm::dbgs(), Ctx
.getPrintingPolicy());
621 llvm::dbgs() << "\n\tremaining on LType: ";
622 LQual
.print(llvm::dbgs(), Ctx
.getPrintingPolicy());
623 llvm::dbgs() << "\n\tremaining on RType: ";
624 RQual
.print(llvm::dbgs(), Ctx
.getPrintingPolicy());
625 llvm::dbgs() << '\n';);
627 // If there are no other non-cvr non-common qualifiers left, we can deduce
628 // that mixability isn't broken.
629 Ret
.HasMixabilityBreakingQualifiers
=
630 LQual
.hasQualifiers() || RQual
.hasQualifiers();
635 /// Approximate the way how LType and RType might refer to "essentially the
636 /// same" type, in a sense that at a particular call site, an expression of
637 /// type LType and RType might be successfully passed to a variable (in our
638 /// specific case, a parameter) of type RType and LType, respectively.
639 /// Note the swapped order!
641 /// The returned data structure is not guaranteed to be properly set, as this
642 /// function is potentially recursive. It is the caller's responsibility to
643 /// call sanitize() on the result once the recursion is over.
645 calculateMixability(const TheCheck
&Check
, QualType LType
, QualType RType
,
646 const ASTContext
&Ctx
,
647 ImplicitConversionModellingMode ImplicitMode
) {
648 LLVM_DEBUG(llvm::dbgs() << ">>> calculateMixability for LType:\n";
649 LType
.dump(llvm::dbgs(), Ctx
); llvm::dbgs() << "\nand RType:\n";
650 RType
.dump(llvm::dbgs(), Ctx
); llvm::dbgs() << '\n';);
651 if (LType
== RType
) {
652 LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Trivial equality.\n");
653 return {MixFlags::Trivial
, LType
};
656 // Dissolve certain type sugars that do not affect the mixability of one type
657 // with the other, and also do not require any sort of elaboration for the
658 // user to understand.
659 if (isUselessSugar(LType
.getTypePtr())) {
660 LLVM_DEBUG(llvm::dbgs()
661 << "--- calculateMixability. LHS is useless sugar.\n");
662 return calculateMixability(Check
, LType
.getSingleStepDesugaredType(Ctx
),
663 RType
, Ctx
, ImplicitMode
);
665 if (isUselessSugar(RType
.getTypePtr())) {
666 LLVM_DEBUG(llvm::dbgs()
667 << "--- calculateMixability. RHS is useless sugar.\n");
668 return calculateMixability(
669 Check
, LType
, RType
.getSingleStepDesugaredType(Ctx
), Ctx
, ImplicitMode
);
672 const auto *LLRef
= LType
->getAs
<LValueReferenceType
>();
673 const auto *RLRef
= RType
->getAs
<LValueReferenceType
>();
674 if (LLRef
&& RLRef
) {
675 LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. LHS and RHS are &.\n");
677 return calculateMixability(Check
, LLRef
->getPointeeType(),
678 RLRef
->getPointeeType(), Ctx
, ImplicitMode
)
679 .withCommonTypeTransformed(
680 [&Ctx
](QualType QT
) { return Ctx
.getLValueReferenceType(QT
); });
682 // At a particular call site, what could be passed to a 'T' or 'const T' might
683 // also be passed to a 'const T &' without the call site putting a direct
684 // side effect on the passed expressions.
686 LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. LHS is &.\n");
687 return isLRefEquallyBindingToType(Check
, LLRef
, RType
, Ctx
, false,
689 MixFlags::ReferenceBind
;
692 LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. RHS is &.\n");
693 return isLRefEquallyBindingToType(Check
, RLRef
, LType
, Ctx
, true,
695 MixFlags::ReferenceBind
;
698 if (LType
->getAs
<TypedefType
>()) {
699 LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. LHS is typedef.\n");
700 return calculateMixability(Check
, LType
.getSingleStepDesugaredType(Ctx
),
701 RType
, Ctx
, ImplicitMode
) |
704 if (RType
->getAs
<TypedefType
>()) {
705 LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. RHS is typedef.\n");
706 return calculateMixability(Check
, LType
,
707 RType
.getSingleStepDesugaredType(Ctx
), Ctx
,
712 // A parameter of type 'cvr1 T' and another of potentially differently
713 // qualified 'cvr2 T' may bind with the same power, if the user so requested.
715 // Whether to do this check for the inner unqualified types.
716 bool CompareUnqualifiedTypes
= false;
717 if (LType
.getLocalCVRQualifiers() != RType
.getLocalCVRQualifiers()) {
718 LLVM_DEBUG(if (LType
.getLocalCVRQualifiers()) {
719 llvm::dbgs() << "--- calculateMixability. LHS has CVR-Qualifiers: ";
720 Qualifiers::fromCVRMask(LType
.getLocalCVRQualifiers())
721 .print(llvm::dbgs(), Ctx
.getPrintingPolicy());
722 llvm::dbgs() << '\n';
724 LLVM_DEBUG(if (RType
.getLocalCVRQualifiers()) {
725 llvm::dbgs() << "--- calculateMixability. RHS has CVR-Qualifiers: ";
726 Qualifiers::fromCVRMask(RType
.getLocalCVRQualifiers())
727 .print(llvm::dbgs(), Ctx
.getPrintingPolicy());
728 llvm::dbgs() << '\n';
731 if (!Check
.QualifiersMix
) {
732 LLVM_DEBUG(llvm::dbgs()
733 << "<<< calculateMixability. QualifiersMix turned off - not "
735 return {MixFlags::None
};
738 CompareUnqualifiedTypes
= true;
740 // Whether the two types had the same CVR qualifiers.
741 bool OriginallySameQualifiers
= false;
742 if (LType
.getLocalCVRQualifiers() == RType
.getLocalCVRQualifiers() &&
743 LType
.getLocalCVRQualifiers() != 0) {
744 LLVM_DEBUG(if (LType
.getLocalCVRQualifiers()) {
746 << "--- calculateMixability. LHS and RHS have same CVR-Qualifiers: ";
747 Qualifiers::fromCVRMask(LType
.getLocalCVRQualifiers())
748 .print(llvm::dbgs(), Ctx
.getPrintingPolicy());
749 llvm::dbgs() << '\n';
752 CompareUnqualifiedTypes
= true;
753 OriginallySameQualifiers
= true;
756 if (CompareUnqualifiedTypes
) {
757 NonCVRQualifiersResult AdditionalQuals
=
758 getNonCVRQualifiers(Ctx
, LType
, RType
);
759 if (AdditionalQuals
.HasMixabilityBreakingQualifiers
) {
760 LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Additional "
761 "non-equal incompatible qualifiers.\n");
762 return {MixFlags::None
};
765 MixData UnqualifiedMixability
=
766 calculateMixability(Check
, LType
.getLocalUnqualifiedType(),
767 RType
.getLocalUnqualifiedType(), Ctx
, ImplicitMode
)
768 .withCommonTypeTransformed([&AdditionalQuals
, &Ctx
](QualType QT
) {
769 // Once the mixability was deduced, apply the qualifiers common
770 // to the two type back onto the diagnostic printout.
771 return Ctx
.getQualifiedType(QT
, AdditionalQuals
.CommonQualifiers
);
774 if (!OriginallySameQualifiers
)
775 // User-enabled qualifier change modelled for the mix.
776 return UnqualifiedMixability
| MixFlags::Qualifiers
;
778 // Apply the same qualifier back into the found common type if they were
780 return UnqualifiedMixability
.withCommonTypeTransformed(
781 [&Ctx
, LType
](QualType QT
) {
782 return Ctx
.getQualifiedType(QT
, LType
.getLocalQualifiers());
786 // Certain constructs match on the last catch-all getCanonicalType() equality,
787 // which is perhaps something not what we want. If this variable is true,
788 // the canonical type equality will be ignored.
789 bool RecursiveReturnDiscardingCanonicalType
= false;
791 if (LType
->isPointerType() && RType
->isPointerType()) {
792 // If both types are pointers, and pointed to the exact same type,
793 // LType == RType took care of that. Try to see if the pointee type has
794 // some other match. However, this must not consider implicit conversions.
795 LLVM_DEBUG(llvm::dbgs()
796 << "--- calculateMixability. LHS and RHS are Ptrs.\n");
797 MixData MixOfPointee
=
798 calculateMixability(Check
, LType
->getPointeeType(),
799 RType
->getPointeeType(), Ctx
,
800 ImplicitConversionModellingMode::None
)
801 .withCommonTypeTransformed(
802 [&Ctx
](QualType QT
) { return Ctx
.getPointerType(QT
); });
803 if (hasFlag(MixOfPointee
.Flags
,
804 MixFlags::WorkaroundDisableCanonicalEquivalence
))
805 RecursiveReturnDiscardingCanonicalType
= true;
807 MixOfPointee
.sanitize();
808 if (MixOfPointee
.indicatesMixability()) {
809 LLVM_DEBUG(llvm::dbgs()
810 << "<<< calculateMixability. Pointees are mixable.\n");
815 if (ImplicitMode
> ImplicitConversionModellingMode::None
) {
816 LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. Start implicit...\n");
818 approximateImplicitConversion(Check
, LType
, RType
, Ctx
, ImplicitMode
);
820 if (hasFlag(MixLTR
.Flags
, MixFlags::ImplicitConversion
)) llvm::dbgs()
821 << "--- calculateMixability. Implicit Left -> Right found.\n";);
824 ImplicitConversionModellingMode::OneWaySingleStandardOnly
&&
825 MixLTR
.Conversion
&& !MixLTR
.Conversion
.AfterFirstStandard
.isNull() &&
826 MixLTR
.Conversion
.UDConvKind
== ConversionSequence::UDCK_None
&&
827 MixLTR
.Conversion
.AfterSecondStandard
.isNull()) {
828 // The invoker of the method requested only modelling a single standard
829 // conversion, in only the forward direction, and they got just that.
830 LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Implicit "
831 "conversion, one-way, standard-only.\n");
832 return {MixFlags::ImplicitConversion
, MixLTR
.Conversion
};
835 // Otherwise if the invoker requested a full modelling, do the other
836 // direction as well.
838 approximateImplicitConversion(Check
, RType
, LType
, Ctx
, ImplicitMode
);
840 if (hasFlag(MixRTL
.Flags
, MixFlags::ImplicitConversion
)) llvm::dbgs()
841 << "--- calculateMixability. Implicit Right -> Left found.\n";);
843 if (MixLTR
.Conversion
&& MixRTL
.Conversion
) {
846 << "<<< calculateMixability. Implicit conversion, bidirectional.\n");
847 return {MixFlags::ImplicitConversion
, MixLTR
.Conversion
,
852 if (RecursiveReturnDiscardingCanonicalType
)
853 LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. Before CanonicalType, "
854 "Discard was enabled.\n");
856 // Certain kinds unfortunately need to be side-stepped for canonical type
858 if (LType
->getAs
<FunctionProtoType
>() || RType
->getAs
<FunctionProtoType
>()) {
859 // Unfortunately, the canonical type of a function pointer becomes the
860 // same even if exactly one is "noexcept" and the other isn't, making us
861 // give a false positive report irrespective of implicit conversions.
862 LLVM_DEBUG(llvm::dbgs()
863 << "--- calculateMixability. Discarding potential canonical "
864 "equivalence on FunctionProtoTypes.\n");
865 RecursiveReturnDiscardingCanonicalType
= true;
868 MixData MixToReturn
{MixFlags::None
};
870 // If none of the previous logic found a match, try if Clang otherwise
871 // believes the types to be the same.
872 QualType LCanonical
= LType
.getCanonicalType();
873 if (LCanonical
== RType
.getCanonicalType()) {
874 LLVM_DEBUG(llvm::dbgs()
875 << "<<< calculateMixability. Same CanonicalType.\n");
876 MixToReturn
= {MixFlags::Canonical
, LCanonical
};
879 if (RecursiveReturnDiscardingCanonicalType
)
880 MixToReturn
|= MixFlags::WorkaroundDisableCanonicalEquivalence
;
882 LLVM_DEBUG(if (MixToReturn
.Flags
== MixFlags::None
) llvm::dbgs()
883 << "<<< calculateMixability. No match found.\n");
887 /// Calculates if the reference binds an expression of the given type. This is
888 /// true iff 'LRef' is some 'const T &' type, and the 'Ty' is 'T' or 'const T'.
890 /// \param ImplicitMode is forwarded in the possible recursive call to
891 /// calculateMixability.
893 isLRefEquallyBindingToType(const TheCheck
&Check
,
894 const LValueReferenceType
*LRef
, QualType Ty
,
895 const ASTContext
&Ctx
, bool IsRefRHS
,
896 ImplicitConversionModellingMode ImplicitMode
) {
897 LLVM_DEBUG(llvm::dbgs() << ">>> isLRefEquallyBindingToType for LRef:\n";
898 LRef
->dump(llvm::dbgs(), Ctx
); llvm::dbgs() << "\nand Type:\n";
899 Ty
.dump(llvm::dbgs(), Ctx
); llvm::dbgs() << '\n';);
901 QualType ReferredType
= LRef
->getPointeeType();
902 if (!ReferredType
.isLocalConstQualified() &&
903 ReferredType
->getAs
<TypedefType
>()) {
906 << "--- isLRefEquallyBindingToType. Non-const LRef to Typedef.\n");
907 ReferredType
= ReferredType
.getDesugaredType(Ctx
);
908 if (!ReferredType
.isLocalConstQualified()) {
909 LLVM_DEBUG(llvm::dbgs()
910 << "<<< isLRefEquallyBindingToType. Typedef is not const.\n");
911 return {MixFlags::None
};
914 LLVM_DEBUG(llvm::dbgs() << "--- isLRefEquallyBindingToType. Typedef is "
915 "const, considering as const LRef.\n");
916 } else if (!ReferredType
.isLocalConstQualified()) {
917 LLVM_DEBUG(llvm::dbgs()
918 << "<<< isLRefEquallyBindingToType. Not const LRef.\n");
919 return {MixFlags::None
};
922 assert(ReferredType
.isLocalConstQualified() &&
923 "Reaching this point means we are sure LRef is effectively a const&.");
925 if (ReferredType
== Ty
) {
928 << "<<< isLRefEquallyBindingToType. Type of referred matches.\n");
929 return {MixFlags::Trivial
, ReferredType
};
932 QualType NonConstReferredType
= ReferredType
;
933 NonConstReferredType
.removeLocalConst();
934 if (NonConstReferredType
== Ty
) {
935 LLVM_DEBUG(llvm::dbgs() << "<<< isLRefEquallyBindingToType. Type of "
936 "referred matches to non-const qualified.\n");
937 return {MixFlags::Trivial
, NonConstReferredType
};
942 << "--- isLRefEquallyBindingToType. Checking mix for underlying type.\n");
943 return IsRefRHS
? calculateMixability(Check
, Ty
, NonConstReferredType
, Ctx
,
945 : calculateMixability(Check
, NonConstReferredType
, Ty
, Ctx
,
949 static inline bool isDerivedToBase(const CXXRecordDecl
*Derived
,
950 const CXXRecordDecl
*Base
) {
951 return Derived
&& Base
&& Derived
->isCompleteDefinition() &&
952 Base
->isCompleteDefinition() && Derived
->isDerivedFrom(Base
);
955 static Optional
<QualType
>
956 approximateStandardConversionSequence(const TheCheck
&Check
, QualType From
,
957 QualType To
, const ASTContext
&Ctx
) {
958 LLVM_DEBUG(llvm::dbgs() << ">>> approximateStdConv for LType:\n";
959 From
.dump(llvm::dbgs(), Ctx
); llvm::dbgs() << "\nand RType:\n";
960 To
.dump(llvm::dbgs(), Ctx
); llvm::dbgs() << '\n';);
962 // A standard conversion sequence consists of the following, in order:
963 // * Maybe either LValue->RValue conv., Array->Ptr conv., Function->Ptr conv.
964 // * Maybe Numeric promotion or conversion.
965 // * Maybe function pointer conversion.
966 // * Maybe qualifier adjustments.
967 QualType WorkType
= From
;
968 // Get out the qualifiers of the original type. This will always be
969 // re-applied to the WorkType to ensure it is the same qualification as the
970 // original From was.
971 auto QualifiersToApply
= From
.split().Quals
.getAsOpaqueValue();
973 // LValue->RValue is irrelevant for the check, because it is a thing to be
974 // done at a call site, and will be performed if need be performed.
976 // Array->Pointer decay is handled by the main method in desugaring
977 // the parameter's DecayedType as "useless sugar".
979 // Function->Pointer conversions are also irrelevant, because a
980 // "FunctionType" cannot be the type of a parameter variable, so this
981 // conversion is only meaningful at call sites.
983 // Numeric promotions and conversions.
984 const auto *FromBuiltin
= WorkType
->getAs
<BuiltinType
>();
985 const auto *ToBuiltin
= To
->getAs
<BuiltinType
>();
986 bool FromNumeric
= FromBuiltin
&& (FromBuiltin
->isIntegerType() ||
987 FromBuiltin
->isFloatingType());
989 ToBuiltin
&& (ToBuiltin
->isIntegerType() || ToBuiltin
->isFloatingType());
990 if (FromNumeric
&& ToNumeric
) {
991 // If both are integral types, the numeric conversion is performed.
992 // Reapply the qualifiers of the original type, however, so
993 // "const int -> double" in this case moves over to
994 // "const double -> double".
995 LLVM_DEBUG(llvm::dbgs()
996 << "--- approximateStdConv. Conversion between numerics.\n");
997 WorkType
= QualType
{ToBuiltin
, QualifiersToApply
};
1000 const auto *FromEnum
= WorkType
->getAs
<EnumType
>();
1001 const auto *ToEnum
= To
->getAs
<EnumType
>();
1002 if (FromEnum
&& ToNumeric
&& FromEnum
->isUnscopedEnumerationType()) {
1003 // Unscoped enumerations (or enumerations in C) convert to numerics.
1004 LLVM_DEBUG(llvm::dbgs()
1005 << "--- approximateStdConv. Unscoped enum to numeric.\n");
1006 WorkType
= QualType
{ToBuiltin
, QualifiersToApply
};
1007 } else if (FromNumeric
&& ToEnum
&& ToEnum
->isUnscopedEnumerationType()) {
1008 // Numeric types convert to enumerations only in C.
1009 if (Ctx
.getLangOpts().CPlusPlus
) {
1010 LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Numeric to unscoped "
1011 "enum, not possible in C++!\n");
1015 LLVM_DEBUG(llvm::dbgs()
1016 << "--- approximateStdConv. Numeric to unscoped enum.\n");
1017 WorkType
= QualType
{ToEnum
, QualifiersToApply
};
1020 // Check for pointer conversions.
1021 const auto *FromPtr
= WorkType
->getAs
<PointerType
>();
1022 const auto *ToPtr
= To
->getAs
<PointerType
>();
1023 if (FromPtr
&& ToPtr
) {
1024 if (ToPtr
->isVoidPointerType()) {
1025 LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. To void pointer.\n");
1026 WorkType
= QualType
{ToPtr
, QualifiersToApply
};
1029 const auto *FromRecordPtr
= FromPtr
->getPointeeCXXRecordDecl();
1030 const auto *ToRecordPtr
= ToPtr
->getPointeeCXXRecordDecl();
1031 if (isDerivedToBase(FromRecordPtr
, ToRecordPtr
)) {
1032 LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived* to Base*\n");
1033 WorkType
= QualType
{ToPtr
, QualifiersToApply
};
1037 // Model the slicing Derived-to-Base too, as "BaseT temporary = derived;"
1038 // can also be compiled.
1039 const auto *FromRecord
= WorkType
->getAsCXXRecordDecl();
1040 const auto *ToRecord
= To
->getAsCXXRecordDecl();
1041 if (isDerivedToBase(FromRecord
, ToRecord
)) {
1042 LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived To Base.\n");
1043 WorkType
= QualType
{ToRecord
->getTypeForDecl(), QualifiersToApply
};
1046 if (Ctx
.getLangOpts().CPlusPlus17
&& FromPtr
&& ToPtr
) {
1047 // Function pointer conversion: A noexcept function pointer can be passed
1048 // to a non-noexcept one.
1049 const auto *FromFunctionPtr
=
1050 FromPtr
->getPointeeType()->getAs
<FunctionProtoType
>();
1051 const auto *ToFunctionPtr
=
1052 ToPtr
->getPointeeType()->getAs
<FunctionProtoType
>();
1053 if (FromFunctionPtr
&& ToFunctionPtr
&&
1054 FromFunctionPtr
->hasNoexceptExceptionSpec() &&
1055 !ToFunctionPtr
->hasNoexceptExceptionSpec()) {
1056 LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. noexcept function "
1057 "pointer to non-noexcept.\n");
1058 WorkType
= QualType
{ToPtr
, QualifiersToApply
};
1062 // Qualifier adjustments are modelled according to the user's request in
1063 // the QualifiersMix check config.
1064 LLVM_DEBUG(llvm::dbgs()
1065 << "--- approximateStdConv. Trying qualifier adjustment...\n");
1066 MixData QualConv
= calculateMixability(Check
, WorkType
, To
, Ctx
,
1067 ImplicitConversionModellingMode::None
);
1068 QualConv
.sanitize();
1069 if (hasFlag(QualConv
.Flags
, MixFlags::Qualifiers
)) {
1070 LLVM_DEBUG(llvm::dbgs()
1071 << "<<< approximateStdConv. Qualifiers adjusted.\n");
1075 if (WorkType
== To
) {
1076 LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Reached 'To' type.\n");
1080 LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Did not reach 'To'.\n");
1086 /// Helper class for storing possible user-defined conversion calls that
1087 /// *could* take place in an implicit conversion, and selecting the one that
1088 /// most likely *does*, if any.
1089 class UserDefinedConversionSelector
{
1091 /// The conversion associated with a conversion function, together with the
1092 /// mixability flags of the conversion function's parameter or return type
1093 /// to the rest of the sequence the selector is used in, and the sequence
1094 /// that applied through the conversion itself.
1095 struct PreparedConversion
{
1096 const CXXMethodDecl
*ConversionFun
;
1098 ConversionSequence Seq
;
1100 PreparedConversion(const CXXMethodDecl
*CMD
, MixFlags F
,
1101 ConversionSequence S
)
1102 : ConversionFun(CMD
), Flags(F
), Seq(S
) {}
1105 UserDefinedConversionSelector(const TheCheck
&Check
) : Check(Check
) {}
1107 /// Adds the conversion between the two types for the given function into
1108 /// the possible implicit conversion set. FromType and ToType is either:
1109 /// * the result of a standard sequence and a converting ctor parameter
1110 /// * the return type of a conversion operator and the expected target of
1111 /// an implicit conversion.
1112 void addConversion(const CXXMethodDecl
*ConvFun
, QualType FromType
,
1114 // Try to go from the FromType to the ToType with only a single implicit
1115 // conversion, to see if the conversion function is applicable.
1116 MixData Mix
= calculateMixability(
1117 Check
, FromType
, ToType
, ConvFun
->getASTContext(),
1118 ImplicitConversionModellingMode::OneWaySingleStandardOnly
);
1120 if (!Mix
.indicatesMixability())
1123 LLVM_DEBUG(llvm::dbgs() << "--- tryConversion. Found viable with flags: "
1124 << formatMixFlags(Mix
.Flags
) << '\n');
1125 FlaggedConversions
.emplace_back(ConvFun
, Mix
.Flags
, Mix
.Conversion
);
1128 /// Selects the best conversion function that is applicable from the
1129 /// prepared set of potential conversion functions taken.
1130 Optional
<PreparedConversion
> operator()() const {
1131 if (FlaggedConversions
.empty()) {
1132 LLVM_DEBUG(llvm::dbgs() << "--- selectUserDefinedConv. Empty.\n");
1135 if (FlaggedConversions
.size() == 1) {
1136 LLVM_DEBUG(llvm::dbgs() << "--- selectUserDefinedConv. Single.\n");
1137 return FlaggedConversions
.front();
1140 Optional
<PreparedConversion
> BestConversion
;
1141 unsigned short HowManyGoodConversions
= 0;
1142 for (const auto &Prepared
: FlaggedConversions
) {
1143 LLVM_DEBUG(llvm::dbgs() << "--- selectUserDefinedConv. Candidate flags: "
1144 << formatMixFlags(Prepared
.Flags
) << '\n');
1145 if (!BestConversion
) {
1146 BestConversion
= Prepared
;
1147 ++HowManyGoodConversions
;
1151 bool BestConversionHasImplicit
=
1152 hasFlag(BestConversion
->Flags
, MixFlags::ImplicitConversion
);
1153 bool ThisConversionHasImplicit
=
1154 hasFlag(Prepared
.Flags
, MixFlags::ImplicitConversion
);
1155 if (!BestConversionHasImplicit
&& ThisConversionHasImplicit
)
1156 // This is a worse conversion, because a better one was found earlier.
1159 if (BestConversionHasImplicit
&& !ThisConversionHasImplicit
) {
1160 // If the so far best selected conversion needs a previous implicit
1161 // conversion to match the user-defined converting function, but this
1162 // conversion does not, this is a better conversion, and we can throw
1163 // away the previously selected conversion(s).
1164 BestConversion
= Prepared
;
1165 HowManyGoodConversions
= 1;
1169 if (BestConversionHasImplicit
== ThisConversionHasImplicit
)
1170 // The current conversion is the same in term of goodness than the
1171 // already selected one.
1172 ++HowManyGoodConversions
;
1175 if (HowManyGoodConversions
== 1) {
1176 LLVM_DEBUG(llvm::dbgs()
1177 << "--- selectUserDefinedConv. Unique result. Flags: "
1178 << formatMixFlags(BestConversion
->Flags
) << '\n');
1179 return BestConversion
;
1182 LLVM_DEBUG(llvm::dbgs()
1183 << "--- selectUserDefinedConv. No, or ambiguous.\n");
1188 llvm::SmallVector
<PreparedConversion
, 2> FlaggedConversions
;
1189 const TheCheck
&Check
;
1194 static Optional
<ConversionSequence
>
1195 tryConversionOperators(const TheCheck
&Check
, const CXXRecordDecl
*RD
,
1197 if (!RD
|| !RD
->isCompleteDefinition())
1199 RD
= RD
->getDefinition();
1201 LLVM_DEBUG(llvm::dbgs() << ">>> tryConversionOperators: " << RD
->getName()
1203 ToType
.dump(llvm::dbgs(), RD
->getASTContext());
1204 llvm::dbgs() << '\n';);
1206 UserDefinedConversionSelector ConversionSet
{Check
};
1208 for (const NamedDecl
*Method
: RD
->getVisibleConversionFunctions()) {
1209 const auto *Con
= dyn_cast
<CXXConversionDecl
>(Method
);
1210 if (!Con
|| Con
->isExplicit())
1212 LLVM_DEBUG(llvm::dbgs() << "--- tryConversionOperators. Trying:\n";
1213 Con
->dump(llvm::dbgs()); llvm::dbgs() << '\n';);
1215 // Try to go from the result of conversion operator to the expected type,
1216 // without calculating another user-defined conversion.
1217 ConversionSet
.addConversion(Con
, Con
->getConversionType(), ToType
);
1220 if (Optional
<UserDefinedConversionSelector::PreparedConversion
>
1221 SelectedConversion
= ConversionSet()) {
1222 QualType RecordType
{RD
->getTypeForDecl(), 0};
1224 ConversionSequence Result
{RecordType
, ToType
};
1225 // The conversion from the operator call's return type to ToType was
1226 // modelled as a "pre-conversion" in the operator call, but it is the
1227 // "post-conversion" from the point of view of the original conversion
1228 // we are modelling.
1229 Result
.AfterSecondStandard
= SelectedConversion
->Seq
.AfterFirstStandard
;
1231 ConversionSequence::UserDefinedConversionOperator ConvOp
;
1232 ConvOp
.Fun
= cast
<CXXConversionDecl
>(SelectedConversion
->ConversionFun
);
1233 ConvOp
.UserDefinedType
= RecordType
;
1234 ConvOp
.ConversionOperatorResultType
= ConvOp
.Fun
->getConversionType();
1235 Result
.setConversion(ConvOp
);
1237 LLVM_DEBUG(llvm::dbgs() << "<<< tryConversionOperators. Found result.\n");
1241 LLVM_DEBUG(llvm::dbgs() << "<<< tryConversionOperators. No conversion.\n");
1245 static Optional
<ConversionSequence
>
1246 tryConvertingConstructors(const TheCheck
&Check
, QualType FromType
,
1247 const CXXRecordDecl
*RD
) {
1248 if (!RD
|| !RD
->isCompleteDefinition())
1250 RD
= RD
->getDefinition();
1252 LLVM_DEBUG(llvm::dbgs() << ">>> tryConveringConstructors: " << RD
->getName()
1254 FromType
.dump(llvm::dbgs(), RD
->getASTContext());
1255 llvm::dbgs() << '\n';);
1257 UserDefinedConversionSelector ConversionSet
{Check
};
1259 for (const CXXConstructorDecl
*Con
: RD
->ctors()) {
1260 if (Con
->isCopyOrMoveConstructor() ||
1261 !Con
->isConvertingConstructor(/* AllowExplicit =*/false))
1263 LLVM_DEBUG(llvm::dbgs() << "--- tryConvertingConstructors. Trying:\n";
1264 Con
->dump(llvm::dbgs()); llvm::dbgs() << '\n';);
1266 // Try to go from the original FromType to the converting constructor's
1267 // parameter type without another user-defined conversion.
1268 ConversionSet
.addConversion(Con
, FromType
, Con
->getParamDecl(0)->getType());
1271 if (Optional
<UserDefinedConversionSelector::PreparedConversion
>
1272 SelectedConversion
= ConversionSet()) {
1273 QualType RecordType
{RD
->getTypeForDecl(), 0};
1275 ConversionSequence Result
{FromType
, RecordType
};
1276 Result
.AfterFirstStandard
= SelectedConversion
->Seq
.AfterFirstStandard
;
1278 ConversionSequence::UserDefinedConvertingConstructor Ctor
;
1279 Ctor
.Fun
= cast
<CXXConstructorDecl
>(SelectedConversion
->ConversionFun
);
1280 Ctor
.ConstructorParameterType
= Ctor
.Fun
->getParamDecl(0)->getType();
1281 Ctor
.UserDefinedType
= RecordType
;
1282 Result
.setConversion(Ctor
);
1284 LLVM_DEBUG(llvm::dbgs()
1285 << "<<< tryConvertingConstructors. Found result.\n");
1289 LLVM_DEBUG(llvm::dbgs() << "<<< tryConvertingConstructors. No conversion.\n");
1293 /// Returns whether an expression of LType can be used in an RType context, as
1294 /// per the implicit conversion rules.
1296 /// Note: the result of this operation, unlike that of calculateMixability, is
1297 /// **NOT** symmetric.
1299 approximateImplicitConversion(const TheCheck
&Check
, QualType LType
,
1300 QualType RType
, const ASTContext
&Ctx
,
1301 ImplicitConversionModellingMode ImplicitMode
) {
1302 LLVM_DEBUG(llvm::dbgs() << ">>> approximateImplicitConversion for LType:\n";
1303 LType
.dump(llvm::dbgs(), Ctx
); llvm::dbgs() << "\nand RType:\n";
1304 RType
.dump(llvm::dbgs(), Ctx
);
1305 llvm::dbgs() << "\nimplicit mode: "; switch (ImplicitMode
) {
1306 case ImplicitConversionModellingMode::None
:
1307 llvm::dbgs() << "None";
1309 case ImplicitConversionModellingMode::All
:
1310 llvm::dbgs() << "All";
1312 case ImplicitConversionModellingMode::OneWaySingleStandardOnly
:
1313 llvm::dbgs() << "OneWay, Single, STD Only";
1315 } llvm::dbgs() << '\n';);
1317 return {MixFlags::Trivial
, LType
};
1319 // An implicit conversion sequence consists of the following, in order:
1320 // * Maybe standard conversion sequence.
1321 // * Maybe user-defined conversion.
1322 // * Maybe standard conversion sequence.
1323 ConversionSequence ImplicitSeq
{LType
, RType
};
1324 QualType WorkType
= LType
;
1326 Optional
<QualType
> AfterFirstStdConv
=
1327 approximateStandardConversionSequence(Check
, LType
, RType
, Ctx
);
1328 if (AfterFirstStdConv
) {
1329 LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Standard "
1330 "Pre-Conversion found!\n");
1331 ImplicitSeq
.AfterFirstStandard
= *AfterFirstStdConv
;
1332 WorkType
= ImplicitSeq
.AfterFirstStandard
;
1335 if (ImplicitMode
== ImplicitConversionModellingMode::OneWaySingleStandardOnly
)
1336 // If the caller only requested modelling of a standard conversion, bail.
1337 return {ImplicitSeq
.AfterFirstStandard
.isNull()
1339 : MixFlags::ImplicitConversion
,
1342 if (Ctx
.getLangOpts().CPlusPlus
) {
1343 bool FoundConversionOperator
= false, FoundConvertingCtor
= false;
1345 if (const auto *LRD
= WorkType
->getAsCXXRecordDecl()) {
1346 Optional
<ConversionSequence
> ConversionOperatorResult
=
1347 tryConversionOperators(Check
, LRD
, RType
);
1348 if (ConversionOperatorResult
) {
1349 LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Found "
1350 "conversion operator.\n");
1351 ImplicitSeq
.update(*ConversionOperatorResult
);
1352 WorkType
= ImplicitSeq
.getTypeAfterUserDefinedConversion();
1353 FoundConversionOperator
= true;
1357 if (const auto *RRD
= RType
->getAsCXXRecordDecl()) {
1358 // Use the original "LType" here, and not WorkType, because the
1359 // conversion to the converting constructors' parameters will be
1360 // modelled in the recursive call.
1361 Optional
<ConversionSequence
> ConvCtorResult
=
1362 tryConvertingConstructors(Check
, LType
, RRD
);
1363 if (ConvCtorResult
) {
1364 LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Found "
1365 "converting constructor.\n");
1366 ImplicitSeq
.update(*ConvCtorResult
);
1367 WorkType
= ImplicitSeq
.getTypeAfterUserDefinedConversion();
1368 FoundConvertingCtor
= true;
1372 if (FoundConversionOperator
&& FoundConvertingCtor
) {
1373 // If both an operator and a ctor matches, the sequence is ambiguous.
1374 LLVM_DEBUG(llvm::dbgs()
1375 << "<<< approximateImplicitConversion. Found both "
1376 "user-defined conversion kinds in the same sequence!\n");
1377 return {MixFlags::None
};
1381 // After the potential user-defined conversion, another standard conversion
1382 // sequence might exist.
1385 << "--- approximateImplicitConversion. Try to find post-conversion.\n");
1386 MixData SecondStdConv
= approximateImplicitConversion(
1387 Check
, WorkType
, RType
, Ctx
,
1388 ImplicitConversionModellingMode::OneWaySingleStandardOnly
);
1389 if (SecondStdConv
.indicatesMixability()) {
1390 LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Standard "
1391 "Post-Conversion found!\n");
1393 // The single-step modelling puts the modelled conversion into the "PreStd"
1394 // variable in the recursive call, but from the PoV of this function, it is
1395 // the post-conversion.
1396 ImplicitSeq
.AfterSecondStandard
=
1397 SecondStdConv
.Conversion
.AfterFirstStandard
;
1398 WorkType
= ImplicitSeq
.AfterSecondStandard
;
1402 LLVM_DEBUG(llvm::dbgs()
1403 << "<<< approximateImplicitConversion. Found a conversion.\n");
1404 return {MixFlags::ImplicitConversion
, ImplicitSeq
};
1408 llvm::dbgs() << "<<< approximateImplicitConversion. No match found.\n");
1409 return {MixFlags::None
};
1412 static MixableParameterRange
modelMixingRange(
1413 const TheCheck
&Check
, const FunctionDecl
*FD
, std::size_t StartIndex
,
1414 const filter::SimilarlyUsedParameterPairSuppressor
&UsageBasedSuppressor
) {
1415 std::size_t NumParams
= FD
->getNumParams();
1416 assert(StartIndex
< NumParams
&& "out of bounds for start");
1417 const ASTContext
&Ctx
= FD
->getASTContext();
1419 MixableParameterRange Ret
;
1420 // A parameter at index 'StartIndex' had been trivially "checked".
1421 Ret
.NumParamsChecked
= 1;
1423 for (std::size_t I
= StartIndex
+ 1; I
< NumParams
; ++I
) {
1424 const ParmVarDecl
*Ith
= FD
->getParamDecl(I
);
1425 StringRef ParamName
= Ith
->getName();
1426 LLVM_DEBUG(llvm::dbgs()
1427 << "Check param #" << I
<< " '" << ParamName
<< "'...\n");
1428 if (filter::isIgnoredParameter(Check
, Ith
)) {
1429 LLVM_DEBUG(llvm::dbgs() << "Param #" << I
<< " is ignored. Break!\n");
1433 StringRef PrevParamName
= FD
->getParamDecl(I
- 1)->getName();
1434 if (!ParamName
.empty() && !PrevParamName
.empty() &&
1435 filter::prefixSuffixCoverUnderThreshold(
1436 Check
.NamePrefixSuffixSilenceDissimilarityTreshold
, PrevParamName
,
1438 LLVM_DEBUG(llvm::dbgs() << "Parameter '" << ParamName
1439 << "' follows a pattern with previous parameter '"
1440 << PrevParamName
<< "'. Break!\n");
1444 // Now try to go forward and build the range of [Start, ..., I, I + 1, ...]
1445 // parameters that can be messed up at a call site.
1446 MixableParameterRange::MixVector MixesOfIth
;
1447 for (std::size_t J
= StartIndex
; J
< I
; ++J
) {
1448 const ParmVarDecl
*Jth
= FD
->getParamDecl(J
);
1449 LLVM_DEBUG(llvm::dbgs()
1450 << "Check mix of #" << J
<< " against #" << I
<< "...\n");
1452 if (isSimilarlyUsedParameter(UsageBasedSuppressor
, Ith
, Jth
)) {
1453 // Consider the two similarly used parameters to not be possible in a
1454 // mix-up at the user's request, if they enabled this heuristic.
1455 LLVM_DEBUG(llvm::dbgs() << "Parameters #" << I
<< " and #" << J
1456 << " deemed related, ignoring...\n");
1458 // If the parameter #I and #J mixes, then I is mixable with something
1459 // in the current range, so the range has to be broken and I not
1466 calculateMixability(Check
, Jth
->getType(), Ith
->getType(), Ctx
,
1467 Check
.ModelImplicitConversions
1468 ? ImplicitConversionModellingMode::All
1469 : ImplicitConversionModellingMode::None
)};
1470 LLVM_DEBUG(llvm::dbgs() << "Mix flags (raw) : "
1471 << formatMixFlags(M
.flags()) << '\n');
1473 LLVM_DEBUG(llvm::dbgs() << "Mix flags (after sanitize): "
1474 << formatMixFlags(M
.flags()) << '\n');
1476 assert(M
.flagsValid() && "All flags decayed!");
1479 MixesOfIth
.emplace_back(std::move(M
));
1482 if (MixesOfIth
.empty()) {
1483 // If there weren't any new mixes stored for Ith, the range is
1485 LLVM_DEBUG(llvm::dbgs()
1487 << " does not mix with any in the current range. Break!\n");
1491 Ret
.Mixes
.insert(Ret
.Mixes
.end(), MixesOfIth
.begin(), MixesOfIth
.end());
1492 ++Ret
.NumParamsChecked
; // Otherwise a new param was iterated.
1498 } // namespace model
1500 /// Matches DeclRefExprs and their ignorable wrappers to ParmVarDecls.
1501 AST_MATCHER_FUNCTION(ast_matchers::internal::Matcher
<Stmt
>, paramRefExpr
) {
1502 return expr(ignoringParenImpCasts(ignoringElidableConstructorCall(
1503 declRefExpr(to(parmVarDecl().bind("param"))))));
1508 /// Returns whether the parameter's name or the parameter's type's name is
1509 /// configured by the user to be ignored from analysis and diagnostic.
1510 static bool isIgnoredParameter(const TheCheck
&Check
, const ParmVarDecl
*Node
) {
1511 LLVM_DEBUG(llvm::dbgs() << "Checking if '" << Node
->getName()
1512 << "' is ignored.\n");
1514 if (!Node
->getIdentifier())
1515 return llvm::is_contained(Check
.IgnoredParameterNames
, "\"\"");
1517 StringRef NodeName
= Node
->getName();
1518 if (llvm::is_contained(Check
.IgnoredParameterNames
, NodeName
)) {
1519 LLVM_DEBUG(llvm::dbgs() << "\tName ignored.\n");
1523 StringRef NodeTypeName
= [Node
] {
1524 const ASTContext
&Ctx
= Node
->getASTContext();
1525 const SourceManager
&SM
= Ctx
.getSourceManager();
1526 SourceLocation B
= Node
->getTypeSpecStartLoc();
1527 SourceLocation E
= Node
->getTypeSpecEndLoc();
1530 LLVM_DEBUG(llvm::dbgs() << "\tType name code is '"
1531 << Lexer::getSourceText(
1532 CharSourceRange::getTokenRange(B
, E
), SM
, LO
)
1534 if (B
.isMacroID()) {
1535 LLVM_DEBUG(llvm::dbgs() << "\t\tBeginning is macro.\n");
1536 B
= SM
.getTopMacroCallerLoc(B
);
1538 if (E
.isMacroID()) {
1539 LLVM_DEBUG(llvm::dbgs() << "\t\tEnding is macro.\n");
1540 E
= Lexer::getLocForEndOfToken(SM
.getTopMacroCallerLoc(E
), 0, SM
, LO
);
1542 LLVM_DEBUG(llvm::dbgs() << "\tType name code is '"
1543 << Lexer::getSourceText(
1544 CharSourceRange::getTokenRange(B
, E
), SM
, LO
)
1547 return Lexer::getSourceText(CharSourceRange::getTokenRange(B
, E
), SM
, LO
);
1550 LLVM_DEBUG(llvm::dbgs() << "\tType name is '" << NodeTypeName
<< "'\n");
1551 if (!NodeTypeName
.empty()) {
1552 if (llvm::any_of(Check
.IgnoredParameterTypeSuffixes
,
1553 [NodeTypeName
](StringRef E
) {
1554 return !E
.empty() && NodeTypeName
.endswith(E
);
1556 LLVM_DEBUG(llvm::dbgs() << "\tType suffix ignored.\n");
1564 /// This namespace contains the implementations for the suppression of
1565 /// diagnostics from similarly-used ("related") parameters.
1566 namespace relatedness_heuristic
{
1568 static constexpr std::size_t SmallDataStructureSize
= 4;
1570 template <typename T
, std::size_t N
= SmallDataStructureSize
>
1571 using ParamToSmallSetMap
=
1572 llvm::DenseMap
<const ParmVarDecl
*, llvm::SmallSet
<T
, N
>>;
1574 /// Returns whether the sets mapped to the two elements in the map have at
1575 /// least one element in common.
1576 template <typename MapTy
, typename ElemTy
>
1577 bool lazyMapOfSetsIntersectionExists(const MapTy
&Map
, const ElemTy
&E1
,
1579 auto E1Iterator
= Map
.find(E1
);
1580 auto E2Iterator
= Map
.find(E2
);
1581 if (E1Iterator
== Map
.end() || E2Iterator
== Map
.end())
1584 for (const auto &E1SetElem
: E1Iterator
->second
)
1585 if (llvm::is_contained(E2Iterator
->second
, E1SetElem
))
1591 /// Implements the heuristic that marks two parameters related if there is
1592 /// a usage for both in the same strict expression subtree. A strict
1593 /// expression subtree is a tree which only includes Expr nodes, i.e. no
1594 /// Stmts and no Decls.
1595 class AppearsInSameExpr
: public RecursiveASTVisitor
<AppearsInSameExpr
> {
1596 using Base
= RecursiveASTVisitor
<AppearsInSameExpr
>;
1598 const FunctionDecl
*FD
;
1599 const Expr
*CurrentExprOnlyTreeRoot
= nullptr;
1600 llvm::DenseMap
<const ParmVarDecl
*,
1601 llvm::SmallPtrSet
<const Expr
*, SmallDataStructureSize
>>
1602 ParentExprsForParamRefs
;
1605 void setup(const FunctionDecl
*FD
) {
1607 TraverseFunctionDecl(const_cast<FunctionDecl
*>(FD
));
1610 bool operator()(const ParmVarDecl
*Param1
, const ParmVarDecl
*Param2
) const {
1611 return lazyMapOfSetsIntersectionExists(ParentExprsForParamRefs
, Param1
,
1615 bool TraverseDecl(Decl
*D
) {
1616 CurrentExprOnlyTreeRoot
= nullptr;
1617 return Base::TraverseDecl(D
);
1620 bool TraverseStmt(Stmt
*S
, DataRecursionQueue
*Queue
= nullptr) {
1621 if (auto *E
= dyn_cast_or_null
<Expr
>(S
)) {
1622 bool RootSetInCurrentStackFrame
= false;
1623 if (!CurrentExprOnlyTreeRoot
) {
1624 CurrentExprOnlyTreeRoot
= E
;
1625 RootSetInCurrentStackFrame
= true;
1628 bool Ret
= Base::TraverseStmt(S
);
1630 if (RootSetInCurrentStackFrame
)
1631 CurrentExprOnlyTreeRoot
= nullptr;
1636 // A Stmt breaks the strictly Expr subtree.
1637 CurrentExprOnlyTreeRoot
= nullptr;
1638 return Base::TraverseStmt(S
);
1641 bool VisitDeclRefExpr(DeclRefExpr
*DRE
) {
1642 if (!CurrentExprOnlyTreeRoot
)
1645 if (auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl()))
1646 if (llvm::find(FD
->parameters(), PVD
))
1647 ParentExprsForParamRefs
[PVD
].insert(CurrentExprOnlyTreeRoot
);
1653 /// Implements the heuristic that marks two parameters related if there are
1654 /// two separate calls to the same function (overload) and the parameters are
1655 /// passed to the same index in both calls, i.e f(a, b) and f(a, c) passes
1656 /// b and c to the same index (2) of f(), marking them related.
1657 class PassedToSameFunction
{
1658 ParamToSmallSetMap
<std::pair
<const FunctionDecl
*, unsigned>> TargetParams
;
1661 void setup(const FunctionDecl
*FD
) {
1662 auto ParamsAsArgsInFnCalls
=
1663 match(functionDecl(forEachDescendant(
1664 callExpr(forEachArgumentWithParam(
1665 paramRefExpr(), parmVarDecl().bind("passed-to")))
1666 .bind("call-expr"))),
1667 *FD
, FD
->getASTContext());
1668 for (const auto &Match
: ParamsAsArgsInFnCalls
) {
1669 const auto *PassedParamOfThisFn
= Match
.getNodeAs
<ParmVarDecl
>("param");
1670 const auto *CE
= Match
.getNodeAs
<CallExpr
>("call-expr");
1671 const auto *PassedToParam
= Match
.getNodeAs
<ParmVarDecl
>("passed-to");
1672 assert(PassedParamOfThisFn
&& CE
&& PassedToParam
);
1674 const FunctionDecl
*CalledFn
= CE
->getDirectCallee();
1678 llvm::Optional
<unsigned> TargetIdx
;
1679 unsigned NumFnParams
= CalledFn
->getNumParams();
1680 for (unsigned Idx
= 0; Idx
< NumFnParams
; ++Idx
)
1681 if (CalledFn
->getParamDecl(Idx
) == PassedToParam
)
1682 TargetIdx
.emplace(Idx
);
1684 assert(TargetIdx
&& "Matched, but didn't find index?");
1685 TargetParams
[PassedParamOfThisFn
].insert(
1686 {CalledFn
->getCanonicalDecl(), *TargetIdx
});
1690 bool operator()(const ParmVarDecl
*Param1
, const ParmVarDecl
*Param2
) const {
1691 return lazyMapOfSetsIntersectionExists(TargetParams
, Param1
, Param2
);
1695 /// Implements the heuristic that marks two parameters related if the same
1696 /// member is accessed (referred to) inside the current function's body.
1697 class AccessedSameMemberOf
{
1698 ParamToSmallSetMap
<const Decl
*> AccessedMembers
;
1701 void setup(const FunctionDecl
*FD
) {
1702 auto MembersCalledOnParams
= match(
1703 functionDecl(forEachDescendant(
1704 memberExpr(hasObjectExpression(paramRefExpr())).bind("mem-expr"))),
1705 *FD
, FD
->getASTContext());
1707 for (const auto &Match
: MembersCalledOnParams
) {
1708 const auto *AccessedParam
= Match
.getNodeAs
<ParmVarDecl
>("param");
1709 const auto *ME
= Match
.getNodeAs
<MemberExpr
>("mem-expr");
1710 assert(AccessedParam
&& ME
);
1711 AccessedMembers
[AccessedParam
].insert(
1712 ME
->getMemberDecl()->getCanonicalDecl());
1716 bool operator()(const ParmVarDecl
*Param1
, const ParmVarDecl
*Param2
) const {
1717 return lazyMapOfSetsIntersectionExists(AccessedMembers
, Param1
, Param2
);
1721 /// Implements the heuristic that marks two parameters related if different
1722 /// ReturnStmts return them from the function.
1724 llvm::SmallVector
<const ParmVarDecl
*, SmallDataStructureSize
> ReturnedParams
;
1727 void setup(const FunctionDecl
*FD
) {
1728 // TODO: Handle co_return.
1729 auto ParamReturns
= match(functionDecl(forEachDescendant(
1730 returnStmt(hasReturnValue(paramRefExpr())))),
1731 *FD
, FD
->getASTContext());
1732 for (const auto &Match
: ParamReturns
) {
1733 const auto *ReturnedParam
= Match
.getNodeAs
<ParmVarDecl
>("param");
1734 assert(ReturnedParam
);
1736 if (find(FD
->parameters(), ReturnedParam
) == FD
->param_end())
1737 // Inside the subtree of a FunctionDecl there might be ReturnStmts of
1738 // a parameter that isn't the parameter of the function, e.g. in the
1742 ReturnedParams
.emplace_back(ReturnedParam
);
1746 bool operator()(const ParmVarDecl
*Param1
, const ParmVarDecl
*Param2
) const {
1747 return llvm::is_contained(ReturnedParams
, Param1
) &&
1748 llvm::is_contained(ReturnedParams
, Param2
);
1752 } // namespace relatedness_heuristic
1754 /// Helper class that is used to detect if two parameters of the same function
1755 /// are used in a similar fashion, to suppress the result.
1756 class SimilarlyUsedParameterPairSuppressor
{
1758 relatedness_heuristic::AppearsInSameExpr SameExpr
;
1759 relatedness_heuristic::PassedToSameFunction PassToFun
;
1760 relatedness_heuristic::AccessedSameMemberOf SameMember
;
1761 relatedness_heuristic::Returned Returns
;
1764 SimilarlyUsedParameterPairSuppressor(const FunctionDecl
*FD
, bool Enable
)
1770 PassToFun
.setup(FD
);
1771 SameMember
.setup(FD
);
1775 /// Returns whether the specified two parameters are deemed similarly used
1776 /// or related by the heuristics.
1777 bool operator()(const ParmVarDecl
*Param1
, const ParmVarDecl
*Param2
) const {
1781 LLVM_DEBUG(llvm::dbgs()
1782 << "::: Matching similar usage / relatedness heuristic...\n");
1784 if (SameExpr(Param1
, Param2
)) {
1785 LLVM_DEBUG(llvm::dbgs() << "::: Used in the same expression.\n");
1789 if (PassToFun(Param1
, Param2
)) {
1790 LLVM_DEBUG(llvm::dbgs()
1791 << "::: Passed to same function in different calls.\n");
1795 if (SameMember(Param1
, Param2
)) {
1796 LLVM_DEBUG(llvm::dbgs()
1797 << "::: Same member field access or method called.\n");
1801 if (Returns(Param1
, Param2
)) {
1802 LLVM_DEBUG(llvm::dbgs() << "::: Both parameter returned.\n");
1806 LLVM_DEBUG(llvm::dbgs() << "::: None.\n");
1811 // (This function hoists the call to operator() of the wrapper, so we do not
1812 // need to define the previous class at the top of the file.)
1814 isSimilarlyUsedParameter(const SimilarlyUsedParameterPairSuppressor
&Suppressor
,
1815 const ParmVarDecl
*Param1
, const ParmVarDecl
*Param2
) {
1816 return Suppressor(Param1
, Param2
);
1819 static void padStringAtEnd(SmallVectorImpl
<char> &Str
, std::size_t ToLen
) {
1820 while (Str
.size() < ToLen
)
1821 Str
.emplace_back('\0');
1824 static void padStringAtBegin(SmallVectorImpl
<char> &Str
, std::size_t ToLen
) {
1825 while (Str
.size() < ToLen
)
1826 Str
.insert(Str
.begin(), '\0');
1829 static bool isCommonPrefixWithoutSomeCharacters(std::size_t N
, StringRef S1
,
1831 assert(S1
.size() >= N
&& S2
.size() >= N
);
1832 StringRef S1Prefix
= S1
.take_front(S1
.size() - N
),
1833 S2Prefix
= S2
.take_front(S2
.size() - N
);
1834 return S1Prefix
== S2Prefix
&& !S1Prefix
.empty();
1837 static bool isCommonSuffixWithoutSomeCharacters(std::size_t N
, StringRef S1
,
1839 assert(S1
.size() >= N
&& S2
.size() >= N
);
1840 StringRef S1Suffix
= S1
.take_back(S1
.size() - N
),
1841 S2Suffix
= S2
.take_back(S2
.size() - N
);
1842 return S1Suffix
== S2Suffix
&& !S1Suffix
.empty();
1845 /// Returns whether the two strings are prefixes or suffixes of each other with
1846 /// at most Threshold characters differing on the non-common end.
1847 static bool prefixSuffixCoverUnderThreshold(std::size_t Threshold
,
1848 StringRef Str1
, StringRef Str2
) {
1852 // Pad the two strings to the longer length.
1853 std::size_t BiggerLength
= std::max(Str1
.size(), Str2
.size());
1855 if (BiggerLength
<= Threshold
)
1856 // If the length of the strings is still smaller than the threshold, they
1857 // would be covered by an empty prefix/suffix with the rest differing.
1858 // (E.g. "A" and "X" with Threshold = 1 would mean we think they are
1859 // similar and do not warn about them, which is a too eager assumption.)
1862 SmallString
<32> S1PadE
{Str1
}, S2PadE
{Str2
};
1863 padStringAtEnd(S1PadE
, BiggerLength
);
1864 padStringAtEnd(S2PadE
, BiggerLength
);
1866 if (isCommonPrefixWithoutSomeCharacters(
1867 Threshold
, StringRef
{S1PadE
.begin(), BiggerLength
},
1868 StringRef
{S2PadE
.begin(), BiggerLength
}))
1871 SmallString
<32> S1PadB
{Str1
}, S2PadB
{Str2
};
1872 padStringAtBegin(S1PadB
, BiggerLength
);
1873 padStringAtBegin(S2PadB
, BiggerLength
);
1875 if (isCommonSuffixWithoutSomeCharacters(
1876 Threshold
, StringRef
{S1PadB
.begin(), BiggerLength
},
1877 StringRef
{S2PadB
.begin(), BiggerLength
}))
1883 } // namespace filter
1885 /// Matches functions that have at least the specified amount of parameters.
1886 AST_MATCHER_P(FunctionDecl
, parameterCountGE
, unsigned, N
) {
1887 return Node
.getNumParams() >= N
;
1890 /// Matches *any* overloaded unary and binary operators.
1891 AST_MATCHER(FunctionDecl
, isOverloadedUnaryOrBinaryOperator
) {
1892 switch (Node
.getOverloadedOperator()) {
1897 case OO_Array_Delete
:
1898 case OO_Conditional
:
1903 return Node
.getNumParams() <= 2;
1907 /// Returns the DefaultMinimumLength if the Value of requested minimum length
1908 /// is less than 2. Minimum lengths of 0 or 1 are not accepted.
1909 static inline unsigned clampMinimumLength(const unsigned Value
) {
1910 return Value
< 2 ? DefaultMinimumLength
: Value
;
1913 // FIXME: Maybe unneeded, getNameForDiagnostic() is expected to change to return
1914 // a crafted location when the node itself is unnamed. (See D84658, D85033.)
1915 /// Returns the diagnostic-friendly name of the node, or empty string.
1916 static SmallString
<64> getName(const NamedDecl
*ND
) {
1917 SmallString
<64> Name
;
1918 llvm::raw_svector_ostream OS
{Name
};
1919 ND
->getNameForDiagnostic(OS
, ND
->getASTContext().getPrintingPolicy(), false);
1923 /// Returns the diagnostic-friendly name of the node, or a constant value.
1924 static SmallString
<64> getNameOrUnnamed(const NamedDecl
*ND
) {
1925 auto Name
= getName(ND
);
1931 /// Returns whether a particular Mix between two parameters should have the
1932 /// types involved diagnosed to the user. This is only a flag check.
1933 static inline bool needsToPrintTypeInDiagnostic(const model::Mix
&M
) {
1934 using namespace model
;
1935 return static_cast<bool>(
1937 (MixFlags::TypeAlias
| MixFlags::ReferenceBind
| MixFlags::Qualifiers
));
1940 /// Returns whether a particular Mix between the two parameters should have
1941 /// implicit conversions elaborated.
1942 static inline bool needsToElaborateImplicitConversion(const model::Mix
&M
) {
1943 return hasFlag(M
.flags(), model::MixFlags::ImplicitConversion
);
1948 /// This class formats a conversion sequence into a "Ty1 -> Ty2 -> Ty3" line
1949 /// that can be used in diagnostics.
1950 struct FormattedConversionSequence
{
1951 std::string DiagnosticText
;
1953 /// The formatted sequence is trivial if it is "Ty1 -> Ty2", but Ty1 and
1954 /// Ty2 are the types that are shown in the code. A trivial diagnostic
1955 /// does not need to be printed.
1958 FormattedConversionSequence(const PrintingPolicy
&PP
,
1959 StringRef StartTypeAsDiagnosed
,
1960 const model::ConversionSequence
&Conv
,
1961 StringRef DestinationTypeAsDiagnosed
) {
1963 llvm::raw_string_ostream OS
{DiagnosticText
};
1965 // Print the type name as it is printed in other places in the diagnostic.
1966 OS
<< '\'' << StartTypeAsDiagnosed
<< '\'';
1967 std::string LastAddedType
= StartTypeAsDiagnosed
.str();
1968 std::size_t NumElementsAdded
= 1;
1970 // However, the parameter's defined type might not be what the implicit
1971 // conversion started with, e.g. if a typedef is found to convert.
1972 std::string SeqBeginTypeStr
= Conv
.Begin
.getAsString(PP
);
1973 std::string SeqEndTypeStr
= Conv
.End
.getAsString(PP
);
1974 if (StartTypeAsDiagnosed
!= SeqBeginTypeStr
) {
1975 OS
<< " (as '" << SeqBeginTypeStr
<< "')";
1976 LastAddedType
= SeqBeginTypeStr
;
1980 auto AddType
= [&](StringRef ToAdd
) {
1981 if (LastAddedType
!= ToAdd
&& ToAdd
!= SeqEndTypeStr
) {
1982 OS
<< " -> '" << ToAdd
<< "'";
1983 LastAddedType
= ToAdd
.str();
1987 for (QualType InvolvedType
: Conv
.getInvolvedTypesInSequence())
1988 // Print every type that's unique in the sequence into the diagnosis.
1989 AddType(InvolvedType
.getAsString(PP
));
1991 if (LastAddedType
!= DestinationTypeAsDiagnosed
) {
1992 OS
<< " -> '" << DestinationTypeAsDiagnosed
<< "'";
1993 LastAddedType
= DestinationTypeAsDiagnosed
.str();
1997 // Same reasoning as with the Begin, e.g. if the converted-to type is a
1998 // typedef, it will not be the same inside the conversion sequence (where
1999 // the model already tore off typedefs) as in the code.
2000 if (DestinationTypeAsDiagnosed
!= SeqEndTypeStr
) {
2001 OS
<< " (as '" << SeqEndTypeStr
<< "')";
2002 LastAddedType
= SeqEndTypeStr
;
2006 if (Trivial
&& NumElementsAdded
> 2)
2007 // If the thing is still marked trivial but we have more than the
2008 // from and to types added, it should not be trivial, and elaborated
2009 // when printing the diagnostic.
2014 /// Retains the elements called with and returns whether the call is done with
2016 template <typename E
, std::size_t N
> class InsertOnce
{
2017 llvm::SmallSet
<E
, N
> CalledWith
;
2020 bool operator()(E El
) { return CalledWith
.insert(std::move(El
)).second
; }
2022 bool calledWith(const E
&El
) const { return CalledWith
.contains(El
); }
2025 struct SwappedEqualQualTypePair
{
2026 QualType LHSType
, RHSType
;
2028 bool operator==(const SwappedEqualQualTypePair
&Other
) const {
2029 return (LHSType
== Other
.LHSType
&& RHSType
== Other
.RHSType
) ||
2030 (LHSType
== Other
.RHSType
&& RHSType
== Other
.LHSType
);
2033 bool operator<(const SwappedEqualQualTypePair
&Other
) const {
2034 return LHSType
< Other
.LHSType
&& RHSType
< Other
.RHSType
;
2038 struct TypeAliasDiagnosticTuple
{
2039 QualType LHSType
, RHSType
, CommonType
;
2041 bool operator==(const TypeAliasDiagnosticTuple
&Other
) const {
2042 return CommonType
== Other
.CommonType
&&
2043 ((LHSType
== Other
.LHSType
&& RHSType
== Other
.RHSType
) ||
2044 (LHSType
== Other
.RHSType
&& RHSType
== Other
.LHSType
));
2047 bool operator<(const TypeAliasDiagnosticTuple
&Other
) const {
2048 return CommonType
< Other
.CommonType
&& LHSType
< Other
.LHSType
&&
2049 RHSType
< Other
.RHSType
;
2053 /// Helper class to only emit a diagnostic related to MixFlags::TypeAlias once.
2054 class UniqueTypeAliasDiagnosticHelper
2055 : public InsertOnce
<TypeAliasDiagnosticTuple
, 8> {
2056 using Base
= InsertOnce
<TypeAliasDiagnosticTuple
, 8>;
2059 /// Returns whether the diagnostic for LHSType and RHSType which are both
2060 /// referring to CommonType being the same has not been emitted already.
2061 bool operator()(QualType LHSType
, QualType RHSType
, QualType CommonType
) {
2062 if (CommonType
.isNull() || CommonType
== LHSType
|| CommonType
== RHSType
)
2063 return Base::operator()({LHSType
, RHSType
, {}});
2065 TypeAliasDiagnosticTuple ThreeTuple
{LHSType
, RHSType
, CommonType
};
2066 if (!Base::operator()(ThreeTuple
))
2069 bool AlreadySaidLHSAndCommonIsSame
= calledWith({LHSType
, CommonType
, {}});
2070 bool AlreadySaidRHSAndCommonIsSame
= calledWith({RHSType
, CommonType
, {}});
2071 if (AlreadySaidLHSAndCommonIsSame
&& AlreadySaidRHSAndCommonIsSame
) {
2072 // "SomeInt == int" && "SomeOtherInt == int" => "Common(SomeInt,
2073 // SomeOtherInt) == int", no need to diagnose it. Save the 3-tuple only
2074 // for shortcut if it ever appears again.
2084 EasilySwappableParametersCheck::EasilySwappableParametersCheck(
2085 StringRef Name
, ClangTidyContext
*Context
)
2086 : ClangTidyCheck(Name
, Context
),
2087 MinimumLength(clampMinimumLength(
2088 Options
.get("MinimumLength", DefaultMinimumLength
))),
2089 IgnoredParameterNames(optutils::parseStringList(
2090 Options
.get("IgnoredParameterNames", DefaultIgnoredParameterNames
))),
2091 IgnoredParameterTypeSuffixes(optutils::parseStringList(
2092 Options
.get("IgnoredParameterTypeSuffixes",
2093 DefaultIgnoredParameterTypeSuffixes
))),
2094 QualifiersMix(Options
.get("QualifiersMix", DefaultQualifiersMix
)),
2095 ModelImplicitConversions(Options
.get("ModelImplicitConversions",
2096 DefaultModelImplicitConversions
)),
2097 SuppressParametersUsedTogether(
2098 Options
.get("SuppressParametersUsedTogether",
2099 DefaultSuppressParametersUsedTogether
)),
2100 NamePrefixSuffixSilenceDissimilarityTreshold(
2101 Options
.get("NamePrefixSuffixSilenceDissimilarityTreshold",
2102 DefaultNamePrefixSuffixSilenceDissimilarityTreshold
)) {}
2104 void EasilySwappableParametersCheck::storeOptions(
2105 ClangTidyOptions::OptionMap
&Opts
) {
2106 Options
.store(Opts
, "MinimumLength", MinimumLength
);
2107 Options
.store(Opts
, "IgnoredParameterNames",
2108 optutils::serializeStringList(IgnoredParameterNames
));
2109 Options
.store(Opts
, "IgnoredParameterTypeSuffixes",
2110 optutils::serializeStringList(IgnoredParameterTypeSuffixes
));
2111 Options
.store(Opts
, "QualifiersMix", QualifiersMix
);
2112 Options
.store(Opts
, "ModelImplicitConversions", ModelImplicitConversions
);
2113 Options
.store(Opts
, "SuppressParametersUsedTogether",
2114 SuppressParametersUsedTogether
);
2115 Options
.store(Opts
, "NamePrefixSuffixSilenceDissimilarityTreshold",
2116 NamePrefixSuffixSilenceDissimilarityTreshold
);
2119 void EasilySwappableParametersCheck::registerMatchers(MatchFinder
*Finder
) {
2120 const auto BaseConstraints
= functionDecl(
2121 // Only report for definition nodes, as fixing the issues reported
2122 // requires the user to be able to change code.
2123 isDefinition(), parameterCountGE(MinimumLength
),
2124 unless(isOverloadedUnaryOrBinaryOperator()));
2127 functionDecl(BaseConstraints
,
2128 unless(ast_matchers::isTemplateInstantiation()))
2132 functionDecl(BaseConstraints
, isExplicitTemplateSpecialization())
2137 void EasilySwappableParametersCheck::check(
2138 const MatchFinder::MatchResult
&Result
) {
2139 using namespace model
;
2140 using namespace filter
;
2142 const auto *FD
= Result
.Nodes
.getNodeAs
<FunctionDecl
>("func");
2145 const PrintingPolicy
&PP
= FD
->getASTContext().getPrintingPolicy();
2146 std::size_t NumParams
= FD
->getNumParams();
2147 std::size_t MixableRangeStartIndex
= 0;
2149 // Spawn one suppressor and if the user requested, gather information from
2150 // the AST for the parameters' usages.
2151 filter::SimilarlyUsedParameterPairSuppressor UsageBasedSuppressor
{
2152 FD
, SuppressParametersUsedTogether
};
2154 LLVM_DEBUG(llvm::dbgs() << "Begin analysis of " << getName(FD
) << " with "
2155 << NumParams
<< " parameters...\n");
2156 while (MixableRangeStartIndex
< NumParams
) {
2157 if (isIgnoredParameter(*this, FD
->getParamDecl(MixableRangeStartIndex
))) {
2158 LLVM_DEBUG(llvm::dbgs()
2159 << "Parameter #" << MixableRangeStartIndex
<< " ignored.\n");
2160 ++MixableRangeStartIndex
;
2164 MixableParameterRange R
= modelMixingRange(
2165 *this, FD
, MixableRangeStartIndex
, UsageBasedSuppressor
);
2166 assert(R
.NumParamsChecked
> 0 && "Ensure forward progress!");
2167 MixableRangeStartIndex
+= R
.NumParamsChecked
;
2168 if (R
.NumParamsChecked
< MinimumLength
) {
2169 LLVM_DEBUG(llvm::dbgs() << "Ignoring range of " << R
.NumParamsChecked
2170 << " lower than limit.\n");
2174 bool NeedsAnyTypeNote
= llvm::any_of(R
.Mixes
, needsToPrintTypeInDiagnostic
);
2175 bool HasAnyImplicits
=
2176 llvm::any_of(R
.Mixes
, needsToElaborateImplicitConversion
);
2177 const ParmVarDecl
*First
= R
.getFirstParam(), *Last
= R
.getLastParam();
2178 std::string FirstParamTypeAsWritten
= First
->getType().getAsString(PP
);
2182 if (HasAnyImplicits
)
2183 DiagText
= "%0 adjacent parameters of %1 of convertible types are "
2184 "easily swapped by mistake";
2185 else if (NeedsAnyTypeNote
)
2186 DiagText
= "%0 adjacent parameters of %1 of similar type are easily "
2187 "swapped by mistake";
2189 DiagText
= "%0 adjacent parameters of %1 of similar type ('%2') are "
2190 "easily swapped by mistake";
2192 auto Diag
= diag(First
->getOuterLocStart(), DiagText
)
2193 << static_cast<unsigned>(R
.NumParamsChecked
) << FD
;
2194 if (!NeedsAnyTypeNote
)
2195 Diag
<< FirstParamTypeAsWritten
;
2197 CharSourceRange HighlightRange
= CharSourceRange::getTokenRange(
2198 First
->getBeginLoc(), Last
->getEndLoc());
2199 Diag
<< HighlightRange
;
2202 // There is a chance that the previous highlight did not succeed, e.g. when
2203 // the two parameters are on different lines. For clarity, show the user
2204 // the involved variable explicitly.
2205 diag(First
->getLocation(), "the first parameter in the range is '%0'",
2206 DiagnosticIDs::Note
)
2207 << getNameOrUnnamed(First
)
2208 << CharSourceRange::getTokenRange(First
->getLocation(),
2209 First
->getLocation());
2210 diag(Last
->getLocation(), "the last parameter in the range is '%0'",
2211 DiagnosticIDs::Note
)
2212 << getNameOrUnnamed(Last
)
2213 << CharSourceRange::getTokenRange(Last
->getLocation(),
2214 Last
->getLocation());
2216 // Helper classes to silence elaborative diagnostic notes that would be
2218 UniqueTypeAliasDiagnosticHelper UniqueTypeAlias
;
2219 InsertOnce
<SwappedEqualQualTypePair
, 8> UniqueBindPower
;
2220 InsertOnce
<SwappedEqualQualTypePair
, 8> UniqueImplicitConversion
;
2222 for (const model::Mix
&M
: R
.Mixes
) {
2223 assert(M
.mixable() && "Sentinel or false mix in result.");
2224 if (!needsToPrintTypeInDiagnostic(M
) &&
2225 !needsToElaborateImplicitConversion(M
))
2228 // Typedefs might result in the type of the variable needing to be
2229 // emitted to a note diagnostic, so prepare it.
2230 const ParmVarDecl
*LVar
= M
.First
;
2231 const ParmVarDecl
*RVar
= M
.Second
;
2232 QualType LType
= LVar
->getType();
2233 QualType RType
= RVar
->getType();
2234 QualType CommonType
= M
.commonUnderlyingType();
2235 std::string LTypeStr
= LType
.getAsString(PP
);
2236 std::string RTypeStr
= RType
.getAsString(PP
);
2237 std::string CommonTypeStr
= CommonType
.getAsString(PP
);
2239 if (hasFlag(M
.flags(), MixFlags::TypeAlias
) &&
2240 UniqueTypeAlias(LType
, RType
, CommonType
)) {
2242 bool ExplicitlyPrintCommonType
= false;
2243 if (LTypeStr
== CommonTypeStr
|| RTypeStr
== CommonTypeStr
) {
2244 if (hasFlag(M
.flags(), MixFlags::Qualifiers
))
2245 DiagText
= "after resolving type aliases, '%0' and '%1' share a "
2249 "after resolving type aliases, '%0' and '%1' are the same";
2250 } else if (!CommonType
.isNull()) {
2251 DiagText
= "after resolving type aliases, the common type of '%0' "
2253 ExplicitlyPrintCommonType
= true;
2257 diag(LVar
->getOuterLocStart(), DiagText
, DiagnosticIDs::Note
)
2258 << LTypeStr
<< RTypeStr
;
2259 if (ExplicitlyPrintCommonType
)
2260 Diag
<< CommonTypeStr
;
2263 if ((hasFlag(M
.flags(), MixFlags::ReferenceBind
) ||
2264 hasFlag(M
.flags(), MixFlags::Qualifiers
)) &&
2265 UniqueBindPower({LType
, RType
})) {
2266 StringRef DiagText
= "'%0' and '%1' parameters accept and bind the "
2267 "same kind of values";
2268 diag(RVar
->getOuterLocStart(), DiagText
, DiagnosticIDs::Note
)
2269 << LTypeStr
<< RTypeStr
;
2272 if (needsToElaborateImplicitConversion(M
) &&
2273 UniqueImplicitConversion({LType
, RType
})) {
2274 const model::ConversionSequence
<R
=
2275 M
.leftToRightConversionSequence();
2276 const model::ConversionSequence
&RTL
=
2277 M
.rightToLeftConversionSequence();
2278 FormattedConversionSequence LTRFmt
{PP
, LTypeStr
, LTR
, RTypeStr
};
2279 FormattedConversionSequence RTLFmt
{PP
, RTypeStr
, RTL
, LTypeStr
};
2281 StringRef DiagText
= "'%0' and '%1' may be implicitly converted";
2282 if (!LTRFmt
.Trivial
|| !RTLFmt
.Trivial
)
2283 DiagText
= "'%0' and '%1' may be implicitly converted: %2, %3";
2287 diag(RVar
->getOuterLocStart(), DiagText
, DiagnosticIDs::Note
)
2288 << LTypeStr
<< RTypeStr
;
2290 if (!LTRFmt
.Trivial
|| !RTLFmt
.Trivial
)
2291 Diag
<< LTRFmt
.DiagnosticText
<< RTLFmt
.DiagnosticText
;
2294 StringRef ConversionFunctionDiagText
=
2295 "the implicit conversion involves the "
2296 "%select{|converting constructor|conversion operator}0 "
2298 if (const FunctionDecl
*LFD
= LTR
.getUserDefinedConversionFunction())
2299 diag(LFD
->getLocation(), ConversionFunctionDiagText
,
2300 DiagnosticIDs::Note
)
2301 << static_cast<unsigned>(LTR
.UDConvKind
)
2302 << LTR
.getUserDefinedConversionHighlight();
2303 if (const FunctionDecl
*RFD
= RTL
.getUserDefinedConversionFunction())
2304 diag(RFD
->getLocation(), ConversionFunctionDiagText
,
2305 DiagnosticIDs::Note
)
2306 << static_cast<unsigned>(RTL
.UDConvKind
)
2307 << RTL
.getUserDefinedConversionHighlight();
2313 } // namespace bugprone
2315 } // namespace clang