diff options
author | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
commit | 056abd2059c65a3e908193aeae16fad98017437c (patch) | |
tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /test/Analysis/inline.cpp | |
parent | cc73504950eb7b5dff2dded9bedd67bc36d64641 (diff) | |
download | FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz |
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'test/Analysis/inline.cpp')
-rw-r--r-- | test/Analysis/inline.cpp | 176 |
1 files changed, 175 insertions, 1 deletions
diff --git a/test/Analysis/inline.cpp b/test/Analysis/inline.cpp index 6b9a885..ddcf5d0 100644 --- a/test/Analysis/inline.cpp +++ b/test/Analysis/inline.cpp @@ -1,8 +1,18 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-ipa=inlining -verify %s void clang_analyzer_eval(bool); void clang_analyzer_checkInlined(bool); +typedef __typeof__(sizeof(int)) size_t; +extern "C" void *malloc(size_t); + +// This is the standard placement new. +inline void* operator new(size_t, void* __p) throw() +{ + return __p; +} + + class A { public: int getZero() { return 0; } @@ -193,3 +203,167 @@ namespace Invalidation { } }; } + +namespace DefaultArgs { + int takesDefaultArgs(int i = 42) { + return -i; + } + + void testFunction() { + clang_analyzer_eval(takesDefaultArgs(1) == -1); // expected-warning{{TRUE}} + clang_analyzer_eval(takesDefaultArgs() == -42); // expected-warning{{TRUE}} + } + + class Secret { + public: + static const int value = 42; + int get(int i = value) { + return i; + } + }; + + void testMethod() { + Secret obj; + clang_analyzer_eval(obj.get(1) == 1); // expected-warning{{TRUE}} + + // FIXME: Should be 'TRUE'. See PR13673 or <rdar://problem/11720796>. + clang_analyzer_eval(obj.get() == 42); // expected-warning{{UNKNOWN}} + + // FIXME: Even if we constrain the variable, we still have a problem. + // See PR13385 or <rdar://problem/12156507>. + if (Secret::value != 42) + return; + clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}} + clang_analyzer_eval(obj.get() == 42); // expected-warning{{UNKNOWN}} + } +} + +namespace OperatorNew { + class IntWrapper { + public: + int value; + + IntWrapper(int input) : value(input) { + // We don't want this constructor to be inlined unless we can actually + // use the proper region for operator new. + // See PR12014 and <rdar://problem/12180598>. + clang_analyzer_checkInlined(false); // no-warning + } + }; + + void test() { + IntWrapper *obj = new IntWrapper(42); + // should be TRUE + clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}} + } + + void testPlacement() { + IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper))); + IntWrapper *alias = new (obj) IntWrapper(42); + + clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}} + + // should be TRUE + clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}} + } +} + + +namespace VirtualWithSisterCasts { + // This entire set of tests exercises casts from sister classes and + // from classes outside the hierarchy, which can very much confuse + // code that uses DynamicTypeInfo or needs to construct CXXBaseObjectRegions. + // These examples used to cause crashes in +Asserts builds. + struct Parent { + virtual int foo(); + int x; + }; + + struct A : Parent { + virtual int foo() { return 42; } + }; + + struct B : Parent { + virtual int foo(); + }; + + struct Grandchild : public A {}; + + struct Unrelated {}; + + void testDowncast(Parent *b) { + A *a = (A *)(void *)b; + clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}} + + a->x = 42; + clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}} + } + + void testRelated(B *b) { + A *a = (A *)(void *)b; + clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}} + + a->x = 42; + clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}} + } + + void testUnrelated(Unrelated *b) { + A *a = (A *)(void *)b; + clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}} + + a->x = 42; + clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}} + } + + void testCastViaNew(B *b) { + Grandchild *g = new (b) Grandchild(); + // FIXME: We actually now have perfect type info because of 'new'. + // This should be TRUE. + clang_analyzer_eval(g->foo() == 42); // expected-warning{{UNKNOWN}} + + g->x = 42; + clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}} + } +} + + +namespace QualifiedCalls { + void test(One *object) { + // This uses the One class from the top of the file. + clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}} + + // getZero is non-virtual. + clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}} +} +} + + +namespace rdar12409977 { + struct Base { + int x; + }; + + struct Parent : public Base { + virtual Parent *vGetThis(); + Parent *getThis() { return vGetThis(); } + }; + + struct Child : public Parent { + virtual Child *vGetThis() { return this; } + }; + + void test() { + Child obj; + obj.x = 42; + + // Originally, calling a devirtualized method with a covariant return type + // caused a crash because the return value had the wrong type. When we then + // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of + // the object region and we get an assertion failure. + clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}} + } +} |