tests for __func__ and friends
[cparser] / parser.c
index 844ced3..32a2a9d 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -53,7 +53,8 @@ struct declaration_specifiers_t {
        source_position_t  source_position;
        unsigned char      declared_storage_class;
        unsigned char      alignment;         /**< Alignment, 0 if not set. */
-       bool               is_inline;
+       unsigned int       is_inline : 1;
+       unsigned int       deprecated : 1;
        decl_modifiers_t   decl_modifiers;    /**< MS __declspec extended modifier mask */
        const char        *deprecated_string; /**< can be set if declaration was marked deprecated. */
        symbol_t          *get_property_sym;  /**< the name of the get property if set. */
@@ -145,7 +146,7 @@ static void semantic_comparison(binary_expression_t *expression);
        case T_restrict:        \
        case T_volatile:        \
        case T_inline:          \
-       case T_forceinline:
+       case T__forceinline:
 
 #ifdef PROVIDE_COMPLEX
 #define COMPLEX_SPECIFIERS  \
@@ -173,7 +174,7 @@ static void semantic_comparison(binary_expression_t *expression);
        case T_enum:              \
        case T___typeof__:        \
        case T___builtin_va_list: \
-       case T_declspec:          \
+       case T__declspec:         \
        COMPLEX_SPECIFIERS        \
        IMAGINARY_SPECIFIERS
 
@@ -296,6 +297,8 @@ static size_t get_expression_struct_size(expression_kind_t kind)
                [EXPR_CLASSIFY_TYPE]           = sizeof(classify_type_expression_t),
                [EXPR_FUNCTION]                = sizeof(string_literal_expression_t),
                [EXPR_PRETTY_FUNCTION]         = sizeof(string_literal_expression_t),
+               [EXPR_FUNCSIG]                 = sizeof(string_literal_expression_t),
+               [EXPR_FUNCDNAME]               = sizeof(string_literal_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),
@@ -939,32 +942,42 @@ static string_t parse_string_literals(void)
        return result;
 }
 
