[ 
https://issues.apache.org/jira/browse/MESOS-3141?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

haosdent updated MESOS-3141:
----------------------------
    Description: 
The purpose of this ticket is to document a very cryptic error message 
(actually a warning that gets propagated by {{-Werror}}) that gets generated by 
{{clang-3.5}} from {{gmock}} source code when trying to mock a perfectly 
innocent-looking function.

h3. Problem

The following code is attempting to mock a {{MesosExecutorDriver}}:

{code}
class MockMesosExecutorDriver : public MesosExecutorDriver {
public:
  MockMesosExecutorDriver(mesos::Executor* executor)
    : MesosExecutorDriver(executor) {}

  MOCK_METHOD1(sendStatusUpdate, Status(const TaskStatus&));
};
{code}

The above code generates the following error message:

{noformat}
In file included from 
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock.h:58:
In file included from 
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:46:
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h:355:10:
 error: indirection of non-volatile null pointer will be deleted, not trap 
[-Werror,-Wnull-dereference]
  return *static_cast<typename remove_reference<T>::type*>(__null);
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:78:22:
 note: in instantiation of function template specialization 
'testing::internal::Invalid<mesos::Status>' requested here
    return internal::Invalid<T>();
                     ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:190:43:
 note: in instantiation of member function 
'testing::internal::BuiltInDefaultValue<mesos::Status>::Get' requested here
        internal::BuiltInDefaultValue<T>::Get() : *value_;
                                          ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1435:34:
 note: in instantiation of member function 
'testing::DefaultValue<mesos::Status>::Get' requested here
    return DefaultValue<Result>::Get();
                                 ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1334:22:
 note: in instantiation of member function 
'testing::internal::FunctionMockerBase<mesos::Status (const mesos::TaskStatus 
&)>::PerformDefaultAction' requested here
        func_mocker->PerformDefaultAction(args, call_description));
                     ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1448:26:
 note: in instantiation of function template specialization 
'testing::internal::ActionResultHolder<mesos::Status>::PerformDefaultAction<mesos::Status
 (const mesos::TaskStatus &)>' requested here
    return ResultHolder::PerformDefaultAction(this, args, call_description);
                         ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-generated-function-mockers.h:81:7:
 note: in instantiation of member function 
'testing::internal::FunctionMockerBase<mesos::Status (const mesos::TaskStatus 
&)>::UntypedPerformDefaultAction' requested here
class FunctionMocker<R(A1)> : public
      ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h:355:10:
 note: consider using __builtin_trap() or qualifying pointer with 'volatile'
  return *static_cast<typename remove_reference<T>::type*>(__null);
         ^
{noformat}

The source of the issue here is that {{Status}} is an {{enum}}. In 
{{gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h}} you can find the 
following function:

{code}
template <typename T>
T Invalid() {
  return *static_cast<typename remove_reference<T>::type*>(NULL);
}
{code}

This function gets called with the return type of a mocked function. In our 
case,  the return type of the mocked function is {{Status}}.

Attempting to compile the following minimal example with {{clang-3.5}} 
reproduces the error message:

{code}
#include <type_traits>

template <typename T>
T invalid() {
  return *static_cast<typename std::remove_reference<T>::type *>(nullptr);
}

enum E { A, B };

int main() {
  invalid<E>();
}
{code}

