mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Support @param directives for ... parameters. #2578
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
- Deprecated `SomeEnum.associated` in favour of `SomeEnum.membersof`
|
||||
- Refactored `@simd` implementation.
|
||||
- Improve error message for `Foo{}` when `Foo` is not a generic type #2574.
|
||||
- Support `@param` directives for `...` parameters. #2578
|
||||
|
||||
### Fixes
|
||||
- `Foo.is_eq` would return false if the type was a `typedef` and had an overload, but the underlying type was not comparable.
|
||||
|
||||
@@ -3078,13 +3078,16 @@ static inline bool parse_contract_param(ParseContext *c, AstId *docs, AstId **do
|
||||
case TOKEN_CT_TYPE_IDENT:
|
||||
case TOKEN_CONST_IDENT:
|
||||
case TOKEN_HASH_IDENT:
|
||||
ast->contract_stmt.param.name = symstr(c);
|
||||
break;
|
||||
case TOKEN_ELLIPSIS:
|
||||
ast->contract_stmt.param.name = NULL;
|
||||
break;
|
||||
default:
|
||||
RETURN_PRINT_ERROR_HERE("Expected a parameter name here.");
|
||||
}
|
||||
ast->contract_stmt.param.name = symstr(c);
|
||||
ast->contract_stmt.param.span = c->span;
|
||||
ast->contract_stmt.param.modifier = mod;
|
||||
ast->contract_stmt.param.span = c->span;
|
||||
ast->contract_stmt.param.by_ref = is_ref;
|
||||
advance(c);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent
|
||||
static inline bool sema_check_struct_holes(SemaContext *context, Decl *decl, Decl *member);
|
||||
static inline bool sema_analyse_bitstruct_member(SemaContext *context, Decl *parent, Decl *member, unsigned index, bool allow_overlap, bool *erase_decl);
|
||||
|
||||
static inline bool sema_analyse_doc_header(SemaContext *context, AstId doc, Decl **params, Decl **extra_params, bool *pure_ref);
|
||||
static inline bool sema_analyse_doc_header(SemaContext *context, AstId doc, Decl **params, Decl **extra_params, bool *pure_ref, bool is_raw_vaarg);
|
||||
|
||||
static const char *attribute_domain_to_string(AttributeDomain domain);
|
||||
static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_data, Decl *decl, Attr *attr, AttributeDomain domain, bool *erase_decl);
|
||||
@@ -1495,7 +1495,7 @@ static inline bool sema_analyse_fntype(SemaContext *context, Decl *decl, bool *e
|
||||
Signature *sig = &decl->fntype_decl.signature;
|
||||
if (!sema_analyse_function_signature(context, decl, NULL, sig->abi, sig)) return false;
|
||||
bool pure = false;
|
||||
if (!sema_analyse_doc_header(context, decl->fntype_decl.docs, sig->params, NULL, &pure)) return false;
|
||||
if (!sema_analyse_doc_header(context, decl->fntype_decl.docs, sig->params, NULL, &pure, sig->variadic == VARIADIC_RAW)) return false;
|
||||
sig->attrs.is_pure = pure;
|
||||
return true;
|
||||
}
|
||||
@@ -3823,8 +3823,9 @@ IS_FAULT:;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_doc_header(SemaContext *context, AstId doc,
|
||||
Decl **params, Decl **extra_params, bool *pure_ref)
|
||||
Decl **params, Decl **extra_params, bool *pure_ref, bool is_raw_vaarg)
|
||||
{
|
||||
bool va_param_found = false;
|
||||
while (doc)
|
||||
{
|
||||
Ast *directive = astptr(doc);
|
||||
@@ -3846,6 +3847,23 @@ static inline bool sema_analyse_doc_header(SemaContext *context, AstId doc,
|
||||
}
|
||||
if (directive_kind != CONTRACT_PARAM) continue;
|
||||
const char *param_name = directive->contract_stmt.param.name;
|
||||
if (!param_name)
|
||||
{
|
||||
if (va_param_found)
|
||||
{
|
||||
RETURN_SEMA_ERROR_AT(directive->contract_stmt.param.span, "The '...' @param may not be repeated.");
|
||||
}
|
||||
if (directive->contract_stmt.param.modifier != INOUT_ANY)
|
||||
{
|
||||
RETURN_SEMA_ERROR_AT(directive->contract_stmt.param.span, "'...' @params may not have any in-out modifiers.");
|
||||
}
|
||||
if (!is_raw_vaarg)
|
||||
{
|
||||
RETURN_SEMA_ERROR_AT(directive->contract_stmt.param.span, "'...' @params are only allowed macros and functions with a '...' parameter.");
|
||||
}
|
||||
va_param_found = true;
|
||||
continue;
|
||||
}
|
||||
Decl *param = NULL;
|
||||
FOREACH(Decl *, other_param, params)
|
||||
{
|
||||
@@ -4322,7 +4340,7 @@ CHECK_DONE:
|
||||
bool pure = false;
|
||||
|
||||
if (!sema_analyse_doc_header(context, decl->func_decl.docs, decl->func_decl.signature.params, NULL,
|
||||
&pure)) return false;
|
||||
&pure, sig->variadic == VARIADIC_RAW)) return false;
|
||||
decl->func_decl.signature.attrs.is_pure = pure;
|
||||
if (!sema_set_alloca_alignment(context, decl->type, &decl->alignment)) return false;
|
||||
DEBUG_LOG("<<< Function analysis of [%s] successful.", decl_safe_name(decl));
|
||||
@@ -4518,27 +4536,28 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl, bool *er
|
||||
if (!sema_analyse_func_macro(context, decl, ATTR_MACRO, erase_decl)) return false;
|
||||
if (*erase_decl) return true;
|
||||
|
||||
if (!sema_analyse_signature(context, &decl->func_decl.signature, type_infoptrzero(decl->func_decl.type_parent), decl)) return false;
|
||||
Signature *sig = &decl->func_decl.signature;
|
||||
if (!sema_analyse_signature(context, sig, type_infoptrzero(decl->func_decl.type_parent), decl)) return false;
|
||||
|
||||
DeclId body_param = decl->func_decl.body_param;
|
||||
if (!decl->func_decl.signature.is_at_macro && body_param && !decl->func_decl.signature.is_safemacro)
|
||||
if (!decl->func_decl.signature.is_at_macro && body_param && !sig->is_safemacro)
|
||||
{
|
||||
RETURN_SEMA_ERROR(decl, "Names of macros with a trailing body must start with '@'.");
|
||||
}
|
||||
Decl **body_parameters = body_param ? declptr(body_param)->body_params : NULL;
|
||||
if (!sema_analyse_macro_body(context, body_parameters)) return false;
|
||||
bool pure = false;
|
||||
if (!sema_analyse_doc_header(context, decl->func_decl.docs, decl->func_decl.signature.params, body_parameters,
|
||||
&pure)) return false;
|
||||
if (!sema_analyse_doc_header(context, decl->func_decl.docs, sig->params, body_parameters,
|
||||
&pure, sig->variadic == VARIADIC_RAW)) return false;
|
||||
if (decl->func_decl.type_parent)
|
||||
{
|
||||
if (!sema_analyse_macro_method(context, decl)) return false;
|
||||
}
|
||||
bool always_const = decl->func_decl.signature.attrs.always_const;
|
||||
bool always_const = sig->attrs.always_const;
|
||||
// Sanity check "always const"
|
||||
if (always_const)
|
||||
{
|
||||
if (typeget(decl->func_decl.signature.rtype) == type_void) RETURN_SEMA_ERROR(decl, "'@const' macros may not return 'void', they should always return a constant value.");
|
||||
if (typeget(sig->rtype) == type_void) RETURN_SEMA_ERROR(decl, "'@const' macros may not return 'void', they should always return a constant value.");
|
||||
if (body_parameters) RETURN_SEMA_ERROR(decl, "'@const' macros cannot have body parameters.");
|
||||
Ast *body = astptr(decl->func_decl.body);
|
||||
ASSERT(body->ast_kind == AST_COMPOUND_STMT);
|
||||
|
||||
21
test/test_suite/contracts/ellipsis_param.c3
Normal file
21
test/test_suite/contracts/ellipsis_param.c3
Normal file
@@ -0,0 +1,21 @@
|
||||
module foo;
|
||||
import std;
|
||||
|
||||
<* @param [in] ... : "ofkeofek" *> // #error: may not have any in-out modifiers
|
||||
extern fn void test2(...);
|
||||
|
||||
<* @param ... : "ofkeofek" *>
|
||||
extern fn void test(...);
|
||||
|
||||
<* @param ... : "ofkeofek" *> // #error: are only allowed macros and functions with
|
||||
extern fn void test3();
|
||||
|
||||
<*
|
||||
@param ... : "ofkeofek"
|
||||
@param ... : "ofkeofek" *> // #error: @param may not be repeated
|
||||
extern fn void test4(...);
|
||||
|
||||
fn int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user