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