* See it online on [GCC Explorer|https://goo.gl/t1FepZ]

Note that if the type is not an {{enum}}, the warning is not generated. This is 
why existing mocked functions that return non-{{enum}} types such as 
{{Future<void>}} does not encounter this issue.

h3. Solutions

The simplest solution is to add {{-Wno-null-deference}} to 
{{mesos_tests_CPPFLAGS}} in {{src/Makefile.am}}.

{code}
mesos_tests_CPPFLAGS = $(MESOS_CPPFLAGS) -Wno-null-dereference
{code}

Another solution is to upgrade {{gmock}} from *1.6* to *1.7* because this 
problem is solved in the newer versions.

In gmock 1.7
{code}
template <typename T>
inline T Invalid() {
  return const_cast<typename remove_reference<T>::type&>(
      *static_cast<volatile typename remove_reference<T>::type*>(NULL));
}
{code}

Add volatile could avoid this warning. https://goo.gl/opCiLC



  was:
The purpose of this ticket is to document a very cryptic error message 
(actually a warning that gets propagated by {{-Werror}}) that gets generated by 
{{clang-3.5}} from {{gmock}} source code when trying to mock a perfectly 
innocent-looking function.

h3. Problem

The following code is attempting to mock a {{MesosExecutorDriver}}:

{code}
class MockMesosExecutorDriver : public MesosExecutorDriver {
public:
  MockMesosExecutorDriver(mesos::Executor* executor)
    : MesosExecutorDriver(executor) {}

  MOCK_METHOD1(sendStatusUpdate, Status(const TaskStatus&));
};
{code}

The above code generates the following error message:

{noformat}
In file included from 
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock.h:58:
In file included from 
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:46:
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h:355:10:
 error: indirection of non-volatile null pointer will be deleted, not trap 
[-Werror,-Wnull-dereference]
  return *static_cast<typename remove_reference<T>::type*>(__null);
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:78:22:
 note: in instantiation of function template specialization 
'testing::internal::Invalid<mesos::Status>' requested here
    return internal::Invalid<T>();
                     ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:190:43:
 note: in instantiation of member function 
'testing::internal::BuiltInDefaultValue<mesos::Status>::Get' requested here
        internal::BuiltInDefaultValue<T>::Get() : *value_;
                                          ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1435:34:
 note: in instantiation of member function 
'testing::DefaultValue<mesos::Status>::Get' requested here
    return DefaultValue<Result>::Get();
                                 ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1334:22:
 note: in instantiation of member function 
'testing::internal::FunctionMockerBase<mesos::Status (const mesos::TaskStatus 
&)>::PerformDefaultAction' requested here
        func_mocker->PerformDefaultAction(args, call_description));
                     ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1448:26:
 note: in instantiation of function template specialization 
'testing::internal::ActionResultHolder<mesos::Status>::PerformDefaultAction<mesos::Status
 (const mesos::TaskStatus &)>' requested here
    return ResultHolder::PerformDefaultAction(this, args, call_description);
                         ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-generated-function-mockers.h:81:7:
 note: in instantiation of member function 
'testing::internal::FunctionMockerBase<mesos::Status (const mesos::TaskStatus 
&)>::UntypedPerformDefaultAction' requested here
class FunctionMocker<R(A1)> : public
      ^
../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h:355:10:
 note: consider using __builtin_trap() or qualifying pointer with 'volatile'
  return *static_cast<typename remove_reference<T>::type*>(__null);
         ^
{noformat}

The source of the issue here is that {{Status}} is an {{enum}}. In 
{{gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h}} you can find the 
following function:

{code}
template <typename T>
T Invalid() {
  return *static_cast<typename remove_reference<T>::type*>(NULL);
}
{code}

This function gets called with the return type of a mocked function. In our 
case,  the return type of the mocked function is {{Status}}.

Attempting to compile the following minimal example with {{clang-3.5}} 
reproduces the error message:

{code}
#include <type_traits>

template <typename T>
T invalid() {
  return *static_cast<typename std::remove_reference<T>::type *>(nullptr);
}

enum E { A, B };

int main() {
  invalid<E>();
}
{code}

