xref: /llvm-project/clang/test/Analysis/Checkers/WebKit/call-args-checked-ptr.cpp (revision 05860f9b384b9b8f8bb01fa8984dbc2833669a27)
1ef353b02SRyosuke Niwa // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncheckedCallArgsChecker -verify %s
2ef353b02SRyosuke Niwa 
3ef353b02SRyosuke Niwa #include "mock-types.h"
4ef353b02SRyosuke Niwa 
5ef353b02SRyosuke Niwa CheckedObj* provide();
6ef353b02SRyosuke Niwa void consume_refcntbl(CheckedObj*);
7ef353b02SRyosuke Niwa void some_function();
8ef353b02SRyosuke Niwa 
9ef353b02SRyosuke Niwa namespace simple {
10ef353b02SRyosuke Niwa   void foo() {
11ef353b02SRyosuke Niwa     consume_refcntbl(provide());
12ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument is unchecked and unsafe}}
13ef353b02SRyosuke Niwa   }
14ef353b02SRyosuke Niwa 
15ef353b02SRyosuke Niwa   // Test that the checker works with [[clang::suppress]].
16ef353b02SRyosuke Niwa   void foo_suppressed() {
17ef353b02SRyosuke Niwa     [[clang::suppress]]
18ef353b02SRyosuke Niwa     consume_refcntbl(provide()); // no-warning
19ef353b02SRyosuke Niwa   }
20ef353b02SRyosuke Niwa }
21ef353b02SRyosuke Niwa 
22ef353b02SRyosuke Niwa namespace multi_arg {
23ef353b02SRyosuke Niwa   void consume_refcntbl(int, CheckedObj* foo, bool);
24ef353b02SRyosuke Niwa   void foo() {
25ef353b02SRyosuke Niwa     consume_refcntbl(42, provide(), true);
26ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument for parameter 'foo' is unchecked and unsafe}}
27ef353b02SRyosuke Niwa   }
28ef353b02SRyosuke Niwa }
29ef353b02SRyosuke Niwa 
30ef353b02SRyosuke Niwa namespace ref_counted {
31ef353b02SRyosuke Niwa   CheckedRef<CheckedObj> provide_ref_counted() { return CheckedRef<CheckedObj>{}; }
32ef353b02SRyosuke Niwa   void consume_ref_counted(CheckedRef<CheckedObj>) {}
33ef353b02SRyosuke Niwa 
34ef353b02SRyosuke Niwa   void foo() {
35ef353b02SRyosuke Niwa     consume_refcntbl(provide_ref_counted().ptr());
36ef353b02SRyosuke Niwa     // no warning
37ef353b02SRyosuke Niwa   }
38ef353b02SRyosuke Niwa }
39ef353b02SRyosuke Niwa 
40ef353b02SRyosuke Niwa namespace methods {
41ef353b02SRyosuke Niwa   struct Consumer {
42ef353b02SRyosuke Niwa     void consume_ptr(CheckedObj* ptr);
43ef353b02SRyosuke Niwa     void consume_ref(const CheckedObj& ref);
44ef353b02SRyosuke Niwa   };
45ef353b02SRyosuke Niwa 
46ef353b02SRyosuke Niwa   void foo() {
47ef353b02SRyosuke Niwa     Consumer c;
48ef353b02SRyosuke Niwa 
49ef353b02SRyosuke Niwa     c.consume_ptr(provide());
50ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument for parameter 'ptr' is unchecked and unsafe}}
51ef353b02SRyosuke Niwa     c.consume_ref(*provide());
52ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument for parameter 'ref' is unchecked and unsafe}}
53ef353b02SRyosuke Niwa   }
54ef353b02SRyosuke Niwa 
55ef353b02SRyosuke Niwa   void foo2() {
56ef353b02SRyosuke Niwa     struct Consumer {
57ef353b02SRyosuke Niwa       void consume(CheckedObj*) { some_function(); }
58ef353b02SRyosuke Niwa       void whatever() {
59ef353b02SRyosuke Niwa         consume(provide());
60ef353b02SRyosuke Niwa         // expected-warning@-1{{Call argument is unchecked and unsafe}}
61ef353b02SRyosuke Niwa       }
62ef353b02SRyosuke Niwa     };
63ef353b02SRyosuke Niwa   }
64ef353b02SRyosuke Niwa 
65ef353b02SRyosuke Niwa   void foo3() {
66ef353b02SRyosuke Niwa     struct Consumer {
67ef353b02SRyosuke Niwa       void consume(CheckedObj*) { some_function(); }
68ef353b02SRyosuke Niwa       void whatever() {
69ef353b02SRyosuke Niwa         this->consume(provide());
70ef353b02SRyosuke Niwa         // expected-warning@-1{{Call argument is unchecked and unsafe}}
71ef353b02SRyosuke Niwa       }
72ef353b02SRyosuke Niwa     };
73ef353b02SRyosuke Niwa   }
74ef353b02SRyosuke Niwa }
75ef353b02SRyosuke Niwa 
76ef353b02SRyosuke Niwa namespace casts {
77ef353b02SRyosuke Niwa   CheckedObj* downcast(CheckedObj*);
78ef353b02SRyosuke Niwa 
79ef353b02SRyosuke Niwa   void foo() {
80ef353b02SRyosuke Niwa     consume_refcntbl(provide());
81ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument is unchecked and unsafe}}
82ef353b02SRyosuke Niwa 
83ef353b02SRyosuke Niwa     consume_refcntbl(static_cast<CheckedObj*>(provide()));
84ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument is unchecked and unsafe}}
85ef353b02SRyosuke Niwa 
86ef353b02SRyosuke Niwa     consume_refcntbl(dynamic_cast<CheckedObj*>(provide()));
87ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument is unchecked and unsafe}}
88ef353b02SRyosuke Niwa 
89ef353b02SRyosuke Niwa     consume_refcntbl(const_cast<CheckedObj*>(provide()));
90ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument is unchecked and unsafe}}
91ef353b02SRyosuke Niwa 
92ef353b02SRyosuke Niwa     consume_refcntbl(reinterpret_cast<CheckedObj*>(provide()));
93ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument is unchecked and unsafe}}
94ef353b02SRyosuke Niwa 
95ef353b02SRyosuke Niwa     consume_refcntbl(downcast(provide()));
96ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument is unchecked and unsafe}}
97ef353b02SRyosuke Niwa 
98ef353b02SRyosuke Niwa     consume_refcntbl(
99ef353b02SRyosuke Niwa       static_cast<CheckedObj*>(
100ef353b02SRyosuke Niwa         downcast(
101ef353b02SRyosuke Niwa           static_cast<CheckedObj*>(
102ef353b02SRyosuke Niwa             provide()
103ef353b02SRyosuke Niwa           )
104ef353b02SRyosuke Niwa         )
105ef353b02SRyosuke Niwa       )
106ef353b02SRyosuke Niwa     );
107ef353b02SRyosuke Niwa     // expected-warning@-8{{Call argument is unchecked and unsafe}}
108ef353b02SRyosuke Niwa   }
109ef353b02SRyosuke Niwa }
110ef353b02SRyosuke Niwa 
111ef353b02SRyosuke Niwa namespace null_ptr {
112ef353b02SRyosuke Niwa   void foo_ref() {
113ef353b02SRyosuke Niwa     consume_refcntbl(nullptr);
114ef353b02SRyosuke Niwa     consume_refcntbl(0);
115ef353b02SRyosuke Niwa   }
116ef353b02SRyosuke Niwa }
117ef353b02SRyosuke Niwa 
118ef353b02SRyosuke Niwa namespace ref_counted_lookalike {
119ef353b02SRyosuke Niwa   struct Decoy {
120*05860f9bSRyosuke Niwa     CheckedObj* get();
121ef353b02SRyosuke Niwa   };
122ef353b02SRyosuke Niwa 
123ef353b02SRyosuke Niwa   void foo() {
124ef353b02SRyosuke Niwa     Decoy D;
125ef353b02SRyosuke Niwa 
126ef353b02SRyosuke Niwa     consume_refcntbl(D.get());
127ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument is unchecked and unsafe}}
128ef353b02SRyosuke Niwa   }
129ef353b02SRyosuke Niwa }
130ef353b02SRyosuke Niwa 
131ef353b02SRyosuke Niwa namespace Ref_to_reference_conversion_operator {
132ef353b02SRyosuke Niwa   template<typename T> struct Ref {
133ef353b02SRyosuke Niwa     Ref() = default;
134ef353b02SRyosuke Niwa     Ref(T*) { }
135ef353b02SRyosuke Niwa     T* get() { return nullptr; }
136ef353b02SRyosuke Niwa     operator T& () { return t; }
137ef353b02SRyosuke Niwa     T t;
138ef353b02SRyosuke Niwa   };
139ef353b02SRyosuke Niwa 
140ef353b02SRyosuke Niwa   void consume_ref(CheckedObj&) {}
141ef353b02SRyosuke Niwa 
142ef353b02SRyosuke Niwa   void foo() {
143ef353b02SRyosuke Niwa     CheckedRef<CheckedObj> bar;
144ef353b02SRyosuke Niwa     consume_ref(bar);
145ef353b02SRyosuke Niwa   }
146ef353b02SRyosuke Niwa }
147ef353b02SRyosuke Niwa 
148ef353b02SRyosuke Niwa namespace param_formarding_function {
149ef353b02SRyosuke Niwa   void consume_ref_countable_ref(CheckedObj&);
150ef353b02SRyosuke Niwa   void consume_ref_countable_ptr(CheckedObj*);
151ef353b02SRyosuke Niwa 
152ef353b02SRyosuke Niwa   namespace ptr {
153ef353b02SRyosuke Niwa     void foo(CheckedObj* param) {
154ef353b02SRyosuke Niwa       consume_ref_countable_ptr(param);
155ef353b02SRyosuke Niwa     }
156ef353b02SRyosuke Niwa   }
157ef353b02SRyosuke Niwa 
158ef353b02SRyosuke Niwa   namespace ref {
159ef353b02SRyosuke Niwa     void foo(CheckedObj& param) {
160ef353b02SRyosuke Niwa       consume_ref_countable_ref(param);
161ef353b02SRyosuke Niwa     }
162ef353b02SRyosuke Niwa   }
163ef353b02SRyosuke Niwa 
164ef353b02SRyosuke Niwa   namespace ref_deref_operators {
165ef353b02SRyosuke Niwa     void foo_ref(CheckedObj& param) {
166ef353b02SRyosuke Niwa       consume_ref_countable_ptr(&param);
167ef353b02SRyosuke Niwa     }
168ef353b02SRyosuke Niwa 
169ef353b02SRyosuke Niwa     void foo_ptr(CheckedObj* param) {
170ef353b02SRyosuke Niwa       consume_ref_countable_ref(*param);
171ef353b02SRyosuke Niwa     }
172ef353b02SRyosuke Niwa   }
173ef353b02SRyosuke Niwa 
174ef353b02SRyosuke Niwa   namespace casts {
175ef353b02SRyosuke Niwa 
176ef353b02SRyosuke Niwa   CheckedObj* downcast(CheckedObj*) { return nullptr; }
177ef353b02SRyosuke Niwa 
178ef353b02SRyosuke Niwa   template<class T>
179ef353b02SRyosuke Niwa   T* bitwise_cast(T*) { return nullptr; }
180ef353b02SRyosuke Niwa 
181ef353b02SRyosuke Niwa     void foo(CheckedObj* param) {
182ef353b02SRyosuke Niwa       consume_ref_countable_ptr(downcast(param));
183ef353b02SRyosuke Niwa       consume_ref_countable_ptr(bitwise_cast(param));
184ef353b02SRyosuke Niwa      }
185ef353b02SRyosuke Niwa   }
186ef353b02SRyosuke Niwa }
187ef353b02SRyosuke Niwa 
188ef353b02SRyosuke Niwa namespace param_formarding_lambda {
189ef353b02SRyosuke Niwa   auto consume_ref_countable_ref = [](CheckedObj&) { some_function(); };
190ef353b02SRyosuke Niwa   auto consume_ref_countable_ptr = [](CheckedObj*) { some_function(); };
191ef353b02SRyosuke Niwa 
192ef353b02SRyosuke Niwa   namespace ptr {
193ef353b02SRyosuke Niwa     void foo(CheckedObj* param) {
194ef353b02SRyosuke Niwa       consume_ref_countable_ptr(param);
195ef353b02SRyosuke Niwa     }
196ef353b02SRyosuke Niwa   }
197ef353b02SRyosuke Niwa 
198ef353b02SRyosuke Niwa   namespace ref {
199ef353b02SRyosuke Niwa     void foo(CheckedObj& param) {
200ef353b02SRyosuke Niwa       consume_ref_countable_ref(param);
201ef353b02SRyosuke Niwa     }
202ef353b02SRyosuke Niwa   }
203ef353b02SRyosuke Niwa 
204ef353b02SRyosuke Niwa   namespace ref_deref_operators {
205ef353b02SRyosuke Niwa     void foo_ref(CheckedObj& param) {
206ef353b02SRyosuke Niwa       consume_ref_countable_ptr(&param);
207ef353b02SRyosuke Niwa     }
208ef353b02SRyosuke Niwa 
209ef353b02SRyosuke Niwa     void foo_ptr(CheckedObj* param) {
210ef353b02SRyosuke Niwa       consume_ref_countable_ref(*param);
211ef353b02SRyosuke Niwa     }
212ef353b02SRyosuke Niwa   }
213ef353b02SRyosuke Niwa 
214ef353b02SRyosuke Niwa   namespace casts {
215ef353b02SRyosuke Niwa 
216ef353b02SRyosuke Niwa   CheckedObj* downcast(CheckedObj*) { return nullptr; }
217ef353b02SRyosuke Niwa 
218ef353b02SRyosuke Niwa   template<class T>
219ef353b02SRyosuke Niwa   T* bitwise_cast(T*) { return nullptr; }
220ef353b02SRyosuke Niwa 
221ef353b02SRyosuke Niwa     void foo(CheckedObj* param) {
222ef353b02SRyosuke Niwa       consume_ref_countable_ptr(downcast(param));
223ef353b02SRyosuke Niwa       consume_ref_countable_ptr(bitwise_cast(param));
224ef353b02SRyosuke Niwa     }
225ef353b02SRyosuke Niwa   }
226ef353b02SRyosuke Niwa }
227ef353b02SRyosuke Niwa 
228ef353b02SRyosuke Niwa namespace param_forwarding_method {
229ef353b02SRyosuke Niwa   struct methodclass {
230ef353b02SRyosuke Niwa     void consume_ref_countable_ref(CheckedObj&) {};
231ef353b02SRyosuke Niwa     static void consume_ref_countable_ptr(CheckedObj*) {};
232ef353b02SRyosuke Niwa   };
233ef353b02SRyosuke Niwa 
234ef353b02SRyosuke Niwa   namespace ptr {
235ef353b02SRyosuke Niwa     void foo(CheckedObj* param) {
236ef353b02SRyosuke Niwa       methodclass::consume_ref_countable_ptr(param);
237ef353b02SRyosuke Niwa      }
238ef353b02SRyosuke Niwa   }
239ef353b02SRyosuke Niwa 
240ef353b02SRyosuke Niwa   namespace ref {
241ef353b02SRyosuke Niwa     void foo(CheckedObj& param) {
242ef353b02SRyosuke Niwa       methodclass mc;
243ef353b02SRyosuke Niwa       mc.consume_ref_countable_ref(param);
244ef353b02SRyosuke Niwa      }
245ef353b02SRyosuke Niwa   }
246ef353b02SRyosuke Niwa 
247ef353b02SRyosuke Niwa   namespace ref_deref_operators {
248ef353b02SRyosuke Niwa     void foo_ref(CheckedObj& param) {
249ef353b02SRyosuke Niwa       methodclass::consume_ref_countable_ptr(&param);
250ef353b02SRyosuke Niwa      }
251ef353b02SRyosuke Niwa 
252ef353b02SRyosuke Niwa     void foo_ptr(CheckedObj* param) {
253ef353b02SRyosuke Niwa       methodclass mc;
254ef353b02SRyosuke Niwa       mc.consume_ref_countable_ref(*param);
255ef353b02SRyosuke Niwa      }
256ef353b02SRyosuke Niwa   }
257ef353b02SRyosuke Niwa 
258ef353b02SRyosuke Niwa   namespace casts {
259ef353b02SRyosuke Niwa 
260ef353b02SRyosuke Niwa   CheckedObj* downcast(CheckedObj*) { return nullptr; }
261ef353b02SRyosuke Niwa 
262ef353b02SRyosuke Niwa   template<class T>
263ef353b02SRyosuke Niwa   T* bitwise_cast(T*) { return nullptr; }
264ef353b02SRyosuke Niwa 
265ef353b02SRyosuke Niwa     void foo(CheckedObj* param) {
266ef353b02SRyosuke Niwa       methodclass::consume_ref_countable_ptr(downcast(param));
267ef353b02SRyosuke Niwa        methodclass::consume_ref_countable_ptr(bitwise_cast(param));
268ef353b02SRyosuke Niwa      }
269ef353b02SRyosuke Niwa   }
270ef353b02SRyosuke Niwa }
271ef353b02SRyosuke Niwa 
272ef353b02SRyosuke Niwa namespace downcast {
273ef353b02SRyosuke Niwa   void consume_ref_countable(CheckedObj*) {}
274ef353b02SRyosuke Niwa   CheckedObj* downcast(CheckedObj*) { return nullptr; }
275ef353b02SRyosuke Niwa 
276ef353b02SRyosuke Niwa   void foo() {
277ef353b02SRyosuke Niwa     CheckedPtr<CheckedObj> bar;
278ef353b02SRyosuke Niwa     consume_ref_countable( downcast(bar.get()) );
279ef353b02SRyosuke Niwa   }
280ef353b02SRyosuke Niwa }
281ef353b02SRyosuke Niwa 
282ef353b02SRyosuke Niwa namespace string_impl {
283ef353b02SRyosuke Niwa   struct String {
284ef353b02SRyosuke Niwa     CheckedObj* impl() { return nullptr; }
285ef353b02SRyosuke Niwa   };
286ef353b02SRyosuke Niwa 
287ef353b02SRyosuke Niwa   struct AtomString {
288ef353b02SRyosuke Niwa     CheckedObj rc;
289ef353b02SRyosuke Niwa     CheckedObj& impl() { return rc; }
290ef353b02SRyosuke Niwa   };
291ef353b02SRyosuke Niwa 
292ef353b02SRyosuke Niwa   void consume_ptr(CheckedObj*) {}
293ef353b02SRyosuke Niwa   void consume_ref(CheckedObj&) {}
294ef353b02SRyosuke Niwa 
295ef353b02SRyosuke Niwa   namespace simple {
296ef353b02SRyosuke Niwa     void foo() {
297ef353b02SRyosuke Niwa       String s;
298ef353b02SRyosuke Niwa       AtomString as;
299ef353b02SRyosuke Niwa       consume_ptr(s.impl());
300ef353b02SRyosuke Niwa       consume_ref(as.impl());
301ef353b02SRyosuke Niwa     }
302ef353b02SRyosuke Niwa   }
303ef353b02SRyosuke Niwa }
304ef353b02SRyosuke Niwa 
305ef353b02SRyosuke Niwa namespace default_arg {
306ef353b02SRyosuke Niwa   CheckedObj* global;
307ef353b02SRyosuke Niwa 
308ef353b02SRyosuke Niwa   void function_with_default_arg(CheckedObj* param = global);
309ef353b02SRyosuke Niwa   // expected-warning@-1{{Call argument for parameter 'param' is unchecked and unsafe}}
310ef353b02SRyosuke Niwa 
311ef353b02SRyosuke Niwa   void foo() {
312ef353b02SRyosuke Niwa     function_with_default_arg();
313ef353b02SRyosuke Niwa   }
314ef353b02SRyosuke Niwa }
315ef353b02SRyosuke Niwa 
316ef353b02SRyosuke Niwa namespace cxx_member_func {
317ef353b02SRyosuke Niwa   CheckedRef<CheckedObj> provideProtected();
318ef353b02SRyosuke Niwa   void foo() {
319ef353b02SRyosuke Niwa     provide()->trivial();
320ef353b02SRyosuke Niwa     provide()->method();
321ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument for 'this' parameter is unchecked and unsafe}}
322ef353b02SRyosuke Niwa     provideProtected()->method();
323ef353b02SRyosuke Niwa     (provideProtected())->method();
324ef353b02SRyosuke Niwa   };
325ef353b02SRyosuke Niwa }
326ef353b02SRyosuke Niwa 
327ef353b02SRyosuke Niwa namespace cxx_member_operator_call {
328ef353b02SRyosuke Niwa   // The hidden this-pointer argument without a corresponding parameter caused couple bugs in parameter <-> argument attribution.
329ef353b02SRyosuke Niwa   struct Foo {
330ef353b02SRyosuke Niwa     Foo& operator+(CheckedObj* bad);
331ef353b02SRyosuke Niwa     friend Foo& operator-(Foo& lhs, CheckedObj* bad);
332ef353b02SRyosuke Niwa     void operator()(CheckedObj* bad);
333ef353b02SRyosuke Niwa   };
334ef353b02SRyosuke Niwa 
335ef353b02SRyosuke Niwa   CheckedObj* global;
336ef353b02SRyosuke Niwa 
337ef353b02SRyosuke Niwa   void foo() {
338ef353b02SRyosuke Niwa     Foo f;
339ef353b02SRyosuke Niwa     f + global;
340ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}}
341ef353b02SRyosuke Niwa     f - global;
342ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}}
343ef353b02SRyosuke Niwa     f(global);
344ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}}
345ef353b02SRyosuke Niwa   }
346ef353b02SRyosuke Niwa }
347ef353b02SRyosuke Niwa 
348ef353b02SRyosuke Niwa namespace call_with_ptr_on_ref {
349ef353b02SRyosuke Niwa   CheckedRef<CheckedObj> provideProtected();
350ef353b02SRyosuke Niwa   void bar(CheckedObj* bad);
351ef353b02SRyosuke Niwa   bool baz();
352ef353b02SRyosuke Niwa   void foo(bool v) {
353ef353b02SRyosuke Niwa     bar(v ? nullptr : provideProtected().ptr());
354ef353b02SRyosuke Niwa     bar(baz() ? provideProtected().ptr() : nullptr);
355ef353b02SRyosuke Niwa     bar(v ? provide() : provideProtected().ptr());
356ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}}
357ef353b02SRyosuke Niwa     bar(v ? provideProtected().ptr() : provide());
358ef353b02SRyosuke Niwa     // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}}
359ef353b02SRyosuke Niwa   }
360ef353b02SRyosuke Niwa }
361ef353b02SRyosuke Niwa 
362ef353b02SRyosuke Niwa namespace call_with_explicit_temporary_obj {
363ef353b02SRyosuke Niwa   void foo() {
364ef353b02SRyosuke Niwa     CheckedRef { *provide() }->method();
365ef353b02SRyosuke Niwa     CheckedPtr { provide() }->method();
366ef353b02SRyosuke Niwa   }
367ef353b02SRyosuke Niwa }
36873b577ccSRyosuke Niwa 
36973b577ccSRyosuke Niwa namespace call_with_checked_ptr {
37073b577ccSRyosuke Niwa 
37173b577ccSRyosuke Niwa   class Foo : public CheckedObj {
37273b577ccSRyosuke Niwa   public:
37373b577ccSRyosuke Niwa     CheckedPtr<CheckedObj> obj1() { return m_obj; }
37473b577ccSRyosuke Niwa     CheckedRef<CheckedObj> obj2() { return *m_obj; }
37573b577ccSRyosuke Niwa   private:
37673b577ccSRyosuke Niwa     CheckedObj* m_obj;
37773b577ccSRyosuke Niwa   };
37873b577ccSRyosuke Niwa 
37973b577ccSRyosuke Niwa   Foo* getFoo();
38073b577ccSRyosuke Niwa 
38173b577ccSRyosuke Niwa   void bar() {
38273b577ccSRyosuke Niwa     getFoo()->obj1()->method();
38373b577ccSRyosuke Niwa     getFoo()->obj2()->method();
38473b577ccSRyosuke Niwa   }
38573b577ccSRyosuke Niwa 
38673b577ccSRyosuke Niwa }
387