Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/decl_inits.c
Original file line number Diff line number Diff line change
Expand Up @@ -6135,7 +6135,10 @@ returned set to TRUE.
below. */
!(static_lifetime &&
!dps->init_state.initializer_must_be_constant &&
constant_addresses_local_var(folded_con))) {
constant_addresses_local_var(folded_con)) &&
/* The unspecified object of a reference or "this" whose
value is not known (P2280R4) has no constant address. */
!constant_addresses_unknown_object(folded_con)) {
if (is_error_constant(folded_con)) {
init_err = TRUE;
} else if (static_lifetime &&
Expand Down
59 changes: 59 additions & 0 deletions src/il.c
Original file line number Diff line number Diff line change
Expand Up @@ -27599,6 +27599,65 @@ variable.
return result;
} /* constant_addresses_local_var */

#if !STANDALONE_UTILITY_PROGRAM

static void examine_constant_for_unknown_object(
a_constant_ptr con,
an_expr_or_stmt_traversal_block_ptr tblock)
/*
Called from traverse_constant to check whether the constant contains a
ck_address entry that designates an unknown object.
*/
{
switch (con->kind) {
case ck_address:
if (address_con_is_unknown_object(con)) {
tblock->result = TRUE;
tblock->terminate = TRUE;
} /* if */
/* Be sure to avoid following pointers, since constants can be
self-referential in that way. */
tblock->suppress_subtree_walk = TRUE;
break;
case ck_dynamic_init:
case ck_template_param:
case ck_reflection:
tblock->suppress_subtree_walk = TRUE;
break;
default:
break;
} /* switch */
} /* examine_constant_for_unknown_object */


a_boolean constant_addresses_unknown_object(a_constant_ptr con)
/*
Return TRUE if con contains a ck_address component that designates an unknown
object (see address_con_is_unknown_object). Such an address has no run-time
representation, so con cannot be used as the initializer of a variable.
*/
{
a_boolean result = FALSE;

switch (con->kind) {
case ck_address:
case ck_aggregate:
{ an_expr_or_stmt_traversal_block tblock;
clear_expr_or_stmt_traversal_block(&tblock);
tblock.process_constant = examine_constant_for_unknown_object;
tblock.process_non_dynamic_constants = TRUE;
traverse_constant(con, &tblock);
result = tblock.result;
}
break;
default:
break;
} /* switch */
return result;
} /* constant_addresses_unknown_object */

#endif /* !STANDALONE_UTILITY_PROGRAM */


static void examine_type_for_error(a_type_ptr type,
an_expr_or_stmt_traversal_block_ptr tblock)
Expand Down
2 changes: 2 additions & 0 deletions src/il.h
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,8 @@ extern a_boolean expr_contains_error(an_expr_node_ptr expr);

extern a_boolean constant_addresses_local_var(a_constant_ptr con);

extern a_boolean constant_addresses_unknown_object(a_constant_ptr con);

extern a_boolean constant_contains_error(a_constant_ptr con);

extern a_boolean type_returned_by_cctor(a_type_ptr return_type,
Expand Down
34 changes: 34 additions & 0 deletions src/pending_changes/gh-525-reference-to-unknown-reference.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[GH #525]
Reference initialized from a reference whose referent is not known

When the initializer of a reference named another reference whose referent is
not known at compile time (e.g., a reference parameter), the new reference
could be bound to the storage of the named reference itself instead of to the
object that reference refers to. The generated code then read and wrote the
wrong object, with no diagnostic. This happened in C++26 mode for reference
parameters and for local references that are not initialized with a constant
expression (the hidden reference of a structured binding declaration such as
"auto &[a, b] = s;" was affected too). It also happened in C++11 and later
modes for a reference with static storage duration whose definition is not
visible, including when such a reference initialized a reference member of an
aggregate with static storage duration. For example:

struct S { int a; long b; };
extern S &ext;
long f(const S &s) {
const S &r = s; // In C++26 mode, r was bound to the storage of s.
return r.a + r.b;
}
long g() {
S &r = ext; // In C++11 and later modes, r was bound to the
// storage of ext.
return r.a + r.b;
}

For the same reason, a constexpr reference initialized that way was accepted
in some modes. Such an initializer is not a constant expression, and is now
diagnosed:

void h(const S &s) {
constexpr const S &r = s; // Previously accepted in C++26 mode; now an
} // error.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1474,13 +1478,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^

"SemaCXX/constant-expression-cxx11.cpp", line 2411: error: expression must have a constant value
constexpr int *q = (&n + 1) - (unsigned __int128)-1;
^
"SemaCXX/constant-expression-cxx11.cpp", line 2411: note: integer operation result is out of range
constexpr int *q = (&n + 1) - (unsigned __int128)-1;
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1477,13 +1481,6 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr int *q = (&n + 1) - (unsigned __int128)-1;
^

"SemaCXX/constant-expression-cxx11.cpp", line 2412: error: expression must have a constant value
constexpr int *r = &(&n + 1)[(unsigned __int128)-1];
^
"SemaCXX/constant-expression-cxx11.cpp", line 2412: note: integer operation result is out of range
constexpr int *r = &(&n + 1)[(unsigned __int128)-1];
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ fe_only -DTEST_NUMBER=3 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1439,14 +1443,6 @@ fe_only -DTEST_NUMBER=3 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr E e(0);
^

"SemaCXX/constant-expression-cxx11.cpp", line 2356: warning: variable "e" was declared but never referenced
constexpr E e(0);
^

"SemaCXX/constant-expression-cxx11.cpp", line 2378: error: reference to local variable of enclosing function is not allowed
return c;
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1471,13 +1475,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^

"SemaCXX/constant-expression-cxx11.cpp", line 2410: error: expression must have a constant value
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^
"SemaCXX/constant-expression-cxx11.cpp", line 2410: note: integer operation result is out of range
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1474,10 +1478,6 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^

"SemaCXX/constant-expression-cxx11.cpp", line 2411: error: expected a ")"
constexpr int *q = (&n + 1) - (unsigned __int128)-1;
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1479,13 +1483,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^

"SemaCXX/constant-expression-cxx11.cpp", line 2410: error: expression must have a constant value
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^
"SemaCXX/constant-expression-cxx11.cpp", line 2410: note: integer operation result is out of range
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1482,10 +1486,6 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^

"SemaCXX/constant-expression-cxx11.cpp", line 2411: error: expected a ")"
constexpr int *q = (&n + 1) - (unsigned __int128)-1;
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ fe_only -DTEST_NUMBER=3 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1443,10 +1447,6 @@ fe_only -DTEST_NUMBER=3 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr E e(0);
^

"SemaCXX/constant-expression-cxx11.cpp", line 2356: error: a constexpr variable must have a literal type or a reference type
constexpr E e(0);
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1482,13 +1486,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr int *p = (&n + 1) + (unsigned __int128)-1;
^

"SemaCXX/constant-expression-cxx11.cpp", line 2411: error: expression must have a constant value
constexpr int *q = (&n + 1) - (unsigned __int128)-1;
^
"SemaCXX/constant-expression-cxx11.cpp", line 2411: note: integer operation result is out of range
constexpr int *q = (&n + 1) - (unsigned __int128)-1;
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1485,13 +1489,6 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr int *q = (&n + 1) - (unsigned __int128)-1;
^

"SemaCXX/constant-expression-cxx11.cpp", line 2412: error: expression must have a constant value
constexpr int *r = &(&n + 1)[(unsigned __int128)-1];
^
"SemaCXX/constant-expression-cxx11.cpp", line 2412: note: integer operation result is out of range
constexpr int *r = &(&n + 1)[(unsigned __int128)-1];
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ fe_only -DTEST_NUMBER=3 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
case __builtin_constant_p(true) ? (long unsigned int)&x : 0:;
^

"SemaCXX/constant-expression-cxx11.cpp", line 127: error: expression must have a constant value
constexpr int &Recurse3 = Recurse2;
^

"SemaCXX/constant-expression-cxx11.cpp", line 168: error: expression must have a constant value
static_assert(F(4, k) == 3, "");
^
Expand Down Expand Up @@ -1443,10 +1447,6 @@ fe_only -DTEST_NUMBER=3 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
constexpr E e(0);
^

"SemaCXX/constant-expression-cxx11.cpp", line 2356: error: a constexpr variable must have a literal type or a reference type
constexpr E e(0);
^

Error limit reached.
200 errors detected in the compilation of "Test_name.c".
Compilation terminated.
Loading
Loading