From 8ef4ae5655ff973b859999834b09b65e0bbe5eb1 Mon Sep 17 00:00:00 2001 From: Matthias Maier Date: Thu, 16 Jul 2015 13:12:12 -0500 Subject: [PATCH] Workaround: fix compilation with icc and linear_operator Disables the sfinae lookup in the has_vmult_add helper class for faulty icc. Intel's compiler up version 15.0.3 run into an sfinae bug otherwise. For affected compiler versions, has_vmult_add will always report "false" for icc which will result in a slight performance penalty due to unnecessary temporary storage. --- cmake/checks/check_03_compiler_bugs.cmake | 47 +++++++++++++++++++++++ include/deal.II/base/config.h.in | 1 + include/deal.II/lac/linear_operator.h | 5 +++ 3 files changed, 53 insertions(+) diff --git a/cmake/checks/check_03_compiler_bugs.cmake b/cmake/checks/check_03_compiler_bugs.cmake index e0445e7094..c741149b4f 100644 --- a/cmake/checks/check_03_compiler_bugs.cmake +++ b/cmake/checks/check_03_compiler_bugs.cmake @@ -375,3 +375,50 @@ IF( CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "Windows" ) SET(DEAL_II_CONSTEXPR_BUG TRUE) ENDIF() + + +# +# Intel (at least 14, 15) has a bug where it incorrectly detects multiple +# matching function candidates and dies during type resolution in a +# perfectly valid SFINAE scenario. This seems to happen because the templated +# variant is not discarded (where it should be): +# +# error: more than one instance of overloaded function +# "has_vmult_add::test [with Range=double, T=MyMatrix]" +# matches the argument list: +# function template "void has_vmult_add::test(decltype(())) [with Range=double, T=MyMatrix]" +# function template "void has_vmult_add::test(decltype((&C::vmult_add))) [with Range=double, T=MyMatrix]" +# [...] +# +# - Matthias Maier, 2015 +# + +IF(DEAL_II_WITH_CXX11) + PUSH_CMAKE_REQUIRED("${DEAL_II_CXX_VERSION_FLAG}") + CHECK_CXX_COMPILER_BUG( + " + template struct has_vmult_add + { + template + static void test(decltype(&C::vmult_add)); + + template + static void test(decltype(&C::template vmult_add)); + + typedef decltype(test(0)) type; + }; + + struct MyMatrix + { + void vmult_add() const; + }; + + int main() + { + typedef has_vmult_add::type test; + } + " + DEAL_II_ICC_SFINAE_BUG + ) + +ENDIF() diff --git a/include/deal.II/base/config.h.in b/include/deal.II/base/config.h.in index 532addee6e..dc538c7087 100644 --- a/include/deal.II/base/config.h.in +++ b/include/deal.II/base/config.h.in @@ -69,6 +69,7 @@ #cmakedefine DEAL_II_BOOST_BIND_COMPILER_BUG #cmakedefine DEAL_II_BIND_NO_CONST_OP_PARENTHESES #cmakedefine DEAL_II_CONSTEXPR_BUG +#cmakedefine DEAL_II_ICC_SFINAE_BUG /*********************************************************************** diff --git a/include/deal.II/lac/linear_operator.h b/include/deal.II/lac/linear_operator.h index 8585bbb37d..2086b94078 100644 --- a/include/deal.II/lac/linear_operator.h +++ b/include/deal.II/lac/linear_operator.h @@ -831,6 +831,10 @@ namespace static std::true_type test(decltype(&C::vmult_add), decltype(&C::Tvmult_add)); + // Work around a bug with icc (up to version 15) that fails during type + // deduction in an SFINAE scenario +#ifndef DEAL_II_ICC_SFINAE_BUG + template static std::true_type test(decltype(&C::template vmult_add), decltype(&C::template Tvmult_add)); @@ -838,6 +842,7 @@ namespace template static std::true_type test(decltype(&C::template vmult_add), decltype(&C::template Tvmult_add)); +#endif public: // type is std::true_type if Matrix provides vmult_add and Tvmult_add, -- 2.39.5