]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Workaround: fix compilation with icc and linear_operator
authorMatthias Maier <tamiko@43-1.org>
Thu, 16 Jul 2015 18:12:12 +0000 (13:12 -0500)
committerMatthias Maier <tamiko@43-1.org>
Fri, 17 Jul 2015 19:47:42 +0000 (14:47 -0500)
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
include/deal.II/base/config.h.in
include/deal.II/lac/linear_operator.h

index e0445e70944609e94015cdb801a3640bd6c063ee..c741149b4f9cbd51ff228207fde689be6fdb841c 100644 (file)
@@ -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<Range, T>::test [with Range=double, T=MyMatrix]"
+# matches the argument list:
+#     function template "void has_vmult_add<Range, T>::test<C>(decltype((<expression>))) [with Range=double, T=MyMatrix]"
+#     function template "void has_vmult_add<Range, T>::test<C>(decltype((&C::vmult_add<double>))) [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 <typename Range, typename T> struct has_vmult_add
+    {
+      template <typename C>
+      static void test(decltype(&C::vmult_add));
+
+      template <typename C>
+      static void test(decltype(&C::template vmult_add<Range>));
+
+      typedef decltype(test<T>(0)) type;
+    };
+
+    struct MyMatrix
+    {
+      void vmult_add() const;
+    };
+
+    int main()
+    {
+      typedef has_vmult_add<double, MyMatrix>::type test;
+    }
+    "
+    DEAL_II_ICC_SFINAE_BUG
+    )
+
+ENDIF()
index 532addee6ec666d10c134f93bc0fa43e3f28cbb3..dc538c70876fea0298f615790421d5a4294fd5a9 100644 (file)
@@ -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
 
 
 /***********************************************************************
index 8585bbb37d02f95ded008a9e642a6e7e82fdb01b..2086b94078085c0002dfb8b34eca98fab2ca3eb8 100644 (file)
@@ -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 <typename C>
     static std::true_type test(decltype(&C::template vmult_add<Range>),
                                decltype(&C::template Tvmult_add<Range>));
@@ -838,6 +842,7 @@ namespace
     template <typename C>
     static std::true_type test(decltype(&C::template vmult_add<Range, Domain>),
                                decltype(&C::template Tvmult_add<Domain, Range>));
+#endif
 
   public:
     // type is std::true_type if Matrix provides vmult_add and Tvmult_add,

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.