862 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			862 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -analyzer-config eagerly-assume=false %s
 | 
						|
// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS -analyzer-config eagerly-assume=false %s
 | 
						|
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -analyzer-config eagerly-assume=false %s
 | 
						|
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS -analyzer-config eagerly-assume=false %s
 | 
						|
 | 
						|
#include "Inputs/system-header-simulator-cxx.h"
 | 
						|
 | 
						|
void clang_analyzer_eval(bool);
 | 
						|
void clang_analyzer_checkInlined(bool);
 | 
						|
 | 
						|
// A simplified version of std::move.
 | 
						|
template <typename T>
 | 
						|
T &&move(T &obj) {
 | 
						|
  return static_cast<T &&>(obj);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
struct Wrapper {
 | 
						|
  __strong id obj;
 | 
						|
};
 | 
						|
 | 
						|
void test() {
 | 
						|
  Wrapper w;
 | 
						|
  // force a diagnostic
 | 
						|
  *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
struct IntWrapper {
 | 
						|
  int x;
 | 
						|
};
 | 
						|
 | 
						|
void testCopyConstructor() {
 | 
						|
  IntWrapper a;
 | 
						|
  a.x = 42;
 | 
						|
 | 
						|
  IntWrapper b(a);
 | 
						|
  clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
 | 
						|
}
 | 
						|
 | 
						|
struct NonPODIntWrapper {
 | 
						|
  int x;
 | 
						|
 | 
						|
  virtual int get();
 | 
						|
};
 | 
						|
 | 
						|
void testNonPODCopyConstructor() {
 | 
						|
  NonPODIntWrapper a;
 | 
						|
  a.x = 42;
 | 
						|
 | 
						|
  NonPODIntWrapper b(a);
 | 
						|
  clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
namespace ConstructorVirtualCalls {
 | 
						|
  class A {
 | 
						|
  public:
 | 
						|
    int *out1, *out2, *out3;
 | 
						|
 | 
						|
    virtual int get() { return 1; }
 | 
						|
 | 
						|
    A(int *out1) {
 | 
						|
      *out1 = get();
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  class B : public A {
 | 
						|
  public:
 | 
						|
    virtual int get() { return 2; }
 | 
						|
 | 
						|
    B(int *out1, int *out2) : A(out1) {
 | 
						|
      *out2 = get();
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  class C : public B {
 | 
						|
  public:
 | 
						|
    virtual int get() { return 3; }
 | 
						|
 | 
						|
    C(int *out1, int *out2, int *out3) : B(out1, out2) {
 | 
						|
      *out3 = get();
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  void test() {
 | 
						|
    int a, b, c;
 | 
						|
 | 
						|
    C obj(&a, &b, &c);
 | 
						|
    clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    // Correctness check for devirtualization.
 | 
						|
    A *base = &obj;
 | 
						|
    clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace TemporaryConstructor {
 | 
						|
  class BoolWrapper {
 | 
						|
  public:
 | 
						|
    BoolWrapper() {
 | 
						|
      clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
 | 
						|
      value = true;
 | 
						|
    }
 | 
						|
    bool value;
 | 
						|
  };
 | 
						|
 | 
						|
  void test() {
 | 
						|
    // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
 | 
						|
    if (BoolWrapper().value)
 | 
						|
      return;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
namespace ConstructorUsedAsRValue {
 | 
						|
  using TemporaryConstructor::BoolWrapper;
 | 
						|
 | 
						|
  bool extractValue(BoolWrapper b) {
 | 
						|
    return b.value;
 | 
						|
  }
 | 
						|
 | 
						|
  void test() {
 | 
						|
    bool result = extractValue(BoolWrapper());
 | 
						|
    clang_analyzer_eval(result); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace PODUninitialized {
 | 
						|
  class POD {
 | 
						|
  public:
 | 
						|
    int x, y;
 | 
						|
  };
 | 
						|
 | 
						|
  class PODWrapper {
 | 
						|
  public:
 | 
						|
    POD p;
 | 
						|
  };
 | 
						|
 | 
						|
  class NonPOD {
 | 
						|
  public:
 | 
						|
    int x, y;
 | 
						|
 | 
						|
    NonPOD() {}
 | 
						|
    NonPOD(const NonPOD &Other)
 | 
						|
      : x(Other.x), y(Other.y) // expected-warning {{undefined}}
 | 
						|
    {
 | 
						|
    }
 | 
						|
    NonPOD(NonPOD &&Other)
 | 
						|
    : x(Other.x), y(Other.y) // expected-warning {{undefined}}
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    NonPOD &operator=(const NonPOD &Other)
 | 
						|
    {
 | 
						|
      x = Other.x;
 | 
						|
      y = Other.y; // expected-warning {{undefined}}
 | 
						|
      return *this;
 | 
						|
    }
 | 
						|
    NonPOD &operator=(NonPOD &&Other)
 | 
						|
    {
 | 
						|
      x = Other.x;
 | 
						|
      y = Other.y; // expected-warning {{undefined}}
 | 
						|
      return *this;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  class NonPODWrapper {
 | 
						|
  public:
 | 
						|
    class Inner {
 | 
						|
    public:
 | 
						|
      int x, y;
 | 
						|
 | 
						|
      Inner() {}
 | 
						|
      Inner(const Inner &Other)
 | 
						|
        : x(Other.x), y(Other.y) // expected-warning {{undefined}}
 | 
						|
      {
 | 
						|
      }
 | 
						|
      Inner(Inner &&Other)
 | 
						|
      : x(Other.x), y(Other.y) // expected-warning {{undefined}}
 | 
						|
      {
 | 
						|
      }
 | 
						|
 | 
						|
      Inner &operator=(const Inner &Other)
 | 
						|
      {
 | 
						|
        x = Other.x; // expected-warning {{undefined}}
 | 
						|
        y = Other.y;
 | 
						|
        return *this;
 | 
						|
      }
 | 
						|
      Inner &operator=(Inner &&Other)
 | 
						|
      {
 | 
						|
        x = Other.x; // expected-warning {{undefined}}
 | 
						|
        y = Other.y;
 | 
						|
        return *this;
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    Inner p;
 | 
						|
  };
 | 
						|
 | 
						|
  void testPOD(const POD &pp) {
 | 
						|
    POD p;
 | 
						|
    p.x = 1;
 | 
						|
    POD p2 = p; // no-warning
 | 
						|
    clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
 | 
						|
    POD p3 = move(p); // no-warning
 | 
						|
    clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    // Use rvalues as well.
 | 
						|
    clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    // Copy from symbolic references correctly.
 | 
						|
    POD p4 = pp;
 | 
						|
    // Make sure that p4.x contains a symbol after copy.
 | 
						|
    if (p4.x > 0)
 | 
						|
      clang_analyzer_eval(p4.x > 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(pp.x == p4.x); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    PODWrapper w;
 | 
						|
    w.p.y = 1;
 | 
						|
    PODWrapper w2 = w; // no-warning
 | 
						|
    clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
 | 
						|
    PODWrapper w3 = move(w); // no-warning
 | 
						|
    clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    // Use rvalues as well.
 | 
						|
    clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  void testNonPOD() {
 | 
						|
    NonPOD p;
 | 
						|
    p.x = 1;
 | 
						|
    NonPOD p2 = p;
 | 
						|
  }
 | 
						|
 | 
						|
  void testNonPODMove() {
 | 
						|
    NonPOD p;
 | 
						|
    p.x = 1;
 | 
						|
    NonPOD p2 = move(p);
 | 
						|
  }
 | 
						|
 | 
						|
  void testNonPODWrapper() {
 | 
						|
    NonPODWrapper w;
 | 
						|
    w.p.y = 1;
 | 
						|
    NonPODWrapper w2 = w;
 | 
						|
  }
 | 
						|
 | 
						|
  void testNonPODWrapperMove() {
 | 
						|
    NonPODWrapper w;
 | 
						|
    w.p.y = 1;
 | 
						|
    NonPODWrapper w2 = move(w);
 | 
						|
  }
 | 
						|
 | 
						|
  // Not strictly about constructors, but trivial assignment operators should
 | 
						|
  // essentially work the same way.
 | 
						|
  namespace AssignmentOperator {
 | 
						|
    void testPOD() {
 | 
						|
      POD p;
 | 
						|
      p.x = 1;
 | 
						|
      POD p2;
 | 
						|
      p2 = p; // no-warning
 | 
						|
      clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
 | 
						|
      POD p3;
 | 
						|
      p3 = move(p); // no-warning
 | 
						|
      clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
      PODWrapper w;
 | 
						|
      w.p.y = 1;
 | 
						|
      PODWrapper w2;
 | 
						|
      w2 = w; // no-warning
 | 
						|
      clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
 | 
						|
      PODWrapper w3;
 | 
						|
      w3 = move(w); // no-warning
 | 
						|
      clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
 | 
						|
    }
 | 
						|
 | 
						|
    void testReturnValue() {
 | 
						|
      POD p;
 | 
						|
      p.x = 1;
 | 
						|
      POD p2;
 | 
						|
      clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
      PODWrapper w;
 | 
						|
      w.p.y = 1;
 | 
						|
      PODWrapper w2;
 | 
						|
      clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}}
 | 
						|
    }
 | 
						|
 | 
						|
    void testNonPOD() {
 | 
						|
      NonPOD p;
 | 
						|
      p.x = 1;
 | 
						|
      NonPOD p2;
 | 
						|
      p2 = p;
 | 
						|
    }
 | 
						|
 | 
						|
    void testNonPODMove() {
 | 
						|
      NonPOD p;
 | 
						|
      p.x = 1;
 | 
						|
      NonPOD p2;
 | 
						|
      p2 = move(p);
 | 
						|
    }
 | 
						|
 | 
						|
    void testNonPODWrapper() {
 | 
						|
      NonPODWrapper w;
 | 
						|
      w.p.y = 1;
 | 
						|
      NonPODWrapper w2;
 | 
						|
      w2 = w;
 | 
						|
    }
 | 
						|
 | 
						|
    void testNonPODWrapperMove() {
 | 
						|
      NonPODWrapper w;
 | 
						|
      w.p.y = 1;
 | 
						|
      NonPODWrapper w2;
 | 
						|
      w2 = move(w);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace ArrayMembers {
 | 
						|
  struct Primitive {
 | 
						|
    int values[3];
 | 
						|
  };
 | 
						|
 | 
						|
  void testPrimitive() {
 | 
						|
    Primitive a = { { 1, 2, 3 } };
 | 
						|
 | 
						|
    clang_analyzer_eval(a.values[0] == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1] == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[2] == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    Primitive b = a;
 | 
						|
 | 
						|
    clang_analyzer_eval(b.values[0] == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[1] == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[2] == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    Primitive c;
 | 
						|
    c = b;
 | 
						|
 | 
						|
    clang_analyzer_eval(c.values[0] == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[1] == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[2] == 3); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct NestedPrimitive {
 | 
						|
    int values[2][3];
 | 
						|
  };
 | 
						|
 | 
						|
  void testNestedPrimitive() {
 | 
						|
    NestedPrimitive a = { { { 0, 0, 0 }, { 1, 2, 3 } } };
 | 
						|
 | 
						|
    clang_analyzer_eval(a.values[1][0] == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1][1] == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1][2] == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    NestedPrimitive b = a;
 | 
						|
 | 
						|
    clang_analyzer_eval(b.values[1][0] == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[1][1] == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[1][2] == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    NestedPrimitive c;
 | 
						|
    c = b;
 | 
						|
 | 
						|
    clang_analyzer_eval(c.values[1][0] == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[1][1] == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[1][2] == 3); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct POD {
 | 
						|
    IntWrapper values[3];
 | 
						|
  };
 | 
						|
 | 
						|
  void testPOD() {
 | 
						|
    POD a = { { { 1 }, { 2 }, { 3 } } };
 | 
						|
 | 
						|
    clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    POD b = a;
 | 
						|
 | 
						|
    clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    POD c;
 | 
						|
    c = b;
 | 
						|
 | 
						|
    clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct NestedPOD {
 | 
						|
    IntWrapper values[2][3];
 | 
						|
  };
 | 
						|
 | 
						|
  void testNestedPOD() {
 | 
						|
    NestedPOD a = { { { { 0 }, { 0 }, { 0 } }, { { 1 }, { 2 }, { 3 } } } };
 | 
						|
 | 
						|
    clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    NestedPOD b = a;
 | 
						|
 | 
						|
    clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    NestedPOD c;
 | 
						|
    c = b;
 | 
						|
 | 
						|
    clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct NonPOD {
 | 
						|
    NonPODIntWrapper values[3];
 | 
						|
  };
 | 
						|
 | 
						|
  void testNonPOD() {
 | 
						|
    NonPOD a;
 | 
						|
    a.values[0].x = 1;
 | 
						|
    a.values[1].x = 2;
 | 
						|
    a.values[2].x = 3;
 | 
						|
 | 
						|
    clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    NonPOD b = a;
 | 
						|
 | 
						|
    clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    NonPOD c;
 | 
						|
    c = b;
 | 
						|
 | 
						|
    clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct NestedNonPOD {
 | 
						|
    NonPODIntWrapper values[2][3];
 | 
						|
  };
 | 
						|
 | 
						|
  void testNestedNonPOD() {
 | 
						|
    NestedNonPOD a;
 | 
						|
    a.values[0][0].x = 0;
 | 
						|
    a.values[0][1].x = 0;
 | 
						|
    a.values[0][2].x = 0;
 | 
						|
    a.values[1][0].x = 1;
 | 
						|
    a.values[1][1].x = 2;
 | 
						|
    a.values[1][2].x = 3;
 | 
						|
 | 
						|
    clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    NestedNonPOD b = a;
 | 
						|
 | 
						|
    clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
 | 
						|
    clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
 | 
						|
    clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
 | 
						|
 | 
						|
    NestedNonPOD c;
 | 
						|
    c = b;
 | 
						|
 | 
						|
    clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
 | 
						|
    clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
 | 
						|
    clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
 | 
						|
  }
 | 
						|
  
 | 
						|
  struct NonPODDefaulted {
 | 
						|
    NonPODIntWrapper values[3];
 | 
						|
 | 
						|
    NonPODDefaulted() = default;
 | 
						|
    NonPODDefaulted(const NonPODDefaulted &) = default;
 | 
						|
    NonPODDefaulted &operator=(const NonPODDefaulted &) = default;
 | 
						|
  };
 | 
						|
 | 
						|
  void testNonPODDefaulted() {
 | 
						|
    NonPODDefaulted a;
 | 
						|
    a.values[0].x = 1;
 | 
						|
    a.values[1].x = 2;
 | 
						|
    a.values[2].x = 3;
 | 
						|
 | 
						|
    clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    NonPODDefaulted b = a;
 | 
						|
 | 
						|
    clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    NonPODDefaulted c;
 | 
						|
    c = b;
 | 
						|
 | 
						|
    clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
namespace VirtualInheritance {
 | 
						|
  int counter;
 | 
						|
 | 
						|
  struct base {
 | 
						|
    base() {
 | 
						|
      ++counter;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  struct virtual_subclass : public virtual base {
 | 
						|
    virtual_subclass() {}
 | 
						|
  };
 | 
						|
 | 
						|
  struct double_subclass : public virtual_subclass {
 | 
						|
    double_subclass() {}
 | 
						|
  };
 | 
						|
 | 
						|
  void test() {
 | 
						|
    counter = 0;
 | 
						|
    double_subclass obj;
 | 
						|
    clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct double_virtual_subclass : public virtual virtual_subclass {
 | 
						|
    double_virtual_subclass() {}
 | 
						|
  };
 | 
						|
 | 
						|
  void testVirtual() {
 | 
						|
    counter = 0;
 | 
						|
    double_virtual_subclass obj;
 | 
						|
    clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace ZeroInitialization {
 | 
						|
  struct raw_pair {
 | 
						|
    int p1;
 | 
						|
    int p2;
 | 
						|
  };
 | 
						|
 | 
						|
  void testVarDecl() {
 | 
						|
    raw_pair p{};
 | 
						|
    clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  void testTemporary() {
 | 
						|
    clang_analyzer_eval(raw_pair().p1 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(raw_pair().p2 == 0); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  void testArray() {
 | 
						|
    raw_pair p[2] = {};
 | 
						|
    clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  void testNew() {
 | 
						|
    raw_pair *pp = new raw_pair();
 | 
						|
    clang_analyzer_eval(pp->p1 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(pp->p2 == 0); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  void testArrayNew() {
 | 
						|
    raw_pair *p = new raw_pair[2]();
 | 
						|
    clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct initializing_pair {
 | 
						|
  public:
 | 
						|
    int x;
 | 
						|
    raw_pair y;
 | 
						|
    initializing_pair() : x(), y() {}
 | 
						|
  };
 | 
						|
  
 | 
						|
  void testFieldInitializers() {
 | 
						|
    initializing_pair p;
 | 
						|
    clang_analyzer_eval(p.x == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p.y.p1 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p.y.p2 == 0); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct subclass : public raw_pair {
 | 
						|
    subclass() = default;
 | 
						|
  };
 | 
						|
 | 
						|
  void testSubclass() {
 | 
						|
    subclass p;
 | 
						|
    clang_analyzer_eval(p.p1 == 0); // expected-warning{{garbage}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct initializing_subclass : public raw_pair {
 | 
						|
    initializing_subclass() : raw_pair() {}
 | 
						|
  };
 | 
						|
 | 
						|
  void testInitializingSubclass() {
 | 
						|
    initializing_subclass p;
 | 
						|
    clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  struct pair_wrapper {
 | 
						|
    pair_wrapper() : p() {}
 | 
						|
    raw_pair p;
 | 
						|
  };
 | 
						|
 | 
						|
  struct virtual_subclass : public virtual pair_wrapper {
 | 
						|
    virtual_subclass() {}
 | 
						|
  };
 | 
						|
 | 
						|
  struct double_virtual_subclass : public virtual_subclass {
 | 
						|
    double_virtual_subclass() {
 | 
						|
      // This previously caused a crash because the pair_wrapper subobject was
 | 
						|
      // initialized twice.
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  class Empty {
 | 
						|
  public:
 | 
						|
    static int glob;
 | 
						|
    Empty(); // No body.
 | 
						|
    Empty(int x); // Body below.
 | 
						|
  };
 | 
						|
 | 
						|
  class PairContainer : public Empty {
 | 
						|
  public:
 | 
						|
    raw_pair p;
 | 
						|
    int q;
 | 
						|
    PairContainer() : Empty(), p() {
 | 
						|
      // This previously caused a crash because the empty base class looked
 | 
						|
      // like an initialization of 'p'.
 | 
						|
    }
 | 
						|
    PairContainer(int) : Empty(), p() {
 | 
						|
      // Test inlining something else here.
 | 
						|
    }
 | 
						|
    PairContainer(double): Empty(1), p() {
 | 
						|
      clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
 | 
						|
      clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
      clang_analyzer_eval(q == 1); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
      // This one's indeed UNKNOWN. Definitely not TRUE.
 | 
						|
      clang_analyzer_eval(p.p2 == glob); // expected-warning{{UNKNOWN}}
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  Empty::Empty(int x) {
 | 
						|
    static_cast<PairContainer *>(this)->p.p1 = x;
 | 
						|
    static_cast<PairContainer *>(this)->q = x;
 | 
						|
    // Our static member will store the old garbage values of fields that aren't
 | 
						|
    // yet initialized. It's not certainly garbage though (i.e. the constructor
 | 
						|
    // could have been called on an initialized piece of memory), so no
 | 
						|
    // uninitialized value warning here, and it should be a symbol, not
 | 
						|
    // undefined value, for later comparison.
 | 
						|
    glob = static_cast<PairContainer *>(this)->p.p2;
 | 
						|
  }
 | 
						|
 | 
						|
	class Empty2 {
 | 
						|
	public:
 | 
						|
		static int glob_p1, glob_p2;
 | 
						|
		Empty2(); // Body below.
 | 
						|
	};
 | 
						|
 | 
						|
	class PairDoubleEmptyContainer: public Empty, public Empty2 {
 | 
						|
	public:
 | 
						|
    raw_pair p;
 | 
						|
		PairDoubleEmptyContainer(): Empty(), Empty2(), p() {
 | 
						|
      clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
 | 
						|
      clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
      // This is indeed UNKNOWN.
 | 
						|
      clang_analyzer_eval(p.p1 == glob_p1); // expected-warning{{UNKNOWN}}
 | 
						|
      clang_analyzer_eval(p.p2 == glob_p2); // expected-warning{{UNKNOWN}}
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
	Empty2::Empty2() {
 | 
						|
    glob_p1 = static_cast<PairDoubleEmptyContainer *>(this)->p.p1;
 | 
						|
    glob_p2 = static_cast<PairDoubleEmptyContainer *>(this)->p.p2;
 | 
						|
	}
 | 
						|
 | 
						|
  class PairContainerContainer {
 | 
						|
    int padding;
 | 
						|
    PairContainer pc;
 | 
						|
  public:
 | 
						|
    PairContainerContainer() : pc(1) {}
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
namespace InitializerList {
 | 
						|
  struct List {
 | 
						|
    bool usedInitializerList;
 | 
						|
 | 
						|
    List() : usedInitializerList(false) {}
 | 
						|
    List(std::initializer_list<int>) : usedInitializerList(true) {}
 | 
						|
  };
 | 
						|
 | 
						|
  void testStatic() {
 | 
						|
    List defaultCtor;
 | 
						|
    clang_analyzer_eval(!defaultCtor.usedInitializerList); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    List list{1, 2};
 | 
						|
    clang_analyzer_eval(list.usedInitializerList); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
 | 
						|
  void testDynamic() {
 | 
						|
    List *list = new List{1, 2};
 | 
						|
    clang_analyzer_eval(list->usedInitializerList); // expected-warning{{TRUE}}
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace PR19579 {
 | 
						|
  class C {};
 | 
						|
 | 
						|
  void f() {
 | 
						|
    C();
 | 
						|
    int a;
 | 
						|
 | 
						|
    extern void use(int);
 | 
						|
    use(a); // expected-warning{{uninitialized}}
 | 
						|
  }
 | 
						|
 | 
						|
  void g() {
 | 
						|
    struct S {
 | 
						|
      C c;
 | 
						|
      int i;
 | 
						|
    };
 | 
						|
    
 | 
						|
    // This order triggers the initialization of the inner "a" after the
 | 
						|
    // constructor for "C" is run, which used to confuse the analyzer
 | 
						|
    // (is "C()" the initialization of "a"?).
 | 
						|
    struct S s = {
 | 
						|
      C(),
 | 
						|
      ({
 | 
						|
        int a, b = 0;
 | 
						|
        0;
 | 
						|
      })
 | 
						|
    };
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace NoCrashOnEmptyBaseOptimization {
 | 
						|
  struct NonEmptyBase {
 | 
						|
    int X;
 | 
						|
    explicit NonEmptyBase(int X) : X(X) {}
 | 
						|
  };
 | 
						|
 | 
						|
  struct EmptyBase {};
 | 
						|
 | 
						|
  struct S : NonEmptyBase, EmptyBase {
 | 
						|
    S() : NonEmptyBase(0), EmptyBase() {}
 | 
						|
  };
 | 
						|
 | 
						|
  void testSCtorNoCrash() {
 | 
						|
    S s;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace EmptyBaseAssign {
 | 
						|
struct B1 {};
 | 
						|
struct B2 { int x; };
 | 
						|
struct D: public B1, public B2 {
 | 
						|
const D &operator=(const D &d) {
 | 
						|
  *((B2 *)this) = d;
 | 
						|
  *((B1 *)this) = d;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
};
 | 
						|
 | 
						|
void test() {
 | 
						|
  D d1;
 | 
						|
  d1.x = 1;
 | 
						|
  D d2;
 | 
						|
  d2 = d1;
 | 
						|
  clang_analyzer_eval(d2.x == 1); // expected-warning{{TRUE}}
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
namespace vbase_zero_init {
 | 
						|
class A {
 | 
						|
  virtual void foo();
 | 
						|
};
 | 
						|
 | 
						|
class B {
 | 
						|
  virtual void bar();
 | 
						|
public:
 | 
						|
  static int glob_y, glob_z, glob_w;
 | 
						|
  int x;
 | 
						|
  B(); // Body below.
 | 
						|
};
 | 
						|
 | 
						|
class C : virtual public A {
 | 
						|
public:
 | 
						|
  int y;
 | 
						|
};
 | 
						|
 | 
						|
class D : public B, public C {
 | 
						|
public:
 | 
						|
  // 'z', unlike 'w', resides in an area that would have been within padding of
 | 
						|
  // base class 'C' if it wasn't part of 'D', but only on 64-bit systems.
 | 
						|
  int z, w;
 | 
						|
  // Initialization order: A(), B(), C().
 | 
						|
  D() : A(), C() {
 | 
						|
    clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
 | 
						|
    clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
 | 
						|
#ifdef I386
 | 
						|
    clang_analyzer_eval(z == 3); // expected-warning{{TRUE}}
 | 
						|
#else
 | 
						|
    // FIXME: Should be TRUE. Initialized in B().
 | 
						|
    clang_analyzer_eval(z == 3); // expected-warning{{UNKNOWN}}
 | 
						|
#endif
 | 
						|
    clang_analyzer_eval(w == 4); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
    // FIXME: Should be UNKNOWN. Changed in B() since glob_y was assigned.
 | 
						|
    clang_analyzer_eval(y == glob_y); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
#ifdef I386
 | 
						|
    clang_analyzer_eval(z == glob_z); // expected-warning{{UNKNOWN}}
 | 
						|
#else
 | 
						|
    // FIXME: Should be UNKNOWN. Changed in B() since glob_z was assigned.
 | 
						|
    clang_analyzer_eval(z == glob_z); // expected-warning{{TRUE}}
 | 
						|
#endif
 | 
						|
 | 
						|
    clang_analyzer_eval(w == glob_w); // expected-warning{{UNKNOWN}}
 | 
						|
  } // no-crash
 | 
						|
};
 | 
						|
 | 
						|
B::B() : x(1) {
 | 
						|
  // Our static members will store the old garbage values of fields that aren't
 | 
						|
  // yet initialized. These aren't certainly garbage though (i.e. the
 | 
						|
  // constructor could have been called on an initialized piece of memory),
 | 
						|
  // so no uninitialized value warning here, and these should be symbols, not
 | 
						|
  // undefined values, for later comparison.
 | 
						|
  glob_y = static_cast<D *>(this)->y;
 | 
						|
  glob_z = static_cast<D *>(this)->z;
 | 
						|
  glob_w = static_cast<D *>(this)->w;
 | 
						|
  static_cast<D *>(this)->y = 2;
 | 
						|
  static_cast<D *>(this)->z = 3;
 | 
						|
  static_cast<D *>(this)->w = 4;
 | 
						|
}
 | 
						|
}
 |