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