forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			83 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
 | 
						|
 | 
						|
void clang_analyzer_eval(bool);
 | 
						|
 | 
						|
struct A {
 | 
						|
  // This conversion operator allows implicit conversion to bool but not to other integer types.
 | 
						|
  typedef A * (A::*MemberPointer);
 | 
						|
  operator MemberPointer() const { return m_ptr ? &A::m_ptr : 0; }
 | 
						|
 | 
						|
  A *m_ptr;
 | 
						|
 | 
						|
  A *getPtr();
 | 
						|
  typedef A * (A::*MemberFnPointer)(void);
 | 
						|
};
 | 
						|
 | 
						|
void testConditionalUse() {
 | 
						|
  A obj;
 | 
						|
 | 
						|
  obj.m_ptr = &obj;
 | 
						|
  clang_analyzer_eval(obj.m_ptr); // expected-warning{{TRUE}}
 | 
						|
  clang_analyzer_eval(&A::m_ptr); // expected-warning{{TRUE}}
 | 
						|
  clang_analyzer_eval(obj); // expected-warning{{TRUE}}
 | 
						|
 | 
						|
  obj.m_ptr = 0;
 | 
						|
  clang_analyzer_eval(obj.m_ptr); // expected-warning{{FALSE}}
 | 
						|
  clang_analyzer_eval(A::MemberPointer(0)); // expected-warning{{FALSE}}
 | 
						|
  clang_analyzer_eval(obj); // expected-warning{{FALSE}}
 | 
						|
 | 
						|
  clang_analyzer_eval(&A::getPtr); // expected-warning{{TRUE}}
 | 
						|
  clang_analyzer_eval(A::MemberFnPointer(0)); // expected-warning{{FALSE}}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void testComparison() {
 | 
						|
  clang_analyzer_eval(&A::getPtr == &A::getPtr); // expected-warning{{TRUE}}
 | 
						|
  clang_analyzer_eval(&A::getPtr == 0); // expected-warning{{FALSE}}
 | 
						|
 | 
						|
  // FIXME: Should be TRUE.
 | 
						|
  clang_analyzer_eval(&A::m_ptr == &A::m_ptr); // expected-warning{{UNKNOWN}}
 | 
						|
}
 | 
						|
 | 
						|
namespace PR15742 {
 | 
						|
  template <class _T1, class _T2> struct A {
 | 
						|
    A (const _T1 &, const _T2 &);
 | 
						|
  };
 | 
						|
  
 | 
						|
  typedef void *NPIdentifier;
 | 
						|
 | 
						|
  template <class T> class B {
 | 
						|
  public:
 | 
						|
    typedef A<NPIdentifier, bool (T::*) (const NPIdentifier *, unsigned,
 | 
						|
                                         NPIdentifier *)> MethodMapMember;
 | 
						|
  };
 | 
						|
 | 
						|
  class C : public B<C> {
 | 
						|
  public:
 | 
						|
    bool Find(const NPIdentifier *, unsigned, NPIdentifier *);
 | 
						|
  };
 | 
						|
 | 
						|
  void InitStaticData () {
 | 
						|
    C::MethodMapMember(0, &C::Find); // don't crash
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// ---------------
 | 
						|
// FALSE NEGATIVES
 | 
						|
// ---------------
 | 
						|
 | 
						|
bool testDereferencing() {
 | 
						|
  A obj;
 | 
						|
  obj.m_ptr = 0;
 | 
						|
 | 
						|
  A::MemberPointer member = &A::m_ptr;
 | 
						|
 | 
						|
  // FIXME: Should be TRUE.
 | 
						|
  clang_analyzer_eval(obj.*member == 0); // expected-warning{{UNKNOWN}}
 | 
						|
 | 
						|
  member = 0;
 | 
						|
 | 
						|
  // FIXME: Should emit a null dereference.
 | 
						|
  return obj.*member; // no-warning
 | 
						|
}
 |