brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.8 KiB · d3046d6 Raw
546 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\2// RUN:   -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\3// RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\4// RUN:   -std=c++11 -verify %s5 6// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\7// RUN:   -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\8// RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\9// RUN:   -std=c++20 -verify %s10 11#include "Inputs/system-header-simulator-cxx.h"12 13void clang_analyzer_warnIfReached();14void clang_analyzer_numTimesReached();15void clang_analyzer_eval(bool);16void clang_analyzer_warnOnDeadSymbol(int *);17 18void derefAfterMove(std::unique_ptr<int> P) {19  std::unique_ptr<int> Q = std::move(P);20  if (Q)21    clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}22  *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}}23  if (P)24    clang_analyzer_warnIfReached(); // no-warning25  // TODO: Report a null dereference (instead).26  *P.get() = 1; // expected-warning {{Method called on moved-from object 'P' [cplusplus.Move]}}27  // expected-warning@-1 {{Dereference of null pointer [core.NullDereference]}}28}29 30// Don't crash when attempting to model a call with unknown callee.31namespace testUnknownCallee {32struct S {33  void foo();34};35void bar(S *s, void (S::*func)(void)) {36  (s->*func)(); // no-crash37}38} // namespace testUnknownCallee39 40class A {41public:42  A(){};43  void foo();44};45 46A *return_null() {47  return nullptr;48}49 50void derefAfterValidCtr() {51  std::unique_ptr<A> P(new A());52  clang_analyzer_numTimesReached(); // expected-warning {{1}}53  P->foo(); // No warning.54}55 56void derefOfUnknown(std::unique_ptr<A> P) {57  P->foo(); // No warning.58}59 60void derefAfterDefaultCtr() {61  std::unique_ptr<A> P;62  clang_analyzer_numTimesReached(); // expected-warning {{1}}63  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}64}65 66void derefAfterCtrWithNull() {67  std::unique_ptr<A> P(nullptr);68  clang_analyzer_numTimesReached(); // expected-warning {{1}}69  *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}70}71 72void derefAfterCtrWithNullVariable() {73  A *InnerPtr = nullptr;74  std::unique_ptr<A> P(InnerPtr);75  clang_analyzer_numTimesReached(); // expected-warning {{1}}76  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}77}78 79void derefAfterRelease() {80  std::unique_ptr<A> P(new A());81  P.release();82  clang_analyzer_numTimesReached(); // expected-warning {{1}}83  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}84}85 86void derefAfterReset() {87  std::unique_ptr<A> P(new A());88  P.reset();89  clang_analyzer_numTimesReached(); // expected-warning {{1}}90  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}91}92 93void derefAfterResetWithNull() {94  std::unique_ptr<A> P(new A());95  P.reset(nullptr);96  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}97}98 99void derefAfterResetWithNonNull() {100  std::unique_ptr<A> P;101  P.reset(new A());102  clang_analyzer_numTimesReached(); // expected-warning {{1}}103  P->foo(); // No warning.104}105 106void derefAfterReleaseAndResetWithNonNull() {107  std::unique_ptr<A> P(new A());108  P.release();109  P.reset(new A());110  P->foo(); // No warning.111}112 113void derefOnReleasedNullRawPtr() {114  std::unique_ptr<A> P;115  A *AP = P.release();116  AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}117}118 119void derefOnReleasedValidRawPtr() {120  std::unique_ptr<A> P(new A());121  A *AP = P.release();122  AP->foo(); // No warning.123}124 125void pass_smart_ptr_by_ref(std::unique_ptr<A> &a);126void pass_smart_ptr_by_const_ref(const std::unique_ptr<A> &a);127void pass_smart_ptr_by_rvalue_ref(std::unique_ptr<A> &&a);128void pass_smart_ptr_by_const_rvalue_ref(const std::unique_ptr<A> &&a);129void pass_smart_ptr_by_ptr(std::unique_ptr<A> *a);130void pass_smart_ptr_by_const_ptr(const std::unique_ptr<A> *a);131 132void regioninvalidationWithPassByRef() {133  std::unique_ptr<A> P;134  pass_smart_ptr_by_ref(P);135  P->foo(); // no-warning136}137 138void regioninvalidationWithPassByCostRef() {139  std::unique_ptr<A> P;140  pass_smart_ptr_by_const_ref(P);141  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}142}143 144void regioninvalidationWithPassByRValueRef() {145  std::unique_ptr<A> P;146  pass_smart_ptr_by_rvalue_ref(std::move(P));147  P->foo(); // no-warning148}149 150void regioninvalidationWithPassByConstRValueRef() {151  std::unique_ptr<A> P;152  pass_smart_ptr_by_const_rvalue_ref(std::move(P));153  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}154}155 156void regioninvalidationWithPassByPtr() {157  std::unique_ptr<A> P;158  pass_smart_ptr_by_ptr(&P);159  P->foo();160}161 162void regioninvalidationWithPassByConstPtr() {163  std::unique_ptr<A> P;164  pass_smart_ptr_by_const_ptr(&P);165  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}166}167 168struct StructWithSmartPtr {169  std::unique_ptr<A> P;170};171 172void pass_struct_with_smart_ptr_by_ref(StructWithSmartPtr &a);173void pass_struct_with_smart_ptr_by_const_ref(const StructWithSmartPtr &a);174void pass_struct_with_smart_ptr_by_rvalue_ref(StructWithSmartPtr &&a);175void pass_struct_with_smart_ptr_by_const_rvalue_ref(const StructWithSmartPtr &&a);176void pass_struct_with_smart_ptr_by_ptr(StructWithSmartPtr *a);177void pass_struct_with_smart_ptr_by_const_ptr(const StructWithSmartPtr *a);178 179void regioninvalidationWithinStructPassByRef() {180  StructWithSmartPtr S;181  pass_struct_with_smart_ptr_by_ref(S);182  S.P->foo(); // no-warning183}184 185void regioninvalidationWithinStructPassByConstRef() {186  StructWithSmartPtr S;187  pass_struct_with_smart_ptr_by_const_ref(S);188  S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}189}190 191void regioninvalidationWithinStructPassByRValueRef() {192  StructWithSmartPtr S;193  pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S));194  S.P->foo(); // no-warning195}196 197void regioninvalidationWithinStructPassByConstRValueRef() {198  StructWithSmartPtr S;199  pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S));200  S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}201}202 203void regioninvalidationWithinStructPassByPtr() {204  StructWithSmartPtr S;205  pass_struct_with_smart_ptr_by_ptr(&S);206  S.P->foo(); // no-warning207}208 209void regioninvalidationWithinStructPassByConstPtr() {210  StructWithSmartPtr S;211  pass_struct_with_smart_ptr_by_const_ptr(&S);212  S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}213}214 215void derefAfterAssignment() {216  {217    std::unique_ptr<A> P(new A());218    std::unique_ptr<A> Q;219    Q = std::move(P);220    Q->foo(); // no-warning221  }222  {223    std::unique_ptr<A> P;224    std::unique_ptr<A> Q;225    Q = std::move(P);226    Q->foo(); // expected-warning {{Dereference of null smart pointer 'Q' [alpha.cplusplus.SmartPtr]}}227  }228}229 230void derefOnSwappedNullPtr() {231  std::unique_ptr<A> P(new A());232  std::unique_ptr<A> PNull;233  P.swap(PNull);234  PNull->foo(); // No warning.235  (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}236}237 238void derefOnFirstStdSwappedNullPtr() {239  std::unique_ptr<A> P;240  std::unique_ptr<A> PNull;241  std::swap(P, PNull);242  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}243}244 245void derefOnSecondStdSwappedNullPtr() {246  std::unique_ptr<A> P;247  std::unique_ptr<A> PNull;248  std::swap(P, PNull);249  PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}250}251 252void derefOnSwappedValidPtr() {253  std::unique_ptr<A> P(new A());254  std::unique_ptr<A> PValid(new A());255  P.swap(PValid);256  (*P).foo(); // No warning.257  PValid->foo(); // No warning.258  std::swap(P, PValid);259  P->foo(); // No warning.260  PValid->foo(); // No warning.261}262 263void derefOnRawPtrFromGetOnNullPtr() {264  std::unique_ptr<A> P;265  P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}266}267 268void derefOnRawPtrFromGetOnValidPtr() {269  std::unique_ptr<A> P(new A());270  P.get()->foo(); // No warning.271}272 273void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) {274  P.get()->foo(); // No warning.275}276 277void derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr<A> P) {278  A *X = P.get();279  A *Y = P.get();280  clang_analyzer_eval(X == Y); // expected-warning{{TRUE}}281  if (!X) {282    Y->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}283  }284}285 286void derefOnMovedFromValidPtr() {287  std::unique_ptr<A> PToMove(new A());288  std::unique_ptr<A> P;289  P = std::move(PToMove);290  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}291}292 293void derefOnMovedToNullPtr() {294  std::unique_ptr<A> PToMove(new A());295  std::unique_ptr<A> P;296  P = std::move(PToMove); // No note.297  P->foo(); // No warning.298}299 300void derefOnNullPtrGotMovedFromValidPtr() {301  std::unique_ptr<A> P(new A());302  std::unique_ptr<A> PToMove;303  P = std::move(PToMove);304  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}305}306 307void derefOnMovedFromUnknownPtr(std::unique_ptr<A> PToMove) {308  std::unique_ptr<A> P;309  P = std::move(PToMove);310  P->foo(); // No warning.311}312 313void derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove) {314  std::unique_ptr<A> P;315  P = std::move(PToMove);316  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}317}318 319void derefOnAssignedNullPtrToNullSmartPtr() {320  std::unique_ptr<A> P;321  P = nullptr;322  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}323}324 325void derefOnAssignedZeroToNullSmartPtr() {326  std::unique_ptr<A> P(new A());327  P = 0;328  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}329}330 331void derefOnAssignedNullToUnknowSmartPtr(std::unique_ptr<A> P) {332  P = nullptr;333  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}334}335 336std::unique_ptr<A> &&returnRValRefOfUniquePtr();337 338void drefOnAssignedNullFromMethodPtrValidSmartPtr() {339  std::unique_ptr<A> P(new A());340  P = returnRValRefOfUniquePtr();341  P->foo(); // No warning.342}343 344void derefMoveConstructedWithValidPtr() {345  std::unique_ptr<A> PToMove(new A());346  std::unique_ptr<A> P(std::move(PToMove));347  P->foo(); // No warning.348}349 350void derefMoveConstructedWithNullPtr() {351  std::unique_ptr<A> PToMove;352  std::unique_ptr<A> P(std::move(PToMove));353  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}354}355 356void derefMoveConstructedWithUnknownPtr(std::unique_ptr<A> PToMove) {357  std::unique_ptr<A> P(std::move(PToMove));358  P->foo(); // No warning.359}360 361void derefValidPtrMovedToConstruct() {362  std::unique_ptr<A> PToMove(new A());363  std::unique_ptr<A> P(std::move(PToMove));364  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}365}366 367void derefNullPtrMovedToConstruct() {368  std::unique_ptr<A> PToMove;369  std::unique_ptr<A> P(std::move(PToMove));370  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}371}372 373void derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove) {374  std::unique_ptr<A> P(std::move(PToMove));375  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}376}377 378std::unique_ptr<A> &&functionReturnsRValueRef();379 380void derefMoveConstructedWithRValueRefReturn() {381  std::unique_ptr<A> P(functionReturnsRValueRef());382  P->foo(); // No warning.383}384 385void derefConditionOnNullPtr() {386  std::unique_ptr<A> P;387  if (P)388    P->foo(); // No warning.389  else390    P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}391}392 393void derefConditionOnNotNullPtr() {394  std::unique_ptr<A> P;395  if (!P)396    P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}397}398 399void derefConditionOnValidPtr() {400  std::unique_ptr<A> P(new A());401  std::unique_ptr<A> PNull;402  if (P)403    PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}404}405 406void derefConditionOnNotValidPtr() {407  std::unique_ptr<A> P(new A());408  std::unique_ptr<A> PNull;409  if (!P)410    PNull->foo(); // No warning.411}412 413void derefConditionOnUnKnownPtr(std::unique_ptr<A> P) {414  if (P)415    P->foo(); // No warning.416  else417    P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}418}419 420void derefOnValidPtrAfterReset(std::unique_ptr<A> P) {421  P.reset(new A());422  if (!P)423    P->foo(); // No warning.424  else425    P->foo(); // No warning.426}427 428void innerPointerSymbolLiveness() {429  std::unique_ptr<int> P(new int());430  clang_analyzer_warnOnDeadSymbol(P.get());431  int *RP = P.release();432} // expected-warning{{SYMBOL DEAD}}433 434void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) {435  if (P) {436    int *X = P.get();437    clang_analyzer_warnOnDeadSymbol(X);438  }439} // expected-warning{{SYMBOL DEAD}}440 441void getCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) {442  int *X = P.get();443  clang_analyzer_warnOnDeadSymbol(X);444  int Y;445  if (!P) {446    Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}}447    // expected-warning@-1 {{SYMBOL DEAD}}448  }449}450 451int derefConditionOnUnKnownPtr(int *q) {452  std::unique_ptr<int> P(q);453  if (P)454    return *P; // No warning.455  else456    return *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}457}458 459void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P) {460  A *RP = P.get();461  if (!RP) {462    P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}463  }464}465 466// The following is a silly function,467// but serves to test if we are picking out468// standard comparision functions from custom ones.469template <typename T>470bool operator<(std::unique_ptr<T> &x, double d);471 472void uniquePtrComparision(std::unique_ptr<int> unknownPtr) {473  auto ptr = std::unique_ptr<int>(new int(13));474  auto nullPtr = std::unique_ptr<int>();475  auto otherPtr = std::unique_ptr<int>(new int(29));476 477  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}478  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}479  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}480 481  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}482  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}483 484  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}485  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}486 487  clang_analyzer_eval(ptr != nullptr);        // expected-warning{{TRUE}}488  clang_analyzer_eval(nullPtr != nullptr);    // expected-warning{{FALSE}}489  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}490}491 492void uniquePtrComparisionStateSplitting(std::unique_ptr<int> unknownPtr) {493  auto ptr = std::unique_ptr<int>(new int(13));494 495  clang_analyzer_eval(ptr > unknownPtr); // expected-warning{{TRUE}}496  // expected-warning@-1{{FALSE}}497}498 499void uniquePtrComparisionDifferingTypes(std::unique_ptr<int> unknownPtr) {500  auto ptr = std::unique_ptr<int>(new int(13));501  auto nullPtr = std::unique_ptr<A>();502  auto otherPtr = std::unique_ptr<double>(new double(3.14));503 504  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}505  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}506 507  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}508  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}509 510  clang_analyzer_eval(ptr != nullptr);        // expected-warning{{TRUE}}511  clang_analyzer_eval(nullPtr != nullptr);    // expected-warning{{FALSE}}512  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}513}514 515#if __cplusplus >= 202002L516 517void testOstreamOverload(std::unique_ptr<int> P) {518  auto &Cout = std::cout;519  auto &PtrCout = std::cout << P;520  auto &StringCout = std::cout << "hello";521  // We are testing the fact that in our modelling of522  // operator<<(basic_ostream<T1> &, const unique_ptr<T2> &)523  // we set the return SVal to the SVal of the ostream arg.524  clang_analyzer_eval(&Cout == &PtrCout);    // expected-warning {{TRUE}}525  // FIXME: Technically, they should be equal,526  // that hasn't been modelled yet.527  clang_analyzer_eval(&Cout == &StringCout); // expected-warning {{UNKNOWN}}528}529 530int glob;531void testOstreamDoesntInvalidateGlobals(std::unique_ptr<int> P) {532  int x = glob;533  std::cout << P;534  int y = glob;535  clang_analyzer_eval(x == y); // expected-warning {{TRUE}}536}537 538#endif539 540// The following test isn't really a "smart-ptr" test541// It came up during a bug fix (D106296)542void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {543  // This should NOT crash.544  bar(true, false);545}546