#include "symbol.h"
#include "token_t.h"
#include "type.h"
+#include "entity_t.h"
#include "adt/obst.h"
/** The AST obstack contains all data that must stay in the AST. */
extern struct obstack ast_obstack;
+/**
+ * Operator precedence classes
+ */
+typedef enum precedence_t {
+ PREC_BOTTOM,
+ PREC_EXPRESSION, /* , left to right */
+ PREC_ASSIGNMENT, /* = += -= *= /= %= <<= >>= &= ^= |= right to left */
+ PREC_CONDITIONAL, /* ?: right to left */
+ PREC_LOGICAL_OR, /* || left to right */
+ PREC_LOGICAL_AND, /* && left to right */
+ PREC_OR, /* | left to right */
+ PREC_XOR, /* ^ left to right */
+ PREC_AND, /* & left to right */
+ PREC_EQUALITY, /* == != left to right */
+ PREC_RELATIONAL, /* < <= > >= left to right */
+ PREC_SHIFT, /* << >> left to right */
+ PREC_ADDITIVE, /* + - left to right */
+ PREC_MULTIPLICATIVE, /* * / % left to right */
+ PREC_CAST, /* (type) right to left */
+ PREC_UNARY, /* ! ~ ++ -- + - * & sizeof right to left */
+ PREC_POSTFIX, /* () [] -> . left to right */
+ PREC_PRIMARY,
+ PREC_TOP
+} precedence_t;
+
/**
* Expression kinds.
*/
-typedef enum {
+typedef enum expression_kind_t {
EXPR_UNKNOWN = 0,
EXPR_INVALID,
EXPR_REFERENCE,
+ EXPR_REFERENCE_ENUM_VALUE,
EXPR_CONST,
EXPR_CHARACTER_CONSTANT,
EXPR_WIDE_CHARACTER_CONSTANT,
EXPR_ALIGNOF,
EXPR_FUNCNAME,
- EXPR_BUILTIN_SYMBOL,
EXPR_BUILTIN_CONSTANT_P,
- EXPR_BUILTIN_PREFETCH,
+ EXPR_BUILTIN_TYPES_COMPATIBLE_P,
EXPR_OFFSETOF,
EXPR_VA_START,
EXPR_VA_ARG,
+ EXPR_VA_COPY,
EXPR_STATEMENT,
+ EXPR_LABEL_ADDRESS, /**< GCC extension &&label operator */
EXPR_UNARY_FIRST,
EXPR_UNARY_NEGATE = EXPR_UNARY_FIRST,
EXPR_UNARY_CAST,
EXPR_UNARY_CAST_IMPLICIT, /**< compiler generated cast */
EXPR_UNARY_ASSUME, /**< MS __assume() */
- EXPR_UNARY_BITFIELD_EXTRACT,
- EXPR_UNARY_LAST = EXPR_UNARY_BITFIELD_EXTRACT,
+ EXPR_UNARY_DELETE,
+ EXPR_UNARY_DELETE_ARRAY,
+ EXPR_UNARY_THROW,
+ EXPR_UNARY_LAST = EXPR_UNARY_THROW,
EXPR_BINARY_FIRST,
EXPR_BINARY_ADD = EXPR_BINARY_FIRST,
EXPR_BINARY_BITWISE_OR_ASSIGN,
EXPR_BINARY_COMMA,
- EXPR_BINARY_BUILTIN_EXPECT,
EXPR_BINARY_ISGREATER,
EXPR_BINARY_ISGREATEREQUAL,
EXPR_BINARY_ISLESS,
EXPR_BINARY_LAST = EXPR_BINARY_ISUNORDERED,
} expression_kind_t;
-typedef enum {
+typedef enum funcname_kind_t {
FUNCNAME_FUNCTION, /**< C99 __func__, older __FUNCTION__ */
FUNCNAME_PRETTY_FUNCTION, /**< GNUC __PRETTY_FUNCTION__ */
FUNCNAME_FUNCSIG, /**< MS __FUNCSIG__ */
case EXPR_BINARY_BITWISE_XOR_ASSIGN: \
case EXPR_BINARY_BITWISE_OR_ASSIGN: \
case EXPR_BINARY_COMMA: \
- case EXPR_BINARY_BUILTIN_EXPECT: \
case EXPR_BINARY_ISGREATER: \
case EXPR_BINARY_ISGREATEREQUAL: \
case EXPR_BINARY_ISLESS: \
case EXPR_BINARY_ISLESSGREATER: \
case EXPR_BINARY_ISUNORDERED:
-#define EXPR_UNARY_CASES \
+/**
+ * unary expression with mandatory operand
+ */
+#define EXPR_UNARY_CASES_MANDATORY \
case EXPR_UNARY_NEGATE: \
case EXPR_UNARY_PLUS: \
case EXPR_UNARY_BITWISE_NEGATE: \
case EXPR_UNARY_CAST: \
case EXPR_UNARY_CAST_IMPLICIT: \
case EXPR_UNARY_ASSUME: \
- case EXPR_UNARY_BITFIELD_EXTRACT:
+ case EXPR_UNARY_DELETE: \
+ case EXPR_UNARY_DELETE_ARRAY:
/**
- * A scope containing declarations.
+ * unary expression with optional operand
*/
-struct scope_t {
- declaration_t *declarations; /**< List of declarations in this scope. */
- declaration_t *last_declaration; /**< last declaration in this scope. */
-};
+#define EXPR_UNARY_CASES_OPTIONAL \
+ case EXPR_UNARY_THROW: \
+#define EXPR_UNARY_CASES \
+ EXPR_UNARY_CASES_MANDATORY \
+ EXPR_UNARY_CASES_OPTIONAL
+
+/**
+ * The base class of every expression.
+ */
struct expression_base_t {
- expression_kind_t kind;
- type_t *type;
- source_position_t source_position;
+ expression_kind_t kind; /**< The expression kind. */
+ type_t *type; /**< The type of the expression. */
+ source_position_t source_position; /**< The source position of this expression. */
+ bool parenthesized;
+#ifndef NDEBUG
+ bool transformed; /**< Set if this expression was transformed. */
+#endif
};
+/**
+ * A constant.
+ */
struct const_expression_t {
expression_base_t base;
union {
initializer_t *initializer;
};
-struct builtin_symbol_expression_t {
- expression_base_t base;
- symbol_t *symbol;
-};
-
struct builtin_constant_expression_t {
expression_base_t base;
expression_t *value;
};
-struct builtin_prefetch_expression_t {
+struct builtin_types_compatible_expression_t {
expression_base_t base;
- expression_t *adr;
- expression_t *rw;
- expression_t *locality;
+ type_t *left;
+ type_t *right;
};
struct reference_expression_t {
expression_base_t base;
- declaration_t *declaration;
+ entity_t *entity;
};
+/**
+ * An argument of a call.
+ */
struct call_argument_t {
- expression_t *expression;
- call_argument_t *next;
+ expression_t *expression; /**< The expression which value is transmitted. */
+ call_argument_t *next; /**< Links to the next argument of this call. */
};
+
struct call_expression_t {
expression_base_t base;
- expression_t *function;
- call_argument_t *arguments;
+ expression_t *function; /**< The address of the function to call. */
+ call_argument_t *arguments; /**< List of arguments of this call. */
};
+
struct unary_expression_t {
expression_base_t base;
- expression_t *value;
+ expression_t *value; /**< The unary operand. */
};
struct binary_expression_t {
struct select_expression_t {
expression_base_t base;
expression_t *compound;
- symbol_t *symbol;
-
- declaration_t *compound_entry;
+ entity_t *compound_entry;
};
struct array_access_expression_t {
expression_base_t base;
- expression_t *array_ref;
- expression_t *index;
- bool flipped; /* index/ref was written in a 5[a] way */
+ expression_t *array_ref; /**< the referenced array */
+ expression_t *index; /**< the index used */
+ bool flipped; /**< True if index/ref was written in a 5[a] way */
};
struct typeprop_expression_t {
struct designator_t {
source_position_t source_position;
- symbol_t *symbol;
- expression_t *array_index;
+ symbol_t *symbol; /**< the symbol if any */
+ expression_t *array_index; /**< the array index if any */
designator_t *next;
};
struct va_start_expression_t {
expression_base_t base;
expression_t *ap;
- declaration_t *parameter;
+ variable_t *parameter;
};
struct va_arg_expression_t {
expression_t *ap;
};
+struct va_copy_expression_t {
+ expression_base_t base;
+ expression_t *dst; /**< destination argument */
+ expression_t *src; /**< source argument */
+};
+
struct conditional_expression_t {
expression_base_t base;
expression_t *condition;
expression_t *type_expression;
};
+struct label_address_expression_t {
+ expression_base_t base;
+ label_t *label;
+};
+
union expression_t {
- expression_kind_t kind;
- expression_base_t base;
- const_expression_t conste;
- funcname_expression_t funcname;
- string_literal_expression_t string;
- wide_string_literal_expression_t wide_string;
- compound_literal_expression_t compound_literal;
- builtin_symbol_expression_t builtin_symbol;
- builtin_constant_expression_t builtin_constant;
- builtin_prefetch_expression_t builtin_prefetch;
- reference_expression_t reference;
- call_expression_t call;
- unary_expression_t unary;
- binary_expression_t binary;
- select_expression_t select;
- array_access_expression_t array_access;
- typeprop_expression_t typeprop;
- offsetof_expression_t offsetofe;
- va_start_expression_t va_starte;
- va_arg_expression_t va_arge;
- conditional_expression_t conditional;
- statement_expression_t statement;
- classify_type_expression_t classify_type;
-};
-
-typedef enum {
- STORAGE_CLASS_NONE,
- STORAGE_CLASS_EXTERN,
- STORAGE_CLASS_STATIC,
- STORAGE_CLASS_TYPEDEF,
- STORAGE_CLASS_AUTO,
- STORAGE_CLASS_REGISTER,
- STORAGE_CLASS_ENUM_ENTRY,
- STORAGE_CLASS_THREAD,
- STORAGE_CLASS_THREAD_EXTERN,
- STORAGE_CLASS_THREAD_STATIC,
-} storage_class_tag_t;
-
-typedef enum {
- NAMESPACE_NORMAL,
- NAMESPACE_STRUCT,
- NAMESPACE_UNION,
- NAMESPACE_ENUM,
- NAMESPACE_LABEL,
-} namespace_t;
-
-typedef enum {
+ expression_kind_t kind;
+ expression_base_t base;
+ const_expression_t conste;
+ funcname_expression_t funcname;
+ string_literal_expression_t string;
+ wide_string_literal_expression_t wide_string;
+ compound_literal_expression_t compound_literal;
+ builtin_constant_expression_t builtin_constant;
+ builtin_types_compatible_expression_t builtin_types_compatible;
+ reference_expression_t reference;
+ call_expression_t call;
+ unary_expression_t unary;
+ binary_expression_t binary;
+ select_expression_t select;
+ array_access_expression_t array_access;
+ typeprop_expression_t typeprop;
+ offsetof_expression_t offsetofe;
+ va_start_expression_t va_starte;
+ va_arg_expression_t va_arge;
+ va_copy_expression_t va_copye;
+ conditional_expression_t conditional;
+ statement_expression_t statement;
+ classify_type_expression_t classify_type;
+ label_address_expression_t label_address;
+};
+
+typedef enum initializer_kind_t {
INITIALIZER_VALUE,
INITIALIZER_LIST,
INITIALIZER_STRING,
};
/**
- * GNU attributes.
+ * The statement kinds.
*/
-typedef enum gnu_attribute_kind_t {
- GNU_AK_CONST,
- GNU_AK_VOLATILE,
- GNU_AK_CDECL,
- GNU_AK_STDCALL,
- GNU_AK_FASTCALL,
- GNU_AK_DEPRECATED,
- GNU_AK_NOINLINE,
- GNU_AK_NORETURN,
- GNU_AK_NAKED,
- GNU_AK_PURE,
- GNU_AK_ALWAYS_INLINE,
- GNU_AK_MALLOC,
- GNU_AK_WEAK,
- GNU_AK_CONSTRUCTOR,
- GNU_AK_DESTRUCTOR,
- GNU_AK_NOTHROW,
- GNU_AK_TRANSPARENT_UNION,
- GNU_AK_COMMON,
- GNU_AK_NOCOMMON,
- GNU_AK_PACKED,
- GNU_AK_SHARED,
- GNU_AK_NOTSHARED,
- GNU_AK_USED,
- GNU_AK_UNUSED,
- GNU_AK_NO_INSTRUMENT_FUNCTION,
- GNU_AK_WARN_UNUSED_RESULT,
- GNU_AK_LONGCALL,
- GNU_AK_SHORTCALL,
- GNU_AK_LONG_CALL,
- GNU_AK_SHORT_CALL,
- GNU_AK_FUNCTION_VECTOR,
- GNU_AK_INTERRUPT,
- GNU_AK_INTERRUPT_HANDLER,
- GNU_AK_NMI_HANDLER,
- GNU_AK_NESTING,
- GNU_AK_NEAR,
- GNU_AK_FAR,
- GNU_AK_SIGNAL,
- GNU_AK_EIGTHBIT_DATA,
- GNU_AK_TINY_DATA,
- GNU_AK_SAVEALL,
- GNU_AK_FLATTEN,
- GNU_AK_SSEREGPARM,
- GNU_AK_EXTERNALLY_VISIBLE,
- GNU_AK_RETURN_TWICE,
- GNU_AK_MAY_ALIAS,
- GNU_AK_MS_STRUCT,
- GNU_AK_GCC_STRUCT,
- GNU_AK_DLLIMPORT,
- GNU_AK_DLLEXPORT,
- GNU_AK_ALIGNED,
- GNU_AK_ALIAS,
- GNU_AK_SECTION,
- GNU_AK_FORMAT,
- GNU_AK_FORMAT_ARG,
- GNU_AK_WEAKREF,
- GNU_AK_NONNULL,
- GNU_AK_TLS_MODEL,
- GNU_AK_VISIBILITY,
- GNU_AK_REGPARM,
- GNU_AK_MODEL,
- GNU_AK_MODE,
- GNU_AK_TRAP_EXIT,
- GNU_AK_SP_SWITCH,
- GNU_AK_SENTINEL,
- GNU_AK_LAST
-} gnu_attribute_kind_t;
-
-/**
- * Extended microsoft modifier.
- */
-typedef enum {
- DM_DLLIMPORT = (1 << 0),
- DM_DLLEXPORT = (1 << 1),
- DM_THREAD = (1 << 2),
- DM_NAKED = (1 << 3),
- DM_MICROSOFT_INLINE = (1 << 4),
- DM_FORCEINLINE = (1 << 5),
- DM_SELECTANY = (1 << 6),
- DM_NOTHROW = (1 << 7),
- DM_NOVTABLE = (1 << 8),
- DM_NORETURN = (1 << 9),
- DM_NOINLINE = (1 << 10),
- DM_RESTRICT = (1 << 11),
- DM_NOALIAS = (1 << 12)
-} decl_modifier_t;
-
-typedef unsigned short decl_modifiers_t;
-
-struct declaration_t {
- unsigned char namespc;
- unsigned char declared_storage_class;
- unsigned char storage_class;
- unsigned char alignment; /**< Alignment of the declaration, 0 for default. */
- decl_modifiers_t decl_modifiers; /**< MS __declspec modifiers. */
- const char *deprecated_string; /**< MS deprecated string if any. */
- symbol_t *get_property_sym; /**< MS get property. */
- symbol_t *put_property_sym; /**< MS put property. */
- unsigned int address_taken : 1;
- unsigned int is_inline : 1;
- unsigned int used : 1; /**< Set if the declaration is used. */
- unsigned int deprecated : 1; /**< Microsoft or GNU deprecated attribute. */
- type_t *type;
- symbol_t *symbol;
- source_position_t source_position;
- union {
- bool complete; /**< used to indicate wether struct/union types are already defined or if just the name is declared */
- statement_t *statement;
- initializer_t *initializer;
- expression_t *enum_value;
- } init;
- scope_t scope; /**< The scope that this declaration opens. */
- scope_t *parent_scope; /**< The parent scope where this declaration lives. */
-
- /** next declaration in a scope */
- declaration_t *next;
- /** next declaration with same symbol */
- declaration_t *symbol_next;
-
- /* the following fields are used in ast2firm module */
- unsigned char declaration_kind;
- union {
- unsigned int value_number;
- ir_entity *entity;
- ir_node *block;
- ir_node *vla_base;
- tarval *enum_val;
- ir_type *irtype;
- } v;
-};
-
-typedef enum {
+typedef enum statement_kind_t {
STATEMENT_INVALID,
STATEMENT_EMPTY,
STATEMENT_COMPOUND,
STATEMENT_DO_WHILE,
STATEMENT_FOR,
STATEMENT_ASM,
- STATEMENT_MS_TRY,
- STATEMENT_LEAVE
+ STATEMENT_MS_TRY, /**< MS __try/__finally or __try/__except */
+ STATEMENT_LEAVE /**< MS __leave */
} statement_kind_t;
+/**
+ * The base class of every statement.
+ */
struct statement_base_t {
statement_kind_t kind;
- statement_t *next;
+ statement_t *next; /**< Point to the next statement in a compound statement. */
source_position_t source_position;
+ statement_t *parent; /**< The Parent statement that controls the execution. */
+ bool reachable; /**< True, if this statement is reachable. */
+#ifndef NDEBUG
+ bool transformed;
+#endif
};
struct invalid_statement_t {
struct return_statement_t {
statement_base_t base;
- expression_t *value;
+ expression_t *value; /**< The return value if any. */
};
struct compound_statement_t {
statement_base_t base;
statement_t *statements;
scope_t scope;
+ bool stmt_expr; /**< True if this compound statement is a statement expression. */
};
struct declaration_statement_t {
statement_base_t base;
- declaration_t *declarations_begin;
- declaration_t *declarations_end;
+ entity_t *declarations_begin;
+ entity_t *declarations_end;
};
struct if_statement_t {
};
struct switch_statement_t {
- statement_base_t base;
+ statement_base_t base;
expression_t *expression;
statement_t *body;
- case_label_statement_t *first_case, *last_case;
+ case_label_statement_t *first_case, *last_case; /**< List of all cases, including default. */
+ case_label_statement_t *default_label; /**< The default label if existent. */
+ unsigned long default_proj_nr; /**< The Proj-number for the default Proj. */
};
struct goto_statement_t {
statement_base_t base;
- declaration_t *label; /**< The destination label. */
- goto_statement_t *next; /**< links all goto statements of a function */
+ label_t *label; /**< The destination label. */
+ expression_t *expression; /**< The expression for an assigned goto. */
+ goto_statement_t *next; /**< links all goto statements of a function */
};
struct case_label_statement_t {
statement_base_t base;
- expression_t *expression; /**< The case label expression, NULL for default label. */
- expression_t *end_range; /**< For GNUC case a .. b: the end range expression, NULL else. */
+ expression_t *expression; /**< The case label expression, NULL for default label. */
+ expression_t *end_range; /**< For GNUC case a .. b: the end range expression, NULL else. */
+ case_label_statement_t *next; /**< link to the next case label in switch */
statement_t *statement;
- case_label_statement_t *next; /**< link to the next case label in switch */
+ long first_case; /**< The folded value of expression. */
+ long last_case; /**< The folded value of end_range. */
+ bool is_bad; /**< If set marked as bad to suppress warnings. */
+ bool is_empty_range; /**< If set marked this as an empty range. */
};
struct label_statement_t {
statement_base_t base;
- declaration_t *label;
+ label_t *label;
statement_t *statement;
label_statement_t *next; /**< links all label statements of a function */
};
expression_t *step;
statement_t *body;
scope_t scope;
+ bool condition_reachable:1;
+ bool step_reachable:1;
};
-struct asm_constraint_t {
- string_t constraints;
- expression_t *expression;
- symbol_t *symbol;
- asm_constraint_t *next;
+struct asm_argument_t {
+ string_t constraints;
+ expression_t *expression;
+ symbol_t *symbol;
+ asm_argument_t *next;
};
struct asm_clobber_t {
};
struct asm_statement_t {
- statement_base_t base;
- string_t asm_text;
- asm_constraint_t *inputs;
- asm_constraint_t *outputs;
- asm_clobber_t *clobbers;
- bool is_volatile;
+ statement_base_t base;
+ string_t asm_text;
+ asm_argument_t *inputs;
+ asm_argument_t *outputs;
+ asm_clobber_t *clobbers;
+ bool is_volatile;
};
struct ms_try_statement_t {
};
struct translation_unit_t {
- scope_t scope;
+ scope_t scope;
+ statement_t *global_asm;
};
static inline
return statement->base.kind == STATEMENT_INVALID;
}
-
#define allocate_ast(size) _allocate_ast(size)
#endif