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