Skip to content

Commit

Permalink
fix(to_cpp1): define static data member with placeholder type in class
Browse files Browse the repository at this point in the history
  • Loading branch information
JohelEGP committed Nov 9, 2023
1 parent 61550a5 commit 2892889
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 5 deletions.
18 changes: 18 additions & 0 deletions regression-tests/pure2-type-and-namespace-aliases.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,21 @@ main: () = {
myfunc2 :== myfunc;
myfunc2();
}

myclass5: type == myclass4;

myclass3: @struct type = {
v0 :== :std::array = (0);;
v1 :== v0; // OK: Also uses the Cpp2 placeholder type.
v2: myclass3 == myclass3(); // OK: Doesn't use the Cpp2 placeholder type.
v3: _ == v0;
v4: myclass3 == v2; // OK: Doesn't use the Cpp2 placeholder type.
v5: myclass4 == myclass4(); // OK: Doesn't use the Cpp2 placeholder type.
v6: myclass5 == myclass5(); // OK: Doesn't use the Cpp2 placeholder type.
}

myclass4: @struct type = { }

myclass6: @struct <T: type> type = {
v: <U> _ requires true == 0;
}
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pure2-bugfix-for-non-local-function-expression.cpp2:9:7: warning: ‘t’ has a base ‘t::<lambda()>’ which has no linkage [-Wsubobject-linkage]
9 | t: @struct type = {
| ^
40 changes: 40 additions & 0 deletions regression-tests/test-results/pure2-type-and-namespace-aliases.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ class myclass;
template<typename T> class myclass2;


#line 39 "pure2-type-and-namespace-aliases.cpp2"
class myclass3;


#line 49 "pure2-type-and-namespace-aliases.cpp2"
class myclass4;

template<typename T> class myclass6;


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


Expand Down Expand Up @@ -60,6 +70,29 @@ template<typename T> class myclass2 {
auto main() -> int;


#line 37 "pure2-type-and-namespace-aliases.cpp2"
using myclass5 = myclass4;

class myclass3 {
public: static constexpr auto v0 = std::array{0};
public: static constexpr auto v1 = v0;// OK: Also uses the Cpp2 placeholder type.
public: static const myclass3 v2;// OK: Doesn't use the Cpp2 placeholder type.
public: static constexpr auto v3 = v0;
public: static const myclass3 v4;// OK: Doesn't use the Cpp2 placeholder type.
public: static const myclass4 v5;// OK: Doesn't use the Cpp2 placeholder type.
public: static const myclass5 v6;// OK: Doesn't use the Cpp2 placeholder type.
};

class myclass4 {};

template<typename T> class myclass6 {
public: template<typename U>
CPP2_REQUIRES_ (true)
#line 52 "pure2-type-and-namespace-aliases.cpp2"
static constexpr auto v = 0;
};


//=== Cpp2 function definitions =================================================


Expand Down Expand Up @@ -93,3 +126,10 @@ auto main() -> int{
myfunc2();
}

#line 42 "pure2-type-and-namespace-aliases.cpp2"
inline CPP2_CONSTEXPR myclass3 myclass3::v2 = myclass3();

inline CPP2_CONSTEXPR myclass3 myclass3::v4 = v2;
inline CPP2_CONSTEXPR myclass4 myclass3::v5 = myclass4();
inline CPP2_CONSTEXPR myclass5 myclass3::v6 = myclass5();

34 changes: 29 additions & 5 deletions source/to_cpp1.h
Original file line number Diff line number Diff line change
Expand Up @@ -5080,8 +5080,18 @@ class cppfront
auto& a = std::get<declaration_node::an_alias>(n.type);
assert(a);

// Helper for aliases that emit as a defining declaration.
auto const type_scope_object_alias_emits_in_phase_1_only = [&]() {
assert(
n.parent_is_type()
&& n.is_object_alias()
);
return !a->type_id
|| a->type_id->is_wildcard();
};

// Namespace-scope aliases are emitted in phase 1,
// type-scope object aliases in both phases 1 and 2, and
// type-scope object aliases is emitted in phase 1 and maybe 2, and
// function-scope aliases in phase 2
if (
(
Expand All @@ -5093,6 +5103,7 @@ class cppfront
n.parent_is_type()
&& n.is_object_alias()
&& printer.get_phase() == printer.phase2_func_defs
&& !type_scope_object_alias_emits_in_phase_1_only()
)
||
(
Expand Down Expand Up @@ -5158,21 +5169,34 @@ class cppfront
// Handle object aliases:
// - at function scope, it's const&
// - at namespace scope, it's inline constexpr
// - at type scope, it's also inline constexpr but see note (*) below
// - at type scope, it's also static constexpr but see note (*) below
else if (a->is_object_alias())
{
auto type = std::string{"auto"};
if (a->type_id) {
type = print_to_string(*a->type_id);
}

// (*) If this is at type scope, Cpp1 requires an out-of-line declaration dance
// for some cases to work - see https://stackoverflow.com/questions/11928089/
if (n.parent_is_type())
{
assert (n.parent_declaration->name());

if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
if (type_scope_object_alias_emits_in_phase_1_only()) {
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
printer.print_cpp2(
"static constexpr "
+ type + " "
+ print_to_string(*n.identifier)
+ " = "
+ print_to_string( *std::get<alias_node::an_object>(a->initializer) )
+ ";\n",
n.position()
);
}
}
// At type scope, Cpp1 requires an out-of-line declaration dance
// for some cases to work - see https://stackoverflow.com/questions/11928089/
else if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
printer.print_cpp2(
"static const "
+ type + " "
Expand Down

0 comments on commit 2892889

Please sign in to comment.