* See it online on [GCC Explorer|https://goo.gl/t1FepZ]

Note that if the type is not an {{enum}}, the warning is not generated. This is 
why existing mocked functions that return non-{{enum}} types such as 
{{Future<void>}} does not encounter this issue.

h3. Solutions

The simplest solution is to add {{-Wno-null-deference}} to 
{{mesos_tests_CPPFLAGS}} in {{src/Makefile.am}}.

{code}
mesos_tests_CPPFLAGS = $(MESOS_CPPFLAGS) -Wno-null-dereference
{code}

Another solution is to upgrade {{gmock}} from *1.6* to *1.7* to as I believe 
this problem is solved in the newer versions.




> Compiler warning when mocking function type has an enum return type.
> --------------------------------------------------------------------
>
>                 Key: MESOS-3141
>                 URL: https://issues.apache.org/jira/browse/MESOS-3141
>             Project: Mesos
>          Issue Type: Bug
>    Affects Versions: 0.23.0
>            Reporter: Michael Park
>            Assignee: haosdent
>              Labels: mesosphere
>             Fix For: 0.24.0
>
>
> The purpose of this ticket is to document a very cryptic error message 
> (actually a warning that gets propagated by {{-Werror}}) that gets generated 
> by {{clang-3.5}} from {{gmock}} source code when trying to mock a perfectly 
> innocent-looking function.
> h3. Problem
> The following code is attempting to mock a {{MesosExecutorDriver}}:
> {code}
> class MockMesosExecutorDriver : public MesosExecutorDriver {
> public:
>   MockMesosExecutorDriver(mesos::Executor* executor)
>     : MesosExecutorDriver(executor) {}
>   MOCK_METHOD1(sendStatusUpdate, Status(const TaskStatus&));
> };
> {code}
> The above code generates the following error message:
> {noformat}
> In file included from 
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock.h:58:
> In file included from 
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:46:
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h:355:10:
>  error: indirection of non-volatile null pointer will be deleted, not trap 
> [-Werror,-Wnull-dereference]
>   return *static_cast<typename remove_reference<T>::type*>(__null);
>          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:78:22:
>  note: in instantiation of function template specialization 
> 'testing::internal::Invalid<mesos::Status>' requested here
>     return internal::Invalid<T>();
>                      ^
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:190:43:
>  note: in instantiation of member function 
> 'testing::internal::BuiltInDefaultValue<mesos::Status>::Get' requested here
>         internal::BuiltInDefaultValue<T>::Get() : *value_;
>                                           ^
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1435:34:
>  note: in instantiation of member function 
> 'testing::DefaultValue<mesos::Status>::Get' requested here
>     return DefaultValue<Result>::Get();
>                                  ^
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1334:22:
>  note: in instantiation of member function 
> 'testing::internal::FunctionMockerBase<mesos::Status (const mesos::TaskStatus 
> &)>::PerformDefaultAction' requested here
>         func_mocker->PerformDefaultAction(args, call_description));
>                      ^
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1448:26:
>  note: in instantiation of function template specialization 
> 'testing::internal::ActionResultHolder<mesos::Status>::PerformDefaultAction<mesos::Status
>  (const mesos::TaskStatus &)>' requested here
>     return ResultHolder::PerformDefaultAction(this, args, call_description);
>                          ^
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-generated-function-mockers.h:81:7:
>  note: in instantiation of member function 
> 'testing::internal::FunctionMockerBase<mesos::Status (const mesos::TaskStatus 
> &)>::UntypedPerformDefaultAction' requested here
> class FunctionMocker<R(A1)> : public
>       ^
> ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h:355:10:
>  note: consider using __builtin_trap() or qualifying pointer with 'volatile'
>   return *static_cast<typename remove_reference<T>::type*>(__null);
>          ^
> {noformat}
> The source of the issue here is that {{Status}} is an {{enum}}. In 
> {{gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h}} you can find 
> the following function:
> {code}
> template <typename T>
> T Invalid() {
>   return *static_cast<typename remove_reference<T>::type*>(NULL);
> }
> {code}
> This function gets called with the return type of a mocked function. In our 
> case,  the return type of the mocked function is {{Status}}.
> Attempting to compile the following minimal example with {{clang-3.5}} 
> reproduces the error message:
> {code}
> #include <type_traits>
> template <typename T>
> T invalid() {
>   return *static_cast<typename std::remove_reference<T>::type *>(nullptr);
> }
> enum E { A, B };
> int main() {
>   invalid<E>();
> }
> {code}
> * See it online on [GCC Explorer|https://goo.gl/t1FepZ]
> Note that if the type is not an {{enum}}, the warning is not generated. This 
> is why existing mocked functions that return non-{{enum}} types such as 
> {{Future<void>}} does not encounter this issue.
> h3. Solutions
> The simplest solution is to add {{-Wno-null-deference}} to 
> {{mesos_tests_CPPFLAGS}} in {{src/Makefile.am}}.
> {code}
> mesos_tests_CPPFLAGS = $(MESOS_CPPFLAGS) -Wno-null-dereference
> {code}
> Another solution is to upgrade {{gmock}} from *1.6* to *1.7* because this 
> problem is solved in the newer versions.
> In gmock 1.7
> {code}
> template <typename T>
> inline T Invalid() {
>   return const_cast<typename remove_reference<T>::type&>(
>       *static_cast<volatile typename remove_reference<T>::type*>(NULL));
> }
> {code}
> Add volatile could avoid this warning. https://goo.gl/opCiLC



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to