PageRenderTime 8ms CodeModel.GetById 1ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/core/externals/update-engine/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheck.h

http://macfuse.googlecode.com/
C++ Header | 88 lines | 26 code | 12 blank | 50 comment | 3 complexity | 56976052a9f8891f7b224195ca520791 MD5 | raw file
 1//
 2//  GTMMethodCheck.h
 3//  
 4//  Copyright 2006-2008 Google Inc.
 5//
 6//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
 7//  use this file except in compliance with the License.  You may obtain a copy
 8//  of the License at
 9// 
10//  http://www.apache.org/licenses/LICENSE-2.0
11// 
12//  Unless required by applicable law or agreed to in writing, software
13//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
15//  License for the specific language governing permissions and limitations under
16//  the License.
17//
18
19#import <Foundation/Foundation.h>
20#import <stdio.h>
21#import <sysexits.h>
22
23/// A macro for enforcing debug time checks to make sure all required methods are linked in
24// 
25// When using categories, it can be very easy to forget to include the
26// implementation of a category. 
27// Let's say you had a class foo that depended on method bar of class baz, and
28// method bar was implemented as a member of a category.
29// You could add the following code:
30// @implementation foo
31// GTM_METHOD_CHECK(baz, bar)
32// @end
33// and the code would check to make sure baz was implemented just before main
34// was called. This works for both dynamic libraries, and executables.
35//
36// Classes (or one of their superclasses) being checked must conform to the 
37// NSObject protocol. We will check this, and spit out a warning if a class does 
38// not conform to NSObject.
39//
40// This is not compiled into release builds.
41
42#ifdef DEBUG
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47  
48// If you get an error for GTMMethodCheckMethodChecker not being defined, 
49// you need to link in GTMMethodCheck.m. We keep it hidden so that we can have 
50// it living in several separate images without conflict.
51// Functions with the ((constructor)) attribute are called after all +loads
52// have been called. See "Initializing Objective-C Classes" in 
53// http://developer.apple.com/documentation/DeveloperTools/Conceptual/DynamicLibraries/Articles/DynamicLibraryDesignGuidelines.html#//apple_ref/doc/uid/TP40002013-DontLinkElementID_20
54  
55__attribute__ ((constructor, visibility("hidden"))) void GTMMethodCheckMethodChecker(void);
56  
57#ifdef __cplusplus
58};
59#endif
60
61// This is the "magic".
62// A) we need a multi layer define here so that the stupid preprocessor
63//    expands __LINE__ out the way we want it. We need LINE so that each of
64//    out GTM_METHOD_CHECKs generates a unique class method for the class.
65#define GTM_METHOD_CHECK(class, method) GTM_METHOD_CHECK_INNER(class, method, __LINE__)
66#define GTM_METHOD_CHECK_INNER(class, method, line) GTM_METHOD_CHECK_INNER_INNER(class, method, line)
67
68// B) Create up a class method called xxGMethodCheckMethod+class+line that the 
69//    GTMMethodCheckMethodChecker function can look for and call. We
70//    look for GTMMethodCheckMethodChecker to enforce linkage of
71//    GTMMethodCheck.m.
72#define GTM_METHOD_CHECK_INNER_INNER(class, method, line) \
73+ (void)xxGTMMethodCheckMethod ## class ## line { \
74  void (*addr)() = GTMMethodCheckMethodChecker; \
75  if (addr && ![class instancesRespondToSelector:@selector(method)] \
76      && ![class respondsToSelector:@selector(method)]) { \
77    fprintf(stderr, "%s:%d: error: We need method '%s' to be linked in for class '%s'\n", \
78            __FILE__, line, #method, #class); \
79    exit(EX_SOFTWARE); \
80  } \
81}
82
83#else // !DEBUG
84
85// Do nothing in release.
86#define GTM_METHOD_CHECK(class, method)
87
88#endif  // DEBUG