source_position_t source_position;
unsigned char storage_class;
bool is_inline;
+ decl_modifiers_t decl_modifiers;
type_t *type;
};
case T_const: \
case T_restrict: \
case T_volatile: \
- case T_inline:
+ case T_inline: \
+ case T_forceinline:
#ifdef PROVIDE_COMPLEX
#define COMPLEX_SPECIFIERS \
print_type_quoted(previous_declaration->type);
fputc('\n', stderr);
} else {
- unsigned old_storage_class = previous_declaration->storage_class;
- unsigned new_storage_class = declaration->storage_class;
+ unsigned old_storage_class = previous_declaration->storage_class;
+ unsigned new_storage_class = declaration->storage_class;
+ type_t *type = previous_declaration->type;
+ type = skip_typeref(type);
+
if (current_function == NULL) {
if (old_storage_class != STORAGE_CLASS_STATIC &&
new_storage_class == STORAGE_CLASS_STATIC) {
if (new_storage_class == STORAGE_CLASS_NONE) {
previous_declaration->storage_class = STORAGE_CLASS_NONE;
}
- } else {
+ } else if(!is_type_function(type)) {
parser_print_warning_prefix_pos(declaration->source_position);
fprintf(stderr, "redundant declaration for '%s'\n",
symbol->string);
static expression_t *parse_constant_expression(void)
{
/* start parsing at precedence 7 (conditional expression) */
- return parse_sub_expression(7);
+ expression_t *result = parse_sub_expression(7);
+
+ if(!is_constant_expression(result)) {
+ parser_print_error_prefix_pos(result->base.source_position);
+ fprintf(stderr, "expression '");
+ print_expression(result);
+ fprintf(stderr, "' is not constant\n");
+ }
+
+ return result;
}
static expression_t *parse_assignment_expression(void)
MATCH_SPECIFIER(T__Complex, SPECIFIER_COMPLEX, "_Complex")
MATCH_SPECIFIER(T__Imaginary, SPECIFIER_IMAGINARY, "_Imaginary")
#endif
+ case T_forceinline:
+ /* only in microsoft mode */
+ specifiers->decl_modifiers |= DM_FORCEINLINE;
+
case T_inline:
next_token();
specifiers->is_inline = true;
parse_declaration_specifiers(&specifiers);
- declaration_t *declaration = parse_declarator(&specifiers, true);
+ declaration_t *declaration = parse_declarator(&specifiers, /*may_be_abstract=*/true);
semantic_parameter(declaration);
static declaration_t *parse_declarator(
const declaration_specifiers_t *specifiers, bool may_be_abstract)
{
- type_t *type = specifiers->type;
- declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
- declaration->storage_class = specifiers->storage_class;
- declaration->is_inline = specifiers->is_inline;
+ type_t *type = specifiers->type;
+ declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
+ declaration->storage_class = specifiers->storage_class;
+ declaration->decl_modifiers = specifiers->decl_modifiers;
+ declaration->is_inline = specifiers->is_inline;
construct_type_t *construct_type
= parse_inner_declarator(declaration, may_be_abstract);
break;
eat(',');
- ndeclaration = parse_declarator(specifiers, false);
+ ndeclaration = parse_declarator(specifiers, /*may_be_abstract=*/false);
}
expect_void(';');
}
if(token.type == ';') {
parse_anonymous_declaration_rest(&specifiers, finished_declaration);
} else {
- declaration_t *declaration = parse_declarator(&specifiers, false);
+ declaration_t *declaration = parse_declarator(&specifiers, /*may_be_abstract=*/false);
parse_declaration_rest(declaration, &specifiers, finished_declaration);
}
}
static void parse_kr_declaration_list(declaration_t *declaration)
{
type_t *type = skip_typeref(declaration->type);
- assert(is_type_function(type));
+ if(!is_type_function(type))
+ return;
if(!type->function.kr_style_parameters)
return;
}
/* declarator is common to both function-definitions and declarations */
- declaration_t *ndeclaration = parse_declarator(&specifiers, false);
+ declaration_t *ndeclaration = parse_declarator(&specifiers, /*may_be_abstract=*/false);
/* must be a declaration */
if(token.type == ',' || token.type == '=' || token.type == ';') {
parse_constant_expression();
/* TODO (bitfields) */
} else {
- declaration_t *declaration = parse_declarator(specifiers, true);
+ declaration_t *declaration = parse_declarator(specifiers, /*may_be_abstract=*/true);
/* TODO: check constraints for struct declarations */
/* TODO: check for doubled fields */
expression->expression.type = EXPR_FUNCTION;
expression->expression.datatype = type_string;
- expression->value = "TODO: FUNCTION";
+ expression->value = current_function->symbol->string;
return (expression_t*) expression;
}
eat(T___PRETTY_FUNCTION__);
/* TODO */
+ if (current_function == NULL) {
+ parse_error("'__PRETTY_FUNCTION__' used outside of a function");
+ }
+
string_literal_expression_t *expression
= allocate_ast_zero(sizeof(expression[0]));
expression->expression.type = EXPR_PRETTY_FUNCTION;
expression->expression.datatype = type_string;
- expression->value = "TODO: PRETTY FUNCTION";
+ expression->value = current_function->symbol->string;
return (expression_t*) expression;
}
return expression;
}
+static expression_t *parse_builtin_expect(void)
+{
+ eat(T___builtin_expect);
+
+ expression_t *expression
+ = allocate_expression_zero(EXPR_BINARY_BUILTIN_EXPECT);
+
+ expect('(');
+ expression->binary.left = parse_assignment_expression();
+ expect(',');
+ expression->binary.right = parse_constant_expression();
+ expect(')');
+
+ expression->base.datatype = expression->binary.left->base.datatype;
+
+ return expression;
+}
+
static expression_t *parse_primary_expression(void)
{
switch(token.type) {
return parse_va_start();
case T___builtin_va_arg:
return parse_va_arg();
+ case T___builtin_expect:
+ return parse_builtin_expect();
case T___builtin_nanf:
case T___builtin_alloca:
- case T___builtin_expect:
case T___builtin_va_end:
return parse_builtin_symbol();
case T___builtin_isgreater:
if(return_type == NULL)
return (statement_t*) statement;
+ if(return_value != NULL && return_value->base.datatype == NULL)
+ return (statement_t*) statement;
return_type = skip_typeref(return_type);