|  | // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=false -verify -analyzer-config eagerly-assume=false %s | 
|  | // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=true -DINLINE=1 -verify -analyzer-config eagerly-assume=false %s | 
|  | // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=false -DTEST_INLINABLE_ALLOCATORS -verify -analyzer-config eagerly-assume=false %s | 
|  | // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=true -DTEST_INLINABLE_ALLOCATORS -DINLINE=1 -verify -analyzer-config eagerly-assume=false %s | 
|  |  | 
|  | #ifndef HEADER | 
|  |  | 
|  | void clang_analyzer_eval(bool); | 
|  | void clang_analyzer_checkInlined(bool); | 
|  |  | 
|  | #define HEADER | 
|  | #include "containers.cpp" | 
|  | #undef HEADER | 
|  |  | 
|  | void test() { | 
|  | MySet set(0); | 
|  |  | 
|  | clang_analyzer_eval(set.isEmpty()); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #else | 
|  | // expected-warning@-4 {{UNKNOWN}} | 
|  | #endif | 
|  |  | 
|  | clang_analyzer_eval(set.raw_begin() == set.raw_end()); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #else | 
|  | // expected-warning@-4 {{UNKNOWN}} | 
|  | #endif | 
|  |  | 
|  | clang_analyzer_eval(set.begin().impl == set.end().impl); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #else | 
|  | // expected-warning@-4 {{UNKNOWN}} | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void testSubclass(MySetSubclass &sub) { | 
|  | sub.useIterator(sub.begin()); | 
|  |  | 
|  | MySetSubclass local; | 
|  | } | 
|  |  | 
|  | void testWrappers(BeginOnlySet &w1, IteratorStructOnlySet &w2, | 
|  | IteratorTypedefOnlySet &w3, IteratorUsingOnlySet &w4) { | 
|  | BeginOnlySet local1; | 
|  | IteratorStructOnlySet local2; | 
|  | IteratorTypedefOnlySet local3; | 
|  | IteratorUsingOnlySet local4; | 
|  |  | 
|  | clang_analyzer_eval(w1.begin().impl.impl == w1.begin().impl.impl); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #else | 
|  | // expected-warning@-4 {{UNKNOWN}} | 
|  | #endif | 
|  |  | 
|  | clang_analyzer_eval(w2.start().impl == w2.start().impl); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #else | 
|  | // expected-warning@-4 {{UNKNOWN}} | 
|  | #endif | 
|  |  | 
|  | clang_analyzer_eval(w3.start().impl == w3.start().impl); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #else | 
|  | // expected-warning@-4 {{UNKNOWN}} | 
|  | #endif | 
|  |  | 
|  | clang_analyzer_eval(w4.start().impl == w4.start().impl); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #else | 
|  | // expected-warning@-4 {{UNKNOWN}} | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | #else // HEADER | 
|  |  | 
|  | #include "../Inputs/system-header-simulator-cxx.h" | 
|  |  | 
|  | class MySet { | 
|  | int *storage; | 
|  | unsigned size; | 
|  | public: | 
|  | MySet() : storage(0), size(0) { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | } | 
|  |  | 
|  | MySet(unsigned n) : storage(new int[n]), size(n) { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | } | 
|  |  | 
|  | ~MySet() { delete[] storage; } | 
|  |  | 
|  | bool isEmpty() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | return size == 0; | 
|  | } | 
|  |  | 
|  | struct iterator { | 
|  | int *impl; | 
|  |  | 
|  | iterator(int *p) : impl(p) {} | 
|  | }; | 
|  |  | 
|  | iterator begin() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | return iterator(storage); | 
|  | } | 
|  |  | 
|  | iterator end() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | return iterator(storage+size); | 
|  | } | 
|  |  | 
|  | typedef int *raw_iterator; | 
|  |  | 
|  | raw_iterator raw_begin() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | return storage; | 
|  | } | 
|  | raw_iterator raw_end() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | return storage + size; | 
|  | } | 
|  | }; | 
|  |  | 
|  | class MySetSubclass : public MySet { | 
|  | public: | 
|  | MySetSubclass() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void useIterator(iterator i) { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | } | 
|  | }; | 
|  |  | 
|  | class BeginOnlySet { | 
|  | MySet impl; | 
|  | public: | 
|  | struct IterImpl { | 
|  | MySet::iterator impl; | 
|  | typedef std::forward_iterator_tag iterator_category; | 
|  |  | 
|  | IterImpl(MySet::iterator i) : impl(i) { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | } | 
|  | }; | 
|  |  | 
|  | BeginOnlySet() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | } | 
|  |  | 
|  | typedef IterImpl wrapped_iterator; | 
|  |  | 
|  | wrapped_iterator begin() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | return IterImpl(impl.begin()); | 
|  | } | 
|  | }; | 
|  |  | 
|  | class IteratorTypedefOnlySet { | 
|  | MySet impl; | 
|  | public: | 
|  |  | 
|  | IteratorTypedefOnlySet() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | } | 
|  |  | 
|  | typedef MySet::iterator iterator; | 
|  |  | 
|  | iterator start() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | return impl.begin(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | class IteratorUsingOnlySet { | 
|  | MySet impl; | 
|  | public: | 
|  |  | 
|  | IteratorUsingOnlySet() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | } | 
|  |  | 
|  | using iterator = MySet::iterator; | 
|  |  | 
|  | iterator start() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | return impl.begin(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | class IteratorStructOnlySet { | 
|  | MySet impl; | 
|  | public: | 
|  |  | 
|  | IteratorStructOnlySet() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | } | 
|  |  | 
|  | struct iterator { | 
|  | int *impl; | 
|  | }; | 
|  |  | 
|  | iterator start() { | 
|  | clang_analyzer_checkInlined(true); | 
|  | #if INLINE | 
|  | // expected-warning@-2 {{TRUE}} | 
|  | #endif | 
|  | return iterator{impl.begin().impl}; | 
|  | } | 
|  | }; | 
|  |  | 
|  | #endif // HEADER |