+/**
+ * Parse one GNU attribute.
+ */
+static void parse_gnu_attribute(void)
+{
+       eat(T___attribute__);
+       expect('(');
+       expect('(');
+       while(true) {
+               if(token.type != T_IDENTIFIER)
+                       break;
+               symbol_t *sym = token.v.symbol;
+               if(sym == sym_deprecated) {
+               }
+               next_token();
+               if(token.type == '(')
+                       eat_until_matching_token('(');
+               if(token.type != ',')
+                       break;
+               next_token();
+       }
+       expect(')');
+       expect(')');
+end_error:
+       return;
+}
+
+/**
+ * Parse GNU attributes.
+ */
 static void parse_attributes(void)
 {
        while(true) {
                switch(token.type) {
                case T___attribute__: {
-                       next_token();
-
-                       expect('(');
-                       int depth = 1;
-                       while(depth > 0) {
-                               switch(token.type) {
-                               case T_EOF:
-                                       errorf(HERE, "EOF while parsing attribute");
-                                       break;
-                               case '(':
-                                       next_token();
-                                       depth++;
-                                       break;
-                               case ')':
-                                       next_token();
-                                       depth--;
-                                       break;
-                               default:
-                                       next_token();
-                               }
-                       }
+                       parse_gnu_attribute();
                        break;
                }
                case T_asm:
@@ -1216,7 +1229,7 @@ static __attribute__((unused)) void debug_print_type_path(
                        }
                        fprintf(stderr, ".%s", entry->v.compound_entry->symbol->string);
                } else if(is_type_array(type)) {
-                       fprintf(stderr, "[%u]", entry->v.index);
+                       fprintf(stderr, "[%zd]", entry->v.index);
                } else {
                        fprintf(stderr, "-INVALID-");
                }
@@ -1996,9 +2009,14 @@ typedef enum {
        SPECIFIER_FLOAT     = 1 << 8,
        SPECIFIER_BOOL      = 1 << 9,
        SPECIFIER_VOID      = 1 << 10,
+       SPECIFIER_INT8      = 1 << 11,
+       SPECIFIER_INT16     = 1 << 12,
+       SPECIFIER_INT32     = 1 << 13,
+       SPECIFIER_INT64     = 1 << 14,
+       SPECIFIER_INT128    = 1 << 15,
 #ifdef PROVIDE_COMPLEX
-       SPECIFIER_COMPLEX   = 1 << 11,
-       SPECIFIER_IMAGINARY = 1 << 12,
+       SPECIFIER_COMPLEX   = 1 << 16,
+       SPECIFIER_IMAGINARY = 1 << 17,
 #endif
 } specifiers_t;
 
@@ -2158,8 +2176,10 @@ static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *spe
                        expect(')');
                } else if(symbol == sym_deprecated) {
                        next_token();
-                       DET_MOD(deprecated, DM_DEPRECATED);
-               if(token.type == '(') {
+                       if(specifiers->deprecated != 0)
+                               warningf(HERE, "deprecated used more than once");
+                       specifiers->deprecated = 1;
+                       if(token.type == '(') {
                                next_token();
                                if(token.type == T_STRING_LITERAL) {
                                        specifiers->deprecated_string = token.v.string.begin;
@@ -2214,7 +2234,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                MATCH_STORAGE_CLASS(T_auto,     STORAGE_CLASS_AUTO)
                MATCH_STORAGE_CLASS(T_register, STORAGE_CLASS_REGISTER)
 
-               case T_declspec:
+               case T__declspec:
                        next_token();
                        expect('(');
                        add_anchor_token(')');
@@ -2254,6 +2274,11 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                MATCH_TYPE_QUALIFIER(T_const,    TYPE_QUALIFIER_CONST);
                MATCH_TYPE_QUALIFIER(T_restrict, TYPE_QUALIFIER_RESTRICT);
                MATCH_TYPE_QUALIFIER(T_volatile, TYPE_QUALIFIER_VOLATILE);
+               MATCH_TYPE_QUALIFIER(T__w64,     TYPE_QUALIFIER_W64);
+               MATCH_TYPE_QUALIFIER(T___ptr32,  TYPE_QUALIFIER_PTR32);
+               MATCH_TYPE_QUALIFIER(T___ptr64,  TYPE_QUALIFIER_PTR64);
+               MATCH_TYPE_QUALIFIER(T___uptr,   TYPE_QUALIFIER_UPTR);
+               MATCH_TYPE_QUALIFIER(T___sptr,   TYPE_QUALIFIER_SPTR);
 
                case T___extension__:
                        /* TODO */
@@ -2280,11 +2305,16 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                MATCH_SPECIFIER(T_signed,     SPECIFIER_SIGNED,    "signed")
                MATCH_SPECIFIER(T_unsigned,   SPECIFIER_UNSIGNED,  "unsigned")
                MATCH_SPECIFIER(T__Bool,      SPECIFIER_BOOL,      "_Bool")
+               MATCH_SPECIFIER(T__int8,      SPECIFIER_INT8,      "_int8")
+               MATCH_SPECIFIER(T__int16,     SPECIFIER_INT16,     "_int16")
+               MATCH_SPECIFIER(T__int32,     SPECIFIER_INT32,     "_int32")
+               MATCH_SPECIFIER(T__int64,     SPECIFIER_INT64,     "_int64")
+               MATCH_SPECIFIER(T__int128,    SPECIFIER_INT128,    "_int128")
 #ifdef PROVIDE_COMPLEX
                MATCH_SPECIFIER(T__Complex,   SPECIFIER_COMPLEX,   "_Complex")
                MATCH_SPECIFIER(T__Imaginary, SPECIFIER_IMAGINARY, "_Imaginary")
 #endif
-               case T_forceinline:
+               case T__forceinline:
                        /* only in microsoft mode */
                        specifiers->decl_modifiers |= DM_FORCEINLINE;
 
@@ -2412,6 +2442,52 @@ finish_specifiers:
                        | SPECIFIER_INT:
                        atomic_type = ATOMIC_TYPE_ULONGLONG;
                        break;
+
+               case SPECIFIER_UNSIGNED | SPECIFIER_INT8:
+                       atomic_type = unsigned_int8_type_kind;
+                       break;
+
+               case SPECIFIER_UNSIGNED | SPECIFIER_INT16:
+                       atomic_type = unsigned_int16_type_kind;
+                       break;
+
+               case SPECIFIER_UNSIGNED | SPECIFIER_INT32:
+                       atomic_type = unsigned_int32_type_kind;
+                       break;
+
+               case SPECIFIER_UNSIGNED | SPECIFIER_INT64:
+                       atomic_type = unsigned_int64_type_kind;
+                       break;
+
+               case SPECIFIER_UNSIGNED | SPECIFIER_INT128:
+                       atomic_type = unsigned_int128_type_kind;
+                       break;
+
+               case SPECIFIER_INT8:
+               case SPECIFIER_SIGNED | SPECIFIER_INT8:
+                       atomic_type = int8_type_kind;
+                       break;
+
+               case SPECIFIER_INT16:
+               case SPECIFIER_SIGNED | SPECIFIER_INT16:
+                       atomic_type = int16_type_kind;
+                       break;
+
+               case SPECIFIER_INT32:
+               case SPECIFIER_SIGNED | SPECIFIER_INT32:
+                       atomic_type = int32_type_kind;
+                       break;
+
+               case SPECIFIER_INT64:
+               case SPECIFIER_SIGNED | SPECIFIER_INT64:
+                       atomic_type = int64_type_kind;
+                       break;
+
+               case SPECIFIER_INT128:
+               case SPECIFIER_SIGNED | SPECIFIER_INT128:
+                       atomic_type = int128_type_kind;
+                       break;
+
                case SPECIFIER_FLOAT:
                        atomic_type = ATOMIC_TYPE_FLOAT;
                        break;
@@ -2477,6 +2553,7 @@ finish_specifiers:
        }
 
        type->base.qualifiers = type_qualifiers;
+       /* FIXME: check type qualifiers here */
 
        type_t *result = typehash_insert(type);
        if(newtype && result != type) {
@@ -2498,6 +2575,12 @@ static type_qualifiers_t parse_type_qualifiers(void)
                MATCH_TYPE_QUALIFIER(T_const,    TYPE_QUALIFIER_CONST);
                MATCH_TYPE_QUALIFIER(T_restrict, TYPE_QUALIFIER_RESTRICT);
                MATCH_TYPE_QUALIFIER(T_volatile, TYPE_QUALIFIER_VOLATILE);
+               /* microsoft extended type modifiers */
+               MATCH_TYPE_QUALIFIER(T__w64,     TYPE_QUALIFIER_W64);
+               MATCH_TYPE_QUALIFIER(T___ptr32,  TYPE_QUALIFIER_PTR32);
+               MATCH_TYPE_QUALIFIER(T___ptr64,  TYPE_QUALIFIER_PTR64);
+               MATCH_TYPE_QUALIFIER(T___uptr,   TYPE_QUALIFIER_UPTR);
+               MATCH_TYPE_QUALIFIER(T___sptr,   TYPE_QUALIFIER_SPTR);
 
                default:
                        return type_qualifiers;
@@ -2954,6 +3037,7 @@ static declaration_t *parse_declarator(
        declaration_t *const declaration    = allocate_declaration_zero();
        declaration->declared_storage_class = specifiers->declared_storage_class;
        declaration->modifiers              = specifiers->decl_modifiers;
+       declaration->deprecated             = specifiers->deprecated;
        declaration->deprecated_string      = specifiers->deprecated_string;
        declaration->get_property_sym       = specifiers->get_property_sym;
        declaration->put_property_sym       = specifiers->put_property_sym;
@@ -4219,7 +4303,7 @@ static expression_t *parse_reference(void)
        declaration->used = true;
 
        /* check for deprecated functions */
-       if(declaration->modifiers & DM_DEPRECATED) {
+       if(declaration->deprecated != 0) {
                const char *prefix = "";
                if (is_type_function(declaration->type))
                        prefix = "function ";
@@ -4376,7 +4460,6 @@ static expression_t *parse_function_keyword(void)
 static expression_t *parse_pretty_function_keyword(void)
 {
        eat(T___PRETTY_FUNCTION__);
-       /* TODO */
 
        if (current_function == NULL) {
                errorf(HERE, "'__PRETTY_FUNCTION__' used outside of a function");
@@ -4388,6 +4471,34 @@ static expression_t *parse_pretty_function_keyword(void)
        return expression;
 }
 
+static expression_t *parse_funcsig_keyword(void)
+{
+       next_token();
+
+       if (current_function == NULL) {
+               errorf(HERE, "'__FUNCSIG__' used outside of a function");
+       }
+
+       expression_t *expression = allocate_expression_zero(EXPR_FUNCSIG);
+       expression->base.type    = type_char_ptr;
+
+       return expression;
+}
+
+static expression_t *parse_funcdname_keyword(void)
+{
+       next_token();
+
+       if (current_function == NULL) {
+               errorf(HERE, "'__FUNCDNAME__' used outside of a function");
+       }
+
+       expression_t *expression = allocate_expression_zero(EXPR_FUNCDNAME);
+       expression->base.type    = type_char_ptr;
+
+       return expression;
+}
+
 static designator_t *parse_designator(void)
 {
        designator_t *result    = allocate_ast_zero(sizeof(result[0]));
@@ -4686,7 +4797,7 @@ end_error:
  * Parses a MS assume() expression.
  */
 static expression_t *parse_assume(void) {
-       eat(T_assume);
+       eat(T__assume);
 
        expression_t *expression
                = allocate_expression_zero(EXPR_UNARY_ASSUME);
@@ -4719,6 +4830,8 @@ static expression_t *parse_primary_expression(void)
                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();
@@ -4736,7 +4849,7 @@ static expression_t *parse_primary_expression(void)
                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__assume:                  return parse_assume();
 
                case '(':                        return parse_brace_expression();
        }
@@ -5713,6 +5826,8 @@ static bool expression_has_effect(const expression_t *const expr)
 
                case EXPR_FUNCTION:                  return false;
                case EXPR_PRETTY_FUNCTION:           return false;
+               case EXPR_FUNCSIG:                   return false;
+               case EXPR_FUNCDNAME:                 return false;
                case EXPR_BUILTIN_SYMBOL:            break; /* handled in EXPR_CALL */
                case EXPR_BUILTIN_CONSTANT_P:        return false;
                case EXPR_BUILTIN_PREFETCH:          return true;