[PATCH] D13386: PR24115: Don't instantiate constexpr function templates in decltype

Stephan Bergmann via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 2 08:05:08 PDT 2015


sberg created this revision.
sberg added reviewers: cfe-commits, rsmith.

As discussed in [[ https://llvm.org/bugs/show_bug.cgi?id=24115 | "llvm-nm fails to build with gcc 5.1's libstdc++," ]] both llvm-nm and LibreOffice fail to build against GCC 5.1 libstdc++, due to Clang trying (and failing) to instantiate constexpr function templates referenced from within a decltype.
See [[ https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/6udLpHDvShU | "Implicit instantiation of constexpr function template specialization called in decltype expression?" ]] for a stripped-down test case and a discussion why the Clang behaviour is considered wrong.
There is a comment in test/SemaTemplate/constexpr-instantiate.cpp claiming this behaviour is in line with g++, but I cannot reproduce that neither with some GCC 5.1.1 nor with a recent GCC trunk build.  The comment also says "FIXME: None of this is required by the C++ standard. The rules in this area are poorly specified, so this is subject to change.", and from the above build breakage I think it would be best to change the behaviour to not instantiate constexpr function templates merely because they are referenced from within a decltype.  (Doing so of course breaks the test corresponding to that comment, so turn that test around to check the changed behaviour now.)

http://reviews.llvm.org/D13386

Files:
  lib/Sema/SemaExpr.cpp
  test/SemaTemplate/constexpr-instantiate.cpp

Index: test/SemaTemplate/constexpr-instantiate.cpp
===================================================================
--- test/SemaTemplate/constexpr-instantiate.cpp
+++ test/SemaTemplate/constexpr-instantiate.cpp
@@ -77,37 +77,23 @@
 }
 
 namespace Unevaluated {
-  // We follow g++ in treating any reference to a constexpr function template
-  // specialization as requiring an instantiation, even if it occurs in an
-  // unevaluated context.
-  //
-  // We go slightly further than g++, and also trigger the implicit definition
-  // of a defaulted special member in the same circumstances. This seems scary,
-  // since a lot of classes have constexpr special members in C++11, but the
-  // only observable impact should be the implicit instantiation of constexpr
-  // special member templates (defaulted special members should only be
-  // generated if they are well-formed, and non-constexpr special members in a
-  // base or member cause the class's special member to not be constexpr).
-  //
-  // FIXME: None of this is required by the C++ standard. The rules in this
-  //        area are poorly specified, so this is subject to change.
   namespace NotConstexpr {
     template<typename T> struct S {
       S() : n(0) {}
       S(const S&) : n(T::error) {}
       int n;
     };
     struct U : S<int> {};
-    decltype(U(U())) u; // ok, don't instantiate S<int>::S() because it wasn't declared constexpr
+    decltype(U(U())) u; // ok, don't instantiate S<int>::S()
   }
   namespace Constexpr {
     template<typename T> struct S {
       constexpr S() : n(0) {}
-      constexpr S(const S&) : n(T::error) {} // expected-error {{has no members}}
+      constexpr S(const S&) : n(T::error) {}
       int n;
     };
-    struct U : S<int> {}; // expected-note {{instantiation}}
-    decltype(U(U())) u; // expected-note {{here}}
+    struct U : S<int> {};
+    decltype(U(U())) u; // ok, don't instantiate S<int>::S()
   }
 
   namespace PR11851_Comment0 {
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -12414,7 +12414,8 @@
     // However, they cannot be referenced if they are deleted, and they are
     // deleted whenever the implicit definition of the special member would
     // fail.
-    if (!Func->isConstexpr() || Func->getBody())
+    if (!Func->isConstexpr() || Func->getBody() ||
+        ExprEvalContexts.back().IsDecltype)
       return;
     CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Func);
     if (!Func->isImplicitlyInstantiable() && (!MD || MD->isUserProvided()))


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D13386.36366.patch
Type: text/x-patch
Size: 2611 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20151002/d6041008/attachment.bin>


More information about the cfe-commits mailing list