From 29de97cc5d25c4ae11de1212f9564823f9d7b72c Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Thu, 21 May 2020 12:45:34 -0700 Subject: [PATCH] Cherry-pick of df719723: Simplify template exporting macros (#7539) * Cherry-pick of df719723: Simplify template exporting macros * Fix macro usage --- src/google/protobuf/parse_context.h | 4 +- src/google/protobuf/port_def.inc | 178 ++------------------------ src/google/protobuf/port_undef.inc | 13 -- src/google/protobuf/repeated_field.cc | 24 ++-- src/google/protobuf/repeated_field.h | 23 ++-- 5 files changed, 32 insertions(+), 210 deletions(-) diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h index c83eed94cf..c0427bc5fc 100644 --- a/src/google/protobuf/parse_context.h +++ b/src/google/protobuf/parse_context.h @@ -744,7 +744,7 @@ PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedEnumParser( void* object, const char* ptr, ParseContext* ctx); template -PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) +PROTOBUF_EXPORT_TEMPLATE_DEFINE PROTOBUF_MUST_USE_RESULT const char* PackedEnumParser(void* object, const char* ptr, ParseContext* ctx, bool (*is_valid)(int), InternalMetadata* metadata, @@ -760,7 +760,7 @@ PROTOBUF_MUST_USE_RESULT const } template -PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) +PROTOBUF_EXPORT_TEMPLATE_DEFINE PROTOBUF_MUST_USE_RESULT const char* PackedEnumParserArg(void* object, const char* ptr, ParseContext* ctx, bool (*is_valid)(const void*, int), diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc index 31cb88e95c..3a18e466e2 100644 --- a/src/google/protobuf/port_def.inc +++ b/src/google/protobuf/port_def.inc @@ -358,20 +358,28 @@ #if defined(PROTOBUF_USE_DLLS) #if defined(_MSC_VER) #ifdef LIBPROTOBUF_EXPORTS - #define PROTOBUF_EXPORT __declspec(dllexport) + #define PROTOBUF_EXPORT __declspec(dllexport) + #define PROTOBUF_EXPORT_TEMPLATE_DECLARE + #define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllexport) #else - #define PROTOBUF_EXPORT __declspec(dllimport) + #define PROTOBUF_EXPORT __declspec(dllimport) + #define PROTOBUF_EXPORT_TEMPLATE_DECLARE + #define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllimport) #endif #ifdef LIBPROTOC_EXPORTS - #define PROTOC_EXPORT __declspec(dllexport) + #define PROTOC_EXPORT __declspec(dllexport) #else - #define PROTOC_EXPORT __declspec(dllimport) + #define PROTOC_EXPORT __declspec(dllimport) #endif #else // defined(_MSC_VER) #ifdef LIBPROTOBUF_EXPORTS #define PROTOBUF_EXPORT __attribute__((visibility("default"))) + #define PROTOBUF_EXPORT_TEMPLATE_DECLARE __attribute__((visibility("default"))) + #define PROTOBUF_EXPORT_TEMPLATE_DEFINE #else #define PROTOBUF_EXPORT + #define PROTOBUF_EXPORT_TEMPLATE_DECLARE + #define PROTOBUF_EXPORT_TEMPLATE_DEFINE #endif #ifdef LIBPROTOC_EXPORTS #define PROTOC_EXPORT __attribute__((visibility("default"))) @@ -382,168 +390,10 @@ #else // defined(PROTOBUF_USE_DLLS) #define PROTOBUF_EXPORT #define PROTOC_EXPORT + #define PROTOBUF_EXPORT_TEMPLATE_DECLARE + #define PROTOBUF_EXPORT_TEMPLATE_DEFINE #endif - -// This portion provides macros for using FOO_EXPORT macros with explicit -// template instantiation declarations and definitions. -// Generally, the FOO_EXPORT macros are used at declarations, -// and GCC requires them to be used at explicit instantiation declarations, -// but MSVC requires __declspec(dllexport) to be used at the explicit -// instantiation definitions instead. - -// Usage -// -// In a header file, write: -// -// extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(FOO_EXPORT) foo; -// -// In a source file, write: -// -// template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(FOO_EXPORT) foo; -// -// Where FOO_EXPORT is either PROTOBUF_EXPORT or PROTOC_EXPORT - -// Implementation notes -// -// The implementation of these macros uses some subtle macro semantics to -// detect what the provided FOO_EXPORT value was defined as and then -// to dispatch to appropriate macro definitions. Unfortunately, -// MSVC's C preprocessor is rather non-compliant and requires special -// care to make it work. -// -// Issue 1. -// -// #define F(x) -// F() -// -// MSVC emits warning C4003 ("not enough actual parameters for macro -// 'F'), even though it's a valid macro invocation. This affects the -// macros below that take just an "export" parameter, because export -// may be empty. -// -// As a workaround, we can add a dummy parameter and arguments: -// -// #define F(x,_) -// F(,) -// -// Issue 2. -// -// #define F(x) G##x -// #define Gj() ok -// F(j()) -// -// The correct replacement for "F(j())" is "ok", but MSVC replaces it -// with "Gj()". As a workaround, we can pass the result to an -// identity macro to force MSVC to look for replacements again. (This -// is why PROTOBUF_EXPORT_TEMPLATE_STYLE_3 exists.) - -#define PROTOBUF_EXPORT_TEMPLATE_DECLARE(export) \ - PROTOBUF_EXPORT_TEMPLATE_INVOKE( \ - DECLARE, PROTOBUF_EXPORT_TEMPLATE_STYLE(export, ), export) -#define PROTOBUF_EXPORT_TEMPLATE_DEFINE(export) \ - PROTOBUF_EXPORT_TEMPLATE_INVOKE( \ - DEFINE, PROTOBUF_EXPORT_TEMPLATE_STYLE(export, ), export) - -// INVOKE is an internal helper macro to perform parameter replacements -// and token pasting to chain invoke another macro. E.g., -// PROTOBUF_EXPORT_TEMPLATE_INVOKE(DECLARE, DEFAULT, FOO_EXPORT) -// will export to call -// PROTOBUF_EXPORT_TEMPLATE_DECLARE_DEFAULT(FOO_EXPORT, ) -// (but with FOO_EXPORT expanded too). -#define PROTOBUF_EXPORT_TEMPLATE_INVOKE(which, style, export) \ - PROTOBUF_EXPORT_TEMPLATE_INVOKE_2(which, style, export) -#define PROTOBUF_EXPORT_TEMPLATE_INVOKE_2(which, style, export) \ - PROTOBUF_EXPORT_TEMPLATE_##which##_##style(export, ) - -// Default style is to apply the FOO_EXPORT macro at declaration sites. -#define PROTOBUF_EXPORT_TEMPLATE_DECLARE_DEFAULT(export, _) export -#define PROTOBUF_EXPORT_TEMPLATE_DEFINE_DEFAULT(export, _) - -// The "MSVC hack" style is used when FOO_EXPORT is defined -// as __declspec(dllexport), which MSVC requires to be used at -// definition sites instead. -#define PROTOBUF_EXPORT_TEMPLATE_DECLARE_MSVC_HACK(export, _) -#define PROTOBUF_EXPORT_TEMPLATE_DEFINE_MSVC_HACK(export, _) export - -// PROTOBUF_EXPORT_TEMPLATE_STYLE is an internal helper macro that identifies -// which export style needs to be used for the provided FOO_EXPORT macro -// definition. "", "__attribute__(...)", and "__declspec(dllimport)" are -// mapped to "DEFAULT"; while "__declspec(dllexport)" is mapped to "MSVC_HACK". -// -// It's implemented with token pasting to transform the __attribute__ and -// __declspec annotations into macro invocations. E.g., if FOO_EXPORT is -// defined as "__declspec(dllimport)", it undergoes the following sequence of -// macro substitutions: -// PROTOBUF_EXPORT_TEMPLATE_STYLE(FOO_EXPORT, ) -// PROTOBUF_EXPORT_TEMPLATE_STYLE_2(__declspec(dllimport), ) -// PROTOBUF_EXPORT_TEMPLATE_STYLE_3( -// PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport)) -// PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport) -// PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport -// DEFAULT -#define PROTOBUF_EXPORT_TEMPLATE_STYLE(export, _) \ - PROTOBUF_EXPORT_TEMPLATE_STYLE_2(export, ) -#define PROTOBUF_EXPORT_TEMPLATE_STYLE_2(export, _) \ - PROTOBUF_EXPORT_TEMPLATE_STYLE_3( \ - PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA##export) -#define PROTOBUF_EXPORT_TEMPLATE_STYLE_3(style) style - -// Internal helper macros for PROTOBUF_EXPORT_TEMPLATE_STYLE. -// -// XXX: C++ reserves all identifiers containing "__" for the implementation, -// but "__attribute__" and "__declspec" already contain "__" and the token-paste -// operator can only add characters; not remove them. To minimize the risk of -// conflict with implementations, we include "foj3FJo5StF0OvIzl7oMxA" (a random -// 128-bit string, encoded in Base64) in the macro name. -#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA DEFAULT -#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__attribute__(...) \ - DEFAULT -#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__declspec(arg) \ - PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_##arg - -// Internal helper macros for PROTOBUF_EXPORT_TEMPLATE_STYLE. -#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport MSVC_HACK -#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport DEFAULT - -// Sanity checks. -// -// PROTOBUF_EXPORT_TEMPLATE_TEST uses the same macro invocation pattern as -// PROTOBUF_EXPORT_TEMPLATE_DECLARE and PROTOBUF_EXPORT_TEMPLATE_DEFINE do to -// check that they're working correctly. When they're working correctly, the -// sequence of macro replacements should go something like: -// -// PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport)); -// -// static_assert(PROTOBUF_EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT, -// PROTOBUF_EXPORT_TEMPLATE_STYLE(__declspec(dllimport), ), -// __declspec(dllimport)), "__declspec(dllimport)"); -// -// static_assert(PROTOBUF_EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT, -// DEFAULT, __declspec(dllimport)), "__declspec(dllimport)"); -// -// static_assert(PROTOBUF_EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT( -// __declspec(dllimport)), "__declspec(dllimport)"); -// -// static_assert(true, "__declspec(dllimport)"); -// -// When they're not working correctly, a syntax error should occur instead. -#define PROTOBUF_EXPORT_TEMPLATE_TEST(want, export) \ - static_assert(PROTOBUF_EXPORT_TEMPLATE_INVOKE( \ - TEST_##want, PROTOBUF_EXPORT_TEMPLATE_STYLE(export, ), \ - export), #export) -#define PROTOBUF_EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(...) true -#define PROTOBUF_EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK(...) true - -PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, ); -PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, __attribute__((visibility("default")))); -PROTOBUF_EXPORT_TEMPLATE_TEST(MSVC_HACK, __declspec(dllexport)); -PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport)); - -#undef PROTOBUF_EXPORT_TEMPLATE_TEST -#undef PROTOBUF_EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT -#undef PROTOBUF_EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK - // Windows declares several inconvenient macro names. We #undef them and then // restore them in port_undef.inc. #ifdef _MSC_VER diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc index 68339f62b0..b35e8568fc 100644 --- a/src/google/protobuf/port_undef.inc +++ b/src/google/protobuf/port_undef.inc @@ -69,19 +69,6 @@ #undef PROTOBUF_EXPORT_TEMPLATE_DECLARE #undef PROTOBUF_EXPORT_TEMPLATE_DEFINE #undef PROTOBUF_ALIGNAS -#undef PROTOBUF_EXPORT_TEMPLATE_INVOKE_2 -#undef PROTOBUF_EXPORT_TEMPLATE_DECLARE_DEFAULT -#undef PROTOBUF_EXPORT_TEMPLATE_DEFINE_DEFAULT -#undef PROTOBUF_EXPORT_TEMPLATE_DECLARE_MSVC_HACK -#undef PROTOBUF_EXPORT_TEMPLATE_DEFINE_MSVC_HACK -#undef PROTOBUF_EXPORT_TEMPLATE_STYLE -#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_2 -#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_3 -#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA -#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__attribute__ -#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__declspec -#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport -#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport #undef PROTOBUF_FINAL // Restore macro that may have been #undef'd in port_def.inc. diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc index 1b5a0b8d15..6450679122 100644 --- a/src/google/protobuf/repeated_field.cc +++ b/src/google/protobuf/repeated_field.cc @@ -123,22 +123,14 @@ MessageLite* RepeatedPtrFieldBase::AddWeak(const MessageLite* prototype) { } // namespace internal -template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) - RepeatedField; -template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) - RepeatedField; -template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) - RepeatedField; -template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) - RepeatedField; -template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) - RepeatedField; -template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) - RepeatedField; -template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) - RepeatedField; -template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT) - RepeatedPtrField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedPtrField; } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 9e2788286e..fd01a667ec 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -2816,21 +2816,14 @@ UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( } // Extern declarations of common instantiations to reduce library bloat. -extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT) - RepeatedField; -extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT) - RepeatedField; -extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT) - RepeatedField; -extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT) - RepeatedField; -extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT) - RepeatedField; -extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT) - RepeatedField; -extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT) - RepeatedField; -extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT) +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedPtrField; } // namespace protobuf