X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=238422ab9ad1486f227b115ac593596d1a1e2fa7;hb=912addb873c5f8b193970fe4f0926ff89aec3fc8;hp=9fabfeb004d866ff1276315e0cafe66b409dbe27;hpb=6115f7412770ceb4f4c7d8cf93fe4088b0be9d2b;p=cparser diff --git a/parser.c b/parser.c index 9fabfeb..238422a 100644 --- a/parser.c +++ b/parser.c @@ -206,6 +206,9 @@ static entity_t *record_entity(entity_t *entity, bool is_definition); static void semantic_comparison(binary_expression_t *expression); +static void create_gnu_builtins(void); +static void create_microsoft_intrinsics(void); + #define STORAGE_CLASSES \ STORAGE_CLASSES_NO_EXTERN \ case T_extern: @@ -288,27 +291,16 @@ static void semantic_comparison(binary_expression_t *expression); case T___FUNCTION__: \ case T___PRETTY_FUNCTION__: \ case T___alignof__: \ - case T___builtin_alloca: \ case T___builtin_classify_type: \ case T___builtin_constant_p: \ - case T___builtin_expect: \ - case T___builtin_huge_val: \ - case T___builtin_inf: \ - case T___builtin_inff: \ - case T___builtin_infl: \ case T___builtin_isgreater: \ case T___builtin_isgreaterequal: \ case T___builtin_isless: \ case T___builtin_islessequal: \ case T___builtin_islessgreater: \ case T___builtin_isunordered: \ - case T___builtin_nan: \ - case T___builtin_nanf: \ - case T___builtin_nanl: \ case T___builtin_offsetof: \ - case T___builtin_prefetch: \ case T___builtin_va_arg: \ - case T___builtin_va_end: \ case T___builtin_va_start: \ case T___func__: \ case T___noop: \ @@ -409,33 +401,32 @@ static size_t get_statement_struct_size(statement_kind_t kind) static size_t get_expression_struct_size(expression_kind_t kind) { static const size_t sizes[] = { - [EXPR_INVALID] = sizeof(expression_base_t), - [EXPR_REFERENCE] = sizeof(reference_expression_t), - [EXPR_REFERENCE_ENUM_VALUE] = sizeof(reference_expression_t), - [EXPR_CONST] = sizeof(const_expression_t), - [EXPR_CHARACTER_CONSTANT] = sizeof(const_expression_t), - [EXPR_WIDE_CHARACTER_CONSTANT] = sizeof(const_expression_t), - [EXPR_STRING_LITERAL] = sizeof(string_literal_expression_t), - [EXPR_WIDE_STRING_LITERAL] = sizeof(wide_string_literal_expression_t), - [EXPR_COMPOUND_LITERAL] = sizeof(compound_literal_expression_t), - [EXPR_CALL] = sizeof(call_expression_t), - [EXPR_UNARY_FIRST] = sizeof(unary_expression_t), - [EXPR_BINARY_FIRST] = sizeof(binary_expression_t), - [EXPR_CONDITIONAL] = sizeof(conditional_expression_t), - [EXPR_SELECT] = sizeof(select_expression_t), - [EXPR_ARRAY_ACCESS] = sizeof(array_access_expression_t), - [EXPR_SIZEOF] = sizeof(typeprop_expression_t), - [EXPR_ALIGNOF] = sizeof(typeprop_expression_t), - [EXPR_CLASSIFY_TYPE] = sizeof(classify_type_expression_t), - [EXPR_FUNCNAME] = sizeof(funcname_expression_t), - [EXPR_BUILTIN_SYMBOL] = sizeof(builtin_symbol_expression_t), - [EXPR_BUILTIN_CONSTANT_P] = sizeof(builtin_constant_expression_t), - [EXPR_BUILTIN_PREFETCH] = sizeof(builtin_prefetch_expression_t), - [EXPR_OFFSETOF] = sizeof(offsetof_expression_t), - [EXPR_VA_START] = sizeof(va_start_expression_t), - [EXPR_VA_ARG] = sizeof(va_arg_expression_t), - [EXPR_STATEMENT] = sizeof(statement_expression_t), - [EXPR_LABEL_ADDRESS] = sizeof(label_address_expression_t), + [EXPR_INVALID] = sizeof(expression_base_t), + [EXPR_REFERENCE] = sizeof(reference_expression_t), + [EXPR_REFERENCE_ENUM_VALUE] = sizeof(reference_expression_t), + [EXPR_CONST] = sizeof(const_expression_t), + [EXPR_CHARACTER_CONSTANT] = sizeof(const_expression_t), + [EXPR_WIDE_CHARACTER_CONSTANT] = sizeof(const_expression_t), + [EXPR_STRING_LITERAL] = sizeof(string_literal_expression_t), + [EXPR_WIDE_STRING_LITERAL] = sizeof(wide_string_literal_expression_t), + [EXPR_COMPOUND_LITERAL] = sizeof(compound_literal_expression_t), + [EXPR_CALL] = sizeof(call_expression_t), + [EXPR_UNARY_FIRST] = sizeof(unary_expression_t), + [EXPR_BINARY_FIRST] = sizeof(binary_expression_t), + [EXPR_CONDITIONAL] = sizeof(conditional_expression_t), + [EXPR_SELECT] = sizeof(select_expression_t), + [EXPR_ARRAY_ACCESS] = sizeof(array_access_expression_t), + [EXPR_SIZEOF] = sizeof(typeprop_expression_t), + [EXPR_ALIGNOF] = sizeof(typeprop_expression_t), + [EXPR_CLASSIFY_TYPE] = sizeof(classify_type_expression_t), + [EXPR_FUNCNAME] = sizeof(funcname_expression_t), + [EXPR_BUILTIN_CONSTANT_P] = sizeof(builtin_constant_expression_t), + [EXPR_BUILTIN_TYPES_COMPATIBLE_P] = sizeof(builtin_types_compatible_expression_t), + [EXPR_OFFSETOF] = sizeof(offsetof_expression_t), + [EXPR_VA_START] = sizeof(va_start_expression_t), + [EXPR_VA_ARG] = sizeof(va_arg_expression_t), + [EXPR_STATEMENT] = sizeof(statement_expression_t), + [EXPR_LABEL_ADDRESS] = sizeof(label_address_expression_t), }; if (kind >= EXPR_UNARY_FIRST && kind <= EXPR_UNARY_LAST) { return sizes[EXPR_UNARY_FIRST]; @@ -1120,7 +1111,7 @@ static void report_assign_error(assign_error_t error, type_t *orig_type_left, } } -/** Implements the rules from § 6.5.16.1 */ +/** Implements the rules from §6.5.16.1 */ static assign_error_t semantic_assign(type_t *orig_type_left, const expression_t *const right) { @@ -2137,9 +2128,8 @@ unary: case EXPR_CLASSIFY_TYPE: case EXPR_ALIGNOF: case EXPR_FUNCNAME: - case EXPR_BUILTIN_SYMBOL: case EXPR_BUILTIN_CONSTANT_P: - case EXPR_BUILTIN_PREFETCH: + case EXPR_BUILTIN_TYPES_COMPATIBLE_P: case EXPR_OFFSETOF: case EXPR_STATEMENT: // TODO case EXPR_LABEL_ADDRESS: @@ -2229,7 +2219,7 @@ static initializer_t *initializer_from_expression(type_t *orig_type, { /* TODO check that expression is a constant expression */ - /* § 6.7.8.14/15 char array may be initialized by string literals */ + /* §6.7.8.14/15 char array may be initialized by string literals */ type_t *type = skip_typeref(orig_type); type_t *expr_type_orig = expression->base.type; type_t *expr_type = skip_typeref(expr_type_orig); @@ -2293,7 +2283,7 @@ static bool is_initializer_constant(const expression_t *expression) /** * Parses an scalar initializer. * - * § 6.7.8.11; eat {} without warning + * §6.7.8.11; eat {} without warning */ static initializer_t *parse_scalar_initializer(type_t *type, bool must_be_constant) @@ -2909,7 +2899,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env) result = parse_scalar_initializer(type, env->must_be_constant); } - /* § 6.7.8:22 array initializers for arrays with unknown size determine + /* §6.7.8:22 array initializers for arrays with unknown size determine * the array type size */ if (is_type_array(type) && type->array.size_expression == NULL && result != NULL) { @@ -3201,7 +3191,7 @@ static type_t *parse_typeof(void) type = parse_typename(); } else { expression = parse_expression(); - type = expression->base.type; + type = revert_automatic_type_conversion(expression); } break; @@ -4999,6 +4989,16 @@ static void error_redefined_as_different_kind(const source_position_t *pos, get_entity_kind_name(new_kind), &old->base.source_position); } +static bool is_error_entity(entity_t *const ent) +{ + if (is_declaration(ent)) { + return is_type_valid(skip_typeref(ent->declaration.type)); + } else if (ent->kind == ENTITY_TYPEDEF) { + return is_type_valid(skip_typeref(ent->typedefe.type)); + } + return false; +} + /** * record entities for the NAMESPACE_NORMAL, and produce error messages/warnings * for various problems that occur for multiple definitions @@ -5013,7 +5013,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) if (symbol == NULL) return entity; - entity_t *previous_entity = get_entity(symbol, namespc); + entity_t *const previous_entity = get_entity(symbol, namespc); /* pushing the same entity twice will break the stack structure */ assert(previous_entity != entity); @@ -5043,160 +5043,167 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) entity->declaration.type, symbol); } - if (previous_entity != NULL && - previous_entity->base.parent_scope == ¤t_function->parameters && - previous_entity->base.parent_scope->depth + 1 == current_scope->depth) { - assert(previous_entity->kind == ENTITY_PARAMETER); - errorf(pos, - "declaration '%#T' redeclares the parameter '%#T' (declared %P)", - entity->declaration.type, symbol, - previous_entity->declaration.type, symbol, - &previous_entity->base.source_position); - goto finish; - } - - if (previous_entity != NULL && - previous_entity->base.parent_scope == current_scope) { - if (previous_entity->kind != entity->kind) { - error_redefined_as_different_kind(pos, previous_entity, - entity->kind); - goto finish; - } - if (previous_entity->kind == ENTITY_ENUM_VALUE) { - errorf(pos, "redeclaration of enum entry '%Y' (declared %P)", - symbol, &previous_entity->base.source_position); - goto finish; - } - if (previous_entity->kind == ENTITY_TYPEDEF) { - /* TODO: C++ allows this for exactly the same type */ - errorf(pos, "redefinition of typedef '%Y' (declared %P)", - symbol, &previous_entity->base.source_position); + if (previous_entity != NULL) { + if (previous_entity->base.parent_scope == ¤t_function->parameters && + previous_entity->base.parent_scope->depth + 1 == current_scope->depth) { + assert(previous_entity->kind == ENTITY_PARAMETER); + errorf(pos, + "declaration '%#T' redeclares the parameter '%#T' (declared %P)", + entity->declaration.type, symbol, + previous_entity->declaration.type, symbol, + &previous_entity->base.source_position); goto finish; } - /* at this point we should have only VARIABLES or FUNCTIONS */ - assert(is_declaration(previous_entity) && is_declaration(entity)); - - declaration_t *const prev_decl = &previous_entity->declaration; - declaration_t *const decl = &entity->declaration; + if (previous_entity->base.parent_scope == current_scope) { + if (previous_entity->kind != entity->kind) { + if (!is_error_entity(previous_entity) && !is_error_entity(entity)) { + error_redefined_as_different_kind(pos, previous_entity, + entity->kind); + } + goto finish; + } + if (previous_entity->kind == ENTITY_ENUM_VALUE) { + errorf(pos, "redeclaration of enum entry '%Y' (declared %P)", + symbol, &previous_entity->base.source_position); + goto finish; + } + if (previous_entity->kind == ENTITY_TYPEDEF) { + /* TODO: C++ allows this for exactly the same type */ + errorf(pos, "redefinition of typedef '%Y' (declared %P)", + symbol, &previous_entity->base.source_position); + goto finish; + } - /* can happen for K&R style declarations */ - if (prev_decl->type == NULL && - previous_entity->kind == ENTITY_PARAMETER && - entity->kind == ENTITY_PARAMETER) { - prev_decl->type = decl->type; - prev_decl->storage_class = decl->storage_class; - prev_decl->declared_storage_class = decl->declared_storage_class; - prev_decl->modifiers = decl->modifiers; - prev_decl->deprecated_string = decl->deprecated_string; - return previous_entity; - } + /* at this point we should have only VARIABLES or FUNCTIONS */ + assert(is_declaration(previous_entity) && is_declaration(entity)); + + declaration_t *const prev_decl = &previous_entity->declaration; + declaration_t *const decl = &entity->declaration; + + /* can happen for K&R style declarations */ + if (prev_decl->type == NULL && + previous_entity->kind == ENTITY_PARAMETER && + entity->kind == ENTITY_PARAMETER) { + prev_decl->type = decl->type; + prev_decl->storage_class = decl->storage_class; + prev_decl->declared_storage_class = decl->declared_storage_class; + prev_decl->modifiers = decl->modifiers; + prev_decl->deprecated_string = decl->deprecated_string; + return previous_entity; + } - type_t *const orig_type = decl->type; - assert(orig_type != NULL); - type_t *const type = skip_typeref(orig_type); - type_t * prev_type = skip_typeref(prev_decl->type); + type_t *const orig_type = decl->type; + assert(orig_type != NULL); + type_t *const type = skip_typeref(orig_type); + type_t *const prev_type = skip_typeref(prev_decl->type); - if (!types_compatible(type, prev_type)) { - errorf(pos, - "declaration '%#T' is incompatible with '%#T' (declared %P)", - orig_type, symbol, prev_decl->type, symbol, - &previous_entity->base.source_position); - } else { - unsigned old_storage_class = prev_decl->storage_class; - if (warning.redundant_decls && - is_definition && - !prev_decl->used && - !(prev_decl->modifiers & DM_USED) && - prev_decl->storage_class == STORAGE_CLASS_STATIC) { - warningf(&previous_entity->base.source_position, - "unnecessary static forward declaration for '%#T'", - prev_decl->type, symbol); - } - - unsigned new_storage_class = decl->storage_class; - if (is_type_incomplete(prev_type)) { - prev_decl->type = type; - prev_type = type; - } - - /* pretend no storage class means extern for function - * declarations (except if the previous declaration is neither - * none nor extern) */ - if (entity->kind == ENTITY_FUNCTION) { - if (prev_type->function.unspecified_parameters) { - prev_decl->type = type; - prev_type = type; + if (!types_compatible(type, prev_type)) { + errorf(pos, + "declaration '%#T' is incompatible with '%#T' (declared %P)", + orig_type, symbol, prev_decl->type, symbol, + &previous_entity->base.source_position); + } else { + unsigned old_storage_class = prev_decl->storage_class; + if (warning.redundant_decls && + is_definition && + !prev_decl->used && + !(prev_decl->modifiers & DM_USED) && + prev_decl->storage_class == STORAGE_CLASS_STATIC) { + warningf(&previous_entity->base.source_position, + "unnecessary static forward declaration for '%#T'", + prev_decl->type, symbol); } - switch (old_storage_class) { - case STORAGE_CLASS_NONE: - old_storage_class = STORAGE_CLASS_EXTERN; - /* FALLTHROUGH */ - - case STORAGE_CLASS_EXTERN: - if (is_definition) { - if (warning.missing_prototypes && - prev_type->function.unspecified_parameters && - !is_sym_main(symbol)) { - warningf(pos, "no previous prototype for '%#T'", - orig_type, symbol); - } - } else if (new_storage_class == STORAGE_CLASS_NONE) { - new_storage_class = STORAGE_CLASS_EXTERN; - } - break; + storage_class_t new_storage_class = decl->storage_class; + + /* pretend no storage class means extern for function + * declarations (except if the previous declaration is neither + * none nor extern) */ + if (entity->kind == ENTITY_FUNCTION) { + /* the previous declaration could have unspecified parameters or + * be a typedef, so use the new type */ + if (prev_type->function.unspecified_parameters || is_definition) + prev_decl->type = type; + + switch (old_storage_class) { + case STORAGE_CLASS_NONE: + old_storage_class = STORAGE_CLASS_EXTERN; + /* FALLTHROUGH */ + + case STORAGE_CLASS_EXTERN: + if (is_definition) { + if (warning.missing_prototypes && + prev_type->function.unspecified_parameters && + !is_sym_main(symbol)) { + warningf(pos, "no previous prototype for '%#T'", + orig_type, symbol); + } + } else if (new_storage_class == STORAGE_CLASS_NONE) { + new_storage_class = STORAGE_CLASS_EXTERN; + } + break; - default: - break; + default: + break; + } + } else if (is_type_incomplete(prev_type)) { + prev_decl->type = type; } - } - if (old_storage_class == STORAGE_CLASS_EXTERN && - new_storage_class == STORAGE_CLASS_EXTERN) { + if (old_storage_class == STORAGE_CLASS_EXTERN && + new_storage_class == STORAGE_CLASS_EXTERN) { warn_redundant_declaration: - if (!is_definition && - warning.redundant_decls && - is_type_valid(prev_type) && - strcmp(previous_entity->base.source_position.input_name, - "") != 0) { - warningf(pos, - "redundant declaration for '%Y' (declared %P)", - symbol, &previous_entity->base.source_position); - } - } else if (current_function == NULL) { - if (old_storage_class != STORAGE_CLASS_STATIC && - new_storage_class == STORAGE_CLASS_STATIC) { - errorf(pos, - "static declaration of '%Y' follows non-static declaration (declared %P)", - symbol, &previous_entity->base.source_position); - } else if (old_storage_class == STORAGE_CLASS_EXTERN) { - prev_decl->storage_class = STORAGE_CLASS_NONE; - prev_decl->declared_storage_class = STORAGE_CLASS_NONE; - } else { - /* ISO/IEC 14882:1998(E) §C.1.2:1 */ - if (c_mode & _CXX) - goto error_redeclaration; - goto warn_redundant_declaration; - } - } else if (is_type_valid(prev_type)) { - if (old_storage_class == new_storage_class) { + if (!is_definition && + warning.redundant_decls && + is_type_valid(prev_type) && + strcmp(previous_entity->base.source_position.input_name, + "") != 0) { + warningf(pos, + "redundant declaration for '%Y' (declared %P)", + symbol, &previous_entity->base.source_position); + } + } else if (current_function == NULL) { + if (old_storage_class != STORAGE_CLASS_STATIC && + new_storage_class == STORAGE_CLASS_STATIC) { + errorf(pos, + "static declaration of '%Y' follows non-static declaration (declared %P)", + symbol, &previous_entity->base.source_position); + } else if (old_storage_class == STORAGE_CLASS_EXTERN) { + prev_decl->storage_class = STORAGE_CLASS_NONE; + prev_decl->declared_storage_class = STORAGE_CLASS_NONE; + } else { + /* ISO/IEC 14882:1998(E) §C.1.2:1 */ + if (c_mode & _CXX) + goto error_redeclaration; + goto warn_redundant_declaration; + } + } else if (is_type_valid(prev_type)) { + if (old_storage_class == new_storage_class) { error_redeclaration: - errorf(pos, "redeclaration of '%Y' (declared %P)", - symbol, &previous_entity->base.source_position); - } else { - errorf(pos, - "redeclaration of '%Y' with different linkage (declared %P)", - symbol, &previous_entity->base.source_position); + errorf(pos, "redeclaration of '%Y' (declared %P)", + symbol, &previous_entity->base.source_position); + } else { + errorf(pos, + "redeclaration of '%Y' with different linkage (declared %P)", + symbol, &previous_entity->base.source_position); + } } } + + prev_decl->modifiers |= decl->modifiers; + if (entity->kind == ENTITY_FUNCTION) { + previous_entity->function.is_inline |= entity->function.is_inline; + } + return previous_entity; } - prev_decl->modifiers |= decl->modifiers; - if (entity->kind == ENTITY_FUNCTION) { - previous_entity->function.is_inline |= entity->function.is_inline; + if (warning.shadow) { + warningf(pos, "%s '%Y' shadows %s (declared %P)", + get_entity_kind_name(entity->kind), symbol, + get_entity_kind_name(previous_entity->kind), + &previous_entity->base.source_position); } - return previous_entity; } if (entity->kind == ENTITY_FUNCTION) { @@ -5296,7 +5303,7 @@ static void parse_init_declarator_rest(entity_t *entity) current_init_decl = NULL; if (entity->kind == ENTITY_VARIABLE) { - /* § 6.7.5:22 array initializers for arrays with unknown size + /* §6.7.5:22 array initializers for arrays with unknown size * determine the array type size */ declaration->type = env.type; entity->variable.initializer = initializer; @@ -5354,11 +5361,9 @@ static void check_variable_type_complete(entity_t *ent) if (!is_type_incomplete(type)) return; - /* GCC allows global arrays without size and assigns them a length of one, - * if no different declaration follows */ - if (is_type_array(type) && - c_mode & _GNUC && - ent->base.parent_scope == file_scope) { + /* §6.9.2:2 and §6.9.2:5: At the end of the translation incomplete arrays + * are given length one. */ + if (is_type_array(type) && ent->base.parent_scope == file_scope) { ARR_APP1(declaration_t*, incomplete_arrays, decl); return; } @@ -5461,7 +5466,7 @@ static type_t *get_default_promoted_type(type_t *orig_type) type_t *type = skip_typeref(orig_type); if (is_type_integer(type)) { result = promote_integer(type); - } else if (type == type_float) { + } else if (is_type_atomic(type, ATOMIC_TYPE_FLOAT)) { result = type_double; } @@ -5522,6 +5527,9 @@ decl_list_end: parameter = entity->function.parameters.entities; for (; parameter != NULL; parameter = parameter->base.next) { + if (parameter->kind != ENTITY_PARAMETER) + continue; + type_t *parameter_type = parameter->declaration.type; if (parameter_type == NULL) { if (strict_mode) { @@ -5558,7 +5566,7 @@ decl_list_end: last_parameter = function_parameter; } - /* § 6.9.1.7: A K&R style parameter list does NOT act as a function + /* §6.9.1.7: A K&R style parameter list does NOT act as a function * prototype */ new_type->function.parameters = parameters; new_type->function.unspecified_parameters = true; @@ -5736,9 +5744,8 @@ static bool expression_returns(expression_t const *const expr) case EXPR_SIZEOF: // TODO handle obscure VLA case case EXPR_ALIGNOF: case EXPR_FUNCNAME: - case EXPR_BUILTIN_SYMBOL: case EXPR_BUILTIN_CONSTANT_P: - case EXPR_BUILTIN_PREFETCH: + case EXPR_BUILTIN_TYPES_COMPATIBLE_P: case EXPR_OFFSETOF: case EXPR_INVALID: return true; @@ -6381,7 +6388,7 @@ static void parse_external_declaration(void) ndeclaration->base.symbol); } - /* § 6.7.5.3:14 a function definition with () means no + /* §6.7.5.3:14 a function definition with () means no * parameters (and not unspecified parameters) */ if (type->function.unspecified_parameters && type->function.parameters == NULL && @@ -6894,6 +6901,19 @@ static type_t *make_function_1_type(type_t *return_type, type_t *argument_type) return identify_new_type(type); } +static type_t *make_function_1_type_variadic(type_t *return_type, type_t *argument_type) +{ + type_t *res = make_function_1_type(return_type, argument_type); + res->function.variadic = 1; + return res; +} + +/** + * Creates a return_type (func)(void) function type if not + * already exists. + * + * @param return_type the return type + */ static type_t *make_function_0_type(type_t *return_type) { type_t *type = allocate_type_zero(TYPE_FUNCTION); @@ -6904,40 +6924,24 @@ static type_t *make_function_0_type(type_t *return_type) } /** - * Creates a function type for some function like builtins. + * Creates a NO_RETURN return_type (func)(void) function type if not + * already exists. * - * @param symbol the symbol describing the builtin - */ -static type_t *get_builtin_symbol_type(symbol_t *symbol) -{ - switch (symbol->ID) { - case T___builtin_alloca: - return make_function_1_type(type_void_ptr, type_size_t); - case T___builtin_huge_val: - return make_function_0_type(type_double); - case T___builtin_inf: - return make_function_0_type(type_double); - case T___builtin_inff: - return make_function_0_type(type_float); - case T___builtin_infl: - return make_function_0_type(type_long_double); - case T___builtin_nan: - return make_function_1_type(type_double, type_char_ptr); - case T___builtin_nanf: - return make_function_1_type(type_float, type_char_ptr); - case T___builtin_nanl: - return make_function_1_type(type_long_double, type_char_ptr); - case T___builtin_va_end: - return make_function_1_type(type_void, type_valist); - case T___builtin_expect: - return make_function_2_type(type_long, type_long, type_long); - default: - internal_errorf(HERE, "not implemented builtin identifier found"); - } + * @param return_type the return type + */ +static type_t *make_function_0_type_noreturn(type_t *return_type) +{ + type_t *type = allocate_type_zero(TYPE_FUNCTION); + type->function.return_type = return_type; + type->function.parameters = NULL; + type->function.base.modifiers |= DM_NORETURN; + return type; + + return identify_new_type(type); } /** - * Performs automatic type cast as described in § 6.3.2.1. + * Performs automatic type cast as described in §6.3.2.1. * * @param orig_type the original type */ @@ -6961,7 +6965,7 @@ static type_t *automatic_type_conversion(type_t *orig_type) /** * reverts the automatic casts of array to pointer types and function - * to function-pointer types as defined § 6.3.2.1 + * to function-pointer types as defined §6.3.2.1 */ type_t *revert_automatic_type_conversion(const expression_t *expression) { @@ -6993,9 +6997,6 @@ type_t *revert_automatic_type_conversion(const expression_t *expression) return type->pointer.points_to; } - case EXPR_BUILTIN_SYMBOL: - return get_builtin_symbol_type(expression->builtin_symbol.symbol); - case EXPR_ARRAY_ACCESS: { const expression_t *array_ref = expression->array_access.array_ref; type_t *type_left = skip_typeref(array_ref->base.type); @@ -7495,24 +7496,8 @@ end_error: return create_invalid_expression(); } -static expression_t *parse_builtin_symbol(void) -{ - expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_SYMBOL); - - symbol_t *symbol = token.v.symbol; - - expression->builtin_symbol.symbol = symbol; - next_token(); - - type_t *type = get_builtin_symbol_type(symbol); - type = automatic_type_conversion(type); - - expression->base.type = type; - return expression; -} - /** - * Parses a __builtin_constant() expression. + * Parses a __builtin_constant_p() expression. */ static expression_t *parse_builtin_constant(void) { @@ -7533,28 +7518,24 @@ end_error: } /** - * Parses a __builtin_prefetch() expression. + * Parses a __builtin_types_compatible_p() expression. */ -static expression_t *parse_builtin_prefetch(void) +static expression_t *parse_builtin_types_compatible(void) { - expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_PREFETCH); + expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_TYPES_COMPATIBLE_P); - eat(T___builtin_prefetch); + eat(T___builtin_types_compatible_p); expect('(', end_error); add_anchor_token(')'); - expression->builtin_prefetch.adr = parse_assignment_expression(); - if (token.type == ',') { - next_token(); - expression->builtin_prefetch.rw = parse_assignment_expression(); - } - if (token.type == ',') { - next_token(); - expression->builtin_prefetch.locality = parse_assignment_expression(); - } + add_anchor_token(','); + expression->builtin_types_compatible.left = parse_typename(); + rem_anchor_token(','); + expect(',', end_error); + expression->builtin_types_compatible.right = parse_typename(); rem_anchor_token(')'); expect(')', end_error); - expression->base.type = type_void; + expression->base.type = type_int; return expression; end_error: @@ -7773,49 +7754,39 @@ end_error: static expression_t *parse_primary_expression(void) { switch (token.type) { - case T_false: return parse_bool_const(false); - case T_true: return parse_bool_const(true); - case T_INTEGER: return parse_int_const(); - case T_CHARACTER_CONSTANT: return parse_character_constant(); - case T_WIDE_CHARACTER_CONSTANT: return parse_wide_character_constant(); - case T_FLOATINGPOINT: return parse_float_const(); + case T_false: return parse_bool_const(false); + case T_true: return parse_bool_const(true); + case T_INTEGER: return parse_int_const(); + case T_CHARACTER_CONSTANT: return parse_character_constant(); + case T_WIDE_CHARACTER_CONSTANT: return parse_wide_character_constant(); + case T_FLOATINGPOINT: return parse_float_const(); case T_STRING_LITERAL: - case T_WIDE_STRING_LITERAL: return parse_string_const(); - case T_IDENTIFIER: return parse_reference(); + case T_WIDE_STRING_LITERAL: return parse_string_const(); + case T_IDENTIFIER: return parse_reference(); case T___FUNCTION__: - case T___func__: return parse_function_keyword(); - case T___PRETTY_FUNCTION__: return parse_pretty_function_keyword(); - case T___FUNCSIG__: return parse_funcsig_keyword(); - case T___FUNCDNAME__: return parse_funcdname_keyword(); - case T___builtin_offsetof: return parse_offsetof(); - case T___builtin_va_start: return parse_va_start(); - case T___builtin_va_arg: return parse_va_arg(); - case T___builtin_expect: - case T___builtin_alloca: - case T___builtin_inf: - case T___builtin_inff: - case T___builtin_infl: - case T___builtin_nan: - case T___builtin_nanf: - case T___builtin_nanl: - case T___builtin_huge_val: - case T___builtin_va_end: return parse_builtin_symbol(); + case T___func__: return parse_function_keyword(); + case T___PRETTY_FUNCTION__: return parse_pretty_function_keyword(); + case T___FUNCSIG__: return parse_funcsig_keyword(); + case T___FUNCDNAME__: return parse_funcdname_keyword(); + case T___builtin_offsetof: return parse_offsetof(); + case T___builtin_va_start: return parse_va_start(); + case T___builtin_va_arg: return parse_va_arg(); case T___builtin_isgreater: case T___builtin_isgreaterequal: case T___builtin_isless: case T___builtin_islessequal: case T___builtin_islessgreater: - case T___builtin_isunordered: return parse_compare_builtin(); - case T___builtin_constant_p: return parse_builtin_constant(); - case T___builtin_prefetch: return parse_builtin_prefetch(); - case T__assume: return parse_assume(); + case T___builtin_isunordered: return parse_compare_builtin(); + case T___builtin_constant_p: return parse_builtin_constant(); + case T___builtin_types_compatible_p: return parse_builtin_types_compatible(); + case T__assume: return parse_assume(); case T_ANDAND: if (GNU_MODE) return parse_label_address(); break; - case '(': return parse_parenthesized_expression(); - case T___noop: return parse_noop_expression(); + case '(': return parse_parenthesized_expression(); + case T___noop: return parse_noop_expression(); } errorf(HERE, "unexpected token %K, expected an expression", &token); @@ -8091,6 +8062,51 @@ static void check_call_argument(const function_parameter_t *parameter, } } +/** + * Handle the semantic restrictions of builtin calls + */ +static void handle_builtin_argument_restrictions(call_expression_t *call) { + switch (call->function->reference.entity->function.btk) { + case bk_gnu_builtin_return_address: + case bk_gnu_builtin_frame_address: { + /* argument must be constant */ + call_argument_t *argument = call->arguments; + + if (! is_constant_expression(argument->expression)) { + errorf(&call->base.source_position, + "argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); + } + break; + } + case bk_gnu_builtin_prefetch: { + /* second and third argument must be constant if existent */ + call_argument_t *rw = call->arguments->next; + call_argument_t *locality = NULL; + + if (rw != NULL) { + if (! is_constant_expression(rw->expression)) { + errorf(&call->base.source_position, + "second argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); + } + locality = rw->next; + } + if (locality != NULL) { + if (! is_constant_expression(locality->expression)) { + errorf(&call->base.source_position, + "third argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); + } + locality = rw->next; + } + break; + } + default: + break; + } +} + /** * Parse a call expression, ie. expression '( ... )'. * @@ -8183,6 +8199,13 @@ static expression_t *parse_call_expression(expression_t *expression) "function call has aggregate value"); } + if (call->function->kind == EXPR_REFERENCE) { + reference_expression_t *reference = &call->function->reference; + if (reference->entity->kind == ENTITY_FUNCTION && + reference->entity->function.btk != bk_none) + handle_builtin_argument_restrictions(call); + } + end_error: return result; } @@ -8772,7 +8795,7 @@ static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right) type_left = get_unqualified_type(type_left); type_right = get_unqualified_type(type_right); - /* § 6.3.1.8 Usual arithmetic conversions */ + /* §6.3.1.8 Usual arithmetic conversions */ if (type_left == type_long_double || type_right == type_long_double) { return type_long_double; } else if (type_left == type_double || type_right == type_double) { @@ -8874,7 +8897,8 @@ static void warn_div_by_zero(binary_expression_t const *const expression) /** * Check the semantic restrictions for a div/mod expression. */ -static void semantic_divmod_arithmetic(binary_expression_t *expression) { +static void semantic_divmod_arithmetic(binary_expression_t *expression) +{ semantic_binexpr_arithmetic(expression); warn_div_by_zero(expression); } @@ -8935,7 +8959,7 @@ static void semantic_add(binary_expression_t *expression) type_t *const type_left = skip_typeref(orig_type_left); type_t *const type_right = skip_typeref(orig_type_right); - /* § 6.5.6 */ + /* §6.5.6 */ if (is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { type_t *arithmetic_type = semantic_arithmetic(type_left, type_right); expression->left = create_implicit_cast(left, arithmetic_type); @@ -8966,7 +8990,7 @@ static void semantic_sub(binary_expression_t *expression) type_t *const type_right = skip_typeref(orig_type_right); source_position_t const *const pos = &expression->base.source_position; - /* § 5.6.5 */ + /* §5.6.5 */ if (is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { type_t *arithmetic_type = semantic_arithmetic(type_left, type_right); expression->left = create_implicit_cast(left, arithmetic_type); @@ -9310,64 +9334,65 @@ static void semantic_binexpr_assign(binary_expression_t *expression) static bool expression_has_effect(const expression_t *const expr) { switch (expr->kind) { - case EXPR_UNKNOWN: break; - case EXPR_INVALID: return true; /* do NOT warn */ - case EXPR_REFERENCE: return false; - case EXPR_REFERENCE_ENUM_VALUE: return false; + case EXPR_UNKNOWN: break; + case EXPR_INVALID: return true; /* do NOT warn */ + case EXPR_REFERENCE: return false; + case EXPR_REFERENCE_ENUM_VALUE: return false; /* suppress the warning for microsoft __noop operations */ - case EXPR_CONST: return expr->conste.is_ms_noop; - case EXPR_CHARACTER_CONSTANT: return false; - case EXPR_WIDE_CHARACTER_CONSTANT: return false; - case EXPR_STRING_LITERAL: return false; - case EXPR_WIDE_STRING_LITERAL: return false; - case EXPR_LABEL_ADDRESS: return false; + case EXPR_CONST: return expr->conste.is_ms_noop; + case EXPR_CHARACTER_CONSTANT: return false; + case EXPR_WIDE_CHARACTER_CONSTANT: return false; + case EXPR_STRING_LITERAL: return false; + case EXPR_WIDE_STRING_LITERAL: return false; + case EXPR_LABEL_ADDRESS: return false; case EXPR_CALL: { const call_expression_t *const call = &expr->call; - if (call->function->kind != EXPR_BUILTIN_SYMBOL) + if (call->function->kind != EXPR_REFERENCE) return true; - switch (call->function->builtin_symbol.symbol->ID) { - case T___builtin_va_end: return true; - default: return false; + switch (call->function->reference.entity->function.btk) { + case bk_gnu_builtin_prefetch: + case bk_gnu_builtin_va_end: return true; + default: return false; } } /* Generate the warning if either the left or right hand side of a * conditional expression has no effect */ case EXPR_CONDITIONAL: { - const conditional_expression_t *const cond = &expr->conditional; + conditional_expression_t const *const cond = &expr->conditional; + expression_t const *const t = cond->true_expression; return - expression_has_effect(cond->true_expression) && + (t == NULL || expression_has_effect(t)) && expression_has_effect(cond->false_expression); } - case EXPR_SELECT: return false; - case EXPR_ARRAY_ACCESS: return false; - case EXPR_SIZEOF: return false; - case EXPR_CLASSIFY_TYPE: return false; - case EXPR_ALIGNOF: return false; - - case EXPR_FUNCNAME: return false; - case EXPR_BUILTIN_SYMBOL: break; /* handled in EXPR_CALL */ - case EXPR_BUILTIN_CONSTANT_P: return false; - case EXPR_BUILTIN_PREFETCH: return true; - case EXPR_OFFSETOF: return false; - case EXPR_VA_START: return true; - case EXPR_VA_ARG: return true; - case EXPR_STATEMENT: return true; // TODO - case EXPR_COMPOUND_LITERAL: return false; - - case EXPR_UNARY_NEGATE: return false; - case EXPR_UNARY_PLUS: return false; - case EXPR_UNARY_BITWISE_NEGATE: return false; - case EXPR_UNARY_NOT: return false; - case EXPR_UNARY_DEREFERENCE: return false; - case EXPR_UNARY_TAKE_ADDRESS: return false; - case EXPR_UNARY_POSTFIX_INCREMENT: return true; - case EXPR_UNARY_POSTFIX_DECREMENT: return true; - case EXPR_UNARY_PREFIX_INCREMENT: return true; - case EXPR_UNARY_PREFIX_DECREMENT: return true; + case EXPR_SELECT: return false; + case EXPR_ARRAY_ACCESS: return false; + case EXPR_SIZEOF: return false; + case EXPR_CLASSIFY_TYPE: return false; + case EXPR_ALIGNOF: return false; + + case EXPR_FUNCNAME: return false; + case EXPR_BUILTIN_CONSTANT_P: return false; + case EXPR_BUILTIN_TYPES_COMPATIBLE_P: return false; + case EXPR_OFFSETOF: return false; + case EXPR_VA_START: return true; + case EXPR_VA_ARG: return true; + case EXPR_STATEMENT: return true; // TODO + case EXPR_COMPOUND_LITERAL: return false; + + case EXPR_UNARY_NEGATE: return false; + case EXPR_UNARY_PLUS: return false; + case EXPR_UNARY_BITWISE_NEGATE: return false; + case EXPR_UNARY_NOT: return false; + case EXPR_UNARY_DEREFERENCE: return false; + case EXPR_UNARY_TAKE_ADDRESS: return false; + case EXPR_UNARY_POSTFIX_INCREMENT: return true; + case EXPR_UNARY_POSTFIX_DECREMENT: return true; + case EXPR_UNARY_PREFIX_INCREMENT: return true; + case EXPR_UNARY_PREFIX_DECREMENT: return true; /* Treat void casts as if they have an effect in order to being able to * suppress the warning */ @@ -9376,39 +9401,39 @@ static bool expression_has_effect(const expression_t *const expr) return is_type_atomic(type, ATOMIC_TYPE_VOID); } - case EXPR_UNARY_CAST_IMPLICIT: return true; - case EXPR_UNARY_ASSUME: return true; - case EXPR_UNARY_DELETE: return true; - case EXPR_UNARY_DELETE_ARRAY: return true; - case EXPR_UNARY_THROW: return true; - - case EXPR_BINARY_ADD: return false; - case EXPR_BINARY_SUB: return false; - case EXPR_BINARY_MUL: return false; - case EXPR_BINARY_DIV: return false; - case EXPR_BINARY_MOD: return false; - case EXPR_BINARY_EQUAL: return false; - case EXPR_BINARY_NOTEQUAL: return false; - case EXPR_BINARY_LESS: return false; - case EXPR_BINARY_LESSEQUAL: return false; - case EXPR_BINARY_GREATER: return false; - case EXPR_BINARY_GREATEREQUAL: return false; - case EXPR_BINARY_BITWISE_AND: return false; - case EXPR_BINARY_BITWISE_OR: return false; - case EXPR_BINARY_BITWISE_XOR: return false; - case EXPR_BINARY_SHIFTLEFT: return false; - case EXPR_BINARY_SHIFTRIGHT: return false; - case EXPR_BINARY_ASSIGN: return true; - case EXPR_BINARY_MUL_ASSIGN: return true; - case EXPR_BINARY_DIV_ASSIGN: return true; - case EXPR_BINARY_MOD_ASSIGN: return true; - case EXPR_BINARY_ADD_ASSIGN: return true; - case EXPR_BINARY_SUB_ASSIGN: return true; - case EXPR_BINARY_SHIFTLEFT_ASSIGN: return true; - case EXPR_BINARY_SHIFTRIGHT_ASSIGN: return true; - case EXPR_BINARY_BITWISE_AND_ASSIGN: return true; - case EXPR_BINARY_BITWISE_XOR_ASSIGN: return true; - case EXPR_BINARY_BITWISE_OR_ASSIGN: return true; + case EXPR_UNARY_CAST_IMPLICIT: return true; + case EXPR_UNARY_ASSUME: return true; + case EXPR_UNARY_DELETE: return true; + case EXPR_UNARY_DELETE_ARRAY: return true; + case EXPR_UNARY_THROW: return true; + + case EXPR_BINARY_ADD: return false; + case EXPR_BINARY_SUB: return false; + case EXPR_BINARY_MUL: return false; + case EXPR_BINARY_DIV: return false; + case EXPR_BINARY_MOD: return false; + case EXPR_BINARY_EQUAL: return false; + case EXPR_BINARY_NOTEQUAL: return false; + case EXPR_BINARY_LESS: return false; + case EXPR_BINARY_LESSEQUAL: return false; + case EXPR_BINARY_GREATER: return false; + case EXPR_BINARY_GREATEREQUAL: return false; + case EXPR_BINARY_BITWISE_AND: return false; + case EXPR_BINARY_BITWISE_OR: return false; + case EXPR_BINARY_BITWISE_XOR: return false; + case EXPR_BINARY_SHIFTLEFT: return false; + case EXPR_BINARY_SHIFTRIGHT: return false; + case EXPR_BINARY_ASSIGN: return true; + case EXPR_BINARY_MUL_ASSIGN: return true; + case EXPR_BINARY_DIV_ASSIGN: return true; + case EXPR_BINARY_MOD_ASSIGN: return true; + case EXPR_BINARY_ADD_ASSIGN: return true; + case EXPR_BINARY_SUB_ASSIGN: return true; + case EXPR_BINARY_SHIFTLEFT_ASSIGN: return true; + case EXPR_BINARY_SHIFTRIGHT_ASSIGN: return true; + case EXPR_BINARY_BITWISE_AND_ASSIGN: return true; + case EXPR_BINARY_BITWISE_XOR_ASSIGN: return true; + case EXPR_BINARY_BITWISE_OR_ASSIGN: return true; /* Only examine the right hand side of && and ||, because the left hand * side already has the effect of controlling the execution of the right @@ -9420,12 +9445,12 @@ static bool expression_has_effect(const expression_t *const expr) case EXPR_BINARY_COMMA: return expression_has_effect(expr->binary.right); - case EXPR_BINARY_ISGREATER: return false; - case EXPR_BINARY_ISGREATEREQUAL: return false; - case EXPR_BINARY_ISLESS: return false; - case EXPR_BINARY_ISLESSEQUAL: return false; - case EXPR_BINARY_ISLESSGREATER: return false; - case EXPR_BINARY_ISUNORDERED: return false; + case EXPR_BINARY_ISGREATER: return false; + case EXPR_BINARY_ISGREATEREQUAL: return false; + case EXPR_BINARY_ISLESS: return false; + case EXPR_BINARY_ISLESSEQUAL: return false; + case EXPR_BINARY_ISLESSGREATER: return false; + case EXPR_BINARY_ISUNORDERED: return false; } internal_errorf(HERE, "unexpected expression"); @@ -10079,7 +10104,8 @@ end_error: * * @param statement the switch statement to check */ -static void check_enum_cases(const switch_statement_t *statement) { +static void check_enum_cases(const switch_statement_t *statement) +{ const type_t *type = skip_typeref(statement->expression->base.type); if (! is_type_enum(type)) return; @@ -10572,12 +10598,11 @@ static statement_t *parse_declaration_statement(void) parse_declaration(record_entity, DECL_FLAGS_NONE); } - if (before == NULL) { - statement->declaration.declarations_begin = current_scope->entities; - } else { - statement->declaration.declarations_begin = before->base.next; - } - statement->declaration.declarations_end = current_scope->last_entity; + declaration_statement_t *const decl = &statement->declaration; + entity_t *const begin = + before != NULL ? before->base.next : current_scope->entities; + decl->declarations_begin = begin; + decl->declarations_end = begin != NULL ? current_scope->last_entity : NULL; return statement; } @@ -10717,10 +10742,13 @@ static void parse_namespace_definition(void) next_token(); entity = get_entity(symbol, NAMESPACE_NORMAL); - if (entity != NULL && entity->kind != ENTITY_NAMESPACE - && entity->base.parent_scope == current_scope) { - error_redefined_as_different_kind(&token.source_position, - entity, ENTITY_NAMESPACE); + if (entity != NULL && + entity->kind != ENTITY_NAMESPACE && + entity->base.parent_scope == current_scope) { + if (!is_error_entity(entity)) { + error_redefined_as_different_kind(&token.source_position, + entity, ENTITY_NAMESPACE); + } entity = NULL; } } @@ -11341,6 +11369,10 @@ void start_parsing(void) assert(current_scope == NULL); scope_push(&unit->scope); + + create_gnu_builtins(); + if (c_mode & _MS) + create_microsoft_intrinsics(); } translation_unit_t *finish_parsing(void) @@ -11360,8 +11392,8 @@ translation_unit_t *finish_parsing(void) return result; } -/* GCC allows global arrays without size and assigns them a length of one, - * if no different declaration follows */ +/* §6.9.2:2 and §6.9.2:5: At the end of the translation incomplete arrays + * are given length one. */ static void complete_incomplete_arrays(void) { size_t n = ARR_LEN(incomplete_arrays); @@ -11404,6 +11436,84 @@ void parse(void) incomplete_arrays = NULL; } +/** + * create a builtin function. + */ +static entity_t *create_builtin_function(builtin_kind_t kind, const char *name, type_t *function_type) +{ + symbol_t *symbol = symbol_table_insert(name); + entity_t *entity = allocate_entity_zero(ENTITY_FUNCTION); + entity->declaration.storage_class = STORAGE_CLASS_EXTERN; + entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN; + entity->declaration.type = function_type; + entity->declaration.implicit = true; + entity->base.symbol = symbol; + entity->base.source_position = builtin_source_position; + + entity->function.btk = kind; + + record_entity(entity, /*is_definition=*/false); + return entity; +} + + +/** + * Create predefined gnu builtins. + */ +static void create_gnu_builtins(void) { +#define _STR(a) #a +#define STR(a) _STR(a) +#define CONCAT(a,b) a##b +#define GNU_BUILTIN_NAME(a) STR(CONCAT(__builtin_, a)) +#define GNU_BUILTIN(a, b) create_builtin_function(CONCAT(bk_gnu_builtin_, a), GNU_BUILTIN_NAME(a), b) + + GNU_BUILTIN(alloca, make_function_1_type(type_void_ptr, type_size_t)); + GNU_BUILTIN(huge_val, make_function_0_type(type_double)); + GNU_BUILTIN(inf, make_function_0_type(type_double)); + GNU_BUILTIN(inff, make_function_0_type(type_float)); + GNU_BUILTIN(infl, make_function_0_type(type_long_double)); + GNU_BUILTIN(nan, make_function_1_type(type_double, type_char_ptr)); + GNU_BUILTIN(nanf, make_function_1_type(type_float, type_char_ptr)); + GNU_BUILTIN(nanl, make_function_1_type(type_long_double, type_char_ptr)); + GNU_BUILTIN(va_end, make_function_1_type(type_void, type_valist)); + GNU_BUILTIN(expect, make_function_2_type(type_long, type_long, type_long)); + GNU_BUILTIN(return_address, make_function_1_type(type_void_ptr, type_unsigned_int)); + GNU_BUILTIN(frame_address, make_function_1_type(type_void_ptr, type_unsigned_int)); + GNU_BUILTIN(ffs, make_function_1_type(type_int, type_unsigned_int)); + GNU_BUILTIN(clz, make_function_1_type(type_int, type_unsigned_int)); + GNU_BUILTIN(ctz, make_function_1_type(type_int, type_unsigned_int)); + GNU_BUILTIN(popcount, make_function_1_type(type_int, type_unsigned_int)); + GNU_BUILTIN(parity, make_function_1_type(type_int, type_unsigned_int)); + GNU_BUILTIN(prefetch, make_function_1_type_variadic(type_float, type_void_ptr)); + GNU_BUILTIN(trap, make_function_0_type_noreturn(type_void)); + +#undef GNU_BUILTIN +#undef GNU_BUILTIN_NAME +#undef CONCAT +#undef STR +#undef _STR +} + +/** + * Create predefined MS intrinsics. + */ +static void create_microsoft_intrinsics(void) { +#define _STR(a) #a +#define STR(a) _STR(a) +#define CONCAT(a,b) a##b +#define MS_BUILTIN(a, b) create_builtin_function(CONCAT(bk_ms, a), STR(a), b) + + MS_BUILTIN(__debugbreak, make_function_0_type(type_void)); + MS_BUILTIN(_ReturnAddress, make_function_0_type(type_void_ptr)); + MS_BUILTIN(__popcount, make_function_1_type(type_unsigned_int, type_unsigned_int)); + MS_BUILTIN(__ud2, make_function_0_type_noreturn(type_void)); + +#undef MS_BUILTIN +#undef CONCAT +#undef STR +#undef _STR +} + /** * Initialize the parser. */