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