Skip to content

Commit 91e1219

Browse files
committed
d: Defer compiling inline definitions until after the module has finished.
This is to prevent the case of when generating the methods of a struct type, we don't accidentally emit an inline function that references it, as the outer struct itself would still be incomplete. gcc/d/ChangeLog: * d-tree.h (d_defer_declaration): Declare. * decl.cc (function_needs_inline_definition_p): Defer checking DECL_UNINLINABLE and DECL_DECLARED_INLINE_P. (maybe_build_decl_tree): Call d_defer_declaration instead of build_decl_tree. * modules.cc (deferred_inline_declarations): New variable. (build_module_tree): Set deferred_inline_declarations and a handle declarations pushed to it. (d_defer_declaration): New function. (cherry picked from commit 8db5b71)
1 parent dc230a0 commit 91e1219

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

gcc/d/d-tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,7 @@ extern tree maybe_expand_intrinsic (tree);
660660
extern void build_module_tree (Module *);
661661
extern tree d_module_context (void);
662662
extern void register_module_decl (Declaration *);
663+
extern void d_defer_declaration (Declaration *);
663664
extern void d_finish_compilation (tree *, int);
664665

665666
/* In runtime.cc. */

gcc/d/decl.cc

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,18 +1041,10 @@ function_needs_inline_definition_p (FuncDeclaration *fd)
10411041
if (!DECL_EXTERNAL (fd->csym))
10421042
return false;
10431043

1044-
/* Non-inlineable functions are always external. */
1045-
if (DECL_UNINLINABLE (fd->csym))
1046-
return false;
1047-
10481044
/* No function body available for inlining. */
10491045
if (!fd->fbody)
10501046
return false;
10511047

1052-
/* Ignore functions that aren't decorated with `pragma(inline)'. */
1053-
if (fd->inlining != PINLINE::always)
1054-
return false;
1055-
10561048
/* These functions are tied to the module they are defined in. */
10571049
if (fd->isFuncLiteralDeclaration ()
10581050
|| fd->isUnitTestDeclaration ()
@@ -1065,6 +1057,14 @@ function_needs_inline_definition_p (FuncDeclaration *fd)
10651057
if (function_defined_in_root_p (fd))
10661058
return false;
10671059

1060+
/* Non-inlineable functions are always external. */
1061+
if (DECL_UNINLINABLE (fd->csym))
1062+
return false;
1063+
1064+
/* Ignore functions that aren't decorated with `pragma(inline)'. */
1065+
if (!DECL_DECLARED_INLINE_P (fd->csym))
1066+
return false;
1067+
10681068
/* Weak functions cannot be inlined. */
10691069
if (lookup_attribute ("weak", DECL_ATTRIBUTES (fd->csym)))
10701070
return false;
@@ -1076,8 +1076,8 @@ function_needs_inline_definition_p (FuncDeclaration *fd)
10761076
return true;
10771077
}
10781078

1079-
/* If the variable or function declaration in DECL needs to be defined, call
1080-
build_decl_tree on it now before returning its back-end symbol. */
1079+
/* If the variable or function declaration in DECL needs to be defined, add it
1080+
to the list of deferred declarations to build later. */
10811081

10821082
static tree
10831083
maybe_build_decl_tree (Declaration *decl)
@@ -1098,7 +1098,7 @@ maybe_build_decl_tree (Declaration *decl)
10981098
if (function_needs_inline_definition_p (fd))
10991099
{
11001100
DECL_EXTERNAL (fd->csym) = 0;
1101-
build_decl_tree (fd);
1101+
d_defer_declaration (fd);
11021102
}
11031103
}
11041104

gcc/d/modules.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ static module_info *current_testing_module;
121121

122122
static Module *current_module_decl;
123123

124+
/* Any inline symbols that were deferred during codegen. */
125+
vec<Declaration *> *deferred_inline_declarations;
126+
124127
/* Returns an internal function identified by IDENT. This is used
125128
by both module initialization and dso handlers. */
126129

@@ -724,6 +727,9 @@ build_module_tree (Module *decl)
724727
current_testing_module = &mitest;
725728
current_module_decl = decl;
726729

730+
vec<Declaration *> deferred_decls = vNULL;
731+
deferred_inline_declarations = &deferred_decls;
732+
727733
/* Layout module members. */
728734
if (decl->members)
729735
{
@@ -811,9 +817,14 @@ build_module_tree (Module *decl)
811817
layout_moduleinfo (decl);
812818
}
813819

820+
/* Process all deferred functions after finishing module. */
821+
for (size_t i = 0; i < deferred_decls.length (); ++i)
822+
build_decl_tree (deferred_decls[i]);
823+
814824
current_moduleinfo = NULL;
815825
current_testing_module = NULL;
816826
current_module_decl = NULL;
827+
deferred_inline_declarations = NULL;
817828
}
818829

819830
/* Returns the current function or module context for the purpose
@@ -888,6 +899,15 @@ register_module_decl (Declaration *d)
888899
}
889900
}
890901

902+
/* Add DECL as a declaration to emit at the end of the current module. */
903+
904+
void
905+
d_defer_declaration (Declaration *decl)
906+
{
907+
gcc_assert (deferred_inline_declarations != NULL);
908+
deferred_inline_declarations->safe_push (decl);
909+
}
910+
891911
/* Wrapup all global declarations and start the final compilation. */
892912

893913
void

0 commit comments

Comments
 (0)