Skip to content

Commit 294140d

Browse files
committed
c++: constexpr error with fn redecl in local scope [PR111132]
We evaluate constexpr functions on the original, pre-genericization bodies. That means that the function body we're evaluating will not have gone through cp_genericize_r's "Map block scope extern declarations to visible declarations with the same name and type in outer scopes if any". Here: constexpr bool bar() { return true; } // #1 constexpr bool foo() { constexpr bool bar(void); // gcc-mirror#2 return bar(); } it means that we: 1) register_constexpr_fundef (#1) 2) cp_genericize (#1) nothing interesting happens 3) register_constexpr_fundef (foo) does copy_fn, so we have two copies of the BIND_EXPR 4) cp_genericize (foo) this remaps gcc-mirror#2 to #1, but only on one copy of the BIND_EXPR 5) retrieve_constexpr_fundef (foo) we find it, no problem 6) retrieve_constexpr_fundef (gcc-mirror#2) and here gcc-mirror#2 isn't found in constexpr_fundef_table, because we're working on the BIND_EXPR copy where gcc-mirror#2 wasn't mapped to #1 so we fail. We've only registered #1. It should work to use DECL_LOCAL_DECL_ALIAS (which used to be extern_decl_map). We evaluate constexpr functions on pre-cp_fold bodies to avoid diagnostic problems, but the remapping I'm proposing should not interfere with diagnostics. This is not a problem for a global scope redeclaration; there we go through duplicate_decls which keeps the DECL_UID: DECL_UID (olddecl) = olddecl_uid; and DECL_UID is what constexpr_fundef_hasher::hash uses. PR c++/111132 gcc/cp/ChangeLog: * constexpr.cc (get_function_named_in_call): Use cp_get_fndecl_from_callee. * cvt.cc (cp_get_fndecl_from_callee): If there's a DECL_LOCAL_DECL_ALIAS, use it. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-redeclaration3.C: New test. * g++.dg/cpp0x/constexpr-redeclaration4.C: New test. (cherry picked from commit 8c90638)
1 parent dfe7b5e commit 294140d

File tree

4 files changed

+47
-8
lines changed

4 files changed

+47
-8
lines changed

gcc/cp/constexpr.cc

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -702,16 +702,14 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
702702

703703
/* We have an expression tree T that represents a call, either CALL_EXPR
704704
or AGGR_INIT_EXPR. If the call is lexically to a named function,
705-
retrun the _DECL for that function. */
705+
return the _DECL for that function. */
706706

707707
static tree
708708
get_function_named_in_call (tree t)
709709
{
710-
tree fun = cp_get_callee (t);
711-
if (fun && TREE_CODE (fun) == ADDR_EXPR
712-
&& TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL)
713-
fun = TREE_OPERAND (fun, 0);
714-
return fun;
710+
tree callee = cp_get_callee (t);
711+
tree fun = cp_get_fndecl_from_callee (callee, /*fold*/false);
712+
return fun ? fun : callee;
715713
}
716714

717715
/* Subroutine of check_constexpr_fundef. BODY is the body of a function

gcc/cp/cvt.cc

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,8 +1001,22 @@ cp_get_fndecl_from_callee (tree fn, bool fold /* = true */)
10011001
{
10021002
if (fn == NULL_TREE)
10031003
return fn;
1004+
1005+
/* We evaluate constexpr functions on the original, pre-genericization
1006+
bodies. So block-scope extern declarations have not been mapped to
1007+
declarations in outer scopes. Use the namespace-scope declaration,
1008+
if any, so that retrieve_constexpr_fundef can find it (PR111132). */
1009+
auto fn_or_local_alias = [] (tree f)
1010+
{
1011+
if (DECL_LOCAL_DECL_P (f))
1012+
if (tree alias = DECL_LOCAL_DECL_ALIAS (f))
1013+
if (alias != error_mark_node)
1014+
return alias;
1015+
return f;
1016+
};
1017+
10041018
if (TREE_CODE (fn) == FUNCTION_DECL)
1005-
return fn;
1019+
return fn_or_local_alias (fn);
10061020
tree type = TREE_TYPE (fn);
10071021
if (type == NULL_TREE || !INDIRECT_TYPE_P (type))
10081022
return NULL_TREE;
@@ -1013,7 +1027,7 @@ cp_get_fndecl_from_callee (tree fn, bool fold /* = true */)
10131027
|| TREE_CODE (fn) == FDESC_EXPR)
10141028
fn = TREE_OPERAND (fn, 0);
10151029
if (TREE_CODE (fn) == FUNCTION_DECL)
1016-
return fn;
1030+
return fn_or_local_alias (fn);
10171031
return NULL_TREE;
10181032
}
10191033

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// PR c++/111132
2+
// { dg-do compile { target c++11 } }
3+
4+
constexpr bool bar(void) {
5+
return true;
6+
}
7+
8+
constexpr bool foo() {
9+
constexpr bool bar(void);
10+
return bar();
11+
}
12+
13+
static_assert(foo(), "");
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// PR c++/111132
2+
// { dg-do compile { target c++11 } }
3+
4+
constexpr bool bar(void) {
5+
return true;
6+
}
7+
8+
constexpr bool bar(void);
9+
10+
constexpr bool foo() {
11+
return bar();
12+
}
13+
14+
static_assert(foo(), "");

0 commit comments

Comments
 (0)