1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s 2 3 #include "mock-types.h" 4 #include "mock-system-header.h" 5 6 void WTFBreakpointTrap(); 7 void WTFCrashWithInfo(int, const char*, const char*, int); 8 void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion); 9 void WTFReportBacktrace(void); 10 11 void WTFCrash(void); 12 void WTFCrashWithSecurityImplication(void); 13 14 inline void compilerFenceForCrash() 15 { 16 asm volatile("" ::: "memory"); 17 } 18 19 inline void isIntegralOrPointerType() { } 20 21 template<typename T, typename... Types> 22 void isIntegralOrPointerType(T, Types... types) 23 { 24 static_assert(sizeof(char) < sizeof(short), "All types need to be bitwise_cast-able to integral type for logging"); 25 isIntegralOrPointerType(types...); 26 } 27 28 #define CRASH_WITH_INFO(...) do { \ 29 isIntegralOrPointerType(__VA_ARGS__); \ 30 compilerFenceForCrash(); \ 31 WTFBreakpointTrap(); \ 32 __builtin_unreachable(); \ 33 } while (0) 34 35 #define RELEASE_ASSERT(assertion, ...) do { \ 36 if (!(assertion)) \ 37 CRASH_WITH_INFO(__VA_ARGS__); \ 38 } while (0) 39 40 #define ASSERT(assertion, ...) do { \ 41 if (!(assertion)) { \ 42 WTFReportAssertionFailure(__FILE__, __LINE__, __PRETTY_FUNCTION__, #assertion); \ 43 CRASH_WITH_INFO(__VA_ARGS__); \ 44 } \ 45 } while (0) 46 47 #if !defined(ALWAYS_INLINE) 48 #define ALWAYS_INLINE inline 49 #endif 50 51 void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, unsigned long reason); 52 void WTFCrashWithInfo(int line, const char* file, const char* function, int counter); 53 54 template<typename T> 55 ALWAYS_INLINE unsigned long wtfCrashArg(T* arg) { return reinterpret_cast<unsigned long>(arg); } 56 57 template<typename T> 58 ALWAYS_INLINE unsigned long wtfCrashArg(T arg) { return arg; } 59 60 template<typename T> 61 void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason) 62 { 63 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason)); 64 } 65 66 template<typename ToType, typename FromType> 67 ToType bitwise_cast(FromType from); 68 69 namespace std { 70 71 template<typename T> 72 T* addressof(T& arg); 73 74 template<typename T> 75 T&& forward(T& arg); 76 77 template<typename T> 78 T&& move( T&& t ); 79 80 } // namespace std 81 82 bool isMainThread(); 83 bool isMainThreadOrGCThread(); 84 bool isMainRunLoop(); 85 bool isWebThread(); 86 bool isUIThread(); 87 bool mayBeGCThread(); 88 89 enum class Flags : unsigned short { 90 Flag1 = 1 << 0, 91 Flag2 = 1 << 1, 92 Flag3 = 1 << 2, 93 }; 94 95 template<typename E> class OptionSet { 96 public: 97 using StorageType = unsigned short; 98 99 static constexpr OptionSet fromRaw(StorageType rawValue) { 100 return OptionSet(static_cast<E>(rawValue), FromRawValue); 101 } 102 103 constexpr OptionSet() = default; 104 105 constexpr OptionSet(E e) 106 : m_storage(static_cast<StorageType>(e)) { 107 } 108 109 constexpr StorageType toRaw() const { return m_storage; } 110 111 constexpr bool isEmpty() const { return !m_storage; } 112 113 constexpr explicit operator bool() const { return !isEmpty(); } 114 115 constexpr bool contains(E option) const { return containsAny(option); } 116 constexpr bool containsAny(OptionSet optionSet) const { 117 return !!(*this & optionSet); 118 } 119 120 constexpr bool containsAll(OptionSet optionSet) const { 121 return (*this & optionSet) == optionSet; 122 } 123 124 constexpr void add(OptionSet optionSet) { m_storage |= optionSet.m_storage; } 125 126 constexpr void remove(OptionSet optionSet) 127 { 128 m_storage &= ~optionSet.m_storage; 129 } 130 131 constexpr void set(OptionSet optionSet, bool value) 132 { 133 if (value) 134 add(optionSet); 135 else 136 remove(optionSet); 137 } 138 139 constexpr friend OptionSet operator|(OptionSet lhs, OptionSet rhs) { 140 return fromRaw(lhs.m_storage | rhs.m_storage); 141 } 142 143 constexpr friend OptionSet operator&(OptionSet lhs, OptionSet rhs) { 144 return fromRaw(lhs.m_storage & rhs.m_storage); 145 } 146 147 constexpr friend OptionSet operator-(OptionSet lhs, OptionSet rhs) { 148 return fromRaw(lhs.m_storage & ~rhs.m_storage); 149 } 150 151 constexpr friend OptionSet operator^(OptionSet lhs, OptionSet rhs) { 152 return fromRaw(lhs.m_storage ^ rhs.m_storage); 153 } 154 155 private: 156 enum InitializationTag { FromRawValue }; 157 constexpr OptionSet(E e, InitializationTag) 158 : m_storage(static_cast<StorageType>(e)) { 159 } 160 StorageType m_storage { 0 }; 161 }; 162 163 int atoi(const char* str); 164 165 class Number { 166 public: 167 Number(int v) : v(v) { } 168 Number(double); 169 Number(const char* str) : v(atoi(str)) { } 170 Number operator+(const Number&); 171 Number& operator++() { ++v; return *this; } 172 Number operator++(int) { Number returnValue(v); ++v; return returnValue; } 173 const int& value() const { return v; } 174 void someMethod(); 175 176 private: 177 int v; 178 }; 179 180 class DerivedNumber : public Number { 181 public: 182 DerivedNumber(char c) : Number(c - '0') { } 183 DerivedNumber(const char* str) : Number(atoi(str)) { } 184 }; 185 186 class ComplexNumber { 187 public: 188 ComplexNumber() : realPart(0), complexPart(0) { } 189 ComplexNumber(int real, const char* str) : realPart(real), complexPart(str) { } 190 ComplexNumber(const ComplexNumber&); 191 ComplexNumber& operator++() { realPart.someMethod(); return *this; } 192 ComplexNumber operator++(int); 193 ComplexNumber& operator<<(int); 194 ComplexNumber& operator+(); 195 196 const Number& real() const { return realPart; } 197 198 private: 199 Number realPart; 200 Number complexPart; 201 }; 202 203 class ObjectWithNonTrivialDestructor { 204 public: 205 ObjectWithNonTrivialDestructor() { } 206 ObjectWithNonTrivialDestructor(unsigned v) : v(v) { } 207 ~ObjectWithNonTrivialDestructor() { } 208 209 unsigned value() const { return v; } 210 211 private: 212 unsigned v { 0 }; 213 }; 214 215 class ObjectWithMutatingDestructor { 216 public: 217 ObjectWithMutatingDestructor() : n(0) { } 218 ObjectWithMutatingDestructor(int n) : n(n) { } 219 ~ObjectWithMutatingDestructor() { n.someMethod(); } 220 221 unsigned value() const { return n.value(); } 222 223 private: 224 Number n; 225 }; 226 227 class BaseType { 228 public: 229 BaseType() : n(0) { } 230 BaseType(int v) : n(v) { } 231 BaseType(const char*); 232 private: 233 Number n; 234 }; 235 236 class SomeType : public BaseType { 237 public: 238 using BaseType::BaseType; 239 }; 240 241 void __libcpp_verbose_abort(const char *__format, ...); 242 243 class RefCounted { 244 public: 245 void ref() const; 246 void deref() const; 247 248 void method(); 249 void someFunction(); 250 int otherFunction(); 251 unsigned recursiveTrivialFunction(int n) { return !n ? 1 : recursiveTrivialFunction(n - 1); } 252 unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : recursiveComplexFunction(n - 1); } 253 unsigned mutuallyRecursiveFunction1(int n) { return n < 0 ? 1 : (n % 2 ? mutuallyRecursiveFunction2(n - 2) : mutuallyRecursiveFunction1(n - 1)); } 254 unsigned mutuallyRecursiveFunction2(int n) { return n < 0 ? 1 : (n % 3 ? mutuallyRecursiveFunction2(n - 3) : mutuallyRecursiveFunction1(n - 2)); } 255 unsigned mutuallyRecursiveFunction3(int n) { return n < 0 ? 1 : (n % 5 ? mutuallyRecursiveFunction3(n - 5) : mutuallyRecursiveFunction4(n - 3)); } 256 unsigned mutuallyRecursiveFunction4(int n) { return n < 0 ? 1 : (n % 7 ? otherFunction() : mutuallyRecursiveFunction3(n - 3)); } 257 unsigned recursiveFunction5(unsigned n) { return n > 100 ? 2 : (n % 2 ? recursiveFunction5(n + 1) : recursiveFunction6(n + 2)); } 258 unsigned recursiveFunction6(unsigned n) { return n > 100 ? 3 : (n % 2 ? recursiveFunction6(n % 7) : recursiveFunction7(n % 5)); } 259 unsigned recursiveFunction7(unsigned n) { return n > 100 ? 5 : recursiveFunction7(n * 5); } 260 261 void mutuallyRecursive8() { mutuallyRecursive9(); someFunction(); } 262 void mutuallyRecursive9() { mutuallyRecursive8(); } 263 264 int recursiveCost() { 265 unsigned totalCost = 0; 266 for (unsigned i = 0; i < sizeof(children)/sizeof(*children); ++i) { 267 if (auto* child = children[i]) 268 totalCost += child->recursiveCost(); 269 } 270 return totalCost; 271 } 272 273 int trivial1() { return 123; } 274 float trivial2() { return 0.3; } 275 float trivial3() { return (float)0.4; } 276 float trivial4() { return 0.5f; } 277 char trivial5() { return 'a'; } 278 const char *trivial6() { return "abc"; } 279 int trivial7() { return (1); } 280 Number trivial8() { return Number { 5 }; } 281 int trivial9() { return 3 + 4; } 282 int trivial10() { return 0x1010 | 0x1; } 283 int trivial11(int v) { return v + 1; } 284 const char *trivial12(char *p) { return p ? "str" : "null"; } 285 int trivial13(int v) { 286 if (v) 287 return 123; 288 else 289 return 0; 290 } 291 int trivial14(int v) { 292 switch (v) { 293 case 1: 294 return 100; 295 case 2: 296 return 200; 297 default: 298 return 300; 299 } 300 return 0; 301 } 302 void *trivial15() { return static_cast<void*>(this); } 303 unsigned long trivial16() { return *reinterpret_cast<unsigned long*>(this); } 304 RefCounted& trivial17() const { return const_cast<RefCounted&>(*this); } 305 RefCounted& trivial18() const { RELEASE_ASSERT(this, "this must be not null"); return const_cast<RefCounted&>(*this); } 306 void trivial19() const { return; } 307 308 static constexpr unsigned numBits = 4; 309 int trivial20() { return v >> numBits; } 310 311 const int* trivial21() { return number ? &number->value() : nullptr; } 312 313 enum class Enum : unsigned short { 314 Value1 = 1, 315 Value2 = 2, 316 }; 317 bool trivial22() { return enumValue == Enum::Value1; } 318 319 bool trivial23() const { return OptionSet<Flags>::fromRaw(v).contains(Flags::Flag1); } 320 int trivial24() const { ASSERT(v); return v; } 321 unsigned trivial25() const { return __c11_atomic_load((volatile _Atomic(unsigned) *)&v, __ATOMIC_RELAXED); } 322 bool trivial26() { bool hasValue = v; return !hasValue; } 323 bool trivial27(int v) { bool value; value = v ? 1 : 0; return value; } 324 bool trivial28() { return true; } 325 bool trivial29() { return false; } 326 unsigned trivial30(unsigned v) { unsigned r = 0xff; r |= v; return r; } 327 int trivial31(int* v) { return v[0]; } 328 unsigned trivial32() { return sizeof(int); } 329 unsigned trivial33() { return ~0xff; } 330 template <unsigned v> unsigned trivial34() { return v; } 331 void trivial35() { v++; } 332 void trivial36() { ++(*number); } 333 void trivial37() { (*number)++; } 334 void trivial38() { v++; if (__builtin_expect(!!(number), 1)) (*number)++; } 335 int trivial39() { return -v; } 336 int trivial40() { return v << 2; } 337 unsigned trivial41() { v = ++s_v; return v; } 338 unsigned trivial42() { return bitwise_cast<unsigned long>(nullptr); } 339 Number* trivial43() { return std::addressof(*number); } 340 Number* trivial44() { return new Number(1); } 341 ComplexNumber* trivial45() { return new ComplexNumber(); } 342 void trivial46() { ASSERT(isMainThread()); } 343 void trivial47() { ASSERT(isMainThreadOrGCThread()); } 344 void trivial48() { ASSERT(isMainRunLoop()); } 345 void trivial49() { ASSERT(isWebThread()); } 346 void trivial50() { ASSERT(isUIThread()); } 347 void trivial51() { ASSERT(mayBeGCThread()); } 348 void trivial52() { WTFCrash(); } 349 void trivial53() { WTFCrashWithSecurityImplication(); } 350 unsigned trivial54() { return ComplexNumber().real().value(); } 351 Number&& trivial55() { return std::forward(*number); } 352 unsigned trivial56() { Number n { 5 }; return std::move(n).value(); } 353 void trivial57() { do { break; } while (1); } 354 void trivial58() { do { continue; } while (0); } 355 void trivial59() { 356 do { goto label; } 357 while (0); 358 label: 359 return; 360 } 361 unsigned trivial60() { return ObjectWithNonTrivialDestructor { 5 }.value(); } 362 unsigned trivial61() { return DerivedNumber('7').value(); } 363 void trivial62() { WTFReportBacktrace(); } 364 SomeType trivial63() { return SomeType(0); } 365 SomeType trivial64() { return SomeType(); } 366 void trivial65() { 367 __libcpp_verbose_abort("%s", "aborting"); 368 } 369 RefPtr<RefCounted> trivial66() { return children[0]; } 370 Ref<RefCounted> trivial67() { return *children[0]; } 371 372 static RefCounted& singleton() { 373 static RefCounted s_RefCounted; 374 s_RefCounted.ref(); 375 return s_RefCounted; 376 } 377 378 static RefCounted& otherSingleton() { 379 static RefCounted s_RefCounted; 380 s_RefCounted.ref(); 381 return s_RefCounted; 382 } 383 384 Number nonTrivial1() { return Number(3) + Number(4); } 385 Number nonTrivial2() { return Number { 0.3 }; } 386 int nonTrivial3() { return v ? otherFunction() : 0; } 387 int nonTrivial4() { 388 if (v) 389 return 8; 390 else 391 return otherFunction(); 392 } 393 394 int nonTrivial5() { 395 if (v) 396 return otherFunction(); 397 else 398 return 9; 399 } 400 401 int nonTrivial6() { 402 if (otherFunction()) 403 return 1; 404 else 405 return 0; 406 } 407 408 int nonTrivial7() { 409 switch (v) { 410 case 1: 411 return otherFunction(); 412 default: 413 return 7; 414 } 415 } 416 417 int nonTrivial8() { 418 switch (v) { 419 case 1: 420 return 9; 421 default: 422 return otherFunction(); 423 } 424 } 425 426 int nonTrivial9() { 427 switch (otherFunction()) { 428 case 0: 429 return -1; 430 default: 431 return 12; 432 } 433 } 434 435 static unsigned* another(); 436 unsigned nonTrivial10() const { 437 return __c11_atomic_load((volatile _Atomic(unsigned) *)another(), __ATOMIC_RELAXED); 438 } 439 440 void nonTrivial11() { 441 Number num(0.3); 442 } 443 444 bool nonTrivial12() { 445 bool val = otherFunction(); 446 return val; 447 } 448 449 int nonTrivial13() { return ~otherFunction(); } 450 int nonTrivial14() { int r = 0xff; r |= otherFunction(); return r; } 451 void nonTrivial15() { ++complex; } 452 void nonTrivial16() { complex++; } 453 ComplexNumber nonTrivial17() { return complex << 2; } 454 ComplexNumber nonTrivial18() { return +complex; } 455 ComplexNumber* nonTrivial19() { return new ComplexNumber(complex); } 456 unsigned nonTrivial20() { return ObjectWithMutatingDestructor { 7 }.value(); } 457 unsigned nonTrivial21() { return Number("123").value(); } 458 unsigned nonTrivial22() { return ComplexNumber(123, "456").real().value(); } 459 unsigned nonTrivial23() { return DerivedNumber("123").value(); } 460 SomeType nonTrivial24() { return SomeType("123"); } 461 462 static unsigned s_v; 463 unsigned v { 0 }; 464 Number* number { nullptr }; 465 ComplexNumber complex; 466 Enum enumValue { Enum::Value1 }; 467 RefCounted* children[4]; 468 }; 469 470 unsigned RefCounted::s_v = 0; 471 472 RefCounted* refCountedObj(); 473 474 void test() 475 { 476 refCountedObj()->someFunction(); 477 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 478 } 479 480 class UnrelatedClass { 481 RefPtr<RefCounted> Field; 482 bool value; 483 484 public: 485 RefCounted &getFieldTrivial() { return *Field.get(); } 486 RefCounted *getFieldTernary() { return value ? Field.get() : nullptr; } 487 488 void test() { 489 getFieldTrivial().trivial1(); // no-warning 490 getFieldTrivial().trivial2(); // no-warning 491 getFieldTrivial().trivial3(); // no-warning 492 getFieldTrivial().trivial4(); // no-warning 493 getFieldTrivial().trivial5(); // no-warning 494 getFieldTrivial().trivial6(); // no-warning 495 getFieldTrivial().trivial7(); // no-warning 496 getFieldTrivial().trivial8(); // no-warning 497 getFieldTrivial().trivial9(); // no-warning 498 getFieldTrivial().trivial10(); // no-warning 499 getFieldTrivial().trivial11(1); // no-warning 500 getFieldTrivial().trivial12(nullptr); // no-warning 501 getFieldTrivial().trivial13(0); // no-warning 502 getFieldTrivial().trivial14(3); // no-warning 503 getFieldTrivial().trivial15(); // no-warning 504 getFieldTrivial().trivial16(); // no-warning 505 getFieldTrivial().trivial17(); // no-warning 506 getFieldTrivial().trivial18(); // no-warning 507 getFieldTrivial().trivial19(); // no-warning 508 getFieldTrivial().trivial20(); // no-warning 509 getFieldTrivial().trivial21(); // no-warning 510 getFieldTrivial().trivial22(); // no-warning 511 getFieldTrivial().trivial23(); // no-warning 512 getFieldTrivial().trivial24(); // no-warning 513 getFieldTrivial().trivial25(); // no-warning 514 getFieldTrivial().trivial26(); // no-warning 515 getFieldTrivial().trivial27(5); // no-warning 516 getFieldTrivial().trivial28(); // no-warning 517 getFieldTrivial().trivial29(); // no-warning 518 getFieldTrivial().trivial30(7); // no-warning 519 int a[] = {1, 2}; 520 getFieldTrivial().trivial31(a); // no-warning 521 getFieldTrivial().trivial32(); // no-warning 522 getFieldTrivial().trivial33(); // no-warning 523 getFieldTrivial().trivial34<7>(); // no-warning 524 getFieldTrivial().trivial35(); // no-warning 525 getFieldTrivial().trivial36(); // no-warning 526 getFieldTrivial().trivial37(); // no-warning 527 getFieldTrivial().trivial38(); // no-warning 528 getFieldTrivial().trivial39(); // no-warning 529 getFieldTrivial().trivial40(); // no-warning 530 getFieldTrivial().trivial41(); // no-warning 531 getFieldTrivial().trivial42(); // no-warning 532 getFieldTrivial().trivial43(); // no-warning 533 getFieldTrivial().trivial44(); // no-warning 534 getFieldTrivial().trivial45(); // no-warning 535 getFieldTrivial().trivial46(); // no-warning 536 getFieldTrivial().trivial47(); // no-warning 537 getFieldTrivial().trivial48(); // no-warning 538 getFieldTrivial().trivial49(); // no-warning 539 getFieldTrivial().trivial50(); // no-warning 540 getFieldTrivial().trivial51(); // no-warning 541 getFieldTrivial().trivial52(); // no-warning 542 getFieldTrivial().trivial53(); // no-warning 543 getFieldTrivial().trivial54(); // no-warning 544 getFieldTrivial().trivial55(); // no-warning 545 getFieldTrivial().trivial56(); // no-warning 546 getFieldTrivial().trivial57(); // no-warning 547 getFieldTrivial().trivial58(); // no-warning 548 getFieldTrivial().trivial59(); // no-warning 549 getFieldTrivial().trivial60(); // no-warning 550 getFieldTrivial().trivial61(); // no-warning 551 getFieldTrivial().trivial62(); // no-warning 552 getFieldTrivial().trivial63(); // no-warning 553 getFieldTrivial().trivial64(); // no-warning 554 getFieldTrivial().trivial65(); // no-warning 555 getFieldTrivial().trivial66()->trivial6(); // no-warning 556 getFieldTrivial().trivial67()->trivial6(); // no-warning 557 558 RefCounted::singleton().trivial18(); // no-warning 559 RefCounted::singleton().someFunction(); // no-warning 560 RefCounted::otherSingleton().trivial18(); // no-warning 561 RefCounted::otherSingleton().someFunction(); // no-warning 562 563 getFieldTrivial().recursiveTrivialFunction(7); // no-warning 564 getFieldTrivial().recursiveComplexFunction(9); 565 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 566 getFieldTrivial().mutuallyRecursiveFunction1(11); // no-warning 567 getFieldTrivial().mutuallyRecursiveFunction2(13); // no-warning 568 getFieldTrivial().mutuallyRecursiveFunction3(17); 569 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 570 getFieldTrivial().mutuallyRecursiveFunction4(19); 571 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 572 getFieldTrivial().recursiveFunction5(23); // no-warning 573 getFieldTrivial().recursiveFunction6(29); // no-warning 574 getFieldTrivial().recursiveFunction7(31); // no-warning 575 576 getFieldTrivial().mutuallyRecursive8(); 577 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 578 getFieldTrivial().mutuallyRecursive9(); 579 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 580 581 getFieldTrivial().recursiveCost(); // no-warning 582 583 getFieldTrivial().someFunction(); 584 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 585 getFieldTrivial().nonTrivial1(); 586 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 587 getFieldTrivial().nonTrivial2(); 588 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 589 getFieldTrivial().nonTrivial3(); 590 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 591 getFieldTrivial().nonTrivial4(); 592 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 593 getFieldTrivial().nonTrivial5(); 594 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 595 getFieldTrivial().nonTrivial6(); 596 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 597 getFieldTrivial().nonTrivial7(); 598 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 599 getFieldTrivial().nonTrivial8(); 600 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 601 getFieldTrivial().nonTrivial9(); 602 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 603 getFieldTrivial().nonTrivial10(); 604 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 605 getFieldTrivial().nonTrivial11(); 606 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 607 getFieldTrivial().nonTrivial12(); 608 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 609 getFieldTrivial().nonTrivial13(); 610 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 611 getFieldTrivial().nonTrivial14(); 612 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 613 getFieldTrivial().nonTrivial15(); 614 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 615 getFieldTrivial().nonTrivial16(); 616 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 617 getFieldTrivial().nonTrivial17(); 618 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 619 getFieldTrivial().nonTrivial18(); 620 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 621 getFieldTrivial().nonTrivial19(); 622 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 623 getFieldTrivial().nonTrivial20(); 624 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 625 getFieldTrivial().nonTrivial21(); 626 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 627 getFieldTrivial().nonTrivial22(); 628 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 629 getFieldTrivial().nonTrivial23(); 630 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 631 getFieldTrivial().nonTrivial24(); 632 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 633 } 634 635 void setField(RefCounted*); 636 }; 637 638 class UnrelatedClass2 { 639 RefPtr<UnrelatedClass> Field; 640 641 public: 642 UnrelatedClass &getFieldTrivial() { return *Field.get(); } 643 RefCounted &getFieldTrivialRecursively() { return getFieldTrivial().getFieldTrivial(); } 644 RefCounted *getFieldTrivialTernary() { return Field ? Field->getFieldTernary() : nullptr; } 645 646 template<typename T, typename ... AdditionalArgs> 647 void callSetField(T&& item, AdditionalArgs&&... args) 648 { 649 item.setField(std::forward<AdditionalArgs>(args)...); 650 } 651 652 template<typename T, typename ... AdditionalArgs> 653 void callSetField2(T&& item, AdditionalArgs&&... args) 654 { 655 item.setField(std::move<AdditionalArgs>(args)...); 656 } 657 658 void test() { 659 getFieldTrivialRecursively().trivial1(); // no-warning 660 getFieldTrivialTernary()->trivial2(); // no-warning 661 getFieldTrivialRecursively().someFunction(); 662 // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} 663 callSetField(getFieldTrivial(), refCountedObj()); // no-warning 664 } 665 }; 666 667 RefPtr<RefCounted> object(); 668 void someFunction(const RefCounted&); 669 670 void test2() { 671 someFunction(*object()); 672 } 673 674 void system_header() { 675 callMethod<RefCountable>(object); 676 } 677