mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Bump version to 0.3.14. Better non-lvalue errors. Dereferenced optional pointers are not lvalues.
This commit is contained in:
@@ -97,58 +97,65 @@ Decl *decl_new_with_type(const char *name, SourceSpan loc, DeclKind decl_type, V
|
||||
}
|
||||
|
||||
const char *decl_to_name(Decl *decl)
|
||||
{
|
||||
const char *name = decl_to_a_name(decl);
|
||||
if (name[1] == 'n') return &name[3];
|
||||
return &name[2];
|
||||
}
|
||||
|
||||
const char *decl_to_a_name(Decl *decl)
|
||||
{
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_BODYPARAM:
|
||||
return "bodyparam";
|
||||
return "a bodyparam";
|
||||
case DECL_DECLARRAY:
|
||||
return "declarray";
|
||||
return "a declarray";
|
||||
case DECL_BITSTRUCT:
|
||||
return "bitstruct";
|
||||
return "a bitstruct";
|
||||
case DECL_POISONED:
|
||||
return "poisoned decl";
|
||||
return "a poisoned decl";
|
||||
case DECL_CT_ASSERT:
|
||||
return "compile time assert";
|
||||
return "a compile time assert";
|
||||
case DECL_CT_CASE:
|
||||
return "compile time case";
|
||||
return "a compile time case";
|
||||
case DECL_CT_ELIF:
|
||||
return "compile time else if";
|
||||
return "a compile time else if";
|
||||
case DECL_CT_ELSE:
|
||||
return "compile time else";
|
||||
return "a compile time else";
|
||||
case DECL_CT_IF:
|
||||
return "compile time if";
|
||||
return "a compile time if";
|
||||
case DECL_CT_SWITCH:
|
||||
return "compile time switch";
|
||||
return "a compile time switch";
|
||||
case DECL_IMPORT:
|
||||
return "import";
|
||||
return "an import";
|
||||
case DECL_LABEL:
|
||||
return "label";
|
||||
return "a label";
|
||||
case DECL_ATTRIBUTE:
|
||||
return "attribute";
|
||||
return "an attribute";
|
||||
case DECL_DEFINE:
|
||||
case DECL_TYPEDEF:
|
||||
return "define";
|
||||
return "a define";
|
||||
case DECL_DISTINCT:
|
||||
return "distinct type";
|
||||
return "a distinct type";
|
||||
case DECL_ENUM:
|
||||
return "enum";
|
||||
return "an enum";
|
||||
case DECL_ENUM_CONSTANT:
|
||||
return "enum value";
|
||||
return "an enum value";
|
||||
case DECL_FAULTVALUE:
|
||||
return "err value";
|
||||
return "a fault value";
|
||||
case DECL_FAULT:
|
||||
return "fault";
|
||||
return "a fault";
|
||||
case DECL_FUNC:
|
||||
return "function";
|
||||
return "a function";
|
||||
case DECL_GENERIC:
|
||||
return "generic";
|
||||
return "a generic";
|
||||
case DECL_MACRO:
|
||||
return "macro";
|
||||
return "a macro";
|
||||
case DECL_STRUCT:
|
||||
return "struct";
|
||||
return "a struct";
|
||||
case DECL_UNION:
|
||||
return "union";
|
||||
return "a union";
|
||||
case DECL_VAR:
|
||||
switch (decl->var.kind)
|
||||
{
|
||||
@@ -156,30 +163,30 @@ const char *decl_to_name(Decl *decl)
|
||||
case VARDECL_REWRAPPED:
|
||||
UNREACHABLE
|
||||
case VARDECL_CONST:
|
||||
return "constant";
|
||||
return "a constant";
|
||||
case VARDECL_GLOBAL:
|
||||
return "global variable";
|
||||
return "a global variable";
|
||||
case VARDECL_LOCAL:
|
||||
return "variable";
|
||||
return "a variable";
|
||||
case VARDECL_PARAM:
|
||||
return "parameter";
|
||||
return "a parameter";
|
||||
case VARDECL_MEMBER:
|
||||
case VARDECL_BITMEMBER:
|
||||
return "member";
|
||||
return "a member";
|
||||
case VARDECL_PARAM_CT:
|
||||
return "compile time parameter";
|
||||
return "a compile time parameter";
|
||||
case VARDECL_PARAM_CT_TYPE:
|
||||
return "compile time type parameter";
|
||||
return "a compile time type parameter";
|
||||
case VARDECL_PARAM_REF:
|
||||
return "ref parameter";
|
||||
return "a ref parameter";
|
||||
case VARDECL_PARAM_EXPR:
|
||||
return "expression parameter";
|
||||
return "a expression parameter";
|
||||
case VARDECL_LOCAL_CT:
|
||||
return "compile time variable";
|
||||
return "a compile time variable";
|
||||
case VARDECL_LOCAL_CT_TYPE:
|
||||
return "compile time type variable";
|
||||
return "a compile time type variable";
|
||||
case VARDECL_UNWRAPPED:
|
||||
return "unwrapped";
|
||||
return "an unwrapped variable";
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
@@ -1907,6 +1907,7 @@ Decl *decl_new_var(const char *name, SourceSpan span, TypeInfo *type, VarDeclKin
|
||||
Decl *decl_new_generated_var(Type *type, VarDeclKind kind, SourceSpan span);
|
||||
void decl_set_external_name(Decl *decl);
|
||||
const char *decl_to_name(Decl *decl);
|
||||
const char *decl_to_a_name(Decl *decl);
|
||||
|
||||
INLINE bool decl_ok(Decl *decl);
|
||||
INLINE bool decl_poison(Decl *decl);
|
||||
|
||||
@@ -558,7 +558,7 @@ int sema_check_comp_time_bool(SemaContext *context, Expr *expr)
|
||||
}
|
||||
|
||||
|
||||
bool expr_is_lvalue(Expr *expr)
|
||||
static bool sema_check_expr_lvalue(Expr *top_expr, Expr *expr)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
@@ -566,9 +566,17 @@ bool expr_is_lvalue(Expr *expr)
|
||||
return true;
|
||||
case EXPR_IDENTIFIER:
|
||||
{
|
||||
if (expr->identifier_expr.is_const) return false;
|
||||
if (expr->identifier_expr.is_const)
|
||||
{
|
||||
SEMA_ERROR(top_expr, "You cannot assign to a constant.");
|
||||
return false;
|
||||
}
|
||||
Decl *decl = expr->identifier_expr.decl;
|
||||
if (decl->decl_kind != DECL_VAR) return false;
|
||||
if (decl->decl_kind != DECL_VAR)
|
||||
{
|
||||
SEMA_ERROR(top_expr, "You cannot assign a value to %s.", decl_to_a_name(decl));
|
||||
return false;
|
||||
}
|
||||
decl = decl_raw(decl);
|
||||
switch (decl->var.kind)
|
||||
{
|
||||
@@ -578,33 +586,96 @@ bool expr_is_lvalue(Expr *expr)
|
||||
case VARDECL_GLOBAL:
|
||||
case VARDECL_PARAM:
|
||||
case VARDECL_PARAM_REF:
|
||||
return true;
|
||||
case VARDECL_CONST:
|
||||
case VARDECL_MEMBER:
|
||||
case VARDECL_BITMEMBER:
|
||||
case VARDECL_PARAM_CT:
|
||||
case VARDECL_PARAM_CT_TYPE:
|
||||
return true;
|
||||
case VARDECL_CONST:
|
||||
case VARDECL_PARAM_EXPR:
|
||||
return false;
|
||||
UNREACHABLE
|
||||
case VARDECL_MEMBER:
|
||||
case VARDECL_BITMEMBER:
|
||||
goto ERR;
|
||||
case VARDECL_UNWRAPPED:
|
||||
case VARDECL_ERASE:
|
||||
case VARDECL_REWRAPPED:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
case EXPR_UNARY:
|
||||
return expr->unary_expr.operator == UNARYOP_DEREF;
|
||||
if (expr->unary_expr.operator != UNARYOP_DEREF) goto ERR;
|
||||
if (IS_OPTIONAL(expr))
|
||||
{
|
||||
SEMA_ERROR(top_expr, "You cannot assign to a dereferenced optional.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case EXPR_BITACCESS:
|
||||
case EXPR_ACCESS:
|
||||
return expr_is_lvalue(expr->access_expr.parent);
|
||||
return sema_check_expr_lvalue(top_expr, expr->access_expr.parent);
|
||||
case EXPR_GROUP:
|
||||
return expr_is_lvalue(expr->inner_expr);
|
||||
return sema_check_expr_lvalue(top_expr, expr->inner_expr);
|
||||
case EXPR_SUBSCRIPT:
|
||||
case EXPR_SLICE:
|
||||
case EXPR_SUBSCRIPT_ADDR:
|
||||
if (IS_OPTIONAL(expr))
|
||||
{
|
||||
SEMA_ERROR(top_expr, "You cannot assign to an optional value.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
case EXPR_HASH_IDENT:
|
||||
SEMA_ERROR(top_expr, "You cannot assign to an unevaluated expression.");
|
||||
return false;
|
||||
case EXPR_POISONED:
|
||||
case EXPR_BITASSIGN:
|
||||
case EXPR_BINARY:
|
||||
case EXPR_BUILTIN:
|
||||
case EXPR_COMPILER_CONST:
|
||||
case EXPR_MACRO_BODY_EXPANSION:
|
||||
case EXPR_CALL:
|
||||
case EXPR_CAST:
|
||||
case EXPR_CATCH:
|
||||
case EXPR_CATCH_UNWRAP:
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
case EXPR_CONST:
|
||||
case EXPR_CT_CALL:
|
||||
case EXPR_CT_CONV:
|
||||
case EXPR_CT_EVAL:
|
||||
case EXPR_COND:
|
||||
case EXPR_DECL:
|
||||
case EXPR_DESIGNATOR:
|
||||
case EXPR_EXPR_BLOCK:
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
case EXPR_FAILABLE:
|
||||
case EXPR_RETHROW:
|
||||
case EXPR_FORCE_UNWRAP:
|
||||
case EXPR_MACRO_BLOCK:
|
||||
case EXPR_RETVAL:
|
||||
case EXPR_FLATPATH:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
case EXPR_POST_UNARY:
|
||||
case EXPR_SLICE_ASSIGN:
|
||||
case EXPR_STRINGIFY:
|
||||
case EXPR_ARGV_TO_SUBARRAY:
|
||||
case EXPR_TERNARY:
|
||||
case EXPR_TRY:
|
||||
case EXPR_TRY_UNWRAP:
|
||||
case EXPR_TRY_UNWRAP_CHAIN:
|
||||
case EXPR_TYPEID:
|
||||
case EXPR_TYPEINFO:
|
||||
case EXPR_VARIANTSWITCH:
|
||||
case EXPR_NOP:
|
||||
case EXPR_TYPEID_INFO:
|
||||
case EXPR_VARIANT:
|
||||
case EXPR_BUILTIN_ACCESS:
|
||||
goto ERR;
|
||||
}
|
||||
UNREACHABLE
|
||||
ERR:
|
||||
SEMA_ERROR(top_expr, "An assignable expression, like a variable, was expected here.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -703,11 +774,7 @@ bool expr_may_addr(Expr *expr)
|
||||
|
||||
bool sema_expr_check_assign(SemaContext *c, Expr *expr)
|
||||
{
|
||||
if (!expr_is_lvalue(expr))
|
||||
{
|
||||
SEMA_ERROR(expr, "An assignable expression, like a variable, was expected here.");
|
||||
return false;
|
||||
}
|
||||
if (!sema_check_expr_lvalue(expr, expr)) return false;
|
||||
if (expr->expr_kind == EXPR_BITACCESS || expr->expr_kind == EXPR_ACCESS) expr = expr->access_expr.parent;
|
||||
if (expr->expr_kind == EXPR_IDENTIFIER)
|
||||
{
|
||||
|
||||
@@ -56,7 +56,6 @@ bool splitpathref(const char *string, ArraySize len, Path **path_ref, const char
|
||||
|
||||
#define IS_CONST(_x) ((_x)->expr_kind == EXPR_CONST)
|
||||
|
||||
bool expr_is_lvalue(Expr *expr);
|
||||
bool sema_expr_check_assign(SemaContext *c, Expr *expr);
|
||||
bool sema_analyse_contracts(SemaContext *context, AstId doc, AstId **asserts);
|
||||
void sema_append_contract_asserts(AstId assert_first, Ast* compound_stmt);
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.3.13"
|
||||
#define COMPILER_VERSION "0.3.14"
|
||||
Reference in New Issue
Block a user