Skip to content

Commit 6d2cf46

Browse files
committed
Don't require named return values be initialized before (other) uninitialized locals
The reason to initialize in declaration order is for things that depend on nested lifetime, which is common for local variables – such as a smart pointer variable followed by another variable whose delayed initialization depends on the smart pointer being constructed and keeping something alive. That doesn’t apply to return values.
1 parent 0fe38ba commit 6d2cf46

File tree

5 files changed

+40
-5
lines changed

5 files changed

+40
-5
lines changed

regression-tests/pure2-initialization-safety-with-else-if.cpp2

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ main: (args) = {
2424
std::cout << p* << std::endl;
2525
}
2626

27+
ad_test: type = {
28+
intermediate_default_no_init: (x: double, y: double) -> (r: double) = {
29+
t: double;
30+
t = x + y;
31+
32+
r = t; // OK, after t but it's a return value
33+
}
34+
}
2735

2836
ok: () = {
2937
i: int;

regression-tests/test-results/pure2-initialization-safety-with-else-if.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,29 @@
88

99
#line 1 "pure2-initialization-safety-with-else-if.cpp2"
1010

11+
#line 27 "pure2-initialization-safety-with-else-if.cpp2"
12+
class ad_test;
13+
1114

1215
//=== Cpp2 type definitions and function declarations ===========================
1316

1417
#line 1 "pure2-initialization-safety-with-else-if.cpp2"
1518
auto main(int const argc_, char** argv_) -> int;
1619

20+
#line 27 "pure2-initialization-safety-with-else-if.cpp2"
21+
class ad_test {
22+
using intermediate_default_no_init_ret = double;
23+
1724
#line 28 "pure2-initialization-safety-with-else-if.cpp2"
25+
public: [[nodiscard]] static auto intermediate_default_no_init(cpp2::impl::in<double> x, cpp2::impl::in<double> y) -> intermediate_default_no_init_ret;
26+
public: ad_test() = default;
27+
public: ad_test(ad_test const&) = delete; /* No 'that' constructor, suppress copy */
28+
public: auto operator=(ad_test const&) -> void = delete;
29+
30+
31+
#line 34 "pure2-initialization-safety-with-else-if.cpp2"
32+
};
33+
1834
auto ok() -> void;
1935

2036
//=== Cpp2 function definitions =================================================
@@ -49,6 +65,16 @@ auto main(int const argc_, char** argv_) -> int{
4965
}
5066

5167
#line 28 "pure2-initialization-safety-with-else-if.cpp2"
68+
[[nodiscard]] auto ad_test::intermediate_default_no_init(cpp2::impl::in<double> x, cpp2::impl::in<double> y) -> intermediate_default_no_init_ret{
69+
cpp2::impl::deferred_init<double> r;
70+
#line 29 "pure2-initialization-safety-with-else-if.cpp2"
71+
cpp2::impl::deferred_init<double> t;
72+
t.construct(x + y);
73+
74+
r.construct(cpp2::move(t.value()));// OK, after t but it's a return value
75+
return std::move(r.value()); }
76+
77+
#line 36 "pure2-initialization-safety-with-else-if.cpp2"
5278
auto ok() -> void{
5379
cpp2::impl::deferred_init<int> i;
5480
if (true) {

regression-tests/test-results/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
cppfront compiler v0.8.2 Build A811:1537
2+
cppfront compiler v0.8.2 Build A812:1040
33
SPDX-License-Identifier Apache-2.0 WITH LLVM-exception
44
Copyright (c) 2022-2025 Herb Sutter

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"A811:1537"
1+
"A812:1040"

source/sema.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,7 @@ class sema
11601160
) const
11611161
-> bool
11621162
{
1163+
assert(decl);
11631164
auto name = decl->identifier->to_string();
11641165

11651166
struct selection_stack_entry{
@@ -1230,9 +1231,9 @@ class sema
12301231
auto const& sym = std::get<symbol::active::identifier>(symbols[pos].sym);
12311232
assert (sym.identifier);
12321233

1233-
if (
1234-
sym.is_use()
1234+
if (sym.is_use()
12351235
&& is_definite_initialization(sym.identifier)
1236+
&& !decl->return_param
12361237
)
12371238
{
12381239
errors.emplace_back(
@@ -2375,7 +2376,7 @@ class sema
23752376
}
23762377

23772378
if (n.pass != passing_style::out) {
2378-
push_activation( declaration_sym( true, n.declaration.get(), n.declaration->name(), n.declaration->initializer.get(), &n, inside_returns_list));
2379+
push_activation( declaration_sym( true, n.declaration.get(), n.declaration->name(), n.declaration->initializer.get(), &n, false, inside_returns_list));
23792380
current_declarations.push_back( &symbols.back().as_declaration() );
23802381
}
23812382
}

0 commit comments

Comments
 (0)