reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s
void clang_analyzer_eval(bool);

struct X0 { };
bool operator==(const X0&, const X0&);

// PR7287
struct test { int a[2]; };

void t2() {
  test p = {{1,2}};
  test q;
  q = p;
}

bool PR7287(X0 a, X0 b) {
  return operator==(a, b);
}


// Inlining non-static member operators mistakenly treated 'this' as the first
// argument for a while.

struct IntComparable {
  bool operator==(int x) const {
    return x == 0;
  }
};

void testMemberOperator(IntComparable B) {
  clang_analyzer_eval(B == 0); // expected-warning{{TRUE}}
}



namespace UserDefinedConversions {
  class Convertible {
  public:
    operator int() const {
      return 42;
    }
    operator bool() const {
      return true;
    }
  };

  void test(const Convertible &obj) {
    clang_analyzer_eval((int)obj == 42); // expected-warning{{TRUE}}
    clang_analyzer_eval(obj); // expected-warning{{TRUE}}
  }
}


namespace RValues {
  struct SmallOpaque {
    float x;
    int operator +() const {
      return (int)x;
    }
  };

  struct LargeOpaque {
    float x[4];
    int operator +() const {
      return (int)x[0];
    }
  };

  SmallOpaque getSmallOpaque() {
    SmallOpaque obj;
    obj.x = 1.0;
    return obj;
  }

  LargeOpaque getLargeOpaque() {
    LargeOpaque obj = LargeOpaque();
    obj.x[0] = 1.0;
    return obj;
  }

  void test(int coin) {
    // Force a cache-out when we try to conjure a temporary region for the operator call.
    // ...then, don't crash.
    clang_analyzer_eval(+(coin ? getSmallOpaque() : getSmallOpaque())); // expected-warning{{UNKNOWN}}
    clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{UNKNOWN}}
  }
}

namespace SynthesizedAssignment {
  struct A {
    int a;
    A& operator=(A& other) { a = -other.a; return *this; }
    A& operator=(A&& other) { a = other.a+1; return *this; }
  };

  struct B {
    int x;
    A a[3];
    B& operator=(B&) = default;
    B& operator=(B&&) = default;
  };

  // This used to produce a warning about the iteration variable in the
  // synthesized assignment operator being undefined.
  void testNoWarning() {
    B v, u;
    u = v;
  }

  void testNoWarningMove() {
    B v, u;
    u = static_cast<B &&>(v);
  }

  void testConsistency() {
    B v, u;
    v.a[1].a = 47;
    v.a[2].a = 42;
    u = v;
    clang_analyzer_eval(u.a[1].a == -47); // expected-warning{{TRUE}}
    clang_analyzer_eval(u.a[2].a == -42); // expected-warning{{TRUE}}
  }

  void testConsistencyMove() {
    B v, u;
    v.a[1].a = 47;
    v.a[2].a = 42;
    u = static_cast<B &&>(v);
    clang_analyzer_eval(u.a[1].a == 48); // expected-warning{{TRUE}}
    clang_analyzer_eval(u.a[2].a == 43); // expected-warning{{TRUE}}
  }
}