brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · b37ce17 Raw
320 lines · cpp
1// RUN: %clang_analyze_cc1 -Wno-error=return-type -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s2 3void clang_analyzer_eval(bool);4 5struct A {6  int x;7  void foo() const;8  void bar();9 10  void testImplicitThisSyntax() {11    x = 3;12    foo();13    clang_analyzer_eval(x == 3); // expected-warning{{TRUE}}14    bar();15    clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}}16  }17};18 19struct B {20  mutable int mut;21  void foo() const;22};23 24struct C {25  int *p;26  void foo() const;27};28 29struct MutBase {30  mutable int b_mut;31};32 33struct MutDerived : MutBase {34  void foo() const;35};36 37struct PBase {38  int *p;39};40 41struct PDerived : PBase {42  void foo() const;43};44 45struct Inner {46  int x;47  int *p;48  void bar() const;49};50 51struct Outer {52  int x;53  Inner in;54  void foo() const;55};56 57void checkThatConstMethodWithoutDefinitionDoesNotInvalidateObject() {58  A t;59  t.x = 3;60  t.foo();61  clang_analyzer_eval(t.x == 3); // expected-warning{{TRUE}}62  // Test non-const does invalidate63  t.bar();64  clang_analyzer_eval(t.x); // expected-warning{{UNKNOWN}}65}66 67void checkThatConstMethodDoesInvalidateMutableFields() {68  B t;69  t.mut = 4;70  t.foo();71  clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}72}73 74void checkThatConstMethodDoesInvalidatePointedAtMemory() {75  int x = 1;76  C t;77  t.p = &x;78  t.foo();79  clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}80  clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}}81}82 83void checkThatConstMethodDoesInvalidateInheritedMutableFields() {84  MutDerived t;85  t.b_mut = 4;86  t.foo();87  clang_analyzer_eval(t.b_mut); // expected-warning{{UNKNOWN}}88}89 90void checkThatConstMethodDoesInvalidateInheritedPointedAtMemory() {91  int x = 1;92  PDerived t;93  t.p = &x;94  t.foo();95  clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}96  clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}}97}98 99void checkThatConstMethodDoesInvalidateContainedPointedAtMemory() {100  int x = 1;101  Outer t;102  t.x = 2;103  t.in.p = &x;104  t.foo();105  clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}106  clang_analyzer_eval(t.x == 2); // expected-warning{{TRUE}}107  clang_analyzer_eval(t.in.p == &x); // expected-warning{{TRUE}}108}109 110void checkThatContainedConstMethodDoesNotInvalidateObjects() {111  Outer t;112  t.x = 1;113  t.in.x = 2;114  t.in.bar();115  clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}116  clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}}117}118 119void checkPointerTypedThisExpression(A *a) {120  a->x = 3;121  a->foo();122  clang_analyzer_eval(a->x == 3); // expected-warning{{TRUE}}123  a->bar();124  clang_analyzer_eval(a->x == 3); // expected-warning{{UNKNOWN}}125}126 127void checkReferenceTypedThisExpression(A &a) {128  a.x = 3;129  a.foo();130  clang_analyzer_eval(a.x == 3); // expected-warning{{TRUE}}131  a.bar();132  clang_analyzer_eval(a.x == 3); // expected-warning{{UNKNOWN}}133}134 135// --- Versions of the above tests where the const method is inherited --- //136 137struct B1 {138  void foo() const;139};140 141struct D1 : public B1 {142  int x;143};144 145struct D2 : public B1 {146  mutable int mut;147};148 149struct D3 : public B1 {150  int *p;151};152 153struct DInner : public B1 {154  int x;155  int *p;156};157 158struct DOuter : public B1 {159  int x;160  DInner in;161};162 163void checkThatInheritedConstMethodDoesNotInvalidateObject() {164  D1 t;165  t.x = 1;166  t.foo();167  clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}168}169 170void checkThatInheritedConstMethodDoesInvalidateMutableFields() {171  D2 t;172  t.mut = 1;173  t.foo();174  clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}175}176 177void checkThatInheritedConstMethodDoesInvalidatePointedAtMemory() {178  int x = 1;179  D3 t;180  t.p = &x;181  t.foo();182  clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}183  clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}}184}185 186void checkThatInheritedConstMethodDoesInvalidateContainedPointedAtMemory() {187  int x = 1;188  DOuter t;189  t.x = 2;190  t.in.x = 3;191  t.in.p = &x;192  t.foo();193  clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}194  clang_analyzer_eval(t.x == 2); // expected-warning{{TRUE}}195  clang_analyzer_eval(t.in.x == 3); // expected-warning{{TRUE}}196  clang_analyzer_eval(t.in.p == &x); // expected-warning{{TRUE}}197}198 199void checkThatInheritedContainedConstMethodDoesNotInvalidateObjects() {200  DOuter t;201  t.x = 1;202  t.in.x = 2;203  t.in.foo();204  clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}205  clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}}206}207 208// --- PR21606 --- //209 210struct s1 {211    void g(const int *i) const;212};213 214struct s2 {215    void f(int *i) {216        m_i = i;217        m_s.g(m_i);218        if (m_i)219            *i = 42; // no-warning220    }221 222    int *m_i;223    s1 m_s;224};225 226void PR21606()227{228    s2().f(0);229}230 231// --- PR25392 --- //232 233struct HasConstMemberFunction {234public:235  void constMemberFunction() const;236};237 238HasConstMemberFunction hasNoReturn() { } // expected-warning {{non-void function does not return a value}}239 240void testUnknownWithConstMemberFunction() {241  hasNoReturn().constMemberFunction();242}243 244void testNonRegionLocWithConstMemberFunction() {245  (*((HasConstMemberFunction *)(&&label))).constMemberFunction();246 247  label: return;248}249 250// FIXME251// When there is a circular reference to an object and a const method is called252// the object is not invalidated because TK_PreserveContents has already been253// set.254struct Outer2;255 256struct InnerWithRef {257  Outer2 *ref;258};259 260struct Outer2 {261  int x;262  InnerWithRef in;263  void foo() const;264};265 266void checkThatConstMethodCallDoesInvalidateObjectForCircularReferences() {267  Outer2 t;268  t.x = 1;269  t.in.ref = &t;270  t.foo();271  // FIXME: Should be UNKNOWN.272  clang_analyzer_eval(t.x); // expected-warning{{TRUE}}273}274 275namespace gh77378 {276template <typename Signature> class callable;277 278template <typename R> class callable<R()> {279  struct CallableType {280    bool operator()();281  };282  using MethodType = R (CallableType::*)();283  CallableType *object_{nullptr};284  MethodType method_;285 286public:287  callable() = default;288 289  template <typename T>290  constexpr callable(const T &obj)291      : object_{reinterpret_cast<CallableType *>(&const_cast<T &>(obj))},292        method_{reinterpret_cast<MethodType>(293            static_cast<bool (T::*)() const>(&T::operator()))} {}294 295  constexpr bool const_method() const {296    return (object_->*(method_))();297  }298 299  callable call() const & {300    static const auto L = [this]() {301      while (true) {302        // This should not crash when conservative eval calling the member function303        // when it unwinds the call stack due to exhausting the budget or reaching304        // the inlining limit.305        if (this->const_method()) {306          break;307        }308      }309      return true;310    };311    return L;312  }313};314 315void entry() {316  callable<bool()>{}.call().const_method();317  // expected-warning@-1 {{Address of stack memory associated with temporary object of type 'callable<bool ()>' is still referred to by the static variable 'L' upon returning to the caller.  This will be a dangling reference}}318}319} // namespace gh77378320