On 03/29/2016 06:37 AM, Jan Hubicka wrote:
On Mon, Mar 28, 2016 at 11:26 PM, Jason Merrill <ja...@redhat.com> wrote:
The constexpr evaluation code uses the inlining code to remap the constexpr
function body for evaluation so that recursion works properly. In this
testcase __func__ is declared as a static local variable, so rather than
remap it, remap_decls tries to add it to the local_decls list for the
function we're inlining into. But there is no such function in this case,
so we crash.
Avoid the add_local_decl call when cfun is null avoids the ICE (thanks
Jakub), but results in an undefined symbol. Calling
varpool_node::finalize_decl instead allows cgraph to handle the reference
from 'c' properly.
OK if testing passes?
So ce will never be instantiated?
Right, because no calls to it survive constexpr evaluation. And the
front end avoids finalizing it in make_rtl_for_nonlocal_decl...which is
another place I could fix this. Thus.
Tested x86_64-pc-linux-gnu, applying to trunk.
Jason
commit 28b2d2bfe2c55aa41e1d540a30595357f000279c
Author: Jason Merrill <ja...@redhat.com>
Date: Mon Mar 28 17:14:43 2016 -0400
PR c++/70353
gcc/
* tree-inline.c (remap_decls): Don't add_local_decl if
cfun is null.
gcc/cp/
* decl.c (make_rtl_for_nonlocal_decl): Don't defer local statics
in constexpr functions.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index cd5db3f..cfae210 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6251,8 +6251,11 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
return;
/* We defer emission of local statics until the corresponding
- DECL_EXPR is expanded. */
- defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl);
+ DECL_EXPR is expanded. But with constexpr its function might never
+ be expanded, so go ahead and tell cgraph about the variable now. */
+ defer_p = ((DECL_FUNCTION_SCOPE_P (decl)
+ && !DECL_DECLARED_CONSTEXPR_P (DECL_CONTEXT (decl)))
+ || DECL_VIRTUAL_P (decl));
/* Defer template instantiations. */
if (DECL_LANG_SPECIFIC (decl)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C
new file mode 100644
index 0000000..e678290
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C
@@ -0,0 +1,13 @@
+// PR c++/70353
+// { dg-do link { target c++11 } }
+
+constexpr const char* ce ()
+{
+ return __func__;
+}
+
+const char *c = ce();
+
+int main()
+{
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 9d4f8f7..5206d20 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -616,7 +616,8 @@ remap_decls (tree decls, vec<tree, va_gc> **nonlocalized_list,
/* We need to add this variable to the local decls as otherwise
nothing else will do so. */
if (TREE_CODE (old_var) == VAR_DECL
- && ! DECL_EXTERNAL (old_var))
+ && ! DECL_EXTERNAL (old_var)
+ && cfun)
add_local_decl (cfun, old_var);
if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE)
&& !DECL_IGNORED_P (old_var)