1*635a8641SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_EXPORT_TEMPLATE_H_ 6*635a8641SAndroid Build Coastguard Worker #define BASE_EXPORT_TEMPLATE_H_ 7*635a8641SAndroid Build Coastguard Worker 8*635a8641SAndroid Build Coastguard Worker // Synopsis 9*635a8641SAndroid Build Coastguard Worker // 10*635a8641SAndroid Build Coastguard Worker // This header provides macros for using FOO_EXPORT macros with explicit 11*635a8641SAndroid Build Coastguard Worker // template instantiation declarations and definitions. 12*635a8641SAndroid Build Coastguard Worker // Generally, the FOO_EXPORT macros are used at declarations, 13*635a8641SAndroid Build Coastguard Worker // and GCC requires them to be used at explicit instantiation declarations, 14*635a8641SAndroid Build Coastguard Worker // but MSVC requires __declspec(dllexport) to be used at the explicit 15*635a8641SAndroid Build Coastguard Worker // instantiation definitions instead. 16*635a8641SAndroid Build Coastguard Worker 17*635a8641SAndroid Build Coastguard Worker // Usage 18*635a8641SAndroid Build Coastguard Worker // 19*635a8641SAndroid Build Coastguard Worker // In a header file, write: 20*635a8641SAndroid Build Coastguard Worker // 21*635a8641SAndroid Build Coastguard Worker // extern template class EXPORT_TEMPLATE_DECLARE(FOO_EXPORT) foo<bar>; 22*635a8641SAndroid Build Coastguard Worker // 23*635a8641SAndroid Build Coastguard Worker // In a source file, write: 24*635a8641SAndroid Build Coastguard Worker // 25*635a8641SAndroid Build Coastguard Worker // template class EXPORT_TEMPLATE_DEFINE(FOO_EXPORT) foo<bar>; 26*635a8641SAndroid Build Coastguard Worker 27*635a8641SAndroid Build Coastguard Worker // Implementation notes 28*635a8641SAndroid Build Coastguard Worker // 29*635a8641SAndroid Build Coastguard Worker // The implementation of this header uses some subtle macro semantics to 30*635a8641SAndroid Build Coastguard Worker // detect what the provided FOO_EXPORT value was defined as and then 31*635a8641SAndroid Build Coastguard Worker // to dispatch to appropriate macro definitions. Unfortunately, 32*635a8641SAndroid Build Coastguard Worker // MSVC's C preprocessor is rather non-compliant and requires special 33*635a8641SAndroid Build Coastguard Worker // care to make it work. 34*635a8641SAndroid Build Coastguard Worker // 35*635a8641SAndroid Build Coastguard Worker // Issue 1. 36*635a8641SAndroid Build Coastguard Worker // 37*635a8641SAndroid Build Coastguard Worker // #define F(x) 38*635a8641SAndroid Build Coastguard Worker // F() 39*635a8641SAndroid Build Coastguard Worker // 40*635a8641SAndroid Build Coastguard Worker // MSVC emits warning C4003 ("not enough actual parameters for macro 41*635a8641SAndroid Build Coastguard Worker // 'F'), even though it's a valid macro invocation. This affects the 42*635a8641SAndroid Build Coastguard Worker // macros below that take just an "export" parameter, because export 43*635a8641SAndroid Build Coastguard Worker // may be empty. 44*635a8641SAndroid Build Coastguard Worker // 45*635a8641SAndroid Build Coastguard Worker // As a workaround, we can add a dummy parameter and arguments: 46*635a8641SAndroid Build Coastguard Worker // 47*635a8641SAndroid Build Coastguard Worker // #define F(x,_) 48*635a8641SAndroid Build Coastguard Worker // F(,) 49*635a8641SAndroid Build Coastguard Worker // 50*635a8641SAndroid Build Coastguard Worker // Issue 2. 51*635a8641SAndroid Build Coastguard Worker // 52*635a8641SAndroid Build Coastguard Worker // #define F(x) G##x 53*635a8641SAndroid Build Coastguard Worker // #define Gj() ok 54*635a8641SAndroid Build Coastguard Worker // F(j()) 55*635a8641SAndroid Build Coastguard Worker // 56*635a8641SAndroid Build Coastguard Worker // The correct replacement for "F(j())" is "ok", but MSVC replaces it 57*635a8641SAndroid Build Coastguard Worker // with "Gj()". As a workaround, we can pass the result to an 58*635a8641SAndroid Build Coastguard Worker // identity macro to force MSVC to look for replacements again. (This 59*635a8641SAndroid Build Coastguard Worker // is why EXPORT_TEMPLATE_STYLE_3 exists.) 60*635a8641SAndroid Build Coastguard Worker 61*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DECLARE(export) \ 62*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_INVOKE(DECLARE, EXPORT_TEMPLATE_STYLE(export, ), export) 63*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DEFINE(export) \ 64*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_INVOKE(DEFINE, EXPORT_TEMPLATE_STYLE(export, ), export) 65*635a8641SAndroid Build Coastguard Worker 66*635a8641SAndroid Build Coastguard Worker // INVOKE is an internal helper macro to perform parameter replacements 67*635a8641SAndroid Build Coastguard Worker // and token pasting to chain invoke another macro. E.g., 68*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_INVOKE(DECLARE, DEFAULT, FOO_EXPORT) 69*635a8641SAndroid Build Coastguard Worker // will export to call 70*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_DECLARE_DEFAULT(FOO_EXPORT, ) 71*635a8641SAndroid Build Coastguard Worker // (but with FOO_EXPORT expanded too). 72*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_INVOKE(which, style, export) \ 73*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_INVOKE_2(which, style, export) 74*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_INVOKE_2(which, style, export) \ 75*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_##which##_##style(export, ) 76*635a8641SAndroid Build Coastguard Worker 77*635a8641SAndroid Build Coastguard Worker // Default style is to apply the FOO_EXPORT macro at declaration sites. 78*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DECLARE_DEFAULT(export, _) export 79*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DEFINE_DEFAULT(export, _) 80*635a8641SAndroid Build Coastguard Worker 81*635a8641SAndroid Build Coastguard Worker // The "MSVC hack" style is used when FOO_EXPORT is defined 82*635a8641SAndroid Build Coastguard Worker // as __declspec(dllexport), which MSVC requires to be used at 83*635a8641SAndroid Build Coastguard Worker // definition sites instead. 84*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DECLARE_MSVC_HACK(export, _) 85*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DEFINE_MSVC_HACK(export, _) export 86*635a8641SAndroid Build Coastguard Worker 87*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_STYLE is an internal helper macro that identifies which 88*635a8641SAndroid Build Coastguard Worker // export style needs to be used for the provided FOO_EXPORT macro definition. 89*635a8641SAndroid Build Coastguard Worker // "", "__attribute__(...)", and "__declspec(dllimport)" are mapped 90*635a8641SAndroid Build Coastguard Worker // to "DEFAULT"; while "__declspec(dllexport)" is mapped to "MSVC_HACK". 91*635a8641SAndroid Build Coastguard Worker // 92*635a8641SAndroid Build Coastguard Worker // It's implemented with token pasting to transform the __attribute__ and 93*635a8641SAndroid Build Coastguard Worker // __declspec annotations into macro invocations. E.g., if FOO_EXPORT is 94*635a8641SAndroid Build Coastguard Worker // defined as "__declspec(dllimport)", it undergoes the following sequence of 95*635a8641SAndroid Build Coastguard Worker // macro substitutions: 96*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_STYLE(FOO_EXPORT, ) 97*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_STYLE_2(__declspec(dllimport), ) 98*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_STYLE_3(EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport)) 99*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport) 100*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport 101*635a8641SAndroid Build Coastguard Worker // DEFAULT 102*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE(export, _) EXPORT_TEMPLATE_STYLE_2(export, ) 103*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_2(export, _) \ 104*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_STYLE_3( \ 105*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA##export) 106*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_3(style) style 107*635a8641SAndroid Build Coastguard Worker 108*635a8641SAndroid Build Coastguard Worker // Internal helper macros for EXPORT_TEMPLATE_STYLE. 109*635a8641SAndroid Build Coastguard Worker // 110*635a8641SAndroid Build Coastguard Worker // XXX: C++ reserves all identifiers containing "__" for the implementation, 111*635a8641SAndroid Build Coastguard Worker // but "__attribute__" and "__declspec" already contain "__" and the token-paste 112*635a8641SAndroid Build Coastguard Worker // operator can only add characters; not remove them. To minimize the risk of 113*635a8641SAndroid Build Coastguard Worker // conflict with implementations, we include "foj3FJo5StF0OvIzl7oMxA" (a random 114*635a8641SAndroid Build Coastguard Worker // 128-bit string, encoded in Base64) in the macro name. 115*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA DEFAULT 116*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__attribute__(...) \ 117*635a8641SAndroid Build Coastguard Worker DEFAULT 118*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__declspec(arg) \ 119*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_##arg 120*635a8641SAndroid Build Coastguard Worker 121*635a8641SAndroid Build Coastguard Worker // Internal helper macros for EXPORT_TEMPLATE_STYLE. 122*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport MSVC_HACK 123*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport DEFAULT 124*635a8641SAndroid Build Coastguard Worker 125*635a8641SAndroid Build Coastguard Worker // Sanity checks. 126*635a8641SAndroid Build Coastguard Worker // 127*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_TEST uses the same macro invocation pattern as 128*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_DECLARE and EXPORT_TEMPLATE_DEFINE do to check that they're 129*635a8641SAndroid Build Coastguard Worker // working correctly. When they're working correctly, the sequence of macro 130*635a8641SAndroid Build Coastguard Worker // replacements should go something like: 131*635a8641SAndroid Build Coastguard Worker // 132*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport)); 133*635a8641SAndroid Build Coastguard Worker // 134*635a8641SAndroid Build Coastguard Worker // static_assert(EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT, 135*635a8641SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_STYLE(__declspec(dllimport), ), 136*635a8641SAndroid Build Coastguard Worker // __declspec(dllimport)), "__declspec(dllimport)"); 137*635a8641SAndroid Build Coastguard Worker // 138*635a8641SAndroid Build Coastguard Worker // static_assert(EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT, 139*635a8641SAndroid Build Coastguard Worker // DEFAULT, __declspec(dllimport)), "__declspec(dllimport)"); 140*635a8641SAndroid Build Coastguard Worker // 141*635a8641SAndroid Build Coastguard Worker // static_assert(EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT( 142*635a8641SAndroid Build Coastguard Worker // __declspec(dllimport)), "__declspec(dllimport)"); 143*635a8641SAndroid Build Coastguard Worker // 144*635a8641SAndroid Build Coastguard Worker // static_assert(true, "__declspec(dllimport)"); 145*635a8641SAndroid Build Coastguard Worker // 146*635a8641SAndroid Build Coastguard Worker // When they're not working correctly, a syntax error should occur instead. 147*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_TEST(want, export) \ 148*635a8641SAndroid Build Coastguard Worker static_assert(EXPORT_TEMPLATE_INVOKE( \ 149*635a8641SAndroid Build Coastguard Worker TEST_##want, EXPORT_TEMPLATE_STYLE(export, ), export), \ 150*635a8641SAndroid Build Coastguard Worker #export) 151*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(...) true 152*635a8641SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK(...) true 153*635a8641SAndroid Build Coastguard Worker 154*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_TEST(DEFAULT, ); 155*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_TEST(DEFAULT, __attribute__((visibility("default")))); 156*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_TEST(MSVC_HACK, __declspec(dllexport)); 157*635a8641SAndroid Build Coastguard Worker EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport)); 158*635a8641SAndroid Build Coastguard Worker 159*635a8641SAndroid Build Coastguard Worker #undef EXPORT_TEMPLATE_TEST 160*635a8641SAndroid Build Coastguard Worker #undef EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT 161*635a8641SAndroid Build Coastguard Worker #undef EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK 162*635a8641SAndroid Build Coastguard Worker 163*635a8641SAndroid Build Coastguard Worker #endif // BASE_EXPORT_TEMPLATE_H_ 164