gmock windows compilation issues for functions with parameters that include __declspec align'd members

266 views
Skip to first unread message

Bryan McQuade

unread,
Jun 26, 2016, 10:01:22 AM6/26/16
to Google C++ Testing Framework
I'm working on a patch to add an additional data member to a struct:

The patch adds a member of type base::Optional<> to the struct PageLoadTiming.

This works just fine in most Chromium code, but it appears to trip up compilation of some code that uses gmock to mock functions that take a PageLoadTiming struct in Windows builds.

PageLoadTiming is used as an argument in a few methods that are mocked using gmock, such as:

class MockIPCSender : public IPC::Sender {
 public:
  MOCK_METHOD2(OnTimingUpdated, void(PageLoadTiming, PageLoadMetadata));
};

As a result of adding the base::Optional member to PageLoadTiming, the gmock code no longer compiles in Chromium Windows builds, reporting error C2719.

Microsoft's documentation for error C2719: https://msdn.microsoft.com/en-us/library/373ak2y1.aspx says "The align __declspec modifier is not permitted on function parameters. Function parameter alignment is controlled by the calling convention used. For more information, see Calling Conventions." None of the function's parameters use __declspec; it's the new member of the PageLoadTiming parameter that uses __declspec align.

base::Optional (https://cs.chromium.org/chromium/src/base/optional.h) includes an OptionalStorage member, which itself includes both a bool and a base::AlignedMemory member. base::AlignedMemory contains a uint8_t array which is annotated as __declspec align via the ALIGNAS macro: https://cs.chromium.org/chromium/src/base/memory/aligned_memory.h?l=60

Other non-gmock Chromium code that takes a PageLoadTiming as a parameter compiles just fine, so there's something about the way gmock is mocking these functions that triggers this compiler error. Is this something you've encountered before? Is there something we can do to update gmock so it no longer generates errors in cases like this? Is there something I can do in my code to update it so it no longer triggers these errors?


Windows compiler output:

e:\b\build\slave\win\build\src\components\page_load_metrics\renderer\page_timing_metrics_sender_unittest.cc(31): error C2719: 'unnamed-parameter': formal parameter with requested alignment of 8 won't be aligned
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\internal\gmock-generated-internal-utils.h(177): error C2719: 'unnamed-parameter': formal parameter with requested alignment of 8 won't be aligned
e:\b\build\slave\win\build\src\components\page_load_metrics\renderer\page_timing_metrics_sender_unittest.cc(31): note: see reference to class template instantiation 'testing::internal::Function<void (page_load_metrics::PageLoadTiming,page_load_metrics::PageLoadMetadata)>' being compiled
...
e:\b\build\slave\win\build\src\components\page_load_metrics\renderer\page_timing_metrics_sender_unittest.cc(31): error C2719: 'gmock_a1': formal parameter with requested alignment of 8 won't be aligned
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-generated-function-mockers.h(107): error C2719: 'unnamed-parameter': formal parameter with requested alignment of 8 won't be aligned
e:\b\build\slave\win\build\src\components\page_load_metrics\renderer\page_timing_metrics_sender_unittest.cc(31): note: see reference to class template instantiation 'testing::internal::FunctionMocker<void (page_load_metrics::PageLoadTiming,page_load_metrics::PageLoadMetadata)>' being compiled

Full compiler output here:

Thanks,
Bryan

Bryan McQuade

unread,
Jun 26, 2016, 10:28:37 PM6/26/16
to Google C++ Testing Framework
I was able to work around this in my code.

When using googlemock with a PageLoadTiming instance, I had to avoid using gmock functionality where a function takes arguments by value, since passing a PageLoadTiming (or any class/struct that includes a member that's __declspec align'd) by value triggers the MS compiler warning.

This meant using Eq(ByRef(PageLoadTiming)) instead of a default by-value equality matcher, as well as avoiding use of Return(PageLoadTiming) since gmock's implementation of Return() takes an argument by value.

If there's an easier/better way, please let me know.

Thanks,
Bryan

Bryan McQuade

unread,
Jun 27, 2016, 7:38:14 AM6/27/16
to Google C++ Testing Framework
I spoke too soon. I was able to address the C2719 errors using the approaches described above, but am now getting C2718 errors for similar reasons.

Is it possible to use structs that include members that are __declspec align'd with gmock?

Compiler output below:

FAILED: obj/components/page_load_metrics/renderer/unit_tests/page_timing_metrics_sender_unittest.obj 
ninja -t msvc -e environment.x86 -- E:\b\build\slave\cache\cipd\goma/gomacc.exe "E:\b\depot_tools\win_toolchain\vs_files\95ddda401ec5678f15eeed01d2bee08fcbc5ee97\VC\bin\amd64_x86/cl.exe" /nologo /showIncludes /FC @obj/components/page_load_metrics/renderer/unit_tests/page_timing_metrics_sender_unittest.obj.rsp /c ../../components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc /Foobj/components/page_load_metrics/renderer/unit_tests/page_timing_metrics_sender_unittest.obj /Fd"obj/components/page_load_metrics/renderer/unit_tests_cc.pdb"
e:\b\build\slave\win\build\src\testing\gtest\include\gtest\internal\gtest-internal.h(892): error C2718: 'const page_load_metrics::PageLoadTiming': actual parameter with requested alignment of 8 won't be aligned
e:\b\build\slave\win\build\src\testing\gtest\include\gtest\gtest-printers.h(207): note: see reference to class template instantiation 'testing::internal::ImplicitlyConvertible<const T &,testing::internal::BiggestInt>' being compiled
        with
        [
            T=T1
        ]
e:\b\build\slave\win\build\src\testing\gtest\include\gtest\gtest-printers.h(249): note: see reference to function template instantiation 'std::basic_ostream<char,std::char_traits<char>> &testing::internal2::operator <<<char,std::char_traits<char>,T>(std::basic_ostream<char,std::char_traits<char>> &,const T &)' being compiled
        with
        [
            T=T1
        ]
e:\b\build\slave\win\build\src\testing\gtest\include\gtest\gtest-printers.h(439): note: see reference to function template instantiation 'void testing_internal::DefaultPrintNonContainerTo<T>(const T &,std::ostream *)' being compiled
        with
        [
            T=T1
        ]
e:\b\build\slave\win\build\src\testing\gtest\include\gtest\gtest-printers.h(477): note: see reference to function template instantiation 'void testing::internal::DefaultPrintTo<T>(testing::internal::IsNotContainer,testing::internal::false_type,const T &,std::ostream *)' being compiled
        with
        [
            T=T1
        ]
e:\b\build\slave\win\build\src\testing\gtest\include\gtest\gtest-printers.h(707): note: see reference to function template instantiation 'void testing::internal::PrintTo<T>(const T &,std::ostream *)' being compiled
        with
        [
            T=T1
        ]
e:\b\build\slave\win\build\src\testing\gtest\include\gtest\gtest-printers.h(698): note: while compiling class template member function 'void testing::internal::UniversalPrinter<T1>::Print(const T &,std::ostream *)'
        with
        [
            T=T1
        ]
e:\b\build\slave\win\build\src\testing\gtest\include\gtest\gtest-printers.h(856): note: see reference to function template instantiation 'void testing::internal::UniversalPrinter<T1>::Print(const T &,std::ostream *)' being compiled
        with
        [
            T=T1
        ]
e:\b\build\slave\win\build\src\testing\gtest\include\gtest\gtest-printers.h(856): note: see reference to class template instantiation 'testing::internal::UniversalPrinter<T1>' being compiled
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-matchers.h(767): note: see reference to function template instantiation 'void testing::internal::UniversalPrint<page_load_metrics::PageLoadTiming>(const T &,std::ostream *)' being compiled
        with
        [
            T=page_load_metrics::PageLoadTiming
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-matchers.h(747): note: see reference to function template instantiation 'void testing::internal::TuplePrefix<1>::ExplainMatchFailuresTo<MatcherTuple,ValueTuple>(const MatcherTuple &,const ValueTuple &,std::ostream *)' being compiled
        with
        [
            MatcherTuple=std::tuple<testing::Matcher<const page_load_metrics::PageLoadTiming &>,testing::Matcher<page_load_metrics::PageLoadMetadata>>,
            ValueTuple=std::tuple<const page_load_metrics::PageLoadTiming &,page_load_metrics::PageLoadMetadata>
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-matchers.h(747): note: see reference to function template instantiation 'void testing::internal::TuplePrefix<1>::ExplainMatchFailuresTo<MatcherTuple,ValueTuple>(const MatcherTuple &,const ValueTuple &,std::ostream *)' being compiled
        with
        [
            MatcherTuple=std::tuple<testing::Matcher<const page_load_metrics::PageLoadTiming &>,testing::Matcher<page_load_metrics::PageLoadMetadata>>,
            ValueTuple=std::tuple<const page_load_metrics::PageLoadTiming &,page_load_metrics::PageLoadMetadata>
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-matchers.h(814): note: see reference to function template instantiation 'void testing::internal::TuplePrefix<2>::ExplainMatchFailuresTo<MatcherTuple,ValueTuple>(const MatcherTuple &,const ValueTuple &,std::ostream *)' being compiled
        with
        [
            MatcherTuple=std::tuple<testing::Matcher<const page_load_metrics::PageLoadTiming &>,testing::Matcher<page_load_metrics::PageLoadMetadata>>,
            ValueTuple=std::tuple<const page_load_metrics::PageLoadTiming &,page_load_metrics::PageLoadMetadata>
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-matchers.h(813): note: see reference to function template instantiation 'void testing::internal::TuplePrefix<2>::ExplainMatchFailuresTo<MatcherTuple,ValueTuple>(const MatcherTuple &,const ValueTuple &,std::ostream *)' being compiled
        with
        [
            MatcherTuple=std::tuple<testing::Matcher<const page_load_metrics::PageLoadTiming &>,testing::Matcher<page_load_metrics::PageLoadMetadata>>,
            ValueTuple=std::tuple<const page_load_metrics::PageLoadTiming &,page_load_metrics::PageLoadMetadata>
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-spec-builders.h(1117): note: see reference to function template instantiation 'void testing::internal::ExplainMatchFailureTupleTo<std::tuple<testing::Matcher<A1>,testing::Matcher<A2>>,std::tuple<A1,A2>>(const MatcherTuple &,const ValueTuple &,std::ostream *)' being compiled
        with
        [
            A1=const page_load_metrics::PageLoadTiming &,
            A2=page_load_metrics::PageLoadMetadata,
            MatcherTuple=std::tuple<testing::Matcher<const page_load_metrics::PageLoadTiming &>,testing::Matcher<page_load_metrics::PageLoadMetadata>>,
            ValueTuple=std::tuple<const page_load_metrics::PageLoadTiming &,page_load_metrics::PageLoadMetadata>
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-spec-builders.h(1109): note: while compiling class template member function 'void testing::internal::TypedExpectation<F>::ExplainMatchResultTo(const std::tuple<A1,A2> &,std::ostream *) const'
        with
        [
            F=void (const page_load_metrics::PageLoadTiming &,page_load_metrics::PageLoadMetadata),
            A1=const page_load_metrics::PageLoadTiming &,
            A2=page_load_metrics::PageLoadMetadata
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-spec-builders.h(1763): note: see reference to function template instantiation 'void testing::internal::TypedExpectation<F>::ExplainMatchResultTo(const std::tuple<A1,A2> &,std::ostream *) const' being compiled
        with
        [
            F=void (const page_load_metrics::PageLoadTiming &,page_load_metrics::PageLoadMetadata),
            A1=const page_load_metrics::PageLoadTiming &,
            A2=page_load_metrics::PageLoadMetadata
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-spec-builders.h(1696): note: see reference to class template instantiation 'testing::internal::TypedExpectation<F>' being compiled
        with
        [
            F=void (const page_load_metrics::PageLoadTiming &,page_load_metrics::PageLoadMetadata)
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-spec-builders.h(1683): note: while compiling class template member function 'const testing::internal::ExpectationBase *testing::internal::FunctionMockerBase<R (A1,A2)>::UntypedFindMatchingExpectation(const void *,const void **,bool *,std::ostream *,std::ostream *)'
        with
        [
            R=void,
            A1=const page_load_metrics::PageLoadTiming &,
            A2=page_load_metrics::PageLoadMetadata
        ]
e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-generated-function-mockers.h(107): note: see reference to class template instantiation 'testing::internal::FunctionMockerBase<R (A1,A2)>' being compiled
        with
        [
            R=void,
            A1=const page_load_metrics::PageLoadTiming &,
            A2=page_load_metrics::PageLoadMetadata
        ]
e:\b\build\slave\win\build\src\components\page_load_metrics\renderer\page_timing_metrics_sender_unittest.cc(34): note: see reference to class template instantiation 'testing::internal::FunctionMocker<void (const page_load_metrics::PageLoadTiming &,page_load_metrics::PageLoadMetadata)>' being compiled
Reply all
Reply to author
Forward
0 new messages