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