Recursive references between globals are now correctly handled.

This commit is contained in:
Christoffer Lerno
2021-01-24 22:53:46 +01:00
committed by Christoffer Lerno
parent 7fc12192f4
commit 26d25e3f74
25 changed files with 75 additions and 163 deletions

View File

@@ -807,38 +807,7 @@ static inline bool sema_analyse_global(Context *context, Decl *decl)
if (!sema_resolve_type_info(context, decl->var.type_info)) return false;
decl->type = decl->var.type_info->type;
}
// Check the initializer.
if (decl->var.init_expr && decl->type)
{
Expr *init_expr = decl->var.init_expr;
// 1. Check type.
if (!sema_analyse_expr_of_required_type(context, decl->type, init_expr, false)) return false;
// 2. Check const-ness
if (!init_expr->constant)
{
// 3. Special case is when the init expression is the reference
// to a constant global structure.
if (init_expr->expr_kind == EXPR_CONST_IDENTIFIER)
{
// 4. If so we copy the init expression, which should always be constant.
*init_expr = *init_expr->identifier_expr.decl->var.init_expr;
assert(init_expr->constant);
}
else
{
if (init_expr->expr_kind == EXPR_CAST)
{
SEMA_ERROR(decl->var.init_expr, "The expression may not be a non constant cast.");
}
else
{
SEMA_ERROR(decl->var.init_expr, "The expression must be a constant value.");
}
return false;
}
}
if (!decl->type) decl->type = decl->var.init_expr->type;
}
// We expect a constant to actually be parsed correctly so that it has a value, so
// this should always be true.
assert(decl->type || decl->var.kind == VARDECL_CONST);
@@ -879,6 +848,45 @@ static inline bool sema_analyse_global(Context *context, Decl *decl)
}
}
// If we already have the type resolved then we can pretend to be done,
// this will help in case we otherwise would get circular references.
if (decl->type)
{
decl->resolve_status = RESOLVE_DONE;
}
// Check the initializer.
if (decl->var.init_expr && decl->type)
{
Expr *init_expr = decl->var.init_expr;
// 1. Check type.
if (!sema_analyse_expr_of_required_type(context, decl->type, init_expr, false)) return false;
// 2. Check const-ness
if (!init_expr->constant)
{
// 3. Special case is when the init expression is the reference
// to a constant global structure.
if (init_expr->expr_kind == EXPR_CONST_IDENTIFIER)
{
// 4. If so we copy the init expression, which should always be constant.
*init_expr = *init_expr->identifier_expr.decl->var.init_expr;
assert(init_expr->constant);
}
else
{
if (init_expr->expr_kind == EXPR_CAST)
{
SEMA_ERROR(decl->var.init_expr, "The expression may not be a non constant cast.");
}
else
{
SEMA_ERROR(decl->var.init_expr, "The expression must be a constant value.");
}
return false;
}
}
}
switch (decl->var.kind)
{
case VARDECL_CONST: