Skip to content

Commit 379ae03

Browse files
committed
Fix @struct closes #426, and lay more groundwork for generative metafunctions
Fix `@struct` to generate a type that's actually usable as a struct, by providing a metafunction a way to disable all member function generation Make member initialization diagnostics clearer and more actionable, with better source location attribution Lay more groundwork for generative metafunctions like `enum` and `flag_enum` that replace the entire type's contents, including to move more semantic checks to `sema.h` where they belong and will run later
1 parent 8345c2f commit 379ae03

File tree

10 files changed

+530
-208
lines changed

10 files changed

+530
-208
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
Microsoft (R) C/C++ Optimizing Compiler Version 19.35.32217.1 for x86
1+
Microsoft (R) C/C++ Optimizing Compiler Version 19.36.32534 for x86
22
Copyright (C) Microsoft Corporation. All rights reserved.
33

regression-tests/test-results/pure2-types-ordering-via-meta-functions.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,6 @@ public: [[nodiscard]] auto operator<=>(person_in_family_tree const& that) const
6868

6969
class mystruct {
7070
public: int val {0};
71-
public: mystruct(mystruct const& that);
72-
73-
public: auto operator=(mystruct const& that) -> mystruct& ;
74-
public: mystruct(mystruct&& that) noexcept;
75-
public: auto operator=(mystruct&& that) noexcept -> mystruct& ;
76-
public: explicit mystruct();
77-
78-
#line 19 "pure2-types-ordering-via-meta-functions.cpp2"
7971
};
8072

8173
auto main() -> int;
@@ -123,18 +115,6 @@ auto main() -> int;
123115
}
124116

125117

126-
mystruct::mystruct(mystruct const& that)
127-
: val{ that.val }{}
128-
129-
auto mystruct::operator=(mystruct const& that) -> mystruct& {
130-
val = that.val;
131-
return *this;}
132-
mystruct::mystruct(mystruct&& that) noexcept
133-
: val{ std::move(that).val }{}
134-
auto mystruct::operator=(mystruct&& that) noexcept -> mystruct& {
135-
val = std::move(that).val;
136-
return *this;}
137-
mystruct::mystruct(){}
138118
#line 21 "pure2-types-ordering-via-meta-functions.cpp2"
139119
auto main() -> int{
140120
my_integer a {1};

regression-tests/test-results/version

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

2-
cppfront compiler v0.2.1 Build 8613:1951
2+
cppfront compiler v0.2.1 Build 8617:0816
33
Copyright(c) Herb Sutter All rights reserved
44

55
SPDX-License-Identifier: CC-BY-NC-ND-4.0

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"8613:1951"
1+
"8617:0816"

source/common.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,15 @@ auto contains(
501501
!= range.end();
502502
}
503503

504+
auto contains(
505+
std::string const& s,
506+
auto const& value
507+
)
508+
-> bool
509+
{
510+
return s.find(value);
511+
}
512+
504513

505514
//-----------------------------------------------------------------------
506515
//

source/cppfront.cpp

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4488,7 +4488,8 @@ class cppfront
44884488

44894489
// We'll use this common guidance in several errors,
44904490
// so write it once to keep the guidance consistent
4491-
auto error_msg = "an operator= body must start with a series of 'member = value;' initialization statements for each of the type-scope objects in the same order they are declared";
4491+
assert (n.parent_declaration && n.parent_declaration->name());
4492+
auto error_msg = "an operator= body must start with a series of 'member = value;' initialization statements for each of the type-scope objects in the same order they are declared, or the member must have a default initializer (in type '" + n.parent_declaration->name()->to_string(true) + "')";
44924493

44934494
// If this constructor's type has data members, handle their initialization
44944495
// - objects is the list of this type's declarations
@@ -4519,6 +4520,9 @@ class cppfront
45194520
{
45204521
assert (*statement);
45214522
stmt_pos = (*statement)->position();
4523+
if (stmt_pos.lineno < 0) {
4524+
stmt_pos = n.position();
4525+
}
45224526

45234527
auto lhs = std::string{};
45244528
auto rhs = std::string{};
@@ -4615,7 +4619,15 @@ class cppfront
46154619
{
46164620
errors.emplace_back(
46174621
stmt_pos,
4618-
"expected '" + object_name + " = ...' initialization statement - " + error_msg
4622+
"in operator=, expected '" + object_name + " = ...' initialization statement (because type scope object '" + object_name + "' does not have a default initializer)"
4623+
);
4624+
errors.emplace_back(
4625+
(*object)->position(),
4626+
"see declaration for '" + object_name + "' here"
4627+
);
4628+
errors.emplace_back(
4629+
stmt_pos,
4630+
error_msg
46194631
);
46204632
return;
46214633
}
@@ -4731,7 +4743,15 @@ class cppfront
47314743
{
47324744
errors.emplace_back(
47334745
(*object)->position(),
4734-
canonize_object_name(*object) + " was not initialized - " + error_msg
4746+
canonize_object_name(*object) + " was not initialized - did you forget to write a default initializer, or assign to it in the operator= body?"
4747+
);
4748+
errors.emplace_back(
4749+
(*object)->position(),
4750+
"see declaration for '" + canonize_object_name(*object) + "' here"
4751+
);
4752+
errors.emplace_back(
4753+
(*object)->position(),
4754+
error_msg
47354755
);
47364756
return;
47374757
}
@@ -4776,7 +4796,7 @@ class cppfront
47764796
// Declarations are handled in multiple passes,
47774797
// but we only want to do the sema checks once
47784798
if (
4779-
printer.get_phase() == printer.phase1_type_defs_func_decls
4799+
printer.get_phase() == printer.phase2_func_defs
47804800
&& !sema.check(n)
47814801
)
47824802
{
@@ -5191,21 +5211,24 @@ class cppfront
51915211
);
51925212
auto prefix = "\n" + std::string( indent, ' ' ) + "public: ";
51935213

5194-
// If no constructor was defined, there should only be
5195-
// a default constructor, so generate that
5196-
if (!found_constructor) {
5197-
printer.print_extra( prefix + id + "() = default;" );
5198-
}
5214+
if (n.member_function_generation)
5215+
{
5216+
// If no constructor was defined, there should only be
5217+
// a default constructor, so generate that
5218+
if (!found_constructor) {
5219+
printer.print_extra( prefix + id + "() = default;" );
5220+
}
51995221

5200-
// If no 'that' constructor was defined, disable copy/move
5201-
// so that Cpp1 doesn't silently generate it anyway
5202-
if (!found_that_constructor) {
5203-
printer.print_extra( prefix + id + "(" + id + " const&) = delete; /* No 'that' constructor, suppress copy */" );
5204-
printer.print_extra( prefix + "auto operator=(" + id + " const&) -> void = delete;" );
5205-
}
5222+
// If no 'that' constructor was defined, disable copy/move
5223+
// so that Cpp1 doesn't silently generate it anyway
5224+
if (!found_that_constructor) {
5225+
printer.print_extra( prefix + id + "(" + id + " const&) = delete; /* No 'that' constructor, suppress copy */" );
5226+
printer.print_extra( prefix + "auto operator=(" + id + " const&) -> void = delete;" );
5227+
}
52065228

5207-
if (!found_constructor || !found_that_constructor) {
5208-
printer.print_extra( "\n" );
5229+
if (!found_constructor || !found_that_constructor) {
5230+
printer.print_extra( "\n" );
5231+
}
52095232
}
52105233

52115234
printer.print_cpp2("};\n", compound_stmt->close_brace);

0 commit comments

Comments
 (0)