diff -uNr gdc-0.11/d/config-lang.in gdc-0.12/d/config-lang.in --- gdc-0.11/d/config-lang.in 2005-02-15 01:07:00.000000000 +0100 +++ gdc-0.12/d/config-lang.in 2005-05-27 03:05:04.000000000 +0200 @@ -20,7 +20,6 @@ language="d" compilers="cc1d\$(exeext)" stagestuff="gdc\$(exeext) gdc-cross\$(exeext) cc1d\$(exeext)" -lang_requires="c++" gtfiles="\$(srcdir)/d/d-lang.h \$(srcdir)/d/d-builtins.c" diff -uNr gdc-0.11/d/d-asm-i386.h gdc-0.12/d/d-asm-i386.h --- gdc-0.11/d/d-asm-i386.h 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/d-asm-i386.h 2005-05-19 02:15:50.000000000 +0200 @@ -1137,7 +1137,7 @@ Reg segmentPrefix; Reg reg; - xdmd_integer_t constDisplacement; // use to build up.. should be int constant in the end.. + sinteger_t constDisplacement; // use to build up.. should be int constant in the end.. Array symbolDisplacement; // array of expressions or.. Reg baseReg; Reg indexReg; @@ -2364,7 +2364,7 @@ // parse primary: DMD allows 'MyAlign' (const int) but not '2+2' // GAS is padding with NOPs last time I checked. Expression * e = parseAsmExp()->constFold(); - xdmd_integer_t align = e->toInteger(); + uinteger_t align = e->toUInteger(); if (align >= 0) { // %% is this printf portable? diff -uNr gdc-0.11/d/d-bi-attrs-341.h gdc-0.12/d/d-bi-attrs-341.h --- gdc-0.11/d/d-bi-attrs-341.h 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.12/d/d-bi-attrs-341.h 2005-05-07 18:06:03.000000000 +0200 @@ -0,0 +1,1536 @@ +static tree handle_packed_attribute (tree *, tree, tree, int, bool *); +static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *); +static tree handle_common_attribute (tree *, tree, tree, int, bool *); +static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); +static tree handle_noinline_attribute (tree *, tree, tree, int, bool *); +static tree handle_always_inline_attribute (tree *, tree, tree, int, + bool *); +static tree handle_used_attribute (tree *, tree, tree, int, bool *); +static tree handle_unused_attribute (tree *, tree, tree, int, bool *); +static tree handle_const_attribute (tree *, tree, tree, int, bool *); +static tree handle_transparent_union_attribute (tree *, tree, tree, + int, bool *); +static tree handle_constructor_attribute (tree *, tree, tree, int, bool *); +static tree handle_destructor_attribute (tree *, tree, tree, int, bool *); +static tree handle_mode_attribute (tree *, tree, tree, int, bool *); +static tree handle_section_attribute (tree *, tree, tree, int, bool *); +static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); +static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; +static tree handle_alias_attribute (tree *, tree, tree, int, bool *); +static tree handle_visibility_attribute (tree *, tree, tree, int, + bool *); +static tree handle_tls_model_attribute (tree *, tree, tree, int, + bool *); +static tree handle_no_instrument_function_attribute (tree *, tree, + tree, int, bool *); +static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); +static tree handle_no_limit_stack_attribute (tree *, tree, tree, int, + bool *); +static tree handle_pure_attribute (tree *, tree, tree, int, bool *); +static tree handle_deprecated_attribute (tree *, tree, tree, int, + bool *); +static tree handle_vector_size_attribute (tree *, tree, tree, int, + bool *); +static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); +static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); +/*not in gdc//static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);*/ +static tree handle_warn_unused_result_attribute (tree *, tree, tree, int, + bool *); +static tree vector_size_helper (tree, tree); + +/*not in gdc//static void check_function_nonnull (tree, tree);*/ +static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); +static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT); +static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *); + +/* extra for gdc copy: */ +static void check_function_arguments_recurse (void (*) + (void *, tree, + unsigned HOST_WIDE_INT), + void *, tree, + unsigned HOST_WIDE_INT); +static tree +handle_format_arg_attribute (tree *node ATTRIBUTE_UNUSED, tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs ATTRIBUTE_UNUSED) +{ + return NULL_TREE; +} +static tree +handle_format_attribute (tree *node ATTRIBUTE_UNUSED, tree name ATTRIBUTE_UNUSED, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs ATTRIBUTE_UNUSED) +{ + return NULL_TREE; +} + +/* -- end extra */ + +/* Table of machine-independent attributes common to all C-like languages. */ +const struct attribute_spec d_common_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "packed", 0, 0, false, false, false, + handle_packed_attribute }, + { "nocommon", 0, 0, true, false, false, + handle_nocommon_attribute }, + { "common", 0, 0, true, false, false, + handle_common_attribute }, + /* FIXME: logically, noreturn attributes should be listed as + "false, true, true" and apply to function types. But implementing this + would require all the places in the compiler that use TREE_THIS_VOLATILE + on a decl to identify non-returning functions to be located and fixed + to check the function type instead. */ + { "noreturn", 0, 0, true, false, false, + handle_noreturn_attribute }, + { "volatile", 0, 0, true, false, false, + handle_noreturn_attribute }, + { "noinline", 0, 0, true, false, false, + handle_noinline_attribute }, + { "always_inline", 0, 0, true, false, false, + handle_always_inline_attribute }, + { "used", 0, 0, true, false, false, + handle_used_attribute }, + { "unused", 0, 0, false, false, false, + handle_unused_attribute }, + /* The same comments as for noreturn attributes apply to const ones. */ + { "const", 0, 0, true, false, false, + handle_const_attribute }, + { "transparent_union", 0, 0, false, false, false, + handle_transparent_union_attribute }, + { "constructor", 0, 0, true, false, false, + handle_constructor_attribute }, + { "destructor", 0, 0, true, false, false, + handle_destructor_attribute }, + { "mode", 1, 1, false, true, false, + handle_mode_attribute }, + { "section", 1, 1, true, false, false, + handle_section_attribute }, + { "aligned", 0, 1, false, false, false, + handle_aligned_attribute }, + { "weak", 0, 0, true, false, false, + handle_weak_attribute }, + { "alias", 1, 1, true, false, false, + handle_alias_attribute }, + { "no_instrument_function", 0, 0, true, false, false, + handle_no_instrument_function_attribute }, + { "malloc", 0, 0, true, false, false, + handle_malloc_attribute }, + { "no_stack_limit", 0, 0, true, false, false, + handle_no_limit_stack_attribute }, + { "pure", 0, 0, true, false, false, + handle_pure_attribute }, + { "deprecated", 0, 0, false, false, false, + handle_deprecated_attribute }, + { "vector_size", 1, 1, false, true, false, + handle_vector_size_attribute }, + { "visibility", 1, 1, true, false, false, + handle_visibility_attribute }, + { "tls_model", 1, 1, true, false, false, + handle_tls_model_attribute }, + { "nonnull", 0, -1, false, true, true, + handle_nonnull_attribute }, + { "nothrow", 0, 0, true, false, false, + handle_nothrow_attribute }, + { "may_alias", 0, 0, false, true, false, NULL }, + /* not in gdc// { "cleanup", 1, 1, true, false, false, + handle_cleanup_attribute },*/ + { "warn_unused_result", 0, 0, false, true, true, + handle_warn_unused_result_attribute }, + { NULL, 0, 0, false, false, false, NULL } +}; + +/* Give the specifications for the format attributes, used by C and all + descendants. */ + +const struct attribute_spec d_common_format_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "format", 3, 3, false, true, true, + handle_format_attribute }, + { "format_arg", 1, 1, false, true, true, + handle_format_arg_attribute }, + { NULL, 0, 0, false, false, false, NULL } +}; + +/* Attribute handlers common to C front ends. */ + +/* Handle a "packed" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_packed_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, + int flags, bool *no_add_attrs) +{ + if (TYPE_P (*node)) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_type_copy (*node); + TYPE_PACKED (*node) = 1; + if (TYPE_MAIN_VARIANT (*node) == *node) + { + /* If it is the main variant, then pack the other variants + too. This happens in, + + struct Foo { + struct Foo const *ptr; // creates a variant w/o packed flag + } __ attribute__((packed)); // packs it now. + */ + tree probe; + + for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe)) + TYPE_PACKED (probe) = 1; + } + + } + else if (TREE_CODE (*node) == FIELD_DECL) + DECL_PACKED (*node) = 1; + /* We can't set DECL_PACKED for a VAR_DECL, because the bit is + used for DECL_REGISTER. It wouldn't mean anything anyway. + We can't set DECL_PACKED on the type of a TYPE_DECL, because + that changes what the typedef is typing. */ + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "nocommon" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_nocommon_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == VAR_DECL) + DECL_COMMON (*node) = 0; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "common" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_common_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == VAR_DECL) + DECL_COMMON (*node) = 1; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "noreturn" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noreturn_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree type = TREE_TYPE (*node); + + /* See FIXME comment in c_common_attribute_table. */ + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_THIS_VOLATILE (*node) = 1; + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + TREE_TYPE (*node) + = build_pointer_type + (build_type_variant (TREE_TYPE (type), + TREE_READONLY (TREE_TYPE (type)), 1)); + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "noinline" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noinline_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + DECL_UNINLINABLE (*node) = 1; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "always_inline" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_always_inline_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + { + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + } + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "used" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_used_attribute (tree *pnode, tree name, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree node = *pnode; + + if (TREE_CODE (node) == FUNCTION_DECL + || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node))) + { + TREE_USED (node) = 1; + } + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "unused" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_unused_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (DECL_P (*node)) + { + tree decl = *node; + + if (TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == LABEL_DECL + || TREE_CODE (decl) == TYPE_DECL) + TREE_USED (decl) = 1; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + } + else + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_type_copy (*node); + TREE_USED (*node) = 1; + } + + return NULL_TREE; +} + +/* Handle a "const" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_const_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree type = TREE_TYPE (*node); + + /* See FIXME comment on noreturn in c_common_attribute_table. */ + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_READONLY (*node) = 1; + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + TREE_TYPE (*node) + = build_pointer_type + (build_type_variant (TREE_TYPE (type), 1, + TREE_THIS_VOLATILE (TREE_TYPE (type)))); + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "transparent_union" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_transparent_union_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, int flags, + bool *no_add_attrs) +{ + tree decl = NULL_TREE; + tree *type = NULL; + int is_type = 0; + + if (DECL_P (*node)) + { + decl = *node; + type = &TREE_TYPE (decl); + is_type = TREE_CODE (*node) == TYPE_DECL; + } + else if (TYPE_P (*node)) + type = node, is_type = 1; + + if (is_type + && TREE_CODE (*type) == UNION_TYPE + && (decl == 0 + || (TYPE_FIELDS (*type) != 0 + && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type))))) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *type = build_type_copy (*type); + TYPE_TRANSPARENT_UNION (*type) = 1; + } + else if (decl != 0 && TREE_CODE (decl) == PARM_DECL + && TREE_CODE (*type) == UNION_TYPE + && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type))) + DECL_TRANSPARENT_UNION (decl) = 1; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "constructor" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_constructor_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + tree decl = *node; + tree type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == FUNCTION_DECL + && TREE_CODE (type) == FUNCTION_TYPE + && decl_function_context (decl) == 0) + { + DECL_STATIC_CONSTRUCTOR (decl) = 1; + TREE_USED (decl) = 1; + } + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "destructor" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_destructor_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + tree decl = *node; + tree type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == FUNCTION_DECL + && TREE_CODE (type) == FUNCTION_TYPE + && decl_function_context (decl) == 0) + { + DECL_STATIC_DESTRUCTOR (decl) = 1; + TREE_USED (decl) = 1; + } + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "mode" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree type = *node; + + *no_add_attrs = true; + + if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE) + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + else + { + int j; + const char *p = IDENTIFIER_POINTER (TREE_VALUE (args)); + int len = strlen (p); + enum machine_mode mode = VOIDmode; + tree typefm; + tree ptr_type; + + if (len > 4 && p[0] == '_' && p[1] == '_' + && p[len - 1] == '_' && p[len - 2] == '_') + { + char *newp = alloca (len - 1); + + strcpy (newp, &p[2]); + newp[len - 4] = '\0'; + p = newp; + } + + /* Change this type to have a type with the specified mode. + First check for the special modes. */ + if (! strcmp (p, "byte")) + mode = byte_mode; + else if (!strcmp (p, "word")) + mode = word_mode; + else if (! strcmp (p, "pointer")) + mode = ptr_mode; + else + for (j = 0; j < NUM_MACHINE_MODES; j++) + if (!strcmp (p, GET_MODE_NAME (j))) + mode = (enum machine_mode) j; + + if (mode == VOIDmode) + error ("unknown machine mode `%s'", p); + else if (0 == (typefm = (*lang_hooks.types.type_for_mode) + (mode, TREE_UNSIGNED (type)))) + error ("no data type for mode `%s'", p); + else if ((TREE_CODE (type) == POINTER_TYPE + || TREE_CODE (type) == REFERENCE_TYPE) + && !(*targetm.valid_pointer_mode) (mode)) + error ("invalid pointer mode `%s'", p); + else + { + /* If this is a vector, make sure we either have hardware + support, or we can emulate it. */ + if (VECTOR_MODE_P (mode) && !vector_mode_valid_p (mode)) + { + error ("unable to emulate '%s'", GET_MODE_NAME (mode)); + return NULL_TREE; + } + + if (TREE_CODE (type) == POINTER_TYPE) + { + ptr_type = build_pointer_type_for_mode (TREE_TYPE (type), + mode); + *node = ptr_type; + } + else if (TREE_CODE (type) == REFERENCE_TYPE) + { + ptr_type = build_reference_type_for_mode (TREE_TYPE (type), + mode); + *node = ptr_type; + } + else + *node = typefm; + /* No need to layout the type here. The caller should do this. */ + } + } + + return NULL_TREE; +} + +/* Handle a "section" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree decl = *node; + + if (targetm.have_named_sections) + { + if ((TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == VAR_DECL) + && TREE_CODE (TREE_VALUE (args)) == STRING_CST) + { + if (TREE_CODE (decl) == VAR_DECL + && current_function_decl != NULL_TREE + && ! TREE_STATIC (decl)) + { + error ("%Jsection attribute cannot be specified for " + "local variables", decl); + *no_add_attrs = true; + } + + /* The decl may have already been given a section attribute + from a previous declaration. Ensure they match. */ + else if (DECL_SECTION_NAME (decl) != NULL_TREE + && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), + TREE_STRING_POINTER (TREE_VALUE (args))) != 0) + { + error ("%Jsection of '%D' conflicts with previous declaration", + *node, *node); + *no_add_attrs = true; + } + else + DECL_SECTION_NAME (decl) = TREE_VALUE (args); + } + else + { + error ("%Jsection attribute not allowed for '%D'", *node, *node); + *no_add_attrs = true; + } + } + else + { + error ("%Jsection attributes are not supported for this target", *node); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "aligned" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, + int flags, bool *no_add_attrs) +{ + tree decl = NULL_TREE; + tree *type = NULL; + int is_type = 0; + tree align_expr = (args ? TREE_VALUE (args) + : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); + int i; + + if (DECL_P (*node)) + { + decl = *node; + type = &TREE_TYPE (decl); + is_type = TREE_CODE (*node) == TYPE_DECL; + } + else if (TYPE_P (*node)) + type = node, is_type = 1; + + /* Strip any NOPs of any kind. */ + while (TREE_CODE (align_expr) == NOP_EXPR + || TREE_CODE (align_expr) == CONVERT_EXPR + || TREE_CODE (align_expr) == NON_LVALUE_EXPR) + align_expr = TREE_OPERAND (align_expr, 0); + + if (TREE_CODE (align_expr) != INTEGER_CST) + { + error ("requested alignment is not a constant"); + *no_add_attrs = true; + } + else if ((i = tree_log2 (align_expr)) == -1) + { + error ("requested alignment is not a power of 2"); + *no_add_attrs = true; + } + else if (i > HOST_BITS_PER_INT - 2) + { + error ("requested alignment is too large"); + *no_add_attrs = true; + } + else if (is_type) + { + /* If we have a TYPE_DECL, then copy the type, so that we + don't accidentally modify a builtin type. See pushdecl. */ + if (decl && TREE_TYPE (decl) != error_mark_node + && DECL_ORIGINAL_TYPE (decl) == NULL_TREE) + { + tree tt = TREE_TYPE (decl); + *type = build_type_copy (*type); + DECL_ORIGINAL_TYPE (decl) = tt; + TYPE_NAME (*type) = decl; + TREE_USED (*type) = TREE_USED (decl); + TREE_TYPE (decl) = *type; + } + else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *type = build_type_copy (*type); + + TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT; + TYPE_USER_ALIGN (*type) = 1; + } + else if (TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != FIELD_DECL) + { + error ("%Jalignment may not be specified for '%D'", decl, decl); + *no_add_attrs = true; + } + else + { + DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT; + DECL_USER_ALIGN (decl) = 1; + } + + return NULL_TREE; +} + +/* Handle a "weak" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_weak_attribute (tree *node, tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs ATTRIBUTE_UNUSED) +{ + declare_weak (*node); + + return NULL_TREE; +} + +/* Handle an "alias" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_alias_attribute (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree decl = *node; + + if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) + || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl))) + { + error ("%J'%D' defined both normally and as an alias", decl, decl); + *no_add_attrs = true; + } + else if (decl_function_context (decl) == 0) + { + tree id; + + id = TREE_VALUE (args); + if (TREE_CODE (id) != STRING_CST) + { + error ("alias arg not a string"); + *no_add_attrs = true; + return NULL_TREE; + } + id = get_identifier (TREE_STRING_POINTER (id)); + /* This counts as a use of the object pointed to. */ + TREE_USED (id) = 1; + + if (TREE_CODE (decl) == FUNCTION_DECL) + DECL_INITIAL (decl) = error_mark_node; + else + DECL_EXTERNAL (decl) = 0; + } + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle an "visibility" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_visibility_attribute (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + tree decl = *node; + tree id = TREE_VALUE (args); + + *no_add_attrs = true; + + if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl)) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + + if (TREE_CODE (id) != STRING_CST) + { + error ("visibility arg not a string"); + return NULL_TREE; + } + + if (strcmp (TREE_STRING_POINTER (id), "default") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; + else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL; + else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; + else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED; + else + error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); + + return NULL_TREE; +} + +/* Handle an "tls_model" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_tls_model_attribute (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree decl = *node; + + if (! DECL_THREAD_LOCAL (decl)) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + else + { + tree id; + + id = TREE_VALUE (args); + if (TREE_CODE (id) != STRING_CST) + { + error ("tls_model arg not a string"); + *no_add_attrs = true; + return NULL_TREE; + } + if (strcmp (TREE_STRING_POINTER (id), "local-exec") + && strcmp (TREE_STRING_POINTER (id), "initial-exec") + && strcmp (TREE_STRING_POINTER (id), "local-dynamic") + && strcmp (TREE_STRING_POINTER (id), "global-dynamic")) + { + error ("tls_model arg must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\""); + *no_add_attrs = true; + return NULL_TREE; + } + } + + return NULL_TREE; +} + +/* Handle a "no_instrument_function" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_instrument_function_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + tree decl = *node; + + if (TREE_CODE (decl) != FUNCTION_DECL) + { + error ("%J'%E' attribute applies only to functions", decl, name); + *no_add_attrs = true; + } + else if (DECL_INITIAL (decl)) + { + error ("%Jcan't set '%E' attribute after definition", decl, name); + *no_add_attrs = true; + } + else + DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1; + + return NULL_TREE; +} + +/* Handle a "malloc" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_malloc_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + DECL_IS_MALLOC (*node) = 1; + /* ??? TODO: Support types. */ + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "no_limit_stack" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_limit_stack_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + tree decl = *node; + + if (TREE_CODE (decl) != FUNCTION_DECL) + { + error ("%J'%E' attribute applies only to functions", decl, name); + *no_add_attrs = true; + } + else if (DECL_INITIAL (decl)) + { + error ("%Jcan't set '%E' attribute after definition", decl, name); + *no_add_attrs = true; + } + else + DECL_NO_LIMIT_STACK (decl) = 1; + + return NULL_TREE; +} + +/* Handle a "pure" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_pure_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + DECL_IS_PURE (*node) = 1; + /* ??? TODO: Support types. */ + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "deprecated" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_deprecated_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, int flags, + bool *no_add_attrs) +{ + tree type = NULL_TREE; + int warn = 0; + const char *what = NULL; + + if (DECL_P (*node)) + { + tree decl = *node; + type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == TYPE_DECL + || TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == FIELD_DECL) + TREE_DEPRECATED (decl) = 1; + else + warn = 1; + } + else if (TYPE_P (*node)) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_type_copy (*node); + TREE_DEPRECATED (*node) = 1; + type = *node; + } + else + warn = 1; + + if (warn) + { + *no_add_attrs = true; + if (type && TYPE_NAME (type)) + { + if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) + what = IDENTIFIER_POINTER (TYPE_NAME (*node)); + else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (type))) + what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); + } + if (what) + warning ("`%s' attribute ignored for `%s'", + IDENTIFIER_POINTER (name), what); + else + warning ("`%s' attribute ignored", + IDENTIFIER_POINTER (name)); + } + + return NULL_TREE; +} + +/* Keep a list of vector type nodes we created in handle_vector_size_attribute, + to prevent us from duplicating type nodes unnecessarily. + The normal mechanism to prevent duplicates is to use type_hash_canon, but + since we want to distinguish types that are essentially identical (except + for their debug representation), we use a local list here. */ +static GTY(()) tree vector_type_node_list = 0; + +/* Handle a "vector_size" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_vector_size_attribute (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + unsigned HOST_WIDE_INT vecsize, nunits; + enum machine_mode mode, orig_mode, new_mode; + tree type = *node, new_type = NULL_TREE; + tree type_list_node; + + *no_add_attrs = true; + + if (! host_integerp (TREE_VALUE (args), 1)) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + + /* Get the vector size (in bytes). */ + vecsize = tree_low_cst (TREE_VALUE (args), 1); + + /* We need to provide for vector pointers, vector arrays, and + functions returning vectors. For example: + + __attribute__((vector_size(16))) short *foo; + + In this case, the mode is SI, but the type being modified is + HI, so we need to look further. */ + + while (POINTER_TYPE_P (type) + || TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE + || TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); + + /* Get the mode of the type being modified. */ + orig_mode = TYPE_MODE (type); + + if (TREE_CODE (type) == RECORD_TYPE + || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT + && GET_MODE_CLASS (orig_mode) != MODE_INT) + || ! host_integerp (TYPE_SIZE_UNIT (type), 1)) + { + error ("invalid vector type for attribute `%s'", + IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + + /* Calculate how many units fit in the vector. */ + nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1); + + /* Find a suitably sized vector. */ + new_mode = VOIDmode; + for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT + ? MODE_VECTOR_INT + : MODE_VECTOR_FLOAT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + if (vecsize == GET_MODE_SIZE (mode) + && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode)) + { + new_mode = mode; + break; + } + + if (new_mode == VOIDmode) + { + error ("no vector mode with the size and type specified could be found"); + return NULL_TREE; + } + + for (type_list_node = vector_type_node_list; type_list_node; + type_list_node = TREE_CHAIN (type_list_node)) + { + tree other_type = TREE_VALUE (type_list_node); + tree record = TYPE_DEBUG_REPRESENTATION_TYPE (other_type); + tree fields = TYPE_FIELDS (record); + tree field_type = TREE_TYPE (fields); + tree array_type = TREE_TYPE (field_type); + if (TREE_CODE (fields) != FIELD_DECL + || TREE_CODE (field_type) != ARRAY_TYPE) + abort (); + + if (TYPE_MODE (other_type) == mode && type == array_type) + { + new_type = other_type; + break; + } + } + + if (new_type == NULL_TREE) + { + tree index, array, rt, list_node; + + new_type = (*lang_hooks.types.type_for_mode) (new_mode, + TREE_UNSIGNED (type)); + + if (!new_type) + { + error ("no vector mode with the size and type specified could be found"); + return NULL_TREE; + } + + new_type = build_type_copy (new_type); + + /* If this is a vector, make sure we either have hardware + support, or we can emulate it. */ + if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT + || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) + && !vector_mode_valid_p (mode)) + { + error ("unable to emulate '%s'", GET_MODE_NAME (mode)); + return NULL_TREE; + } + + /* Set the debug information here, because this is the only + place where we know the underlying type for a vector made + with vector_size. For debugging purposes we pretend a vector + is an array within a structure. */ + index = build_int_2 (TYPE_VECTOR_SUBPARTS (new_type) - 1, 0); + array = build_array_type (type, build_index_type (index)); + rt = make_node (RECORD_TYPE); + + TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array); + DECL_CONTEXT (TYPE_FIELDS (rt)) = rt; + layout_type (rt); + TYPE_DEBUG_REPRESENTATION_TYPE (new_type) = rt; + + list_node = build_tree_list (NULL, new_type); + TREE_CHAIN (list_node) = vector_type_node_list; + vector_type_node_list = list_node; + } + + /* Build back pointers if needed. */ + *node = vector_size_helper (*node, new_type); + + return NULL_TREE; +} + +/* HACK. GROSS. This is absolutely disgusting. I wish there was a + better way. + + If we requested a pointer to a vector, build up the pointers that + we stripped off while looking for the inner type. Similarly for + return values from functions. + + The argument "type" is the top of the chain, and "bottom" is the + new type which we will point to. */ + +static tree +vector_size_helper (tree type, tree bottom) +{ + tree inner, outer; + + if (POINTER_TYPE_P (type)) + { + inner = vector_size_helper (TREE_TYPE (type), bottom); + outer = build_pointer_type (inner); + } + else if (TREE_CODE (type) == ARRAY_TYPE) + { + inner = vector_size_helper (TREE_TYPE (type), bottom); + outer = build_array_type (inner, TYPE_DOMAIN (type)); + } + else if (TREE_CODE (type) == FUNCTION_TYPE) + { + inner = vector_size_helper (TREE_TYPE (type), bottom); + outer = build_function_type (inner, TYPE_ARG_TYPES (type)); + } + else if (TREE_CODE (type) == METHOD_TYPE) + { + inner = vector_size_helper (TREE_TYPE (type), bottom); + outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type), + inner, + TYPE_ARG_TYPES (type)); + } + else + return bottom; + + TREE_READONLY (outer) = TREE_READONLY (type); + TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type); + + return outer; +} + +/* Handle the "nonnull" attribute. */ +static tree +handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED, + tree args, int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + tree type = *node; + unsigned HOST_WIDE_INT attr_arg_num; + + /* If no arguments are specified, all pointer arguments should be + non-null. Verify a full prototype is given so that the arguments + will have the correct types when we actually check them later. */ + if (! args) + { + if (! TYPE_ARG_TYPES (type)) + { + error ("nonnull attribute without arguments on a non-prototype"); + *no_add_attrs = true; + } + return NULL_TREE; + } + + /* Argument list specified. Verify that each argument number references + a pointer argument. */ + for (attr_arg_num = 1; args; args = TREE_CHAIN (args)) + { + tree argument; + unsigned HOST_WIDE_INT arg_num, ck_num; + + if (! get_nonnull_operand (TREE_VALUE (args), &arg_num)) + { + error ("nonnull argument has invalid operand number (arg %lu)", + (unsigned long) attr_arg_num); + *no_add_attrs = true; + return NULL_TREE; + } + + argument = TYPE_ARG_TYPES (type); + if (argument) + { + for (ck_num = 1; ; ck_num++) + { + if (! argument || ck_num == arg_num) + break; + argument = TREE_CHAIN (argument); + } + + if (! argument + || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE) + { + error ("nonnull argument with out-of-range operand number (arg %lu, operand %lu)", + (unsigned long) attr_arg_num, (unsigned long) arg_num); + *no_add_attrs = true; + return NULL_TREE; + } + + if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE) + { + error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)", + (unsigned long) attr_arg_num, (unsigned long) arg_num); + *no_add_attrs = true; + return NULL_TREE; + } + } + } + + return NULL_TREE; +} + +#if 0 +/* not in gdc */ +/* Check the argument list of a function call for null in argument slots + that are marked as requiring a non-null pointer argument. */ + +static void +check_function_nonnull (tree attrs, tree params) +{ + tree a, args, param; + int param_num; + + for (a = attrs; a; a = TREE_CHAIN (a)) + { + if (is_attribute_p ("nonnull", TREE_PURPOSE (a))) + { + args = TREE_VALUE (a); + + /* Walk the argument list. If we encounter an argument number we + should check for non-null, do it. If the attribute has no args, + then every pointer argument is checked (in which case the check + for pointer type is done in check_nonnull_arg). */ + for (param = params, param_num = 1; ; + param_num++, param = TREE_CHAIN (param)) + { + if (! param) + break; + if (! args || nonnull_check_p (args, param_num)) + check_function_arguments_recurse (check_nonnull_arg, NULL, + TREE_VALUE (param), + param_num); + } + } + } +} +#endif + +/* Helper for check_function_nonnull; given a list of operands which + must be non-null in ARGS, determine if operand PARAM_NUM should be + checked. */ + +static bool +nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num) +{ + unsigned HOST_WIDE_INT arg_num; + + for (; args; args = TREE_CHAIN (args)) + { + if (! get_nonnull_operand (TREE_VALUE (args), &arg_num)) + abort (); + + if (arg_num == param_num) + return true; + } + return false; +} + +/* Check that the function argument PARAM (which is operand number + PARAM_NUM) is non-null. This is called by check_function_nonnull + via check_function_arguments_recurse. */ + +static void +check_nonnull_arg (void *ctx ATTRIBUTE_UNUSED, tree param, + unsigned HOST_WIDE_INT param_num) +{ + /* Just skip checking the argument if it's not a pointer. This can + happen if the "nonnull" attribute was given without an operand + list (which means to check every pointer argument). */ + + if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE) + return; + + if (integer_zerop (param)) + warning ("null argument where non-null required (arg %lu)", + (unsigned long) param_num); +} + +/* Helper for nonnull attribute handling; fetch the operand number + from the attribute argument list. */ + +static bool +get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp) +{ + /* Strip any conversions from the arg number and verify they + are constants. */ + while (TREE_CODE (arg_num_expr) == NOP_EXPR + || TREE_CODE (arg_num_expr) == CONVERT_EXPR + || TREE_CODE (arg_num_expr) == NON_LVALUE_EXPR) + arg_num_expr = TREE_OPERAND (arg_num_expr, 0); + + if (TREE_CODE (arg_num_expr) != INTEGER_CST + || TREE_INT_CST_HIGH (arg_num_expr) != 0) + return false; + + *valp = TREE_INT_CST_LOW (arg_num_expr); + return true; +} + +/* Handle a "nothrow" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_nothrow_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_NOTHROW (*node) = 1; + /* ??? TODO: Support types. */ + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +#if 0 +/* not in gdc */ +/* Handle a "cleanup" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_cleanup_attribute (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree decl = *node; + tree cleanup_id, cleanup_decl; + + /* ??? Could perhaps support cleanups on TREE_STATIC, much like we do + for global destructors in C++. This requires infrastructure that + we don't have generically at the moment. It's also not a feature + we'd be missing too much, since we do have attribute constructor. */ + if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl)) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + return NULL_TREE; + } + + /* Verify that the argument is a function in scope. */ + /* ??? We could support pointers to functions here as well, if + that was considered desirable. */ + cleanup_id = TREE_VALUE (args); + if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE) + { + error ("cleanup arg not an identifier"); + *no_add_attrs = true; + return NULL_TREE; + } + cleanup_decl = lookup_name (cleanup_id); + if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL) + { + error ("cleanup arg not a function"); + *no_add_attrs = true; + return NULL_TREE; + } + + /* That the function has proper type is checked with the + eventual call to build_function_call. */ + + return NULL_TREE; +} +#endif + +/* Handle a "warn_unused_result" attribute. No special handling. */ + +static tree +handle_warn_unused_result_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + /* Ignore the attribute for functions not returning any value. */ + if (VOID_TYPE_P (TREE_TYPE (*node))) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +#if 0 +/* not in gdc */ +/* Check for valid arguments being passed to a function. */ +static void +check_function_arguments (tree attrs, tree params) +{ + /* Check for null being passed in a pointer argument that must be + non-null. We also need to do this if format checking is enabled. */ + + if (warn_nonnull) + check_function_nonnull (attrs, params); + + /* Check for errors in format strings. */ + + if (warn_format) + check_function_format (NULL, attrs, params); +} +#endif + +/* Generic argument checking recursion routine. PARAM is the argument to + be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked + once the argument is resolved. CTX is context for the callback. */ +void +check_function_arguments_recurse (void (*callback) + (void *, tree, unsigned HOST_WIDE_INT), + void *ctx, tree param, + unsigned HOST_WIDE_INT param_num) +{ + if (TREE_CODE (param) == NOP_EXPR) + { + /* Strip coercion. */ + check_function_arguments_recurse (callback, ctx, + TREE_OPERAND (param, 0), param_num); + return; + } + + if (TREE_CODE (param) == CALL_EXPR) + { + tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0))); + tree attrs; + bool found_format_arg = false; + + /* See if this is a call to a known internationalization function + that modifies a format arg. Such a function may have multiple + format_arg attributes (for example, ngettext). */ + + for (attrs = TYPE_ATTRIBUTES (type); + attrs; + attrs = TREE_CHAIN (attrs)) + if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs))) + { + tree inner_args; + tree format_num_expr; + int format_num; + int i; + + /* Extract the argument number, which was previously checked + to be valid. */ + format_num_expr = TREE_VALUE (TREE_VALUE (attrs)); + while (TREE_CODE (format_num_expr) == NOP_EXPR + || TREE_CODE (format_num_expr) == CONVERT_EXPR + || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR) + format_num_expr = TREE_OPERAND (format_num_expr, 0); + + if (TREE_CODE (format_num_expr) != INTEGER_CST + || TREE_INT_CST_HIGH (format_num_expr) != 0) + abort (); + + format_num = TREE_INT_CST_LOW (format_num_expr); + + for (inner_args = TREE_OPERAND (param, 1), i = 1; + inner_args != 0; + inner_args = TREE_CHAIN (inner_args), i++) + if (i == format_num) + { + check_function_arguments_recurse (callback, ctx, + TREE_VALUE (inner_args), + param_num); + found_format_arg = true; + break; + } + } + + /* If we found a format_arg attribute and did a recursive check, + we are done with checking this argument. Otherwise, we continue + and this will be considered a non-literal. */ + if (found_format_arg) + return; + } + + if (TREE_CODE (param) == COND_EXPR) + { + /* Check both halves of the conditional expression. */ + check_function_arguments_recurse (callback, ctx, + TREE_OPERAND (param, 1), param_num); + check_function_arguments_recurse (callback, ctx, + TREE_OPERAND (param, 2), param_num); + return; + } + + (*callback) (ctx, param, param_num); +} diff -uNr gdc-0.11/d/d-builtins2.cc gdc-0.12/d/d-builtins2.cc --- gdc-0.11/d/d-builtins2.cc 2005-02-21 02:40:45.000000000 +0100 +++ gdc-0.12/d/d-builtins2.cc 2005-05-08 16:01:26.000000000 +0200 @@ -101,6 +101,12 @@ break; case REAL_TYPE: { + // Double and long double may be the same size + if (t == double_type_node) + return Type::tfloat64; + else if (t == long_double_type_node) + return Type::tfloat80; + unsigned sz = tree_low_cst( TYPE_SIZE_UNIT( t ), 1 ); for (int i = 0; i < (int) TMAX; i++) { d = Type::basic[i]; diff -uNr gdc-0.11/d/d-builtins.c gdc-0.12/d/d-builtins.c --- gdc-0.11/d/d-builtins.c 2005-02-21 02:40:45.000000000 +0100 +++ gdc-0.12/d/d-builtins.c 2005-05-07 18:06:03.000000000 +0200 @@ -50,7 +50,11 @@ #if D_GCC_VER < 34 #include "d-bi-attrs-33.h" #elif D_GCC_VER < 40 -#include "d-bi-attrs-34.h" +# ifdef D_GCC_VER341 +# include "d-bi-attrs-341.h" +# else +# include "d-bi-attrs-34.h" +# endif #else #include "d-bi-attrs-40.h" #endif diff -uNr gdc-0.11/d/d-codegen.cc gdc-0.12/d/d-codegen.cc --- gdc-0.11/d/d-codegen.cc 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/d-codegen.cc 2005-05-29 00:00:56.000000000 +0200 @@ -37,11 +37,20 @@ #endif IRState gen; // Top-level IRState +bool IRState::inGenObjFile; ModuleInfo IRState::moduleInfo; Array IRState::stmtExprList; TemplateEmission IRState::emitTemplates; bool IRState::warnSignCompare = false; bool IRState::originalOmitFramePointer; +tree IRState::staticCtorList = NULL_TREE; + +bool +d_gcc_force_templates() +{ + return IRState::emitTemplates == TEprivate || + IRState::emitTemplates == TEall; +} void IRState::doLineNote(const Loc & loc) @@ -121,23 +130,34 @@ bool is_template = false; Dsymbol * sym = dsym->toParent(); + Module * ti_obj_file_mod; while (sym) { - if (sym->isTemplateInstance()) { + TemplateInstance * ti = sym->isTemplateInstance(); + if (ti) { + ti_obj_file_mod = ti->objFileModule; is_template = true; break; } sym = sym->toParent(); } + bool is_static; + if (is_template) { D_DECL_ONE_ONLY( decl_tree ) = 1; D_DECL_IS_TEMPLATE( decl_tree ) = 1; + is_static = ti_obj_file_mod == getCurrentModule() && emitTemplates != TEnone; + } else { + is_static = dsym->getModule() == getCurrentModule(); } - - bool is_static = is_template ? - emitTemplates != TEnone : // only because of the change in templates.c that emit all instances in this module - dsym->getModule() == getCurrentModule(); + /* + if (func_decl) + fprintf(stderr, "%s: is_template = %d is_static = %d te = %d m = %s cur = %s\n", + func_decl->toPrettyChars(), is_template, is_static, emitTemplates, + dsym->getModule() ? dsym->getModule()->toChars() : "ZOMGNONE?", + getCurrentModule()->toChars()); + */ if ( is_static ) { DECL_EXTERNAL( decl_tree ) = 0; @@ -176,17 +196,13 @@ } // %% Need to do this now, or Mach-O will have stub issues ? - if (is_template && emitTemplates == TEprivate) { + if (is_template && is_static && emitTemplates == TEprivate) { TREE_PRIVATE(decl_tree) = 1; TREE_PUBLIC(decl_tree) = 0; } - if ( func_decl ) { - if (func_decl->isNested()) { - TREE_PUBLIC( decl_tree ) = 0; - } - } - + if ( func_decl && func_decl->isNested() ) + TREE_PUBLIC( decl_tree ) = 0; } else { TREE_STATIC( decl_tree ) = 0; DECL_EXTERNAL( decl_tree ) = 0; @@ -203,14 +219,19 @@ IRState::prepareSymbolOutput(Symbol * s) { tree decl_tree = s->Stree; - // make_decl_one_only checks variables for DECL_INITIAL. - // If it doesn't have one, it makes in a common variable. - // This is no good because we don't have DECL_INITIAL - // until the variable is emitted. So.... - + /* make_decl_one_only checks variables for DECL_INITIAL. + If it doesn't have one, it makes in a common variable. + This is a problem because we don't have DECL_INITIAL + until the variable is emitted. Solution is to call this + routine after DECL_INITIAL is set and before + rest_of_decl_compilation. */ + if (D_DECL_ONE_ONLY(decl_tree)) { - if (SUPPORTS_ONE_ONLY // have to check, otherwise backend will abort - && ! (D_DECL_IS_TEMPLATE( decl_tree ) && emitTemplates == TEprivate) // this check is only to make -femit-templates=private work on targets that it is not actually needed... + if (SUPPORTS_ONE_ONLY // Must check, otherwise backend will abort + + /* This check is only to make -femit-templates=private work on + targets that it is not actually needed. */ + && ! (D_DECL_IS_TEMPLATE( decl_tree ) && emitTemplates == TEprivate) ) { // this sets TREE_PUBLIC make_decl_one_only( decl_tree ); @@ -242,13 +263,9 @@ (* targetm.asm_out.constructor) (XEXP (DECL_RTL (decl_tree), 0), DEFAULT_INIT_PRIORITY); } else { + // change to list maker... + staticCtorList = tree_cons(NULL_TREE, decl_tree, staticCtorList); // %%TODO: fallback if ! targetm.have_ctors_dtors - - static bool apologized = false; - if (! apologized) { - sorry("system does not support init functions and fallbacks have not been implemented yet"); - apologized = true; - } } } } @@ -397,10 +414,15 @@ tree IRState::declContext(Dsymbol * d_sym) { + Dsymbol * orig_sym = d_sym; AggregateDeclaration * agg_decl; while ( (d_sym = d_sym->toParent()) ) { - if (d_sym->isFuncDeclaration()) { + if (d_sym->isFuncDeclaration()) { + // 3.3.x (others?) dwarf2out chokes without this check... (output_pubnames) + FuncDeclaration * f = orig_sym->isFuncDeclaration(); + if (f && ! f->isNested()) + return 0; return d_sym->toSymbol()->Stree; } else if ( (agg_decl = d_sym->isAggregateDeclaration()) ) { tree type = agg_decl->type->toCtype(); @@ -593,7 +615,7 @@ } else if (target_type->ty == Tarray) { TypeSArray * a_type = (TypeSArray*) exp_type; - unsigned array_len = a_type->dim->toInteger(); + unsigned array_len = a_type->dim->toUInteger(); unsigned sz_a = a_type->next->size(); unsigned sz_b = target_type->next->size(); @@ -817,7 +839,7 @@ final_sa_elem_type(target_base_type)->equals(exp_base_type)) { // %% what about implicit converions...? TypeSArray * sa_type = (TypeSArray *) target_base_type; - xdmd_integer_t count = sa_type->dim->toInteger(); + uinteger_t count = sa_type->dim->toUInteger(); tree ctor = make_node( CONSTRUCTOR ); TREE_TYPE( ctor ) = target_type->toCtype(); @@ -911,7 +933,7 @@ if (exp->type) { exp = exp->integralPromotions(); // %% figure out why I needed this... - if (exp->type->ty == Tsarray) + if (exp->type->toBasetype()->ty == Tsarray) exp = exp->castTo( exp->type->toBasetype()->next->arrayOf() ); } return exp->toElem( this ); @@ -1801,6 +1823,7 @@ fnname = XSTR(XEXP(DECL_RTL(thunk_decl), 0), 0); initFunctionStart(thunk_decl, 0); + current_function_is_thunk = 1; assemble_start_function (thunk_decl, fnname); targetm.asm_out.output_mi_thunk (asm_out_file, thunk_decl, delta, 0, alias); @@ -1819,7 +1842,7 @@ } tree -IRState::doSimpleFunction(Module * mod, const char * name, tree expr, bool static_ctor) +IRState::doSimpleFunction(Module * mod, const char * name, tree expr, bool static_ctor, bool public_fn) { TypeFunction * func_type = new TypeFunction(0, Type::tvoid, 0, LINKc); FuncDeclaration * func = new FuncDeclaration(mod->loc, mod->loc, // %% locs may be wrong @@ -1834,7 +1857,9 @@ DECL_STATIC_CONSTRUCTOR( func_decl ) = 1; // apparently, the back end doesn't do anything with this TREE_USED( func_decl ) = 1; // only needed for GCC 3.3? } - TREE_PUBLIC( func_decl ) = 0; // these are always private (see IRState::setupSymbolStorage, default case) + // D static ctors, dtors, unittests, and the ModuleInfo chain function + // are always private (see IRState::setupSymbolStorage, default case) + TREE_PUBLIC( func_decl ) = public_fn; // %% maybe remove the identifier @@ -2173,7 +2198,7 @@ Type * base_type = exp_type->toBasetype(); switch (base_type->ty) { case Tsarray: - return size_int( ((TypeSArray *) base_type)->dim->toInteger() ); + return size_int( ((TypeSArray *) base_type)->dim->toUInteger() ); case Tarray: return darrayLenRef(exp); default: @@ -2346,13 +2371,22 @@ { Type * obj_type = obj_exp->type->toBasetype(); if (func->isThis()) { + bool is_dottype; tree this_expr; // DotTypeExp cannot be evaluated - if (obj_exp->op != TOKdottype) - this_expr = obj_exp->toElem( this ); - else + if (obj_exp->op == TOKdottype) { + is_dottype = true; this_expr = ((DotTypeExp *) obj_exp)->e1->toElem( this ); + } else if (obj_exp->op == TOKcast && + ((CastExp*) obj_exp)->e1->op == TOKdottype) { + is_dottype = true; + // see expression.c:"See if we need to adjust the 'this' pointer" + this_expr = ((DotTypeExp *) ((CastExp*) obj_exp)->e1)->e1->toElem( this ); + } else { + is_dottype = false; + this_expr = obj_exp->toElem( this ); + } // Calls to super are static (func is the super's method) // Structs don't have vtables. @@ -2361,8 +2395,7 @@ if (obj_exp->op == TOKsuper || obj_type->ty == Tstruct || obj_type->ty == Tpointer || - func->isFinal() || ! func->isVirtual() || - obj_exp->op == TOKdottype) { + func->isFinal() || ! func->isVirtual() || is_dottype) { if (obj_type->ty == Tstruct) this_expr = addressOf(this_expr); @@ -2514,7 +2547,8 @@ tree IRState::aggDeclStaticInit(AggregateDeclaration * agg_decl) { - SymbolDeclaration * symdec = new SymbolDeclaration(0, agg_decl->toInitializer()); + SymbolDeclaration * symdec = new SymbolDeclaration(0, agg_decl->toInitializer(), + agg_decl->isStructDeclaration()); tree t = symdec->toSymbol()->Stree; delete symdec; return t; @@ -2668,7 +2702,7 @@ } tree -IRState::arrayType(tree type_node, xdmd_integer_t size) +IRState::arrayType(tree type_node, uinteger_t size) { tree index_type_node; if (size > 0) { @@ -3217,6 +3251,13 @@ //SET_DECL_OFFSET_ALIGN (field_decl, BIGGEST_ALIGNMENT); // ? layout_decl( field_decl, 0 ); + + // get_inner_reference doesn't check these, leaves a variable unitialized + // DECL_SIZE is NULL if size is zero. + if (var_decl->size(var_decl->loc)) { + assert(DECL_MODE(field_decl) != VOIDmode); + assert(DECL_SIZE(field_decl) != NULL_TREE); + } fieldList.chain( field_decl ); } } diff -uNr gdc-0.11/d/d-codegen.h gdc-0.12/d/d-codegen.h --- gdc-0.11/d/d-codegen.h 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/d-codegen.h 2005-05-25 03:51:33.000000000 +0200 @@ -85,12 +85,12 @@ typedef enum { TEnone, - TEfull, + TEnormal, + TEall, TEprivate, TEauto } TemplateEmission; - // Code generation routines should be in a separate namespace, but so many // routines need a reference to an IRState to expand Expressions. Solution // is to make IRState the code generation namespace with the actual IR state @@ -212,9 +212,9 @@ static bool isArgumentReferenceType(Argument * arg); static tree trueArgumentType(Argument * arg); - static tree arrayType(Type * d_type, xdmd_integer_t size) // %% use of integer_t + static tree arrayType(Type * d_type, uinteger_t size) // %% use of integer_t { return arrayType(d_type->toCtype(), size); } - static tree arrayType(tree type_node, xdmd_integer_t size); + static tree arrayType(tree type_node, uinteger_t size); // Can't call this until common types have been built static bool haveLongDouble() { @@ -418,6 +418,7 @@ tree typeinfoReference(Type * t); // ** Other + static bool inGenObjFile; static Module * builtinsModule; static Module * intrinsicModule; @@ -439,7 +440,7 @@ void outputThunk(tree thunk_decl, tree target_decl, int offset); public: - tree doSimpleFunction(Module * mod, const char * name, tree expr, bool static_ctor); + tree doSimpleFunction(Module * mod, const char * name, tree expr, bool static_ctor, bool public_fn = false); tree doFunctionToCallFunctions(Module * mod, const char * name, Array * functions); // Create a tree node to set multiple elements to a single value @@ -505,6 +506,9 @@ static ModuleInfo moduleInfo; ModuleInfo & getModuleInfo() { return moduleInfo; } + // ** static constructors (not D static constructors) + static tree staticCtorList; // not an array since there is at most one + static void rodc(tree decl, int top_level) { #if D_GCC_VER < 40 diff -uNr gdc-0.11/d/d-decls.cc gdc-0.12/d/d-decls.cc --- gdc-0.11/d/d-decls.cc 2005-04-26 03:45:07.000000000 +0200 +++ gdc-0.12/d/d-decls.cc 2005-05-27 03:05:04.000000000 +0200 @@ -51,11 +51,12 @@ /********************************* SymbolDeclaration ****************************/ -SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s) +SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym) : Declaration(new Identifier(s->Sident, TOKidentifier)) { this->loc = loc; sym = s; + this->dsym = dsym; storage_class |= STCconst; } @@ -63,9 +64,8 @@ { // Create the actual back-end value if not yet done if (! sym->Stree) { - AggregateDeclaration * agg_decl = sym->Sspecial.aggDecl; - agg_decl->toInitializer(); // Try to create the VAR_DECL... - // ... If it didn't work, then the returned Symbol* is invalid + if (dsym) + dsym->toInitializer(); assert(sym->Stree); } return sym; @@ -93,7 +93,7 @@ Symbol *Dsymbol::toSymbol() { - printf("Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind()); + fprintf(stderr, "Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind()); assert(0); // BUG: implement return NULL; } @@ -425,7 +425,7 @@ case LINKcpp: break; default: - printf("linkage = %d\n", linkage); + fprintf(stderr, "linkage = %d\n", linkage); assert(0); } @@ -505,8 +505,8 @@ #if D_GCC_VER >= 34 DECL_DECLARED_INLINE_P(thunk_decl) = 0; #endif - D_DECL_ONE_ONLY(thunk_decl) = D_DECL_ONE_ONLY(target_func_decl);//needed on some targets to avoid "causes a section type conflict" //EXPERenb - //EXPER//D_DECL_IS_TEMPLATE(thunk_decl) = D_DECL_IS_TEMPLATE(target_func_decl); // This does not do anything now. + //needed on some targets to avoid "causes a section type conflict" + D_DECL_ONE_ONLY(thunk_decl) = D_DECL_ONE_ONLY(target_func_decl); TREE_ADDRESSABLE(thunk_decl) = 1; TREE_USED (thunk_decl) = 1; @@ -528,86 +528,6 @@ return thunk->symbol; } -#if 0 -Symbol *FuncDeclaration::toThunkSymbol(int offset) -{ - Symbol *sthunk; - Thunk * thunk; - bool is_extern; - - toSymbol(); - is_extern = DECL_EXTERNAL( csym->Stree ); // shortcut for shouldEmit, isTemplate, etc. - - /* If the thunk is to be static (that is, it is being emitted in this - module, there can only be one FUNCTION_DECL for it. Thus, there - is a list of all thunks for a given function. */ - if ( ! csym->Sspecial.thunks ) - csym->Sspecial.thunks = new Array; - Array & thunks = * csym->Sspecial.thunks; - bool found = false; - - for (unsigned i = 0; i < thunks.dim; i++) { - thunk = (Thunk *) thunks.data[i]; - if (thunk->offset == offset) { - found = true; - break; - } - } - - if (! found) { - thunk = new Thunk; - thunk->offset = offset; - thunks.push(thunk); - } - - if ( ! thunk->symbol ) { - char *id; - char *n; - //type *t; - - n = csym->Sident; // dmd uses 'sym' -- not sure what that is... - id = (char *) alloca(8 + 5 + strlen(n) + 1); - sprintf(id,"_thunk%d__%s", offset, n); - sthunk = symbol_calloc(id); - slist_add(sthunk); - //sthunk = symbol_generate(SCstatic, csym->Stype); - //sthunk->Sflags |= SFLimplem; - - tree target_func_decl = csym->Stree; - tree thunk_decl = build_decl(FUNCTION_DECL, get_identifier(id), TREE_TYPE( target_func_decl )); - dkeep(thunk_decl); - sthunk->Stree = thunk_decl; - - SET_DECL_ASSEMBLER_NAME(thunk_decl, DECL_NAME(thunk_decl)); - DECL_CONTEXT(thunk_decl) = DECL_CONTEXT(target_func_decl); // from c++... - TREE_READONLY(thunk_decl) = TREE_READONLY(target_func_decl); - TREE_THIS_VOLATILE(thunk_decl) = TREE_THIS_VOLATILE(target_func_decl); - TREE_PUBLIC(thunk_decl) = TREE_PUBLIC(target_func_decl); - DECL_ARTIFICIAL(thunk_decl) = 1; - DECL_NO_STATIC_CHAIN(thunk_decl) = 1; - DECL_INLINE(thunk_decl) = 0; -#if D_GCC_VER >= 34 - DECL_DECLARED_INLINE_P(thunk_decl) = 0; -#endif - D_DECL_ONE_ONLY(thunk_decl) = D_DECL_ONE_ONLY(target_func_decl); - D_DECL_IS_TEMPLATE(thunk_decl) = D_DECL_IS_TEMPLATE(target_func_decl); // This does not do anything now. - - TREE_ADDRESSABLE(thunk_decl) = 1; - TREE_USED (thunk_decl) = 1; // assuming only called if it will be used - - gen.prepareSymbolOutput(sthunk); - - if (is_extern) { - DECL_EXTERNAL( thunk_decl ) = 1; - } else { - gen.doThunk(thunk_decl, target_func_decl, offset); - } - - thunk->symbol = sthunk; - } - return thunk->symbol; -} -#endif /**************************************** * Create a static symbol we can hang DT initializers onto. @@ -705,7 +625,6 @@ TREE_TYPE(some_type->toCtype())); // want the RECORD_TYPE, not the REFERENCE_TYPE csym->Stree = decl; #if D_GCC_VER >= 34 - // EXPER /* csym->ScontextDecl = build_decl(TRANSLATION_UNIT_DECL, NULL, NULL); dkeep(csym->ScontextDecl); @@ -715,8 +634,12 @@ dkeep(decl); gen.setupStaticStorage(this, decl); + // EXPER disab//? DMD doesn't actually use weak refs? + /* if (DECL_EXTERNAL( decl ) && (SUPPORTS_WEAK)) declare_weak( decl ); + */ + TREE_CONSTANT( decl ) = 0; // *not* readonly, moduleinit depends on this TREE_READONLY( decl ) = 0; // Not an lvalue, tho } @@ -764,6 +687,12 @@ /* Because this is called from the front end (mtype.cc:TypeStruct::defaultInit()), we need to hold off using back-end stuff until the toobjfile phase. + + Specifically, it is not safe create a VAR_DECL with a type from toCtype() + because there may be unresolved recursive references. + StructDeclaration::toObjFile calls toInitializer without ever calling + SymbolDeclaration::toSymbol, so we just need to keep checking if we + are in the toObjFile phase. */ Symbol *AggregateDeclaration::toInitializer() @@ -781,29 +710,27 @@ id = (char *) alloca(6 + strlen(n) + 1); sprintf(id,"_init_%s",n); s = symbol_calloc(id); - s->Sspecial.aggDecl = this; slist_add(s); sinit = s; } - if (! sinit->Stree) { - if (getCurrentModule()) { - tree struct_type = type->toCtype(); - if ( POINTER_TYPE_P( struct_type ) ) - struct_type = TREE_TYPE( struct_type ); // for TypeClass, want the RECORD_TYPE, not the REFERENCE_TYPE - tree t = build_decl(VAR_DECL, get_identifier(sinit->Sident), struct_type); - sinit->Stree = t; - dkeep(t); - - gen.setupStaticStorage(this, t); - - // %% what's the diff between setting this stuff on the DECL and the - // CONSTRUCTOR itself? - - TREE_ADDRESSABLE( t ) = 1; - TREE_CONSTANT( t ) = 1; - TREE_READONLY( t ) = 1; - DECL_CONTEXT( t ) = 0; // These are always global - } + if (! sinit->Stree && gen.inGenObjFile) + { + tree struct_type = type->toCtype(); + if ( POINTER_TYPE_P( struct_type ) ) + struct_type = TREE_TYPE( struct_type ); // for TypeClass, want the RECORD_TYPE, not the REFERENCE_TYPE + tree t = build_decl(VAR_DECL, get_identifier(sinit->Sident), struct_type); + sinit->Stree = t; + dkeep(t); + + gen.setupStaticStorage(this, t); + + // %% what's the diff between setting this stuff on the DECL and the + // CONSTRUCTOR itself? + + TREE_ADDRESSABLE( t ) = 1; + TREE_CONSTANT( t ) = 1; + TREE_READONLY( t ) = 1; + DECL_CONTEXT( t ) = 0; // These are always global } return sinit; } diff -uNr gdc-0.11/d/d-dmd-gcc.h gdc-0.12/d/d-dmd-gcc.h --- gdc-0.11/d/d-dmd-gcc.h 2005-01-10 04:30:55.000000000 +0100 +++ gdc-0.12/d/d-dmd-gcc.h 2005-05-25 03:51:33.000000000 +0200 @@ -36,6 +36,11 @@ /* used in toobj.c */ struct VarDeclaration; extern void d_gcc_emit_local_variable(VarDeclaration *); +extern bool d_gcc_supports_weak(); + +/* used in template.c */ +extern bool d_gcc_force_templates(); +extern Module * getCurrentModule(); #endif diff -uNr gdc-0.11/d/d-gcc-real.cc gdc-0.12/d/d-gcc-real.cc --- gdc-0.11/d/d-gcc-real.cc 2005-04-24 18:48:31.000000000 +0200 +++ gdc-0.12/d/d-gcc-real.cc 2005-05-07 18:06:03.000000000 +0200 @@ -385,6 +385,6 @@ { char buf[128]; format(buf, sizeof(buf)); - printf("%s\n", buf); + fprintf(stderr, "%s\n", buf); } diff -uNr gdc-0.11/d/d-glue.cc gdc-0.12/d/d-glue.cc --- gdc-0.11/d/d-glue.cc 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/d-glue.cc 2005-05-27 03:05:04.000000000 +0200 @@ -615,9 +615,12 @@ elem * AddExp::toElem(IRState* irs) { - if ((e1->type->ty == Tarray || e1->type->ty == Tsarray) && - (e2->type->ty == Tarray || e2->type->ty == Tsarray) ) { - ::error("Array operations not implemented"); + TY ty1 = e1->type->toBasetype()->ty; + TY ty2 = e2->type->toBasetype()->ty; + + if ((ty1 == Tarray || ty1 == Tsarray) && + (ty2 == Tarray || ty2 == Tsarray) ) { + error("Array operations not implemented"); return error_mark_node; } else // The front end has already taken care of (pointer + integer) @@ -1217,9 +1220,10 @@ return irs->libCall(lib_call, 1, & t); } -elem * BoolExp::toElem(IRState *) +elem * +BoolExp::toElem(IRState * irs) { - return op == TOKtrue ? boolean_true_node : boolean_false_node; + return d_convert_basic(type->toCtype(), irs->convertForCondition(e1)); } elem * @@ -1269,7 +1273,7 @@ Expression * rec_exp = ((AddrExp*) add_exp->e1)->e1; rec_type = rec_exp->type->toBasetype(); rec_tree = rec_exp->toElem(irs); - the_offset = add_exp->e2->toInteger(); + the_offset = add_exp->e2->toUInteger(); } } else if (e1->op == TOKsymoff) { SymOffExp * sym_exp = (SymOffExp *) e1; @@ -1327,7 +1331,7 @@ elem * Expression::toElem(IRState*) { - error("abstract Expression::toElem called\n"); + error("abstract Expression::toElem called"); return error_mark_node; } @@ -1357,7 +1361,7 @@ error("delegates are only for non-static functions"); return irs->objectInstanceMethod(e1, func, type); } else { - assert(func->isNested()); + assert(func->isNested() || func->isThis()); return irs->methodCallExpr(irs->functionPointer(func), func->isNested() ? d_null_pointer : e1->toElem(irs), type); } @@ -1456,6 +1460,10 @@ cur_irs->emitLocalVar(v); } +bool d_gcc_supports_weak() +{ + return SUPPORTS_WEAK; +} // %% check calling this directly? elem * @@ -1544,15 +1552,10 @@ NewExp::toElem(IRState * irs) { Type * base_type = type->toBasetype(); - Array actual_new_args; tree result; - if (newargs && allocator) { - actual_new_args.reserve(newargs->dim + 1); - actual_new_args.push(0); // size filled in below - actual_new_args.append( newargs ); - } else - actual_new_args.reserve(3); + if (allocator) + assert(newargs); switch (base_type->ty) { case Tclass: @@ -1565,10 +1568,9 @@ tree rec_type = TREE_TYPE( class_type->toCtype() ); tree exp_node; - actual_new_args.data[0] = new IntegerExp(loc, class_type->sym->structsize, Type::tuns32); - new_call = irs->call(allocator, & actual_new_args); + new_call = irs->call(allocator, newargs); // %% playing fast and loose with type vs. base_type vs. class_type - if (1) { + //if (1) { // first, save the result of the allocation call new_call = save_expr( new_call ); // copy memory... @@ -1578,15 +1580,14 @@ irs->aggDeclStaticInit(class_type->sym)); //class_type->defaultInit()->toElem( irs )); // the constructor needs the reference, tho.. - // is addr_of bettern than compound (indirect(ptr),ptr) ? new_call = build(COMPOUND_EXPR, TREE_TYPE(new_call), exp_node, new_call); // new_call = irs->addressOf(exp_node); - } else { + /*} else { exp_node = build(MODIFY_EXPR, rec_type, build1(INDIRECT_REF, rec_type, new_call ), irs->aggDeclStaticInit(class_type->sym)); new_call = build1(ADDR_EXPR, class_type->toCtype(), exp_node); - } + }*/ } else { tree arg = irs->addressOf( class_type->sym->toSymbol()->Stree ); new_call = irs->libCall(LIBCALL_NEWCLASS, 1, & arg); @@ -1620,7 +1621,7 @@ } else { while (elem_type->ty == Tsarray) { - multiple = ((TypeSArray *) elem_type)->dim->toInteger() * multiple; + multiple = ((TypeSArray *) elem_type)->dim->toUInteger() * multiple; elem_type = elem_type->next->toBasetype(); } @@ -1670,23 +1671,28 @@ { Type * object_type = base_type->next->toBasetype(); tree new_call; + tree t; if (allocator) { - actual_new_args.data[0] = new IntegerExp(loc, object_type->size(), Type::tuns32); - new_call = irs->call(allocator, & actual_new_args); + new_call = irs->call(allocator, newargs); } else { + Array built_new_args; // there doesn't seem to be any simple allocation call... // just need a wrapper around gc.alloc - actual_new_args.push( new IntegerExp( 1 )); - actual_new_args.push( new IntegerExp(loc, object_type->size(), Type::tuns32 )); - new_call = irs->libCall(LIBCALL_NEW, & actual_new_args); + built_new_args.reserve(2); + built_new_args.push( new IntegerExp( 1 )); + built_new_args.push( new IntegerExp(loc, object_type->size(), Type::tuns32 )); + new_call = irs->libCall(LIBCALL_NEW, & built_new_args); new_call = irs->darrayPtrRef(new_call); } new_call = build1(NOP_EXPR, base_type->toCtype(), new_call); if ( ! object_type->isZeroInit() ) { - new_call = build1(INDIRECT_REF, TREE_TYPE(TREE_TYPE(new_call)), new_call); - new_call = build(MODIFY_EXPR, TREE_TYPE(new_call), new_call, + // Save the result allocation call. + new_call = save_expr( new_call ); + t = build1(INDIRECT_REF, TREE_TYPE(TREE_TYPE( new_call )), new_call); + t = build(MODIFY_EXPR, TREE_TYPE(t), t, irs->convertForAssignment(object_type->defaultInit(), object_type) ); - new_call = build1(ADDR_EXPR, type->toCtype(), new_call); + //new_call = build1(ADDR_EXPR, type->toCtype(), new_call); + new_call = build(COMPOUND_EXPR, TREE_TYPE(new_call), t, new_call); } return new_call; } @@ -2045,7 +2051,8 @@ rest_of_decl_compilation(fn_decl, NULL, 1, 0); } - pushdecl(fn_decl); // %%EXPERIMENTAL -- don't pushdecl functions! + //pushdecl(fn_decl); // %%EXPERIMENTAL -- don't pushdecl functions! + /* (wouldn't this conflict with the TYPE_METHODS chain?) */ } #elif D_GCC_VER >= 40 void @@ -2249,7 +2256,7 @@ rest_of_decl_compilation(fn_decl, 1, 0); } - pushdecl(fn_decl); // %%EXPERIMENTAL -- don't pushdecl functions! + //pushdecl(fn_decl); // %%EXPERIMENTAL -- don't pushdecl functions! } #else #error Fix @@ -2270,6 +2277,7 @@ { IRState * ir_state = new IRState; cur_irs = ir_state; + IRState::inGenObjFile = true; if (members) { for (unsigned i = 0; i < members->dim; i++) { @@ -2315,12 +2323,20 @@ TREE_STATIC( */ - - // all this for: - // void init() { - // our_mod_ref.next = _Dmodule_ref; - // _Dmodule_ref = & our_mod_ref; - // } + /* + Generate: + struct _modref_t { + _modref_t * next; + ModuleInfo m; + } + extern (C) _modref_t * _Dmodule_ref; + private _modref_t our_mod_ref = + { next: null, m: _ModuleInfo_xxx }; + void ___modinit() { + our_mod_ref.next = _Dmodule_ref; + _Dmodule_ref = & our_mod_ref; + } + */ // struct ModuleReference in moduleinit.d tree mod_ref_type = gen.twoFieldType(Type::tvoid->pointerTo(), gen.getObjectType()); @@ -2357,6 +2373,27 @@ } } + if (IRState::staticCtorList) { + // silly, since we are usually just aclling ___modinit... + // ___modinit should be this function... + + // note: list is backwards.. + tree exp = NULL_TREE; + tree call_exp = NULL_TREE; + tree p = IRState::staticCtorList; + while (p) { + call_exp = gen.buildCall(void_type_node, gen.addressOf(TREE_VALUE(p)), NULL_TREE); + if (! exp) + exp = call_exp; + else + exp = build(COMPOUND_EXPR, void_type_node, call_exp, exp); + p = TREE_CHAIN(p); + } + gen.doSimpleFunction(this, + IDENTIFIER_POINTER(get_file_function_name('I')), exp, false, true); + } + + IRState::inGenObjFile = false; // %% This might cause problems if any if are code is called from the gcc wrapup code.. cur_irs = 0; } @@ -2410,6 +2447,16 @@ return ctype; case Terror: return error_mark_node; + + /* We can get Tident with forward references. There seems to + be a legitame case (dstress:debug_info_03). I have not seen this + happen for an error, so maybe it's okay... + + A way to handle this would be to partially construct + function types and not complete it until it was actually + used in a call. */ + case Tident: return void_type_node; + default: ::error("unexpected call to Type::toCtype() for %s\n", this->toChars()); abort(); @@ -2506,6 +2553,18 @@ TYPE_NAME( ctype ) = build_decl(TYPE_DECL, get_identifier(sym->ident->string), ctype); } + + /* %% copied from AggLayout::finish -- also have to set the size + for (indirect) self-references. */ + + TYPE_SIZE( ctype ) = bitsize_int( sym->structsize * BITS_PER_UNIT ); + TYPE_SIZE_UNIT( ctype ) = size_int( sym->structsize ); + TYPE_ALIGN( ctype ) = sym->alignsize * BITS_PER_UNIT; // %%doc int, not a tree + // TYPE_ALIGN_UNIT is not an lvalue + TYPE_PACKED ( ctype ) = TYPE_PACKED ( ctype ); // %% todo + compute_record_mode ( ctype ); + // %% stor-layout.c:finalize_type_size ... it's private to that file + AggLayout agg_layout(sym, ctype); agg_layout.go(); @@ -2587,12 +2646,16 @@ { if (! ctype) { if (dim->isConst() && dim->type->isintegral()) { - xdmd_integer_t size = dim->toInteger(); - if (! next->isbit()) - ctype = cur_irs->arrayType(next, size); - else + uinteger_t size = dim->toUInteger(); + + if (next->isbit()) ctype = cur_irs->arrayType(bitConfig.elemType, bitConfig.bitCountToWords(size)); + else if (next->toBasetype()->ty == Tvoid) + ctype = cur_irs->arrayType(Type::tuns8, size); + else + ctype = cur_irs->arrayType(next, size); + } else { ::error("invalid expressions for static array dimension: %s", dim->toChars()); abort(); @@ -2886,7 +2949,7 @@ void ThrowStatement::toIR(IRState* irs) { - ClassDeclaration * class_decl = exp->type->isClassHandle(); + ClassDeclaration * class_decl = exp->type->toBasetype()->isClassHandle(); // Front end already checks for isClassHandle InterfaceDeclaration * intfc_decl = class_decl->isInterfaceDeclaration(); @@ -2910,8 +2973,8 @@ { // %% doc: this is not the same as a start_eh/end_eh_cleanup sequence tree tf = build(TRY_FINALLY_EXPR, void_type_node, - irs->makeStmtExpr(body), - irs->makeStmtExpr(finalbody)); + body ? irs->makeStmtExpr(body) : d_void_zero_node, + finalbody ? irs->makeStmtExpr(finalbody) : d_void_zero_node); // TREE_SIDE_EFFECTS(tf) = 1; // probably not needed irs->doLineNote(loc); irs->doExp(tf); @@ -2943,7 +3006,8 @@ irs->emitLocalVar(a_catch->var); } - a_catch->handler->toIR(irs); + if (a_catch->handler) + a_catch->handler->toIR(irs); irs->endScope(); irs->endCatch(); } @@ -3481,13 +3545,17 @@ gen.retrieveStmtExpr(exp, & stmt, & irs); // need push_temp_slots()? - push_temp_slots (); // will this work? maybe expand_start_binding tree rtl_expr = expand_start_stmt_expr(1); + // This startBindings call is needed so get_last_insn() doesn't return NULL + // in expand_start_case(). + irs->startBindings(); // preserve_temp_slots as in c-common.c:c_expand_expr stmt->toIR(irs); + irs->endBindings(); expand_end_stmt_expr (rtl_expr); + rtx result = expand_expr (rtl_expr, target, tmode, (enum expand_modifier) modifier); pop_temp_slots(); return result; diff -uNr gdc-0.11/d/d-lang.cc gdc-0.12/d/d-lang.cc --- gdc-0.11/d/d-lang.cc 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/d-lang.cc 2005-05-25 03:51:33.000000000 +0200 @@ -24,7 +24,7 @@ #include "mtype.h" #include "id.h" #include "module.h" -#include "debcond.h" +#include "cond.h" #include #include "d-gcc-includes.h" @@ -263,8 +263,8 @@ q++; *q = 0; if (p != q) { - // EXPER -- %% needs to be predefined... since - // we define Unix/Windows this way + /* Needs to be predefined because we define + Unix/Windows this way. */ VersionCondition::addPredefinedGlobalIdent(xstrdup(p)); } } @@ -316,6 +316,7 @@ { long v; char * err; + errno = 0; v = strtol(arg, & err, 10); if (*err || errno || v > INT_MAX) return false; @@ -380,13 +381,15 @@ } break; case OPT_femit_templates: - gen.emitTemplates = value ? TEfull : TEnone; + gen.emitTemplates = value ? TEauto : TEnone; break; case OPT_femit_templates_: if (! arg || ! *arg) { - gen.emitTemplates = value ? TEfull : TEnone; - } else if (! strcmp(arg, "full")) { - gen.emitTemplates = TEfull; + gen.emitTemplates = value ? TEauto : TEnone; + } else if (! strcmp(arg, "normal")) { + gen.emitTemplates = TEnormal; + } else if (! strcmp(arg, "all")) { + gen.emitTemplates = TEall; } else if (! strcmp(arg, "private")) { gen.emitTemplates = TEprivate; } else if (! strcmp(arg, "none")) { @@ -490,6 +493,7 @@ d_handle_option(OPT_Wall, NULL, value); else if (strcmp(p_arg, "sign-compare") == 0) d_handle_option(OPT_Wsign_compare, NULL, value); + return 1; } else if (p_arg[0] != '-') { all_input_files->push((void *) p_arg); return 0; @@ -577,7 +581,7 @@ global.params.useAssert = 1; global.params.useArrayBounds = flag_bounds_check; if (gen.emitTemplates == TEauto) { - gen.emitTemplates = (SUPPORTS_ONE_ONLY) ? TEfull : TEprivate; + gen.emitTemplates = (SUPPORTS_ONE_ONLY) ? TEnormal : TEprivate; } global.params.symdebug = write_symbols != NO_DEBUG; gen.originalOmitFramePointer = flag_omit_frame_pointer; @@ -705,9 +709,9 @@ { m = (Module *)modules.data[i]; if (global.params.verbose) - printf("parse %s\n", m->toChars()); + fprintf(stderr, "parse %s\n", m->toChars()); //m->deleteObjFile(); // %% driver does this - m->read(); + m->read(0); m->parse(global.params.dump_source); } if (global.errors) @@ -718,7 +722,7 @@ { m = (Module *)modules.data[i]; if (global.params.verbose) - printf("semantic %s\n", m->toChars()); + fprintf(stderr, "semantic %s\n", m->toChars()); m->semantic(); } if (global.errors) @@ -730,7 +734,7 @@ { m = (Module *)modules.data[i]; if (global.params.verbose) - printf("semantic2 %s\n", m->toChars()); + fprintf(stderr, "semantic2 %s\n", m->toChars()); m->semantic2(); } if (global.errors) @@ -746,7 +750,7 @@ { m = (Module *)modules.data[i]; if (global.params.verbose) - printf("semantic3 %s\n", m->toChars()); + fprintf(stderr, "semantic3 %s\n", m->toChars()); m->semantic3(); } if (global.errors) @@ -764,7 +768,7 @@ { m = (Module *)modules.data[i]; if (global.params.verbose) - printf("inline scan %s\n", m->toChars()); + fprintf(stderr, "inline scan %s\n", m->toChars()); m->inlineScan(); } } @@ -778,44 +782,11 @@ { m = (Module *)modules.data[i]; if (global.params.verbose) - printf("code %s\n", m->toChars()); + fprintf(stderr, "code %s\n", m->toChars()); m->genobjfile(); // m->gensymfile(); } */ - - /* old - - id = new Identifier(name, 0); - // %%TODO: fix crasher when file doesn't exist dsymbol.cc:80 - m = new Module((char*) input_filename, id); - current_module = m; - - m->read(); - m->parse(); - if (global.errors) - goto had_errors; - - if (global.params.verbose) - printf("semantic %s\n", m->toChars()); - m->semantic(); - if (global.errors) - goto had_errors; - - if (global.params.verbose) - printf("semantic2 %s\n", m->toChars()); - m->semantic2(); - if (global.errors) - goto had_errors; - - if (global.params.verbose) - printf("semantic3 %s\n", m->toChars()); - m->semantic3(); - if (global.errors) - goto had_errors; - */ - - //printf("d_parse_file: parsed!\n"); the_one->genobjfile(); // should probably set current_module to itself #if D_GCC_VER == 33 diff -uNr gdc-0.11/d/dmd/aggregate.h gdc-0.12/d/dmd/aggregate.h --- gdc-0.11/d/dmd/aggregate.h 2005-04-17 14:44:07.000000000 +0200 +++ gdc-0.12/d/dmd/aggregate.h 2005-05-19 02:15:50.000000000 +0200 @@ -172,6 +172,7 @@ Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf); + int isBaseOf2(ClassDeclaration *cd); #define OFFSET_RUNTIME 0x76543210 virtual int isBaseOf(ClassDeclaration *cd, int *poffset); diff -uNr gdc-0.11/d/dmd/array.c gdc-0.12/d/dmd/array.c --- gdc-0.11/d/dmd/array.c 2005-04-12 05:16:27.000000000 +0200 +++ gdc-0.12/d/dmd/array.c 2005-05-08 16:01:26.000000000 +0200 @@ -18,14 +18,13 @@ #include #include #include -#ifndef alloca -#include -#endif #if _MSC_VER #include #endif +#include "gdc_alloca.h" + #if _WIN32 #include #endif diff -uNr gdc-0.11/d/dmd/attrib.c gdc-0.12/d/dmd/attrib.c --- gdc-0.11/d/dmd/attrib.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/attrib.c 2005-05-21 19:29:57.000000000 +0200 @@ -7,13 +7,17 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + #include #include #include -#ifdef IN_GCC -#include "../root/mem.h" -#elif _WIN32 +#if _WIN32 || IN_GCC #include "mem.h" #elif linux #include "../root/mem.h" @@ -22,7 +26,7 @@ #include "init.h" #include "declaration.h" #include "attrib.h" -#include "debcond.h" +#include "cond.h" #include "scope.h" #include "id.h" #include "expression.h" @@ -31,6 +35,7 @@ extern void obj_includelib(char *name); + /********************************* AttribDeclaration ****************************/ AttribDeclaration::AttribDeclaration(Array *decl) @@ -39,15 +44,15 @@ this->decl = decl; } -Array *AttribDeclaration::include() +Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) { return decl; } -void AttribDeclaration::addMember(ScopeDsymbol *sd) +void AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd) { unsigned i; - Array *d = include(); + Array *d = include(sc, sd); if (d) { @@ -55,14 +60,14 @@ { Dsymbol *s; s = (Dsymbol *)d->data[i]; - s->addMember(sd); + s->addMember(sc, sd); } } } void AttribDeclaration::semantic(Scope *sc) { - Array *d = include(); + Array *d = include(sc, NULL); //printf("\tAttribDeclaration::semantic '%s'\n",toChars()); if (d) @@ -79,7 +84,7 @@ void AttribDeclaration::semantic2(Scope *sc) { unsigned i; - Array *d = include(); + Array *d = include(sc, NULL); if (d) { @@ -95,7 +100,7 @@ void AttribDeclaration::semantic3(Scope *sc) { unsigned i; - Array *d = include(); + Array *d = include(sc, NULL); if (d) { @@ -111,7 +116,7 @@ void AttribDeclaration::inlineScan() { unsigned i; - Array *d = include(); + Array *d = include(NULL, NULL); if (d) { @@ -128,7 +133,7 @@ void AttribDeclaration::toObjFile() { unsigned i; - Array *d = include(); + Array *d = include(NULL, NULL); if (d) { @@ -146,7 +151,7 @@ unsigned i; int nwritten = 0; int n; - Array *d = include(); + Array *d = include(NULL, NULL); if (d) { @@ -170,7 +175,7 @@ Dsymbol *AttribDeclaration::oneMember() { Dsymbol *s; - Array *d = include(); + Array *d = include(NULL, NULL); if (d && d->dim == 1) { s = (Dsymbol *)d->data[0]; @@ -184,7 +189,7 @@ void AttribDeclaration::addLocalClass(Array *aclasses) { unsigned i; - Array *d = include(); + Array *d = include(NULL, NULL); if (d) { @@ -445,9 +450,10 @@ /********************************* AnonDeclaration ****************************/ -AnonDeclaration::AnonDeclaration(int isunion, Array *decl) +AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl) : AttribDeclaration(decl) { + this->loc = loc; this->isunion = isunion; } @@ -456,7 +462,7 @@ AnonDeclaration *ad; assert(!s); - ad = new AnonDeclaration(isunion, Dsymbol::arraySyntaxCopy(decl)); + ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl)); return ad; } @@ -592,12 +598,12 @@ if (e->op == TOKstring) { StringExp *se = (StringExp *)e; - printf("%.*s", se->len, se->string); + fprintf(stderr, "%.*s", se->len, se->string); } else error("string expected for message, not '%s'", e->toChars()); } - printf("\n"); + fprintf(stderr, "\n"); } } else if (ident == Id::lib) @@ -668,45 +674,40 @@ } -/********************************* DebugDeclaration ****************************/ +/********************************* ConditionalDeclaration ****************************/ -DebugDeclaration::DebugDeclaration(Condition *condition, Array *decl, Array *elsedecl) +ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl) : AttribDeclaration(decl) { - //printf("DebugDeclaration::DebugDeclaration()\n"); + //printf("ConditionalDeclaration::ConditionalDeclaration()\n"); this->condition = condition; this->elsedecl = elsedecl; } -Dsymbol *DebugDeclaration::syntaxCopy(Dsymbol *s) +Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s) { - DebugDeclaration *dd; + ConditionalDeclaration *dd; assert(!s); - dd = new DebugDeclaration(condition, + dd = new ConditionalDeclaration(condition->syntaxCopy(), Dsymbol::arraySyntaxCopy(decl), Dsymbol::arraySyntaxCopy(elsedecl)); return dd; } -// Decide if debug code should be included +// Decide if 'then' or 'else' code should be included -Array *DebugDeclaration::include() +Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd) { assert(condition); - return condition->include() ? decl : elsedecl; + return condition->include(sc, sd) ? decl : elsedecl; } -void DebugDeclaration::toCBuffer(OutBuffer *buf) +void ConditionalDeclaration::toCBuffer(OutBuffer *buf) { - if (isVersionDeclaration()) - buf->writestring("version("); - else - buf->writestring("debug("); condition->toCBuffer(buf); - buf->writeByte(')'); if (decl || elsedecl) { buf->writenl(); @@ -746,23 +747,3 @@ } -/********************************* VersionDeclaration ****************************/ - -VersionDeclaration::VersionDeclaration(Condition *condition, Array *decl, Array *elsedecl) - : DebugDeclaration(condition, decl, elsedecl) -{ - //printf("VersionDeclaration::VersionDeclaration()\n"); -} - -Dsymbol *VersionDeclaration::syntaxCopy(Dsymbol *s) -{ - VersionDeclaration *vd; - - assert(!s); - vd = new VersionDeclaration(condition, - Dsymbol::arraySyntaxCopy(decl), - Dsymbol::arraySyntaxCopy(elsedecl)); - return vd; -} - - diff -uNr gdc-0.11/d/dmd/attrib.h gdc-0.12/d/dmd/attrib.h --- gdc-0.11/d/dmd/attrib.h 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/attrib.h 2005-05-21 19:29:57.000000000 +0200 @@ -30,8 +30,8 @@ Array *decl; // array of Dsymbol's AttribDeclaration(Array *decl); - virtual Array *include(); - void addMember(ScopeDsymbol *s); + virtual Array *include(Scope *sc, ScopeDsymbol *s); + void addMember(Scope *sc, ScopeDsymbol *s); void semantic(Scope *sc); void semantic2(Scope *sc); void semantic3(Scope *sc); @@ -91,7 +91,7 @@ { int isunion; - AnonDeclaration(int isunion, Array *decl); + AnonDeclaration(Loc loc, int isunion, Array *decl); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf); @@ -110,23 +110,15 @@ void toObjFile(); // compile to .obj file }; -struct DebugDeclaration : AttribDeclaration +struct ConditionalDeclaration : AttribDeclaration { Condition *condition; Array *elsedecl; // array of Dsymbol's for else block - DebugDeclaration(Condition *condition, Array *decl, Array *elsedecl); + ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl); Dsymbol *syntaxCopy(Dsymbol *s); - Array *include(); + Array *include(Scope *sc, ScopeDsymbol *s); void toCBuffer(OutBuffer *buf); }; -struct VersionDeclaration : DebugDeclaration -{ - VersionDeclaration(Condition *condition, Array *decl, Array *elsedecl); - Dsymbol *syntaxCopy(Dsymbol *s); - - VersionDeclaration *isVersionDeclaration() { return this; } -}; - #endif /* DMD_ATTRIB_H */ diff -uNr gdc-0.11/d/dmd/cast.c gdc-0.12/d/dmd/cast.c --- gdc-0.11/d/dmd/cast.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/cast.c 2005-05-08 16:01:26.000000000 +0200 @@ -16,7 +16,7 @@ #include #include -#if _WIN32 +#if _WIN32 || IN_GCC #include "mem.h" #else #include "../root/mem.h" @@ -49,7 +49,7 @@ if (e->op == TOKint64) return e->implicitCastTo(t); - printf("warning - "); + fprintf(stderr, "warning - "); error("implicit conversion of expression (%s) of type %s to %s can cause loss of data", toChars(), type->toChars(), t->toChars()); } diff -uNr gdc-0.11/d/dmd/class.c gdc-0.12/d/dmd/class.c --- gdc-0.11/d/dmd/class.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/class.c 2005-05-25 03:51:33.000000000 +0200 @@ -57,7 +57,7 @@ vtblsym = NULL; vclassinfo = NULL; - if (id == Id::__sizeof) + if (id == Id::__sizeof || id == Id::alignof) error("illegal class name"); // BUG: What if this is the wrong ClassInfo, i.e. it is nested? @@ -69,7 +69,7 @@ Module::moduleinfo = this; // BUG: What if this is the wrong TypeInfo, i.e. it is nested? - if (id->toChars()[0] == 'T') + if (id && id->toChars()[0] == 'T') { if (!Type::typeinfo && id == Id::TypeInfo) Type::typeinfo = this; @@ -172,6 +172,9 @@ scx = scope; // save so we don't make redundant copies scope = NULL; } +#ifdef IN_GCC + methods.setDim(0); +#endif // See if there's a base class as first in baseclasses[] if (baseclasses.dim) @@ -193,12 +196,16 @@ ; else { - if (tc->sym == this) + for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass) { - error("base class same as class"); - baseclasses.remove(0); + if (cdb == this) + { + error("circular inheritance"); + baseclasses.remove(0); + goto L7; + } } - else if (!tc->sym->symtab || tc->sym->scope) + if (!tc->sym->symtab || tc->sym->scope) { //error("forward reference of base class %s", baseClass->toChars()); // Forward reference of base class, try again later @@ -212,6 +219,7 @@ { baseClass = tc->sym; b->base = baseClass; } + L7: ; } } } @@ -303,7 +311,7 @@ for (i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; - s->addMember(this); + s->addMember(sc, this); } } @@ -390,7 +398,7 @@ ctor = new CtorDeclaration(0, 0, NULL, 0); ctor->fbody = new CompoundStatement(0, new Array()); members->push(ctor); - ctor->addMember(this); + ctor->addMember(sc, this); *sc = scsave; sc->offset = structsize; ctor->semantic(sc); @@ -488,6 +496,25 @@ } #endif +/********************************************* + * Determine if 'this' is a base class of cd. + * This is used to detect circular inheritance only. + */ + +int ClassDeclaration::isBaseOf2(ClassDeclaration *cd) +{ + if (!cd) + return 0; + //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); + for (int i = 0; i < cd->baseclasses.dim; i++) + { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; + + if (b->base == this || isBaseOf2(b->base)) + return 1; + } + return 0; +} + /******************************************* * Determine if 'this' is a base class of cd. */ @@ -718,16 +745,16 @@ tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) { - error("base type must be interface, not %s", b->type->toChars()); + //error("base type must be interface, not %s", b->type->toChars()); baseclasses.remove(i); continue; } else { b->base = tc->sym; - if (b->base == this) + if (b->base == this || isBaseOf2(b->base)) { - error("base interface same as interface"); + error("circular inheritance of interface"); baseclasses.remove(i); continue; } @@ -735,7 +762,7 @@ { //error("forward reference of base class %s", baseClass->toChars()); // Forward reference of base, try again later - //printf("\ttry later, forward reference of base %s\n", baseClass->toChars()); + //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); scope = scx ? scx : new Scope(*sc); scope->setNoFree(); scope->module->addDeferredSemantic(this); @@ -767,12 +794,17 @@ // Copy vtbl[] from base class if (b->base->vtblOffset()) { int d = b->base->vtbl.dim; - vtbl.reserve(d - 1); - for (int j = 1; j < d; j++) - vtbl.push(b->base->vtbl.data[j]); + if (d > 1) + { + vtbl.reserve(d - 1); + for (int j = 1; j < d; j++) + vtbl.push(b->base->vtbl.data[j]); + } } else + { vtbl.append(&b->base->vtbl); + } Lcontinue: ; @@ -781,7 +813,7 @@ for (i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; - s->addMember(this); + s->addMember(sc, this); } sc = sc->push(this); @@ -817,12 +849,13 @@ { unsigned j; - //printf("InterfaceDeclaration::isBaseOf(cd = '%s')\n", cd->toChars()); + //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars()); assert(!baseClass); for (j = 0; j < cd->interfaces_dim; j++) { BaseClass *b = cd->interfaces[j]; + //printf("\tbase %s\n", b->base->toChars()); if (this == b->base) { //printf("\tfound at offset %d\n", b->offset); @@ -851,7 +884,7 @@ int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset) { - //printf("InterfaceDeclaration::isBaseOf(bc = '%s')\n", bc->base->toChars()); + //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars()); for (unsigned j = 0; j < bc->baseInterfaces_dim; j++) { BaseClass *b = &bc->baseInterfaces[j]; @@ -984,9 +1017,14 @@ void BaseClass::copyBaseInterfaces(Array *vtblInterfaces) { + //printf("+copyBaseInterfaces(), %s\n", base->toChars()); +// if (baseInterfaces_dim) +// return; + baseInterfaces_dim = base->interfaces_dim; baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass)); + //printf("%s.copyBaseInterfaces()\n", base->toChars()); for (int i = 0; i < baseInterfaces_dim; i++) { BaseClass *b = &baseInterfaces[i]; @@ -999,4 +1037,5 @@ vtblInterfaces->push(b); // only need for M.I. b->copyBaseInterfaces(vtblInterfaces); } + //printf("-copyBaseInterfaces\n"); } diff -uNr gdc-0.11/d/dmd/cond.c gdc-0.12/d/dmd/cond.c --- gdc-0.11/d/dmd/cond.c 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.12/d/dmd/cond.c 2005-05-25 03:51:33.000000000 +0200 @@ -0,0 +1,342 @@ + +// Copyright (c) 1999-2005 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include +#include + +#include "id.h" +#include "init.h" +#include "declaration.h" +#include "identifier.h" +#include "expression.h" +#include "cond.h" +#include "module.h" +#include "template.h" + +int findCondition(Array *ids, Identifier *ident) +{ + if (ids) + { + for (int i = 0; i < ids->dim; i++) + { + char *id = (char *)ids->data[i]; + + if (strcmp(id, ident->toChars()) == 0) + return TRUE; + } + } + + return FALSE; +} + +/* ============================================================ */ + +Condition::Condition(Loc loc) +{ + this->loc = loc; + inc = 0; +} + +/* ============================================================ */ + +DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident) + : Condition(0) +{ + this->mod = mod; + this->level = level; + this->ident = ident; +} + +Condition *DVCondition::syntaxCopy() +{ + return this; // don't need to copy +} + +/* ============================================================ */ + +void DebugCondition::setGlobalLevel(unsigned level) +{ + global.params.debuglevel = level; +} + +void DebugCondition::addGlobalIdent(char *ident) +{ + if (!global.params.debugids) + global.params.debugids = new Array(); + global.params.debugids->push(ident); +} + + +DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident) + : DVCondition(mod, level, ident) +{ +} + +int DebugCondition::include(Scope *sc, ScopeDsymbol *s) +{ + //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel); + if (inc == 0) + { + inc = 2; + if (ident) + { + if (findCondition(mod->debugids, ident)) + inc = 1; + else if (findCondition(global.params.debugids, ident)) + inc = 1; + } + else if (level <= global.params.debuglevel || level <= mod->debuglevel) + inc = 1; + } + return (inc == 1); +} + +void DebugCondition::toCBuffer(OutBuffer *buf) +{ + if (ident) + buf->printf("debug (%s)", ident->toChars()); + else + buf->printf("debug (%u)", level); +} + +/* ============================================================ */ + +void VersionCondition::setGlobalLevel(unsigned level) +{ + global.params.versionlevel = level; +} + +void VersionCondition::checkPredefined(Loc loc, char *ident) +{ + static char* reserved[] = + { + "DigitalMars", "X86", "X86_64", + "Windows", "Win32", "Win64", + "linux", + "LittleEndian", "BigEndian", + "all", + "none", + }; + + for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) + { + if (strcmp(ident, reserved[i]) == 0) + goto Lerror; + } + + if (ident[0] == 'D' && ident[1] == '_') + goto Lerror; + + return; + + Lerror: + error(loc, "version identifier '%s' is reserved and cannot be set", ident); +} + +void VersionCondition::addGlobalIdent(char *ident) +{ + checkPredefined(0, ident); + addPredefinedGlobalIdent(ident); +} + +void VersionCondition::addPredefinedGlobalIdent(char *ident) +{ + if (!global.params.versionids) + global.params.versionids = new Array(); + global.params.versionids->push(ident); +} + + +VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident) + : DVCondition(mod, level, ident) +{ +} + +int VersionCondition::include(Scope *sc, ScopeDsymbol *s) +{ + //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel); + if (inc == 0) + { + inc = 2; + if (ident) + { + if (findCondition(mod->versionids, ident)) + inc = 1; + else if (findCondition(global.params.versionids, ident)) + inc = 1; + } + else if (level <= global.params.versionlevel || level <= mod->versionlevel) + inc = 1; + } + return (inc == 1); +} + +void VersionCondition::toCBuffer(OutBuffer *buf) +{ + if (ident) + buf->printf("version (%s)", ident->toChars()); + else + buf->printf("version (%u)", level); +} + + +/**************************** StaticIfCondition *******************************/ + +StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp) + : Condition(loc) +{ + this->exp = exp; +} + +Condition *StaticIfCondition::syntaxCopy() +{ + return new StaticIfCondition(loc, exp->syntaxCopy()); +} + +int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) +{ + if (inc == 0) + { + if (!sc) + { + error(loc, "static if conditional cannot be at global scope"); + inc = 2; + return 0; + } + + Expression *e = exp->semantic(sc); + e = e->optimize(WANTvalue); + if (e->isBool(TRUE)) + inc = 1; + else if (e->isBool(FALSE)) + inc = 2; + else + { + e->error("expression %s does not evaluate to a boolean", e->toChars()); + inc = 2; + } + } + return (inc == 1); +} + +void StaticIfCondition::toCBuffer(OutBuffer *buf) +{ + buf->writestring("static if("); + exp->toCBuffer(buf); + buf->writeByte(')'); +} + + +/**************************** IftypeCondition *******************************/ + +IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, Type *tspec) + : Condition(loc) +{ + this->targ = targ; + this->id = id; + this->tspec = tspec; +} + +Condition *IftypeCondition::syntaxCopy() +{ + return new IftypeCondition(loc, + targ->syntaxCopy(), + id, + tspec ? tspec->syntaxCopy() : NULL); +} + +int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd) +{ + //printf("IftypeCondition::include()\n"); + if (inc == 0) + { + if (!sc) + { + error(loc, "iftype conditional cannot be at global scope"); + inc = 2; + return 0; + } + targ = targ->semantic(loc, sc); + + if (id && tspec) + { + /* Evaluate to TRUE if targ matches tspec. + * If TRUE, declare id as an alias for the specialized type. + */ + + MATCH m; + TemplateTypeParameter tp(loc, id, NULL, NULL); + + Array parameters; + parameters.setDim(1); + parameters.data[0] = (void *)&tp; + + Array dedtypes; + dedtypes.setDim(1); + + m = targ->deduceType(tspec, ¶meters, &dedtypes); + if (m == MATCHnomatch) + inc = 2; + else + { + inc = 1; + Type *tded = (Type *)dedtypes.data[0]; + if (!tded) + tded = targ; + Dsymbol *s = new AliasDeclaration(loc, id, tded); + s->semantic(sc); + sc->insert(s); + if (sd) + s->addMember(sc, sd); + } + } + else if (id) + { + /* Declare id as an alias for type targ. Evaluate to TRUE + */ + Dsymbol *s = new AliasDeclaration(loc, id, targ); + s->semantic(sc); + sc->insert(s); + if (sd) + s->addMember(sc, sd); + inc = 1; + } + else if (tspec) + { + /* Evaluate to TRUE if targ matches tspec + */ + tspec = tspec->semantic(loc, sc); + //printf("targ = %s\n", targ->toChars()); + //printf("tspec = %s\n", tspec->toChars()); + //if (targ->equals(tspec)) + if (targ->implicitConvTo(tspec)) + inc = 1; + else + inc = 2; + } + else + assert(0); + //printf("inc = %d\n", inc); + } + return (inc == 1); +} + +void IftypeCondition::toCBuffer(OutBuffer *buf) +{ + buf->writestring("iftype("); + targ->toCBuffer(buf, id); + if (tspec) + { + buf->writestring(" : "); + tspec->toCBuffer(buf, NULL); + } + buf->writeByte(')'); +} + + diff -uNr gdc-0.11/d/dmd/cond.h gdc-0.12/d/dmd/cond.h --- gdc-0.11/d/dmd/cond.h 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.12/d/dmd/cond.h 2005-05-21 19:29:57.000000000 +0200 @@ -0,0 +1,96 @@ + +// Copyright (c) 1999-2005 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#ifndef DMD_DEBCOND_H +#define DMD_DEBCOND_H + +struct Expression; +struct Identifier; +struct OutBuffer; +struct Module; +struct Scope; +struct ScopeDsymbol; + +struct Condition +{ + Loc loc; + int inc; // 0: not computed yet + // 1: include + // 2: do not include + + Condition(Loc loc); + + virtual Condition *syntaxCopy() = 0; + virtual int include(Scope *sc, ScopeDsymbol *s) = 0; + virtual void toCBuffer(OutBuffer *buf) = 0; +}; + +struct DVCondition : Condition +{ + unsigned level; + Identifier *ident; + Module *mod; + + DVCondition(Module *mod, unsigned level, Identifier *ident); + + Condition *syntaxCopy(); +}; + +struct DebugCondition : DVCondition +{ + static void setGlobalLevel(unsigned level); + static void addGlobalIdent(char *ident); + static void addPredefinedGlobalIdent(char *ident); + + DebugCondition(Module *mod, unsigned level, Identifier *ident); + + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf); +}; + +struct VersionCondition : DVCondition +{ + static void setGlobalLevel(unsigned level); + static void checkPredefined(Loc loc, char *ident); + static void addGlobalIdent(char *ident); + static void addPredefinedGlobalIdent(char *ident); + + VersionCondition(Module *mod, unsigned level, Identifier *ident); + + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf); +}; + +struct StaticIfCondition : Condition +{ + Expression *exp; + + StaticIfCondition(Loc loc, Expression *exp); + Condition *syntaxCopy(); + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf); +}; + +struct IftypeCondition : Condition +{ + /* iftype (targ id : tspec) + */ + Loc loc; + Type *targ; + Identifier *id; // can be NULL + Type *tspec; // can be NULL + + IftypeCondition(Loc loc, Type *targ, Identifier *id, Type *tspec); + Condition *syntaxCopy(); + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf); +}; + + +#endif diff -uNr gdc-0.11/d/dmd/constfold.c gdc-0.12/d/dmd/constfold.c --- gdc-0.11/d/dmd/constfold.c 2005-04-24 18:48:31.000000000 +0200 +++ gdc-0.12/d/dmd/constfold.c 2005-05-21 19:29:57.000000000 +0200 @@ -135,7 +135,12 @@ if (tb->ty == Tbit) return new IntegerExp(loc, e1->toInteger() != 0, type); if (type->isintegral()) - return new IntegerExp(loc, e1->toInteger(), type); + { + if (type->isunsigned()) + return new IntegerExp(loc, e1->toUInteger(), type); + else + return new IntegerExp(loc, e1->toInteger(), type); + } if (tb->isreal()) { real_t value = e1->toReal(); @@ -375,6 +380,10 @@ n1 = e1->toInteger(); n2 = e2->toInteger(); + if (n2 == 0) + { error("divide by 0"); + n2 = 1; + } if (isunsigned()) n = ((d_uns64) n1) % ((d_uns64) n2); else @@ -404,25 +413,37 @@ switch (e1->type->toBasetype()->ty) { case Tint8: - case Tuns8: value = (d_int8)(value) >> count; break; + case Tuns8: + value = (d_uns8)(value) >> count; + break; + case Tint16: - case Tuns16: value = (d_int16)(value) >> count; break; + case Tuns16: + value = (d_uns16)(value) >> count; + break; + case Tint32: - case Tuns32: value = (d_int32)(value) >> count; break; + case Tuns32: + value = (d_uns32)(value) >> count; + break; + case Tint64: - case Tuns64: value = (d_int64)(value) >> count; break; + case Tuns64: + value = (d_uns64)(value) >> count; + break; + default: assert(0); } @@ -516,6 +537,7 @@ real_t r1; real_t r2; + //printf("CmpExp::constFold()\n"); e1 = e1->constFold(); e2 = e2->constFold(); if (e1->type->isreal()) diff -uNr gdc-0.11/d/dmd/dchar.h gdc-0.12/d/dmd/dchar.h --- gdc-0.11/d/dmd/dchar.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/dmd/dchar.h 2005-05-08 16:01:26.000000000 +0200 @@ -17,7 +17,7 @@ #ifndef DCHAR_H #define DCHAR_H -#if __GNUC__ +#if __GNUC__ && ! _WIN32 #include "gnuc.h" #endif diff -uNr gdc-0.11/d/dmd/debcond.c gdc-0.12/d/dmd/debcond.c --- gdc-0.11/d/dmd/debcond.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/debcond.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,175 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "id.h" -#include "init.h" -#include "declaration.h" -#include "identifier.h" -#include "expression.h" -#include "debcond.h" -#include "module.h" - -int findCondition(Array *ids, Identifier *ident) -{ - if (ids) - { - for (int i = 0; i < ids->dim; i++) - { - char *id = (char *)ids->data[i]; - - if (strcmp(id, ident->toChars()) == 0) - return TRUE; - } - } - - return FALSE; -} - -/* ============================================================ */ - -Condition::Condition(Module *mod, unsigned level, Identifier *ident) -{ - this->mod = mod; - this->level = level; - this->ident = ident; -} - -int Condition::include() -{ - assert(0); - return FALSE; -} - -int Condition::isBool(int result) -{ - return (result == include()); -} - -Expression *Condition::toExpr() -{ - assert(0); // BUG: not implemented - return NULL; -} - -void Condition::toCBuffer(OutBuffer *buf) -{ - if (ident) - buf->printf("%s", ident->toChars()); - else - buf->printf("%u", level); -} - -/* ============================================================ */ - -void DebugCondition::setGlobalLevel(unsigned level) -{ - global.params.debuglevel = level; -} - -void DebugCondition::addGlobalIdent(char *ident) -{ - if (!global.params.debugids) - global.params.debugids = new Array(); - global.params.debugids->push(ident); -} - - -DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident) - : Condition(mod, level, ident) -{ -} - -int DebugCondition::include() -{ - //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel); - if (ident) - { - if (findCondition(mod->debugids, ident)) - return TRUE; - - if (findCondition(global.params.debugids, ident)) - return TRUE; - } - else if (level <= global.params.debuglevel || level <= mod->debuglevel) - return TRUE; - return FALSE; -} - -/* ============================================================ */ - -void VersionCondition::setGlobalLevel(unsigned level) -{ - global.params.versionlevel = level; -} - -void VersionCondition::checkPredefined(char *ident) -{ - static char* reserved[] = - { - "DigitalMars", "X86", "X86_64", - "Windows", "Win32", "Win64", - "linux", - "LittleEndian", "BigEndian", - "all", - "none", - }; - - for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) - { - if (strcmp(ident, reserved[i]) == 0) - goto Lerror; - } - - if (ident[0] == 'D' && ident[1] == '_') - goto Lerror; - - return; - - Lerror: - error("version identifier '%s' is reserved and cannot be set", ident); -} - -void VersionCondition::addGlobalIdent(char *ident) -{ - checkPredefined(ident); - addPredefinedGlobalIdent(ident); -} - -void VersionCondition::addPredefinedGlobalIdent(char *ident) -{ - if (!global.params.versionids) - global.params.versionids = new Array(); - global.params.versionids->push(ident); -} - - -VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident) - : Condition(mod, level, ident) -{ -} - -int VersionCondition::include() -{ - //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel); - if (ident) - { - if (findCondition(mod->versionids, ident)) - return TRUE; - - if (findCondition(global.params.versionids, ident)) - return TRUE; - } - else if (level <= global.params.versionlevel || level <= mod->versionlevel) - return TRUE; - return FALSE; -} - diff -uNr gdc-0.11/d/dmd/debcond.h gdc-0.12/d/dmd/debcond.h --- gdc-0.11/d/dmd/debcond.h 2005-04-17 15:49:49.000000000 +0200 +++ gdc-0.12/d/dmd/debcond.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,55 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_DEBCOND_H -#define DMD_DEBCOND_H - -struct Expression; -struct Identifier; -struct OutBuffer; -struct Module; - -struct Condition -{ - unsigned level; - Identifier *ident; - Module *mod; - - Condition(Module *mod, unsigned level, Identifier *ident); - - virtual int include(); - int isBool(int result); - Expression *toExpr(); - void toCBuffer(OutBuffer *buf); -}; - -struct DebugCondition : Condition -{ - static void setGlobalLevel(unsigned level); - static void addGlobalIdent(char *ident); - static void addPredefinedGlobalIdent(char *ident); - - DebugCondition(Module *mod, unsigned level, Identifier *ident); - - int include(); -}; - -struct VersionCondition : Condition -{ - static void setGlobalLevel(unsigned level); - static void checkPredefined(char *ident); - static void addGlobalIdent(char *ident); - static void addPredefinedGlobalIdent(char *ident); - - VersionCondition(Module *mod, unsigned level, Identifier *ident); - - int include(); -}; - -#endif /* DMD_DEBCOND_H */ diff -uNr gdc-0.11/d/dmd/declaration.c gdc-0.12/d/dmd/declaration.c --- gdc-0.11/d/dmd/declaration.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/declaration.c 2005-05-19 02:15:50.000000000 +0200 @@ -79,13 +79,14 @@ /********************************* TypedefDeclaration ****************************/ -TypedefDeclaration::TypedefDeclaration(Identifier *id, Type *basetype, Initializer *init) +TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init) : Declaration(id) { this->type = new TypeTypedef(this); this->basetype = basetype->toBasetype(); this->init = init; this->sem = 0; + this->loc = loc; } Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) @@ -98,7 +99,7 @@ assert(!s); TypedefDeclaration *st; - st = new TypedefDeclaration(ident, basetype, init); + st = new TypedefDeclaration(loc, ident, basetype, init); return st; } @@ -203,6 +204,9 @@ } this->inSemantic = 1; + if (storage_class & STCconst) + error("cannot be const"); + storage_class |= sc->stc & STCdeprecated; // Given: @@ -652,7 +656,7 @@ cd; cd = cd->baseClass) { - if (cd->dtor) + //if (cd->dtor) { FuncDeclaration *fd; Expression *efd; Expression *ec; diff -uNr gdc-0.11/d/dmd/declaration.h gdc-0.12/d/dmd/declaration.h --- gdc-0.11/d/dmd/declaration.h 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/declaration.h 2005-05-21 19:29:57.000000000 +0200 @@ -31,6 +31,7 @@ struct ForeachStatement; struct FuncDeclaration; struct ExpInitializer; +struct StructDeclaration; enum PROT; enum LINK; @@ -116,7 +117,7 @@ // 2: semantic() has been run // 3: semantic2() has been run - TypedefDeclaration(Identifier *ident, Type *basetype, Initializer *init); + TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); void semantic2(Scope *sc); @@ -184,10 +185,14 @@ struct SymbolDeclaration : Declaration { Symbol *sym; + StructDeclaration *dsym; - SymbolDeclaration(Loc loc, Symbol *s); + SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym); Symbol *toSymbol(); + + // Eliminate need for dynamic_cast + SymbolDeclaration *isSymbolDeclaration() { return (SymbolDeclaration *)this; } }; struct ClassInfoDeclaration : VarDeclaration diff -uNr gdc-0.11/d/dmd/dsymbol.c gdc-0.12/d/dmd/dsymbol.c --- gdc-0.11/d/dmd/dsymbol.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/dsymbol.c 2005-05-21 19:29:57.000000000 +0200 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + #include #include #include @@ -69,7 +75,7 @@ Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s) { print(); - printf("%s %s\n", kind(), toChars()); + fprintf(stderr, "%s %s\n", kind(), toChars()); assert(0); return NULL; } @@ -260,7 +266,7 @@ return FALSE; } -void Dsymbol::addMember(ScopeDsymbol *sd) +void Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd) { //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars()); //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab); @@ -279,8 +285,8 @@ } if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) { - if (ident == Id::__sizeof) - error(".sizeof property cannot be redefined"); + if (ident == Id::__sizeof || ident == Id::alignof) + error(".%s property cannot be redefined", ident->toChars()); } } } @@ -291,18 +297,21 @@ char *p = locToChars(); if (*p) - printf("%s: ", p); + fprintf(stderr, "%s: ", p); mem.free(p); - printf("%s %s ", kind(), toPrettyChars()); + if (isAnonymous()) + fprintf(stderr, "%s ", kind()); + else + fprintf(stderr, "%s %s ", kind(), toPrettyChars()); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); global.errors++; @@ -316,18 +325,18 @@ p = locToChars(); if (*p) - printf("%s: ", p); + fprintf(stderr, "%s: ", p); mem.free(p); - printf("%s %s ", kind(), toPrettyChars()); + fprintf(stderr, "%s %s ", kind(), toPrettyChars()); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); global.errors++; diff -uNr gdc-0.11/d/dmd/dsymbol.h gdc-0.12/d/dmd/dsymbol.h --- gdc-0.11/d/dmd/dsymbol.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/dsymbol.h 2005-05-21 19:29:57.000000000 +0200 @@ -46,7 +46,6 @@ struct UnitTestDeclaration; struct NewDeclaration; struct VarDeclaration; -struct VersionDeclaration; struct Symbol; struct Package; struct Module; @@ -62,6 +61,7 @@ struct ScopeDsymbol; struct WithScopeSymbol; struct ArrayScopeSymbol; +struct SymbolDeclaration; struct Expression; union tree_node; typedef union tree_node TYPE; @@ -107,7 +107,7 @@ virtual char *kind(); virtual Dsymbol *toAlias(); // resolve real symbol - virtual void addMember(ScopeDsymbol *s); + virtual void addMember(Scope *sc, ScopeDsymbol *s); virtual void semantic(Scope *sc); virtual void semantic2(Scope *sc); virtual void semantic3(Scope *sc); @@ -168,12 +168,12 @@ virtual StructDeclaration *isStructDeclaration() { return NULL; } virtual UnionDeclaration *isUnionDeclaration() { return NULL; } virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; } - virtual VersionDeclaration *isVersionDeclaration() { return NULL; } virtual ScopeDsymbol *isScopeDsymbol() { return NULL; } virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; } virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; } virtual Import *isImport() { return NULL; } virtual EnumDeclaration *isEnumDeclaration() { return NULL; } + virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; } }; // Dsymbol that generates a scope diff -uNr gdc-0.11/d/dmd/enum.c gdc-0.12/d/dmd/enum.c --- gdc-0.11/d/dmd/enum.c 2005-02-20 16:43:51.000000000 +0100 +++ gdc-0.12/d/dmd/enum.c 2005-05-21 19:29:57.000000000 +0200 @@ -17,13 +17,14 @@ /********************************* EnumDeclaration ****************************/ -EnumDeclaration::EnumDeclaration(Identifier *id, Type *memtype) +EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype) : ScopeDsymbol(id) { + this->loc = loc; type = new TypeEnum(this); this->memtype = memtype; maxval = 0; - minval = 0x7FFFFFFF; // BUG: long long max? + minval = 0; defaultval = 0; } @@ -39,14 +40,14 @@ ed->memtype = t; } else - ed = new EnumDeclaration(ident, t); + ed = new EnumDeclaration(loc, ident, t); ScopeDsymbol::syntaxCopy(ed); return ed; } void EnumDeclaration::semantic(Scope *sc) { int i; - integer_t number; + uinteger_t number; Type *t; Scope *sce; @@ -58,7 +59,7 @@ parent = sc->scopesym; memtype = memtype->semantic(loc, sc); if (!memtype->isintegral()) - error("EnumBaseType must be integral type, not %s", memtype->toChars()); + error("base type must be of integral type, not %s", memtype->toChars()); t = isAnonymous() ? memtype : type; symtab = new DsymbolTable(); @@ -69,6 +70,7 @@ return; if (members->dim == 0) error("enum %s must have at least one member", toChars()); + int first = 1; for (i = 0; i < members->dim; i++) { EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); @@ -99,22 +101,37 @@ // Add to symbol table only after evaluating 'value' if (isAnonymous()) - { //em->addMember((ScopeDsymbol *)parent); + { sce->enclosing->insert(em); em->parent = sce->enclosing->parent; } else - em->addMember(this); + em->addMember(sc, this); - if (number < minval) + if (first) + { first = 0; + defaultval = number; minval = number; - if (number > maxval) maxval = number; - if (i == 0) - defaultval = number; + } + else if (memtype->isunsigned()) + { + if (number < minval) + minval = number; + if (number > maxval) + maxval = number; + } + else + { + if ((sinteger_t)number < (sinteger_t)minval) + minval = number; + if ((sinteger_t)number > (sinteger_t)maxval) + maxval = number; + } number++; } + //printf("defaultval = %lld\n", defaultval); sce->pop(); //members->print(); diff -uNr gdc-0.11/d/dmd/enum.h gdc-0.12/d/dmd/enum.h --- gdc-0.11/d/dmd/enum.h 2005-01-10 04:30:55.000000000 +0100 +++ gdc-0.12/d/dmd/enum.h 2005-05-19 02:15:50.000000000 +0200 @@ -29,7 +29,7 @@ integer_t minval; integer_t defaultval; // default initializer - EnumDeclaration(Identifier *id, Type *memtype); + EnumDeclaration(Loc loc, Identifier *id, Type *memtype); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); Dsymbol *oneMember(); diff -uNr gdc-0.11/d/dmd/expression.c gdc-0.12/d/dmd/expression.c --- gdc-0.11/d/dmd/expression.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/expression.c 2005-05-25 03:51:33.000000000 +0200 @@ -26,10 +26,11 @@ #define integer_t dmd_integer_t #endif -#if _WIN32 +#if IN_GCC +#include "mem.h" +#elif _WIN32 #include "..\root\mem.h" -#endif -#ifndef _WIN32 +#elif linux #include "../root/mem.h" #endif #include "port.h" @@ -90,7 +91,7 @@ } if (!fd->isThis()) - { //printf("test2 '%s'\n", fd->toChars()); + { //printf("test '%s'\n", fd->toChars()); goto Lno; } @@ -325,7 +326,7 @@ { Expression *e; if (!size) - printf("No expression copy for: %s\n", toChars()); + fprintf(stderr, "No expression copy for: %s\n", toChars()); e = (Expression *)mem.malloc(size); return (Expression *)memcpy(e, this, size); } @@ -349,8 +350,8 @@ void Expression::print() { - printf("%s\n", toChars()); - fflush(stdout); + fprintf(stderr, "%s\n", toChars()); + fflush(stderr); } char *Expression::toChars() @@ -366,16 +367,16 @@ char *p = loc.toChars(); if (*p) - printf("%s: ", p); + fprintf(stderr, "%s: ", p); mem.free(p); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); global.errors++; //fatal(); @@ -409,6 +410,12 @@ return 0; } +uinteger_t Expression::toUInteger() +{ + //printf("Expression %s\n", Token::toChars(op)); + return (uinteger_t)toInteger(); +} + real_t Expression::toReal() { error("Floating point constant expression expected instead of %s", toChars()); @@ -693,6 +700,11 @@ return (real_t) 0; } +complex_t IntegerExp::toComplex() +{ + return toReal(); +} + int IntegerExp::isBool(int result) { return result ? value != 0 : value == 0; @@ -724,7 +736,7 @@ e = this; else if (!loc.filename) loc = e->loc; - error("constant %s is not an lvalue", e->toChars()); + e->error("constant %s is not an lvalue", e->toChars()); return this; } @@ -776,6 +788,15 @@ #endif } +uinteger_t RealExp::toUInteger() +{ +#ifdef IN_GCC + return (uinteger_t) value.toInt(); +#else + return (uinteger_t) value; +#endif +} + real_t RealExp::toReal() { return value; @@ -930,7 +951,12 @@ integer_t ComplexExp::toInteger() { - return (integer_t) value; + return (sinteger_t) value; +} + +uinteger_t ComplexExp::toUInteger() +{ + return (uinteger_t) value; } real_t ComplexExp::toReal() @@ -2558,7 +2584,7 @@ type = Type::tvoid; return this; } - else if (e1->type->ty == Tpointer && ident != Id::size && + else if (e1->type->ty == Tpointer && ident != Id::init && ident != Id::__sizeof && ident != Id::alignof && ident != Id::offsetof) { @@ -3125,7 +3151,7 @@ e1 = e; } else - { error("function expected before (), not '%s'", e1->type->toChars()); + { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); type = Type::terror; return this; } @@ -3450,36 +3476,51 @@ type = Type::tvoid; tb = e1->type->toBasetype(); - if (tb->ty == Tclass) - { - TypeClass *tc = (TypeClass *)tb; - ClassDeclaration *cd = tc->sym; + switch (tb->ty) + { case Tclass: + { TypeClass *tc = (TypeClass *)tb; + ClassDeclaration *cd = tc->sym; - if (cd->isInterfaceDeclaration() && cd->isCOMclass()) - error("cannot delete instance of COM interface %s", cd->toChars()); - } - else if (tb->ty == Tpointer) - { - tb = tb->next->toBasetype(); - if (tb->ty == Tstruct) - { - TypeStruct *ts = (TypeStruct *)tb; - StructDeclaration *sd = ts->sym; - FuncDeclaration *f = sd->aggDelete; + if (cd->isInterfaceDeclaration() && cd->isCOMclass()) + error("cannot delete instance of COM interface %s", cd->toChars()); + break; + } + case Tpointer: + tb = tb->next->toBasetype(); + if (tb->ty == Tstruct) + { + TypeStruct *ts = (TypeStruct *)tb; + StructDeclaration *sd = ts->sym; + FuncDeclaration *f = sd->aggDelete; - if (f) + if (f) + { + Expression *e; + Expression *ec; + Type *tpv = Type::tvoid->pointerTo(); + + e = e1; + e->type = tpv; + ec = new VarExp(loc, f); + e = new CallExp(loc, ec, e); + return e->semantic(sc); + } + } + break; + + case Tarray: + break; + + default: + if (e1->op == TOKindex) { - Expression *e; - Expression *ec; - Type *tpv = Type::tvoid->pointerTo(); - - e = e1; - e->type = tpv; - ec = new VarExp(loc, f); - e = new CallExp(loc, ec, e); - return e->semantic(sc); + IndexExp *ae = (IndexExp *)(e1); + Type *tb1 = ae->e1->type->toBasetype(); + if (tb1->ty == Taarray) + break; } - } + error("cannot delete type %s", e1->type->toChars()); + break; } return this; } @@ -4242,14 +4283,14 @@ } else { - typeCombine(); type = e1->type; + typeCombine(); e1->checkArithmetic(); e2->checkArithmetic(); if (type->isreal() || type->isimaginary()) { assert(global.errors || e2->type->isfloating()); - e2 = e2->castTo(type); + e2 = e2->castTo(e1->type); } e = this; } @@ -4283,14 +4324,14 @@ e = scaleFactor(); else { - typeCombine(); type = e1->type; + typeCombine(); e1->checkArithmetic(); e2->checkArithmetic(); if (type->isreal() || type->isimaginary()) { assert(e2->type->isfloating()); - e2 = e2->castTo(type); + e2 = e2->castTo(e1->type); } e = this; } @@ -4436,7 +4477,16 @@ Type *t2; t1 = e1->type; - if (t1->isreal() || t1->isimaginary()) + if (t1->isreal()) + { // x/iv = i(-x/v) + // Therefore, the result is 0 + e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1)); + e2->type = t1; + e = new AssignExp(loc, e1, e2); + e->type = t1; + return e; + } + else if (t1->isimaginary()) { Expression *e; switch (t1->ty) @@ -4764,12 +4814,6 @@ Type *tb1 = e1->type->toBasetype(); Type *tb2 = e2->type->toBasetype(); -#if 0 - if (tb1->ty == Tsarray) - e1 = e1->castTo(tb1->next->arrayOf()); - if (tb2->ty == Tsarray) - e2 = e2->castTo(tb2->next->arrayOf()); -#endif /* BUG: Should handle things like: * char c; @@ -4777,8 +4821,27 @@ * ' ' ~ c; */ +#if 0 + e1->type->print(); + e2->type->print(); +#endif + if ((tb1->ty == Tsarray || tb1->ty == Tarray) && + e2->type->equals(tb1->next)) + { + type = tb1->next->arrayOf(); + return this; + } + else if ((tb2->ty == Tsarray || tb2->ty == Tarray) && + e1->type->equals(tb2->next)) + { + type = tb2->next->arrayOf(); + return this; + } + typeCombine(); + if (type->toBasetype()->ty == Tsarray) + type = type->toBasetype()->next->arrayOf(); #if 0 e1->type->print(); e2->type->print(); @@ -5263,6 +5326,13 @@ error("need member function opCmp() for struct %s to compare", t1->toChars()); e = this; } +#if 1 + else if (t1->iscomplex() || t2->iscomplex()) + { + error("compare not defined for complex operands"); + e = new IntegerExp(0); + } +#endif else e = this; return e; diff -uNr gdc-0.11/d/dmd/expression.h gdc-0.12/d/dmd/expression.h --- gdc-0.11/d/dmd/expression.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/expression.h 2005-05-19 02:15:50.000000000 +0200 @@ -73,6 +73,7 @@ static Array *arraySyntaxCopy(Array *exps); virtual integer_t toInteger(); + virtual uinteger_t toUInteger(); virtual real_t toReal(); virtual real_t toImaginary(); virtual complex_t toComplex(); @@ -128,6 +129,7 @@ integer_t toInteger(); real_t toReal(); real_t toImaginary(); + complex_t toComplex(); int isConst(); int isBool(int result); int implicitConvTo(Type *t); @@ -145,6 +147,7 @@ Expression *semantic(Scope *sc); char *toChars(); integer_t toInteger(); + uinteger_t toUInteger(); real_t toReal(); real_t toImaginary(); complex_t toComplex(); @@ -181,6 +184,7 @@ Expression *semantic(Scope *sc); char *toChars(); integer_t toInteger(); + uinteger_t toUInteger(); real_t toReal(); real_t toImaginary(); complex_t toComplex(); diff -uNr gdc-0.11/d/dmd/func.c gdc-0.12/d/dmd/func.c --- gdc-0.11/d/dmd/func.c 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/dmd/func.c 2005-05-19 02:15:50.000000000 +0200 @@ -674,7 +674,7 @@ { Expression *e; if (global.params.warnings) - { printf("warning - "); + { fprintf(stderr, "warning - "); error("no return at end of function"); } @@ -764,7 +764,7 @@ } if (inv) { - e = new DsymbolExp(0, ad->inv); + e = new DsymbolExp(0, inv); e = new CallExp(0, e); e = e->semantic(sc2); } @@ -1721,7 +1721,7 @@ error("invariants only are for struct/union/class definitions"); return; } - else if (ad->inv) + else if (ad->inv && ad->inv != this) { error("more than one invariant for %s", ad->toChars()); } diff -uNr gdc-0.11/d/dmd/html.c gdc-0.12/d/dmd/html.c --- gdc-0.11/d/dmd/html.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/html.c 2005-05-19 02:15:50.000000000 +0200 @@ -102,15 +102,15 @@ void Html::error(const char *format, ...) { - printf("%s:%d: HTML Error: ", sourcename, linnum); + fprintf(stderr, "%s:%d: HTML Error: ", sourcename, linnum); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); global.errors++; fatal(); @@ -461,6 +461,12 @@ int scangt = 0; //printf("scanComment()\n"); + if (*p == '\n') + { linnum++; + // Always extract new lines, so that D lexer counts the + // lines right. + dbuf->writeByte(*p); + } while (1) { //scangt = 1; // IE 5.0 compatibility diff -uNr gdc-0.11/d/dmd/identifier.c gdc-0.12/d/dmd/identifier.c --- gdc-0.11/d/dmd/identifier.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/identifier.c 2005-05-08 16:01:26.000000000 +0200 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + #include #include @@ -45,7 +51,7 @@ void Identifier::print() { - printf("%s",string); + fprintf(stderr, "%s",string); } int Identifier::dyncast() diff -uNr gdc-0.11/d/dmd/import.c gdc-0.12/d/dmd/import.c --- gdc-0.11/d/dmd/import.c 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/dmd/import.c 2005-05-19 02:15:50.000000000 +0200 @@ -49,33 +49,54 @@ return si; } - -void Import::semantic(Scope *sc) +void Import::load() { DsymbolTable *dst; Dsymbol *s; - //printf("Import::semantic('%s')\n", toChars()); + //printf("Import::load('%s')\n", toChars()); // See if existing module dst = Package::resolve(packages, NULL, &pkg); s = dst->lookup(id); - if (s && !s->isModule()) - error("package and module have the same name"); - else + if (s) { - mod = (Module *)s; - if (!mod) - { - // Load module - mod = Module::load(loc, packages, id); + if (s->isModule()) + mod = (Module *)s; + else + error("package and module have the same name"); + } + + if (!mod) + { + // Load module + mod = Module::load(loc, packages, id); + dst->insert(id, mod); // id may be different from mod->ident, + // if so then insert alias + } + if (!pkg) + pkg = mod; + mod->semantic(); + + //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg); +} + + +void Import::semantic(Scope *sc) +{ + //printf("Import::semantic('%s')\n", toChars()); + + load(); + + if (mod) + { + if (mod->loc.linnum != 0) + /* If the line number is not 0, then this is not + * a 'root' module, i.e. it was not specified on the command line. + */ mod->importedFrom = sc->module->importedFrom; - dst->insert(id, mod); // id may be different from mod->ident, - // if so then insert alias - } - mod->semantic(); - //printf("import '%s', protection = %d for '%s'\n", toChars(), sc->protection, mod->toChars()); + sc->scopesym->importScope(mod, sc->protection); // Modules need a list of each imported module @@ -84,11 +105,7 @@ if (mod->needmoduleinfo) sc->module->needmoduleinfo = 1; } - if (!pkg) - pkg = mod; - -// if (sc->module) -// sc->module->needmoduleinfo = 1; + //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); } void Import::semantic2(Scope *sc) @@ -100,6 +117,11 @@ Dsymbol *Import::search(Identifier *ident, int flags) { + //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags); + + if (!pkg) + load(); + // Forward it to the package/module return pkg->search(ident, flags); } diff -uNr gdc-0.11/d/dmd/import.h gdc-0.12/d/dmd/import.h --- gdc-0.11/d/dmd/import.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/dmd/import.h 2005-05-19 02:15:50.000000000 +0200 @@ -33,6 +33,7 @@ Import(Loc loc, Array *packages, Identifier *id); char *kind(); Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees + void load(); void semantic(Scope *sc); void semantic2(Scope *sc); Dsymbol *search(Identifier *ident, int flags); diff -uNr gdc-0.11/d/dmd/init.c gdc-0.12/d/dmd/init.c --- gdc-0.11/d/dmd/init.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/init.c 2005-05-19 02:15:50.000000000 +0200 @@ -257,9 +257,14 @@ val = val->semantic(sc, t->next); value.data[i] = (void *)val; length++; + if (length == 0) + error("array dimension overflow"); if (length > dim) dim = length; } + unsigned long amax = 0x80000000; + if ((unsigned long) dim * t->next->size() >= amax) + error(loc, "array dimension %u exceeds max of %lu", dim, amax / t->next->size()); return this; } diff -uNr gdc-0.11/d/dmd/lexer.c gdc-0.12/d/dmd/lexer.c --- gdc-0.11/d/dmd/lexer.c 2005-04-24 18:48:31.000000000 +0200 +++ gdc-0.12/d/dmd/lexer.c 2005-05-21 19:29:57.000000000 +0200 @@ -28,7 +28,7 @@ #ifdef IN_GCC #include -#include "../root/mem.h" +#include "mem.h" #else @@ -113,7 +113,7 @@ void Token::print() { - printf("%s\n", toChars()); + fprintf(stderr, "%s\n", toChars()); } char *Token::toChars() @@ -256,16 +256,36 @@ { char *p = loc.toChars(); if (*p) - printf("%s: ", p); + fprintf(stderr, "%s: ", p); + mem.free(p); + + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + + fprintf(stderr, "\n"); + fflush(stderr); + + global.errors++; + if (global.errors > 20) // moderate blizzard of cascading messages + fatal(); +} + +void Lexer::error(Loc loc, const char *format, ...) +{ + char *p = loc.toChars(); + if (*p) + fprintf(stderr, "%s: ", p); mem.free(p); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); global.errors++; if (global.errors > 20) // moderate blizzard of cascading messages @@ -1082,6 +1102,8 @@ p++; if (u == PS || u == LS) loc.linnum++; + stringbuffer.writeUTF8(u); + continue; } break; } @@ -1917,15 +1939,17 @@ Token tok; int linnum; char *filespec = NULL; + Loc loc = this->loc; scan(&tok); if (tok.value != TOKidentifier || tok.ident != Id::line) goto Lerr; scan(&tok); - if (tok.value != TOKint32v) + if (tok.value == TOKint32v || tok.value == TOKint64v) + linnum = tok.uns64value - 1; + else goto Lerr; - linnum = tok.uns64value - 1; while (1) { @@ -1935,13 +1959,17 @@ case 0x1A: case '\n': Lnewline: - loc.linnum = linnum; + this->loc.linnum = linnum; + if (filespec) + this->loc.filename = filespec; return; case '\r': p++; if (*p != '\n') - loc.linnum = linnum; + { p--; + goto Lnewline; + } continue; case ' ': @@ -1951,6 +1979,14 @@ p++; continue; // skip white space + case '_': + if (memcmp(p, "__FILE__", 8) == 0) + { + p += 8; + filespec = mem.strdup(loc.filename ? loc.filename : mod->ident->toChars()); + } + continue; + case '"': if (filespec) goto Lerr; @@ -1971,7 +2007,6 @@ case '"': stringbuffer.writeByte(0); filespec = mem.strdup((char *)stringbuffer.data); - loc.filename = filespec; p++; break; @@ -2000,7 +2035,7 @@ } Lerr: - error("#line integer [\"filespec\"]\\n expected"); + error(loc, "#line integer [\"filespec\"]\\n expected"); } @@ -2083,6 +2118,7 @@ { "pragma", TOKpragma }, { "typeof", TOKtypeof }, { "typeid", TOKtypeid }, + { "iftype", TOKiftype }, { "template", TOKtemplate }, { "instance", TOKinstance }, diff -uNr gdc-0.11/d/dmd/lexer.h gdc-0.12/d/dmd/lexer.h --- gdc-0.11/d/dmd/lexer.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/lexer.h 2005-05-21 19:29:57.000000000 +0200 @@ -70,6 +70,7 @@ TOKdeclaration, TOKtypeof, TOKpragma, TOKdsymbol, TOKtypeid, TOKuadd, + TOKiftype, // Operators TOKlt, TOKgt, @@ -253,6 +254,7 @@ TOK number(Token *t); TOK inreal(Token *t); void error(const char *format, ...); + void error(Loc loc, const char *format, ...); void pragma(); unsigned decodeUTF(); }; diff -uNr gdc-0.11/d/dmd/link.c gdc-0.12/d/dmd/link.c --- gdc-0.11/d/dmd/link.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/dmd/link.c 2005-05-21 19:29:57.000000000 +0200 @@ -182,11 +182,14 @@ argv.push((void *) global.params.linkswitches->data[i]); } - // Print it - for (i = 0; i < argv.dim; i++) - printf("%s ", (char *)argv.data[i]); - printf("\n"); - fflush(stdout); + if (!global.params.quiet) + { + // Print it + for (i = 0; i < argv.dim; i++) + printf("%s ", (char *)argv.data[i]); + printf("\n"); + fflush(stdout); + } argv.push(NULL); childpid = fork(); diff -uNr gdc-0.11/d/dmd/mangle.c gdc-0.12/d/dmd/mangle.c --- gdc-0.11/d/dmd/mangle.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/mangle.c 2005-05-08 16:01:26.000000000 +0200 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + #include #include #include @@ -62,7 +68,7 @@ return ident->toChars(); default: - printf("'%s', linkage = %d\n", toChars(), linkage); + fprintf(stderr, "'%s', linkage = %d\n", toChars(), linkage); assert(0); } } diff -uNr gdc-0.11/d/dmd/mars.c gdc-0.12/d/dmd/mars.c --- gdc-0.11/d/dmd/mars.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/mars.c 2005-05-25 03:51:33.000000000 +0200 @@ -28,7 +28,7 @@ #include "module.h" #include "mtype.h" #include "id.h" -#include "debcond.h" +#include "cond.h" void getenv_setargv(const char *envvar, int *pargc, char** *pargv); @@ -49,7 +49,7 @@ copyright = "Copyright (c) 1999-2005 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.121"; + version = "v0.125"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -128,21 +128,22 @@ files.d D source files\n\ -c do not link\n\ -d allow deprecated features\n\ + -debug compile in debug code\n\ + -debug=level compile in debug code <= level\n\ + -debug=ident compile in debug code identified by ident\n\ -g add symbolic debug info\n\ - -v verbose\n\ + -Ipath where to look for imports\n\ + -inline do function inlining\n\ + -Llinkerflag pass linkerflag to link\n\ -O optimize\n\ -odobjdir write object files to directory objdir\n\ -offilename name output file to filename\n\ -op do not strip paths from source file\n\ - -Ipath where to look for imports\n\ - -Llinkerflag pass linkerflag to link\n\ - -debug compile in debug code\n\ - -debug=level compile in debug code <= level\n\ - -debug=ident compile in debug code identified by ident\n\ - -inline do function inlining\n\ -profile profile runtime performance of generated code\n\ + -quiet suppress unnecessary messages\n\ -release compile release version\n\ -unittest compile in unit tests\n\ + -v verbose\n\ -version=level compile in version code >= level\n\ -version=ident compile in version code identified by ident\n\ -w enable warnings\n\ @@ -269,6 +270,8 @@ } else if (strcmp(p + 1, "inline") == 0) global.params.useInline = 1; + else if (strcmp(p + 1, "quiet") == 0) + global.params.quiet = 1; else if (strcmp(p + 1, "release") == 0) global.params.release = 1; else if (strcmp(p + 1, "unittest") == 0) @@ -521,7 +524,7 @@ if (global.params.verbose) printf("parse %s\n", m->toChars()); m->deleteObjFile(); - m->read(); + m->read(0); m->parse(); } if (global.errors) diff -uNr gdc-0.11/d/dmd/mars.h gdc-0.12/d/dmd/mars.h --- gdc-0.11/d/dmd/mars.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/mars.h 2005-05-21 19:29:57.000000000 +0200 @@ -27,6 +27,7 @@ { char link; // perform link char trace; // insert profiling hooks + char quiet; // suppress non-error messages char verbose; // verbose compile char symdebug; // insert debug symbolic information char optimize; // run optimizer @@ -115,8 +116,14 @@ #endif #endif +// Be careful not to care about sign with integer_t typedef unsigned long long integer_t; +// Signed and unsigned variants +typedef long long sinteger_t; +typedef unsigned long long uinteger_t; + + typedef signed char d_int8; typedef unsigned char d_uns8; typedef short d_int16; @@ -211,6 +218,7 @@ void error(Loc loc, const char *format, ...); void fatal(); +void err_nomem(); int runLINK(); void inifile(char *argv0, char *inifile); diff -uNr gdc-0.11/d/dmd/mem.c gdc-0.12/d/dmd/mem.c --- gdc-0.11/d/dmd/mem.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/dmd/mem.c 2005-05-19 02:15:50.000000000 +0200 @@ -2,11 +2,19 @@ /* Copyright (c) 2000 Digital Mars */ /* All Rights Reserved */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + #include #include #include -#if linux +#if IN_GCC +#include "mem.h" +#elif linux #include "../root/mem.h" #else #include "mem.h" @@ -110,7 +118,7 @@ void Mem::error() { - printf("Error: out of memory\n"); + fprintf(stderr, "Error: out of memory\n"); exit(EXIT_FAILURE); } @@ -127,7 +135,12 @@ void * operator new(size_t m_size) { - return malloc(m_size); + void *p = malloc(m_size); + if (p) + return p; + fprintf(stderr, "Error: out of memory\n"); + exit(EXIT_FAILURE); + return p; } void operator delete(void *p) diff -uNr gdc-0.11/d/dmd/module.c gdc-0.12/d/dmd/module.c --- gdc-0.11/d/dmd/module.c 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/dmd/module.c 2005-05-21 19:29:57.000000000 +0200 @@ -16,9 +16,8 @@ #include #include #include -#ifndef alloca -#include -#endif + +#include "gdc_alloca.h" #include "mars.h" #include "module.h" @@ -176,7 +175,7 @@ // BUG: the sym file is actually a source file that is // parsed. Someday make it a real symbol table m->srcfile = m->symfile; - m->read(); + m->read(loc); m->parse(); #ifdef IN_GCC @@ -186,10 +185,13 @@ return m; } -void Module::read() +void Module::read(Loc loc) { //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars()); - srcfile->readv(); + if (srcfile->read()) + { error(loc, "cannot read file '%s'", srcfile->toChars()); + fatal(); + } } inline unsigned readwordLE(unsigned short *p) @@ -480,7 +482,7 @@ { Dsymbol *s; s = (Dsymbol *)members->data[i]; - s->addMember(sc->scopesym); + s->addMember(NULL, sc->scopesym); } // Pass 1 semantic routines: do public side of the definition diff -uNr gdc-0.11/d/dmd/module.h gdc-0.12/d/dmd/module.h --- gdc-0.11/d/dmd/module.h 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/dmd/module.h 2005-05-19 02:15:50.000000000 +0200 @@ -92,7 +92,7 @@ static Module *load(Loc loc, Array *packages, Identifier *ident); char *kind(); - void read(); // read file + void read(Loc loc); // read file void parse(bool dump_source = false); // syntactic parse void semantic(); // semantic analysis void semantic2(); // pass 2 semantic analysis diff -uNr gdc-0.11/d/dmd/mtype.c gdc-0.12/d/dmd/mtype.c --- gdc-0.11/d/dmd/mtype.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/mtype.c 2005-05-21 19:29:57.000000000 +0200 @@ -18,9 +18,8 @@ #include #include -#ifndef alloca -#include -#endif + +#include "gdc_alloca.h" #ifdef __DMC__ #include @@ -123,7 +122,7 @@ Type *Type::syntaxCopy() { print(); - printf("ty = %d\n", ty); + fprintf(stderr, "ty = %d\n", ty); assert(0); return this; } @@ -194,7 +193,7 @@ for (i = 0; i < TMAX; i++) { if (!mangleChar[i]) - printf("ty = %d\n", i); + fprintf(stderr, "ty = %d\n", i); assert(mangleChar[i]); } @@ -517,8 +516,7 @@ } else if (ident == Id::size) { - if (!global.params.useDeprecated) - error(loc, ".size property is deprecated, use .sizeof"); + error(loc, ".size property should be replaced with .sizeof"); e = new IntegerExp(loc, size(loc), Type::tsize_t); } else if (ident == Id::alignof) @@ -602,16 +600,16 @@ { char *p = loc.toChars(); if (*p) - printf("%s: ", p); + fprintf(stderr, "%s: ", p); mem.free(p); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); global.errors++; //fatal(); @@ -1565,6 +1563,7 @@ { //printf("TypeSArray::semantic() %s\n", toChars()); next = next->semantic(loc,sc); + Type *tbn = next->toBasetype(); if (dim) { integer_t n, n2; @@ -1577,23 +1576,26 @@ if (d1 != d2) goto Loverflow; - if (next->ty == Tbit && (d2 + 31) < d2) + + if (tbn->ty == Tbit && (d2 + 31) < d2) goto Loverflow; - else if (next->isintegral() || - next->isfloating() || - next->ty == Tpointer || - next->ty == Tarray || - next->ty == Tsarray || - next->ty == Taarray || - next->ty == Tclass) + else if (tbn->isintegral() || + tbn->isfloating() || + tbn->ty == Tpointer || + tbn->ty == Tarray || + tbn->ty == Tsarray || + tbn->ty == Taarray || + tbn->ty == Tclass) { /* Only do this for types that don't need to have semantic() * run on them for the size, since they may be forward referenced. */ - n = next->size(loc); + n = tbn->size(loc); n2 = n * d2; if ((int)n2 < 0) goto Loverflow; + if (n2 >= 0x1000000) // put a 'reasonable' limit on it + goto Loverflow; if (n && n2 / n != d2) { Loverflow: @@ -1602,15 +1604,15 @@ } } } - switch (next->ty) + switch (tbn->ty) { case Tfunction: case Tnone: - error(loc, "can't have array of %s", next->toChars()); + error(loc, "can't have array of %s", tbn->toChars()); break; } - if (next->isauto()) - error(loc, "cannot have array of auto %s", next->toChars()); + if (tbn->isauto()) + error(loc, "cannot have array of auto %s", tbn->toChars()); return merge(); } @@ -3275,6 +3277,10 @@ { e = new IntegerExp(0, sym->minval, this); } + else if (ident == Id::init) + { + e = defaultInit(); + } else { assert(sym->memtype); @@ -3711,7 +3717,7 @@ printf("TypeStruct::defaultInit() '%s'\n", toChars()); #endif s = sym->toInitializer(); - d = new SymbolDeclaration(sym->loc, s); + d = new SymbolDeclaration(sym->loc, s, sym); assert(d); d->type = this; return new VarExp(sym->loc, d); diff -uNr gdc-0.11/d/dmd/opover.c gdc-0.12/d/dmd/opover.c --- gdc-0.11/d/dmd/opover.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/opover.c 2005-05-08 16:01:26.000000000 +0200 @@ -26,10 +26,11 @@ #define integer_t dmd_integer_t #endif -#ifndef _WIN32 +#if IN_GCC +#include "mem.h" +#elif linux #include "../root/mem.h" -#endif -#if _WIN32 +#elif _WIN32 #include "..\root\mem.h" #endif diff -uNr gdc-0.11/d/dmd/optimize.c gdc-0.12/d/dmd/optimize.c --- gdc-0.11/d/dmd/optimize.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/optimize.c 2005-05-21 19:29:57.000000000 +0200 @@ -23,6 +23,7 @@ Expression *Expression::optimize(int result) { + //printf("Expression::optimize(result = %d) %s\n", result, toChars()); return this; } @@ -156,6 +157,7 @@ Expression *BinExp::optimize(int result) { Expression *e; + //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() == 1 && e2->isConst() == 1) diff -uNr gdc-0.11/d/dmd/parse.c gdc-0.12/d/dmd/parse.c --- gdc-0.11/d/dmd/parse.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/parse.c 2005-05-21 19:29:57.000000000 +0200 @@ -21,7 +21,7 @@ #include "parse.h" #include "init.h" #include "attrib.h" -#include "debcond.h" +#include "cond.h" #include "mtype.h" #include "template.h" #include "staticassert.h" @@ -144,8 +144,10 @@ { Dsymbol *s; Array *decldefs; Array *a; + Array *aelse; enum PROT prot; unsigned stc; + Condition *condition; //printf("Parser::parseDeclDefs()\n"); decldefs = new Array(); @@ -251,6 +253,10 @@ s = parseStaticDtor(); else if (token.value == TOKassert) s = parseStaticAssert(); + else if (token.value == TOKif) + { condition = parseStaticIfCondition(); + goto Lcondition; + } else { stc = STCstatic; goto Lstc2; @@ -398,17 +404,14 @@ } case TOKdebug: - { DebugCondition *condition; - Array *aelse; - nextToken(); if (token.value == TOKassign) { nextToken(); if (token.value == TOKidentifier) - s = new DebugSymbol(token.ident); + s = new DebugSymbol(loc, token.ident); else if (token.value == TOKint32v) - s = new DebugSymbol((unsigned)token.uns64value); + s = new DebugSymbol(loc, (unsigned)token.uns64value); else { error("identifier or integer expected, not %s", token.toChars()); s = NULL; @@ -420,36 +423,18 @@ break; } - if (token.value == TOKlparen) - { - nextToken(); - condition = parseDebugCondition(); - check(TOKrparen); - } - else - condition = new DebugCondition(mod, 1, NULL); - a = parseBlock(); - aelse = NULL; - if (token.value == TOKelse) - { nextToken(); - aelse = parseBlock(); - } - s = new DebugDeclaration(condition, a, aelse); - break; - } + condition = parseDebugCondition(); + goto Lcondition; case TOKversion: - { VersionCondition *condition; - Array *aelse; - nextToken(); if (token.value == TOKassign) { nextToken(); if (token.value == TOKidentifier) - s = new VersionSymbol(token.ident); + s = new VersionSymbol(loc, token.ident); else if (token.value == TOKint32v) - s = new VersionSymbol((unsigned)token.uns64value); + s = new VersionSymbol(loc, (unsigned)token.uns64value); else { error("identifier or integer expected, not %s", token.toChars()); s = NULL; @@ -460,26 +445,22 @@ nextToken(); break; } + condition = parseVersionCondition(); + goto Lcondition; - if (token.value == TOKlparen) - { - nextToken(); - condition = parseVersionCondition(); - check(TOKrparen); - } - else - { error("(condition) expected following version"); - condition = NULL; - } + case TOKiftype: + condition = parseIftypeCondition(); + goto Lcondition; + + Lcondition: a = parseBlock(); aelse = NULL; if (token.value == TOKelse) { nextToken(); aelse = parseBlock(); } - s = new VersionDeclaration(condition, a, aelse); + s = new ConditionalDeclaration(condition, a, aelse); break; - } case TOKsemicolon: // empty declaration nextToken(); @@ -500,6 +481,7 @@ return decldefs; } + /******************************************** * Parse declarations after an align, protection, or extern decl. */ @@ -566,40 +548,132 @@ * Parse a debug conditional */ -DebugCondition *Parser::parseDebugCondition() +Condition *Parser::parseDebugCondition() { - unsigned level = 1; - Identifier *id = NULL; + Condition *c; - if (token.value == TOKidentifier) - id = token.ident; - else if (token.value == TOKint32v) - level = (unsigned)token.uns64value; + if (token.value == TOKlparen) + { + nextToken(); + unsigned level = 1; + Identifier *id = NULL; + + if (token.value == TOKidentifier) + id = token.ident; + else if (token.value == TOKint32v) + level = (unsigned)token.uns64value; + else + error("identifier or integer expected, not %s", token.toChars()); + nextToken(); + check(TOKrparen); + c = new DebugCondition(mod, level, id); + } else - error("identifier or integer expected, not %s", token.toChars()); - nextToken(); + c = new DebugCondition(mod, 1, NULL); + return c; - return new DebugCondition(mod, level, id); } /************************************** * Parse a version conditional */ -VersionCondition *Parser::parseVersionCondition() +Condition *Parser::parseVersionCondition() { - unsigned level = 1; - Identifier *id = NULL; + Condition *c; - if (token.value == TOKidentifier) - id = token.ident; - else if (token.value == TOKint32v) - level = (unsigned)token.uns64value; + if (token.value == TOKlparen) + { + unsigned level = 1; + Identifier *id = NULL; + + nextToken(); + if (token.value == TOKidentifier) + id = token.ident; + else if (token.value == TOKint32v) + level = (unsigned)token.uns64value; + else + error("identifier or integer expected, not %s", token.toChars()); + nextToken(); + check(TOKrparen); + + c = new VersionCondition(mod, level, id); + } + else + { error("(condition) expected following version"); + c = NULL; + } + return c; + +} + +/*********************************************** + * static if (expression) + * body + * else + * body + */ + +Condition *Parser::parseStaticIfCondition() +{ Expression *exp; + Condition *condition; + Array *aif; + Array *aelse; + Loc loc = this->loc; + + nextToken(); + if (token.value == TOKlparen) + { + nextToken(); + exp = parseAssignExp(); + check(TOKrparen); + } else - error("identifier or integer expected, not %s", token.toChars()); + { error("(expression) expected following static if"); + exp = NULL; + } + condition = new StaticIfCondition(loc, exp); + return condition; +} + + +/*********************************************** + * iftype (type identifier : specialization) + * body + * else + * body + */ + +Condition *Parser::parseIftypeCondition() +{ + Type *targ; + Identifier *ident = NULL; + Type *tspec = NULL; + Loc loc = this->loc; + nextToken(); + if (token.value == TOKlparen) + { + nextToken(); + targ = parseBasicType(); + targ = parseDeclarator(targ, &ident); + if (token.value == TOKcolon) + { + nextToken(); + tspec = parseBasicType(); + tspec = parseDeclarator(tspec, NULL); + } + check(TOKrparen); - return new VersionCondition(mod, level, id); + if (!ident && !tspec) + error("expected either Identifier or TypeSpecialization or both"); + } + else + { error("(type identifier : specialization) expected following iftype"); + return NULL; + } + Condition *condition = new IftypeCondition(loc, targ, ident, tspec); + return condition; } /***************************************** @@ -850,6 +924,7 @@ { EnumDeclaration *e; Identifier *id; Type *t; + Loc loc = this->loc; //printf("Parser::parseEnum()\n"); nextToken(); @@ -868,7 +943,7 @@ else t = NULL; - e = new EnumDeclaration(id, t); + e = new EnumDeclaration(loc, id, t); if (token.value == TOKsemicolon && id) nextToken(); else if (token.value == TOKlcurly) @@ -936,6 +1011,7 @@ } } + Loc loc = this->loc; switch (tok) { case TOKclass: case TOKinterface: @@ -1026,7 +1102,7 @@ { /* Anonymous structs/unions are more like attributes. */ - return new AnonDeclaration(anon - 1, decl); + return new AnonDeclaration(loc, anon - 1, decl); } else a->members = decl; @@ -1908,7 +1984,7 @@ init = parseInitializer(); } if (tok == TOKtypedef) - v = new TypedefDeclaration(ident, t, init); + v = new TypedefDeclaration(loc, ident, t, init); else { if (init) error("alias cannot have initializer"); @@ -2197,6 +2273,9 @@ Statement *Parser::parseStatement(int flags) { Statement *s; Token *t; + Condition *condition; + Statement *ifbody; + Statement *elsebody; Loc loc = this->loc; //printf("parseStatement()\n"); @@ -2306,7 +2385,7 @@ break; case TOKstatic: - { // Look ahead to see if it's static assert() + { // Look ahead to see if it's static assert() or static if() Token *t; t = peek(&token); @@ -2316,6 +2395,12 @@ s = new StaticAssertStatement(parseStaticAssert()); break; } + if (t->value == TOKif) + { + nextToken(); + condition = parseStaticIfCondition(); + goto Lcondition; + } goto Ldeclaration; } @@ -2539,58 +2624,29 @@ } case TOKdebug: - { Condition *condition; - Statement *ifbody; - Statement *elsebody; - nextToken(); - if (token.value == TOKlparen) - { - nextToken(); - condition = parseDebugCondition(); - check(TOKrparen); - } - else - condition = new DebugCondition(mod, 1, NULL); - ifbody = parseStatement(PSsemi); - if (token.value == TOKelse) - { - nextToken(); - elsebody = parseStatement(PSsemi); - } - else - elsebody = NULL; - s = new ConditionalStatement(loc, condition, ifbody, elsebody); - break; - } + condition = parseDebugCondition(); + goto Lcondition; case TOKversion: - { Condition *condition; - Statement *ifbody; - Statement *elsebody; - nextToken(); - if (token.value == TOKlparen) - { - nextToken(); - condition = parseVersionCondition(); - check(TOKrparen); - } - else - { error("(condition) expected after version"); - condition = NULL; - } + condition = parseVersionCondition(); + goto Lcondition; + + case TOKiftype: + condition = parseIftypeCondition(); + goto Lcondition; + + Lcondition: ifbody = parseStatement(PSsemi); + elsebody = NULL; if (token.value == TOKelse) { nextToken(); elsebody = parseStatement(PSsemi); } - else - elsebody = NULL; s = new ConditionalStatement(loc, condition, ifbody, elsebody); break; - } case TOKpragma: { Identifier *ident; @@ -2920,6 +2976,7 @@ continue; case TOKeof: + /* { */ error("matching '}' expected, not end of file"); break; diff -uNr gdc-0.11/d/dmd/parse.h gdc-0.12/d/dmd/parse.h --- gdc-0.11/d/dmd/parse.h 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/dmd/parse.h 2005-05-21 19:29:57.000000000 +0200 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2003 by Digital Mars +// Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -28,12 +28,12 @@ struct DtorDeclaration; struct StaticCtorDeclaration; struct StaticDtorDeclaration; +struct ConditionalDeclaration; struct InvariantDeclaration; struct UnitTestDeclaration; struct NewDeclaration; struct DeleteDeclaration; -struct DebugCondition; -struct VersionCondition; +struct Condition; struct Module; struct ModuleDeclaration; struct TemplateDeclaration; @@ -58,8 +58,10 @@ Dsymbol *parseMixin(); Array *parseTemplateArgumentList(); StaticAssert *parseStaticAssert(); - DebugCondition *parseDebugCondition(); - VersionCondition *parseVersionCondition(); + Condition *parseDebugCondition(); + Condition *parseVersionCondition(); + Condition *parseStaticIfCondition(); + Condition *parseIftypeCondition(); CtorDeclaration *parseCtor(); DtorDeclaration *parseDtor(); StaticCtorDeclaration *parseStaticCtor(); diff -uNr gdc-0.11/d/dmd/root.c gdc-0.12/d/dmd/root.c --- gdc-0.11/d/dmd/root.c 2005-04-12 05:16:27.000000000 +0200 +++ gdc-0.12/d/dmd/root.c 2005-05-08 16:01:26.000000000 +0200 @@ -18,13 +18,8 @@ #include #include #include -#ifndef alloca -#include -#endif -#if _MSC_VER -#include -#endif +#include "gdc_alloca.h" #if _WIN32 #include @@ -124,11 +119,11 @@ va_list ap; va_start(ap, format); - printf("Error: "); - vprintf(format, ap); + fprintf(stderr, "Error: "); + vfprintf(stderr, format, ap); va_end( ap ); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); exit(EXIT_FAILURE); } @@ -139,11 +134,11 @@ va_list ap; va_start(ap, format); - printf("Error: "); - vwprintf(format, ap); + fprintf(stderr, "Error: "); + vfwprintf(stderr, format, ap); va_end( ap ); - printf("\n"); - fflush(stdout); + printf(stderr, "\n"); + fflush(stderr); exit(EXIT_FAILURE); } @@ -163,11 +158,11 @@ va_list ap; va_start(ap, format); - printf("Warning: "); - vprintf(format, ap); + fprintf(stderr, "Warning: "); + vfprintf(stderr, format, ap); va_end( ap ); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); } /****************************** Object ********************************/ @@ -189,7 +184,7 @@ void Object::print() { - printf("%s %p\n", toChars(), this); + fprintf(stderr, "%s %p\n", toChars(), this); } char *Object::toChars() @@ -307,7 +302,7 @@ void String::print() { - printf("String '%s'\n",str); + fprintf(stderr, "String '%s'\n",str); } @@ -336,7 +331,7 @@ } #endif #if _WIN32 - if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':') + if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':' && path[pathlen - 1] != '/') { f[pathlen] = '\\'; pathlen++; } @@ -526,6 +521,7 @@ break; #endif #if _WIN32 + case '/': case '\\': case ':': break; @@ -564,6 +560,7 @@ return e + 1; #endif #if _WIN32 + case '/': case '\\': case ':': return e + 1; @@ -601,7 +598,7 @@ n--; #endif #if _WIN32 - if (n[-1] == '\\') + if (n[-1] == '\\' || n[-1] == '/') n--; #endif } @@ -639,7 +636,7 @@ } #endif #if _WIN32 - if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':') + if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':' && path[pathlen - 1] != '/') { f[pathlen] = '\\'; pathlen++; } @@ -864,21 +861,21 @@ //printf("\tfile opened\n"); if (fstat(fd, &buf)) { - printf("\tfstat error, errno = %d\n",errno); + fprintf(stderr, "\tfstat error, errno = %d\n",errno); goto err2; } size = buf.st_size; buffer = (unsigned char *) mem.malloc(size + 2); if (!buffer) { - printf("\tmalloc error, errno = %d\n",errno); + fprintf(stderr, "\tmalloc error, errno = %d\n",errno); goto err2; } numread = ::read(fd, buffer, size); if (numread != size) { - printf("\tread error, errno = %d\n",errno); + fprintf(stderr, "\tread error, errno = %d\n",errno); goto err2; } @@ -887,7 +884,7 @@ if (close(fd) == -1) { - printf("\tclose error, errno = %d\n",errno); + fprintf(stderr, "\tclose error, errno = %d\n",errno); goto err; } diff -uNr gdc-0.11/d/dmd/scope.c gdc-0.12/d/dmd/scope.c --- gdc-0.11/d/dmd/scope.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/scope.c 2005-05-21 19:29:57.000000000 +0200 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + #include #include @@ -107,7 +113,7 @@ Dsymbol *m = module; while (m->parent) m = m->parent; - m->addMember(sc->scopesym); + m->addMember(NULL, sc->scopesym); m->parent = NULL; // got changed by addMember() // Create the module scope underneath the global scope @@ -218,7 +224,7 @@ sc->enclosing && sc->enclosing->search(ident, NULL)) { - printf("warning - "); + fprintf(stderr, "warning - "); error("array 'length' hides other 'length' name in outer scope"); } diff -uNr gdc-0.11/d/dmd/statement.c gdc-0.12/d/dmd/statement.c --- gdc-0.11/d/dmd/statement.c 2005-04-26 03:45:07.000000000 +0200 +++ gdc-0.12/d/dmd/statement.c 2005-05-21 19:29:57.000000000 +0200 @@ -21,7 +21,7 @@ #include "statement.h" #include "expression.h" -#include "debcond.h" +#include "cond.h" #include "init.h" #include "staticassert.h" #include "mtype.h" @@ -46,8 +46,8 @@ void Statement::print() { - printf("%s\n", toChars()); - fflush(stdout); + fprintf(stderr, "%s\n", toChars()); + fflush(stderr); } char *Statement::toChars() @@ -89,16 +89,16 @@ { char *p = loc.toChars(); if (*p) - printf("%s: ", p); + fprintf(stderr, "%s: ", p); mem.free(p); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); global.errors++; fatal(); @@ -383,7 +383,7 @@ if (!falloff && global.params.warnings && !s->comeFrom()) { - printf("warning - "); + fprintf(stderr, "warning - "); s->error("statement is not reachable"); } falloff = s->fallOffEnd(); @@ -629,7 +629,8 @@ int ForStatement::fallOffEnd() { - body->fallOffEnd(); + if (body) + body->fallOffEnd(); return TRUE; } @@ -975,7 +976,8 @@ int ForeachStatement::fallOffEnd() { - body->fallOffEnd(); + if (body) + body->fallOffEnd(); return TRUE; } @@ -1008,41 +1010,18 @@ // semantic analysis of the skipped code. // This feature allows a limited form of conditional compilation. condition = condition->optimize(WANTflags); -#if 0 - /* Don't do this because of: - * if (0) { Label: ... ; } else { ... ; goto Label; } - */ - if (condition->isBool(FALSE)) - { Statement *s; - s = new ExpStatement(loc, condition); - if (elsebody) - { elsebody = elsebody->semanticScope(sc, NULL, NULL); - s = new CompoundStatement(loc, s, elsebody); - } - return s; - } - else if (condition->isBool(TRUE)) - { Statement *s; + // Evaluate at runtime + unsigned cs0 = sc->callSuper; + unsigned cs1; + + ifbody = ifbody->semanticScope(sc, NULL, NULL); + cs1 = sc->callSuper; + sc->callSuper = cs0; + if (elsebody) + elsebody = elsebody->semanticScope(sc, NULL, NULL); + sc->mergeCallSuper(loc, cs1); - s = new ExpStatement(loc, condition); - ifbody = ifbody->semanticScope(sc, NULL, NULL); - s = new CompoundStatement(loc, s, ifbody); - return s; - } - else -#endif - { // Evaluate at runtime - unsigned cs0 = sc->callSuper; - unsigned cs1; - - ifbody = ifbody->semanticScope(sc, NULL, NULL); - cs1 = sc->callSuper; - sc->callSuper = cs0; - if (elsebody) - elsebody = elsebody->semanticScope(sc, NULL, NULL); - sc->mergeCallSuper(loc, cs1); - } return this; } @@ -1082,7 +1061,7 @@ if (elsebody) e = elsebody->syntaxCopy(); ConditionalStatement *s = new ConditionalStatement(loc, - condition, ifbody->syntaxCopy(), e); + condition->syntaxCopy(), ifbody->syntaxCopy(), e); return s; } @@ -1093,26 +1072,17 @@ // If we can short-circuit evaluate the if statement, don't do the // semantic analysis of the skipped code. // This feature allows a limited form of conditional compilation. - if (condition->isBool(FALSE)) - { - if (elsebody) - elsebody = elsebody->semantic(sc); - return elsebody; - } - else if (condition->isBool(TRUE)) + if (condition->include(sc, NULL)) { ifbody = ifbody->semantic(sc); return ifbody; } else - { Statement *s; - - // Evaluate at runtime - s = new IfStatement(loc, condition->toExpr(), ifbody, elsebody); - s = s->semantic(sc); - return s; + { + if (elsebody) + elsebody = elsebody->semantic(sc); + return elsebody; } - return this; } int ConditionalStatement::usesEH() @@ -1122,6 +1092,8 @@ void ConditionalStatement::toCBuffer(OutBuffer *buf) { + condition->toCBuffer(buf); + buf->writenl(); buf->printf("ConditionalStatement::toCBuffer()"); buf->writenl(); } @@ -1161,12 +1133,12 @@ if (e->op == TOKstring) { StringExp *se = (StringExp *)e; - printf("%.*s", se->len, se->string); + fprintf(stderr, "%.*s", se->len, se->string); } else error("string expected for message, not '%s'", e->toChars()); } - printf("\n"); + fprintf(stderr, "\n"); } } else if (ident == Id::lib) @@ -1319,7 +1291,7 @@ if (!sc->sw->sdefault) { if (global.params.warnings) - { printf("warning - "); + { fprintf(stderr, "warning - "); error("switch statement has no default"); } diff -uNr gdc-0.11/d/dmd/staticassert.c gdc-0.12/d/dmd/staticassert.c --- gdc-0.11/d/dmd/staticassert.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/dmd/staticassert.c 2005-05-21 19:29:57.000000000 +0200 @@ -33,7 +33,7 @@ return sa; } -void StaticAssert::addMember(ScopeDsymbol *sd) +void StaticAssert::addMember(Scope *sc, ScopeDsymbol *sd) { } diff -uNr gdc-0.11/d/dmd/staticassert.h gdc-0.12/d/dmd/staticassert.h --- gdc-0.11/d/dmd/staticassert.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/dmd/staticassert.h 2005-05-21 19:29:57.000000000 +0200 @@ -25,7 +25,7 @@ StaticAssert(Loc loc, Expression *exp); Dsymbol *syntaxCopy(Dsymbol *s); - void addMember(ScopeDsymbol *sd); + void addMember(Scope *sc, ScopeDsymbol *sd); void semantic(Scope *sc); void semantic2(Scope *sc); void inlineScan(); diff -uNr gdc-0.11/d/dmd/struct.c gdc-0.12/d/dmd/struct.c --- gdc-0.11/d/dmd/struct.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/struct.c 2005-05-21 19:29:57.000000000 +0200 @@ -229,6 +229,9 @@ scx = scope; // save so we don't make redundant copies scope = NULL; } +#ifdef IN_GCC + methods.setDim(0); +#endif parent = sc->parent; handle = type->pointerTo(); @@ -243,7 +246,7 @@ { Dsymbol *s = (Dsymbol *)members->data[i]; //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); - s->addMember(this); + s->addMember(sc, this); } } @@ -309,8 +312,10 @@ e = new IdentifierExp(loc, id); e = new CallExp(loc, e, args); fdptr->fbody = new ReturnStatement(loc, e); - members->push(fdptr); - fdptr->addMember(this); + ScopeDsymbol *s = fdx->parent->isScopeDsymbol(); + assert(s); + s->members->push(fdptr); + fdptr->addMember(sc, s); fdptr->semantic(sc2); } } diff -uNr gdc-0.11/d/dmd/template.c gdc-0.12/d/dmd/template.c --- gdc-0.11/d/dmd/template.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/template.c 2005-05-27 03:05:04.000000000 +0200 @@ -790,7 +790,7 @@ void TemplateTypeParameter::print(Object *oarg, Object *oded) { - printf(" %s\n", ident->toChars()); + fprintf(stderr, " %s\n", ident->toChars()); Type *t = isType(oarg); Type *ta = isType(oded); @@ -798,11 +798,11 @@ assert(ta); if (specType) - printf("\tSpecialization: %s\n", specType->toChars()); + fprintf(stderr, "\tSpecialization: %s\n", specType->toChars()); if (defaultType) - printf("\tDefault: %s\n", defaultType->toChars()); - printf("\tArgument: %s\n", t ? t->toChars() : "NULL"); - printf("\tDeduced Type: %s\n", ta->toChars()); + fprintf(stderr, "\tDefault: %s\n", defaultType->toChars()); + fprintf(stderr, "\tArgument: %s\n", t ? t->toChars() : "NULL"); + fprintf(stderr, "\tDeduced Type: %s\n", ta->toChars()); } @@ -969,12 +969,12 @@ void TemplateAliasParameter::print(Object *oarg, Object *oded) { - printf(" %s\n", ident->toChars()); + fprintf(stderr, " %s\n", ident->toChars()); Dsymbol *sa = isDsymbol(oded); assert(sa); - printf("\tArgument alias: %s\n", sa->toChars()); + fprintf(stderr, "\tArgument alias: %s\n", sa->toChars()); } void TemplateAliasParameter::toCBuffer(OutBuffer *buf) @@ -1157,13 +1157,13 @@ void TemplateValueParameter::print(Object *oarg, Object *oded) { - printf(" %s\n", ident->toChars()); + fprintf(stderr, " %s\n", ident->toChars()); Expression *ea = isExpression(oded); if (specValue) - printf("\tSpecialization: %s\n", specValue->toChars()); - printf("\tArgument Value: %s\n", ea ? ea->toChars() : "NULL"); + fprintf(stderr, "\tSpecialization: %s\n", specValue->toChars()); + fprintf(stderr, "\tArgument Value: %s\n", ea ? ea->toChars() : "NULL"); } @@ -1227,6 +1227,9 @@ this->argsym = NULL; this->aliasdecl = NULL; this->semanticdone = 0; +#ifdef IN_GCC + this->objFileModule = NULL; +#endif } @@ -1270,17 +1273,24 @@ } #ifdef IN_GCC -// This is needed for -femit-templates=private work-around. We -// must ensure the TemplateInstance ends up as a member of the -// module that is being compiled so that the template instance's -// toObjfile is called. -extern Module * getCurrentModule(); +#include "d-dmd-gcc.h" #endif void TemplateInstance::semantic(Scope *sc) { #if LOG - printf("+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); + printf("+TemplateInstance::semantic('%s' (%p), this=%p)\n", toChars(), this, this); +#endif +#ifdef IN_GCC + /* + fprintf(stderr, "ti '%s' (%p), belongs in '%s'\n", toChars(), this, + sc->module->toPrettyChars()); + if (inst) { + fprintf(stderr, " -- really '%s' (%p)\n", inst->toChars(), inst); + } else { + fprintf(stderr, " -- doing semantic\n"); + } + */ #endif if (inst) // if semantic() was already run { @@ -1404,21 +1414,37 @@ { Array *a; int i; #ifdef IN_GCC - // For gcc, always add it the module that is being compiled - a = getCurrentModule()->members; -#else + /* For "all" and "private" template modes, templates are always + emitted. Problem: This picks up templates that aren't even + needed in the current module. */ + + if (d_gcc_force_templates()) + { + //fprintf(stderr, "\t0: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars()); + objFileModule = getCurrentModule(); + a = objFileModule->members; + } + else +#endif if (sc->scopesym && sc->scopesym->members && !sc->scopesym->isTemplateMixin()) { + //fprintf(stderr, "\t1: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars()); //printf("\t1: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars()); a = sc->scopesym->members; +#ifdef IN_GCC + objFileModule = sc->module; // %% correct? +#endif } else { + //fprintf(stderr, "\t2: adding to module %s\n", sc->module->importedFrom->toChars()); //printf("\t2: adding to module %s\n", sc->module->importedFrom->toChars()); a = sc->module->importedFrom->members; - } +#ifdef IN_GCC + objFileModule = sc->module->importedFrom; #endif + } for (i = 0; 1; i++) { if (i == a->dim) @@ -1462,7 +1488,7 @@ #if LOG printf("\tadding member '%s' %p to '%s'\n", s->toChars(), s, this->toChars()); #endif - s->addMember(this); + s->addMember(scope, this); } /* See if there is only one member of template instance, and that @@ -2062,6 +2088,7 @@ #if LOG printf("\tdo semantic\n"); #endif + // Run semantic on each argument, place results in tiargs[] semanticTiargs(sc); @@ -2154,41 +2181,59 @@ inst = this; parent = sc->parent; - // Copy the syntax trees from the TemplateDeclaration - members = Dsymbol::arraySyntaxCopy(tempdecl->members); - if (!members) - return; - - symtab = new DsymbolTable(); - - // Add members to enclosing scope, as well as this scope - for (unsigned i = 0; i < members->dim; i++) - { Dsymbol *s; + /* Detect recursive mixin instantiations. + */ + for (Dsymbol *s = parent; s; s = s->parent) + { + //printf("\ts = '%s'\n", s->toChars()); + TemplateMixin *tm = s->isTemplateMixin(); + if (!tm || tempdecl != tm->tempdecl) + continue; - s = (Dsymbol *)members->data[i]; - s->addMember(this); - //sc->insert(s); - //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); - //printf("s->parent = %s\n", s->parent->toChars()); - if (isAnonymous()) - { -#if 0 - if (sc->parent != sc->scopesym) + for (int i = 0; i < tiargs->dim; i++) + { Object *o = (Object *)tiargs->data[i]; + Type *ta = isType(o); + Expression *ea = isExpression(o); + Dsymbol *sa = isDsymbol(o); + Object *tmo = (Object *)tm->tiargs->data[i]; + if (ta) + { + Type *tmta = isType(tmo); + if (!tmta) + goto Lcontinue; + if (!ta->equals(tmta)) + goto Lcontinue; + } + else if (ea) + { Expression *tme = isExpression(tmo); + if (!tme || !ea->equals(tme)) + goto Lcontinue; + } + else if (sa) { - if (!sc->insert(s)) - error("%s is multiply defined", s->toChars()); + Dsymbol *tmsa = isDsymbol(tmo); + if (sa != tmsa) + goto Lcontinue; } else - s->addMember((ScopeDsymbol *)sc->parent); -#endif - //s->parent = parent; + assert(0); } + error("recursive mixin instantiation"); + return; + + Lcontinue: + continue; } -// if (isAnonymous()) + // Copy the syntax trees from the TemplateDeclaration + members = Dsymbol::arraySyntaxCopy(tempdecl->members); + if (!members) + return; + + symtab = new DsymbolTable(); + { ScopeDsymbol *sds = (ScopeDsymbol *)sc->scopesym; - sds->importScope(this, PROTpublic); } @@ -2196,11 +2241,9 @@ printf("\tcreate scope for template parameters '%s'\n", toChars()); #endif Scope *scx = sc; -// if (!isAnonymous()) - { - scx = sc->push(this); - scx->parent = this; - } + scx = sc->push(this); + scx->parent = this; + argsym = new ScopeDsymbol(); argsym->parent = scx->parent; Scope *scope = scx->push(argsym); @@ -2208,6 +2251,17 @@ // Declare each template parameter as an alias for the argument type declareParameters(scope); + // Add members to enclosing scope, as well as this scope + for (unsigned i = 0; i < members->dim; i++) + { Dsymbol *s; + + s = (Dsymbol *)members->data[i]; + s->addMember(scope, this); + //sc->insert(s); + //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); + //printf("s->parent = %s\n", s->parent->toChars()); + } + // Do semantic() analysis on template instance members #if LOG printf("\tdo semantic() on template instance members '%s'\n", toChars()); diff -uNr gdc-0.11/d/dmd/template.h gdc-0.12/d/dmd/template.h --- gdc-0.11/d/dmd/template.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/dmd/template.h 2005-05-25 03:51:33.000000000 +0200 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + #ifndef DMD_TEMPLATE_H #define DMD_TEMPLATE_H @@ -180,6 +186,12 @@ // sole member int semanticdone; // has semantic() been done? int nest; // for recursion detection +#ifdef IN_GCC + /* On some targets, it is necessary to know whether a symbol + will be emitted in the output or not before the symbol + is used. We can't rely on ti->getModule(). */ + Module * objFileModule; +#endif TemplateInstance(Loc loc, Identifier *temp_id); Dsymbol *syntaxCopy(Dsymbol *); diff -uNr gdc-0.11/d/dmd/tocsym.c gdc-0.12/d/dmd/tocsym.c --- gdc-0.11/d/dmd/tocsym.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/tocsym.c 2005-05-21 19:29:57.000000000 +0200 @@ -45,11 +45,12 @@ /********************************* SymbolDeclaration ****************************/ -SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s) +SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym) : Declaration(new Identifier(s->Sident, TOKidentifier)) { this->loc = loc; sym = s; + this->dsym = dsym; storage_class |= STCconst; } @@ -80,7 +81,7 @@ Symbol *Dsymbol::toSymbol() { - printf("Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind()); + fprintf(stderr, "Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind()); assert(0); // BUG: implement return NULL; } @@ -216,7 +217,7 @@ break; default: - printf("linkage = %d\n", linkage); + fprintf(stderr, "linkage = %d\n", linkage); assert(0); } type_setmangle(&t, m); @@ -317,7 +318,7 @@ break; default: - printf("linkage = %d\n", linkage); + fprintf(stderr, "linkage = %d\n", linkage); assert(0); } } diff -uNr gdc-0.11/d/dmd/todt.c gdc-0.12/d/dmd/todt.c --- gdc-0.11/d/dmd/todt.c 2005-04-17 14:44:07.000000000 +0200 +++ gdc-0.12/d/dmd/todt.c 2005-05-21 19:29:57.000000000 +0200 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2002 by Digital Mars +// Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -188,8 +188,9 @@ idx = (Expression *)index.data[i]; if (idx) length = idx->toInteger(); - //printf("index[%d] = %p, length = %d\n", i, idx, length); + //printf("index[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); + assert(length < dim); val = (Initializer *)value.data[i]; dt = val->toDt(); if (dts.data[length]) @@ -198,6 +199,8 @@ length++; } + Expression *edefault = tb->next->defaultInit(); + d = NULL; pdtend = &d; for (i = 0; i < dim; i++) @@ -206,7 +209,7 @@ if (dt) pdtend = dtcat(pdtend, dt); else - pdtend = tn->toDt(pdtend); + pdtend = edefault->toDt(pdtend); } switch (tb->ty) { @@ -216,7 +219,16 @@ tadim = ta->dim->toInteger(); if (dim < tadim) - pdtend = dtnzeros(pdtend, size * (tadim - dim)); // pad out end of array + { + if (edefault->isBool(FALSE)) + // pad out end of array + pdtend = dtnzeros(pdtend, size * (tadim - dim)); + else + { + for (i = dim; i < tadim; i++) + pdtend = edefault->toDt(pdtend); + } + } else if (dim > tadim) error("too many initializers %d for array[%d]", dim, tadim); break; @@ -367,7 +379,9 @@ dt_t **Expression::toDt(dt_t **pdt) { - //printf("Expression::toDt() %d\n", op); +#ifdef DEBUG + printf("Expression::toDt() %d\n", op); +#endif error("non-constant expression %s", toChars()); pdt = dtnzeros(pdt, 1); return pdt; @@ -412,7 +426,7 @@ break; default: - printf("%s\n", toChars()); + fprintf(stderr, "%s\n", toChars()); type->print(); assert(0); break; @@ -540,7 +554,7 @@ break; default: - printf("StringExp::toDt(type = %s)\n", type->toChars()); + fprintf(stderr, "StringExp::toDt(type = %s)\n", type->toChars()); assert(0); } return pdt; @@ -553,7 +567,11 @@ //printf("SymOffExp::toDt('%s')\n", var->toChars()); assert(var); if (!(var->isDataseg() || var->isCodeseg()) || var->needThis()) - { error("non-constant expression %s", toChars()); + { +#ifdef DEBUG + printf("SymOffExp::toDt()\n"); +#endif + error("non-constant expression %s", toChars()); return pdt; } s = var->toSymbol(); @@ -563,15 +581,24 @@ dt_t **VarExp::toDt(dt_t **pdt) { //printf("VarExp::toDt() %d\n", op); + for (; *pdt; pdt = &((*pdt)->DTnext)) + ; + VarDeclaration *v = var->isVarDeclaration(); if (v && v->isConst() && type->toBasetype()->ty != Tsarray && v->init) - { dt_t **pdtend; - - for (pdtend = pdt; *pdtend; pdtend = &((*pdtend)->DTnext)) - ; - *pdtend = v->init->toDt(); + { + *pdt = v->init->toDt(); return pdt; } + SymbolDeclaration *sd = var->isSymbolDeclaration(); + if (sd && sd->dsym) + { + sd->dsym->toDt(pdt); + return pdt; + } +#ifdef DEBUG + printf("VarExp::toDt(), kind = %s\n", var->kind()); +#endif error("non-constant expression %s", toChars()); pdt = dtnzeros(pdt, 1); return pdt; @@ -623,7 +650,7 @@ VarDeclaration *v = (VarDeclaration *)fields.data[i]; Initializer *init; - //printf("\t\tv->offset = %d, offset = %d\n", v->offset, offset); + //printf("\t\tv = '%s' v->offset = %2d, offset = %2d\n", v->toChars(), v->offset, offset); dt = NULL; init = v->init; if (init) @@ -631,7 +658,9 @@ dt = init->toDt(); } else if (v->offset >= offset) + { //printf("\t\tdefault initializer\n"); v->type->toDt(&dt); + } if (dt) { if (v->offset < offset) @@ -737,17 +766,28 @@ int i; unsigned len; + //printf("TypeSArray::toDt()\n"); len = dim->toInteger(); if (len) { while (*pdt) pdt = &((*pdt)->DTnext); - if (next->toBasetype()->ty == Tbit) + Type *tnext = next; + Type *tbn = tnext->toBasetype(); + while (tbn->ty == Tsarray) + { TypeSArray *tsa = (TypeSArray *)tbn; + + len *= tsa->dim->toInteger(); + tnext = tbn->next; + tbn = tnext->toBasetype(); + } + Expression *e = tnext->defaultInit(); + if (tbn->ty == Tbit) { Bits databits; databits.resize(len); - if (next->defaultInit()->toInteger()) + if (e->toInteger()) databits.set(); #ifdef IN_GCC pdt = dtnbits(pdt, databits.allocdim * sizeof(databits.data[0]), @@ -759,16 +799,30 @@ } else { - next->toDt(pdt); + if (tbn->ty == Tstruct) + tnext->toDt(pdt); + else + e->toDt(pdt); + dt_optimize(*pdt); if ((*pdt)->dt == DT_azeros && !(*pdt)->DTnext) { (*pdt)->DTazeros *= len; + pdt = &((*pdt)->DTnext); + } + else if ((*pdt)->dt == DT_1byte && (*pdt)->DTonebyte == 0 && !(*pdt)->DTnext) + { + (*pdt)->dt = DT_azeros; + (*pdt)->DTazeros = len; + pdt = &((*pdt)->DTnext); } else { for (i = 1; i < len; i++) { - pdt = next->toDt(pdt); + if (tbn->ty == Tstruct) + pdt = tnext->toDt(pdt); + else + pdt = e->toDt(pdt); } } } diff -uNr gdc-0.11/d/dmd/toobj.c gdc-0.12/d/dmd/toobj.c --- gdc-0.11/d/dmd/toobj.c 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/dmd/toobj.c 2005-05-19 02:15:50.000000000 +0200 @@ -53,6 +53,7 @@ void obj_lzext(Symbol *s1,Symbol *s2); #ifdef IN_GCC +#if 0 static bool m_in_a(Module * m, Array * a) { for (unsigned i = 0; i < a->dim; i++) if ( m == (Module *) a->data[i] ) @@ -69,10 +70,18 @@ Module * a_module = (Module *) work.data[wi]; for (unsigned i = 0; i < a_module->aimports.dim; i++) { Module * an_imp = (Module*) a_module->aimports.data[i]; - if (m_in_a(an_imp, & work) || m_in_a(an_imp, out_deps)) + if (! an_imp->needModuleInfo() || + m_in_a(an_imp, & work) || m_in_a(an_imp, out_deps)) continue; if (an_imp->strictlyneedmoduleinfo) + { out_deps->push(an_imp); + fprintf(stderr, "idep: %s -> %s", the_module->toPrettyChars(), + an_imp->toPrettyChars()); + if (a_module != the_module) + fprintf(stderr, " (via %s)", a_module->toPrettyChars()); + fprintf(stderr, "\n"); + } else work.push(an_imp); } @@ -80,6 +89,7 @@ } } #endif +#endif /* ================================================================== */ @@ -139,17 +149,23 @@ // importedModules[] int aimports_dim = aimports.dim; -#ifndef IN_GCC +#ifdef IN_GCC +#if 0 + Array adeps; + + if (! d_gcc_supports_weak()) + { + find_module_deps(this, & adeps); + aimports_dim = adeps.dim; + } + else +#endif +#endif for (i = 0; i < aimports.dim; i++) { Module *m = (Module *)aimports.data[i]; if (!m->needModuleInfo()) aimports_dim--; } -#else - Array adeps; - find_module_deps(this, & adeps); - aimports_dim = adeps.dim; -#endif dtdword(&dt, aimports_dim); if (aimports.dim) dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr); @@ -182,7 +198,22 @@ ////////////////////////////////////////////// -#ifndef IN_GCC +#ifdef IN_GCC +#if 0 + if (! d_gcc_supports_weak()) + for (i = 0; i < adeps.dim; i++) + { + Module *m; + Symbol *s; + + m = (Module *) adeps.data[i]; + s = m->toSymbol(); + s->Sflags |= SFLweak; // doesn't do anything yet, but see d-decls.cc:Module::toSymbol + dtxoff(&dt, s, 0, TYnptr); + } + else +#endif +#endif for (i = 0; i < aimports.dim; i++) { Module *m; @@ -194,18 +225,6 @@ dtxoff(&dt, s, 0, TYnptr); } } -#else - for (i = 0; i < adeps.dim; i++) - { - Module *m; - Symbol *s; - - m = (Module *) adeps.data[i]; - s = m->toSymbol(); - s->Sflags |= SFLweak; // doesn't do anything yet, but see d-decls.cc:Module::toSymbol - dtxoff(&dt, s, 0, TYnptr); - } -#endif for (i = 0; i < aclasses.dim; i++) { @@ -656,7 +675,10 @@ //printf("InterfaceDeclaration::toObjFile('%s')\n", toChars()); - if (members && global.params.symdebug) + if (!members) + return; + + if (global.params.symdebug) toDebug(); if (parent && parent->isTemplateInstance()) diff -uNr gdc-0.11/d/dmd/total.h gdc-0.12/d/dmd/total.h --- gdc-0.11/d/dmd/total.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/dmd/total.h 2005-05-21 19:29:57.000000000 +0200 @@ -37,7 +37,7 @@ #include "import.h" #include "module.h" #include "id.h" -#include "debcond.h" +#include "cond.h" #include "version.h" #endif /* DMD_TOTAL_H */ diff -uNr gdc-0.11/d/dmd/version.c gdc-0.12/d/dmd/version.c --- gdc-0.11/d/dmd/version.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/version.c 2005-05-21 19:29:57.000000000 +0200 @@ -13,32 +13,39 @@ #include "identifier.h" #include "dsymbol.h" -#include "debcond.h" +#include "cond.h" #include "version.h" #include "module.h" /* ================================================== */ -DebugSymbol::DebugSymbol(Identifier *ident) +/* DebugSymbol's happen for statements like: + * debug = identifier; + * debug = integer; + */ + +DebugSymbol::DebugSymbol(Loc loc, Identifier *ident) : Dsymbol(ident) { + this->loc = loc; } -DebugSymbol::DebugSymbol(unsigned level) +DebugSymbol::DebugSymbol(Loc loc, unsigned level) : Dsymbol() { this->level = level; + this->loc = loc; } Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s) { assert(!s); - DebugSymbol *ds = new DebugSymbol(ident); + DebugSymbol *ds = new DebugSymbol(loc, ident); ds->level = level; return ds; } -void DebugSymbol::addMember(ScopeDsymbol *sd) +void DebugSymbol::addMember(Scope *sc, ScopeDsymbol *sd) { //printf("DebugSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); Module *m; @@ -89,26 +96,33 @@ /* ================================================== */ -VersionSymbol::VersionSymbol(Identifier *ident) +/* VersionSymbol's happen for statements like: + * version = identifier; + * version = integer; + */ + +VersionSymbol::VersionSymbol(Loc loc, Identifier *ident) : Dsymbol(ident) { + this->loc = loc; } -VersionSymbol::VersionSymbol(unsigned level) +VersionSymbol::VersionSymbol(Loc loc, unsigned level) : Dsymbol() { this->level = level; + this->loc = loc; } Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s) { assert(!s); - VersionSymbol *ds = new VersionSymbol(ident); + VersionSymbol *ds = new VersionSymbol(loc, ident); ds->level = level; return ds; } -void VersionSymbol::addMember(ScopeDsymbol *sd) +void VersionSymbol::addMember(Scope *sc, ScopeDsymbol *sd) { //printf("VersionSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); Module *m; @@ -118,7 +132,7 @@ m = sd->isModule(); if (ident) { - VersionCondition::checkPredefined(ident->toChars()); + VersionCondition::checkPredefined(loc, ident->toChars()); if (!m) error("declaration must be at module level"); else diff -uNr gdc-0.11/d/dmd/version.h gdc-0.12/d/dmd/version.h --- gdc-0.11/d/dmd/version.h 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/dmd/version.h 2005-05-21 19:29:57.000000000 +0200 @@ -22,11 +22,11 @@ { unsigned level; - DebugSymbol(Identifier *ident); - DebugSymbol(unsigned level); + DebugSymbol(Loc loc, Identifier *ident); + DebugSymbol(Loc loc, unsigned level); Dsymbol *syntaxCopy(Dsymbol *); - void addMember(ScopeDsymbol *s); + void addMember(Scope *sc, ScopeDsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf); char *kind(); @@ -36,11 +36,11 @@ { unsigned level; - VersionSymbol(Identifier *ident); - VersionSymbol(unsigned level); + VersionSymbol(Loc loc, Identifier *ident); + VersionSymbol(Loc loc, unsigned level); Dsymbol *syntaxCopy(Dsymbol *); - void addMember(ScopeDsymbol *s); + void addMember(Scope *sc, ScopeDsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf); char *kind(); diff -uNr gdc-0.11/d/dmd-script gdc-0.12/d/dmd-script --- gdc-0.11/d/dmd-script 2005-04-26 03:45:07.000000000 +0200 +++ gdc-0.12/d/dmd-script 2005-05-29 00:00:56.000000000 +0200 @@ -18,13 +18,14 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # This is a wrapper script for gdc that emulates the dmd command. -# Unknown options are passed on to gdc. The two extra options are: +# -f and -m options are passed to gdc. Extra options are: # # -vdmd Print commands executed by this wrapper script -# -q[,,,...] Pass the comma-separated arguments to gdc +# -q,[,,,...] Pass the comma-separated arguments to gdc use strict; +use Cwd qw(abs_path); use File::Basename; use File::Spec; @@ -42,6 +43,11 @@ my @out; my @link_out; +# Use the gdc executable in the same directory as this script and account +# for the target prefix. +basename($0) =~ m/^(.*-)?g?dmd$/; +my $gdc = File::Spec->catfile( abs_path(dirname($0)), ($1?$1:"") . "gdc" ); + sub osHasEXE() { return $^O =~ m/MS(DOS|Win32)|os2/i; # taken from File::Basename } @@ -84,6 +90,8 @@ } elsif ( $arg =~ m/^-debug.*$/ ) { # Passing this to gdc only gives warnings; exit with an error here errorExit "unrecognized switch '$arg'"; + } elsif ( $arg =~ m/^-g$/ ) { + push @out, '-g'; } elsif ( $arg =~ m/^-gt$/ ) { errorExit "use -profile instead of -gt"; push @out, '-pg'; @@ -123,13 +131,21 @@ $show_commands = 1; } elsif ( $arg =~ m/^-w$/ ) { push @out, "-Wall"; - } elsif ( $arg =~ m/^-q(.*)$/ ) { + } elsif ( $arg =~ m/^-quiet$/ ) { + # ignored + } elsif ( $arg =~ m/^-q,(.*)$/ ) { push @out, split(qr/,/, $1); } elsif ( $arg eq '-fall-sources' ) { $seen_all_sources_flag = 1; # push @out, $arg; - } elsif ( $arg =~ m/^-.+$/ ) { + } elsif ( $arg =~ m/^-f.+/ ) { + # Pass -fxxx options push @out, $arg; + } elsif ( $arg =~ m/^-m.+/ ) { + # Pass -mxxx options + push @out, $arg; + } elsif ( $arg =~ m/^-.+$/ ) { + errorExit "unrecognized switch '$arg'"; } elsif ( $arg =~ m/^.+\.d$/i || $arg =~ m/^.+\.htm$/i || $arg =~ m/^.+\.html$/i) { @@ -165,7 +181,44 @@ } if (! scalar(@sources) && ! ($link && scalar(@objects))) { - errorExit "no input files"; + my @cmd = ('gdc', '--version', @out); + my $result = system(@cmd); + errorExit if $result & 0xff; # Give up if can't exec or gdc exited with a signal + print <= level + -version=ident compile in version code identified by ident + -w enable warnings +EOF +; + exit 1; } my $ok = 1; diff -uNr gdc-0.11/d/d-spec.c gdc-0.12/d/d-spec.c --- gdc-0.11/d/d-spec.c 2005-04-12 05:16:27.000000000 +0200 +++ gdc-0.12/d/d-spec.c 2005-05-08 16:01:26.000000000 +0200 @@ -53,10 +53,10 @@ #endif #ifndef LIBPHOBOS -#define LIBPHOBOS "-lphobos" +#define LIBPHOBOS "-lgphobos" #endif #ifndef LIBPHOBOS_PROFILE -#define LIBPHOBOS_PROFILE "-lphobos" +#define LIBPHOBOS_PROFILE "-lgphobos" #endif /* #ifndef THREAD_LIBRARY @@ -414,7 +414,7 @@ arglist[j++] = THREAD_LIBRARY; added_libraries++; */ - arglist[j++] = "-specs=libphobos.spec"; + arglist[j++] = "-specs=libgphobos.spec"; } if (saw_math) arglist[j++] = saw_math; diff -uNr gdc-0.11/d/dt.h gdc-0.12/d/dt.h --- gdc-0.11/d/dt.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/dt.h 2005-05-19 02:15:50.000000000 +0200 @@ -29,6 +29,7 @@ DT_abytes, DT_word, DT_xoff, + DT_1byte, DT_tree }; @@ -38,6 +39,7 @@ union { integer_t DTint; integer_t DTazeros; + integer_t DTonebyte; }; union { Symbol * DTsym; diff -uNr gdc-0.11/d/gcc-mars.cc gdc-0.12/d/gcc-mars.cc --- gdc-0.11/d/gcc-mars.cc 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/gcc-mars.cc 2005-05-25 03:51:33.000000000 +0200 @@ -32,7 +32,7 @@ copyright = "Copyright (c) 1999-2005 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.102"; + version = "v0.125"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -68,16 +68,16 @@ char *p = loc.toChars(); if (*p) - printf("%s: ", p); + fprintf(stderr, "%s: ", p); mem.free(p); va_list ap; va_start(ap, format); - printf("Error: "); - vprintf(format, ap); + fprintf(stderr, "Error: "); + vfprintf(stderr, format, ap); va_end( ap ); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); global.errors++; } diff -uNr gdc-0.11/d/gdc_alloca.h gdc-0.12/d/gdc_alloca.h --- gdc-0.11/d/gdc_alloca.h 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.12/d/gdc_alloca.h 2005-05-08 16:01:26.000000000 +0200 @@ -0,0 +1,13 @@ +/* This should be autoconf'd, but I want to avoid + patching the configure script. */ +#include +#ifndef alloca +# if _WIN32 +# include +# elif __sun__ +# include +# else +/* guess... */ +# include +# endif +#endif diff -uNr gdc-0.11/d/gdc-version gdc-0.12/d/gdc-version --- gdc-0.11/d/gdc-version 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.12/d/gdc-version 2005-05-25 03:51:33.000000000 +0200 @@ -0,0 +1 @@ +gdc 0.12, using dmd 0.125 \ No newline at end of file diff -uNr gdc-0.11/d/lang.opt gdc-0.12/d/lang.opt --- gdc-0.11/d/lang.opt 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/lang.opt 2005-05-25 03:51:33.000000000 +0200 @@ -54,7 +54,7 @@ femit-templates= D Joined RejectNegative --femit-templates=[full|private|none|auto] Control template emission foo! +-femit-templates=[normal|private|all|none|auto] Control template emission femit-templates D diff -uNr gdc-0.11/d/Make-lang.in gdc-0.12/d/Make-lang.in --- gdc-0.11/d/Make-lang.in 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/Make-lang.in 2005-05-27 03:05:04.000000000 +0200 @@ -33,8 +33,10 @@ D_INSTALL_NAME = $(shell echo $(D_DRIVER_NAME)|sed '$(program_transform_name)') DMD_INSTALL_NAME = $(shell echo dmd|sed '$(program_transform_name)') +GDMD_INSTALL_NAME = $(shell echo gdmd|sed '$(program_transform_name)') D_TARGET_INSTALL_NAME = $(target_alias)-$(shell echo $(D_DRIVER_NAME)|sed '$(program_transform_name)') DMD_TARGET_INSTALL_NAME = $(target_alias)-$(shell echo dmd|sed '$(program_transform_name)') +GDMD_TARGET_INSTALL_NAME = $(target_alias)-$(shell echo gdmd|sed '$(program_transform_name)') # configurate? gcc_d_include_dir = $(libsubdir)/$(unlibsubdir)/..`echo $(exec_prefix) | sed -e 's|^$(prefix)||' -e 's|/[^/]*|/..|g'`/include/d/$(gcc_version) @@ -64,6 +66,7 @@ # Note: this gcc 3.3.x style installation is not actually supported D_CROSS_NAME = `echo $(D_DRIVER_NAME)|sed '$(program_transform_cross_name)'` DMD_CROSS_NAME = `echo dmd|sed '$(program_transform_cross_name)'` + GDMD_CROSS_NAME = `echo gdmd|sed '$(program_transform_cross_name)'` else D_EXTRA_DEFINES += -DD_PHOBOS_TARGET_DIR=\"$(gcc_d_include_dir)/$(target_noncanonical)\" ifeq ($(D_silly_ver),3.4) @@ -76,11 +79,17 @@ # Actual names to use when installing a cross-compiler. D_CROSS_NAME = $(D_INSTALL_NAME) DMD_CROSS_NAME = $(DMD_INSTALL_NAME) + GDMD_CROSS_NAME = $(GDMD_INSTALL_NAME) endif ifeq ($(gcc_version),3.3-fast) D_EXTRA_DEFINES += -DD_GCC_VER330=1 endif +ifeq ($(gcc_version),3.4.1) +# need for Cygwin which does not have 3.4.x, x>1 yet... +D_EXTRA_DEFINES += -DD_GCC_VER341=1 +endif + D d: $(D_COMPILER_NAME)$(exeext) # Tell GNU make to ignore these if they exist. @@ -117,7 +126,7 @@ cp $(D_DRIVER_NAME)$(exeext) $(D_DRIVER_NAME)-cross$(exeext) D_DMD_OBJS = \ - d/access.dmd.o d/array.dmd.o d/attrib.dmd.o d/cast.dmd.o d/class.dmd.o d/constfold.dmd.o d/dchar.dmd.o d/debcond.dmd.o d/declaration.dmd.o \ + d/access.dmd.o d/array.dmd.o d/attrib.dmd.o d/cast.dmd.o d/class.dmd.o d/cond.dmd.o d/constfold.dmd.o d/dchar.dmd.o d/declaration.dmd.o \ d/dsymbol.dmd.o d/dump.dmd.o d/entity.dmd.o d/enum.dmd.o d/expression.dmd.o d/func.dmd.o d/gnuc.dmd.o d/html.dmd.o d/identifier.dmd.o d/import.dmd.o \ d/init.dmd.o d/inline.dmd.o d/lexer.dmd.o d/lstring.dmd.o d/mangle.dmd.o d/mem.dmd.o d/mtype.dmd.o d/module.dmd.o d/opover.dmd.o d/optimize.dmd.o d/parse.dmd.o \ d/root.dmd.o d/scope.dmd.o d/statement.dmd.o d/staticassert.dmd.o d/stringtable.dmd.o d/struct.dmd.o d/template.dmd.o \ @@ -240,39 +249,40 @@ d.install-normal: d.install-common: installdirs -rm -f $(DESTDIR)$(bindir)/$(D_INSTALL_NAME)$(exeext) - -rm -f $(DESTDIR)$(bindir)/$(DMD_INSTALL_NAME) + -rm -f $(DESTDIR)$(bindir)/$(GDMD_INSTALL_NAME) $(INSTALL_PROGRAM) $(D_DRIVER_NAME)$(exeext) $(DESTDIR)$(bindir)/$(D_INSTALL_NAME)$(exeext) - -perl -e 'exit 0;' && $(INSTALL_PROGRAM) $(srcdir)/d/dmd-script $(DESTDIR)$(bindir)/$(DMD_INSTALL_NAME) + -perl -e 'exit 0;' && $(INSTALL_PROGRAM) $(srcdir)/d/dmd-script $(DESTDIR)$(bindir)/$(GDMD_INSTALL_NAME) -chmod a+x $(DESTDIR)$(bindir)/$(D_INSTALL_NAME)$(exeext) - -chmod a+x $(DESTDIR)$(bindir)/$(DMD_INSTALL_NAME) + -chmod a+x $(DESTDIR)$(bindir)/$(GDMD_INSTALL_NAME) + -$(LN) -if [ -f $(D_COMPILER_NAME)$(exeext) ] ; then \ if [ -f $(D_DRIVER_NAME)-cross$(exeext) ] ; then \ if [ -d $(DESTDIR)$(gcc_tooldir)/bin/. ] ; then \ rm -f $(DESTDIR)$(gcc_tooldir)/bin/$(D_DRIVER_NAME)$(exeext); \ - rm -f $(DESTDIR)$(gcc_tooldir)/bin/dmd$(exeext); \ + rm -f $(DESTDIR)$(gcc_tooldir)/bin/gdmd$(exeext); \ $(INSTALL_PROGRAM) $(D_DRIVER_NAME)-cross$(exeext) $(DESTDIR)$(gcc_tooldir)/bin/$(D_DRIVER_NAME)$(exeext); \ - perl -e 'exit 0;' && $(INSTALL_PROGRAM) $(srcdir)/d/dmd-script $(DESTDIR)$(gcc_tooldir)/bin/dmd; \ + perl -e 'exit 0;' && $(INSTALL_PROGRAM) $(srcdir)/d/dmd-script $(DESTDIR)$(gcc_tooldir)/bin/gdmd; \ else true; fi; \ else \ rm -f $(DESTDIR)$(bindir)/$(D_TARGET_INSTALL_NAME)$(exeext); \ - rm -f $(DESTDIR)$(bindir)/$(DMD_TARGET_INSTALL_NAME); \ + rm -f $(DESTDIR)$(bindir)/$(GDMD_TARGET_INSTALL_NAME); \ ( cd $(DESTDIR)$(bindir) && \ $(LN) $(D_INSTALL_NAME)$(exeext) $(D_TARGET_INSTALL_NAME)$(exeext) ); \ ( cd $(DESTDIR)$(bindir) && \ - $(LN) $(DMD_INSTALL_NAME)$(exeext) $(DMD_TARGET_INSTALL_NAME) ); \ + $(LN) $(GDMD_INSTALL_NAME)$(exeext) $(GDMD_TARGET_INSTALL_NAME)$(exeext) ); \ fi ; \ fi d.install-info: -d.install-man: installdirs $(DESTDIR)$(man1dir)/$(D_INSTALL_NAME)$(man1ext) $(DESTDIR)$(man1dir)/$(DMD_INSTALL_NAME)$(man1ext) +d.install-man: installdirs $(DESTDIR)$(man1dir)/$(D_INSTALL_NAME)$(man1ext) $(DESTDIR)$(man1dir)/$(GDMD_INSTALL_NAME)$(man1ext) $(DESTDIR)$(man1dir)/$(D_INSTALL_NAME)$(man1ext): $(srcdir)/d/gdc.1 -rm -f $@ -$(INSTALL_DATA) $< $@ -chmod a-x $@ -$(DESTDIR)$(man1dir)/$(DMD_INSTALL_NAME)$(man1ext): $(srcdir)/d/dmd-script.1 +$(DESTDIR)$(man1dir)/$(GDMD_INSTALL_NAME)$(man1ext): $(srcdir)/d/dmd-script.1 -rm -f $@ -$(INSTALL_DATA) $< $@ -chmod a-x $@ diff -uNr gdc-0.11/d/patch-gcc-3.3.x gdc-0.12/d/patch-gcc-3.3.x --- gdc-0.11/d/patch-gcc-3.3.x 2005-02-21 02:40:45.000000000 +0100 +++ gdc-0.12/d/patch-gcc-3.3.x 2005-05-21 22:34:31.000000000 +0200 @@ -59,3 +59,46 @@ enum machine_mode rttype; addr_diff_vec_flags rt_addr_diff_vec_flags; struct cselib_val_struct *rt_cselib; +*** gcc-orig/config/rs6000/rs6000.c Wed Jan 14 09:03:58 2004 +--- gcc/config/rs6000/rs6000.c Sat May 21 16:06:49 2005 +*************** +*** 387,396 **** + + /* ??? Should work everywhere, but ask dje@watson.ibm.com before + enabling for AIX. */ +! #if TARGET_OBJECT_FORMAT != OBJECT_XCOFF + #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK + #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall +! #endif + + struct gcc_target targetm = TARGET_INITIALIZER; + +--- 387,396 ---- + + /* ??? Should work everywhere, but ask dje@watson.ibm.com before + enabling for AIX. */ +! /*#if TARGET_OBJECT_FORMAT != OBJECT_XCOFF*//*enabled for gdc*/ + #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK + #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall +! /*#endif*/ + + struct gcc_target targetm = TARGET_INITIALIZER; + +*************** +*** 11193,11199 **** + although IBM appears to be using 13. There is no official value + for Chill, so we've chosen 44 pseudo-randomly. */ + if (! strcmp (language_string, "GNU C") +! || ! strcmp (language_string, "GNU Objective-C")) + i = 0; + else if (! strcmp (language_string, "GNU F77")) + i = 1; +--- 11193,11200 ---- + although IBM appears to be using 13. There is no official value + for Chill, so we've chosen 44 pseudo-randomly. */ + if (! strcmp (language_string, "GNU C") +! || ! strcmp (language_string, "GNU Objective-C") +! || ! strcmp (language_string, "GNU D")) + i = 0; + else if (! strcmp (language_string, "GNU F77")) + i = 1; diff -uNr gdc-0.11/d/patch-gcc-3.4.x gdc-0.12/d/patch-gcc-3.4.x --- gdc-0.11/d/patch-gcc-3.4.x 2005-02-21 02:40:45.000000000 +0100 +++ gdc-0.12/d/patch-gcc-3.4.x 2005-05-21 22:34:31.000000000 +0200 @@ -60,3 +60,45 @@ enum machine_mode rttype; addr_diff_vec_flags rt_addr_diff_vec_flags; struct cselib_val_struct *rt_cselib; +*** gcc-orig/libgcc2.c Sun Sep 26 16:47:14 2004 +--- gcc/libgcc2.c Sat May 7 11:47:55 2005 +*************** +*** 29,34 **** +--- 29,45 ---- + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + ++ #ifdef L_eprintf ++ #ifdef __APPLE__ ++ /* Hack for MacOS 10.4: gcc 3.4.x uses -mlong-double-128 to build ++ libgcc. On 10.4, this causes *printf to be defined as ++ *printf$LDBLStub and requires linking with libSystemStubs. Prevent ++ this from happening by making it seem as though double is the same ++ as long double. */ ++ #undef __LDBL_MANT_DIG__ ++ #define __LDBL_MANT_DIG__ __DBL_MANT_DIG__ ++ #endif ++ #endif + + /* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is + supposedly valid even though this is a "target" file. */ +*** gcc-orig/config/rs6000/rs6000.c Fri Oct 22 15:19:35 2004 +--- gcc/config/rs6000/rs6000.c Sat May 21 16:08:37 2005 +*************** +*** 12973,12979 **** + use language_string. + C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9. + Java is 13. Objective-C is 14. */ +! if (! strcmp (language_string, "GNU C")) + i = 0; + else if (! strcmp (language_string, "GNU F77")) + i = 1; +--- 12973,12980 ---- + use language_string. + C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9. + Java is 13. Objective-C is 14. */ +! if (! strcmp (language_string, "GNU C") || +! ! strcmp (language_string, "GNU D")) + i = 0; + else if (! strcmp (language_string, "GNU F77")) + i = 1; diff -uNr gdc-0.11/d/patch-gcc-darwin-eh-3.3.x gdc-0.12/d/patch-gcc-darwin-eh-3.3.x --- gdc-0.11/d/patch-gcc-darwin-eh-3.3.x 2005-04-10 18:24:35.000000000 +0200 +++ gdc-0.12/d/patch-gcc-darwin-eh-3.3.x 2005-05-08 16:01:26.000000000 +0200 @@ -17,22 +17,19 @@ \ static void \ objc_section_init () \ -*** gcc/dwarf2out.c.orig Sun Feb 20 16:41:20 2005 ---- gcc/dwarf2out.c Sun Feb 20 19:24:38 2005 +*** gcc-orig/dwarf2out.c Sun Feb 20 16:41:20 2005 +--- gcc/dwarf2out.c Sat May 7 21:29:14 2005 *************** *** 348,354 **** +--- 348,358 ---- #define FUNC_END_LABEL "LFE" #endif -! #define FRAME_BEGIN_LABEL "Lframe" - #define CIE_AFTER_SIZE_LABEL "LSCIE" - #define CIE_END_LABEL "LECIE" - #define FDE_LABEL "LSFDE" ---- 348,354 ---- - #define FUNC_END_LABEL "LFE" - #endif - -! #define FRAME_BEGIN_LABEL "EH_frame"/*df*/ ++ #ifdef DARWIN_REGISTER_TARGET_PRAGMAS ++ #define FRAME_BEGIN_LABEL "EH_frame" ++ #else + #define FRAME_BEGIN_LABEL "Lframe" ++ #endif #define CIE_AFTER_SIZE_LABEL "LSCIE" #define CIE_END_LABEL "LECIE" #define FDE_LABEL "LSFDE" diff -uNr gdc-0.11/d/patch-gcc-darwin-eh-3.4.x gdc-0.12/d/patch-gcc-darwin-eh-3.4.x --- gdc-0.11/d/patch-gcc-darwin-eh-3.4.x 2005-04-10 20:15:52.000000000 +0200 +++ gdc-0.12/d/patch-gcc-darwin-eh-3.4.x 2005-05-08 16:01:26.000000000 +0200 @@ -18,21 +18,18 @@ static void \ objc_section_init (void) \ *** gcc-orig/dwarf2out.c Mon Oct 25 17:46:45 2004 ---- gcc/dwarf2out.c Wed Jan 19 18:02:06 2005 +--- gcc/dwarf2out.c Sat May 7 21:19:29 2005 *************** *** 390,396 **** +--- 390,400 ---- #define FUNC_END_LABEL "LFE" #endif -! #define FRAME_BEGIN_LABEL "Lframe" - #define CIE_AFTER_SIZE_LABEL "LSCIE" - #define CIE_END_LABEL "LECIE" - #define FDE_LABEL "LSFDE" ---- 390,396 ---- - #define FUNC_END_LABEL "LFE" - #endif - -! #define FRAME_BEGIN_LABEL "EH_frame"/*df*/ ++ #ifdef DARWIN_REGISTER_TARGET_PRAGMAS ++ #define FRAME_BEGIN_LABEL "EH_frame" ++ #else + #define FRAME_BEGIN_LABEL "Lframe" ++ #endif #define CIE_AFTER_SIZE_LABEL "LSCIE" #define CIE_END_LABEL "LECIE" #define FDE_LABEL "LSFDE" diff -uNr gdc-0.11/d/phobos/acinclude.m4 gdc-0.12/d/phobos/acinclude.m4 --- gdc-0.11/d/phobos/acinclude.m4 2005-04-12 05:16:27.000000000 +0200 +++ gdc-0.12/d/phobos/acinclude.m4 2005-05-21 02:41:57.000000000 +0200 @@ -82,37 +82,63 @@ AC_MSG_ERROR([Can not handle layout of sockaddr. Please report this so your system can be supported.])]) fi -AC_CHECK_HEADERS(semaphore.h) AC_SEARCH_LIBS(sem_init, pthread rt posix4) -AC_CHECK_FUNC(sem_init) -AC_CHECK_FUNC(semaphore_create) -if test -z "$d_sem_impl"; then - # Probably need to test what actually works because of sem_init issue on darwin.. - # For now, test for Mach semaphores first so it overrides Posix - if test "$ac_cv_func_semaphore_create" = "yes"; then - d_sem_impl="mach" - elif test "$ac_cv_func_sem_init" = "yes" && test "$ac_cv_header_semaphore_h" = "yes"; then - d_sem_impl="posix" +DCFG_PTHREAD_SUSPEND= +AC_SUBST(DCFG_PTHREAD_SUSPEND) + +if true; then + AC_CHECK_HEADERS(semaphore.h) + AC_CHECK_FUNC(sem_init) + AC_CHECK_FUNC(semaphore_create) + AC_CHECK_FUNC(pthread_cond_wait) + + if test -z "$d_sem_impl"; then + # Probably need to test what actually works. sem_init is defined + # on AIX and Darwin but does not actually work. + # For now, test for Mach semaphores first so it overrides Posix. AIX + # is a special case. + if test "$ac_cv_func_semaphore_create" = "yes"; then + d_sem_impl="mach" + elif test "$ac_cv_func_sem_init" = "yes" && \ + test "$ac_cv_header_semaphore_h" = "yes" && \ + test -z "$d_is_aix"; then + d_sem_impl="posix" + elif test "$ac_cv_func_pthread_cond_wait" = "yes"; then + d_sem_impl="pthreads" + fi fi -fi -dnl TODO: change this to using pthreads? if so, define usepthreads -dnl and configure semaphore + dnl TODO: change this to using pthreads? if so, define usepthreads + dnl and configure semaphore -case "$d_sem_impl" in - posix) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_POSIX" ;; - mach) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_Mach" - d_module_mach=1 ;; - *) AC_MSG_ERROR([No usable semaphore implementation]) ;; -esac + case "$d_sem_impl" in + posix) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_POSIX" ;; + mach) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_Mach" + d_module_mach=1 ;; + pthreads) DCFG_SEMAPHORE_IMPL="GNU_Sempahore_Pthreads" ;; + *) AC_MSG_ERROR([No usable semaphore implementation]) ;; + esac +else + dnl Need to be able to query thread state for this method to be useful + AC_CHECK_FUNC(pthread_suspend_np) + AC_CHECK_FUNC(pthread_continue_np) + + if test "$ac_cv_func_pthread_suspend_np" = "yes" && \ + test "$ac_cv_func_pthread_continue_np" = "yes" ; then + # TODO: need to test that these actually work. + DCFG_PTHREAD_SUSPEND=GNU_pthread_suspend + else + AC_MSG_ERROR([TODO]) + fi +fi AC_DEFINE(PHOBOS_USE_PTHREADS,1,[Define if using pthreads]) RECLS_CXXFLAGS="$RECLS_CXXFLAGS -Dunix" D_RECLS_OS=unix -D_EXTRA_OBJS="gcc/configunix.o gcc/cbridge_fdset.o $D_EXTRA_OBJS" +D_EXTRA_OBJS="gcc/configunix.o gcc/cbridge_fdset.o std/c/unix/unix.o $D_EXTRA_OBJS" DCFG_UNIX="Unix" ]) @@ -127,6 +153,8 @@ d_gc_data= case "$target_os" in + aix*) d_gc_data="$d_gc_data GC_Use_Data_Fixed" + ;; cygwin*) d_gc_data="$d_gc_data GC_Use_Data_Fixed" ;; darwin*) D_GC_MODULES="$D_GC_MODULES internal/gc/gc_dyld.o" diff -uNr gdc-0.11/d/phobos/aclocal.m4 gdc-0.12/d/phobos/aclocal.m4 --- gdc-0.11/d/phobos/aclocal.m4 2005-04-12 05:16:27.000000000 +0200 +++ gdc-0.12/d/phobos/aclocal.m4 2005-05-21 02:41:57.000000000 +0200 @@ -95,37 +95,63 @@ AC_MSG_ERROR([Can not handle layout of sockaddr. Please report this so your system can be supported.])]) fi -AC_CHECK_HEADERS(semaphore.h) AC_SEARCH_LIBS(sem_init, pthread rt posix4) -AC_CHECK_FUNC(sem_init) -AC_CHECK_FUNC(semaphore_create) -if test -z "$d_sem_impl"; then - # Probably need to test what actually works because of sem_init issue on darwin.. - # For now, test for Mach semaphores first so it overrides Posix - if test "$ac_cv_func_semaphore_create" = "yes"; then - d_sem_impl="mach" - elif test "$ac_cv_func_sem_init" = "yes" && test "$ac_cv_header_semaphore_h" = "yes"; then - d_sem_impl="posix" +DCFG_PTHREAD_SUSPEND= +AC_SUBST(DCFG_PTHREAD_SUSPEND) + +if true; then + AC_CHECK_HEADERS(semaphore.h) + AC_CHECK_FUNC(sem_init) + AC_CHECK_FUNC(semaphore_create) + AC_CHECK_FUNC(pthread_cond_wait) + + if test -z "$d_sem_impl"; then + # Probably need to test what actually works. sem_init is defined + # on AIX and Darwin but does not actually work. + # For now, test for Mach semaphores first so it overrides Posix. AIX + # is a special case. + if test "$ac_cv_func_semaphore_create" = "yes"; then + d_sem_impl="mach" + elif test "$ac_cv_func_sem_init" = "yes" && \ + test "$ac_cv_header_semaphore_h" = "yes" && \ + test -z "$d_is_aix"; then + d_sem_impl="posix" + elif test "$ac_cv_func_pthread_cond_wait" = "yes"; then + d_sem_impl="pthreads" + fi fi -fi -dnl TODO: change this to using pthreads? if so, define usepthreads -dnl and configure semaphore + dnl TODO: change this to using pthreads? if so, define usepthreads + dnl and configure semaphore -case "$d_sem_impl" in - posix) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_POSIX" ;; - mach) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_Mach" - d_module_mach=1 ;; - *) AC_MSG_ERROR([No usable semaphore implementation]) ;; -esac + case "$d_sem_impl" in + posix) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_POSIX" ;; + mach) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_Mach" + d_module_mach=1 ;; + pthreads) DCFG_SEMAPHORE_IMPL="GNU_Sempahore_Pthreads" ;; + *) AC_MSG_ERROR([No usable semaphore implementation]) ;; + esac +else + dnl Need to be able to query thread state for this method to be useful + AC_CHECK_FUNC(pthread_suspend_np) + AC_CHECK_FUNC(pthread_continue_np) + + if test "$ac_cv_func_pthread_suspend_np" = "yes" && \ + test "$ac_cv_func_pthread_continue_np" = "yes" ; then + # TODO: need to test that these actually work. + DCFG_PTHREAD_SUSPEND=GNU_pthread_suspend + else + AC_MSG_ERROR([TODO]) + fi +fi AC_DEFINE(PHOBOS_USE_PTHREADS,1,[Define if using pthreads]) RECLS_CXXFLAGS="$RECLS_CXXFLAGS -Dunix" D_RECLS_OS=unix -D_EXTRA_OBJS="gcc/configunix.o gcc/cbridge_fdset.o $D_EXTRA_OBJS" +D_EXTRA_OBJS="gcc/configunix.o gcc/cbridge_fdset.o std/c/unix/unix.o $D_EXTRA_OBJS" DCFG_UNIX="Unix" ]) @@ -140,6 +166,8 @@ d_gc_data= case "$target_os" in + aix*) d_gc_data="$d_gc_data GC_Use_Data_Fixed" + ;; cygwin*) d_gc_data="$d_gc_data GC_Use_Data_Fixed" ;; darwin*) D_GC_MODULES="$D_GC_MODULES internal/gc/gc_dyld.o" diff -uNr gdc-0.11/d/phobos/internal/adi.d gdc-0.12/d/phobos/internal/adi.d --- gdc-0.11/d/phobos/internal/adi.d 2005-04-24 18:48:31.000000000 +0200 +++ gdc-0.12/d/phobos/internal/adi.d 2005-05-19 02:15:50.000000000 +0200 @@ -63,8 +63,10 @@ { char clo = *lo; char chi = *hi; + //printf("lo = %d, hi = %d\n", lo, hi); if (clo <= 0x7F && chi <= 0x7F) { + //printf("\tascii\n"); *lo = chi; *hi = clo; lo++; @@ -84,6 +86,7 @@ if (lo == hi) break; + //printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi); if (stridelo == stridehi) { @@ -91,7 +94,7 @@ memcpy(lo, hi, stridelo); memcpy(hi, tmp, stridelo); lo += stridelo; - hi -= stridehi; + hi--; continue; } @@ -104,7 +107,7 @@ memcpy(lo, tmp, stridehi); lo += stridehi; - hi -= stridelo; + hi = hi - 1 + (stridehi - stridelo); } } return *cast(Array*)(&a); @@ -182,7 +185,7 @@ *cast(int*)lo = *cast(int*)hi; *cast(int*)hi = tmp; lo += stridelo; - hi -= stridehi; + hi--; continue; } @@ -194,7 +197,7 @@ memcpy(lo, tmp, stridehi * wchar.sizeof); lo += stridehi; - hi -= stridelo; + hi = hi - 1 + (stridehi - stridelo); } } return *cast(Array*)(&a); diff -uNr gdc-0.11/d/phobos/internal/arraycat.d gdc-0.12/d/phobos/internal/arraycat.d --- gdc-0.11/d/phobos/internal/arraycat.d 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/phobos/internal/arraycat.d 2005-05-19 02:15:50.000000000 +0200 @@ -28,25 +28,6 @@ extern (C): -byte[] _d_arraycat(byte[] x, byte[] y, uint size) -{ byte[] a; - uint length; - - if (!x.length) - return y; - if (!y.length) - return x; - - length = x.length + y.length; - a = new byte[length * size]; - memcpy(a, x, x.length * size); - //a[0 .. x.length * size] = x[]; - memcpy(&a[x.length * size], y, y.length * size); - *cast(int *)&a = length; // jam length - //a.length = length; - return a; -} - byte[] _d_arraycatn(uint size, uint n, ...) { byte[] a; uint length; @@ -88,6 +69,7 @@ uint a_length; uint x_bytes; + //printf("_d_arraycatb(x.ptr = %p, x.length = %d, y.ptr = %p, y.length = %d)\n", x.ptr, x.length, y.ptr, y.length); if (!x.length) return y; if (!y.length) @@ -189,6 +171,7 @@ memset(ba.ptr, val, len >> 3); for (uint i = len & ~7; i < len; i++) ba[i] = value; + //printf("-_d_arraysetbit2(ba.ptr = %p, ba.length = %d, value = %d)\n", ba.ptr, ba.length, ba[0]); return ba; } diff -uNr gdc-0.11/d/phobos/internal/dgccmain2.d gdc-0.12/d/phobos/internal/dgccmain2.d --- gdc-0.11/d/phobos/internal/dgccmain2.d 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/phobos/internal/dgccmain2.d 2005-05-28 01:57:05.000000000 +0200 @@ -55,13 +55,15 @@ int i; int result; + version (GC_Use_Stack_Guess) + stackOriginGuess = &argv; // Win32: original didn't do this -- what about Gcc? _STI_monitor_staticctor(); _STI_critical_init(); gc_init(); + version (GNU_CBridge_Stdio) + _d_gnu_cbridge_init_stdio(); am = cast(char[] *) malloc(argc * (char[]).sizeof); - version (GC_Use_Stack_Guess) - stackOriginGuess = &argv; try { diff -uNr gdc-0.11/d/phobos/internal/gc/gc.d gdc-0.12/d/phobos/internal/gc/gc.d --- gdc-0.11/d/phobos/internal/gc/gc.d 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/phobos/internal/gc/gc.d 2005-05-25 03:51:33.000000000 +0200 @@ -38,6 +38,7 @@ //debug = PRINTF; +import std.c.stdarg; import std.c.stdlib; import std.string; import gcx; @@ -215,7 +216,7 @@ */ if (length && size) { - p = _gc.malloc(length * size); + p = _gc.malloc(length * size + 1); debug(PRINTF) printf(" p = %p\n", p); memset(p, 0, length * size); result.length = length; @@ -246,24 +247,27 @@ void *p; Array result; - debug(PRINTF) printf("_d_newarrayi(length = %d, size = %d)\n", length, size); + //debug(PRINTF) printf("_d_newarrayi(length = %d, size = %d)\n", length, size); /* if (length == 0 || size == 0) result = 0; else */ if (length && size) - { void* q = cast(void*)(&size + 1); // pointer to initializer + { + //void* q = cast(void*)(&size + 1); // pointer to initializer + va_list q; + va_start!(uint)(q, size); // q is pointer to ... initializer version (BigEndian) { switch(size) { - case 1: q = cast(byte*)q + 3; break; - case 2: q = cast(byte*)q + 2; break; + case 1: q = cast(va_list)( cast(byte*)q + 3 ); break; + case 2: q = cast(va_list)( cast(byte*)q + 2 ); break; default: ; } } - p = _gc.malloc(length * size); + p = _gc.malloc(length * size + 1); debug(PRINTF) printf(" p = %p\n", p); if (size == 1) memset(p, *cast(ubyte*)q, length); @@ -292,7 +296,8 @@ else */ if (length) - { uint size = ((length + 31) >> 5) * 4; // number of bytes + { uint size = ((length + 31) >> 5) * 4 + 1; // number of bytes + // (not sure what the extra byte is for...) ubyte fill = value ? 0xFF : 0; p = _gc.malloc(size); @@ -409,9 +414,9 @@ if (newsize > size) { uint cap = _gc.capacity(p.data); - if (cap < newsize) + if (cap <= newsize) { - newdata = cast(byte *)_gc.malloc(newsize); + newdata = cast(byte *)_gc.malloc(newsize + 1); newdata[0 .. size] = p.data[0 .. size]; } newdata[size .. newsize] = 0; @@ -419,7 +424,7 @@ } else { - newdata = cast(byte *)_gc.calloc(newsize, 1); + newdata = cast(byte *)_gc.calloc(newsize + 1, 1); } } else @@ -456,9 +461,9 @@ if (newsize > size) { uint cap = _gc.capacity(p.data); - if (cap < newsize) + if (cap <= newsize) { - newdata = cast(byte *)_gc.malloc(newsize); + newdata = cast(byte *)_gc.malloc(newsize + 1); newdata[0 .. size] = p.data[0 .. size]; } newdata[size .. newsize] = 0; @@ -466,7 +471,7 @@ } else { - newdata = cast(byte *)_gc.calloc(newsize, 1); + newdata = cast(byte *)_gc.calloc(newsize + 1, 1); } } else @@ -495,7 +500,7 @@ { byte* newdata; //newdata = cast(byte *)_gc.malloc(newlength * size); - newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size)); + newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size) + 1); memcpy(newdata, px.data, length * size); px.data = newdata; } @@ -516,7 +521,7 @@ { void* newdata; //newdata = _gc.malloc(newlength * size); - newdata = _gc.malloc(newCapacity(newsize, 1)); + newdata = _gc.malloc(newCapacity(newsize, 1) + 1); memcpy(newdata, px.data, (length + 7) / 8); px.data = cast(byte*)newdata; } @@ -540,7 +545,7 @@ { version(none) { - newcap = newlength * size; + uint newcap = newlength * size; } else { @@ -591,6 +596,7 @@ //printf("mult: %2.2f, mult2: %2.2f, alloc: %2.2f\n",mult/100.0,mult2,newext / cast(double)size); } newcap = newext > newcap ? newext : newcap; + //printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size); } return newcap; } @@ -601,11 +607,18 @@ size_t cap = _gc.capacity(x); size_t length = x.length; size_t newlength = length + 1; - if (newlength * size > cap) + + assert(cap == 0 || length * size <= cap); + + //printf("_d_arrayappendc(size = %d, ptr = %p, length = %d, cap = %d)\n", size, x.ptr, x.length, cap); + + if (newlength * size >= cap) { byte* newdata; - //printf("_d_arrayappendc(%d, %d)\n", size, newlength); - newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size)); + //printf("_d_arrayappendc(size = %d, newlength = %d, cap = %d)\n", size, newlength, cap); + cap = newCapacity(newlength, size); + assert(cap >= newlength * size); + newdata = cast(byte *)_gc.malloc(cap + 1); memcpy(newdata, x, length * size); (cast(void **)(&x))[1] = newdata; } @@ -626,29 +639,46 @@ (cast(byte *)x)[length * size .. newlength * size] = argp[0 .. size]; } } + assert((cast(uint)x.ptr & 15) == 0); + assert(_gc.capacity(x.ptr) > x.length * size); return x; +} -/+ - byte[] a; - uint length; - void *argp; +extern (C) +byte[] _d_arraycat(byte[] x, byte[] y, uint size) +out (result) +{ + //printf("_d_arraycat(%d,%p ~ %d,%p size = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, size, result.length, result.ptr); + assert(result.length == x.length + y.length); + for (uint i = 0; i < x.length * size; i++) + assert((cast(byte*)result)[i] == (cast(byte*)x)[i]); + for (uint i = 0; i < y.length * size; i++) + assert((cast(byte*)result)[x.length * size + i] == (cast(byte*)y)[i]); + + uint cap = _gc.capacity(result.ptr); + assert(!cap || cap > result.length * size); +} +body +{ byte[] a; + uint len; + + if (!y.length) + return x; + if (!x.length) + return y; - //printf("size = %d\n", size); - length = x.length + 1; - a = new byte[length * size]; + len = x.length + y.length; + a = new byte[len * size]; memcpy(a, x, x.length * size); - argp = &size + 1; - //printf("*argp = %llx\n", *cast(long *)argp); - memcpy(&a[x.length * size], argp, size); - //printf("a[0] = %llx\n", *cast(long *)&a[0]); - *cast(int *)&a = length; // jam length - //printf("a[0] = %llx\n", *cast(long *)&a[0]); - x = a; + //a[0 .. x.length * size] = x[]; + memcpy(&a[x.length * size], y, y.length * size); + *cast(int *)&a = len; // jam length + //a.length = len; return a; -+/ } + extern (C) bit[] _d_arrayappendcb(inout bit[] x, bit b) { diff -uNr gdc-0.11/d/phobos/internal/gc/gc_freebsd.c gdc-0.12/d/phobos/internal/gc/gc_freebsd.c --- gdc-0.11/d/phobos/internal/gc/gc_freebsd.c 2005-04-12 05:16:27.000000000 +0200 +++ gdc-0.12/d/phobos/internal/gc/gc_freebsd.c 2005-05-29 00:00:56.000000000 +0200 @@ -8,5 +8,5 @@ size_t len = sizeof(void *); int r = sysctl(nm, 2, out_origin, &len, NULL, 0); - return ! ! r; + return ! r; } diff -uNr gdc-0.11/d/phobos/internal/gc/gcgcc.d gdc-0.12/d/phobos/internal/gc/gcgcc.d --- gdc-0.11/d/phobos/internal/gc/gcgcc.d 2005-04-26 03:45:07.000000000 +0200 +++ gdc-0.12/d/phobos/internal/gc/gcgcc.d 2005-05-25 03:51:33.000000000 +0200 @@ -10,7 +10,7 @@ version (GC_Use_Alloc_MMap) { - private import std.c.unix; + private import std.c.unix.unix; void *os_mem_map(uint nbytes) { void *p; @@ -104,7 +104,7 @@ version (GC_Use_Data_Proc_Maps) { - private import std.c.unix; + private import std.c.unix.unix; private import std.c.stdlib; } @@ -130,18 +130,18 @@ version (GC_Use_Data_Fixed) { - if (FM.One) { + static if (FM.One) { main_data_start = & Data_Start; main_data_end = & Data_End; *base = main_data_start; *nbytes = main_data_end - main_data_start; - } else if (FM.Two) { + } else static if (FM.Two) { main_data_start = & Data_Start; main_data_end = & Data_End; *base = main_data_start; *nbytes = main_data_end - main_data_start; addRange(& Data_Start_2, & Data_End_2); - } else if (FM.MinMax) { + } else static if (FM.MinMax) { static void * min(void *a, void *b) { return a < b ? a : b; } static void * max(void *a, void *b) { return a > b ? a : b; } main_data_start = & Data_Start < & Data_Start_2 ? & Data_Start : & Data_Start_2; diff -uNr gdc-0.11/d/phobos/internal/gc/gcgccextern.d gdc-0.12/d/phobos/internal/gc/gcgccextern.d --- gdc-0.11/d/phobos/internal/gc/gcgccextern.d 2005-04-26 03:45:07.000000000 +0200 +++ gdc-0.12/d/phobos/internal/gc/gcgccextern.d 2005-05-25 03:51:33.000000000 +0200 @@ -5,6 +5,7 @@ version(GC_Use_Data_Fixed) { + extern (C) int _data; extern (C) int __data_start; extern (C) int _end; extern (C) int _data_start__; @@ -18,7 +19,13 @@ .. the Mode can be a version instead of enum trick */ - version (bsd) + version (aix) + { + alias _data Data_Start; + alias _end Data_End; + enum FM { One = 1, MinMax = 0, Two = 0 } + } + else version (bsd) { // use '_etext' if '__fini_array_end' doesn't work /* There is a bunch of read-only data after .data and before .bss, but @@ -26,8 +33,6 @@ and scan... */ alias __fini_array_end Data_Start; alias _end Data_End; - alias Data_Start Data_Start_2; - alias Data_End Data_End_2; enum FM { One = 1, MinMax = 0, Two = 0 } } else version (cygwin) @@ -41,13 +46,11 @@ else version (linux) { alias __data_start Data_Start; + alias _end Data_End; /* possible better way: [__data_start,_DYNAMIC) and [_edata/edata or __bss_start,_end/end) This doesn't really save much.. a better linker script is needed. */ - alias _end Data_End; - alias Data_Start Data_Start_2; - alias Data_End Data_End_2; enum FM { One = 1, MinMax = 0, Two = 0 } } } diff -uNr gdc-0.11/d/phobos/internal/memset.d gdc-0.12/d/phobos/internal/memset.d --- gdc-0.11/d/phobos/internal/memset.d 2005-02-20 16:43:51.000000000 +0100 +++ gdc-0.12/d/phobos/internal/memset.d 2005-05-19 02:15:50.000000000 +0200 @@ -81,6 +81,16 @@ return pstart; } +cdouble *_memset128(cdouble *p, cdouble value, int count) +{ + cdouble *pstart = p; + cdouble *ptop; + + for (ptop = &p[count]; p < ptop; p++) + *p = value; + return pstart; +} + real *_memset80(real *p, real value, int count) { real *pstart = p; @@ -91,6 +101,16 @@ return pstart; } +creal *_memset160(creal *p, creal value, int count) +{ + creal *pstart = p; + creal *ptop; + + for (ptop = &p[count]; p < ptop; p++) + *p = value; + return pstart; +} + void *_memsetn(void *p, void *value, int count, int sizelem) { void *pstart = p; int i; diff -uNr gdc-0.11/d/phobos/libgphobos.spec.in gdc-0.12/d/phobos/libgphobos.spec.in --- gdc-0.11/d/phobos/libgphobos.spec.in 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.12/d/phobos/libgphobos.spec.in 2005-05-08 16:01:26.000000000 +0200 @@ -0,0 +1,7 @@ +# +# This spec file is read by gdc when linking. +# It is used to specify the standard libraries we need in order +# to link with libphobos. +# +%rename lib liborig +*lib: @LIBS@ %(liborig) diff -uNr gdc-0.11/d/phobos/libphobos.spec.in gdc-0.12/d/phobos/libphobos.spec.in --- gdc-0.11/d/phobos/libphobos.spec.in 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/phobos/libphobos.spec.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -# -# This spec file is read by gdc when linking. -# It is used to specify the standard libraries we need in order -# to link with libphobos. -# -%rename lib liborig -*lib: @LIBS@ %(liborig) diff -uNr gdc-0.11/d/phobos/linux.mak gdc-0.12/d/phobos/linux.mak --- gdc-0.11/d/phobos/linux.mak 2005-04-17 15:49:49.000000000 +0200 +++ gdc-0.12/d/phobos/linux.mak 2005-05-21 19:29:57.000000000 +0200 @@ -56,7 +56,7 @@ crc32.o conv.o arraycast.o errno.o alloca.o cmath2.o \ process.o syserror.o \ socket.o socketstream.o stdarg.o stdio.o format.o \ - perf.o openrj.o uni.o trace.o \ + perf.o openrj.o uni.o trace.o boxer.o \ ti_wchar.o ti_uint.o ti_short.o ti_ushort.o \ ti_byte.o ti_ubyte.o ti_long.o ti_ulong.o ti_ptr.o \ ti_float.o ti_double.o ti_real.o ti_delegate.o \ @@ -98,7 +98,8 @@ std/intrinsic.d std/array.d std/switcherr.d std/syserror.d \ std/regexp.d std/random.d std/stream.d std/process.d std/recls.d \ std/socket.d std/socketstream.d std/loader.d std/stdarg.d \ - std/stdio.d std/format.d std/perf.d std/openrj.d std/uni.d + std/stdio.d std/format.d std/perf.d std/openrj.d std/uni.d \ + std/boxer.d SRC_STD_C= std/c/process.d std/c/stdlib.d std/c/time.d std/c/stdio.d \ std/c/math.d std/c/stdarg.d std/c/stddef.d @@ -471,6 +472,9 @@ base64.o : std/base64.d $(DMD) -c $(DFLAGS) std/base64.d +boxer.o : std/boxer.d + $(DMD) -c $(DFLAGS) std/boxer.d + compiler.o : std/compiler.d $(DMD) -c $(DFLAGS) std/compiler.d diff -uNr gdc-0.11/d/phobos/Makefile.in gdc-0.12/d/phobos/Makefile.in --- gdc-0.11/d/phobos/Makefile.in 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/phobos/Makefile.in 2005-05-29 00:00:56.000000000 +0200 @@ -34,6 +34,7 @@ DFLAGS=@DFLAGS@ $(D_GC_FLAGS) -nostdinc +D_ENABLE_RECLS=@D_ENABLE_RECLS@ D_RECLS_OS=@D_RECLS_OS@ D_GENERATE_FRAGMENTS=@D_GENERATE_FRAGMENTS@ @@ -75,7 +76,7 @@ gdc_include_dir=@gdc_include_dir@ -all: libphobos.a +all: libgphobos.a %.o : %.c $(CC) -o $@ $(OUR_CFLAGS) $(CFLAGS) -c $< @@ -92,8 +93,15 @@ Makefile: Makefile.in ./config.status -unittest: unittest.o libphobos.a - $(CC) -o $@ $(DFLAGS) unittest.o -L./ -lphobos $(LIBS) +unittest: unittest.o libgphobos.a + $(CC) -o $@ $(CFLAGS) unittest.o -L./ -lgphobos $(LIBS) + +internal/gc/testgc.o: $(host_alias)/gcc/config.d $(srcdir)/internal/gc/testgc.d + $(GDC) -o $@ $(DFLAGS) -fno-release -I $(srcdir) -I $(srcdir)/internal/gc -I ./$(host_alias) -c $(srcdir)/internal/gc/testgc.d + +testgc: internal/gc/testgc.o libgphobos.a + $(CC) -o $@ $(CFLAGS) internal/gc/testgc.o -L./ -lgphobos $(LIBS) + #$(GDC) -o $@ $(DFLAGS) unittest.o -L./ @@ -118,9 +126,9 @@ crc32.o std/conv.o internal/arraycast.o errno.o \ std/process.o std/syserror.o \ std/socket.o std/socketstream.o std/c/stdarg.o std/stdio.o std/format.o \ - std/perf.o std/openrj.o std/uni.o \ + std/perf.o std/openrj.o std/uni.o std/boxer.o \ $(subst ti_,std/typeinfo/ti_,$(TI)) \ - std/date.o std/dateparse.o std/math2.o etc/c/zlib.o std/zlib.o std/zip.o std/recls.o \ + std/date.o std/dateparse.o std/math2.o etc/c/zlib.o std/zlib.o std/zip.o \ internal/dgccmain2.o internal/rundmain.o # This should not be linked into a shared library. @@ -133,13 +141,18 @@ etc/c/zlib/inflate.o etc/c/zlib/infback.o \ etc/c/zlib/inftrees.o etc/c/zlib/inffast.o +ifdef D_ENABLE_RECLS RECLS_OBJS=etc/c/recls/recls_api.o \ etc/c/recls/recls_fileinfo.o \ etc/c/recls/recls_internal.o \ etc/c/recls/recls_util.o \ etc/c/recls/recls_api_$(D_RECLS_OS).o \ etc/c/recls/recls_fileinfo_$(D_RECLS_OS).o \ - etc/c/recls/recls_util_$(D_RECLS_OS).o + etc/c/recls/recls_util_$(D_RECLS_OS).o \ + std/recls.o +else +RECLS_OBJS= +endif GC_OBJS= internal/gc/gc.o internal/gc/gcx.o \ internal/gc/gcbits.o @@ -216,14 +229,15 @@ # GCC_OBJS (gcc/config.o) first so I don't have to write more deps ALL_PHOBOS_OBJS = $(D_EXTRA_OBJS) $(GCC_OBJS) $(MAIN_OBJS) $(ZLIB_OBJS) $(GC_OBJS) $(RECLS_OBJS) $(WEAK_OBJS) -libphobos.a : $(ALL_PHOBOS_OBJS) $(CMAIN_OBJS) +libgphobos.a : $(ALL_PHOBOS_OBJS) $(CMAIN_OBJS) $(AR) -r $@ $(ALL_PHOBOS_OBJS) $(CMAIN_OBJS) $(RANLIB) $@ .PHONY: info dvi TAGS install-info installcheck mostlyclean distclean maintainer-clean check -check: unittest +check: unittest testgc ./unittest + ./testgc info: dvi: @@ -239,10 +253,10 @@ # 3.3.x install-sh can't handle multiple source arguments # $(INSTALL_HEADER) $(srcdir)/$$i/*.[hd] $(DESTDIR)$(gdc_include_dir)/$$i; done -install: $(host_alias)/gcc/config.d libphobos.a +install: $(host_alias)/gcc/config.d libgphobos.a for i in etc/c etc/c/recls etc/c/stlsoft etc/c/zlib \ gcc std std/c \ - std/c/darwin std/c/linux std/c/mach std/c/windows \ + std/c/darwin std/c/linux std/c/mach std/c/unix std/c/windows \ std/typeinfo std/windows; do \ $(mkinstalldirs) $(DESTDIR)$(gdc_include_dir)/$$i; \ for f in $(srcdir)/$$i/*.[hd]; do $(INSTALL_HEADER) $$f $(DESTDIR)$(gdc_include_dir)/$$i; done; \ @@ -254,9 +268,9 @@ if test -f $(host_alias)/gcc/configunix.d; then $(INSTALL_HEADER) $(host_alias)/gcc/configunix.d $(DESTDIR)$(gdc_include_dir)/$(host_alias)/gcc; fi $(INSTALL) phobos-ver-syms $(DESTDIR)$(gdc_include_dir)/$(host_alias) $(mkinstalldirs) $(DESTDIR)$(toolexeclibdir) - $(INSTALL) libphobos.a $(DESTDIR)$(toolexeclibdir) - $(RANLIB) $(DESTDIR)$(toolexeclibdir)/libphobos.a - $(INSTALL) libphobos.spec $(DESTDIR)$(toolexeclibdir) + $(INSTALL) libgphobos.a $(DESTDIR)$(toolexeclibdir) + $(RANLIB) $(DESTDIR)$(toolexeclibdir)/libgphobos.a + $(INSTALL) libgphobos.spec $(DESTDIR)$(toolexeclibdir) clean: echo 'Removing files...' @@ -265,4 +279,4 @@ rm -f unittest rm -f config/gen_config1.o config/gen_unix.o config/gen_math.o gen_config1 gen_unix gen_math rm -f frag-gen $(host_alias)/gcc/config.d $(host_alias)/gcc/configunix.d - rm -f libphobos.a + rm -f libgphobos.a diff -uNr gdc-0.11/d/phobos/phobos-ver-syms.in gdc-0.12/d/phobos/phobos-ver-syms.in --- gdc-0.11/d/phobos/phobos-ver-syms.in 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/phobos/phobos-ver-syms.in 2005-05-21 02:41:57.000000000 +0200 @@ -1,8 +1,11 @@ @DCFG_UNIX@ +@DCFG_PTHREAD_SUSPEND@ @DCFG_SEMAPHORE_IMPL@ @DCFG_TRUNC@ @DCFG_EXP2_LOG2@ @DCFG_EXECVPE@ +@DCFG_SPAWNVP@ @DCFG_FWIDE@ @DCFG_STRTOLD@ @DCFG_SA_LEN@ +@DCFG_CBRIDGE_STDIO@ diff -uNr gdc-0.11/d/phobos/std/base64.d gdc-0.12/d/phobos/std/base64.d --- gdc-0.11/d/phobos/std/base64.d 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/phobos/std/base64.d 2005-05-29 00:00:56.000000000 +0200 @@ -22,6 +22,12 @@ 3. This notice may not be removed or altered from any source distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + module std.base64; class Base64Exception: Exception @@ -75,7 +81,8 @@ sp = &str[0]; for(stri = 0; stri != strmax; stri++) { - x = (*sp++ << 16) | (*sp++ << 8) | (*sp++); + x = (sp[0] << 16) | (sp[1] << 8) | (sp[2]); + sp+= 3; *bp++ = array[(x & 0b11111100_00000000_00000000) >> 18]; *bp++ = array[(x & 0b00000011_11110000_00000000) >> 12]; *bp++ = array[(x & 0b00000000_00001111_11000000) >> 6]; @@ -85,7 +92,8 @@ switch(strleft) { case 2: - x = (*sp++ << 16) | (*sp++ << 8); + x = (sp[0] << 16) | (sp[1] << 8); + sp += 2; *bp++ = array[(x & 0b11111100_00000000_00000000) >> 18]; *bp++ = array[(x & 0b00000011_11110000_00000000) >> 12]; *bp++ = array[(x & 0b00000000_00001111_11000000) >> 6]; diff -uNr gdc-0.11/d/phobos/std/boxer.d gdc-0.12/d/phobos/std/boxer.d --- gdc-0.11/d/phobos/std/boxer.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.12/d/phobos/std/boxer.d 2005-05-25 03:51:33.000000000 +0200 @@ -0,0 +1,839 @@ +/* This module is written by Burton Radons and placed into the public domain. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 + + This module make not work on all GCC targets due to assumptions + about the type of va_list. +*/ +module std.boxer; + +private import std.format; +private import std.string; +private import std.utf; +version (GNU) + private import std.stdarg; + +/** These functions and types allow packing objects into generic containers + * and recovering them later. This comes into play in a wide spectrum of + * utilities, such as with a scripting language, or as additional user data + * for an object. + * + * Box an object by calling the box function: + * + * Box x = box(4); + * + * Recover the value by using the unbox template: + * + * int y = unbox!(int)(x); + * + * If it cannot unbox the object to that type, it throws UnboxException. It will + * use implicit casts to behave in the exact same way as D does - for + * instance: + * + * byte v; + * int i = v; // Implicitly cast from byte to int. + * int j = unbox!(int)(Box(i)); // Do the exact same thing at runtime. + * + * This therefore means that attempting to unbox an int as a string will + * throw an error and not format it. In general, you can call the toString + * method on the box and receive a good result, depending upon whether + * std.string.format accepts it. + * + * Boxes can be compared to one another and they can be used as keys for + * associative arrays. Boxes of different types can be compared to one + * another, using the same casting rules as the main type system. + * + * boxArray has two forms: + * + * Box[] boxArray(...); + * Box[] boxArray(TypeInfo[] types, void* data); + * + * This converts an array of arguments into an array of boxes. To convert + * back into an array of arguments, use boxArrayToArguments: + * + * void boxArrayToArguments(Box[] arguments, out TypeInfo[] types, + * out void[] data); + * + * Finally, you can discover whether unboxing as a certain type is legal by + * using the unboxable template or method: + * + * bit unboxable!(T) (Box value); + * bit Box.unboxable(TypeInfo T); + */ + +/** Return the next type in an array typeinfo, or null if there is none. */ +private bit isArrayTypeInfo(TypeInfo type) +{ + char[] name = type.classinfo.name; + return name.length >= 10 && name[9] == 'A' && name != "TypeInfo_AssociativeArray"; +} + +/** The type class returned from Box.findTypeClass; the order of entries is important. */ +private enum TypeClass +{ + Bit, /**< bit */ + Integer, /**< byte, ubyte, short, ushort, int, uint, long, ulong */ + Float, /**< float, double, real */ + Complex, /**< cfloat, cdouble, creal */ + Imaginary, /**< ifloat, idouble, ireal */ + Class, /**< Inherits from Object */ + Pointer, /**< Pointer type (T *) */ + Array, /**< Array type (T []) */ + Other, /**< Any other type, such as delegates, function pointers, struct, void... */ +} + +version (DigitalMars) + version = DigitalMars_TypeInfo; +else version (GNU) + version = DigitalMars_TypeInfo; + +/** A box object contains a value in a generic fashion, allowing it to be + * passed from one place to another without having to know its type. It is + * created by calling the box function, and you can recover the value by + * instantiating the unbox template. + */ +struct Box +{ + private TypeInfo p_type; /**< The type of the contained object. */ + + private union + { + void* p_longData; /**< An array of the contained object. */ + void[8] p_shortData; /**< Data used when the object is small. */ + } + + private static TypeClass findTypeClass(TypeInfo type) + { + if (cast(TypeInfo_Class) type) + return TypeClass.Class; + if (cast(TypeInfo_Pointer) type) + return TypeClass.Pointer; + if (isArrayTypeInfo(type)) + return TypeClass.Array; + + version (DigitalMars_TypeInfo) + { + /* Depend upon the name of the base type classes. */ + if (type.classinfo.name.length != "TypeInfo_?".length) + return TypeClass.Other; + switch (type.classinfo.name[9]) + { + case 'b': return TypeClass.Bit; + case 'g', 'h', 's', 't', 'i', 'k', 'l', 'm': return TypeClass.Integer; + case 'f', 'd', 'e': return TypeClass.Float; + case 'q', 'r', 'c': return TypeClass.Complex; + case 'o', 'p', 'j': return TypeClass.Imaginary; + default: return TypeClass.Other; + } + } + else + { + /* Use the name returned from toString, which might (but hopefully doesn't) include an allocation. */ + switch (type.toString) + { + case "bit": return TypeClass.Bit; + case "byte", "ubyte", "short", "ushort", "int", "uint", "long", "ulong": return TypeClass.Integer; + case "float", "real", "double": return TypeClass.Float; + case "cfloat", "cdouble", "creal": return TypeClass.Complex; + case "ifloat", "idouble", "ireal": return TypeClass.Imaginary; + default: return TypeClass.Other; + } + } + } + + /** Return whether this value could be unboxed as the given type without throwing. */ + bit unboxable(TypeInfo test) + { + if (type is test) + return true; + + TypeInfo_Class ca = cast(TypeInfo_Class) type, cb = cast(TypeInfo_Class) test; + + if (ca !== null && cb !== null) + { + ClassInfo ia = (*cast(Object *) data).classinfo, ib = cb.info; + + for ( ; ia !== null; ia = ia.base) + if (ia is ib) + return true; + return false; + } + + TypeClass ta = findTypeClass(type), tb = findTypeClass(test); + + if (type is typeid(void*) && *cast(void**) data is null) + return (tb == TypeClass.Class || tb == TypeClass.Pointer || tb == TypeClass.Array); + + if (test is typeid(void*)) + return (tb == TypeClass.Class || tb == TypeClass.Pointer || tb == TypeClass.Array); + + if (ta == TypeClass.Pointer && tb == TypeClass.Pointer) + return (cast(TypeInfo_Pointer)type).next is (cast(TypeInfo_Pointer)test).next; + + if ((ta == tb && ta != TypeClass.Other) + || (ta == TypeClass.Bit && tb == TypeClass.Integer) + || (ta <= TypeClass.Integer && tb == TypeClass.Float) + || (ta <= TypeClass.Imaginary && tb == TypeClass.Complex)) + return true; + return false; + } + + /** Return the type of the contained object. */ + TypeInfo type() + { + return p_type; + } + + /** Return the data array. */ + void[] data() + { + size_t size = type.tsize(); + + return size <= p_shortData.length ? p_shortData[0..size] : p_longData[0..size]; + } + + /** Attempt to convert the object to a string by doing D formatting on it. + */ + char[] toString() + { + if (type is null) + return ""; + + version (GNU) + { + // This branch could be used on all targets, but using the above + // will help work out bugs for the baseline distro. + TypeInfo ti = type; + while (1) { + switch (ti.classinfo.name[9]) { + case 'b': return .toString(*cast(bit*)data); + case 'a': return .toString(*cast(char*)data); + case 'u': + { + char[] string; + encode(string, *cast(wchar*)data); + return string; + } + case 'w': + { + char[] string; + encode(string, *cast(dchar*)data); + return string; + } + case 'g': return .toString(*cast(byte*)data); + case 'h': return .toString(*cast(ubyte*)data); + case 's': return .toString(*cast(short*)data); + case 't': return .toString(*cast(ushort*)data); + case 'i': return .toString(*cast(int*)data); + case 'k': return .toString(*cast(uint*)data); + case 'l': return .toString(*cast(long*)data); + case 'm': return .toString(*cast(ulong*)data); + case 'f': return .toString(*cast(float*)data); + case 'd': return .toString(*cast(double*)data); + case 'e': return .toString(*cast(real*)data); + case 'o': return .toString(*cast(ifloat*)data); + case 'p': return .toString(*cast(idouble*)data); + case 'j': return .toString(*cast(ireal*)data); + case 'q': return .toString(*cast(cfloat*)data); + case 'r': return .toString(*cast(cdouble*)data); + case 'c': return .toString(*cast(creal*)data); + case 'P': return .format("%s",*cast(void**)data); + case 'C': return (*cast(Object*)data).toString(); + case 'T': ti = (cast(TypeInfo_Typedef)ti).base; + default: + // doFormat raises errors for the rest: + return .format("%s", & toString); + } + } + } else { + TypeInfo[2] arguments; + char[] string; + void[] args = new void[(char[]).sizeof + data.length]; + char[] format = "%s"; + + arguments[0] = typeid(char[]); + arguments[1] = type; + + void putc(dchar ch) + { + std.utf.encode(string, ch); + } + + args[0..(char[]).sizeof] = (cast(void*) &format)[0..(char[]).sizeof]; + args[(char[]).sizeof..length] = data; + version (GNU) + std.format.doFormat(&putc, arguments, cast(va_list) args); + else + std.format.doFormat(&putc, arguments, args); + delete args; + + return string; + } + } + + private bit opEqualsInternal(Box other, bit inverted) + { + if (type != other.type) + { + if (!unboxable(other.type)) + { + if (inverted) + return false; + return other.opEqualsInternal(*this, true); + } + + TypeClass ta = findTypeClass(type), tb = findTypeClass(other.type); + + if (ta <= TypeClass.Integer && tb <= TypeClass.Integer) + { + char[] na = type.toString, nb = other.type.toString; + + if (na == "ulong" || nb == "ulong") + return unbox!(ulong)(*this) == unbox!(ulong)(other); + return unbox!(long)(*this) == unbox!(long)(other); + } + else if (tb == TypeClass.Float) + return unbox!(real)(*this) == unbox!(real)(other); + else if (tb == TypeClass.Complex) + return unbox!(creal)(*this) == unbox!(creal)(other); + else if (tb == TypeClass.Imaginary) + return unbox!(ireal)(*this) == unbox!(ireal)(other); + + assert (0); + } + + return cast(bit)type.equals(data, other.data); + } + + /** Implement the equals operator. */ + bit opEquals(Box other) + { + return opEqualsInternal(other, false); + } + + private float opCmpInternal(Box other, bit inverted) + { + if (type != other.type) + { + if (!unboxable(other.type)) + { + if (inverted) + return 0; + return other.opCmpInternal(*this, true); + } + + TypeClass ta = findTypeClass(type), tb = findTypeClass(other.type); + + if (ta <= TypeClass.Integer && tb == TypeClass.Integer) + { + if (type == typeid(ulong) || other.type == typeid(ulong)) + { + ulong va = unbox!(ulong)(*this), vb = unbox!(ulong)(other); + return va > vb ? 1 : va < vb ? -1 : 0; + } + + long va = unbox!(long)(*this), vb = unbox!(long)(other); + return va > vb ? 1 : va < vb ? -1 : 0; + } + else if (tb == TypeClass.Float) + { + real va = unbox!(real)(*this), vb = unbox!(real)(other); + return va > vb ? 1 : va < vb ? -1 : va == vb ? 0 : float.nan; + } + else if (tb == TypeClass.Complex) + { + creal va = unbox!(creal)(*this), vb = unbox!(creal)(other); + return va == vb ? 0 : float.nan; + } + else if (tb == TypeClass.Imaginary) + { + ireal va = unbox!(ireal)(*this), vb = unbox!(ireal)(other); + return va > vb ? 1 : va < vb ? -1 : va == vb ? 0 : float.nan; + } + + assert (0); + } + + return type.compare(data, other.data); + } + + /** Implement the compare operator. */ + float opCmp(Box other) + { + return opCmpInternal(other, false); + } + + uint toHash() + { + return type.getHash(data); + } +} + +/** Create a box out of the first argument passed. */ +Box box(...) +in +{ + assert (_arguments.length == 1); +} +body +{ + version (GNU) + { + void * p; + version (BigEndian) + { + byte b; + short s; + switch (_arguments[0].tsize()) { + case 1: b = va_arg!(byte)(_argptr); p = & b; break; + case 2: s = va_arg!(short)(_argptr); p = & s; break; + default: p = cast(void *) _argptr; + } + } + else + p = cast(void *) _argptr; + return box(_arguments[0], p); + } + else + return box(_arguments[0], _argptr); +} + +/** Assign the parameters, copying data as needed. */ +Box box(TypeInfo type, void* data) +in +{ + assert(type !== null); +} +body +{ + Box result; + size_t size = type.tsize(); + + result.p_type = type; + if (size <= result.p_shortData.length) + result.p_shortData[0..size] = data[0..size]; + else + result.p_longData = data[0..size].dup; + + return result; +} + +/** Return the length of an argument in bytes. */ +private size_t argumentLength(size_t baseLength) +{ + return (baseLength + int.sizeof - 1) & ~(int.sizeof - 1); +} + +/** Box each argument in the list. */ +Box[] boxArray(TypeInfo[] types, void* data) +{ + Box[] array = new Box[types.length]; + + foreach(size_t index, TypeInfo type; types) + { + array[index] = box(type, data); + data += argumentLength(type.tsize()); + } + + return array; +} + +/** Box each argument passed to the function, returning an array of boxes. */ +Box[] boxArray(...) +{ + return boxArray(_arguments, cast(void *) _argptr); +} + +/** Convert an array of boxes into an array of arguments. */ +void boxArrayToArguments(Box[] arguments, out TypeInfo[] types, out void* data) +{ + size_t dataLength; + void* pointer; + + /* Determine the number of bytes of data to allocate by summing the arguments. */ + foreach (Box item; arguments) + dataLength += argumentLength(item.data.length); + + types = new TypeInfo[arguments.length]; + pointer = data = new void[dataLength]; + + /* Stash both types and data. */ + foreach (size_t index, Box item; arguments) + { + types[index] = item.type; + pointer[0..item.data.length] = item.data; + pointer += argumentLength(item.data.length); + } +} + +/** This is thrown if you try to unbox an incompatible type. */ +class UnboxException : Exception +{ + /** The boxed object spawning the error. */ + Box object; + + /** The type that we tried to unbox as. */ + TypeInfo outputType; + + /** Assign parameters and the message. */ + this(Box object, TypeInfo outputType) + { + this.object = object; + this.outputType = outputType; + super(format("Could not unbox from type %s to %s.", object.type, outputType)); + } +} + +/** A generic unboxer for the real numeric types. */ +private template unboxCastReal(T) +{ + T unboxCastReal(Box value) + { + assert (value.type !== null); + + if (value.type is typeid(float)) + return cast(T) *cast(float*) value.data; + if (value.type is typeid(double)) + return cast(T) *cast(double*) value.data; + if (value.type is typeid(real)) + return cast(T) *cast(real*) value.data; + return unboxCastInteger!(T)(value); + } +} + +/** A generic unboxer for the integral numeric types. */ +private template unboxCastInteger(T) +{ + T unboxCastInteger(Box value) + { + assert (value.type !== null); + + if (value.type is typeid(int)) + return cast(T) *cast(int*) value.data; + if (value.type is typeid(uint)) + return cast(T) *cast(uint*) value.data; + if (value.type is typeid(long)) + return cast(T) *cast(long*) value.data; + if (value.type is typeid(ulong)) + return cast(T) *cast(ulong*) value.data; + if (value.type is typeid(bit)) + return cast(T) *cast(bit*) value.data; + if (value.type is typeid(byte)) + return cast(T) *cast(byte*) value.data; + if (value.type is typeid(ubyte)) + return cast(T) *cast(ubyte*) value.data; + if (value.type is typeid(short)) + return cast(T) *cast(short*) value.data; + if (value.type is typeid(ushort)) + return cast(T) *cast(ushort*) value.data; + throw new UnboxException(value, typeid(T)); + } +} + +/** A generic unboxer for the complex numeric types. */ +private template unboxCastComplex(T) +{ + T unboxCastComplex(Box value) + { + assert (value.type !== null); + + if (value.type is typeid(cfloat)) + return cast(T) *cast(cfloat*) value.data; + if (value.type is typeid(cdouble)) + return cast(T) *cast(cdouble*) value.data; + if (value.type is typeid(creal)) + return cast(T) *cast(creal*) value.data; + if (value.type is typeid(ifloat)) + return cast(T) *cast(ifloat*) value.data; + if (value.type is typeid(idouble)) + return cast(T) *cast(idouble*) value.data; + if (value.type is typeid(ireal)) + return cast(T) *cast(ireal*) value.data; + return unboxCastReal!(T)(value); + } +} + +/** A generic unboxer for the imaginary numeric types. */ +private template unboxCastImaginary(T) +{ + T unboxCastImaginary(Box value) + { + assert (value.type !== null); + + if (value.type is typeid(ifloat)) + return cast(T) *cast(ifloat*) value.data; + if (value.type is typeid(idouble)) + return cast(T) *cast(idouble*) value.data; + if (value.type is typeid(ireal)) + return cast(T) *cast(ireal*) value.data; + throw new UnboxException(value, typeid(T)); + } +} + +/** This unbox template takes a template parameter and returns a function that + * takes a box object and returns the specified type. If it cannot cast to + * the type, it throws UnboxException. For example: + * + * Box y = box(4); + * int x = unbox!(int) (y); + */ +template unbox(T) +{ + T unbox(Box value) + { + assert (value.type !== null); + + if (typeid(T) is value.type) + return *cast(T*) value.data; + throw new UnboxException(value, typeid(T)); + } +} + +template unbox(T : byte) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : ubyte) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : short) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : ushort) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : int) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : uint) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : long) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : ulong) { T unbox(Box value) { return unboxCastInteger!(T) (value); } } +template unbox(T : float) { T unbox(Box value) { return unboxCastReal!(T) (value); } } +template unbox(T : double) { T unbox(Box value) { return unboxCastReal!(T) (value); } } +template unbox(T : real) { T unbox(Box value) { return unboxCastReal!(T) (value); } } +template unbox(T : cfloat) { T unbox(Box value) { return unboxCastComplex!(T) (value); } } +template unbox(T : cdouble) { T unbox(Box value) { return unboxCastComplex!(T) (value); } } +template unbox(T : creal) { T unbox(Box value) { return unboxCastComplex!(T) (value); } } +template unbox(T : ifloat) { T unbox(Box value) { return unboxCastImaginary!(T) (value); } } +template unbox(T : idouble) { T unbox(Box value) { return unboxCastImaginary!(T) (value); } } +template unbox(T : ireal) { T unbox(Box value) { return unboxCastImaginary!(T) (value); } } + +template unbox(T : Object) +{ + T unbox(Box value) + { + assert (value.type !== null); + + if (typeid(T) == value.type || cast(TypeInfo_Class) value.type) + { + Object object = *cast(Object*)value.data; + T result = cast(T)object; + + if (object is null) + return null; + if (result is null) + throw new UnboxException(value, typeid(T)); + return result; + } + + if (typeid(void*) is value.type && *cast(void**) value.data is null) + return null; + throw new UnboxException(value, typeid(T)); + } +} + +template unbox(T : T[]) +{ + T[] unbox(Box value) + { + assert (value.type !== null); + + if (typeid(T[]) is value.type) + return *cast(T[]*) value.data; + if (typeid(void*) is value.type && *cast(void**) value.data is null) + return null; + throw new UnboxException(value, typeid(T[])); + } +} + +template unbox(T : T*) +{ + T* unbox(Box value) + { + assert (value.type !== null); + + if (typeid(T*) is value.type) + return *cast(T**) value.data; + if (typeid(void*) is value.type && *cast(void**) value.data is null) + return null; + if (typeid(T[]) is value.type) + return *cast(T[]*) value.data; + + throw new UnboxException(value, typeid(T*)); + } +} + +template unbox(T : void*) +{ + T unbox(Box value) + { + assert (value.type !== null); + + if (cast(TypeInfo_Pointer) value.type) + return *cast(void**) value.data; + if (isArrayTypeInfo(value.type)) + return *cast(void[]*) value.data; + if (typeid(Object) == value.type) + return *cast(Object*) value.data; + + throw new UnboxException(value, typeid(T)); + } +} + +/** Return whether the value can be unboxed to this type without throwing + * UnboxException. + */ +template unboxable(T) +{ + bit unboxable(Box value) + { + return value.unboxable(typeid(T)); + } +} + +/* Tests unboxing - assert that if it says it's unboxable, it is. */ +private template unboxTest(T) +{ + T unboxTest(Box value) + { + T result; + bit unboxable = value.unboxable(typeid(T)); + + try result = unbox!(T) (value); + catch (UnboxException error) + { + if (unboxable) + throw new Error ("Could not unbox " ~ value.type.toString ~ " as " ~ typeid(T).toString ~ "; however, unboxable says it would work."); + assert (!unboxable); + throw error; + } + + if (!unboxable) + throw new Error ("Unboxed " ~ value.type.toString ~ " as " ~ typeid(T).toString ~ "; however, unboxable says it should fail."); + return result; + } +} + +unittest +{ + class A { } + class B : A { } + struct SA { } + struct SB { } + + Box a, b; + + /* Call the function, catch UnboxException, return that it threw correctly. */ + bit fails(void delegate()func) + { + try func(); + catch (UnboxException error) + return true; + return false; + } + + /* Check that equals and comparison work properly. */ + a = box(0); + b = box(32); + assert (a != b); + assert (a == a); + assert (a < b); + + /* Check that toString works properly. */ + assert (b.toString == "32"); + + /* Assert that unboxable works. */ + assert (unboxable!(char[])(box("foobar"))); + + /* Assert that we can cast from int to byte. */ + assert (unboxTest!(byte)(b) == 32); + + /* Assert that we can cast from int to real. */ + assert (unboxTest!(real)(b) == 32.0L); + + /* Check that real works properly. */ + assert (unboxTest!(real)(box(32.45L)) == 32.45L); + + /* Assert that we cannot implicitly cast from real to int. */ + assert(fails(delegate void() { unboxTest!(int)(box(1.3)); })); + + /* Check that the unspecialized unbox template works. */ + assert(unboxTest!(char[])(box("foobar")) == "foobar"); + + /* Assert that complex works correctly. */ + assert(unboxTest!(cdouble)(box(1 + 2i)) == 1 + 2i); + + /* Assert that imaginary works correctly. */ + assert(unboxTest!(ireal)(box(45i)) == 45i); + + /* Create an array of boxes from arguments. */ + Box[] array = boxArray(16, "foobar", new Object); + + assert(array.length == 3); + assert(unboxTest!(int)(array[0]) == 16); + assert(unboxTest!(char[])(array[1]) == "foobar"); + assert(unboxTest!(Object)(array[2]) !== null); + + /* Convert the box array back into arguments. */ + TypeInfo[] array_types; + void* array_data; + + boxArrayToArguments(array, array_types, array_data); + assert (array_types.length == 3); + + /* Confirm the symmetry. */ + assert (boxArray(array_types, array_data) == array); + + /* Assert that we can cast from int to creal. */ + assert (unboxTest!(creal)(box(45)) == 45+0i); + + /* Assert that we can cast from idouble to creal. */ + assert (unboxTest!(creal)(box(45i)) == 0+45i); + + /* Assert that equality testing casts properly. */ + assert (box(1) == box(cast(byte)1)); + assert (box(cast(real)4) == box(4)); + assert (box(5) == box(5+0i)); + assert (box(0+4i) == box(4i)); + assert (box(8i) == box(0+8i)); + + /* Assert that comparisons cast properly. */ + assert (box(450) < box(451)); + assert (box(4) > box(3.0)); + assert (box(0+3i) < box(0+4i)); + + /* Assert that casting from bit to int works. */ + assert (1 == unboxTest!(int)(box(true))); + assert (box(1) == box(true)); + + /* Assert that unboxing to an object works properly. */ + assert (unboxTest!(B)(box(cast(A)new B)) !== null); + + /* Assert that illegal object casting fails properly. */ + assert (fails(delegate void() { unboxTest!(B)(box(new A)); })); + + /* Assert that we can unbox a null. */ + assert (unboxTest!(A)(box(cast(A)null)) is null); + assert (unboxTest!(A)(box(null)) is null); + + /* Unboxing null in various contexts. */ + assert (unboxTest!(char[])(box(null)) is null); + assert (unboxTest!(int*)(box(null)) is null); + + /* Assert that unboxing between pointer types fails. */ + int [1] p; + assert (fails(delegate void() { unboxTest!(char*)(box(p.ptr)); })); + + /* Assert that unboxing various types as void* does work. */ + assert (unboxTest!(void*)(box(p.ptr))); // int* + assert (unboxTest!(void*)(box(p))); // int[] + assert (unboxTest!(void*)(box(new A))); // Object + + /* Assert that we can't unbox an integer as bit. */ + assert (!unboxable!(bit) (box(4))); + + /* Assert that we can't unbox a struct as another struct. */ + SA sa; + assert (!unboxable!(SB)(box(sa))); +} diff -uNr gdc-0.11/d/phobos/std/c/stdio.d gdc-0.12/d/phobos/std/c/stdio.d --- gdc-0.11/d/phobos/std/c/stdio.d 2005-04-17 14:44:07.000000000 +0200 +++ gdc-0.12/d/phobos/std/c/stdio.d 2005-05-21 02:41:57.000000000 +0200 @@ -116,7 +116,8 @@ version (Win32) { version (GNU) { - private import gcc.mingwext; + // _NFILE is not defined anywhere + export FILE _iob[5]; } else { FILE _iob[_NFILE]; void function() _fcloseallp; @@ -152,19 +153,57 @@ } } -version (Win32) + +version (GNU_CBridge_Stdio) +{ + FILE * _d_gnu_cbridge_stdin; + FILE * _d_gnu_cbridge_stdout; + FILE * _d_gnu_cbridge_stderr; + + /* Call from dgccmain2. Can't use a static constructor here + because std.c.stdio is not compiled. */ + void _d_gnu_cbridge_init_stdio(); + + alias _d_gnu_cbridge_stdin stdin; + alias _d_gnu_cbridge_stdout stdout; + alias _d_gnu_cbridge_stderr stderr; +} +else version (Win32) { + // This works for DMD/DMC and MinGW/msvcrt const FILE *stdin = &_iob[0]; const FILE *stdout = &_iob[1]; const FILE *stderr = &_iob[2]; const FILE *stdaux = &_iob[3]; const FILE *stdprn = &_iob[4]; } -else version (GNU) +else version (aix) +{ + // 32- and 64-bit + FILE _iob[16]; + const FILE *stdin = &_iob[0]; + const FILE *stdout = &_iob[1]; + const FILE *stderr = &_iob[2]; +} +else version (darwin) { - const FILE * stdin = cast(FILE *) gcc.config.stdin; - const FILE * stdout = cast(FILE *) gcc.config.stdout; - const FILE * stderr = cast(FILE *) gcc.config.stderr; + version (GNU_BitsPerPointer32) + { + static assert(gcc.config.FILE_struct_size != 0); + FILE __sF[3]; + const FILE * stdin = &__sF[0]; + const FILE * stdout = &__sF[1]; + const FILE * stderr = &__sF[2]; + } + else version (GNU_BitsPerPointer64) + { + FILE *__stdinp; + FILE *__stdoutp; + FILE *__stderrp; + alias __stdinp stdin; + alias __stdoutp stdout; + alias __stderrp stderr; + } } else version (linux) { diff -uNr gdc-0.11/d/phobos/std/c/stdlib.d gdc-0.12/d/phobos/std/c/stdlib.d --- gdc-0.11/d/phobos/std/c/stdlib.d 2005-01-10 04:30:55.000000000 +0100 +++ gdc-0.12/d/phobos/std/c/stdlib.d 2005-05-19 02:15:50.000000000 +0200 @@ -61,11 +61,18 @@ int getErrno(); int setErrno(int); +const int ERANGE = 34; // on both Windows and linux + double atof(char *); int atoi(char *); int atol(char *); +float strtof(char *,char **); double strtod(char *,char **); -real strtold(char *,char **); + +//real strtold(char *,char **); +private import gcc.config; +alias gcc.config.cstrtold strtold; + long strtol(char *,char **,int); uint strtoul(char *,char **,int); long atoll(char *); diff -uNr gdc-0.11/d/phobos/std/c/unix/unix.d gdc-0.12/d/phobos/std/c/unix/unix.d --- gdc-0.11/d/phobos/std/c/unix/unix.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.12/d/phobos/std/c/unix/unix.d 2005-05-13 01:32:29.000000000 +0200 @@ -0,0 +1,28 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +module std.c.unix.unix; + +/* This module imports the unix module for the currect + target system. Currently, all targets can be + handled with the autoconf'd version. */ + +import gcc.configunix; + +// DMD linux.d has dirent.h declarations +import std.c.dirent; diff -uNr gdc-0.11/d/phobos/std/c/unix.d gdc-0.12/d/phobos/std/c/unix.d --- gdc-0.11/d/phobos/std/c/unix.d 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/phobos/std/c/unix.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,29 +0,0 @@ -/* GDC -- D front-end for GCC - Copyright (C) 2004 David Friedman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -module std.c.unix; - -/* This module imports the unix module for the currect - target system. Currently, all targets can be - handled with the autoconf'd version -*/ - -import gcc.configunix; - -// DMD linux.d has dirent.h declarations -import std.c.dirent; diff -uNr gdc-0.11/d/phobos/std/conv.d gdc-0.12/d/phobos/std/conv.d --- gdc-0.11/d/phobos/std/conv.d 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/phobos/std/conv.d 2005-05-28 01:57:05.000000000 +0200 @@ -3,15 +3,20 @@ // Copyright (c) 2002-2003 Digital Mars // All Rights Reserved // www.digitalmars.com +// Some parts contributed by David L. Davis // Conversion building blocks. These differ from the C equivalents by // checking for overflow and not allowing whitespace. module std.conv; -//debug=conv; // uncomment to turn on debugging printf's +private import std.string; // for atof(), toString() +private import std.c.stdlib; +private import std.math; // for fabs(), isnan() +private import std.stdio; // for writefln() and printf() +//debug=conv; // uncomment to turn on debugging printf's /************** Exceptions ****************/ @@ -831,4 +836,721 @@ } +/*************************************************************** + * Convert character string to float. + */ + +float toFloat(in char[] s) +{ + float f; + char* endptr; + char* sz; + + //writefln("toFloat('%s')", s); + version (aix) + s = toupper(s); + sz = toStringz(s); + if (std.ctype.isspace(*sz)) + goto Lerr; + + // BUG: should set __locale_decpoint to "." for DMC + + setErrno(0); + f = strtof(sz, &endptr); + if (getErrno() == ERANGE) + goto Lerr; + if (endptr && (endptr == sz || *endptr != 0)) + goto Lerr; + + return f; + + Lerr: + conv_error(s ~ " not representable as a float"); +} + +unittest +{ + debug( conv ) writefln( "conv.toFloat.unittest" ); + float f; + + f = toFloat( "123" ); + assert( f == 123f ); + f = toFloat( "+123" ); + assert( f == +123f ); + f = toFloat( "-123" ); + assert( f == -123f ); + f = toFloat( "123e+2" ); + assert( f == 123e+2f ); + + f = toFloat( "123e-2" ); + assert( f == 123e-2f ); + f = toFloat( "123." ); + assert( f == 123.f ); + f = toFloat( ".456" ); + assert( f == .456f ); + + // min and max + f = toFloat("1.17549e-38"); + assert(feq(cast(real)f, cast(real)1.17549e-38)); + assert(feq(cast(real)f, cast(real)float.min)); + f = toFloat("3.40282e+38"); + assert(toString(f) == toString(3.40282e+38)); + + // nan + f = toFloat("nan"); + assert(toString(f) == toString(float.nan)); +} + +/*************************************************************** + * Convert character string to double. + */ + +double toDouble(in char[] s) +{ + double f; + char* endptr; + char* sz; + + //writefln("toDouble('%s')", s); + version (aix) + s = toupper(s); + sz = toStringz(s); + if (std.ctype.isspace(*sz)) + goto Lerr; + + // BUG: should set __locale_decpoint to "." for DMC + + setErrno(0); + f = strtod(sz, &endptr); + if (getErrno() == ERANGE) + goto Lerr; + if (endptr && (endptr == sz || *endptr != 0)) + goto Lerr; + + return f; + + Lerr: + conv_error(s ~ " not representable as a double"); +} + +unittest +{ + debug( conv ) writefln( "conv.toDouble.unittest" ); + double d; + + d = toDouble( "123" ); + assert( d == 123 ); + d = toDouble( "+123" ); + assert( d == +123 ); + d = toDouble( "-123" ); + assert( d == -123 ); + d = toDouble( "123e2" ); + assert( d == 123e2); + d = toDouble( "123e-2" ); + assert( d == 123e-2 ); + d = toDouble( "123." ); + assert( d == 123. ); + d = toDouble( ".456" ); + assert( d == .456 ); + d = toDouble( "1.23456E+2" ); + assert( d == 1.23456E+2 ); + + // min and max + d = toDouble("2.22507e-308"); + assert(feq(cast(real)d, cast(real)2.22507e-308)); + assert(feq(cast(real)d, cast(real)double.min)); + d = toDouble("1.79769e+308"); + assert(toString(d) == toString(1.79769e+308)); + assert(toString(d) == toString(double.max)); + + // nan + d = toDouble("nan"); + assert(toString(d) == toString(double.nan)); + //assert(cast(real)d == cast(real)double.nan); +} + +/*************************************************************** + * Convert character string to real. + * Grammar: + * ['+'|'-'] digit {digit} + */ +real toReal(in char[] s) +{ + real f; + char* endptr; + char* sz; + + //writefln("toReal('%s')", s); + version (aix) + s = toupper(s); + sz = toStringz(s); + if (std.ctype.isspace(*sz)) + goto Lerr; + + // BUG: should set __locale_decpoint to "." for DMC + + setErrno(0); + f = strtold(sz, &endptr); + if (getErrno() == ERANGE) + goto Lerr; + if (endptr && (endptr == sz || *endptr != 0)) + goto Lerr; + + return f; + + Lerr: + conv_error(s ~ " not representable as a real"); +} + +unittest +{ + debug(conv) writefln("conv.toReal.unittest"); + real r; + + r = toReal("123"); + assert(r == 123L); + r = toReal("+123"); + assert(r == 123L); + r = toReal("-123"); + assert(r == -123L); + r = toReal("123e2"); + assert(feq(r, 123e2L)); + r = toReal("123e-2"); + assert(feq(r, 1.23L)); + r = toReal("123."); + assert(r == 123L); + r = toReal(".456"); + assert(r == .456L); + + r = toReal("1.23456e+2"); + assert(feq(r, 1.23456e+2L)); + r = toReal(toString(real.max / 2L)); + assert(toString(r) == toString(real.max / 2L)); + + // min and max + r = toReal(toString(real.min)); + assert(toString(r) == toString(real.min)); + r = toReal(toString(real.max)); + assert(toString(r) == toString(real.max)); + + // nan + r = toReal("nan"); + assert(toString(r) == toString(real.nan)); + //assert(r == real.nan); + + r = toReal(toString(real.nan)); + assert(toString(r) == toString(real.nan)); + //assert(r == real.nan); +} + +version (none) +{ /* These are removed for the moment because of concern about + * what to do about the 'i' suffix. Should it be there? + * Should it not? What about 'nan', should it be 'nani'? + * 'infinity' or 'infinityi'? + * Should it match what toString(ifloat) does with the 'i' suffix? + */ + +/*************************************************************** + * Convert character string to ifloat. + */ + +ifloat toIfloat(in char[] s) +{ + return toFloat(s) * 1.0i; +} + +unittest +{ + debug(conv) writefln("conv.toIfloat.unittest"); + ifloat ift; + + ift = toIfloat(toString(123.45)); + assert(toString(ift) == toString(123.45i)); + + ift = toIfloat(toString(456.77i)); + assert(toString(ift) == toString(456.77i)); + + // min and max + ift = toIfloat(toString(ifloat.min)); + assert(toString(ift) == toString(ifloat.min) ); + assert(feq(cast(ireal)ift, cast(ireal)ifloat.min)); + + ift = toIfloat(toString(ifloat.max)); + assert(toString(ift) == toString(ifloat.max)); + assert(feq(cast(ireal)ift, cast(ireal)ifloat.max)); + + // nan + ift = toIfloat("nani"); + assert(cast(real)ift == cast(real)ifloat.nan); + + ift = toIfloat(toString(ifloat.nan)); + assert(toString(ift) == toString(ifloat.nan)); + assert(feq(cast(ireal)ift, cast(ireal)ifloat.nan)); +} + +/*************************************************************** + * Convert character string to idouble. + */ + +idouble toIdouble(in char[] s) +{ + return toDouble(s) * 1.0i; +} + +unittest +{ + debug(conv) writefln("conv.toIdouble.unittest"); + idouble id; + + id = toIdouble(toString("123.45")); + assert(id == 123.45i); + + id = toIdouble(toString("123.45e+302i")); + assert(id == 123.45e+302i); + + // min and max + id = toIdouble(toString(idouble.min)); + assert(toString( id ) == toString(idouble.min)); + assert(feq(cast(ireal)id.re, cast(ireal)idouble.min.re)); + assert(feq(cast(ireal)id.im, cast(ireal)idouble.min.im)); + + id = toIdouble(toString(idouble.max)); + assert(toString(id) == toString(idouble.max)); + assert(feq(cast(ireal)id.re, cast(ireal)idouble.max.re)); + assert(feq(cast(ireal)id.im, cast(ireal)idouble.max.im)); + + // nan + id = toIdouble("nani"); + assert(cast(real)id == cast(real)idouble.nan); + + id = toIdouble(toString(idouble.nan)); + assert(toString(id) == toString(idouble.nan)); +} + +/*************************************************************** + * Convert character string to ireal. + */ + +ireal toIreal(in char[] s) +{ + return toReal(s) * 1.0i; +} + +unittest +{ + debug(conv) writefln("conv.toIreal.unittest"); + ireal ir; + + ir = toIreal(toString("123.45")); + assert(feq(cast(real)ir.re, cast(real)123.45i)); + + ir = toIreal(toString("123.45e+82i")); + assert(toString(ir) == toString(123.45e+82i)); + //assert(ir == 123.45e+82i); + + // min and max + ir = toIreal(toString(ireal.min)); + assert(toString(ir) == toString(ireal.min)); + assert(feq(cast(real)ir.re, cast(real)ireal.min.re)); + assert(feq(cast(real)ir.im, cast(real)ireal.min.im)); + + ir = toIreal(toString(ireal.max)); + assert(toString(ir) == toString(ireal.max)); + assert(feq(cast(real)ir.re, cast(real)ireal.max.re)); + //assert(feq(cast(real)ir.im, cast(real)ireal.max.im)); + + // nan + ir = toIreal("nani"); + assert(cast(real)ir == cast(real)ireal.nan); + + ir = toIreal(toString(ireal.nan)); + assert(toString(ir) == toString(ireal.nan)); +} + +/*************************************************************** + * Convert character string to cfloat. + * Grammar: + * ['+'|'-'] digit {digit} + */ +cfloat toCfloat(in char[] s) +{ + char[] s1; + char[] s2; + real r1; + real r2; + cfloat cf; + bit b = 0; + char* endptr; + + if (!s.length) + goto Lerr; + + b = getComplexStrings(s, s1, s2); + + if (!b) + goto Lerr; + + // atof(s1); + endptr = &s1[s1.length - 1]; + r1 = strtold(s1, &endptr); + + // atof(s2); + endptr = &s2[s2.length - 1]; + r2 = strtold(s2, &endptr); + + cf = cast(cfloat)(r1 + (r2 * 1.0i)); + + //writefln( "toCfloat() r1=%g, r2=%g, cf=%g, max=%g", + // r1, r2, cf, cfloat.max); + // Currently disabled due to a posted bug where a + // complex float greater-than compare to .max compares + // incorrectly. + //if (cf > cfloat.max) + // goto Loverflow; + + return cf; + + Loverflow: + conv_overflow(s); + + Lerr: + conv_error(s); + return cast(cfloat)0.0e-0+0i; +} + +unittest +{ + debug(conv) writefln("conv.toCfloat.unittest"); + cfloat cf; + + cf = toCfloat(toString("1.2345e-5+0i")); + assert(toString(cf) == toString(1.2345e-5+0i)); + assert(feq(cf, 1.2345e-5+0i)); + + // min and max + cf = toCfloat(toString(cfloat.min)); + assert(toString(cf) == toString(cfloat.min)); + + cf = toCfloat(toString(cfloat.max)); + assert(toString(cf) == toString(cfloat.max)); + + // nan ( nan+nani ) + cf = toCfloat("nani"); + //writefln("toCfloat() cf=%g, cf=\"%s\", nan=%s", + // cf, toString(cf), toString(cfloat.nan)); + assert(toString(cf) == toString(cfloat.nan)); + + cf = toCdouble("nan+nani"); + assert(toString(cf) == toString(cfloat.nan)); + + cf = toCfloat(toString(cfloat.nan)); + assert(toString(cf) == toString(cfloat.nan)); + assert(feq(cast(creal)cf, cast(creal)cfloat.nan)); +} + +/*************************************************************** + * Convert character string to cdouble. + * Grammar: + * ['+'|'-'] digit {digit} + */ +cdouble toCdouble(in char[] s) +{ + char[] s1; + char[] s2; + real r1; + real r2; + cdouble cd; + bit b = 0; + char* endptr; + + if (!s.length) + goto Lerr; + + b = getComplexStrings(s, s1, s2); + + if (!b) + goto Lerr; + + // atof(s1); + endptr = &s1[s1.length - 1]; + r1 = strtold(s1, &endptr); + + // atof(s2); + endptr = &s2[s2.length - 1]; + r2 = strtold(s2, &endptr); //atof(s2); + + cd = cast(cdouble)(r1 + (r2 * 1.0i)); + + //Disabled, waiting on a bug fix. + //if (cd > cdouble.max) //same problem the toCfloat() having + // goto Loverflow; + + return cd; + + Loverflow: + conv_overflow(s); + + Lerr: + conv_error(s); + return cast(cdouble)0.0e-0+0i; +} + +unittest +{ + debug(conv) writefln("conv.toCdouble.unittest"); + cdouble cd; + + cd = toCdouble(toString("1.2345e-5+0i")); + assert(toString( cd ) == toString(1.2345e-5+0i)); + assert(feq(cd, 1.2345e-5+0i)); + + // min and max + cd = toCdouble(toString(cdouble.min)); + assert(toString(cd) == toString(cdouble.min)); + assert(feq(cast(creal)cd, cast(creal)cdouble.min)); + + cd = toCdouble(toString(cdouble.max)); + assert(toString( cd ) == toString(cdouble.max)); + assert(feq(cast(creal)cd, cast(creal)cdouble.max)); + + // nan ( nan+nani ) + cd = toCdouble("nani"); + assert(toString(cd) == toString(cdouble.nan)); + + cd = toCdouble("nan+nani"); + assert(toString(cd) == toString(cdouble.nan)); + + cd = toCdouble(toString(cdouble.nan)); + assert(toString(cd) == toString(cdouble.nan)); + assert(feq(cast(creal)cd, cast(creal)cdouble.nan)); +} + +/*************************************************************** + * Convert character string to creal. + * Grammar: + * ['+'|'-'] digit {digit} + */ +creal toCreal(in char[] s) +{ + char[] s1; + char[] s2; + real r1; + real r2; + creal cr; + bit b = 0; + char* endptr; + + if (!s.length) + goto Lerr; + + b = getComplexStrings(s, s1, s2); + + if (!b) + goto Lerr; + + // atof(s1); + endptr = &s1[s1.length - 1]; + r1 = strtold(s1, &endptr); + + // atof(s2); + endptr = &s2[s2.length - 1]; + r2 = strtold(s2, &endptr); //atof(s2); + + //writefln("toCreal() r1=%g, r2=%g, s1=\"%s\", s2=\"%s\", nan=%g", + // r1, r2, s1, s2, creal.nan); + + if (s1 =="nan" && s2 == "nani") + cr = creal.nan; + else if (r2 != 0.0) + cr = cast(creal)(r1 + (r2 * 1.0i)); + else + cr = cast(creal)(r1 + 0.0i); + + return cr; + + Lerr: + conv_error(s); + return cast(creal)0.0e-0+0i; +} + +unittest +{ + debug(conv) writefln("conv.toCreal.unittest"); + creal cr; + + cr = toCreal(toString("1.2345e-5+0i")); + assert(toString(cr) == toString(1.2345e-5+0i)); + assert(feq(cr, 1.2345e-5+0i)); + + cr = toCreal(toString("0.0e-0+0i")); + assert(toString(cr) == toString(0.0e-0+0i)); + assert(cr == 0.0e-0+0i); + assert(feq(cr, 0.0e-0+0i)); + + cr = toCreal("123"); + assert(cr == 123); + + cr = toCreal("+5"); + assert(cr == 5); + + cr = toCreal("-78"); + assert(cr == -78); + + // min and max + cr = toCreal(toString(creal.min)); + assert(toString(cr) == toString(creal.min)); + assert(feq(cr, creal.min)); + + cr = toCreal(toString(creal.max)); + assert(toString(cr) == toString(creal.max)); + assert(feq(cr, creal.max)); + + // nan ( nan+nani ) + cr = toCreal("nani"); + assert(toString(cr) == toString(creal.nan)); + + cr = toCreal("nan+nani"); + assert(toString(cr) == toString(creal.nan)); + + cr = toCreal(toString(cdouble.nan)); + assert(toString(cr) == toString(creal.nan)); + assert(feq(cr, creal.nan)); +} + +} + +/*************************************************************** + * Splits a complex float (cfloat, cdouble, and creal) into two workable strings. + * Grammar: + * ['+'|'-'] string floating-point digit {digit} + */ +private bit getComplexStrings(in char[] s, out char[] s1, out char[] s2) +{ + int len = s.length; + + if (!len) + goto Lerr; + + // When "nan" or "nani" just return them. + if (s == "nan" || s == "nani" || s == "nan+nani") + { + s1 = "nan"; + s2 = "nani"; + return 1; + } + + // Split the original string out into two strings. + for (int i = 1; i < len; i++) + if ((s[i - 1] != 'e' && s[i - 1] != 'E') && s[i] == '+') + { + s1 = s[0..i]; + if (i + 1 < len - 1) + s2 = s[i + 1..len - 1]; + else + s2 = "0e+0i"; + + break; + } + + // Handle the case when there's only a single value + // to work with, and set the other string to zero. + if (!s1.length) + { + s1 = s; + s2 = "0e+0i"; + } + + //writefln( "getComplexStrings() s=\"%s\", s1=\"%s\", s2=\"%s\", len=%d", + // s, s1, s2, len ); + + return 1; + + Lerr: + // Display the original string in the error message. + conv_error("getComplexStrings() \"" ~ s ~ "\"" ~ " s1=\"" ~ s1 ~ "\"" ~ " s2=\"" ~ s2 ~ "\""); + return 0; +} + +// feq() functions now used only in unittesting + +/**************************************** + * Main function to compare reals with given precision + */ +private bit feq(in real rx, in real ry, in real precision) +{ + if (rx == ry) + return 1; + + if (isnan(rx)) + return cast(bit)isnan(ry); + + if (isnan(ry)) + return 0; + + return cast(bit)(fabs(rx - ry) <= precision); +} + +/**************************************** + * (Note: Copied here from std.math's mfeq() function for unittesting) + * Simple function to compare two floating point values + * to a specified precision. + * Returns: + * 1 match + * 0 nomatch + */ +private bit feq(in real r1, in real r2) +{ + if (r1 == r2) + return 1; + + if (isnan(r1)) + return cast(bit)isnan(r2); + + if (isnan(r2)) + return 0; + + return cast(bit)(feq(r1, r2, 0.000001L)); +} + +/**************************************** + * compare ireals with given precision + */ +private bit feq(in ireal r1, in ireal r2) +{ + real rx = cast(real)r1; + real ry = cast(real)r2; + + if (rx == ry) + return 1; + + if (isnan(rx)) + return cast(bit)isnan(ry); + + if (isnan(ry)) + return 0; + + return feq(rx, ry, 0.000001L); +} + +/**************************************** + * compare creals with given precision + */ +private bit feq(in creal r1, in creal r2) +{ + real r1a = fabs(cast(real)r1.re - cast(real)r2.re); + real r2b = fabs(cast(real)r1.im - cast(real)r2.im); + + if ((cast(real)r1.re == cast(real)r2.re) && + (cast(real)r1.im == cast(real)r2.im)) + return 1; + + if (isnan(r1a)) + return cast(bit)isnan(r2b); + + if (isnan(r2b)) + return 0; + + return feq(r1a, r2b, 0.000001L); +} diff -uNr gdc-0.11/d/phobos/std/date.d gdc-0.12/d/phobos/std/date.d --- gdc-0.11/d/phobos/std/date.d 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/phobos/std/date.d 2005-05-27 03:05:04.000000000 +0200 @@ -7,7 +7,7 @@ /* NOTE: This file has been patched from the original DMD distribution to work with the GDC compiler. - Modified by David Friedman, September 2004 + Modified by David Friedman, May 2005 */ module std.date; @@ -452,7 +452,7 @@ DateFromTime(t), cast(int)HourFromTime(t), cast(int)MinFromTime(t), cast(int)SecFromTime(t), sign, hr, mn, - cast(long)YearFromTime(t)); + /*cast(long)*/YearFromTime(t)); // Ensure no buggy buffer overflows //printf("len = %d, buffer.length = %d\n", len, buffer.length); @@ -505,7 +505,7 @@ &daystr[WeekDay(t) * 3], &monstr[MonthFromTime(t) * 3], DateFromTime(t), - cast(long)YearFromTime(t)); + /*cast(long)*/YearFromTime(t)); // Ensure no buggy buffer overflows assert(len < buffer.length); @@ -727,7 +727,7 @@ else version (GNU) { // for now, just copy linux - private import std.c.unix; + private import std.c.unix.unix; d_time getUTCtime() { timeval tv; diff -uNr gdc-0.11/d/phobos/std/file.d gdc-0.12/d/phobos/std/file.d --- gdc-0.11/d/phobos/std/file.d 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/phobos/std/file.d 2005-05-13 01:32:29.000000000 +0200 @@ -569,7 +569,7 @@ /* { version (Unix) { - private import std.c.unix; + private import std.c.unix.unix; } } */ @@ -581,8 +581,8 @@ version (Unix) { version (GNU) { - private import std.c.unix; - alias std.c.unix unix; + private import std.c.unix.unix; + alias std.c.unix.unix unix; } else version (linux) { private import std.c.linux.linux; alias std.c.linux.linux unix; diff -uNr gdc-0.11/d/phobos/std/math.d gdc-0.12/d/phobos/std/math.d --- gdc-0.11/d/phobos/std/math.d 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/phobos/std/math.d 2005-05-29 00:00:56.000000000 +0200 @@ -571,6 +571,9 @@ for (i = 0; i < vals.length; i++) { + if (i == 5 && real.sizeof <= double.sizeof) + continue; + real x = vals[i][0]; real y = vals[i][1]; real z = vals[i][2]; @@ -692,7 +695,10 @@ for (i = 0; i < vals.length; i++) { - real x = vals[i][0]; + if (i >= 6 && i <= 8 && real.sizeof <= double.sizeof) + continue; + + real x = vals[i][0]; real e = vals[i][1]; int exp = cast(int)vals[i][2]; int eptr; diff -uNr gdc-0.11/d/phobos/std/mmfile.d gdc-0.12/d/phobos/std/mmfile.d --- gdc-0.11/d/phobos/std/mmfile.d 2005-02-20 16:43:51.000000000 +0100 +++ gdc-0.12/d/phobos/std/mmfile.d 2005-05-13 01:32:29.000000000 +0200 @@ -42,7 +42,8 @@ } else version (Unix) { - private import std.c.unix; + private import std.c.unix.unix; + alias std.c.unix.unix unix; } else { @@ -227,26 +228,26 @@ { struct_stat statbuf; - fd = std.c.unix.open(namez, oflag, fmode); + fd = unix.open(namez, oflag, fmode); if (fd == -1) { printf("\topen error, errno = %d\n",getErrno()); errNo(); } - if (std.c.unix.fstat(fd, &statbuf)) + if (unix.fstat(fd, &statbuf)) { //printf("\tfstat error, errno = %d\n",getErrno()); - std.c.unix.close(fd); + unix.close(fd); errNo(); } if (prot & PROT_WRITE && size > statbuf.st_size) { // Need to make the file size bytes big - std.c.unix.lseek(fd, size - 1, SEEK_SET); + unix.lseek(fd, size - 1, SEEK_SET); char c = 0; - std.c.unix.write(fd, &c, 1); + unix.write(fd, &c, 1); } else if (prot & PROT_READ && size == 0) size = statbuf.st_size; @@ -264,7 +265,7 @@ * Closing it now avoids worrys about closing it during error * recovery. */ - if (fd != -1 && std.c.unix.close(fd) == -1) + if (fd != -1 && unix.close(fd) == -1) errNo(); if (p == MAP_FAILED) // in sys/mman.h diff -uNr gdc-0.11/d/phobos/std/perf.d gdc-0.12/d/phobos/std/perf.d --- gdc-0.11/d/phobos/std/perf.d 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/phobos/std/perf.d 2005-05-13 01:32:29.000000000 +0200 @@ -94,7 +94,7 @@ { version (GNU) { - private import std.c.unix; + private import std.c.unix.unix; } else version (linux) { extern (C) diff -uNr gdc-0.11/d/phobos/std/process.d gdc-0.12/d/phobos/std/process.d --- gdc-0.11/d/phobos/std/process.d 2005-02-20 16:43:51.000000000 +0100 +++ gdc-0.12/d/phobos/std/process.d 2005-05-21 02:41:57.000000000 +0200 @@ -55,6 +55,12 @@ /* ========================================================== */ +version (GNU_Need_spawnvp) +{ + // TODO: implement +} +else +{ int spawnvp(int mode, char[] pathname, char[][] argv) { char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); @@ -63,6 +69,7 @@ return std.c.process.spawnvp(mode, toStringz(pathname), argv_); } +} /* ========================================================== */ diff -uNr gdc-0.11/d/phobos/std/random.d gdc-0.12/d/phobos/std/random.d --- gdc-0.11/d/phobos/std/random.d 2005-04-10 18:24:35.000000000 +0200 +++ gdc-0.12/d/phobos/std/random.d 2005-05-19 02:15:50.000000000 +0200 @@ -18,14 +18,13 @@ extern(Windows) int QueryPerformanceCounter(ulong *count); } -else version (linux) +else version (GNU) { - private import std.c.linux.linux; + private import std.c.unix.unix; } -else version (GNU) +else version (linux) { - // TODO - private import std.c.unix; + private import std.c.linux.linux; } /* ===================== Random ========================= */ @@ -87,23 +86,7 @@ { QueryPerformanceCounter(&s); } - else version(linux) - { - // time.h - // sys/time.h - - timeval tv; - - if (gettimeofday(&tv, null)) - { // Some error happened - try time() instead - s = time(null); - } - else - { - s = (cast(long)tv.tv_sec << 32) + tv.tv_usec; - } - } - else version(GNU) + else version(Unix) { // time.h // sys/time.h diff -uNr gdc-0.11/d/phobos/std/recls.d gdc-0.12/d/phobos/std/recls.d --- gdc-0.11/d/phobos/std/recls.d 2004-12-19 18:51:04.000000000 +0100 +++ gdc-0.12/d/phobos/std/recls.d 2005-05-19 02:15:50.000000000 +0200 @@ -78,15 +78,14 @@ import std.string; -version (linux) +version (Unix) { - private import std.c.time; - private import std.c.linux.linux; + private import std.c.unix.unix; } -else version (GNU) +else version (linux) { - version (Unix) - private import std.c.unix; + private import std.c.time; + private import std.c.linux.linux; } //////////////////////////////////////////////////////////////////////////////// @@ -112,7 +111,7 @@ /// Win32 file size type alias ulong recls_filesize_t; } -else version(linux) +else version(Unix) { /// UNIX time type typedef time_t recls_time_t; @@ -120,7 +119,7 @@ /// UNIX file size type typedef off_t recls_filesize_t; } -else version(GNU) +else version(linux) { /// UNIX time type typedef time_t recls_time_t; diff -uNr gdc-0.11/d/phobos/std/socket.d gdc-0.12/d/phobos/std/socket.d --- gdc-0.11/d/phobos/std/socket.d 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/phobos/std/socket.d 2005-05-13 01:32:29.000000000 +0200 @@ -58,8 +58,8 @@ { version (Unix) { - private import std.c.unix; - private alias std.c.unix.timeval _ctimeval; + private import std.c.unix.unix; + private alias std.c.unix.unix.timeval _ctimeval; } typedef int32_t socket_t = -1; @@ -895,7 +895,7 @@ version (BsdSockets) version (GNU) { - private alias std.c.unix.linger __unix_linger; + private alias std.c.unix.unix.linger __unix_linger; static assert(linger.sizeof == __unix_linger.sizeof); } // D interface diff -uNr gdc-0.11/d/phobos/std/stream.d gdc-0.12/d/phobos/std/stream.d --- gdc-0.11/d/phobos/std/stream.d 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/phobos/std/stream.d 2005-05-25 03:51:33.000000000 +0200 @@ -175,6 +175,8 @@ int scanf(char[] format, ...); size_t available(); + bool eof(); + bool isOpen(); } // Interface for writable streams @@ -219,13 +221,13 @@ // writes a line, throws WriteException on error void writeLine(char[] s); - // writes a UNICODE line, throws WriteException on error + // writes a Unicode line, throws WriteException on error void writeLineW(wchar[] s); // writes a string, throws WriteException on error void writeString(char[] s); - // writes a UNICODE string, throws WriteException on error + // writes a Unicode string, throws WriteException on error void writeStringW(wchar[] s); // writes data to stream using vprintf() syntax, @@ -241,6 +243,10 @@ // writes data with trailing newline and returns self Stream writefln(...); + + void flush(); + void close(); + bool isOpen(); } // base class for all streams; not really abstract, @@ -254,17 +260,27 @@ bit seekable = false; protected bit isopen = true; + // flag that last readBlock resulted in eof + protected bit readEOF = false; + this() {} // reads block of data of specified size, // returns actual number of bytes read + // returning 0 indicates end-of-file abstract size_t readBlock(void* buffer, size_t size); // reads block of data of specified size, // throws ReadException on error void readExact(void* buffer, size_t size) { - size_t readsize = readBlock(buffer, size); - if (readsize != size) + for(;;) { + if (!size) return; + size_t readsize = readBlock(buffer, size); // return 0 on eof + if (readsize == 0) break; + buffer += readsize; + size -= readsize; + } + if (size != 0) throw new ReadException("not enough data in stream"); } @@ -471,6 +487,7 @@ // unget buffer private wchar[] unget; + final int ungetAvailable() { return unget.length > 1; } // reads and returns next character from the stream, // handles characters pushed back by ungetc() @@ -886,7 +903,7 @@ writeString("\n"); } - // writes a UNICODE line, throws WriteException on error + // writes a Unicode line, throws WriteException on error void writeLineW(wchar[] s) { writeStringW(s); version (Win32) @@ -902,7 +919,7 @@ writeExact(s, s.length); } - // writes a UNICODE string, throws WriteException on error + // writes a Unicode string, throws WriteException on error void writeStringW(wchar[] s) { writeExact(s, s.length * wchar.sizeof); } @@ -976,10 +993,18 @@ // copies all data from given stream into this one, // may throw ReadException or WriteException on failure void copyFrom(Stream s) { - ulong pos = s.position(); - s.position(0); - copyFrom(s, s.size()); - s.position(pos); + if (seekable) { + ulong pos = s.position(); + s.position(0); + copyFrom(s, s.size()); + s.position(pos); + } else { + ubyte[128] buf; + while (!s.eof()) { + size_t m = s.readBlock(buf, buf.length); + writeExact(buf, m); + } + } } // copies specified number of bytes from given stream into @@ -1015,16 +1040,25 @@ // returns size of stream ulong size() { + assertSeekable(); ulong pos = position(), result = seek(0, SeekPos.End); position(pos); return result; } // returns true if end of stream is reached, false otherwise - bit eof() { return position() == size(); } + bit eof() { + // for unseekable streams we only know the end when we read it + if (readEOF && !ungetAvailable()) + return true; + else if (seekable) + return position() == size(); + else + return false; + } // returns true if the stream is open - bit isOpen() { return isopen; } + bool isOpen() { return isopen; } // flush the buffer if writeable void flush() { @@ -1036,7 +1070,7 @@ void close() { if (isopen) flush(); - isopen = readable = writeable = seekable = false; + readEOF = isopen = readable = writeable = seekable = false; } // creates a string in memory containing copy of stream data @@ -1063,8 +1097,8 @@ result = new char[blockSize]; while ((rdlen = readBlock(&result[pos], blockSize)) > 0) { pos += rdlen; - result.length = result.length + blockSize; blockSize += rdlen; + result.length = result.length + blockSize; } } return result[0 .. pos]; @@ -1077,7 +1111,8 @@ ulong pos = position(); uint crc = init_crc32 (); position(0); - for (ulong i = 0; i < size(); i++) { + ulong len = size(); + for (ulong i = 0; i < len; i++) { ubyte c; read(c); crc = update_crc32(c, crc); @@ -1149,6 +1184,7 @@ readable = writeable = seekable = false; isopen = false; } + readEOF = false; streamPos = 0; bufferLen = bufferSourcePos = bufferCurPos = 0; bufferDirty = false; @@ -1165,45 +1201,49 @@ // reads block of data of specified size using any buffered data // returns actual number of bytes read - override size_t readBlock(void* result, size_t size) { + override size_t readBlock(void* result, size_t len) { + if (len == 0) return 0; + assertReadable(); - ubyte* buf = cast(ubyte*)result; + ubyte* outbuf = cast(ubyte*)result; size_t readsize = 0; - if (bufferCurPos + size <= bufferLen) { + if (bufferCurPos + len < bufferLen) { // buffer has all the data so copy it - buf[0 .. size] = buffer[bufferCurPos .. bufferCurPos+size]; - bufferCurPos += size; - readsize = size; + outbuf[0 .. len] = buffer[bufferCurPos .. bufferCurPos+len]; + bufferCurPos += len; + readsize = len; goto ExitRead; } readsize = bufferLen - bufferCurPos; if (readsize > 0) { // buffer has some data so copy what is left - buf[0 .. readsize] = buffer[bufferCurPos .. bufferLen]; - buf += readsize; + outbuf[0 .. readsize] = buffer[bufferCurPos .. bufferLen]; + outbuf += readsize; bufferCurPos += readsize; - size -= readsize; + len -= readsize; } flush(); - if (size >= buffer.length) { + if (len >= buffer.length) { // buffer can't hold the data so fill output buffer directly - size_t siz = s.readBlock(buf, size); + size_t siz = s.readBlock(outbuf, len); readsize += siz; streamPos += siz; + readEOF = siz == 0; } else { // read a new block into buffer bufferLen = s.readBlock(buffer, buffer.length); - if (bufferLen < size) size = bufferLen; - buf[0 .. size] = buffer[0 .. size]; + readEOF = bufferLen == 0; + if (bufferLen < len) len = bufferLen; + outbuf[0 .. len] = buffer[0 .. len]; bufferSourcePos = bufferLen; streamPos += bufferLen; - bufferCurPos = size; - readsize += size; + bufferCurPos = len; + readsize += len; } ExitRead: @@ -1212,7 +1252,7 @@ // write block of data of specified size // returns actual number of bytes written - override size_t writeBlock(void* result, size_t size) { + override size_t writeBlock(void* result, size_t len) { assertWriteable(); ubyte* buf = cast(ubyte*)result; @@ -1220,26 +1260,26 @@ if (bufferLen == 0) { // buffer is empty so fill it if possible - if ((size < buffer.length) && (readable)) { + if ((len < buffer.length) && (readable)) { // read in data if the buffer is currently empty bufferLen = s.readBlock(buffer,buffer.length); bufferSourcePos = bufferLen; streamPos += bufferLen; - } else if (size >= buffer.length) { + } else if (len >= buffer.length) { // buffer can't hold the data so write it directly and exit - writesize = s.writeBlock(buf,size); + writesize = s.writeBlock(buf,len); streamPos += writesize; goto ExitWrite; } } - if (bufferCurPos + size <= buffer.length) { + if (bufferCurPos + len <= buffer.length) { // buffer has space for all the data so copy it and exit - buffer[bufferCurPos .. bufferCurPos+size] = buf[0 .. size]; - bufferCurPos += size; + buffer[bufferCurPos .. bufferCurPos+len] = buf[0 .. len]; + bufferCurPos += len; bufferLen = bufferCurPos > bufferLen ? bufferCurPos : bufferLen; - writesize = size; + writesize = len; bufferDirty = true; goto ExitWrite; } @@ -1250,7 +1290,7 @@ buffer[bufferCurPos .. buffer.length] = buf[0 .. writesize]; bufferCurPos = bufferLen = buffer.length; buf += writesize; - size -= writesize; + len -= writesize; bufferDirty = true; } @@ -1259,7 +1299,7 @@ flush(); - writesize += writeBlock(buf,size); + writesize += writeBlock(buf,len); ExitWrite: return writesize; @@ -1276,6 +1316,7 @@ } else { bufferCurPos += offset; } + readEOF = false; return streamPos-bufferSourcePos+bufferCurPos; } @@ -1332,7 +1373,7 @@ } // template TreadLine(T) override char[] readLine(char[] inBuffer) { - if (unget.length > 1) + if (ungetAvailable()) return super.readLine(inBuffer); else return TreadLine!(char).readLine(inBuffer); @@ -1340,7 +1381,7 @@ alias Stream.readLine readLine; override wchar[] readLineW(wchar[] inBuffer) { - if (unget.length > 1) + if (ungetAvailable()) return super.readLineW(inBuffer); else return TreadLine!(wchar).readLine(inBuffer); @@ -1356,7 +1397,7 @@ body { super.flush(); if (writeable && bufferDirty) { - if (bufferSourcePos != 0) { + if (bufferSourcePos != 0 && seekable) { // move actual file pointer to front of buffer streamPos = s.seek(-bufferSourcePos, SeekPos.Current); } @@ -1366,8 +1407,8 @@ throw new WriteException("Unable to write to stream"); } } - long diff = bufferCurPos-bufferSourcePos; - if (diff != 0) { + long diff = cast(long)bufferCurPos-bufferSourcePos; + if (diff != 0 && seekable) { // move actual file pointer to current position streamPos = s.seek(diff, SeekPos.Current); } @@ -1377,28 +1418,26 @@ } // returns true if end of stream is reached, false otherwise - override bit eof() { + override bool eof() { if ((buffer.length == 0) || !readable) { return super.eof(); } - if (bufferCurPos == bufferLen) { - if ((bufferLen != buffer.length) && - (bufferLen != 0)) { - return true; - } - } - else + // some simple tests to avoid flushing + if (ungetAvailable() || bufferCurPos != bufferLen) return false; - size_t res = s.readBlock(buffer,buffer.length); - bufferSourcePos = bufferLen = res; + if (bufferLen == buffer.length) + flush(); + size_t res = s.readBlock(&buffer[bufferLen],buffer.length-bufferLen); + bufferSourcePos += res; + bufferLen += res; streamPos += res; - bufferCurPos = 0; - return res == 0; + readEOF = res == 0; + return readEOF; } // returns size of stream ulong size() { - flush(); + if (bufferDirty) flush(); return s.size(); } @@ -1436,7 +1475,7 @@ } } version (Unix) { - private import std.c.unix; + private import std.c.unix.unix; alias int HANDLE; } @@ -1498,7 +1537,7 @@ isopen = hFile != INVALID_HANDLE_VALUE; } version (Unix) { - hFile = std.c.unix.open(toStringz(filename), access | createMode, share); + hFile = std.c.unix.unix.open(toStringz(filename), access | createMode, share); isopen = hFile != -1; } if (!isopen) @@ -1573,7 +1612,7 @@ CloseHandle(hFile); hFile = null; } else version (Unix) { - std.c.unix.close(hFile); + std.c.unix.unix.close(hFile); hFile = -1; } } @@ -1586,6 +1625,7 @@ version (Win32) { // returns size of stream ulong size() { + assertSeekable(); uint sizehi; uint sizelow = GetFileSize(hFile,&sizehi); return (cast(ulong)sizehi << 32) + sizelow; @@ -1597,10 +1637,11 @@ version (Win32) { ReadFile(hFile, buffer, size, &size, null); } else version (Unix) { - size = std.c.unix.read(hFile, buffer, size); + size = std.c.unix.unix.read(hFile, buffer, size); if (size == -1) size = 0; } + readEOF = (size == 0); return size; } @@ -1609,7 +1650,7 @@ version (Win32) { WriteFile(hFile, buffer, size, &size, null); } else version (Unix) { - size = std.c.unix.write(hFile, buffer, size); + size = std.c.unix.unix.write(hFile, buffer, size); if (size == -1) size = 0; } @@ -1625,10 +1666,11 @@ throw new SeekException("unable to move file pointer"); ulong result = (cast(ulong)hi << 32) + low; } else version (Unix) { - ulong result = std.c.unix.lseek(hFile, offset, rel); + ulong result = std.c.unix.unix.lseek(hFile, offset, rel); if (result == 0xFFFFFFFF) throw new SeekException("unable to move file pointer"); } + readEOF = false; return result; } @@ -1763,12 +1805,17 @@ assert(file.position() == 18 + 13 + 4); // we must be at the end of file assert(file.eof()); + long oldsize = file.size(); file.close(); // no operations are allowed when file is closed assert(!file.readable && !file.writeable && !file.seekable); file.open("stream.$$$"); // should be ok to read assert(file.readable); + // test getc/ungetc and size() + char c1 = file.getc(); + file.ungetc(c1); + assert( file.size() == oldsize ); assert(!std.string.cmp(file.readLine(), "Testing stream.d:")); // jump over "Hello, " file.seek(7, SeekPos.Current); @@ -1997,7 +2044,7 @@ } override void flush() { super.flush(); s.flush(); } - override bit eof() { return s.eof(); } + override bool eof() { return s.eof() && !ungetAvailable(); } override ulong size() { return s.size(); } unittest { diff -uNr gdc-0.11/d/phobos/std/string.d gdc-0.12/d/phobos/std/string.d --- gdc-0.11/d/phobos/std/string.d 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/phobos/std/string.d 2005-05-19 02:15:50.000000000 +0200 @@ -73,13 +73,6 @@ int memicmp(char *, char *, uint); char *memchr(char *, char, uint); char* strerror(int); - version (GNU_Have_strtold) - real strtold(char*, char**); - else - { - extern (C) double strtod(char*, char**); - extern (D) real strtold(char* a, char** b) { return strtod(a, b); } - } int wcslen(wchar *); int wcscmp(wchar *, wchar *); diff -uNr gdc-0.11/d/phobos/std/thread.d gdc-0.12/d/phobos/std/thread.d --- gdc-0.11/d/phobos/std/thread.d 2005-04-10 18:24:35.000000000 +0200 +++ gdc-0.12/d/phobos/std/thread.d 2005-05-19 02:15:50.000000000 +0200 @@ -394,10 +394,18 @@ else version (GNU) { -private import std.c.unix; -private import gcc.threadsem; +private import std.c.unix.unix; private import gcc.builtins; +version (GNU_pthread_suspend) +{ + // nothing +} +else +{ + private import gcc.threadsem; +} + private extern (C) void* _d_gcc_query_stack_origin(); @@ -586,13 +594,21 @@ void pause() { if (state == TS.RUNNING) - { int result; - - result = pthread_kill(id, SIGUSR1); - if (result) - error("cannot pause"); + { + version (GNU_pthread_suspend) + { + if (pthread_suspend_np(id) != 0) + error("cannot pause"); + } else - flagSuspend.wait(); // wait for acknowledgement + { int result; + + result = pthread_kill(id, SIGUSR1); + if (result) + error("cannot pause"); + else + flagSuspend.wait(); // wait for acknowledgement + } } else error("cannot pause"); @@ -601,11 +617,19 @@ void resume() { if (state == TS.RUNNING) - { int result; + { + version (GNU_pthread_suspend) + { + if (pthread_continue_np(id) != 0) + error("cannot pause"); + } + else + { int result; - result = pthread_kill(id, SIGUSR2); - if (result) - error("cannot resume"); + result = pthread_kill(id, SIGUSR2); + if (result) + error("cannot resume"); + } } else error("cannot resume"); @@ -613,6 +637,24 @@ static void pauseAll() { + version (GNU_pthread_suspend) + { + if (nthreads > 1) + { + Thread tthis = getThis(); + + for (int i = 0; i < allThreadsDim; i++) + { Thread t; + + t = allThreads[i]; + if (t && t !== tthis && t.state == TS.RUNNING) + t.pause(); + } + } + } + else + { + if (nthreads > 1) { Thread tthis = getThis(); @@ -639,6 +681,8 @@ flagSuspend.wait(); } } + + } } static void resumeAll() @@ -669,7 +713,14 @@ static uint allThreadsDim; static Object threadLock; static Thread[/*_POSIX_THREAD_THREADS_MAX*/ 100] allThreads; - static Semaphore flagSuspend; + version (GNU_pthread_suspend) + { + // nothing + } + else + { + static Semaphore flagSuspend; + } TS state; int idx = -1; // index into allThreads[] @@ -741,25 +792,32 @@ allThreadsDim = 1; t.idx = 0; - /* Install signal handlers so we can suspend/resume threads - */ + version (GNU_pthread_suspend) + { + // nothing + } + else + { + /* Install signal handlers so we can suspend/resume threads + */ - int result; - sigaction_t sigact; - result = sigfillset(&sigact.sa_mask); - if (result) - goto Lfail; - sigact.sa_handler = &pauseHandler; - result = sigaction(SIGUSR1, &sigact, null); - if (result) - goto Lfail; - sigact.sa_handler = &resumeHandler; - result = sigaction(SIGUSR2, &sigact, null); - if (result) - goto Lfail; + int result; + sigaction_t sigact; + result = sigfillset(&sigact.sa_mask); + if (result) + goto Lfail; + sigact.sa_handler = &pauseHandler; + result = sigaction(SIGUSR1, &sigact, null); + if (result) + goto Lfail; + sigact.sa_handler = &resumeHandler; + result = sigaction(SIGUSR2, &sigact, null); + if (result) + goto Lfail; - if (! flagSuspend.create()) - goto Lfail; + if (! flagSuspend.create()) + goto Lfail; + } return; @@ -767,47 +825,55 @@ getThis().error("cannot initialize threads"); } - /********************************** - * This gets called when a thread gets SIGUSR1. - */ - - extern (C) static void pauseHandler(int sig) - { int result; - - // Save all registers on the stack so they'll be scanned by the GC - __builtin_unwind_init(); + version (GNU_pthread_suspend) + { + // nothing + } + else + { + /********************************** + * This gets called when a thread gets SIGUSR1. + */ - assert(sig == SIGUSR1); - // %% moved call to sem_post + extern (C) static void pauseHandler(int sig) + { int result; - sigset_t sigmask; - result = sigfillset(&sigmask); - assert(result == 0); - result = sigdelset(&sigmask, SIGUSR2); - assert(result == 0); + // Save all registers on the stack so they'll be scanned by the GC + __builtin_unwind_init(); - Thread t = getThis(); - t.stackTop = getESP(); - t.flags &= ~1; - flagSuspend.signal(); - while (1) - { - sigsuspend(&sigmask); // suspend until SIGUSR2 - if (t.flags & 1) // ensure it was resumeHandler() - break; + + assert(sig == SIGUSR1); + // %% moved call to sem_post + + sigset_t sigmask; + result = sigfillset(&sigmask); + assert(result == 0); + result = sigdelset(&sigmask, SIGUSR2); + assert(result == 0); + + Thread t = getThis(); + t.stackTop = getESP(); + t.flags &= ~1; + flagSuspend.signal(); + while (1) + { + sigsuspend(&sigmask); // suspend until SIGUSR2 + if (t.flags & 1) // ensure it was resumeHandler() + break; + } } - } - /********************************** - * This gets called when a thread gets SIGUSR2. - */ + /********************************** + * This gets called when a thread gets SIGUSR2. + */ - extern (C) static void resumeHandler(int sig) - { - Thread t = getThis(); + extern (C) static void resumeHandler(int sig) + { + Thread t = getThis(); - t.flags |= 1; + t.flags |= 1; + } } static void* getESP() diff -uNr gdc-0.11/d/phobos/std/typeinfo/ti_cdouble.d gdc-0.12/d/phobos/std/typeinfo/ti_cdouble.d --- gdc-0.11/d/phobos/std/typeinfo/ti_cdouble.d 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/phobos/std/typeinfo/ti_cdouble.d 2005-05-19 02:15:50.000000000 +0200 @@ -17,8 +17,19 @@ } static int _compare(cdouble f1, cdouble f2) - { - return f1 < f2 ? -1 : f1 > f2 ? 1 : 0; + { int result; + + if (f1.re < f2.re) + result = -1; + else if (f1.re > f2.re) + result = 1; + else if (f1.im < f2.im) + result = -1; + else if (f1.im > f2.im) + result = 1; + else + result = 0; + return result; } int equals(void *p1, void *p2) diff -uNr gdc-0.11/d/phobos/std/typeinfo/ti_cfloat.d gdc-0.12/d/phobos/std/typeinfo/ti_cfloat.d --- gdc-0.11/d/phobos/std/typeinfo/ti_cfloat.d 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/phobos/std/typeinfo/ti_cfloat.d 2005-05-19 02:15:50.000000000 +0200 @@ -16,8 +16,19 @@ } static int _compare(cfloat f1, cfloat f2) - { - return f1 < f2 ? -1 : f1 > f2 ? 1 : 0; + { int result; + + if (f1.re < f2.re) + result = -1; + else if (f1.re > f2.re) + result = 1; + else if (f1.im < f2.im) + result = -1; + else if (f1.im > f2.im) + result = 1; + else + result = 0; + return result; } int equals(void *p1, void *p2) diff -uNr gdc-0.11/d/phobos/std/typeinfo/ti_creal.d gdc-0.12/d/phobos/std/typeinfo/ti_creal.d --- gdc-0.11/d/phobos/std/typeinfo/ti_creal.d 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/phobos/std/typeinfo/ti_creal.d 2005-05-19 02:15:50.000000000 +0200 @@ -18,8 +18,19 @@ } static int _compare(creal f1, creal f2) - { - return f1 < f2 ? -1 : f1 > f2 ? 1 : 0; + { int result; + + if (f1.re < f2.re) + result = -1; + else if (f1.re > f2.re) + result = 1; + else if (f1.im < f2.im) + result = -1; + else if (f1.im > f2.im) + result = 1; + else + result = 0; + return result; } int equals(void *p1, void *p2) diff -uNr gdc-0.11/d/phobos/std/typeinfo/ti_void.d gdc-0.12/d/phobos/std/typeinfo/ti_void.d --- gdc-0.11/d/phobos/std/typeinfo/ti_void.d 2005-04-17 15:49:49.000000000 +0200 +++ gdc-0.12/d/phobos/std/typeinfo/ti_void.d 2005-05-21 19:29:57.000000000 +0200 @@ -13,27 +13,23 @@ int equals(void *p1, void *p2) { - assert(0); return *cast(byte *)p1 == *cast(byte *)p2; } int compare(void *p1, void *p2) { - assert(0); return *cast(byte *)p1 - *cast(byte *)p2; } int tsize() { - assert(0); - return byte.sizeof; + return void.sizeof; } void swap(void *p1, void *p2) { byte t; - assert(0); t = *cast(byte *)p1; *cast(byte *)p1 = *cast(byte *)p2; *cast(byte *)p2 = t; diff -uNr gdc-0.11/d/phobos/unittest.d gdc-0.12/d/phobos/unittest.d --- gdc-0.11/d/phobos/unittest.d 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/phobos/unittest.d 2005-05-21 19:29:57.000000000 +0200 @@ -43,6 +43,8 @@ import std.zlib; import std.md5; import std.stdio; +import std.conv; +import std.boxer; int main(char[][] args) { @@ -53,7 +55,8 @@ printf("test1\n"); fncharmatch('a', 'b'); // path isnan(1.0); // math - feq(1.0, 2.0); // math2 + std.math2.feq(1.0, 2.0); // math2 + std.conv.toDouble("1.0"); // std.conv printf("test1\n"); OutBuffer b = new OutBuffer(); // outbuffer std.ctype.tolower('A'); // ctype @@ -74,6 +77,7 @@ writefln("hello world!"); // std.format + Box abox; { creal c = 3.0 + 4.0i; c = sqrt(c); diff -uNr gdc-0.11/d/phobos/win32.mak gdc-0.12/d/phobos/win32.mak --- gdc-0.11/d/phobos/win32.mak 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/phobos/win32.mak 2005-05-21 19:29:57.000000000 +0200 @@ -65,6 +65,7 @@ Czlib.obj Dzlib.obj zip.obj process.obj registry.obj recls.obj \ socket.obj socketstream.obj loader.obj stdarg.obj format.obj stdio.obj \ perf.obj openrj.obj uni.obj winsock.obj oldsyserror.obj \ + errno.obj boxer.obj \ ti_Aa.obj ti_Ag.obj ti_C.obj ti_int.obj ti_char.obj \ ti_wchar.obj ti_uint.obj ti_short.obj ti_ushort.obj \ ti_byte.obj ti_ubyte.obj ti_long.obj ti_ulong.obj ti_ptr.obj \ @@ -89,7 +90,7 @@ std\intrinsic.d std\array.d std\switcherr.d std\syserror.d \ std\regexp.d std\random.d std\stream.d std\process.d std\recls.d \ std\socket.d std\socketstream.d std\loader.d std\stdarg.d std\format.d \ - std\stdio.d std\perf.d std\openrj.d std\uni.d + std\stdio.d std\perf.d std\openrj.d std\uni.d std\boxer.d SRC_STD_C= std\c\process.d std\c\stdlib.d std\c\time.d std\c\stdio.d \ std\c\math.d std\c\stdarg.d std\c\stddef.d @@ -363,6 +364,8 @@ make -f win32.mak zlib.lib cd ..\..\.. +errno.obj : errno.c + ### internal aaA.obj : internal\aaA.d @@ -433,6 +436,9 @@ base64.obj : std\base64.d $(DMD) -c $(DFLAGS) -inline std\base64.d +boxer.obj : std\boxer.d + $(DMD) -c $(DFLAGS) std\boxer.d + compiler.obj : std\compiler.d $(DMD) -c $(DFLAGS) std\compiler.d diff -uNr gdc-0.11/d/README gdc-0.12/d/README --- gdc-0.11/d/README 2005-04-28 06:27:54.000000000 +0200 +++ gdc-0.12/d/README 2005-05-29 00:00:56.000000000 +0200 @@ -1,8 +1,6 @@ -D Front End for GCC - Release 0.11 +D Front End for GCC - Release 0.12 -THIS IS AN UNSTABLE RELEASE - -Last update: April 27, 2005 +Last update: May 24, 2005 Supported Systems * GCC 3.3.x, 3.4.x @@ -11,6 +9,7 @@ * FreeBSD 5.2.1 * Cygwin * MinGW + * AIX (test on 5.1) Similar versions should work and other Unix platforms may work. Although the compiler will probably work on most 32-bit architectures, the D runtime @@ -18,13 +17,16 @@ Downloads - * Main package (Release 0.11) - http://home.earthlink.net/~dvdfrdmn/d/gdc-0.11.tgz - http://home.earthlink.net/~dvdfrdmn/d/gdc-0.11.tar.bz2 + * Main package (Release 0.12) + http://home.earthlink.net/~dvdfrdmn/d/gdc-0.12.tgz + http://home.earthlink.net/~dvdfrdmn/d/gdc-0.12.tar.bz2 * Build Instructions http://home.earthlink.net/~dvdfrdmn/d/INSTALL.html (or see INSTALL included in the main package) + * Patch for DMDScript 1.05 + http://home.earthlink.net/~dvdfrdmn/d/dmdscript-1.05-gdc.diff + Links * This Project -- http://home.earthlink.net/~dvdfrdmn/d @@ -40,55 +42,50 @@ e-mail: d3rdclsmail earthlink.net Status -What's Working - * Most features of Digital Mars D version 0.121 - -Gray Area / Known Issues +Known Issues * See the DStress (http://svn.kuehne.cn/dstress/www/dstress.html) - * Inline assembler has limitations. Namely, frame-relative addressing - (var[EBP]) does not work with optimization turned on. Also, mixing - assembler code with normal D code doesn't work as well as in DMD - page for known failing cases. Some Pentium IV instructions are missing. + page for known failing cases. * Debugging information may have a few problems. In any case, GDB does not support D name mangling. * Templates on Mac OS X. The stock compiler doesn't support one-only - linkage. Apple's version does support it, but this release will not - work with that. The current solution is to make template - instantiations private to each module that uses them. This should - work as long as the template does not have non-constant static data. - If you need more control over how emplates are emitted, use the - -femit-templates flag (see below). Note that you don't have to worry - about the stdarg templates as they are handled magically. + linkage. Apple's version does support it, but this release will + not work with that. Templates on Mac OS X. The stock compiler + doesn't support one-only linkage. Apple's version does support + it, but this release will not work with that. There are a + number of ways to deal with this. See the -femit-templates + option below. * Complex floating point operations may not work the same as DMD. - * The 80-bit real type is not supported on Mac OS X and is replaced by - the 64-bit double type. * Some math functions behave differently due to the 80-bit real issue and not being able to access x86 floating-point hardware. Some std.math unit tests will fail because of this. * In order to prevent nested synchronized statements from deadlocking, pthread recursive mutexes are used. This can cause starvation problems on Linux. I will try the "error-checking" type mutex. - * Volatile statements probably don't do the right thing. + * Volatile statements may not always do the right thing. * Delegates that refer to nested functions are not valid after the parent function returns. + * Because of a problem on AIX, the linker will pull in more + modules than needed (including recls.) + See: http://groups-beta.google.com/groups?hl=en&q=%22large+executables+on+AIX%22&qt_s=Search + * Some C libraries (Cygwin, MinGW, AIX) don't handle + floating-point formatting and parsing in a standard way. + Known Differences from DMD - * Private functions are not normally exported from the object - file. However, as of gdc 0.9, they are exported. This will - probably change again. * The type of _argptr in variadic functions is the target-specific - va_list type. It is not portable to assume this is a pointer. The - only portable way to use _argptr is the std.stdarg.va_arg template. + va_list type. The only portable way to use _argptr is the + std.stdarg.va_arg template. * In assembler code, direct access to parameters in naked functions works differently. Frame relative addressing through [ESP+4] does work the same way. * Currently, GDC uses the C calling convention for all functions except those declared extern (Windows). - * Module dependencies are handled differently. * GDC allows catches in try blocks. * pragma(lib) is not supported. + * Some targets do not have a distinct extended floating-point + type. On these targets, real and double are the same size. Inline Assembler Notes @@ -113,12 +110,14 @@ -fdeprecated -debug[=] -fdebug[=] +-g + -g -inline -finline-functions -I -I -L - -L + -Wl, -O -O3 without inlining (may not be equivalent) -od @@ -128,32 +127,38 @@ no equivalent; use the wrapper script -profile (see the GCC manual for profiling options) +-quiet + no equivalent -release -frelease -unittest -funittest -version= -fversion= +-w + -Wall Other options: -f[no-]bounds-check Controls array bounds checking --femit-templates[=full|private|none|auto] +-femit-templates[=normal|private|all|none|auto] -f[no-]emit-templates Controls whether or not template code is emitted. - "full" Emit templates, expecting multiple copies to be merged by + "normal" Emit templates, expecting multiple copies to be merged by linker. "private" Emit templates, but make them private to the translation unit. The executable will have multiple copies of code and data. + "all" Emit all template instances with public visibility. Do + this even if they would not normally be emitted. "none" Do not emit templates at all. - "auto" For targets that support templates, the "full" mode is + "auto" For targets that support templates, the "normal" mode is used. Otherwise, the "private" mode is used. "none" and -fno-emit-templates are synonyms. - "full" and -femit-templates are synonyms. + "auto" and -femit-templates are synonyms. -fall-sources For each source file on the command line, semantically process each @@ -167,6 +172,27 @@ Changes + * Fixes + o Various problems building MinGW in MSYS + o Mango "endless output" + o Build problems with gcc 3.4.1 + o Various problems revealed by dmdscript + o Error message now go to standard error + o DStress catch_01, catch_02, new_04, switch_19, throw_02, and others. + * Improvements + o Updated to DMD 0.125 + o New target: AIX + o GDC and DMD versions are reported with "gcc --version" + o Take advantage of DMD template improvements on + * Changes + o std.c.unix is now std.c.unix.unix + o The runtime library is now "libgphobos" to avoid conflicts with DMD. + o The dmd wrapper script... + + Is now named "gdmd". + + Looks for gdc in its own directory instead of searching the path + + Requires a comma after the "-q" option. + + 0.11: * Fixes diff -uNr gdc-0.11/d/root/access.c gdc-0.12/d/root/access.c --- gdc-0.11/d/root/access.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/access.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,361 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#include -#include -#include - -#include "root.h" -#include "mem.h" - -#include "enum.h" -#include "aggregate.h" -#include "init.h" -#include "attrib.h" -#include "scope.h" -#include "id.h" -#include "mtype.h" -#include "declaration.h" -#include "aggregate.h" -#include "expression.h" -#include "module.h" - -#define LOG 0 - -/* Code to do access checks - */ - -/**************************************** - * Return PROT access for Dsymbol smember in this class. - */ - -enum PROT ClassDeclaration::getAccess(Dsymbol *smember) -{ - enum PROT access_ret = PROTnone; - -#if LOG - printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n", - toChars(), smember->toChars()); -#endif - if (smember->toParent() == this) - { - access_ret = smember->prot(); - } - else - { - enum PROT access; - int i; - - for (i = 0; i < baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)baseclasses.data[i]; - - access = b->base->getAccess(smember); - switch (access) - { - case PROTnone: - break; - - case PROTprivate: - access = PROTnone; // private members of base class not accessible - break; - - case PROTpackage: - case PROTprotected: - case PROTpublic: - case PROTexport: - // If access is to be tightened - if (b->protection < access) - access = b->protection; - - // Pick path with loosest access - if (access > access_ret) - access_ret = access; - break; - - default: - assert(0); - } - } - } -#if LOG - printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n", - toChars(), smember->toChars(), access_ret); -#endif - return access_ret; -} - -/******************************************************** - * Helper function for ClassDeclaration::accessCheck() - * Returns: - * 0 no access - * 1 access - */ - -static int accessCheckX( - Dsymbol *smember, - Dsymbol *sfunc, - ClassDeclaration *cdthis, - ClassDeclaration *cdscope) -{ - assert(cdthis); - -#if 0 - printf("accessCheckX for %s.%s in function %s() in scope %s\n", - cdthis->toChars(), smember->toChars(), - sfunc ? sfunc->toChars() : "NULL", - cdscope ? cdscope->toChars() : "NULL"); -#endif - if (cdthis->hasPrivateAccess(sfunc) || - cdthis->isFriendOf(cdscope)) - { - if (smember->toParent() == cdthis) - return 1; - else - { - int i; - - for (i = 0; i < cdthis->baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; - enum PROT access; - - access = b->base->getAccess(smember); - if (access >= PROTprotected || - accessCheckX(smember, sfunc, b->base, cdscope) - ) - return 1; - - } - } - } - else - { - if (smember->toParent() != cdthis) - { - int i; - - for (i = 0; i < cdthis->baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; - - if (accessCheckX(smember, sfunc, b->base, cdscope)) - return 1; - } - } - } - return 0; -} - -/******************************* - * Do access check for member of this class, this class being the - * type of the 'this' pointer used to access smember. - */ - -void ClassDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember) -{ - int result; - - FuncDeclaration *f = sc->func; - ClassDeclaration *cdscope = sc->getClassScope(); - enum PROT access; - -#if LOG - printf("ClassDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n", - toChars(), smember->toChars(), - f ? f->toChars() : NULL, - cdscope ? cdscope->toChars() : NULL); -#endif - - if (!smember->isClassMember()) // if not a member of a class - { -#if LOG - printf("not a class member\n"); -#endif - return; // then it is accessible - } - - // BUG: should enable this check - //assert(smember->parent->isBaseOf(this, NULL)); - - if (smember->toParent() == this) - { enum PROT access = smember->prot(); - - result = access >= PROTpublic || - hasPrivateAccess(f) || - isFriendOf(cdscope) || - (access == PROTpackage && hasPackageAccess(sc)); -#if LOG - printf("result1 = %d\n", result); -#endif - } - else if ((access = this->getAccess(smember)) >= PROTpublic) - { - result = 1; -#if LOG - printf("result2 = %d\n", result); -#endif - } - else if (access == PROTpackage && hasPackageAccess(sc)) - { - result = 1; -#if LOG - printf("result3 = %d\n", result); -#endif - } - else - { - result = accessCheckX(smember, f, this, cdscope); -#if LOG - printf("result4 = %d\n", result); -#endif - } - if (!result) - { - error(loc, "member %s is not accessible", smember->toChars()); - } -} - -/**************************************** - * Determine if this is the same or friend of cd. - */ - -int ClassDeclaration::isFriendOf(ClassDeclaration *cd) -{ -#if LOG - printf("ClassDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null"); -#endif - if (this == cd) - return 1; - - // Friends if both are in the same module - if (cd && toParent() == cd->toParent()) - { -#if LOG - printf("\tin same module\n"); -#endif - return 1; - } - - if (cd && cd->toParent() == this) - { -#if LOG - printf("\tcd is nested in this\n"); -#endif - return 1; - } - - -#if LOG - printf("\tnot friend\n"); -#endif - return 0; -} - -/**************************************** - * Determine if scope sc has package level access to 'this'. - */ - -int ClassDeclaration::hasPackageAccess(Scope *sc) -{ -#if LOG - printf("ClassDeclaration::hasPackageAccess(this = '%s', sc = '%p')\n", toChars(), sc); -#endif - Dsymbol *mthis; - - for (mthis = this; mthis; mthis = mthis->parent) - { - if (mthis->isPackage() && !mthis->isModule()) - break; - } -#if LOG - if (mthis) - printf("\tthis is in package '%s'\n", mthis->toChars()); -#endif - - if (mthis && mthis == sc->module->parent) - { -#if LOG - printf("\t'this' is in same package as cd\n"); -#endif - return 1; - } - - -#if LOG - printf("\tno package access\n"); -#endif - return 0; -} - -/********************************** - * Determine if smember has access to private members of this class. - */ - -int ClassDeclaration::hasPrivateAccess(Dsymbol *smember) -{ - if (smember) - { ClassDeclaration *cd = smember->isClassMember(); - -#if LOG - printf("ClassDeclaration::hasPrivateAccess(class %s, member %s)\n", - toChars(), smember->toChars()); -#endif - - if (this == cd) // smember is a member of this class - { -#if LOG - printf("\tyes 1\n"); -#endif - return 1; // so we get private access - } - - // If both are members of the same module, grant access - while (1) - { Dsymbol *sp = smember->toParent(); - if (sp->isFuncDeclaration() && smember->isFuncDeclaration()) - smember = sp; - else - break; - } - if (!cd && toParent() == smember->toParent()) - { -#if LOG - printf("\tyes 2\n"); -#endif - return 1; - } - } -#if LOG - printf("\tno\n"); -#endif - return 0; -} - -/**************************************** - * Check access to d for expression e.d - */ - -void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d) -{ - if (e->type->ty == Tclass) - { // Do access check - ClassDeclaration *cd; - - cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym); -#if 1 - if (e->op == TOKsuper) - { ClassDeclaration *cd2; - - cd2 = sc->func->toParent()->isClassDeclaration(); - if (cd2) - cd = cd2; - } -#endif - cd->accessCheck(loc, sc, d); - } -} diff -uNr gdc-0.11/d/root/aggregate.h gdc-0.12/d/root/aggregate.h --- gdc-0.11/d/root/aggregate.h 2005-04-17 14:44:07.000000000 +0200 +++ gdc-0.12/d/root/aggregate.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,225 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, October 2004 -*/ - -#ifndef DMD_AGGREGATE_H -#define DMD_AGGREGATE_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" -#include "dsymbol.h" - -struct Identifier; -struct Type; -struct TypeFunction; -struct Expression; -struct FuncDeclaration; -struct CtorDeclaration; -struct DtorDeclaration; -struct InvariantDeclaration; -struct NewDeclaration; -struct DeleteDeclaration; -struct InterfaceDeclaration; -struct ClassInfoDeclaration; -struct VarDeclaration; -struct dt_t; - - -struct AggregateDeclaration : ScopeDsymbol -{ - Type *type; - Type *handle; // 'this' type - unsigned structsize; // size of struct - unsigned alignsize; // size of struct for alignment purposes - unsigned structalign; // struct member alignment in effect - Array fields; // VarDeclaration fields - unsigned sizeok; // set when structsize contains valid data - // 0: no size - // 1: size is correct - // 2: cannot determine size; fwd referenced - int isdeprecated; // !=0 if deprecated - Scope *scope; // !=NULL means context to use - - // Special member functions - InvariantDeclaration *inv; // invariant - NewDeclaration *aggNew; // allocator - DeleteDeclaration *aggDelete; // deallocator -#ifdef IN_GCC - - Array methods; // flat list of all methods for debug information -#endif - - - AggregateDeclaration(Loc loc, Identifier *id); - void semantic2(Scope *sc); - void semantic3(Scope *sc); - void inlineScan(); - unsigned size(Loc loc); - static void alignmember(unsigned salign, unsigned size, unsigned *poffset); - Type *getType(); - void addField(Scope *sc, VarDeclaration *v); - int isDeprecated(); // is aggregate deprecated? - - // Back end - Symbol *stag; // tag symbol for debug data - Symbol *sinit; - Symbol *toInitializer(); - - AggregateDeclaration *isAggregateDeclaration() { return this; } -}; - -struct AnonymousAggregateDeclaration : AggregateDeclaration -{ - AnonymousAggregateDeclaration() - : AggregateDeclaration(0, NULL) - { - } - - AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; } -}; - -struct StructDeclaration : AggregateDeclaration -{ - int zeroInit; // !=0 if initialize with 0 fill - - StructDeclaration(Loc loc, Identifier *id); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - char *mangle(); - char *kind(); - - void toObjFile(); // compile to .obj file - void toDt(dt_t **pdt); - void toDebug(); // to symbolic debug info - - StructDeclaration *isStructDeclaration() { return this; } -}; - -struct UnionDeclaration : StructDeclaration -{ - UnionDeclaration(Loc loc, Identifier *id); - Dsymbol *syntaxCopy(Dsymbol *s); - char *kind(); - - UnionDeclaration *isUnionDeclaration() { return this; } -}; - -struct BaseClass -{ - Type *type; // (before semantic processing) - enum PROT protection; // protection for the base interface - - ClassDeclaration *base; - int offset; // 'this' pointer offset - Array vtbl; // for interfaces: Array of FuncDeclaration's - // making up the vtbl[] - - int baseInterfaces_dim; - BaseClass *baseInterfaces; // if BaseClass is an interface, these - // are a copy of the InterfaceDeclaration::interfaces - - BaseClass(); - BaseClass(Type *type, enum PROT protection); - - int fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance); - void copyBaseInterfaces(Array *); -}; - -#define CLASSINFO_SIZE 0x3C // value of ClassInfo.size - -struct ClassDeclaration : AggregateDeclaration -{ - static ClassDeclaration *classinfo; - - ClassDeclaration *baseClass; // NULL only if this is Object - CtorDeclaration *ctor; - DtorDeclaration *dtor; - FuncDeclaration *staticCtor; - FuncDeclaration *staticDtor; - Array vtbl; // Array of FuncDeclaration's making up the vtbl[] - - Array baseclasses; // Array of BaseClass's; first is super, - // rest are Interface's - - int interfaces_dim; - BaseClass **interfaces; // interfaces[interfaces_dim] for this class - // (does not include baseClass) - - Array *vtblInterfaces; // array of base interfaces that have - // their own vtbl[] - - ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration - int com; // !=0 if this is a COM class - int isauto; // !=0 if this is an auto class - int isabstract; // !=0 if abstract class - - ClassDeclaration(Loc loc, Identifier *id, Array *baseclasses); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - - #define OFFSET_RUNTIME 0x76543210 - virtual int isBaseOf(ClassDeclaration *cd, int *poffset); - - Dsymbol *search(Identifier *ident, int flags); - FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); - void interfaceSemantic(Scope *sc); - int isCOMclass(); - int isAbstract(); - virtual int vtblOffset(); - char *kind(); - char *mangle(); - - PROT getAccess(Dsymbol *smember); // determine access to smember - int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class? - void accessCheck(Loc loc, Scope *sc, Dsymbol *smember); - int isFriendOf(ClassDeclaration *cd); - int hasPackageAccess(Scope *sc); - void addLocalClass(Array *); - - // Back end - void toObjFile(); // compile to .obj file - void toDebug(); - unsigned baseVtblOffset(BaseClass *bc); - Symbol *toSymbol(); - Symbol *toVtblSymbol(); - void toDt(dt_t **pdt); - void toDt2(dt_t **pdt, ClassDeclaration *cd); - - Symbol *vtblsym; - - ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } -}; - -struct InterfaceDeclaration : ClassDeclaration -{ - InterfaceDeclaration(Loc loc, Identifier *id, Array *baseclasses); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - int isBaseOf(ClassDeclaration *cd, int *poffset); - int isBaseOf(BaseClass *bc, int *poffset); - char *kind(); - int vtblOffset(); - - void toObjFile(); // compile to .obj file - Symbol *toSymbol(); - - InterfaceDeclaration *isInterfaceDeclaration() { return this; } -}; - -#endif /* DMD_AGGREGATE_H */ diff -uNr gdc-0.11/d/root/array.c gdc-0.12/d/root/array.c --- gdc-0.11/d/root/array.c 2005-04-12 05:16:27.000000000 +0200 +++ gdc-0.12/d/root/array.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,225 +0,0 @@ - -// Copyright (c) 1999-2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include -#include -#include -#include -#ifndef alloca -#include -#endif - -#if _MSC_VER -#include -#endif - -#if _WIN32 -#include -#endif - -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#endif - -#include "port.h" -#include "root.h" -#include "dchar.h" -#include "mem.h" - - -/********************************* Array ****************************/ - -Array::Array() -{ - data = NULL; - dim = 0; - allocdim = 0; -} - -Array::~Array() -{ - mem.free(data); -} - -void Array::mark() -{ unsigned u; - - mem.mark(data); - for (u = 0; u < dim; u++) - mem.mark(data[u]); // BUG: what if arrays of Object's? -} - -void Array::reserve(unsigned nentries) -{ - //printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); - if (allocdim - dim < nentries) - { - allocdim = dim + nentries; - data = (void **)mem.realloc(data, allocdim * sizeof(*data)); - } -} - -void Array::setDim(unsigned newdim) -{ - if (dim < newdim) - { - reserve(newdim - dim); - } - dim = newdim; -} - -void Array::fixDim() -{ - if (dim != allocdim) - { data = (void **)mem.realloc(data, dim * sizeof(*data)); - allocdim = dim; - } -} - -void Array::push(void *ptr) -{ - reserve(1); - data[dim++] = ptr; -} - -void *Array::pop() -{ - return data[--dim]; -} - -void Array::shift(void *ptr) -{ - reserve(1); - memmove(data + 1, data, dim * sizeof(*data)); - data[0] = ptr; - dim++; -} - -void Array::insert(unsigned index, void *ptr) -{ - reserve(1); - memmove(data + index + 1, data + index, (dim - index) * sizeof(*data)); - data[index] = ptr; - dim++; -} - - -void Array::insert(unsigned index, Array *a) -{ - if (a) - { unsigned d; - - d = a->dim; - reserve(d); - if (dim != index) - memmove(data + index + d, data + index, (dim - index) * sizeof(*data)); - memcpy(data + index, a->data, d * sizeof(*data)); - dim += d; - } -} - - -/*********************************** - * Append array a to this array. - */ - -void Array::append(Array *a) -{ - insert(dim, a); -} - -void Array::remove(unsigned i) -{ - memcpy(data + i, data + i + 1, (dim - i) * sizeof(data[0])); - dim--; -} - -char *Array::toChars() -{ - unsigned len; - unsigned u; - char **buf; - char *str; - char *p; - - buf = (char **)alloca(dim * sizeof(char *)); - len = 2; - for (u = 0; u < dim; u++) - { - buf[u] = ((Object *)data[u])->toChars(); - len += strlen(buf[u]) + 1; - } - str = (char *)mem.malloc(len); - - str[0] = '['; - p = str + 1; - for (u = 0; u < dim; u++) - { - if (u) - *p++ = ','; - len = strlen(buf[u]); - memcpy(p,buf[u],len); - p += len; - } - *p++ = ']'; - *p = 0; - return str; -} - -void Array::zero() -{ - memset(data,0,dim * sizeof(data[0])); -} - -void *Array::tos() -{ - return dim ? data[dim - 1] : NULL; -} - -int -#if _WIN32 - __cdecl -#endif - Array_sort_compare(const void *x, const void *y) -{ - Object *ox = *(Object **)x; - Object *oy = *(Object **)y; - - return ox->compare(oy); -} - -void Array::sort() -{ - if (dim) - { - qsort(data, dim, sizeof(Object *), Array_sort_compare); - } -} - -Array *Array::copy() -{ - Array *a = new Array(); - - a->setDim(dim); - memcpy(a->data, data, dim * sizeof(void *)); - return a; -} - diff -uNr gdc-0.11/d/root/artistic.txt gdc-0.12/d/root/artistic.txt --- gdc-0.11/d/root/artistic.txt 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/artistic.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,117 +0,0 @@ - - - - - The "Artistic License" - - Preamble - -The intent of this document is to state the conditions under which a -Package may be copied, such that the Copyright Holder maintains some -semblance of artistic control over the development of the package, -while giving the users of the package the right to use and distribute -the Package in a more-or-less customary fashion, plus the right to make -reasonable modifications. - -Definitions: - - "Package" refers to the collection of files distributed by the - Copyright Holder, and derivatives of that collection of files - created through textual modification. - - "Standard Version" refers to such a Package if it has not been - modified, or has been modified in accordance with the wishes - of the Copyright Holder as specified below. - - "Copyright Holder" is whoever is named in the copyright or - copyrights for the package. - - "You" is you, if you're thinking about copying or distributing - this Package. - - "Reasonable copying fee" is whatever you can justify on the - basis of media cost, duplication charges, time of people involved, - and so on. (You will not be required to justify it to the - Copyright Holder, but only to the computing community at large - as a market that must bear the fee.) - - "Freely Available" means that no fee is charged for the item - itself, though there may be fees involved in handling the item. - It also means that recipients of the item may redistribute it - under the same conditions they received it. - -1. You may make and give away verbatim copies of the source form of the -Standard Version of this Package without restriction, provided that you -duplicate all of the original copyright notices and associated disclaimers. - -2. You may apply bug fixes, portability fixes and other modifications -derived from the Public Domain or from the Copyright Holder. A Package -modified in such a way shall still be considered the Standard Version. - -3. You may otherwise modify your copy of this Package in any way, provided -that you insert a prominent notice in each changed file stating how and -when you changed that file, and provided that you do at least ONE of the -following: - - a) place your modifications in the Public Domain or otherwise make them - Freely Available, such as by posting said modifications to Usenet or - an equivalent medium, or placing the modifications on a major archive - site such as uunet.uu.net, or by allowing the Copyright Holder to include - your modifications in the Standard Version of the Package. - - b) use the modified Package only within your corporation or organization. - - c) rename any non-standard executables so the names do not conflict - with standard executables, which must also be provided, and provide - a separate manual page for each non-standard executable that clearly - documents how it differs from the Standard Version. - - d) make other distribution arrangements with the Copyright Holder. - -4. You may distribute the programs of this Package in object code or -executable form, provided that you do at least ONE of the following: - - a) distribute a Standard Version of the executables and library files, - together with instructions (in the manual page or equivalent) on where - to get the Standard Version. - - b) accompany the distribution with the machine-readable source of - the Package with your modifications. - - c) give non-standard executables non-standard names, and clearly - document the differences in manual pages (or equivalent), together - with instructions on where to get the Standard Version. - - d) make other distribution arrangements with the Copyright Holder. - -5. You may charge a reasonable copying fee for any distribution of this -Package. You may charge any fee you choose for support of this -Package. You may not charge a fee for this Package itself. However, -you may distribute this Package in aggregate with other (possibly -commercial) programs as part of a larger (possibly commercial) software -distribution provided that you do not advertise this Package as a -product of your own. You may embed this Package's interpreter within -an executable of yours (by linking); this shall be construed as a mere -form of aggregation, provided that the complete Standard Version of the -interpreter is so embedded. - -6. The source code and object code supplied as input to or produced as -output from the programs of this Package do not automatically fall -under the copyright of this Package, but belong to whoever generated -them, and may be sold commercially, and may be aggregated with this -Package. - -7. Aggregation of this Package with a commercial distribution is always -permitted provided that the use of this Package is embedded; that is, -when no overt attempt is made to make this Package's interfaces visible -to the end user of the commercial distribution. Such use shall not be -construed as a distribution of this Package. - -8. The name of the Copyright Holder may not be used to endorse or promote -products derived from this software without specific prior written permission. - -9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - The End diff -uNr gdc-0.11/d/root/attrib.c gdc-0.12/d/root/attrib.c --- gdc-0.11/d/root/attrib.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/attrib.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,768 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include - -#ifdef IN_GCC -#include "../root/mem.h" -#elif _WIN32 -#include "mem.h" -#elif linux -#include "../root/mem.h" -#endif - -#include "init.h" -#include "declaration.h" -#include "attrib.h" -#include "debcond.h" -#include "scope.h" -#include "id.h" -#include "expression.h" -#include "dsymbol.h" -#include "aggregate.h" - -extern void obj_includelib(char *name); - -/********************************* AttribDeclaration ****************************/ - -AttribDeclaration::AttribDeclaration(Array *decl) - : Dsymbol() -{ - this->decl = decl; -} - -Array *AttribDeclaration::include() -{ - return decl; -} - -void AttribDeclaration::addMember(ScopeDsymbol *sd) -{ - unsigned i; - Array *d = include(); - - if (d) - { - for (i = 0; i < d->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)d->data[i]; - s->addMember(sd); - } - } -} - -void AttribDeclaration::semantic(Scope *sc) -{ - Array *d = include(); - - //printf("\tAttribDeclaration::semantic '%s'\n",toChars()); - if (d) - { - for (unsigned i = 0; i < d->dim; i++) - { - Dsymbol *s = (Dsymbol *)d->data[i]; - - s->semantic(sc); - } - } -} - -void AttribDeclaration::semantic2(Scope *sc) -{ - unsigned i; - Array *d = include(); - - if (d) - { - for (i = 0; i < d->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)d->data[i]; - s->semantic2(sc); - } - } -} - -void AttribDeclaration::semantic3(Scope *sc) -{ - unsigned i; - Array *d = include(); - - if (d) - { - for (i = 0; i < d->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)d->data[i]; - s->semantic3(sc); - } - } -} - -void AttribDeclaration::inlineScan() -{ - unsigned i; - Array *d = include(); - - if (d) - { - for (i = 0; i < d->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)d->data[i]; - //printf("AttribDeclaration::inlineScan %s\n", s->toChars()); - s->inlineScan(); - } - } -} - -void AttribDeclaration::toObjFile() -{ - unsigned i; - Array *d = include(); - - if (d) - { - for (i = 0; i < d->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)d->data[i]; - s->toObjFile(); - } - } -} - -int AttribDeclaration::cvMember(unsigned char *p) -{ - unsigned i; - int nwritten = 0; - int n; - Array *d = include(); - - if (d) - { - for (i = 0; i < d->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)d->data[i]; - n = s->cvMember(p); - if (p) - p += n; - nwritten += n; - } - } - return nwritten; -} - -char *AttribDeclaration::kind() -{ - return "attribute"; -} - -Dsymbol *AttribDeclaration::oneMember() -{ Dsymbol *s; - Array *d = include(); - - if (d && d->dim == 1) - { s = (Dsymbol *)d->data[0]; - return s->oneMember(); - } - return NULL; -} - -/**************************************** - */ - -void AttribDeclaration::addLocalClass(Array *aclasses) -{ unsigned i; - Array *d = include(); - - if (d) - { - for (i = 0; i < d->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)d->data[i]; - s->addLocalClass(aclasses); - } - } -} - - -void AttribDeclaration::toCBuffer(OutBuffer *buf) -{ - if (decl) - { - buf->writenl(); - buf->writeByte('{'); - buf->writenl(); - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - buf->writestring(" "); - s->toCBuffer(buf); - } - buf->writeByte('}'); - } - else - buf->writeByte(':'); - buf->writenl(); -} - -/************************* StorageClassDeclaration ****************************/ - -StorageClassDeclaration::StorageClassDeclaration(unsigned stc, Array *decl) - : AttribDeclaration(decl) -{ - this->stc = stc; -} - -Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s) -{ - StorageClassDeclaration *scd; - - assert(!s); - scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl)); - return scd; -} - -void StorageClassDeclaration::semantic(Scope *sc) -{ - if (decl) - { unsigned stc_save = sc->stc; - - if (stc & (STCauto | STCstatic | STCextern)) - sc->stc &= ~(STCauto | STCstatic | STCextern); - sc->stc |= stc; - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic(sc); - } - sc->stc = stc_save; - } - else - sc->stc = stc; -} - -void StorageClassDeclaration::toCBuffer(OutBuffer *buf) -{ - buf->writestring("BUG: storage class goes here"); // BUG - AttribDeclaration::toCBuffer(buf); -} - -/********************************* LinkDeclaration ****************************/ - -LinkDeclaration::LinkDeclaration(enum LINK p, Array *decl) - : AttribDeclaration(decl) -{ - //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl); - linkage = p; -} - -Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s) -{ - LinkDeclaration *ld; - - assert(!s); - ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl)); - return ld; -} - -void LinkDeclaration::semantic(Scope *sc) -{ - //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl); - if (decl) - { enum LINK linkage_save = sc->linkage; - - sc->linkage = linkage; - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic(sc); - } - sc->linkage = linkage_save; - } - else - { - sc->linkage = linkage; - } -} - -void LinkDeclaration::semantic3(Scope *sc) -{ - //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl); - if (decl) - { enum LINK linkage_save = sc->linkage; - - sc->linkage = linkage; - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic3(sc); - } - sc->linkage = linkage_save; - } - else - { - sc->linkage = linkage; - } -} - -void LinkDeclaration::toCBuffer(OutBuffer *buf) -{ char *p; - - switch (linkage) - { - case LINKd: p = "D"; break; - case LINKc: p = "C"; break; - case LINKcpp: p = "C++"; break; - case LINKwindows: p = "Windows"; break; - case LINKpascal: p = "Pascal"; break; - default: - assert(0); - break; - } - buf->writestring("extern "); - buf->writestring(p); - AttribDeclaration::toCBuffer(buf); -} - -char *LinkDeclaration::toChars() -{ - return "extern ()"; -} - -/********************************* ProtDeclaration ****************************/ - -ProtDeclaration::ProtDeclaration(enum PROT p, Array *decl) - : AttribDeclaration(decl) -{ - protection = p; - //printf("decl = %p\n", decl); -} - -Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s) -{ - ProtDeclaration *pd; - - assert(!s); - pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl)); - return pd; -} - -void ProtDeclaration::semantic(Scope *sc) -{ - if (decl) - { enum PROT protection_save = sc->protection; - - sc->protection = protection; - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic(sc); - } - sc->protection = protection_save; - } - else - sc->protection = protection; -} - -void ProtDeclaration::toCBuffer(OutBuffer *buf) -{ char *p; - - switch (protection) - { - case PROTprivate: p = "private"; break; - case PROTpackage: p = "package"; break; - case PROTprotected: p = "protected"; break; - case PROTpublic: p = "public"; break; - case PROTexport: p = "export"; break; - default: - assert(0); - break; - } - buf->writestring(p); - AttribDeclaration::toCBuffer(buf); -} - -/********************************* AlignDeclaration ****************************/ - -AlignDeclaration::AlignDeclaration(unsigned sa, Array *decl) - : AttribDeclaration(decl) -{ - salign = sa; -} - -Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s) -{ - AlignDeclaration *ad; - - assert(!s); - ad = new AlignDeclaration(salign, Dsymbol::arraySyntaxCopy(decl)); - return ad; -} - -void AlignDeclaration::semantic(Scope *sc) -{ - //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); - if (decl) - { unsigned salign_save = sc->structalign; - - sc->structalign = salign; - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic(sc); - } - sc->structalign = salign_save; - } - else - sc->structalign = salign; -} - - -void AlignDeclaration::toCBuffer(OutBuffer *buf) -{ - buf->printf("align %d", salign); - AttribDeclaration::toCBuffer(buf); -} - -/********************************* AnonDeclaration ****************************/ - -AnonDeclaration::AnonDeclaration(int isunion, Array *decl) - : AttribDeclaration(decl) -{ - this->isunion = isunion; -} - -Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s) -{ - AnonDeclaration *ad; - - assert(!s); - ad = new AnonDeclaration(isunion, Dsymbol::arraySyntaxCopy(decl)); - return ad; -} - -void AnonDeclaration::semantic(Scope *sc) -{ - //printf("\tAnonDeclaration::semantic '%s'\n",toChars()); - assert(sc->parent); - - Dsymbol *parent = sc->parent->pastMixin(); - AggregateDeclaration *ad = parent->isAggregateDeclaration(); - - if (!ad || (!ad->isStructDeclaration() && !ad->isClassDeclaration())) - { - error("can only be a part of an aggregate"); - return; - } - - if (decl) - { Scope sc_save = *sc; - AnonymousAggregateDeclaration aad; - int adisunion; - - if (sc->anonAgg) - { ad = sc->anonAgg; - adisunion = sc->inunion; - } - else - adisunion = ad->isUnionDeclaration() != NULL; - - sc->anonAgg = &aad; - sc->stc &= ~(STCauto | STCstatic); - sc->inunion = isunion; - sc->offset = 0; - sc->flags = 0; - aad.structalign = sc->structalign; - - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic(sc); - if (isunion) - sc->offset = 0; - } - *sc = sc_save; - - // 0 sized structs are set to 1 byte - if (aad.structsize == 0) - { - aad.structsize = 1; - aad.alignsize = 1; - } - - // Align size of anonymous aggregate -//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset); - ad->alignmember(aad.structalign, aad.alignsize, &sc->offset); - //ad->structsize = sc->offset; -//printf("sc->offset = %d\n", sc->offset); - - // Add members of aad to ad - //printf("\tadding members of aad to '%s'\n", ad->toChars()); - for (unsigned i = 0; i < aad.fields.dim; i++) - { - VarDeclaration *v = (VarDeclaration *)aad.fields.data[i]; - - v->offset += sc->offset; - ad->fields.push(v); - } - - // Add size of aad to ad - if (adisunion) - { - if (aad.structsize > ad->structsize) - ad->structsize = aad.structsize; - sc->offset = 0; - } - else - { - ad->structsize = sc->offset + aad.structsize; - sc->offset = ad->structsize; - } - - if (ad->alignsize < aad.alignsize) - ad->alignsize = aad.alignsize; - } -} - - -void AnonDeclaration::toCBuffer(OutBuffer *buf) -{ - buf->printf(isunion ? "union" : "struct"); - AttribDeclaration::toCBuffer(buf); -} - -char *AnonDeclaration::kind() -{ - return (char *)(isunion ? "anonymous union" : "anonymous struct"); -} - -/********************************* PragmaDeclaration ****************************/ - -PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Array *args, Array *decl) - : AttribDeclaration(decl) -{ - this->loc = loc; - this->ident = ident; - this->args = args; -} - -Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s) -{ - PragmaDeclaration *pd; - - assert(!s); - pd = new PragmaDeclaration(loc, ident, - Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl)); - return pd; -} - -void PragmaDeclaration::semantic(Scope *sc) -{ // Should be merged with PragmaStatement - - //printf("\tPragmaDeclaration::semantic '%s'\n",toChars()); - if (ident == Id::msg) - { - if (args) - { - for (size_t i = 0; i < args->dim; i++) - { - Expression *e = (Expression *)args->data[i]; - - e = e->semantic(sc); - if (e->op == TOKstring) - { - StringExp *se = (StringExp *)e; - printf("%.*s", se->len, se->string); - } - else - error("string expected for message, not '%s'", e->toChars()); - } - printf("\n"); - } - } - else if (ident == Id::lib) - { - if (!args || args->dim != 1) - error("string expected for library name"); - else - { - Expression *e = (Expression *)args->data[0]; - - e = e->semantic(sc); - args->data[0] = (void *)e; - if (e->op != TOKstring) - error("string expected for library name, not '%s'", e->toChars()); - } - } - else - error("unrecognized pragma(%s)", ident->toChars()); - - if (decl) - { - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic(sc); - } - } -} - -char *PragmaDeclaration::kind() -{ - return "pragma"; -} - -void PragmaDeclaration::toObjFile() -{ - if (ident == Id::lib) - { - assert(args && args->dim == 1); - - Expression *e = (Expression *)args->data[0]; - - assert(e->op == TOKstring); - - StringExp *se = (StringExp *)e; - char *name = (char *)mem.malloc(se->len + 1); - memcpy(name, se->string, se->len); - name[se->len] = 0; - obj_includelib(name); - } -} - -void PragmaDeclaration::toCBuffer(OutBuffer *buf) -{ - buf->printf("pragma(%s", ident->toChars()); - if (args) - { - for (size_t i = 0; i < args->dim; i++) - { - Expression *e = (Expression *)args->data[i]; - - buf->printf(", %s", e->toChars()); - } - } - buf->writestring(")"); - AttribDeclaration::toCBuffer(buf); -} - - -/********************************* DebugDeclaration ****************************/ - -DebugDeclaration::DebugDeclaration(Condition *condition, Array *decl, Array *elsedecl) - : AttribDeclaration(decl) -{ - //printf("DebugDeclaration::DebugDeclaration()\n"); - this->condition = condition; - this->elsedecl = elsedecl; -} - -Dsymbol *DebugDeclaration::syntaxCopy(Dsymbol *s) -{ - DebugDeclaration *dd; - - assert(!s); - dd = new DebugDeclaration(condition, - Dsymbol::arraySyntaxCopy(decl), - Dsymbol::arraySyntaxCopy(elsedecl)); - return dd; -} - - -// Decide if debug code should be included - -Array *DebugDeclaration::include() -{ - assert(condition); - return condition->include() ? decl : elsedecl; -} - - -void DebugDeclaration::toCBuffer(OutBuffer *buf) -{ - if (isVersionDeclaration()) - buf->writestring("version("); - else - buf->writestring("debug("); - condition->toCBuffer(buf); - buf->writeByte(')'); - if (decl || elsedecl) - { - buf->writenl(); - buf->writeByte('{'); - buf->writenl(); - if (decl) - { - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - buf->writestring(" "); - s->toCBuffer(buf); - } - } - buf->writeByte('}'); - if (elsedecl) - { - buf->writenl(); - buf->writestring("else"); - buf->writenl(); - buf->writeByte('{'); - buf->writenl(); - for (unsigned i = 0; i < elsedecl->dim; i++) - { - Dsymbol *s = (Dsymbol *)elsedecl->data[i]; - - buf->writestring(" "); - s->toCBuffer(buf); - } - buf->writeByte('}'); - } - } - else - buf->writeByte(':'); - buf->writenl(); -} - - -/********************************* VersionDeclaration ****************************/ - -VersionDeclaration::VersionDeclaration(Condition *condition, Array *decl, Array *elsedecl) - : DebugDeclaration(condition, decl, elsedecl) -{ - //printf("VersionDeclaration::VersionDeclaration()\n"); -} - -Dsymbol *VersionDeclaration::syntaxCopy(Dsymbol *s) -{ - VersionDeclaration *vd; - - assert(!s); - vd = new VersionDeclaration(condition, - Dsymbol::arraySyntaxCopy(decl), - Dsymbol::arraySyntaxCopy(elsedecl)); - return vd; -} - - diff -uNr gdc-0.11/d/root/attrib.h gdc-0.12/d/root/attrib.h --- gdc-0.11/d/root/attrib.h 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/attrib.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,132 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_ATTRIB_H -#define DMD_ATTRIB_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "dsymbol.h" - -struct Expression; -struct Statement; -struct LabelDsymbol; -struct Initializer; -struct Module; -struct Condition; - -/**************************************************************/ - -struct AttribDeclaration : Dsymbol -{ - Array *decl; // array of Dsymbol's - - AttribDeclaration(Array *decl); - virtual Array *include(); - void addMember(ScopeDsymbol *s); - void semantic(Scope *sc); - void semantic2(Scope *sc); - void semantic3(Scope *sc); - void inlineScan(); - char *kind(); - Dsymbol *oneMember(); - void addLocalClass(Array *); - void toCBuffer(OutBuffer *buf); - - void toObjFile(); // compile to .obj file - int cvMember(unsigned char *p); -}; - -struct StorageClassDeclaration: AttribDeclaration -{ - unsigned stc; - - StorageClassDeclaration(unsigned stc, Array *decl); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); -}; - -struct LinkDeclaration : AttribDeclaration -{ - enum LINK linkage; - - LinkDeclaration(enum LINK p, Array *decl); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - void semantic3(Scope *sc); - void toCBuffer(OutBuffer *buf); - char *toChars(); -}; - -struct ProtDeclaration : AttribDeclaration -{ - enum PROT protection; - - ProtDeclaration(enum PROT p, Array *decl); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); -}; - -struct AlignDeclaration : AttribDeclaration -{ - unsigned salign; - - AlignDeclaration(unsigned sa, Array *decl); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); -}; - -struct AnonDeclaration : AttribDeclaration -{ - int isunion; - - AnonDeclaration(int isunion, Array *decl); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - char *kind(); -}; - -struct PragmaDeclaration : AttribDeclaration -{ - Array *args; // array of Expression's - - PragmaDeclaration(Loc loc, Identifier *ident, Array *args, Array *decl); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - char *kind(); - void toObjFile(); // compile to .obj file -}; - -struct DebugDeclaration : AttribDeclaration -{ - Condition *condition; - Array *elsedecl; // array of Dsymbol's for else block - - DebugDeclaration(Condition *condition, Array *decl, Array *elsedecl); - Dsymbol *syntaxCopy(Dsymbol *s); - Array *include(); - void toCBuffer(OutBuffer *buf); -}; - -struct VersionDeclaration : DebugDeclaration -{ - VersionDeclaration(Condition *condition, Array *decl, Array *elsedecl); - Dsymbol *syntaxCopy(Dsymbol *s); - - VersionDeclaration *isVersionDeclaration() { return this; } -}; - -#endif /* DMD_ATTRIB_H */ diff -uNr gdc-0.11/d/root/bit.c gdc-0.12/d/root/bit.c --- gdc-0.11/d/root/bit.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/bit.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,149 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -// Routines to convert expressions to elems. - -#include -#include -#include - -#include "cc.h" -#include "el.h" -#include "oper.h" -#include "global.h" -#include "code.h" -#include "type.h" -#include "dt.h" - -static char __file__[] = __FILE__; /* for tassert.h */ -#include "tassert.h" - -/********************************************** - * Generate code for: - * (*eb)[ei] = ev; - * ev should already be a bit type. - * result: - * 0 don't want result - * 1 want result in flags - * 2 want value of result - */ - -#if 1 -#define BIT_SHIFT 3 -#define BIT_MASK 7 -#define TYbit TYuchar -#else -#define BIT_SHIFT 5 -#define BIT_MASK 31 -#define TYbit TYuint -#endif - -elem *bit_assign(enum OPER op, elem *eb, elem *ei, elem *ev, int result) -{ -#if 1 - elem *e; - elem *es; - elem *er; - - es = el_bin(OPbts, TYbit, eb, ei); - er = el_copytree(es); - er->Eoper = OPbtr; - es = el_bin(OPcomma, TYbit, es, el_long(TYbit, 1)); - er = el_bin(OPcomma, TYbit, er, el_long(TYbit, 0)); - - e = el_bin(OPcolon, TYvoid, es, er); - e = el_bin(OPcond, ev->Ety, ev, e); - return e; -#else - /* - The idea is: - - *(eb + (ei >> 5)) &= ~(1 << (ei & 31)); - *(eb + (ei >> 5)) |= ev << (ei & 31); - ev; - - So we generate: - - et = (eb + (ei >> 5)); - em = (eit & 31); - *ett = (*et & ~(1 << em)) | (ev << em); - evt; - */ - - printf("bit_assign()\n"); - - elem *e; - elem *em; - elem *eit = el_same(&ei); - elem *et; - elem *ett; - elem *evt = el_same(&ev); - - ei->Ety = TYuint; - et = el_bin(OPshr, TYuint, ei, el_long(TYuint, BIT_SHIFT)); - et = el_bin(OPadd, TYnptr, eb, et); - ett = el_same(&et); - - eit->Ety = TYbit; - em = el_bin(OPand, TYbit, eit, el_long(TYbit, BIT_MASK)); - - e = el_bin(OPshl, TYbit, el_long(TYbit, 1), em); - e = el_una(OPcom, TYbit, e); - et = el_una(OPind, TYbit, et); - e = el_bin(OPand, TYbit, et, e); - - ev->Ety = TYbit; - e = el_bin(OPor, TYbit, e, el_bin(OPshl, TYbit, ev, el_copytree(em))); - ett = el_una(OPind, TYbit, ett); - e = el_bin(OPeq, TYbit, ett, e); - - e = el_bin(OPcomma, evt->Ety, e, evt); - return e; -#endif -} - -/********************************************** - * Generate code for: - * (*eb)[ei] - * ev should already be a bit type. - * result: - * 0 don't want result - * 1 want result in flags - * 2 want value of result - * 3 ? - */ - -elem *bit_read(elem *eb, elem *ei, int result) -{ -#if 1 - elem *e; - - e = el_bin(OPbt, TYbit, eb, ei); - e = el_bin(OPand, TYbit, e, el_long(TYbit, 1)); - return e; -#else - // eb[ei] => (eb[ei >>> 5] >> (ei & 31)) & 1 - elem *e; - elem *eit = el_same(&ei); - - // Now generate ((*(eb + (ei >>> 5)) >>> (eit & 31)) & 1 - - ei->Ety = TYuint; - e = el_bin(OPshr, TYuint, ei, el_long(TYuint, BIT_SHIFT)); - e = el_bin(OPadd, TYnptr, eb, e); - e = el_una(OPind, TYbit, e); - eit->Ety = TYbit; - eit = el_bin(OPand, TYbit, eit, el_long(TYbit, BIT_MASK)); - e = el_bin(OPshr, TYbit, e, eit); - e = el_bin(OPand, TYbit, e, el_long(TYbit, 1)); - - // BUG: what about return type of e? - return e; -#endif -} diff -uNr gdc-0.11/d/root/cast.c gdc-0.12/d/root/cast.c --- gdc-0.11/d/root/cast.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/cast.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1068 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include - -#if _WIN32 -#include "mem.h" -#else -#include "../root/mem.h" -#endif - -#include "expression.h" -#include "mtype.h" -#include "utf.h" -#include "declaration.h" -#include "aggregate.h" - -/* ==================== implicitCast ====================== */ - -/************************************** - * Do an implicit cast. - * Issue error if it can't be done. - */ - -Expression *Expression::implicitCastTo(Type *t) -{ - //printf("implicitCastTo(%s) => %s\n", type->toChars(), t->toChars()); - if (implicitConvTo(t)) - { - if (global.params.warnings && - Type::impcnvWarn[type->toBasetype()->ty][t->toBasetype()->ty] && - op != TOKint64) - { - Expression *e = optimize(WANTflags | WANTvalue); - - if (e->op == TOKint64) - return e->implicitCastTo(t); - - printf("warning - "); - error("implicit conversion of expression (%s) of type %s to %s can cause loss of data", - toChars(), type->toChars(), t->toChars()); - } - return castTo(t); - } -#if 0 -print(); -type->print(); -printf("to:\n"); -t->print(); -printf("%p %p %s %s\n", type->deco, t->deco, type->deco, t->deco); -//printf("%p %p %p\n", type->next->arrayOf(), type, t); -fflush(stdout); -#endif -//*(char*)0=0; - error("cannot implicitly convert expression (%s) of type %s to %s", - toChars(), type->toChars(), t->toChars()); - return castTo(t); -} - -/******************************************* - * Return !=0 if we can implicitly convert this to type t. - * Don't do the actual cast. - */ - -int Expression::implicitConvTo(Type *t) -{ -#if 0 - printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", - toChars(), type->toChars(), t->toChars()); -#endif - if (!type) - { error("%s is not an expression", toChars()); - type = Type::terror; - } - if (t->ty == Tbit && isBit()) - return MATCHconvert; - Expression *e = optimize(WANTvalue | WANTflags); - if (e != this) - { //printf("optimzed to %s\n", e->toChars()); - return e->implicitConvTo(t); - } - return type->implicitConvTo(t); -} - - -int IntegerExp::implicitConvTo(Type *t) -{ -#if 0 - printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", - toChars(), type->toChars(), t->toChars()); -#endif - if (type->equals(t)) - return MATCHexact; - - enum TY ty = type->toBasetype()->ty; - switch (ty) - { - case Tbit: - value &= 1; - ty = Tint32; - break; - - case Tint8: - value = (signed char)value; - ty = Tint32; - break; - - case Tchar: - case Tuns8: - value &= 0xFF; - ty = Tint32; - break; - - case Tint16: - value = (short)value; - ty = Tint32; - break; - - case Tuns16: - case Twchar: - value &= 0xFFFF; - ty = Tint32; - break; - - case Tint32: - value = (int)value; - break; - - case Tuns32: - case Tdchar: - value &= 0xFFFFFFFF; - ty = Tuns32; - break; - - default: - break; - } - - // Only allow conversion if no change in value - enum TY toty = t->toBasetype()->ty; - switch (toty) - { - case Tbit: - if (value & ~1) - goto Lno; - goto Lyes; - - case Tint8: - if ((signed char)value != value) - goto Lno; - goto Lyes; - - case Tchar: - case Tuns8: - //printf("value = %llu %llu\n", (integer_t)(unsigned char)value, value); - if ((unsigned char)value != value) - goto Lno; - goto Lyes; - - case Tint16: - if ((short)value != value) - goto Lno; - goto Lyes; - - case Tuns16: - if ((unsigned short)value != value) - goto Lno; - goto Lyes; - - case Tint32: - if (ty == Tuns32) - { - } - else if ((int)value != value) - goto Lno; - goto Lyes; - - case Tuns32: - if (ty == Tint32) - { - } - else if ((unsigned)value != value) - goto Lno; - goto Lyes; - - case Tdchar: - if (value > 0x10FFFFUL) - goto Lno; - goto Lyes; - - case Twchar: - if ((unsigned short)value != value) - goto Lno; - goto Lyes; - - case Tfloat32: - case Tcomplex32: - { - volatile float f; - if (type->isunsigned()) - { - f = (float)value; - if (f != value) - goto Lno; - } - else - { - f = (float)(long long)value; - if (f != (long long)value) - goto Lno; - } - goto Lyes; - } - - case Tfloat64: - case Tcomplex64: - { - volatile double f; - if (type->isunsigned()) - { - f = (double)value; - if (f != value) - goto Lno; - } - else - { - f = (double)(long long)value; - if (f != (long long)value) - goto Lno; - } - goto Lyes; - } - - case Tfloat80: - case Tcomplex80: - { - volatile long double f; - if (type->isunsigned()) - { - f = (long double)value; - if (f != value) - goto Lno; - } - else - { - f = (long double)(long long)value; - if (f != (long long)value) - goto Lno; - } - goto Lyes; - } - } - return Expression::implicitConvTo(t); - -Lyes: - return MATCHconvert; - -Lno: - return MATCHnomatch; -} - -int NullExp::implicitConvTo(Type *t) -{ -#if 0 - printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s)\n", - toChars(), type->toChars(), t->toChars()); -#endif - if (this->type->equals(t)) - return 2; - // NULL implicitly converts to any pointer type or dynamic array - if (type->ty == Tpointer && type->next->ty == Tvoid) - { - if (t->ty == Ttypedef) - t = ((TypeTypedef *)t)->sym->basetype; - if (t->ty == Tpointer || t->ty == Tarray || - t->ty == Taarray || t->ty == Tclass || - t->ty == Tdelegate) - return 1; - } - return type->implicitConvTo(t); -} - -int StringExp::implicitConvTo(Type *t) -{ MATCH m; - - //printf("StringExp::implicitConvTo(), committed = %d\n", committed); - if (!committed) - { - if (!committed && t->ty == Tpointer && t->next->ty == Tvoid) - { - return MATCHnomatch; - } - if (type->ty == Tsarray || type->ty == Tarray || type->ty == Tpointer) - { - if (type->next->ty == Tchar) - { - switch (t->ty) - { - case Tsarray: - if (type->ty == Tsarray && - ((TypeSArray *)type)->dim->toInteger() != - ((TypeSArray *)t)->dim->toInteger()) - return MATCHnomatch; - case Tarray: - case Tpointer: - if (t->next->ty == Tchar) - return MATCHexact; - else if (t->next->ty == Twchar) - return MATCHexact; - else if (t->next->ty == Tdchar) - return MATCHexact; - break; - } - } - } - } - m = (MATCH)type->implicitConvTo(t); - if (m) - { - return m; - } - - return MATCHnomatch; -} - -int AddrExp::implicitConvTo(Type *t) -{ -#if 0 - printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", - toChars(), type->toChars(), t->toChars()); -#endif - int result; - - result = type->implicitConvTo(t); - //printf("\tresult = %d\n", result); - - if (result == MATCHnomatch) - { - // Look for pointers to functions where the functions are overloaded. - VarExp *ve; - FuncDeclaration *f; - - t = t->toBasetype(); - if (type->ty == Tpointer && type->next->ty == Tfunction && - t->ty == Tpointer && t->next->ty == Tfunction && - e1->op == TOKvar) - { - ve = (VarExp *)e1; - f = ve->var->isFuncDeclaration(); - if (f && f->overloadExactMatch(t->next)) - result = MATCHexact; - } - } - //printf("\tresult = %d\n", result); - return result; -} - -int DelegateExp::implicitConvTo(Type *t) -{ -#if 0 - printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", - toChars(), type->toChars(), t->toChars()); -#endif - int result; - - result = type->implicitConvTo(t); - - if (result == 0) - { - // Look for pointers to functions where the functions are overloaded. - FuncDeclaration *f; - - t = t->toBasetype(); - if (type->ty == Tdelegate && type->next->ty == Tfunction && - t->ty == Tdelegate && t->next->ty == Tfunction) - { - if (func && func->overloadExactMatch(t->next)) - result = 2; - } - } - return result; -} - -int CondExp::implicitConvTo(Type *t) -{ - int m1; - int m2; - - m1 = e1->implicitConvTo(t); - m2 = e2->implicitConvTo(t); - - // Pick the worst match - return (m1 < m2) ? m1 : m2; -} - - -/* ==================== castTo ====================== */ - -/************************************** - * Do an explicit cast. - */ - -Expression *Expression::castTo(Type *t) -{ Expression *e; - Type *tb; - -#if 0 - printf("Expression::castTo(this=%s, type=%s, t=%s)\n", - toChars(), type->toChars(), t->toChars()); -#endif - e = this; - tb = t->toBasetype(); - type = type->toBasetype(); - if (tb != type) - { - if (tb->ty == Tbit && isBit()) - ; - - // Do (type *) cast of (type [dim]) - else if (tb->ty == Tpointer && - type->ty == Tsarray - ) - { - //printf("Converting [dim] to *\n"); - - e = new AddrExp(loc, e); - } - else - e = new CastExp(loc, e, tb); - } - e->type = t; - return e; -} - -Expression *NullExp::castTo(Type *t) -{ Expression *e; - Type *tb; - - //printf("NullExp::castTo(t = %p)\n", t); - e = this; - tb = t->toBasetype(); - type = type->toBasetype(); - if (tb != type) - { - // NULL implicitly converts to any pointer type or dynamic array - if (type->ty == Tpointer && type->next->ty == Tvoid && - (tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray || - tb->ty == Tdelegate)) - { - } - else - { - e = new CastExp(loc, e, tb); - } - } - e->type = t; - return e; -} - -Expression *StringExp::castTo(Type *t) -{ - StringExp *se; - Type *tb; - int unique; - - //printf("StringExp::castTo('%s')\n", string); - //if (((char*)string)[0] == 'd') *(char*)0=0; - if (!committed && t->ty == Tpointer && t->next->ty == Tvoid) - { - error("cannot convert string literal to void*"); - } - - se = this; - unique = 0; - if (!committed) - { - // Copy when committing the type - void *s; - - s = (unsigned char *)mem.malloc((len + 1) * sz); - memcpy(s, string, (len + 1) * sz); - se = new StringExp(loc, s, len); - se->type = type; - se->sz = sz; - se->committed = 1; // it now has a firm type - unique = 1; // this is the only instance - } - tb = t->toBasetype(); - se->type = type->toBasetype(); - if (tb == se->type) - { se->type = t; - return se; - } - - if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer) - goto Lcast; - if (se->type->ty != Tsarray && se->type->ty != Tarray && se->type->ty != Tpointer) - goto Lcast; - - int tfty; - int ttty; - char *p; - unsigned u; - unsigned c; - unsigned newlen; - -#define X(tf,tt) ((tf) * 256 + (tt)) - { - OutBuffer buffer; - newlen = 0; - tfty = se->type->next->toBasetype()->ty; - ttty = tb->next->toBasetype()->ty; - switch (X(tfty, ttty)) - { - case X(Tchar, Tchar): - case X(Twchar,Twchar): - case X(Tdchar,Tdchar): - break; - - case X(Tchar, Twchar): - for (u = 0; u < len;) - { - p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); - if (p) - error(p); - else - buffer.writeUTF16(c); - } - newlen = buffer.offset / 2; - buffer.writeUTF16(0); - goto L1; - - case X(Tchar, Tdchar): - for (u = 0; u < len;) - { - p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); - if (p) - error(p); - buffer.write4(c); - newlen++; - } - buffer.write4(0); - goto L1; - - case X(Twchar,Tchar): - for (u = 0; u < len;) - { - p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); - if (p) - error(p); - else - buffer.writeUTF8(c); - } - newlen = buffer.offset; - buffer.writeUTF8(0); - goto L1; - - case X(Twchar,Tdchar): - for (u = 0; u < len;) - { - p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); - if (p) - error(p); - buffer.write4(c); - newlen++; - } - buffer.write4(0); - goto L1; - - case X(Tdchar,Tchar): - for (u = 0; u < len; u++) - { - c = ((unsigned *)se->string)[u]; - if (!utf_isValidDchar(c)) - error("invalid UCS-32 char \\U%08x", c); - else - buffer.writeUTF8(c); - newlen++; - } - newlen = buffer.offset; - buffer.writeUTF8(0); - goto L1; - - case X(Tdchar,Twchar): - for (u = 0; u < len; u++) - { - c = ((unsigned *)se->string)[u]; - if (!utf_isValidDchar(c)) - error("invalid UCS-32 char \\U%08x", c); - else - buffer.writeUTF16(c); - newlen++; - } - newlen = buffer.offset / 2; - buffer.writeUTF16(0); - goto L1; - - L1: - if (!unique) - se = new StringExp(loc, NULL, 0); - se->string = buffer.extractData(); - se->len = newlen; - se->sz = tb->next->size(); - break; - - default: - goto Lcast; - } - } -#undef X - - // See if need to truncate or extend the literal - if (tb->ty == Tsarray) - { - int dim2 = ((TypeSArray *)tb)->dim->toInteger(); - - //printf("dim from = %d, to = %d\n", se->len, dim2); - - // Changing dimensions - if (dim2 != se->len) - { - unsigned newsz = se->sz; - - if (unique && dim2 < se->len) - { se->len = dim2; - // Add terminating 0 - memset((unsigned char *)se->string + dim2 * newsz, 0, newsz); - } - else - { - // Copy when changing the string literal - void *s; - int d; - - d = (dim2 < se->len) ? dim2 : se->len; - s = (unsigned char *)mem.malloc((dim2 + 1) * newsz); - memcpy(s, se->string, d * newsz); - // Extend with 0, add terminating 0 - memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz); - se = new StringExp(loc, s, dim2); - se->committed = 1; // it now has a firm type - se->sz = newsz; - } - } - } - se->type = t; - return se; - -Lcast: - Expression *e = new CastExp(loc, se, t); - e->type = t; - return e; -} - -Expression *AddrExp::castTo(Type *t) -{ - Type *tb; - -#if 0 - printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", - toChars(), type->toChars(), t->toChars()); -#endif - Expression *e = this; - - tb = t->toBasetype(); - type = type->toBasetype(); - if (tb != type) - { - // Look for pointers to functions where the functions are overloaded. - VarExp *ve; - FuncDeclaration *f; - - if (type->ty == Tpointer && type->next->ty == Tfunction && - tb->ty == Tpointer && tb->next->ty == Tfunction && - e1->op == TOKvar) - { - ve = (VarExp *)e1; - f = ve->var->isFuncDeclaration(); - if (f) - { - f = f->overloadExactMatch(tb->next); - if (f) - { - e = new VarExp(loc, f); - e->type = f->type; - e = new AddrExp(loc, e); - e->type = t; - return e; - } - } - } - e = Expression::castTo(t); - } - - e->type = t; - return e; -} - -Expression *DelegateExp::castTo(Type *t) -{ - Type *tb; -#if 0 - printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", - toChars(), type->toChars(), t->toChars()); -#endif - Expression *e = this; - - tb = t->toBasetype(); - type = type->toBasetype(); - if (tb != type) - { - // Look for delegates to functions where the functions are overloaded. - FuncDeclaration *f; - - if (type->ty == Tdelegate && type->next->ty == Tfunction && - tb->ty == Tdelegate && tb->next->ty == Tfunction) - { - if (func) - { - f = func->overloadExactMatch(tb->next); - if (f) - { - e = new DelegateExp(loc, e1, f); - e->type = t; - return e; - } - } - } - e = Expression::castTo(t); - } - e->type = t; - return e; -} - -Expression *CondExp::castTo(Type *t) -{ - Expression *e = this; - - if (type != t) - { - if (1 || e1->op == TOKstring || e2->op == TOKstring) - { e = new CondExp(loc, econd, e1->castTo(t), e2->castTo(t)); - e->type = t; - } - else - e = Expression::castTo(t); - } - return e; -} - -/* ==================== ====================== */ - -/**************************************** - * Scale addition/subtraction to/from pointer. - */ - -Expression *BinExp::scaleFactor() -{ d_uns64 stride; - Type *t1b = e1->type->toBasetype(); - Type *t2b = e2->type->toBasetype(); - - if (t1b->ty == Tpointer && t2b->isintegral()) - { // Need to adjust operator by the stride - // Replace (ptr + int) with (ptr + (int * stride)) - Type *t = Type::tptrdiff_t; - - stride = t1b->next->size(); - if (!t->equals(t2b)) - e2 = e2->castTo(t); - if (t1b->next->isbit()) - // BUG: should add runtime check for misaligned offsets - // This perhaps should be done by rewriting as &p[i] - // and letting back end do it. - e2 = new UshrExp(loc, e2, new IntegerExp(0, 3, t)); - else - e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t)); - e2->type = t; - type = e1->type; - } - else if (t2b->ty && t1b->isintegral()) - { // Need to adjust operator by the stride - // Replace (int + ptr) with (ptr + (int * stride)) - Type *t = Type::tptrdiff_t; - Expression *e; - - stride = t2b->next->size(); - if (!t->equals(t1b)) - e = e1->castTo(t); - else - e = e1; - if (t2b->next->isbit()) - // BUG: should add runtime check for misaligned offsets - e = new UshrExp(loc, e, new IntegerExp(0, 3, t)); - else - e = new MulExp(loc, e, new IntegerExp(0, stride, t)); - e->type = t; - type = e2->type; - e1 = e2; - e2 = e; - } - return this; -} - -/************************************ - * Bring leaves to common type. - */ - -Expression *BinExp::typeCombine() -{ - Type *t1; - Type *t2; - Type *t; - TY ty; - - //printf("BinExp::typeCombine()\n"); - //dump(0); - - e1 = e1->integralPromotions(); - e2 = e2->integralPromotions(); - - // BUG: do toBasetype() - t1 = e1->type; - t2 = e2->type; - assert(t1); -#ifdef DEBUG - if (!t2) printf("\te2 = '%s'\n", e2->toChars()); -#endif - assert(t2); - - ty = (TY)Type::impcnvResult[t1->ty][t2->ty]; - if (ty != Terror) - { TY ty1; - TY ty2; - - if (!type) - type = Type::basic[ty]; - ty1 = (TY)Type::impcnvType1[t1->ty][t2->ty]; - ty2 = (TY)Type::impcnvType2[t1->ty][t2->ty]; - t1 = Type::basic[ty1]; - t2 = Type::basic[ty2]; - e1 = e1->castTo(t1); - e2 = e2->castTo(t2); -#if 0 - if (type != Type::basic[ty]) - { t = type; - type = Type::basic[ty]; - return castTo(t); - } -#endif - //printf("after typeCombine():\n"); - //dump(0); - //printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2); - return this; - } - - t = t1; - if (t1 == t2) - { - if ((t1->ty == Tstruct || t1->ty == Tclass) && - (op == TOKmin || op == TOKadd)) - goto Lincompatible; - } - else if (t1->isintegral() && t2->isintegral()) - { - //printf("t1 = %s, t2 = %s\n", t1->toChars(), t2->toChars()); - int sz1 = t1->size(); - int sz2 = t2->size(); - int sign1 = t1->isunsigned() == 0; - int sign2 = t2->isunsigned() == 0; - - if (sign1 == sign2) - { - if (sz1 < sz2) - goto Lt2; - else - goto Lt1; - } - if (!sign1) - { - if (sz1 >= sz2) - goto Lt1; - else - goto Lt2; - } - else - { - if (sz2 >= sz1) - goto Lt2; - else - goto Lt1; - } - } - else if (t1->ty == Tpointer && t2->ty == Tpointer) - { - // Bring pointers to compatible type - Type *t1n = t1->next; - Type *t2n = t2->next; - -//t1->print(); -//t2->print(); -//if (t1n == t2n) *(char *)0 = 0; - assert(t1n != t2n); - if (t1n->ty == Tvoid) // pointers to void are always compatible - t = t2; - else if (t2n->ty == Tvoid) - ; - else if (t1n->ty == Tclass && t2n->ty == Tclass) - { ClassDeclaration *cd1 = t1n->isClassHandle(); - ClassDeclaration *cd2 = t2n->isClassHandle(); - int offset; - - if (cd1->isBaseOf(cd2, &offset)) - { - if (offset) - e2 = e2->castTo(t); - } - else if (cd2->isBaseOf(cd1, &offset)) - { - t = t2; - if (offset) - e1 = e1->castTo(t); - } - else - goto Lincompatible; - } - else - goto Lincompatible; - } - else if ((t1->ty == Tsarray || t1->ty == Tarray) && - e2->op == TOKnull && t2->ty == Tpointer && t2->next->ty == Tvoid) - { - goto Lx1; - } - else if ((t2->ty == Tsarray || t2->ty == Tarray) && - e1->op == TOKnull && t1->ty == Tpointer && t1->next->ty == Tvoid) - { - goto Lx2; - } - else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2)) - { - goto Lt2; - } - else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1)) - { - goto Lt1; - } - else if (t1->ty == Tclass || t2->ty == Tclass) - { int i1; - int i2; - - i1 = e2->implicitConvTo(t1); - i2 = e1->implicitConvTo(t2); - - if (i1 && i2) - { - // We have the case of class vs. void*, so pick class - if (t1->ty == Tpointer) - i1 = 0; - else if (t2->ty == Tpointer) - i2 = 0; - } - - if (i2) - { - goto Lt2; - } - else if (i1) - { - goto Lt1; - } - else - goto Lincompatible; - } - else if ((e1->op == TOKstring || e1->op == TOKnull) && e1->implicitConvTo(t2)) - { - goto Lt2; - } -//else if (e2->op == TOKstring) { printf("test2\n"); } - else if ((e2->op == TOKstring || e2->op == TOKnull) && e2->implicitConvTo(t1)) - { - goto Lt1; - } - else if (t1->ty == Tsarray && t2->ty == Tsarray && - e2->implicitConvTo(t1->next->arrayOf())) - { - Lx1: - t = t1->next->arrayOf(); - e1 = e1->castTo(t); - e2 = e2->castTo(t); - } - else if (t1->ty == Tsarray && t2->ty == Tsarray && - e1->implicitConvTo(t2->next->arrayOf())) - { - Lx2: - t = t2->next->arrayOf(); - e1 = e1->castTo(t); - e2 = e2->castTo(t); - } - else - { - Lincompatible: - error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", - e1->toChars(), Token::toChars(op), e2->toChars(), - t1->toChars(), t2->toChars()); - } -Lret: - if (!type) - type = t; - //dump(0); - return this; - - -Lt1: - e2 = e2->castTo(t1); - t = t1; - goto Lret; - -Lt2: - e1 = e1->castTo(t2); - t = t2; - goto Lret; -} - -/*********************************** - * Do integral promotions (convertchk). - * Don't convert to - */ - -Expression *Expression::integralPromotions() -{ Expression *e; - - e = this; - switch (type->toBasetype()->ty) - { - case Tvoid: - error("void has no value"); - break; - - case Tint8: - case Tuns8: - case Tint16: - case Tuns16: - case Tbit: - case Tchar: - case Twchar: - e = e->castTo(Type::tint32); - break; - - case Tdchar: - e = e->castTo(Type::tuns32); - break; - } - return e; -} - diff -uNr gdc-0.11/d/root/class.c gdc-0.12/d/root/class.c --- gdc-0.11/d/root/class.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/class.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1002 +0,0 @@ - - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include - -#include "root.h" -#include "mem.h" - -#include "enum.h" -#include "init.h" -#include "attrib.h" -#include "declaration.h" -#include "aggregate.h" -#include "id.h" -#include "mtype.h" -#include "scope.h" -#include "module.h" -#include "expression.h" -#include "statement.h" - -/********************************* ClassDeclaration ****************************/ - -ClassDeclaration *ClassDeclaration::classinfo; - -ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, Array *baseclasses) - : AggregateDeclaration(loc, id) -{ - if (baseclasses) - this->baseclasses = *baseclasses; - baseClass = NULL; - - interfaces_dim = 0; - interfaces = NULL; - - vtblInterfaces = NULL; - - //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses.dim); - - // For forward references - type = new TypeClass(this); - handle = type; - - ctor = NULL; - dtor = NULL; - staticCtor = NULL; - staticDtor = NULL; - - vtblsym = NULL; - vclassinfo = NULL; - - if (id == Id::__sizeof) - error("illegal class name"); - - // BUG: What if this is the wrong ClassInfo, i.e. it is nested? - if (!classinfo && id == Id::ClassInfo) - classinfo = this; - - // BUG: What if this is the wrong ModuleInfo, i.e. it is nested? - if (!Module::moduleinfo && id == Id::ModuleInfo) - Module::moduleinfo = this; - - // BUG: What if this is the wrong TypeInfo, i.e. it is nested? - if (id->toChars()[0] == 'T') - { - if (!Type::typeinfo && id == Id::TypeInfo) - Type::typeinfo = this; - - if (!Type::typeinfoclass && id == Id::TypeInfo_Class) - Type::typeinfoclass = this; - - if (!Type::typeinfostruct && id == Id::TypeInfo_Struct) - Type::typeinfostruct = this; - - if (!Type::typeinfotypedef && id == Id::TypeInfo_Typedef) - Type::typeinfotypedef = this; - - if (!Type::typeinfopointer && id == Id::TypeInfo_Pointer) - Type::typeinfopointer = this; - - if (!Type::typeinfoarray && id == Id::TypeInfo_Array) - Type::typeinfoarray = this; - - if (!Type::typeinfostaticarray && id == Id::TypeInfo_StaticArray) - Type::typeinfostaticarray = this; - - if (!Type::typeinfoassociativearray && id == Id::TypeInfo_AssociativeArray) - Type::typeinfoassociativearray = this; - - if (!Type::typeinfoenum && id == Id::TypeInfo_Enum) - Type::typeinfoenum = this; - - if (!Type::typeinfofunction && id == Id::TypeInfo_Function) - Type::typeinfofunction = this; - - if (!Type::typeinfodelegate && id == Id::TypeInfo_Delegate) - Type::typeinfodelegate = this; - } - - com = 0; -#if 0 - if (id == Id::IUnknown) // IUnknown is the root of all COM objects - com = 1; -#endif - isauto = 0; - isabstract = 0; -} - -Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) -{ - ClassDeclaration *cd; - - //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars()); - if (s) - cd = (ClassDeclaration *)s; - else - cd = new ClassDeclaration(loc, ident, NULL); - - cd->baseclasses.setDim(this->baseclasses.dim); - for (int i = 0; i < cd->baseclasses.dim; i++) - { - BaseClass *b = (BaseClass *)this->baseclasses.data[i]; - BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection); - cd->baseclasses.data[i] = b2; - } - - ScopeDsymbol::syntaxCopy(cd); - return cd; -} - -void ClassDeclaration::semantic(Scope *sc) -{ int i; - unsigned offset; - - //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); - //printf("parent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : ""); - - //{ static int n; if (++n == 20) *(char*)0=0; } - - if (!scope) - { - if (!parent && sc->parent && !sc->parent->isModule()) - parent = sc->parent; - - type = type->semantic(loc, sc); - handle = handle->semantic(loc, sc); - } - if (!members) // if forward reference - { //printf("\tclass '%s' is forward referenced\n", toChars()); - return; - } - if (symtab) - { if (!scope) - { //printf("\tsemantic for '%s' is already completed\n", toChars()); - return; // semantic() already completed - } - } - else - symtab = new DsymbolTable(); - - Scope *scx = NULL; - if (scope) - { sc = scope; - scx = scope; // save so we don't make redundant copies - scope = NULL; - } - - // See if there's a base class as first in baseclasses[] - if (baseclasses.dim) - { TypeClass *tc; - BaseClass *b; - Type *tb; - - b = (BaseClass *)baseclasses.data[0]; - b->type = b->type->semantic(loc, sc); - tb = b->type->toBasetype(); - if (tb->ty != Tclass) - { error("base type must be class or interface, not %s", b->type->toChars()); - baseclasses.remove(0); - } - else - { - tc = (TypeClass *)(tb); - if (tc->sym->isInterfaceDeclaration()) - ; - else - { - if (tc->sym == this) - { - error("base class same as class"); - baseclasses.remove(0); - } - else if (!tc->sym->symtab || tc->sym->scope) - { - //error("forward reference of base class %s", baseClass->toChars()); - // Forward reference of base class, try again later - //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars()); - scope = scx ? scx : new Scope(*sc); - scope->setNoFree(); - scope->module->addDeferredSemantic(this); - return; - } - else - { baseClass = tc->sym; - b->base = baseClass; - } - } - } - } - - // Check for errors, handle forward references - for (i = (baseClass ? 1 : 0); i < baseclasses.dim; ) - { TypeClass *tc; - BaseClass *b; - Type *tb; - - b = (BaseClass *)baseclasses.data[i]; - b->type = b->type->semantic(loc, sc); - tb = b->type->toBasetype(); - if (tb->ty == Tclass) - tc = (TypeClass *)tb; - else - tc = NULL; - if (!tc || !tc->sym->isInterfaceDeclaration()) - { - error("base type must be interface, not %s", b->type->toChars()); - baseclasses.remove(i); - continue; - } - else - { - b->base = tc->sym; - if (!b->base->symtab || b->base->scope) - { - //error("forward reference of base class %s", baseClass->toChars()); - // Forward reference of base, try again later - //printf("\ttry later, forward reference of base %s\n", baseClass->toChars()); - scope = scx ? scx : new Scope(*sc); - scope->setNoFree(); - scope->module->addDeferredSemantic(this); - return; - } - } - i++; - } - - - // If no base class, and this is not an Object, use Object as base class - if (!baseClass && ident != Id::Object) - { - // BUG: what if Object is redefined in an inner scope? - Type *tbase = new TypeIdentifier(0, Id::Object); - BaseClass *b; - TypeClass *tc; - Type *bt; - - bt = tbase->semantic(loc, sc)->toBasetype(); - b = new BaseClass(bt, PROTpublic); - baseclasses.shift(b); - assert(b->type->ty == Tclass); - tc = (TypeClass *)(b->type); - baseClass = tc->sym; - assert(!baseClass->isInterfaceDeclaration()); - b->base = baseClass; - } - - interfaces_dim = baseclasses.dim; - interfaces = (BaseClass **)baseclasses.data; - - - if (baseClass) - { - interfaces_dim--; - interfaces++; - - // Copy vtbl[] from base class - vtbl.setDim(baseClass->vtbl.dim); - memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim); - - // Inherit properties from base class - com = baseClass->isCOMclass(); - isauto = baseClass->isauto; - } - else - { - // No base class, so this is the root of the class heirarchy - vtbl.setDim(0); - vtbl.push(this); // leave room for classinfo as first member - } - - if (sizeok == 0) - { - interfaceSemantic(sc); - - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->addMember(this); - } - } - - if (sc->stc & STCauto) - isauto = 1; - if (sc->stc & STCabstract) - isabstract = 1; - if (sc->stc & STCdeprecated) - isdeprecated = 1; - - sc = sc->push(this); - sc->stc &= ~(STCauto | STCstatic | STCabstract); - sc->parent = this; - - if (isCOMclass()) - sc->linkage = LINKwindows; - sc->protection = PROTpublic; - sc->structalign = 8; - structalign = sc->structalign; - if (baseClass) - { sc->offset = baseClass->structsize; - alignsize = baseClass->alignsize; - } - else - { sc->offset = 8; // allow room for vptr[] and monitor - alignsize = 4; - } - structsize = sc->offset; - Scope scsave = *sc; - int members_dim = members->dim; - sizeok = 0; - for (i = 0; i < members_dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic(sc); - } - - if (sizeok == 2) - { // semantic() failed because of forward references. - // Unwind what we did, and defer it for later - fields.setDim(0); - structsize = 0; - alignsize = 0; - structalign = 0; - - sc->pop(); - - scope = scx ? scx : new Scope(*sc); - scope->setNoFree(); - scope->module->addDeferredSemantic(this); - return; - } - - //printf("\tsemantic('%s') successful\n", toChars()); - - structsize = sc->offset; - //members->print(); - - /* Look for special member functions. - * They must be in this class, not in a base class. - */ - ctor = (CtorDeclaration *)search(Id::ctor, 0); - if (ctor && ctor->toParent() != this) - ctor = NULL; - - dtor = (DtorDeclaration *)search(Id::dtor, 0); - if (dtor && dtor->toParent() != this) - dtor = NULL; - -// inv = (InvariantDeclaration *)search(Id::classInvariant, 0); -// if (inv && inv->toParent() != this) -// inv = NULL; - - // Can be in base class - aggNew = (NewDeclaration *)search(Id::classNew, 0); - aggDelete = (DeleteDeclaration *)search(Id::classDelete, 0); - - // If this class has no constructor, but base class does, create - // a constructor: - // this() { } - if (!ctor && baseClass && baseClass->ctor) - { - //printf("Creating default this(){} for class %s\n", toChars()); - ctor = new CtorDeclaration(0, 0, NULL, 0); - ctor->fbody = new CompoundStatement(0, new Array()); - members->push(ctor); - ctor->addMember(this); - *sc = scsave; - sc->offset = structsize; - ctor->semantic(sc); - } - -#if 0 - if (baseClass) - { if (!aggDelete) - aggDelete = baseClass->aggDelete; - if (!aggNew) - aggNew = baseClass->aggNew; - } -#endif - - // Allocate instance of each new interface - for (i = 0; i < vtblInterfaces->dim; i++) - { - BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; - unsigned thissize = PTRSIZE; - - alignmember(structalign, thissize, &sc->offset); - assert(b->offset == 0); - b->offset = sc->offset; - - // Take care of single inheritance offsets - while (b->baseInterfaces_dim) - { - b = &b->baseInterfaces[0]; - b->offset = sc->offset; - } - - sc->offset += thissize; - if (alignsize < thissize) - alignsize = thissize; - } - structsize = sc->offset; - sizeok = 1; - - sc->pop(); - -#if 0 // Do not call until toObjfile() because of forward references - // Fill in base class vtbl[]s - for (i = 0; i < vtblInterfaces->dim; i++) - { - BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; - - //b->fillVtbl(this, &b->vtbl, 1); - } -#endif - //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type); -} - -void ClassDeclaration::toCBuffer(OutBuffer *buf) -{ int i; - int needcomma; - - buf->printf("%s %s", kind(), toChars()); - needcomma = 0; - if (baseClass) - { buf->printf(" : %s", baseClass->toChars()); - needcomma = 1; - } - for (i = 0; i < baseclasses.dim; i++) - { - BaseClass *b = (BaseClass *)baseclasses.data[i]; - - if (needcomma) - buf->writeByte(','); - needcomma = 1; - buf->writestring(b->base->ident->toChars()); - } - buf->writenl(); - buf->writeByte('{'); - buf->writenl(); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - - buf->writestring(" "); - s->toCBuffer(buf); - } - buf->writestring("}"); - buf->writenl(); -} - -#if 0 -void ClassDeclaration::defineRef(Dsymbol *s) -{ - ClassDeclaration *cd; - - AggregateDeclaration::defineRef(s); - cd = s->isClassDeclaration(); - baseType = cd->baseType; - cd->baseType = NULL; -} -#endif - -/******************************************* - * Determine if 'this' is a base class of cd. - */ - -int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) -{ - //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); - if (poffset) - *poffset = 0; - while (cd) - { - if (this == cd->baseClass) - return 1; - - /* cd->baseClass might not be set if cd is forward referenced. - */ - if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration()) - { - cd->error("base class is forward referenced by %s", toChars()); - } - - cd = cd->baseClass; - } - return 0; -} - -Dsymbol *ClassDeclaration::search(Identifier *ident, int flags) -{ - Dsymbol *s; - - //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); - if (scope) - semantic(scope); - - if (!members || !symtab || scope) - { error("is forward referenced when looking for '%s'", ident->toChars()); - //*(char*)0=0; - return NULL; - } - - s = ScopeDsymbol::search(ident, flags); - if (!s) - { - // Search bases classes in depth-first, left to right order - - int i; - - for (i = 0; i < baseclasses.dim; i++) - { - BaseClass *b = (BaseClass *)baseclasses.data[i]; - - if (b->base) - { - if (!b->base->symtab) - error("base %s is forward referenced", b->base->ident->toChars()); - else - { - s = b->base->search(ident, flags); - if (s) - break; - } - } - } - } - return s; -} - -/**************** - * Find virtual function matching identifier and type. - * Used to build virtual function tables for interface implementations. - */ - -FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) -{ - unsigned i; - - for (i = 0; i < vtbl.dim; i++) - { - FuncDeclaration *fd = (FuncDeclaration *)vtbl.data[i]; - - if (ident == fd->ident && - tf->equals(fd->type)) - return fd; - } - - return NULL; -} - -void ClassDeclaration::interfaceSemantic(Scope *sc) -{ int i; - - vtblInterfaces = new Array(); - vtblInterfaces->reserve(interfaces_dim); - - for (i = 0; i < interfaces_dim; i++) - { - BaseClass *b = interfaces[i]; - - // If this is an interface, and it derives from a COM interface, - // then this is a COM interface too. - if (b->base->isCOMclass()) - com = 1; - - vtblInterfaces->push(b); - b->copyBaseInterfaces(vtblInterfaces); - } -} - -/**************************************** - */ - -int ClassDeclaration::isCOMclass() -{ - return com; -} - - -/**************************************** - */ - -int ClassDeclaration::isAbstract() -{ - if (isabstract) - return TRUE; - for (int i = 1; i < vtbl.dim; i++) - { - FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration(); - - //printf("\tvtbl[%d] = %p\n", i, fd); - if (!fd || fd->isAbstract()) - { - isabstract |= 1; - return TRUE; - } - } - return FALSE; -} - -/**************************************** - * Determine if slot 0 of the vtbl[] is reserved for something else. - * For class objects, yes, this is where the classinfo ptr goes. - * For COM interfaces, no. - * For non-COM interfaces, yes, this is where the Interface ptr goes. - */ - -int ClassDeclaration::vtblOffset() -{ - return 1; -} - -/**************************************** - */ - -char *ClassDeclaration::kind() -{ - return "class"; -} - -/**************************************** - */ - -void ClassDeclaration::addLocalClass(Array *aclasses) -{ - aclasses->push(this); -} - -/********************************* InterfaceDeclaration ****************************/ - -InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, Array *baseclasses) - : ClassDeclaration(loc, id, baseclasses) -{ - com = 0; - if (id == Id::IUnknown) // IUnknown is the root of all COM objects - com = 1; -} - -Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s) -{ - InterfaceDeclaration *id; - - if (s) - id = (InterfaceDeclaration *)s; - else - id = new InterfaceDeclaration(loc, ident, NULL); - - ClassDeclaration::syntaxCopy(id); - return id; -} - -void InterfaceDeclaration::semantic(Scope *sc) -{ int i; - - //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); - if (!scope) - { type = type->semantic(loc, sc); - handle = handle->semantic(loc, sc); - } - if (!members) // if forward reference - { //printf("\tinterface '%s' is forward referenced\n", toChars()); - return; - } - if (symtab) // if already done - { if (!scope) - return; - } - else - symtab = new DsymbolTable(); - - Scope *scx = NULL; - if (scope) - { sc = scope; - scx = scope; // save so we don't make redundant copies - scope = NULL; - } - - // Check for errors, handle forward references - for (i = 0; i < baseclasses.dim; ) - { TypeClass *tc; - BaseClass *b; - Type *tb; - - b = (BaseClass *)baseclasses.data[i]; - b->type = b->type->semantic(loc, sc); - tb = b->type->toBasetype(); - if (tb->ty == Tclass) - tc = (TypeClass *)tb; - else - tc = NULL; - if (!tc || !tc->sym->isInterfaceDeclaration()) - { - error("base type must be interface, not %s", b->type->toChars()); - baseclasses.remove(i); - continue; - } - else - { - b->base = tc->sym; - if (b->base == this) - { - error("base interface same as interface"); - baseclasses.remove(i); - continue; - } - if (!b->base->symtab || b->base->scope) - { - //error("forward reference of base class %s", baseClass->toChars()); - // Forward reference of base, try again later - //printf("\ttry later, forward reference of base %s\n", baseClass->toChars()); - scope = scx ? scx : new Scope(*sc); - scope->setNoFree(); - scope->module->addDeferredSemantic(this); - return; - } - } - i++; - } - - interfaces_dim = baseclasses.dim; - interfaces = (BaseClass **)baseclasses.data; - - interfaceSemantic(sc); - - if (vtblOffset()) - vtbl.push(this); // leave room at vtbl[0] for classinfo - - // Cat together the vtbl[]'s from base interfaces - for (i = 0; i < interfaces_dim; i++) - { BaseClass *b = interfaces[i]; - - // Skip if b has already appeared - for (int k = 0; k < i; k++) - { - if (b == interfaces[i]) - goto Lcontinue; - } - - // Copy vtbl[] from base class - if (b->base->vtblOffset()) - { int d = b->base->vtbl.dim; - vtbl.reserve(d - 1); - for (int j = 1; j < d; j++) - vtbl.push(b->base->vtbl.data[j]); - } - else - vtbl.append(&b->base->vtbl); - - Lcontinue: - ; - } - - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->addMember(this); - } - - sc = sc->push(this); - sc->parent = this; - if (isCOMclass()) - sc->linkage = LINKwindows; - sc->structalign = 8; - structalign = sc->structalign; - sc->offset = 8; - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic(sc); - } - //members->print(); - sc->pop(); - //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); -} - - -/******************************************* - * Determine if 'this' is a base class of cd. - * (Actually, if it is an interface supported by cd) - * Output: - * *poffset offset to start of class - * OFFSET_RUNTIME must determine offset at runtime - * Returns: - * 0 not a base - * 1 is a base - */ - -int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) -{ - unsigned j; - - //printf("InterfaceDeclaration::isBaseOf(cd = '%s')\n", cd->toChars()); - assert(!baseClass); - for (j = 0; j < cd->interfaces_dim; j++) - { - BaseClass *b = cd->interfaces[j]; - - if (this == b->base) - { - //printf("\tfound at offset %d\n", b->offset); - if (poffset) - { *poffset = b->offset; - if (j && cd->isInterfaceDeclaration()) - *poffset = OFFSET_RUNTIME; - } - return 1; - } - if (isBaseOf(b, poffset)) - { if (j && poffset && cd->isInterfaceDeclaration()) - *poffset = OFFSET_RUNTIME; - return 1; - } - } - - if (cd->baseClass && isBaseOf(cd->baseClass, poffset)) - return 1; - - if (poffset) - *poffset = 0; - return 0; -} - - -int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset) -{ - //printf("InterfaceDeclaration::isBaseOf(bc = '%s')\n", bc->base->toChars()); - for (unsigned j = 0; j < bc->baseInterfaces_dim; j++) - { - BaseClass *b = &bc->baseInterfaces[j]; - - if (this == b->base) - { - if (poffset) - { *poffset = b->offset; - } - return 1; - } - if (isBaseOf(b, poffset)) - { - return 1; - } - } - if (poffset) - *poffset = 0; - return 0; -} - -/**************************************** - * Determine if slot 0 of the vtbl[] is reserved for something else. - * For class objects, yes, this is where the classinfo ptr goes. - * For COM interfaces, no. - * For non-COM interfaces, yes, this is where the Interface ptr goes. - */ - -int InterfaceDeclaration::vtblOffset() -{ - if (isCOMclass()) - return 0; - return 1; -} - -/******************************************* - */ - -char *InterfaceDeclaration::kind() -{ - return "interface"; -} - - -/******************************** BaseClass *****************************/ - -BaseClass::BaseClass() -{ - memset(this, 0, sizeof(BaseClass)); -} - -BaseClass::BaseClass(Type *type, enum PROT protection) -{ - //printf("BaseClass(this = %p, '%s')\n", this, type->toChars()); - this->type = type; - this->protection = protection; - base = NULL; - offset = 0; - - baseInterfaces_dim = 0; - baseInterfaces = NULL; -} - -/**************************************** - * Fill in vtbl[] for base class based on member functions of class cd. - * Input: - * vtbl if !=NULL, fill it in - * newinstance !=0 means all entries must be filled in by members - * of cd, not members of any base classes of cd. - * Returns: - * !=0 if any entries were filled in by members of cd (not exclusively - * by base classes) - */ - -int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance) -{ - ClassDeclaration *id = base; - int j; - int result = 0; - - //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars()); - if (vtbl) - vtbl->setDim(base->vtbl.dim); - - // first entry is ClassInfo reference - for (j = base->vtblOffset(); j < base->vtbl.dim; j++) - { - FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration(); - FuncDeclaration *fd; - TypeFunction *tf; - - //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null"); - - assert(ifd); - // Find corresponding function in this class - tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL; - fd = cd->findFunc(ifd->ident, tf); - if (fd && !fd->isAbstract()) - { - //printf(" found\n"); - // Check that calling conventions match - if (fd->linkage != ifd->linkage) - fd->error("linkage doesn't match interface function"); - - // Check that it is current - if (newinstance && - fd->toParent() != cd && - ifd->toParent() == base) - cd->error("interface function %s.%s is not implemented", - id->toChars(), ifd->ident->toChars()); - - if (fd->toParent() == cd) - result = 1; - } - else - { - //printf(" not found\n"); - // BUG: should mark this class as abstract? - if (!cd->isAbstract()) - cd->error("interface function %s.%s isn't implemented", - id->toChars(), ifd->ident->toChars()); - fd = NULL; - } - if (vtbl) - vtbl->data[j] = fd; - } - - return result; -} - -void BaseClass::copyBaseInterfaces(Array *vtblInterfaces) -{ - baseInterfaces_dim = base->interfaces_dim; - baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass)); - - for (int i = 0; i < baseInterfaces_dim; i++) - { - BaseClass *b = &baseInterfaces[i]; - BaseClass *b2 = base->interfaces[i]; - - assert(b2->vtbl.dim == 0); // should not be filled yet - memcpy(b, b2, sizeof(BaseClass)); - - if (i) // single inheritance is i==0 - vtblInterfaces->push(b); // only need for M.I. - b->copyBaseInterfaces(vtblInterfaces); - } -} diff -uNr gdc-0.11/d/root/complex_t.h gdc-0.12/d/root/complex_t.h --- gdc-0.11/d/root/complex_t.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/complex_t.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,66 +0,0 @@ -// Copyright (c) 1999-2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright and Burton Radons -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* Roll our own complex type for compilers that don't support complex - */ - -struct complex_t -{ - long double re; - long double im; - - complex_t() { this->re = 0; this->im = 0; } - complex_t(long double re) { this->re = re; this->im = 0; } - complex_t(long double re, long double im) { this->re = re; this->im = im; } - - complex_t operator + (complex_t y) { complex_t r; r.re = re + y.re; r.im = im + y.im; return r; } - complex_t operator - (complex_t y) { complex_t r; r.re = re - y.re; r.im = im - y.im; return r; } - complex_t operator - () { complex_t r; r.re = -re; r.im = -im; return r; } - complex_t operator * (complex_t y) { return complex_t(re * y.re - im * y.im, im * y.re + re * y.im); } - - complex_t operator / (complex_t y) - { - long double abs_y_re = y.re < 0 ? -y.re : y.re; - long double abs_y_im = y.im < 0 ? -y.im : y.im; - long double r, den; - - if (abs_y_re < abs_y_im) - { - r = y.re / y.im; - den = y.im + r * y.re; - return complex_t((re * r + im) / den, - (im * r - re) / den); - } - else - { - r = y.im / y.re; - den = y.re + r * y.im; - return complex_t((re + r * im) / den, - (im - r * re) / den); - } - } - - operator bool () { return re || im; } -}; - -inline complex_t operator * (long double x, complex_t y) { return complex_t(x) * y; } -inline complex_t operator * (complex_t x, long double y) { return x * complex_t(y); } -inline complex_t operator / (complex_t x, long double y) { return x / complex_t(y); } - - -inline long double creall(complex_t x) -{ - return x.re; -} - -inline long double cimagl(complex_t x) -{ - return x.im; -} - - diff -uNr gdc-0.11/d/root/constfold.c gdc-0.12/d/root/constfold.c --- gdc-0.11/d/root/constfold.c 2005-04-24 18:48:31.000000000 +0200 +++ gdc-0.12/d/root/constfold.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,746 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include -#include -#include - -#if __DMC__ -#include -#endif - -#include "mtype.h" -#include "expression.h" - -#ifdef IN_GCC -#include "d-gcc-real.h" - -/* %% fix? */ -extern "C" bool real_isnan (const real_t *); - -#endif - - -static real_t zero; // work around DMC bug for now - - -/* ================================== isConst() ============================== */ - -int Expression::isConst() -{ - //printf("Expression::isConst(): %s\n", toChars()); - return 0; -} - -int IntegerExp::isConst() -{ - return 1; -} - -int RealExp::isConst() -{ - return 1; -} - -int ImaginaryExp::isConst() -{ - return 1; -} - -int ComplexExp::isConst() -{ - return 1; -} - -int SymOffExp::isConst() -{ - return 2; -} - -/* ================================== constFold() ============================== */ - -Expression *Expression::constFold() -{ - return this; -} - -Expression *NegExp::constFold() -{ - e1 = e1->constFold(); - if (e1->type->isreal()) - { RealExp *e; - - e = new RealExp(loc, -e1->toReal(), type); - return e; - } - else if (e1->type->isimaginary()) - { ImaginaryExp *e; - - e = new ImaginaryExp(loc, -e1->toImaginary(), type); - return e; - } - else if (e1->type->iscomplex()) - { ComplexExp *e; - - e = new ComplexExp(loc, -e1->toComplex(), type); - return e; - } - else - return new IntegerExp(loc, -e1->toInteger(), type); -} - -Expression *ComExp::constFold() -{ - e1 = e1->constFold(); - return new IntegerExp(loc, ~e1->toInteger(), type); -} - -Expression *NotExp::constFold() -{ - e1 = e1->constFold(); - return new IntegerExp(loc, e1->isBool(0), type); -} - -Expression *BoolExp::constFold() -{ - e1 = e1->constFold(); - return new IntegerExp(loc, e1->isBool(1), type); -} - -Expression *CastExp::constFold() -{ - //printf("CastExp::constFold(%s)\n", toChars()); - - e1 = e1->constFold(); - if (e1->op == TOKsymoff && type->size() == e1->type->size()) - { - e1->type = type; - return e1; - } - - Type *tb = type->toBasetype(); - if (tb->ty == Tbit) - return new IntegerExp(loc, e1->toInteger() != 0, type); - if (type->isintegral()) - return new IntegerExp(loc, e1->toInteger(), type); - if (tb->isreal()) - { real_t value = e1->toReal(); - -#if 0 - if (tb->ty == Tfloat32) - { float f = (float)value; - value = f; - } - else if (tb->ty == Tfloat64) - value = (double)value; -#endif - return new RealExp(loc, value, type); - } - if (tb->isimaginary()) - { real_t value = e1->toImaginary(); -#if 0 - if (tb->ty == Timaginary32) - value = (float)value; - else if (tb->ty == Timaginary64) - value = (double)value; -#endif - return new ImaginaryExp(loc, value, type); - } - if (tb->iscomplex()) - { complex_t value = e1->toComplex(); - -#if 0 -#if __DMC__ - if (tb->ty == Tcomplex32) - value = (_Complex float)value; - else if (tb->ty == Tcomplex64) - value = (_Complex double)value; -#else - if (tb->ty == Tcomplex32) - { value.re = (float)value.re; - value.im = (float)value.im; - } - else if (tb->ty == Tcomplex64) - { value.re = (double)value.re; - value.im = (double)value.im; - } -#endif -#endif - return new ComplexExp(loc, value, type); - } - if (tb->isscalar()) - return new IntegerExp(loc, e1->toInteger(), type); - if (tb->ty != Tvoid) - error("cannot cast %s to %s", e1->type->toChars(), type->toChars()); - return this; -} - -Expression *AddExp::constFold() -{ - Expression *e; - - //printf("AddExp::constFold(%s)\n", toChars()); - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e1->op == TOKsymoff && e2->op == TOKsymoff) - return this; - if (type->isreal()) - { - e = new RealExp(loc, e1->toReal() + e2->toReal(), type); - } - else if (type->isimaginary()) - { - e = new ImaginaryExp(loc, e1->toImaginary() + e2->toImaginary(), type); - } - else if (type->iscomplex()) - { - e = new ComplexExp(loc, e1->toComplex() + e2->toComplex(), type); - } - else if (e1->op == TOKsymoff) - { - SymOffExp *soe = (SymOffExp *)e1; - e = new SymOffExp(loc, soe->var, soe->offset + e2->toInteger()); - e->type = type; - } - else if (e2->op == TOKsymoff) - { - SymOffExp *soe = (SymOffExp *)e2; - e = new SymOffExp(loc, soe->var, soe->offset + e1->toInteger()); - e->type = type; - } - else - e = new IntegerExp(loc, e1->toInteger() + e2->toInteger(), type); - return e; -} - -Expression *MinExp::constFold() -{ - Expression *e; - - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e2->op == TOKsymoff) - return this; - if (type->isreal()) - { - e = new RealExp(loc, e1->toReal() - e2->toReal(), type); - } - else if (type->isimaginary()) - { - e = new ImaginaryExp(loc, e1->toImaginary() - e2->toImaginary(), type); - } - else if (type->iscomplex()) - { - e = new ComplexExp(loc, e1->toComplex() - e2->toComplex(), type); - } - else if (e1->op == TOKsymoff) - { - SymOffExp *soe = (SymOffExp *)e1; - e = new SymOffExp(loc, soe->var, soe->offset - e2->toInteger()); - e->type = type; - } - else - { - e = new IntegerExp(loc, e1->toInteger() - e2->toInteger(), type); - } - return e; -} - -Expression *MulExp::constFold() -{ Expression *e; - - //printf("MulExp::constFold(%s)\n", toChars()); - e1 = e1->constFold(); - e2 = e2->constFold(); - if (type->isfloating()) - { complex_t c; - - if (e1->type->isreal()) - c = e1->toReal() * e2->toComplex(); - else if (e1->type->isimaginary()) - c = e1->toImaginary() * e2->toComplex(); - else if (e2->type->isreal()) - c = e1->toComplex() * e2->toReal(); - else if (e2->type->isimaginary()) - c = e1->toComplex() * e2->toImaginary(); - else - c = e1->toComplex() * e2->toComplex(); - - if (type->isreal()) - e = new RealExp(loc, creall(c), type); - else if (type->isimaginary()) - e = new ImaginaryExp(loc, cimagl(c), type); - else if (type->iscomplex()) - e = new ComplexExp(loc, c, type); - else - assert(0); - } - else - { - e = new IntegerExp(loc, e1->toInteger() * e2->toInteger(), type); - } - return e; -} - -Expression *DivExp::constFold() -{ Expression *e; - - e1 = e1->constFold(); - e2 = e2->constFold(); - if (type->isfloating()) - { complex_t c; - - if (e2->type->isreal()) - { - if (e1->type->isreal()) - c = e1->toReal() / e2->toReal(); - else - c = e1->toComplex() / e2->toReal(); - } - else if (e2->type->isimaginary()) - { - if (e1->type->isimaginary()) - c = e1->toImaginary() / e2->toImaginary(); - else - c = e1->toComplex() / e2->toImaginary(); - } - else - c = e1->toComplex() / e2->toComplex(); - - if (type->isreal()) - e = new RealExp(loc, creall(c), type); - else if (type->isimaginary()) - e = new ImaginaryExp(loc, cimagl(c), type); - else if (type->iscomplex()) - e = new ComplexExp(loc, c, type); - else - assert(0); - } - else - { integer_t n1; - integer_t n2; - integer_t n; - - n1 = e1->toInteger(); - n2 = e2->toInteger(); - if (n2 == 0) - { error("divide by 0"); - n2 = 1; - } - if (isunsigned()) - n = ((d_uns64) n1) / ((d_uns64) n2); - else - n = n1 / n2; - e = new IntegerExp(loc, n, type); - } - return e; -} - -Expression *ModExp::constFold() -{ Expression *e; - - e1 = e1->constFold(); - e2 = e2->constFold(); - if (type->isreal()) - { real_t c; - -#ifdef IN_GCC - c = e1->toReal() % e2->toReal(); -#else - c = fmodl(e1->toReal(), e2->toReal()); -#endif - e = new RealExp(loc, c, type); - } - else if (type->isfloating()) - { - assert(0); - } - else - { integer_t n1; - integer_t n2; - integer_t n; - - n1 = e1->toInteger(); - n2 = e2->toInteger(); - if (isunsigned()) - n = ((d_uns64) n1) % ((d_uns64) n2); - else - n = n1 % n2; - e = new IntegerExp(loc, n, type); - } - return e; -} - -Expression *ShlExp::constFold() -{ - //printf("ShlExp::constFold(%s)\n", toChars()); - e1 = e1->constFold(); - e2 = e2->constFold(); - return new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type); -} - -Expression *ShrExp::constFold() -{ - unsigned count; - integer_t value; - - e1 = e1->constFold(); - e2 = e2->constFold(); - value = e1->toInteger(); - count = e2->toInteger(); - switch (e1->type->toBasetype()->ty) - { - case Tint8: - case Tuns8: - value = (d_int8)(value) >> count; - break; - - case Tint16: - case Tuns16: - value = (d_int16)(value) >> count; - break; - - case Tint32: - case Tuns32: - value = (d_int32)(value) >> count; - break; - - case Tint64: - case Tuns64: - value = (d_int64)(value) >> count; - break; - - default: - assert(0); - } - return new IntegerExp(loc, value, type); -} - -Expression *UshrExp::constFold() -{ - unsigned count; - integer_t value; - - e1 = e1->constFold(); - e2 = e2->constFold(); - value = e1->toInteger(); - count = e2->toInteger(); - switch (e1->type->toBasetype()->ty) - { - case Tint8: - case Tuns8: - value = (value & 0xFF) >> count; - break; - - case Tint16: - case Tuns16: - value = (value & 0xFFFF) >> count; - break; - - case Tint32: - case Tuns32: - value = (value & 0xFFFFFFFF) >> count; - break; - - case Tint64: - case Tuns64: - value = (d_uns64)(value) >> count; - break; - - default: - assert(0); - } - return new IntegerExp(loc, value, type); -} - -Expression *AndExp::constFold() -{ - e1 = e1->constFold(); - e2 = e2->constFold(); - return new IntegerExp(loc, e1->toInteger() & e2->toInteger(), type); -} - -Expression *OrExp::constFold() -{ - e1 = e1->constFold(); - e2 = e2->constFold(); - return new IntegerExp(loc, e1->toInteger() | e2->toInteger(), type); -} - -Expression *XorExp::constFold() -{ - e1 = e1->constFold(); - e2 = e2->constFold(); - return new IntegerExp(loc, e1->toInteger() ^ e2->toInteger(), type); -} - -Expression *AndAndExp::constFold() -{ integer_t n; - - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e1->type->isfloating()) - n = e1->toComplex() && e2->toComplex(); - else - n = e1->toInteger() && e2->toInteger(); - return new IntegerExp(loc, n, type); -} - -Expression *OrOrExp::constFold() -{ integer_t n; - - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e1->type->isfloating()) - n = e1->toComplex() || e2->toComplex(); - else - n = e1->toInteger() || e2->toInteger(); - return new IntegerExp(loc, n, type); -} - -Expression *CmpExp::constFold() -{ integer_t n; - real_t r1; - real_t r2; - - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e1->type->isreal()) - { - r1 = e1->toReal(); - r2 = e2->toReal(); - goto L1; - } - else if (e1->type->isimaginary()) - { - r1 = e1->toImaginary(); - r2 = e2->toImaginary(); - L1: -#if __DMC__ - // DMC is the only compiler I know of that handles NAN arguments - // correctly in comparisons. - switch (op) - { - case TOKlt: n = r1 < r2; break; - case TOKle: n = r1 <= r2; break; - case TOKgt: n = r1 > r2; break; - case TOKge: n = r1 >= r2; break; - - case TOKleg: n = r1 <>= r2; break; - case TOKlg: n = r1 <> r2; break; - case TOKunord: n = r1 !<>= r2; break; - case TOKue: n = r1 !<> r2; break; - case TOKug: n = r1 !<= r2; break; - case TOKuge: n = r1 !< r2; break; - case TOKul: n = r1 !>= r2; break; - case TOKule: n = r1 !> r2; break; - - default: - assert(0); - } -#else - // Don't rely on compiler, handle NAN arguments separately - if (real_isnan(&r1) || real_isnan(&r2)) // if unordered - { - switch (op) - { - case TOKlt: n = 0; break; - case TOKle: n = 0; break; - case TOKgt: n = 0; break; - case TOKge: n = 0; break; - - case TOKleg: n = 0; break; - case TOKlg: n = 0; break; - case TOKunord: n = 1; break; - case TOKue: n = 1; break; - case TOKug: n = 1; break; - case TOKuge: n = 1; break; - case TOKul: n = 1; break; - case TOKule: n = 1; break; - - default: - assert(0); - } - } - else - { - switch (op) - { - case TOKlt: n = r1 < r2; break; - case TOKle: n = r1 <= r2; break; - case TOKgt: n = r1 > r2; break; - case TOKge: n = r1 >= r2; break; - - case TOKleg: n = 1; break; - case TOKlg: n = r1 != r2; break; - case TOKunord: n = 0; break; - case TOKue: n = r1 == r2; break; - case TOKug: n = r1 > r2; break; - case TOKuge: n = r1 >= r2; break; - case TOKul: n = r1 < r2; break; - case TOKule: n = r1 <= r2; break; - - default: - assert(0); - } - } -#endif - } - else if (e1->type->iscomplex()) - { - assert(0); - } - else - { integer_t n1; - integer_t n2; - - n1 = e1->toInteger(); - n2 = e2->toInteger(); - if (isunsigned()) - { - switch (op) - { - case TOKlt: n = ((d_uns64) n1) < ((d_uns64) n2); break; - case TOKle: n = ((d_uns64) n1) <= ((d_uns64) n2); break; - case TOKgt: n = ((d_uns64) n1) > ((d_uns64) n2); break; - case TOKge: n = ((d_uns64) n1) >= ((d_uns64) n2); break; - - case TOKleg: n = 1; break; - case TOKlg: n = ((d_uns64) n1) != ((d_uns64) n2); break; - case TOKunord: n = 0; break; - case TOKue: n = ((d_uns64) n1) == ((d_uns64) n2); break; - case TOKug: n = ((d_uns64) n1) > ((d_uns64) n2); break; - case TOKuge: n = ((d_uns64) n1) >= ((d_uns64) n2); break; - case TOKul: n = ((d_uns64) n1) < ((d_uns64) n2); break; - case TOKule: n = ((d_uns64) n1) <= ((d_uns64) n2); break; - - default: - assert(0); - } - } - else - { - switch (op) - { - case TOKlt: n = n1 < n2; break; - case TOKle: n = n1 <= n2; break; - case TOKgt: n = n1 > n2; break; - case TOKge: n = n1 >= n2; break; - - case TOKleg: n = 1; break; - case TOKlg: n = n1 != n2; break; - case TOKunord: n = 0; break; - case TOKue: n = n1 == n2; break; - case TOKug: n = n1 > n2; break; - case TOKuge: n = n1 >= n2; break; - case TOKul: n = n1 < n2; break; - case TOKule: n = n1 <= n2; break; - - default: - assert(0); - } - } - } - return new IntegerExp(loc, n, type); -} - -Expression *EqualExp::constFold() -{ int cmp; - real_t r1; - real_t r2; - - assert(op == TOKequal || op == TOKnotequal); - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e1->type->isreal()) - { - r1 = e1->toReal(); - r2 = e2->toReal(); - goto L1; - } - else if (e1->type->isimaginary()) - { - r1 = e1->toImaginary(); - r2 = e2->toImaginary(); - L1: -#if __DMC__ - cmp = (r1 == r2); -#else - if (real_isnan(&r1) || real_isnan(&r2)) // if unordered - { - cmp = 0; - } - else - { - cmp = (r1 == r2); - } -#endif - } - else if (e1->type->iscomplex()) - { - cmp = e1->toComplex() == e2->toComplex(); - } - else - { - cmp = (e1->toInteger() == e2->toInteger()); - } - if (op == TOKnotequal) - cmp ^= 1; - return new IntegerExp(loc, cmp, type); -} - -Expression *IdentityExp::constFold() -{ int cmp; - - e1 = e1->constFold(); - e2 = e2->constFold(); - if (e1->type->isfloating()) - { - cmp = e1->toComplex() == e2->toComplex(); - } - else if (e1->type->isintegral()) - { - cmp = (e1->toInteger() == e2->toInteger()); - } - else if (e1->op == TOKsymoff && e2->op == TOKsymoff) - { - SymOffExp *es1 = (SymOffExp *)e1; - SymOffExp *es2 = (SymOffExp *)e2; - - cmp = (es1->var == es2->var && es1->offset == es2->offset); - } - else - { - return this; - } - if (op == TOKnotidentity) - cmp ^= 1; - return new IntegerExp(loc, cmp, type); -} - - -Expression *CondExp::constFold() -{ - int n; - - econd = econd->constFold(); - if (econd->type->isfloating()) - n = econd->toComplex() != 0; - else - n = econd->toInteger() != 0; - return n ? e1->constFold() : e2->constFold(); -} - diff -uNr gdc-0.11/d/root/dchar.c gdc-0.12/d/root/dchar.c --- gdc-0.11/d/root/dchar.c 2005-02-21 02:40:45.000000000 +0100 +++ gdc-0.12/d/root/dchar.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,465 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, February 2005 -*/ - - -#include -#include -#include - -#include "dchar.h" -#include "mem.h" - -#if M_UNICODE - -// Converts a char string to Unicode - -dchar *Dchar::dup(char *p) -{ - dchar *s; - size_t len; - - if (!p) - return NULL; - len = strlen(p); - s = (dchar *)mem.malloc((len + 1) * sizeof(dchar)); - for (unsigned i = 0; i < len; i++) - { - s[i] = (dchar)(p[i] & 0xFF); - } - s[len] = 0; - return s; -} - -dchar *Dchar::memchr(dchar *p, int c, int count) -{ - int u; - - for (u = 0; u < count; u++) - { - if (p[u] == c) - return p + u; - } - return NULL; -} - -#if _WIN32 && __DMC__ -__declspec(naked) -unsigned Dchar::calcHash(const dchar *str, unsigned len) -{ - __asm - { - mov ECX,4[ESP] - mov EDX,8[ESP] - xor EAX,EAX - test EDX,EDX - je L92 - -LC8: cmp EDX,1 - je L98 - cmp EDX,2 - je LAE - - add EAX,[ECX] -// imul EAX,EAX,025h - lea EAX,[EAX][EAX*8] - add ECX,4 - sub EDX,2 - jmp LC8 - -L98: mov DX,[ECX] - and EDX,0FFFFh - add EAX,EDX - ret - -LAE: add EAX,[ECX] -L92: ret - } -} -#else -unsigned Dchar::calcHash(const dchar *str, unsigned len) -{ - unsigned hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash += *(unsigned short *)str; - return hash; - - case 2: - hash += *(unsigned long *)str; - return hash; - - default: - hash += *(long *)str; - hash *= 37; - str += 2; - len -= 2; - break; - } - } -} -#endif - -unsigned Dchar::icalcHash(const dchar *str, unsigned len) -{ - unsigned hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash += *(unsigned short *)str | 0x20; - return hash; - - case 2: - hash += *(unsigned long *)str | 0x200020; - return hash; - - default: - hash += *(unsigned long *)str | 0x200020; - hash *= 37; - str += 2; - len -= 2; - break; - } - } -} - -#elif MCBS - -unsigned Dchar::calcHash(const dchar *str, unsigned len) -{ - unsigned hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(unsigned char *)str; - return hash; - - case 2: - hash *= 37; - hash += *(unsigned short *)str; - return hash; - - case 3: - hash *= 37; - hash += (*(unsigned short *)str << 8) + - ((unsigned char *)str)[2]; - return hash; - - default: - hash *= 37; - hash += *(long *)str; - str += 4; - len -= 4; - break; - } - } -} - -#elif UTF8 - -// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335 - -char Dchar::mblen[256] = -{ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1, -}; - -dchar *Dchar::dec(dchar *pstart, dchar *p) -{ - while ((p[-1] & 0xC0) == 0x80) - p--; - return p; -} - -int Dchar::get(dchar *p) -{ - unsigned c; - unsigned char *q = (unsigned char *)p; - - c = q[0]; - switch (mblen[c]) - { - case 2: - c = ((c - 0xC0) << 6) | - (q[1] - 0x80); - break; - - case 3: - c = ((c - 0xE0) << 12) | - ((q[1] - 0x80) << 6) | - (q[2] - 0x80); - break; - - case 4: - c = ((c - 0xF0) << 18) | - ((q[1] - 0x80) << 12) | - ((q[2] - 0x80) << 6) | - (q[3] - 0x80); - break; - - case 5: - c = ((c - 0xF8) << 24) | - ((q[1] - 0x80) << 18) | - ((q[2] - 0x80) << 12) | - ((q[3] - 0x80) << 6) | - (q[4] - 0x80); - break; - - case 6: - c = ((c - 0xFC) << 30) | - ((q[1] - 0x80) << 24) | - ((q[2] - 0x80) << 18) | - ((q[3] - 0x80) << 12) | - ((q[4] - 0x80) << 6) | - (q[5] - 0x80); - break; - } - return c; -} - -dchar *Dchar::put(dchar *p, unsigned c) -{ - if (c <= 0x7F) - { - *p++ = c; - } - else if (c <= 0x7FF) - { - p[0] = 0xC0 + (c >> 6); - p[1] = 0x80 + (c & 0x3F); - p += 2; - } - else if (c <= 0xFFFF) - { - p[0] = 0xE0 + (c >> 12); - p[1] = 0x80 + ((c >> 6) & 0x3F); - p[2] = 0x80 + (c & 0x3F); - p += 3; - } - else if (c <= 0x1FFFFF) - { - p[0] = 0xF0 + (c >> 18); - p[1] = 0x80 + ((c >> 12) & 0x3F); - p[2] = 0x80 + ((c >> 6) & 0x3F); - p[3] = 0x80 + (c & 0x3F); - p += 4; - } - else if (c <= 0x3FFFFFF) - { - p[0] = 0xF8 + (c >> 24); - p[1] = 0x80 + ((c >> 18) & 0x3F); - p[2] = 0x80 + ((c >> 12) & 0x3F); - p[3] = 0x80 + ((c >> 6) & 0x3F); - p[4] = 0x80 + (c & 0x3F); - p += 5; - } - else if (c <= 0x7FFFFFFF) - { - p[0] = 0xFC + (c >> 30); - p[1] = 0x80 + ((c >> 24) & 0x3F); - p[2] = 0x80 + ((c >> 18) & 0x3F); - p[3] = 0x80 + ((c >> 12) & 0x3F); - p[4] = 0x80 + ((c >> 6) & 0x3F); - p[5] = 0x80 + (c & 0x3F); - p += 6; - } - else - assert(0); // not a UCS-4 character - return p; -} - -unsigned Dchar::calcHash(const dchar *str, unsigned len) -{ - unsigned hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(unsigned char *)str; - return hash; - - case 2: - hash *= 37; - hash += *(unsigned short *)str; - return hash; - - case 3: - hash *= 37; - hash += (*(unsigned short *)str << 8) + - ((unsigned char *)str)[2]; - return hash; - - default: - hash *= 37; - hash += *(long *)str; - str += 4; - len -= 4; - break; - } - } -} - -#else // ascii - -unsigned Dchar::calcHash(const dchar *str, unsigned len) -{ - unsigned hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(unsigned char *)str; - return hash; - - case 2: - hash *= 37; - hash += str[0] * 256 + str[1]; -/* hash += *(unsigned short *)str; */ - return hash; - - case 3: - hash *= 37; - hash += (str[0] * 256 + str[1]) * 256 + str[2]; -/* hash += (*(unsigned short *)str << 8) + - ((unsigned char *)str)[2]; */ - return hash; - - default: - hash *= 37; - hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; -/* hash += *(long*)str; */ - str += 4; - len -= 4; - break; - } - } -} - -unsigned Dchar::icalcHash(const dchar *str, unsigned len) -{ - unsigned hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(unsigned char *)str | 0x20; - return hash; - - case 2: - hash *= 37; - hash += *(unsigned short *)str | 0x2020; - return hash; - - case 3: - hash *= 37; - hash += ((*(unsigned short *)str << 8) + - ((unsigned char *)str)[2]) | 0x202020; - return hash; - - default: - hash *= 37; - hash += *(long *)str | 0x20202020; - str += 4; - len -= 4; - break; - } - } -} - -#endif - -#if 0 -#include - -void main() -{ - // Print out values to hardcode into Dchar::mblen[] - int c; - int s; - - for (c = 0; c < 256; c++) - { - s = 1; - if (c >= 0xC0 && c <= 0xDF) - s = 2; - if (c >= 0xE0 && c <= 0xEF) - s = 3; - if (c >= 0xF0 && c <= 0xF7) - s = 4; - if (c >= 0xF8 && c <= 0xFB) - s = 5; - if (c >= 0xFC && c <= 0xFD) - s = 6; - - printf("%d", s); - if ((c & 15) == 15) - printf(",\n"); - else - printf(","); - } -} -#endif diff -uNr gdc-0.11/d/root/dchar.h gdc-0.12/d/root/dchar.h --- gdc-0.11/d/root/dchar.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/dchar.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,198 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - - -#ifndef DCHAR_H -#define DCHAR_H - -#if __GNUC__ -#include "gnuc.h" -#endif - -#if _MSC_VER - // Disable useless warnings about unreferenced functions - #pragma warning (disable : 4514) -#endif - -//#include "root.h" - -#undef TEXT - -// NOTE: All functions accepting pointer arguments must not be NULL - -#if M_UNICODE - -#include -#include - -typedef wchar_t dchar; -#define TEXT(x) L##x - -#define Dchar_mbmax 1 - -struct Dchar -{ - static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; } - static int len(const dchar *p) { return wcslen(p); } - static dchar get(dchar *p) { return *p; } - static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; } - static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; } - static int cmp(dchar *s1, dchar *s2) - { -#if __DMC__ - if (!*s1 && !*s2) // wcscmp is broken - return 0; -#endif - return wcscmp(s1, s2); -#if 0 - return (*s1 == *s2) - ? wcscmp(s1, s2) - : ((int)*s1 - (int)*s2); -#endif - } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } - static int isAlpha(dchar c) { return iswalpha(c); } - static int isUpper(dchar c) { return iswupper(c); } - static int isLower(dchar c) { return iswlower(c); } - static int isLocaleUpper(dchar c) { return isUpper(c); } - static int isLocaleLower(dchar c) { return isLower(c); } - static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; } - static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory? - static dchar *dup(char *p); - static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); } - static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); } - static dchar *memchr(dchar *p, int c, int count); - static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); } - static unsigned calcHash(const dchar *str, unsigned len); - - // Case insensitive versions - static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); } - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); } - static unsigned icalcHash(const dchar *str, unsigned len); -}; - -#elif MCBS - -#include -#include - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax MB_LEN_MAX - -#elif UTF8 - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax 6 - -struct Dchar -{ - static char mblen[256]; - - static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; } - static dchar *dec(dchar *pstart, dchar *p); - static int len(const dchar *p) { return strlen(p); } - static int get(dchar *p); - static int getprev(dchar *pstart, dchar *p) - { return *dec(pstart, p) & 0xFF; } - static dchar *put(dchar *p, unsigned c); - static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } - static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; } - static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; } - static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; } - static int isLocaleUpper(dchar c) { return isUpper(c); } - static int isLocaleLower(dchar c) { return isLower(c); } - static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; } - static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? - static dchar *chr(dchar *p, int c) { return strchr(p, c); } - static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } - static dchar *memchr(dchar *p, int c, int count) - { return (dchar *)::memchr(p, c, count); } - static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } - static unsigned calcHash(const dchar *str, unsigned len); - - // Case insensitive versions - static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); } - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); } -}; - -#else - -#include -#ifndef GCC_SAFE_DMD -#include -#endif - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax 1 - -struct Dchar -{ - static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, dchar *p) { return p - 1; } - static int len(const dchar *p) { return strlen(p); } - static int get(dchar *p) { return *p & 0xFF; } - static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; } - static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; } - static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } -#ifndef GCC_SAFE_DMD - static int isAlpha(dchar c) { return isalpha(c); } - static int isUpper(dchar c) { return isupper(c); } - static int isLower(dchar c) { return islower(c); } - static int isLocaleUpper(dchar c) { return isupper(c); } - static int isLocaleLower(dchar c) { return islower(c); } - static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; } - static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? -#endif - static dchar *chr(dchar *p, int c) { return strchr(p, c); } - static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } - static dchar *memchr(dchar *p, int c, int count) - { return (dchar *)::memchr(p, c, count); } - static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } - static unsigned calcHash(const dchar *str, unsigned len); - - // Case insensitive versions -#ifdef __GNUC__ - static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); } -#else - static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); } -#endif - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); } - static unsigned icalcHash(const dchar *str, unsigned len); -}; - -#endif -#endif - diff -uNr gdc-0.11/d/root/debcond.c gdc-0.12/d/root/debcond.c --- gdc-0.11/d/root/debcond.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/debcond.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,175 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "id.h" -#include "init.h" -#include "declaration.h" -#include "identifier.h" -#include "expression.h" -#include "debcond.h" -#include "module.h" - -int findCondition(Array *ids, Identifier *ident) -{ - if (ids) - { - for (int i = 0; i < ids->dim; i++) - { - char *id = (char *)ids->data[i]; - - if (strcmp(id, ident->toChars()) == 0) - return TRUE; - } - } - - return FALSE; -} - -/* ============================================================ */ - -Condition::Condition(Module *mod, unsigned level, Identifier *ident) -{ - this->mod = mod; - this->level = level; - this->ident = ident; -} - -int Condition::include() -{ - assert(0); - return FALSE; -} - -int Condition::isBool(int result) -{ - return (result == include()); -} - -Expression *Condition::toExpr() -{ - assert(0); // BUG: not implemented - return NULL; -} - -void Condition::toCBuffer(OutBuffer *buf) -{ - if (ident) - buf->printf("%s", ident->toChars()); - else - buf->printf("%u", level); -} - -/* ============================================================ */ - -void DebugCondition::setGlobalLevel(unsigned level) -{ - global.params.debuglevel = level; -} - -void DebugCondition::addGlobalIdent(char *ident) -{ - if (!global.params.debugids) - global.params.debugids = new Array(); - global.params.debugids->push(ident); -} - - -DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident) - : Condition(mod, level, ident) -{ -} - -int DebugCondition::include() -{ - //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel); - if (ident) - { - if (findCondition(mod->debugids, ident)) - return TRUE; - - if (findCondition(global.params.debugids, ident)) - return TRUE; - } - else if (level <= global.params.debuglevel || level <= mod->debuglevel) - return TRUE; - return FALSE; -} - -/* ============================================================ */ - -void VersionCondition::setGlobalLevel(unsigned level) -{ - global.params.versionlevel = level; -} - -void VersionCondition::checkPredefined(char *ident) -{ - static char* reserved[] = - { - "DigitalMars", "X86", "X86_64", - "Windows", "Win32", "Win64", - "linux", - "LittleEndian", "BigEndian", - "all", - "none", - }; - - for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) - { - if (strcmp(ident, reserved[i]) == 0) - goto Lerror; - } - - if (ident[0] == 'D' && ident[1] == '_') - goto Lerror; - - return; - - Lerror: - error("version identifier '%s' is reserved and cannot be set", ident); -} - -void VersionCondition::addGlobalIdent(char *ident) -{ - checkPredefined(ident); - addPredefinedGlobalIdent(ident); -} - -void VersionCondition::addPredefinedGlobalIdent(char *ident) -{ - if (!global.params.versionids) - global.params.versionids = new Array(); - global.params.versionids->push(ident); -} - - -VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident) - : Condition(mod, level, ident) -{ -} - -int VersionCondition::include() -{ - //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel); - if (ident) - { - if (findCondition(mod->versionids, ident)) - return TRUE; - - if (findCondition(global.params.versionids, ident)) - return TRUE; - } - else if (level <= global.params.versionlevel || level <= mod->versionlevel) - return TRUE; - return FALSE; -} - diff -uNr gdc-0.11/d/root/debcond.h gdc-0.12/d/root/debcond.h --- gdc-0.11/d/root/debcond.h 2005-04-17 15:49:49.000000000 +0200 +++ gdc-0.12/d/root/debcond.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,55 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_DEBCOND_H -#define DMD_DEBCOND_H - -struct Expression; -struct Identifier; -struct OutBuffer; -struct Module; - -struct Condition -{ - unsigned level; - Identifier *ident; - Module *mod; - - Condition(Module *mod, unsigned level, Identifier *ident); - - virtual int include(); - int isBool(int result); - Expression *toExpr(); - void toCBuffer(OutBuffer *buf); -}; - -struct DebugCondition : Condition -{ - static void setGlobalLevel(unsigned level); - static void addGlobalIdent(char *ident); - static void addPredefinedGlobalIdent(char *ident); - - DebugCondition(Module *mod, unsigned level, Identifier *ident); - - int include(); -}; - -struct VersionCondition : Condition -{ - static void setGlobalLevel(unsigned level); - static void checkPredefined(char *ident); - static void addGlobalIdent(char *ident); - static void addPredefinedGlobalIdent(char *ident); - - VersionCondition(Module *mod, unsigned level, Identifier *ident); - - int include(); -}; - -#endif /* DMD_DEBCOND_H */ diff -uNr gdc-0.11/d/root/declaration.c gdc-0.12/d/root/declaration.c --- gdc-0.11/d/root/declaration.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/declaration.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,821 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "init.h" -#include "declaration.h" -#include "attrib.h" -#include "mtype.h" -#include "template.h" -#include "scope.h" -#include "aggregate.h" -#include "module.h" -#include "id.h" -#include "expression.h" - -/********************************* Declaration ****************************/ - -Declaration::Declaration(Identifier *id) - : Dsymbol(id) -{ - type = NULL; - storage_class = STCundefined; - protection = PROTundefined; - linkage = LINKdefault; -} - -void Declaration::semantic(Scope *sc) -{ -} - -char *Declaration::kind() -{ - return "declaration"; -} - -unsigned Declaration::size(Loc loc) -{ - assert(type); - return type->size(); -} - -int Declaration::isStaticConstructor() -{ - return FALSE; -} - -int Declaration::isStaticDestructor() -{ - return FALSE; -} - -int Declaration::isDelete() -{ - return FALSE; -} - -int Declaration::isDataseg() -{ - return FALSE; -} - -int Declaration::isCodeseg() -{ - return FALSE; -} - -enum PROT Declaration::prot() -{ - return protection; -} - -/********************************* TypedefDeclaration ****************************/ - -TypedefDeclaration::TypedefDeclaration(Identifier *id, Type *basetype, Initializer *init) - : Declaration(id) -{ - this->type = new TypeTypedef(this); - this->basetype = basetype->toBasetype(); - this->init = init; - this->sem = 0; -} - -Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) -{ - Type *basetype = this->basetype->syntaxCopy(); - - Initializer *init = NULL; - if (this->init) - init = this->init->syntaxCopy(); - - assert(!s); - TypedefDeclaration *st; - st = new TypedefDeclaration(ident, basetype, init); - return st; -} - -void TypedefDeclaration::semantic(Scope *sc) -{ - //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem); - if (sem == 0) - { sem = 1; - basetype = basetype->semantic(loc, sc); - sem = 2; - if (sc->parent->isFuncDeclaration() && init) - semantic2(sc); - } - else if (sem == 1) - { - error("circular definition"); - } -} - -void TypedefDeclaration::semantic2(Scope *sc) -{ - //printf("TypedefDeclaration::semantic2()\n"); - if (sem == 2) - { sem = 3; - if (init) - { - init = init->semantic(sc, basetype); - - ExpInitializer *ie = init->isExpInitializer(); - if (ie) - { - if (ie->exp->type == basetype) - ie->exp->type = type; - } - } - } -} - -char *TypedefDeclaration::kind() -{ - return "typedef"; -} - -Type *TypedefDeclaration::getType() -{ - return type; -} - -void TypedefDeclaration::toCBuffer(OutBuffer *buf) -{ - buf->writestring("typedef "); - basetype->toCBuffer(buf, ident); - buf->writeByte(';'); - buf->writenl(); -} - -/********************************* AliasDeclaration ****************************/ - -AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type) - : Declaration(id) -{ - //printf("AliasDeclaration(id = '%s')\n", id->toChars()); - this->loc = loc; - this->type = type; - this->aliassym = NULL; - this->overnext = NULL; - this->inSemantic = 0; - assert(type); -} - -AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s) - : Declaration(id) -{ - assert(s != this); - this->loc = loc; - this->type = NULL; - this->aliassym = s; - this->overnext = NULL; - this->inSemantic = 0; - assert(s); -} - -Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(!s); - AliasDeclaration *sa; - if (type) - sa = new AliasDeclaration(loc, ident, type->syntaxCopy()); - else - sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL)); - return sa; -} - -void AliasDeclaration::semantic(Scope *sc) -{ - //printf("AliasDeclaration::semantic() %s\n", toChars()); - if (aliassym) - { - if (aliassym->isTemplateInstance()) - aliassym->semantic(sc); - return; - } - this->inSemantic = 1; - - storage_class |= sc->stc & STCdeprecated; - - // Given: - // alias foo.bar.abc def; - // it is not knowable from the syntax whether this is an alias - // for a type or an alias for a symbol. It is up to the semantic() - // pass to distinguish. - // If it is a type, then type is set and getType() will return that - // type. If it is a symbol, then aliassym is set and type is NULL - - // toAlias() will return aliasssym. - - Dsymbol *s; - - if (type->ty == Tident) - { - TypeIdentifier *ti = (TypeIdentifier *)type; - - s = ti->toDsymbol(sc); - if (s) - goto L2; // it's a symbolic alias - } - else if (type->ty == Tinstance) - { - // Handle forms like: - // alias instance TFoo(int).bar.abc def; - - TypeInstance *ti = (TypeInstance *)type; - - s = ti->tempinst; - if (s) - { - s->semantic(sc); - s = s->toAlias(); - if (sc->parent->isFuncDeclaration()) - s->semantic2(sc); - - for (int i = 0; i < ti->idents.dim; i++) - { Identifier *id; - - id = (Identifier *)ti->idents.data[i]; - s = s->search(id, 0); - if (!s) // failed to find a symbol - goto L1; // it must be a type - s = s->toAlias(); - } - goto L2; - } - } - L1: - if (overnext) - ScopeDsymbol::multiplyDefined(this, overnext); - type = type->semantic(loc, sc); - this->inSemantic = 0; - return; - - L2: - type = NULL; - VarDeclaration *v = s->isVarDeclaration(); - if (v && v->linkage == LINKdefault) - { - error("forward reference of %s", v->toChars()); - s = NULL; - } - else - { - FuncDeclaration *f = s->isFuncDeclaration(); - if (f) - { - if (overnext) - { - FuncAliasDeclaration *fa = new FuncAliasDeclaration(f); - if (!fa->overloadInsert(overnext)) - ScopeDsymbol::multiplyDefined(f, overnext); - overnext = NULL; - s = fa; - } - } - if (overnext) - ScopeDsymbol::multiplyDefined(s, overnext); - if (s == this) - { - assert(global.errors); - s = NULL; - } - } - aliassym = s; - this->inSemantic = 0; -} - -int AliasDeclaration::overloadInsert(Dsymbol *s) -{ - /* Don't know yet what the aliased symbol is, so assume it can - * be overloaded and check later for correctness. - */ - - //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars()); - if (overnext == NULL) - { overnext = s; - return TRUE; - } - else - { - return overnext->overloadInsert(s); - } -} - -char *AliasDeclaration::kind() -{ - return "alias"; -} - -Type *AliasDeclaration::getType() -{ - return type; -} - -Dsymbol *AliasDeclaration::toAlias() -{ - //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym->kind()); - assert(this != aliassym); - //static int count; if (++count == 10) *(char*)0=0; - if (inSemantic) - error("recursive alias declaration"); - Dsymbol *s = aliassym ? aliassym->toAlias() : this; - return s; -} - -void AliasDeclaration::toCBuffer(OutBuffer *buf) -{ - buf->writestring("alias "); - if (aliassym) - { - aliassym->toCBuffer(buf); - buf->writeByte(' '); - buf->writestring(ident->toChars()); - } - else - type->toCBuffer(buf, ident); - buf->writeByte(';'); - buf->writenl(); -} - -/********************************* VarDeclaration ****************************/ - -VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init) - : Declaration(id) -{ -#ifdef DEBUG - if (!type) - { printf("VarDeclaration('%s')\n", id->toChars()); - *(char*)0=0; - } -#endif - assert(type); - this->type = type; - this->init = init; - this->loc = loc; - offset = 0; - noauto = 0; - nestedref = 0; - inuse = 0; -} - -Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) -{ - //printf("VarDeclaration::syntaxCopy(%s)\n", toChars()); - - VarDeclaration *sv; - if (s) - { sv = (VarDeclaration *)s; - } - else - { - Initializer *init = NULL; - if (this->init) - { init = this->init->syntaxCopy(); - //init->isExpInitializer()->exp->print(); - //init->isExpInitializer()->exp->dump(0); - } - - sv = new VarDeclaration(loc, type->syntaxCopy(), ident, init); - sv->storage_class = storage_class; - //sv->storage_class |= storage_class & STCauto; - } - return sv; -} - -void VarDeclaration::semantic(Scope *sc) -{ - //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars()); - - type = type->semantic(loc, sc); - type->checkDeprecated(loc, sc); - linkage = sc->linkage; - this->parent = sc->parent; - //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); - protection = sc->protection; - storage_class |= sc->stc; - //printf("sc->stc = %x\n", sc->stc); - //printf("storage_class = %x\n", storage_class); - - Dsymbol *parent = toParent(); - FuncDeclaration *fd = parent->isFuncDeclaration(); - - Type *tb = type->toBasetype(); - if (tb->ty == Tvoid) - { error("voids have no value"); - type = Type::terror; - tb = type; - } - if (tb->ty == Tfunction) - { error("cannot be declared to be a function"); - type = Type::terror; - tb = type; - } - - if (isConst()) - { - } - else if (isStatic()) - { - } - else if (isSynchronized()) - { - error("variable %s cannot be synchronized", toChars()); - } - else if (isOverride()) - { - error("override cannot be applied to variable"); - } - else if (isAbstract()) - { - error("abstract cannot be applied to variable"); - } - else - { - AnonymousAggregateDeclaration *aad = sc->anonAgg; - if (aad) - { - aad->addField(sc, this); - } - else - { - AggregateDeclaration *ad = parent->isAggregateDeclaration(); - if (ad) - ad->addField(sc, this); - } - - InterfaceDeclaration *id = parent->isInterfaceDeclaration(); - if (id) - { - error("field not allowed in interface"); - } - - TemplateInstance *ti = parent->isTemplateInstance(); - if (ti) - { - // Take care of nested templates - while (1) - { - TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); - if (!ti2) - break; - ti = ti2; - } - - // If it's a member template - AggregateDeclaration *ad = ti->tempdecl->isMember(); - if (ad) - { - error("cannot use template to add field to aggregate '%s'", ad->toChars()); - } - } - } - - if (type->isauto() && !noauto) - { - if (storage_class & (STCfield | STCout | STCstatic) || !fd) - { - error("globals, statics, fields, inout and out parameters cannot be auto"); - } - - if (!(storage_class & STCauto)) - { - if (!(storage_class & STCparameter) && ident != Id::withSym) - error("reference to auto class must be auto"); - } - } - - if (!init && !sc->inunion && !isStatic() && !isConst() && fd && - !(storage_class & (STCfield | STCin | STCforeach))) - { - // Provide a default initializer - //printf("Providing default initializer for '%s'\n", toChars()); - if (type->ty == Tstruct && - ((TypeStruct *)type)->sym->zeroInit == 1) - { - Expression *e = new IntegerExp(loc, 0, Type::tint32); - Expression *e1; - e1 = new VarExp(loc, this); - e = new AssignExp(loc, e1, e); - e->type = e1->type; - init = new ExpInitializer(loc, e); - return; - } - else - { - init = getExpInitializer(); - } - } - - // If inside function, there is no semantic3() call - if (sc->func && init) - { - // If local variable, use AssignExp to handle all the various - // possibilities. - if (fd && !isStatic() && !isConst()) - { - ExpInitializer *ie; - Expression *e1; - Type *t; - int dim; - - //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); - ie = init->isExpInitializer(); - if (!ie) - { - error("is not a static and cannot have static initializer"); - return; - } - - e1 = new VarExp(loc, this); - - t = type->toBasetype(); - if (t->ty == Tsarray) - { - dim = ((TypeSArray *)t)->dim->toInteger(); - // If multidimensional static array, treat as one large array - while (1) - { - t = t->next->toBasetype(); - if (t->ty != Tsarray) - break; - dim *= ((TypeSArray *)t)->dim->toInteger(); - e1->type = new TypeSArray(t->next, new IntegerExp(0, dim, Type::tindex)); - } - e1 = new SliceExp(loc, e1, NULL, NULL); - } - ie->exp = new AssignExp(loc, e1, ie->exp); - ie->exp = ie->exp->semantic(sc); - ie->exp->optimize(WANTvalue); - } - else - { - init = init->semantic(sc, type); - if (fd && isConst() && !isStatic()) - { // Make it static - storage_class |= STCstatic; - } - } - } -} - -ExpInitializer *VarDeclaration::getExpInitializer() -{ - ExpInitializer *ei; - - if (init) - ei = init->isExpInitializer(); - else - { - Expression *e = type->defaultInit(); - if (e) - ei = new ExpInitializer(loc, e); - else - ei = NULL; - } - return ei; -} - -void VarDeclaration::semantic2(Scope *sc) -{ - //printf("VarDeclaration::semantic2('%s')\n", toChars()); - if (init && !sc->parent->isFuncDeclaration()) - { inuse = 1; - init = init->semantic(sc, type); - inuse = 0; - } -} - -char *VarDeclaration::kind() -{ - return "variable"; -} - -void VarDeclaration::toCBuffer(OutBuffer *buf) -{ - type->toCBuffer(buf, ident); - if (init) - { buf->writestring(" = "); - init->toCBuffer(buf); - } - buf->writeByte(';'); - buf->writenl(); -} - -int VarDeclaration::needThis() -{ - return storage_class & STCfield; -} - -int VarDeclaration::isImportedSymbol() -{ - if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule())) - return TRUE; - return FALSE; -} - -/******************************* - * Does symbol go into data segment? - */ - -int VarDeclaration::isDataseg() -{ -#if 0 - printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); - printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); - printf("parent = '%s'\n", parent->toChars()); -#endif - Dsymbol *parent = this->toParent(); - return (storage_class & (STCstatic | STCconst) || - parent->isModule() || - parent->isTemplateInstance()); -} - -/****************************************** - * If a variable has an auto destructor call, return call for it. - * Otherwise, return NULL. - */ - -Expression *VarDeclaration::callAutoDtor() -{ Expression *e = NULL; - - if (storage_class & STCauto && !noauto) - { - for (ClassDeclaration *cd = type->isClassHandle(); - cd; - cd = cd->baseClass) - { - if (cd->dtor) - { FuncDeclaration *fd; - Expression *efd; - Expression *ec; - Array *arguments; - - fd = FuncDeclaration::genCfunc(Type::tvoid, "_d_callfinalizer"); - efd = new VarExp(loc, fd); - ec = new VarExp(loc, this); - arguments = new Array(); - arguments->push(ec); - e = new CallExp(loc, efd, arguments); - e->type = fd->type->next; - break; - } - } - } - return e; -} - -/********************************* ClassInfoDeclaration ****************************/ - -ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd) - : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL) -{ - this->cd = cd; - storage_class = STCstatic; -} - -Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(0); // should never be produced by syntax - return NULL; -} - -void ClassInfoDeclaration::semantic(Scope *sc) -{ -} - -/********************************* ModuleInfoDeclaration ****************************/ - -ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod) - : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL) -{ - this->mod = mod; - storage_class = STCstatic; -} - -Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(0); // should never be produced by syntax - return NULL; -} - -void ModuleInfoDeclaration::semantic(Scope *sc) -{ -} - -/********************************* TypeInfoDeclaration ****************************/ - -TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal) - : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) -{ - this->tinfo = tinfo; - storage_class = STCstatic; - protection = PROTpublic; - linkage = LINKc; -} - -Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(0); // should never be produced by syntax - return NULL; -} - -void TypeInfoDeclaration::semantic(Scope *sc) -{ - assert(linkage == LINKc); -} - -/***************************** TypeInfoStructDeclaration ***********************/ - -TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoClassDeclaration ***********************/ - -TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoTypedefDeclaration *********************/ - -TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoPointerDeclaration *********************/ - -TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoArrayDeclaration ***********************/ - -TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoStaticArrayDeclaration *****************/ - -TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoAssociativeArrayDeclaration ************/ - -TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoEnumDeclaration ***********************/ - -TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoFunctionDeclaration ********************/ - -TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoDelegateDeclaration ********************/ - -TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/********************************* ThisDeclaration ****************************/ - -// For the "this" parameter to member functions - -ThisDeclaration::ThisDeclaration(Type *t) - : VarDeclaration(0, t, Id::This, NULL) -{ - noauto = 1; -} - -Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(0); // should never be produced by syntax - return NULL; -} - - diff -uNr gdc-0.11/d/root/declaration.h gdc-0.12/d/root/declaration.h --- gdc-0.11/d/root/declaration.h 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/declaration.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,517 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef DMD_DECLARATION_H -#define DMD_DECLARATION_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "dsymbol.h" - -struct Expression; -struct Statement; -struct LabelDsymbol; -struct Initializer; -struct Module; -struct InlineScanState; -struct ForeachStatement; -struct FuncDeclaration; -struct ExpInitializer; - -enum PROT; -enum LINK; -enum TOK; -enum MATCH; - -enum STC -{ - STCundefined = 0, - STCstatic = 1, - STCextern = 2, - STCconst = 4, - STCfinal = 8, - STCabstract = 0x10, - STCparameter = 0x20, - STCfield = 0x40, - STCoverride = 0x80, - STCauto = 0x100, - STCsynchronized = 0x200, - STCdeprecated = 0x400, - STCin = 0x800, // in parameter - STCout = 0x1000, // out parameter - STCforeach = 0x2000, // variable for foreach loop - STCcomdat = 0x4000, // should go into COMDAT record -}; - -struct Match -{ - int count; // number of matches found - MATCH last; // match level of lastf - FuncDeclaration *lastf; // last matching function we found - FuncDeclaration *nextf; // current matching function - FuncDeclaration *anyf; // pick a func, any func, to use for error recovery -}; - -void overloadResolveX(Match *m, FuncDeclaration *f, Array *arguments); - -/**************************************************************/ - -struct Declaration : Dsymbol -{ - Type *type; - unsigned storage_class; - enum PROT protection; - enum LINK linkage; - - Declaration(Identifier *id); - void semantic(Scope *sc); - char *kind(); - unsigned size(Loc loc); - - char *mangle(); - int isStatic() { return storage_class & STCstatic; } - virtual int isStaticConstructor(); - virtual int isStaticDestructor(); - virtual int isDelete(); - virtual int isDataseg(); - virtual int isCodeseg(); - int isFinal() { return storage_class & STCfinal; } - int isAbstract() { return storage_class & STCabstract; } - int isConst() { return storage_class & STCconst; } - int isAuto() { return storage_class & STCauto; } - int isSynchronized() { return storage_class & STCsynchronized; } - int isParameter() { return storage_class & STCparameter; } - int isDeprecated() { return storage_class & STCdeprecated; } - int isOverride() { return storage_class & STCoverride; } - - int isIn() { return storage_class & STCin; } - int isOut() { return storage_class & STCout; } - int isInOut() { return (storage_class & (STCin | STCout)) == (STCin | STCout); } - - enum PROT prot(); - - Declaration *isDeclaration() { return this; } -}; - -struct TypedefDeclaration : Declaration -{ - Type *basetype; - Initializer *init; - int sem; // 0: semantic() has not been run - // 1: semantic() is in progress - // 2: semantic() has been run - // 3: semantic2() has been run - - TypedefDeclaration(Identifier *ident, Type *basetype, Initializer *init); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void semantic2(Scope *sc); - char *mangle(); - char *kind(); - Type *getType(); - void toCBuffer(OutBuffer *buf); - - void toObjFile(); // compile to .obj file - void toDebug(); - int cvMember(unsigned char *p); - - TypedefDeclaration *isTypedefDeclaration() { return this; } -}; - -struct AliasDeclaration : Declaration -{ - Dsymbol *aliassym; - Dsymbol *overnext; // next in overload list - int inSemantic; - - AliasDeclaration(Loc loc, Identifier *ident, Type *type); - AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - int overloadInsert(Dsymbol *s); - char *kind(); - Type *getType(); - Dsymbol *toAlias(); - void toCBuffer(OutBuffer *buf); - - AliasDeclaration *isAliasDeclaration() { return this; } -}; - -struct VarDeclaration : Declaration -{ - Initializer *init; - unsigned offset; - int noauto; // no auto semantics - int nestedref; // referenced by a lexically nested function - int inuse; - - VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void semantic2(Scope *sc); - char *kind(); - void toCBuffer(OutBuffer *buf); - int needThis(); - int isImportedSymbol(); - int isDataseg(); - Expression *callAutoDtor(); - ExpInitializer *getExpInitializer(); - - Symbol *toSymbol(); - void toObjFile(); // compile to .obj file - int cvMember(unsigned char *p); - - // Eliminate need for dynamic_cast - VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } -}; - -// This is a shell around a back end symbol - -struct SymbolDeclaration : Declaration -{ - Symbol *sym; - - SymbolDeclaration(Loc loc, Symbol *s); - - Symbol *toSymbol(); -}; - -struct ClassInfoDeclaration : VarDeclaration -{ - ClassDeclaration *cd; - - ClassInfoDeclaration(ClassDeclaration *cd); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - - Symbol *toSymbol(); -}; - -struct ModuleInfoDeclaration : VarDeclaration -{ - Module *mod; - - ModuleInfoDeclaration(Module *mod); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - - Symbol *toSymbol(); -}; - -struct TypeInfoDeclaration : VarDeclaration -{ - Type *tinfo; - - TypeInfoDeclaration(Type *tinfo, int internal); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - - Symbol *toSymbol(); - void toObjFile(); // compile to .obj file - virtual void toDt(dt_t **pdt); -}; - -struct TypeInfoStructDeclaration : TypeInfoDeclaration -{ - TypeInfoStructDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct TypeInfoClassDeclaration : TypeInfoDeclaration -{ - TypeInfoClassDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct TypeInfoTypedefDeclaration : TypeInfoDeclaration -{ - TypeInfoTypedefDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct TypeInfoPointerDeclaration : TypeInfoDeclaration -{ - TypeInfoPointerDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct TypeInfoArrayDeclaration : TypeInfoDeclaration -{ - TypeInfoArrayDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration -{ - TypeInfoStaticArrayDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration -{ - TypeInfoAssociativeArrayDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct TypeInfoEnumDeclaration : TypeInfoDeclaration -{ - TypeInfoEnumDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct TypeInfoFunctionDeclaration : TypeInfoDeclaration -{ - TypeInfoFunctionDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct TypeInfoDelegateDeclaration : TypeInfoDeclaration -{ - TypeInfoDelegateDeclaration(Type *tinfo); - - void toDt(dt_t **pdt); -}; - -struct ThisDeclaration : VarDeclaration -{ - ThisDeclaration(Type *t); - Dsymbol *syntaxCopy(Dsymbol *); -}; - -enum ILS -{ - ILSuninitialized, // not computed yet - ILSno, // cannot inline - ILSyes, // can inline -}; - -struct FuncDeclaration : Declaration -{ - Array *fthrows; // Array of Type's of exceptions - Statement *frequire; - Identifier *outId; // identifier for out statement - VarDeclaration *vresult; // variable corresponding to outId - LabelDsymbol *returnLabel; // where the return goes - Statement *fensure; - Statement *fbody; - - DsymbolTable *localsymtab; // used to prevent symbols in different - // scopes from having the same name - VarDeclaration *vthis; // 'this' parameter - VarDeclaration *v_arguments; // '_arguments' parameter - VarDeclaration *v_argptr; // '_argptr' variable - Array *parameters; // Array of Argument's for parameters - DsymbolTable *labtab; // statement label symbol table - Declaration *overnext; // next in overload list - Loc endloc; // location of closing curly bracket - int vtblIndex; // for member functions, index into vtbl[] - int naked; // !=0 if naked - int inlineAsm; // !=0 if has inline assembler - ILS inlineStatus; - int inlineNest; // !=0 if nested inline - int semanticRun; // !=0 if semantic3() had been run - int nestedFrameRef; // !=0 if nested variables referenced frame ptr - int introducing; // !=0 if 'introducing' function - ForeachStatement *fes; // if foreach body, this is the foreach - - // Things that should really go into Scope - int hasReturnExp; // if there's a return exp; statement - - FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void semantic3(Scope *sc); - void toHBuffer(OutBuffer *buf); - void toCBuffer(OutBuffer *buf); - int overrides(FuncDeclaration *fd); - int overloadInsert(Dsymbol *s); - FuncDeclaration *overloadExactMatch(Type *t); - FuncDeclaration *overloadResolve(Loc loc, Array *arguments); - LabelDsymbol *searchLabel(Identifier *ident); - AggregateDeclaration *isThis(); - AggregateDeclaration *isMember2(); - int getLevel(Loc loc, FuncDeclaration *fd); // lexical nesting level difference - void appendExp(Expression *e); - void appendState(Statement *s); - char *mangle(); - int isMain(); - int isWinMain(); - int isDllMain(); - int isExport(); - int isImportedSymbol(); - int isAbstract(); - int isCodeseg(); - virtual int isNested(); - int needThis(); - virtual int isVirtual(); - virtual int addPreInvariant(); - virtual int addPostInvariant(); - void inlineScan(); - int canInline(int hasthis); - Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments); - char *kind(); - - static FuncDeclaration *genCfunc(Type *treturn, char *name); - - Symbol *toSymbol(); - Symbol *toThunkSymbol(int offset); // thunk version - void toObjFile(); // compile to .obj file - int cvMember(unsigned char *p); - - FuncDeclaration *isFuncDeclaration() { return this; } -}; - -struct FuncAliasDeclaration : FuncDeclaration -{ - FuncDeclaration *funcalias; - - FuncAliasDeclaration(FuncDeclaration *funcalias); - - FuncAliasDeclaration *isFuncAliasDeclaration() { return this; } - char *kind(); -}; - -struct FuncLiteralDeclaration : FuncDeclaration -{ - enum TOK tok; // TOKfunction or TOKdelegate - - FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok, - ForeachStatement *fes); - Dsymbol *syntaxCopy(Dsymbol *); - int isNested(); - - FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; } - char *kind(); -}; - -struct CtorDeclaration : FuncDeclaration -{ Array *arguments; - int varargs; - - CtorDeclaration(Loc loc, Loc endloc, Array *arguments, int varargs); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - char *kind(); - char *toChars(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - - CtorDeclaration *isCtorDeclaration() { return this; } -}; - -struct DtorDeclaration : FuncDeclaration -{ - DtorDeclaration(Loc loc, Loc endloc); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - int addPreInvariant(); - int addPostInvariant(); - int overloadInsert(Dsymbol *s); - - DtorDeclaration *isDtorDeclaration() { return this; } -}; - -struct StaticCtorDeclaration : FuncDeclaration -{ - StaticCtorDeclaration(Loc loc, Loc endloc); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - AggregateDeclaration *isThis(); - int isStaticConstructor(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); -}; - -struct StaticDtorDeclaration : FuncDeclaration -{ - StaticDtorDeclaration(Loc loc, Loc endloc); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - AggregateDeclaration *isThis(); - int isStaticDestructor(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); -}; - -struct InvariantDeclaration : FuncDeclaration -{ - InvariantDeclaration(Loc loc, Loc endloc); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - - InvariantDeclaration *isInvariantDeclaration() { return this; } -}; - - -struct UnitTestDeclaration : FuncDeclaration -{ - UnitTestDeclaration(Loc loc, Loc endloc); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - AggregateDeclaration *isThis(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - - UnitTestDeclaration *isUnitTestDeclaration() { return this; } -}; - -struct NewDeclaration : FuncDeclaration -{ Array *arguments; - int varargs; - - NewDeclaration(Loc loc, Loc endloc, Array *arguments, int varargs); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - char *kind(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - - NewDeclaration *isNewDeclaration() { return this; } -}; - - -struct DeleteDeclaration : FuncDeclaration -{ Array *arguments; - - DeleteDeclaration(Loc loc, Loc endloc, Array *arguments); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - char *kind(); - int isDelete(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); -}; - -#endif /* DMD_DECLARATION_H */ diff -uNr gdc-0.11/d/root/dsymbol.c gdc-0.12/d/root/dsymbol.c --- gdc-0.11/d/root/dsymbol.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/dsymbol.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,689 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include - -#include "mem.h" - -#include "mars.h" -#include "dsymbol.h" -#include "aggregate.h" -#include "identifier.h" -#include "module.h" -#include "mtype.h" -#include "expression.h" -#include "statement.h" -#include "declaration.h" -#include "id.h" -#include "scope.h" - -/****************************** Dsymbol ******************************/ - -Dsymbol::Dsymbol() -{ - //printf("Dsymbol::Dsymbol(%p)\n", this); - this->ident = NULL; - this->c_ident = NULL; - this->parent = NULL; - this->csym = NULL; - this->isym = NULL; - this->loc = 0; -} - -Dsymbol::Dsymbol(Identifier *ident) -{ - //printf("Dsymbol::Dsymbol(%p, ident)\n", this); - this->ident = ident; - this->c_ident = NULL; - this->parent = NULL; - this->csym = NULL; - this->isym = NULL; - this->loc = 0; -} - -int Dsymbol::equals(Object *o) -{ Dsymbol *s; - - if (this == o) - return TRUE; - s = (Dsymbol *)(o); - if (s && ident->equals(s->ident)) - return TRUE; - return FALSE; -} - -/************************************** - * Copy the syntax. - * Used for template instantiations. - * If s is NULL, allocate the new object, otherwise fill it in. - */ - -Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s) -{ - print(); - printf("%s %s\n", kind(), toChars()); - assert(0); - return NULL; -} - -char *Dsymbol::toChars() -{ - return ident ? ident->toChars() : (char *)"__anonymous"; -} - -char *Dsymbol::toPrettyChars() -{ Dsymbol *p; - char *s; - char *q; - size_t len; - - if (!parent) - return toChars(); - - len = 0; - for (p = this; p; p = p->parent) - len += strlen(p->toChars()) + 1; - - s = (char *)mem.malloc(len); - q = s + len - 1; - *q = 0; - for (p = this; 1; p = p->parent) - { - char *t = p->toChars(); - len = strlen(t); - q -= len; - memcpy(q, t, len); - if (q == s) - break; - q--; - *q = '.'; - } - return s; -} - -char *Dsymbol::locToChars() -{ - OutBuffer buf; - char *p; - - Module *m = getModule(); - - if (m && m->srcfile) - loc.filename = m->srcfile->toChars(); - return loc.toChars(); -} - -char *Dsymbol::kind() -{ - return "symbol"; -} - -/********************************* - * If this symbol is really an alias for another, - * return that other. - */ - -Dsymbol *Dsymbol::toAlias() -{ - return this; -} - -Dsymbol *Dsymbol::toParent() -{ - return parent ? parent->pastMixin() : NULL; -} - -Dsymbol *Dsymbol::pastMixin() -{ - Dsymbol *s = this; - - while (s && s->isTemplateMixin()) - s = s->parent; - return s; -} - -int Dsymbol::isAnonymous() -{ - return ident ? 0 : 1; -} - -void Dsymbol::semantic(Scope *sc) -{ - error("%p has no semantic routine", this); -} - -void Dsymbol::semantic2(Scope *sc) -{ - // Most Dsymbols have no further semantic analysis needed -} - -void Dsymbol::semantic3(Scope *sc) -{ - // Most Dsymbols have no further semantic analysis needed -} - -void Dsymbol::inlineScan() -{ - // Most Dsymbols have no further semantic analysis needed -} - -Dsymbol *Dsymbol::search(Identifier *ident, int flags) -{ - //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); - return NULL; -// error("%s.%s is undefined",toChars(), ident->toChars()); -// return this; -} - -int Dsymbol::overloadInsert(Dsymbol *s) -{ - //printf("Dsymbol::overloadInsert('%s')\n", s->toChars()); - return FALSE; -} - -void Dsymbol::toCBuffer(OutBuffer *buf) -{ - buf->printf("Dsymbol '%s' to C file", toChars()); - buf->writenl(); -} - -unsigned Dsymbol::size(Loc loc) -{ - error("Dsymbol '%s' has no size\n", toChars()); - return 0; -} - -int Dsymbol::isforwardRef() -{ - return FALSE; -} - -AggregateDeclaration *Dsymbol::isThis() -{ - return NULL; -} - -ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class? -{ - Dsymbol *parent = toParent(); - if (parent && parent->isClassDeclaration()) - return (ClassDeclaration *)parent; - return NULL; -} - -void Dsymbol::defineRef(Dsymbol *s) -{ - assert(0); -} - -int Dsymbol::isExport() -{ - return FALSE; -} - -int Dsymbol::isImportedSymbol() -{ - return FALSE; -} - -int Dsymbol::isDeprecated() -{ - return FALSE; -} - -LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? -{ - return NULL; -} - -AggregateDeclaration *Dsymbol::isMember() // is this a member of an AggregateDeclaration? -{ - Dsymbol *parent = toParent(); - return parent ? parent->isAggregateDeclaration() : NULL; -} - -Type *Dsymbol::getType() -{ - return NULL; -} - -int Dsymbol::needThis() -{ - return FALSE; -} - -void Dsymbol::addMember(ScopeDsymbol *sd) -{ - //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars()); - //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab); - parent = sd; - if (!isAnonymous()) // no name, so can't add it to symbol table - { - if (!sd->symtab->insert(this)) // if name is already defined - { - Dsymbol *s2; - - s2 = sd->symtab->lookup(ident); - if (!s2->overloadInsert(this)) - { - sd->multiplyDefined(this, s2); - } - } - if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) - { - if (ident == Id::__sizeof) - error(".sizeof property cannot be redefined"); - } - } -} - -void Dsymbol::error(const char *format, ...) -{ - //printf("Dsymbol::error()\n"); - char *p = locToChars(); - - if (*p) - printf("%s: ", p); - mem.free(p); - - printf("%s %s ", kind(), toPrettyChars()); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); - - global.errors++; - - //fatal(); -} - -void Dsymbol::error(Loc loc, const char *format, ...) -{ - char *p = loc.toChars(); - if (!*p) - p = locToChars(); - - if (*p) - printf("%s: ", p); - mem.free(p); - - printf("%s %s ", kind(), toPrettyChars()); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); - - global.errors++; - - //fatal(); -} - -void Dsymbol::checkDeprecated(Loc loc, Scope *sc) -{ - if (!global.params.useDeprecated && isDeprecated()) - { - // Don't complain if we're inside a deprecated symbol's scope - for (Dsymbol *sp = sc->parent; sp; sp = sp->parent) - { if (sp->isDeprecated()) - return; - } - - for (; sc; sc = sc->enclosing) - { - if (sc->scopesym && sc->scopesym->isDeprecated()) - return; - } - - error(loc, "is deprecated"); - } -} - -/********************************** - * Determine which Module a Dsymbol is in. - */ - -Module *Dsymbol::getModule() -{ - Module *m; - Dsymbol *s; - - //printf("Dsymbol::getModule()\n"); - s = this; - while (s) - { - //printf("\ts = '%s'\n", s->toChars()); - m = s->isModule(); - if (m) - return m; - s = s->parent; - } - return NULL; -} - -/************************************* - */ - -enum PROT Dsymbol::prot() -{ - return PROTpublic; -} - -/************************************* - * Do syntax copy of an array of Dsymbol's. - */ - - -Array *Dsymbol::arraySyntaxCopy(Array *a) -{ - - Array *b = NULL; - if (a) - { - b = a->copy(); - for (int i = 0; i < b->dim; i++) - { - Dsymbol *s = (Dsymbol *)b->data[i]; - - s = s->syntaxCopy(NULL); - b->data[i] = (void *)s; - } - } - return b; -} - -/********************************* ScopeDsymbol ****************************/ - -ScopeDsymbol::ScopeDsymbol() - : Dsymbol() -{ - members = NULL; - symtab = NULL; - imports = NULL; - prots = NULL; -} - -ScopeDsymbol::ScopeDsymbol(Identifier *id) - : Dsymbol(id) -{ - members = NULL; - symtab = NULL; - imports = NULL; - prots = NULL; -} - -Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) -{ - //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars()); - - ScopeDsymbol *sd; - if (s) - sd = (ScopeDsymbol *)s; - else - sd = new ScopeDsymbol(ident); - sd->members = arraySyntaxCopy(members); - return sd; -} - -Dsymbol *ScopeDsymbol::search(Identifier *ident, int flags) -{ Dsymbol *s; - int i; - - //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags); - // Look in symbols declared in this module - s = symtab ? symtab->lookup(ident) : NULL; - if (s) - { - //printf("\ts = '%s.%s'\n",toChars(),s->toChars()); - } - else if (imports) - { - // Look in imported modules - for (i = 0; i < imports->dim; i++) - { ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i]; - Dsymbol *s2; - - // If private import, don't search it - if (flags & 1 && prots[i] == PROTprivate) - continue; - - //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport()); - s2 = ss->search(ident, ss->isModule() ? 1 : 0); - if (!s) - s = s2; - else if (s2 && s != s2) - { - ss->multiplyDefined(s, s2); - break; - } - } - if (s) - { - Declaration *d = s->isDeclaration(); - if (d && d->protection == PROTprivate) - error("%s is private", d->toPrettyChars()); - } - } - return s; -} - -void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection) -{ - //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection); - - // No circular or redundant import's - if (s != this) - { - if (!imports) - imports = new Array(); - else - { - for (int i = 0; i < imports->dim; i++) - { ScopeDsymbol *ss; - - ss = (ScopeDsymbol *) imports->data[i]; - if (ss == s) - { - if (protection > prots[i]) - prots[i] = protection; // upgrade access - return; - } - } - } - imports->push(s); - prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); - prots[imports->dim - 1] = protection; - } -} - -int ScopeDsymbol::isforwardRef() -{ - return (members == NULL); -} - -void ScopeDsymbol::defineRef(Dsymbol *s) -{ - ScopeDsymbol *ss; - - ss = s->isScopeDsymbol(); - members = ss->members; - ss->members = NULL; -} - -void ScopeDsymbol::multiplyDefined(Dsymbol *s1, Dsymbol *s2) -{ - //printf("s1 = '%s'\n", s1->toChars()); - //printf("s2 = '%s', parent = %p\n", s2->toChars(), s2->parent); -#if 1 - s1->error("conflicts with %s at %s", - s2->toPrettyChars(), - s2->locToChars()); -#else - s1->error("symbol %s conflicts with %s at %s", - s1->toPrettyChars(), - s2->toPrettyChars(), - s2->locToChars()); -#endif -} - -Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s) -{ - Dsymbol *sprev; - - // Look to see if we are defining a forward referenced symbol - - sprev = symtab->lookup(s->ident); - assert(sprev); - if (s->equals(sprev)) // if the same symbol - { - if (s->isforwardRef()) // if second declaration is a forward reference - return sprev; - if (sprev->isforwardRef()) - { - sprev->defineRef(s); // copy data from s into sprev - return sprev; - } - } - multiplyDefined(s, sprev); - return sprev; -} - -char *ScopeDsymbol::kind() -{ - return "ScopeDsymbol"; -} - - -/****************************** WithScopeSymbol ******************************/ - -WithScopeSymbol::WithScopeSymbol(WithStatement *withstate) - : ScopeDsymbol() -{ - this->withstate = withstate; -} - -Dsymbol *WithScopeSymbol::search(Identifier *ident, int flags) -{ - // Acts as proxy to the with class declaration - return withstate->exp->type->toDsymbol(NULL)->search(ident, 0); -} - -/****************************** ArrayScopeSymbol ******************************/ - -ArrayScopeSymbol::ArrayScopeSymbol(Expression *e) - : ScopeDsymbol() -{ - assert(e->op == TOKindex || e->op == TOKslice); - exp = e; -} - -Dsymbol *ArrayScopeSymbol::search(Identifier *ident, int flags) -{ - if (ident == Id::length || ident == Id::dollar) - { VarDeclaration **pvar; - - if (exp->op == TOKindex) - { - IndexExp *ie = (IndexExp *)exp; - - pvar = &ie->lengthVar; - } - else if (exp->op == TOKslice) - { - SliceExp *se = (SliceExp *)exp; - - pvar = &se->lengthVar; - } - else - return NULL; - if (!*pvar) - { - VarDeclaration *v = new VarDeclaration(0, Type::tsize_t, Id::dollar, NULL); - - *pvar = v; - } - return (*pvar); - } - return NULL; -} - - -/****************************** DsymbolTable ******************************/ - -DsymbolTable::DsymbolTable() -{ - tab = new StringTable; -} - -DsymbolTable::~DsymbolTable() -{ - delete tab; -} - -Dsymbol *DsymbolTable::lookup(Identifier *ident) -{ StringValue *sv; - -#ifdef DEBUG - assert(ident); - assert(tab); -#endif - sv = tab->lookup((char*)ident->string, ident->len); - return (Dsymbol *)(sv ? sv->ptrvalue : NULL); -} - -Dsymbol *DsymbolTable::insert(Dsymbol *s) -{ StringValue *sv; - Identifier *ident; - - //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars()); - ident = s->ident; -#ifdef DEBUG - assert(ident); - assert(tab); -#endif - sv = tab->insert(ident->toChars(), ident->len); - if (!sv) - return NULL; // already in table - sv->ptrvalue = s; - return s; -} - -Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s) -{ StringValue *sv; - - //printf("DsymbolTable::insert()\n"); - sv = tab->insert(ident->toChars(), ident->len); - if (!sv) - return NULL; // already in table - sv->ptrvalue = s; - return s; -} - -Dsymbol *DsymbolTable::update(Dsymbol *s) -{ StringValue *sv; - Identifier *ident; - - ident = s->ident; - sv = tab->update(ident->toChars(), ident->len); - sv->ptrvalue = s; - return s; -} - - - - diff -uNr gdc-0.11/d/root/dsymbol.h gdc-0.12/d/root/dsymbol.h --- gdc-0.11/d/root/dsymbol.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/dsymbol.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,247 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef DMD_DSYMBOL_H -#define DMD_DSYMBOL_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" -#include "stringtable.h" - -#include "mars.h" - -struct Identifier; -struct Scope; -struct DsymbolTable; -struct Declaration; -struct TypedefDeclaration; -struct AliasDeclaration; -struct AggregateDeclaration; -struct EnumDeclaration; -struct ClassDeclaration; -struct InterfaceDeclaration; -struct StructDeclaration; -struct UnionDeclaration; -struct FuncDeclaration; -struct FuncAliasDeclaration; -struct FuncLiteralDeclaration; -struct CtorDeclaration; -struct DtorDeclaration; -struct InvariantDeclaration; -struct UnitTestDeclaration; -struct NewDeclaration; -struct VarDeclaration; -struct VersionDeclaration; -struct Symbol; -struct Package; -struct Module; -struct Import; -struct Type; -struct WithStatement; -struct LabelDsymbol; -struct ScopeDsymbol; -struct TemplateDeclaration; -struct TemplateInstance; -struct TemplateMixin; -struct EnumMember; -struct ScopeDsymbol; -struct WithScopeSymbol; -struct ArrayScopeSymbol; -struct Expression; - -union tree_node; typedef union tree_node TYPE; - -enum PROT -{ - PROTundefined, - PROTnone, // no access - PROTprivate, - PROTpackage, - PROTprotected, - PROTpublic, - PROTexport, -}; - - -struct Dsymbol : Object -{ - Identifier *ident; - Identifier *c_ident; - Dsymbol *parent; - Symbol *csym; // symbol for code generator - Symbol *isym; // import version of csym - Loc loc; // where defined - - Dsymbol(); - Dsymbol(Identifier *); - char *toChars(); - char *toPrettyChars(); - char *locToChars(); - int equals(Object *o); - int isAnonymous(); - void error(Loc loc, const char *format, ...); - void error(const char *format, ...); - void checkDeprecated(Loc loc, Scope *sc); - Module *getModule(); - Dsymbol *pastMixin(); - Dsymbol *toParent(); - - int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol() - - static Array *arraySyntaxCopy(Array *a); - - virtual char *kind(); - virtual Dsymbol *toAlias(); // resolve real symbol - virtual void addMember(ScopeDsymbol *s); - virtual void semantic(Scope *sc); - virtual void semantic2(Scope *sc); - virtual void semantic3(Scope *sc); - virtual void inlineScan(); - virtual Dsymbol *search(Identifier *ident, int flags); - virtual int overloadInsert(Dsymbol *s); - virtual void toCBuffer(OutBuffer *buf); - virtual unsigned size(Loc loc); - virtual int isforwardRef(); - virtual void defineRef(Dsymbol *s); - virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member - virtual ClassDeclaration *isClassMember(); // are we a member of a class? - virtual int isExport(); // is Dsymbol exported? - virtual int isImportedSymbol(); // is Dsymbol imported? - virtual int isDeprecated(); // is Dsymbol deprecated? - virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol? - virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration? - virtual Type *getType(); // is this a type? - virtual char *mangle(); - virtual int needThis(); // need a 'this' pointer? - virtual enum PROT prot(); - virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees - virtual Dsymbol *oneMember() { return this; } - virtual void addLocalClass(Array *) { } - - // Backend - - virtual Symbol *toSymbol(); // to backend symbol - virtual void toObjFile(); // compile to .obj file - virtual int cvMember(unsigned char *p); // emit cv debug info for member - - Symbol *toImport(); // to backend import symbol - static Symbol *toImport(Symbol *s); // to backend import symbol - - Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t); // helper - - // Eliminate need for dynamic_cast - virtual Package *isPackage() { return NULL; } - virtual Module *isModule() { return NULL; } - virtual EnumMember *isEnumMember() { return NULL; } - virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; } - virtual TemplateInstance *isTemplateInstance() { return NULL; } - virtual TemplateMixin *isTemplateMixin() { return NULL; } - virtual Declaration *isDeclaration() { return NULL; } - virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; } - virtual AliasDeclaration *isAliasDeclaration() { return NULL; } - virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; } - virtual FuncDeclaration *isFuncDeclaration() { return NULL; } - virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; } - virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; } - virtual CtorDeclaration *isCtorDeclaration() { return NULL; } - virtual DtorDeclaration *isDtorDeclaration() { return NULL; } - virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; } - virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; } - virtual NewDeclaration *isNewDeclaration() { return NULL; } - virtual VarDeclaration *isVarDeclaration() { return NULL; } - virtual ClassDeclaration *isClassDeclaration() { return NULL; } - virtual StructDeclaration *isStructDeclaration() { return NULL; } - virtual UnionDeclaration *isUnionDeclaration() { return NULL; } - virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; } - virtual VersionDeclaration *isVersionDeclaration() { return NULL; } - virtual ScopeDsymbol *isScopeDsymbol() { return NULL; } - virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; } - virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; } - virtual Import *isImport() { return NULL; } - virtual EnumDeclaration *isEnumDeclaration() { return NULL; } -}; - -// Dsymbol that generates a scope - -struct ScopeDsymbol : Dsymbol -{ - Array *members; // all Dsymbol's in this scope - DsymbolTable *symtab; // members[] sorted into table - - Array *imports; // imported ScopeDsymbol's - unsigned char *prots; // PROT for each import - - ScopeDsymbol(); - ScopeDsymbol(Identifier *id); - Dsymbol *syntaxCopy(Dsymbol *s); - Dsymbol *search(Identifier *ident, int flags); - void importScope(ScopeDsymbol *s, enum PROT protection); - int isforwardRef(); - void defineRef(Dsymbol *s); - static void multiplyDefined(Dsymbol *s1, Dsymbol *s2); - Dsymbol *nameCollision(Dsymbol *s); - char *kind(); - - ScopeDsymbol *isScopeDsymbol() { return this; } -}; - -// With statement scope - -struct WithScopeSymbol : ScopeDsymbol -{ - WithStatement *withstate; - - WithScopeSymbol(WithStatement *withstate); - Dsymbol *search(Identifier *ident, int flags); - - WithScopeSymbol *isWithScopeSymbol() { return this; } -}; - -// Array Index/Slice scope - -struct ArrayScopeSymbol : ScopeDsymbol -{ - Expression *exp; // IndexExp or SliceExp - - ArrayScopeSymbol(Expression *e); - Dsymbol *search(Identifier *ident, int flags); - - ArrayScopeSymbol *isArrayScopeSymbol() { return this; } -}; - -// Table of Dsymbol's - -struct DsymbolTable : Object -{ - StringTable *tab; - - DsymbolTable(); - ~DsymbolTable(); - - // Look up Identifier. Return Dsymbol if found, NULL if not. - Dsymbol *lookup(Identifier *ident); - - // Insert Dsymbol in table. Return NULL if already there. - Dsymbol *insert(Dsymbol *s); - - // Look for Dsymbol in table. If there, return it. If not, insert s and return that. - Dsymbol *update(Dsymbol *s); - Dsymbol *insert(Identifier *ident, Dsymbol *s); // when ident and s are not the same -}; - -#endif /* DMD_DSYMBOL_H */ diff -uNr gdc-0.11/d/root/dump.c gdc-0.12/d/root/dump.c --- gdc-0.11/d/root/dump.c 2005-02-20 16:43:51.000000000 +0100 +++ gdc-0.12/d/root/dump.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,125 +0,0 @@ - -// Copyright (c) 1999-2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include - -#include "mars.h" -#include "mtype.h" -#include "declaration.h" -#include "expression.h" -#include "template.h" - -static void indent(int indent) -{ - int i; - - for (i = 0; i < indent; i++) - printf(" "); -} - -static char *type_print(Type *type) -{ - return type ? type->toChars() : (char *) "null"; -} - -void Expression::dump(int i) -{ - indent(i); - printf("%p %s type=%s\n", this, Token::toChars(op), type_print(type)); -} - -void IntegerExp::dump(int i) -{ - indent(i); - printf("%p %lld type=%s\n", this, (d_int64)value, type_print(type)); -} - -void IdentifierExp::dump(int i) -{ - indent(i); - printf("%p ident '%s' type=%s\n", this, ident->toChars(), type_print(type)); -} - -void DsymbolExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s\n", this, s->toChars(), type_print(type)); -} - -void VarExp::dump(int i) -{ - indent(i); - printf("%p %s var=%s type=%s\n", this, Token::toChars(op), var->toChars(), type_print(type)); -} - -void UnaExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1); - if (e1) - e1->dump(i + 2); -} - -void SliceExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1); - if (e1) - e1->dump(i + 2); - if (lwr) - lwr->dump(i + 2); - if (upr) - upr->dump(i + 2); -} - -void DotIdExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s ident=%s e1=%p\n", this, Token::toChars(op), type_print(type), ident->toChars(), e1); - if (e1) - e1->dump(i + 2); -} - -void DotVarExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s var='%s' e1=%p\n", this, Token::toChars(op), type_print(type), var->toChars(), e1); - if (e1) - e1->dump(i + 2); -} - -void DotTemplateInstanceExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s ti='%s' e1=%p\n", this, Token::toChars(op), type_print(type), ti->toChars(), e1); - if (e1) - e1->dump(i + 2); -} - -void DelegateExp::dump(int i) -{ - indent(i); - printf("%p %s func=%s type=%s e1=%p\n", this, Token::toChars(op), func->toChars(), type_print(type), e1); - if (e1) - e1->dump(i + 2); -} - -void BinExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s e1=%p e2=%p\n", this, Token::toChars(op), type_print(type), e1, e2); - if (e1) - e1->dump(i + 2); - if (e2) - e2->dump(i + 2); -} - - diff -uNr gdc-0.11/d/root/entity.c gdc-0.12/d/root/entity.c --- gdc-0.11/d/root/entity.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/entity.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1373 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, April 2005 - Changes from Thomas Kuehne, November 2004 -*/ - - -#include - -/********************************************* - * Convert from named entity to its encoding. - * For reference: - * http://www.htmlhelp.com/reference/html40/entities/ - * http://www.w3.org/TR/1999/REC-html401-19991224/sgml/entities.html - */ - -struct NameId -{ - char *name; - unsigned short value; -}; - -#if 0 -//TODO: Merge Walter's list with Thomas' - -static NameId names[] = -{ - // Entities - "quot", 34, - "amp", 38, - "lt", 60, - "gt", 62, - - "OElig", 338, - "oelig", 339, - "Scaron", 352, - "scaron", 353, - "Yuml", 376, - "circ", 710, - "tilde", 732, - "ensp", 8194, - "emsp", 8195, - "thinsp", 8201, - "zwnj", 8204, - "zwj", 8205, - "lrm", 8206, - "rlm", 8207, - "ndash", 8211, - "mdash", 8212, - "lsquo", 8216, - "rsquo", 8217, - "sbquo", 8218, - "ldquo", 8220, - "rdquo", 8221, - "bdquo", 8222, - "dagger", 8224, - "Dagger", 8225, - "permil", 8240, - "lsaquo", 8249, - "rsaquo", 8250, - "euro", 8364, - - // Latin-1 (ISO-8859-1) Entities - "nbsp", 160, - "iexcl", 161, - "cent", 162, - "pound", 163, - "curren", 164, - "yen", 165, - "brvbar", 166, - "sect", 167, - "uml", 168, - "copy", 169, - "ordf", 170, - "laquo", 171, - "not", 172, - "shy", 173, - "reg", 174, - "macr", 175, - "deg", 176, - "plusmn", 177, - "sup2", 178, - "sup3", 179, - "acute", 180, - "micro", 181, - "para", 182, - "middot", 183, - "cedil", 184, - "sup1", 185, - "ordm", 186, - "raquo", 187, - "frac14", 188, - "frac12", 189, - "frac34", 190, - "iquest", 191, - "Agrave", 192, - "Aacute", 193, - "Acirc", 194, - "Atilde", 195, - "Auml", 196, - "Aring", 197, - "AElig", 198, - "Ccedil", 199, - "Egrave", 200, - "Eacute", 201, - "Ecirc", 202, - "Euml", 203, - "Igrave", 204, - "Iacute", 205, - "Icirc", 206, - "Iuml", 207, - "ETH", 208, - "Ntilde", 209, - "Ograve", 210, - "Oacute", 211, - "Ocirc", 212, - "Otilde", 213, - "Ouml", 214, - "times", 215, - "Oslash", 216, - "Ugrave", 217, - "Uacute", 218, - "Ucirc", 219, - "Uuml", 220, - "Yacute", 221, - "THORN", 222, - "szlig", 223, - "agrave", 224, - "aacute", 225, - "acirc", 226, - "atilde", 227, - "auml", 228, - "aring", 229, - "aelig", 230, - "ccedil", 231, - "egrave", 232, - "eacute", 233, - "ecirc", 234, - "euml", 235, - "igrave", 236, - "iacute", 237, - "icirc", 238, - "iuml", 239, - "eth", 240, - "ntilde", 241, - "ograve", 242, - "oacute", 243, - "ocirc", 244, - "otilde", 245, - "ouml", 246, - "divide", 247, - "oslash", 248, - "ugrave", 249, - "uacute", 250, - "ucirc", 251, - "uuml", 252, - "yacute", 253, - "thorn", 254, - "yuml", 255, - - // Symbols and Greek letter entities - "fnof", 402, - "Alpha", 913, - "Beta", 914, - "Gamma", 915, - "Delta", 916, - "Epsilon", 917, - "Zeta", 918, - "Eta", 919, - "Theta", 920, - "Iota", 921, - "Kappa", 922, - "Lambda", 923, - "Mu", 924, - "Nu", 925, - "Xi", 926, - "Omicron", 927, - "Pi", 928, - "Rho", 929, - "Sigma", 931, - "Tau", 932, - "Upsilon", 933, - "Phi", 934, - "Chi", 935, - "Psi", 936, - "Omega", 937, - "alpha", 945, - "beta", 946, - "gamma", 947, - "delta", 948, - "epsilon", 949, - "zeta", 950, - "eta", 951, - "theta", 952, - "iota", 953, - "kappa", 954, - "lambda", 955, - "mu", 956, - "nu", 957, - "xi", 958, - "omicron", 959, - "pi", 960, - "rho", 961, - "sigmaf", 962, - "sigma", 963, - "tau", 964, - "upsilon", 965, - "phi", 966, - "chi", 967, - "psi", 968, - "omega", 969, - "thetasym", 977, - "upsih", 978, - "piv", 982, - "bull", 8226, - "hellip", 8230, - "prime", 8242, - "Prime", 8243, - "oline", 8254, - "frasl", 8260, - "weierp", 8472, - "image", 8465, - "real", 8476, - "trade", 8482, - "alefsym", 8501, - "larr", 8592, - "uarr", 8593, - "rarr", 8594, - "darr", 8595, - "harr", 8596, - "crarr", 8629, - "lArr", 8656, - "uArr", 8657, - "rArr", 8658, - "dArr", 8659, - "hArr", 8660, - "forall", 8704, - "part", 8706, - "exist", 8707, - "empty", 8709, - "nabla", 8711, - "isin", 8712, - "notin", 8713, - "ni", 8715, - "prod", 8719, - "sum", 8721, - "minus", 8722, - "lowast", 8727, - "radic", 8730, - "prop", 8733, - "infin", 8734, - "ang", 8736, - "and", 8743, - "or", 8744, - "cap", 8745, - "cup", 8746, - "int", 8747, - "there4", 8756, - "sim", 8764, - "cong", 8773, - "asymp", 8776, - "ne", 8800, - "equiv", 8801, - "le", 8804, - "ge", 8805, - "sub", 8834, - "sup", 8835, - "nsub", 8836, - "sube", 8838, - "supe", 8839, - "oplus", 8853, - "otimes", 8855, - "perp", 8869, - "sdot", 8901, - "lceil", 8968, - "rceil", 8969, - "lfloor", 8970, - "rfloor", 8971, - "lang", 9001, - "rang", 9002, - "loz", 9674, - "spades", 9824, - "clubs", 9827, - "hearts", 9829, - "diams", 9830, -}; - -int HtmlNamedEntity(unsigned char *p, int length) -{ - int i; - - // BUG: this is a dumb, slow linear search - for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) - { - // Entries are case sensitive - if (memcmp(names[i].name, (char *)p, length) == 0 && - !names[i].name[length]) - return names[i].value; - } - return -1; -} - -#endif - -static NameId namesA[]={ - "Aacgr", 0x0386, - "aacgr", 0x03AC, - "Aacute", 0x00C1, - "aacute", 0x00E1, - "Abreve", 0x0102, - "abreve", 0x0103, - "Acirc", 0x00C2, - "acirc", 0x00E2, - "acute", 0x00B4, - "Acy", 0x0410, - "acy", 0x0430, - "AElig", 0x00C6, - "aelig", 0x00E6, - "Agr", 0x0391, - "agr", 0x03B1, - "Agrave", 0x00C0, - "agrave", 0x00E0, - "aleph", 0x2135, - "alpha", 0x03B1, - "Amacr", 0x0100, - "amacr", 0x0101, - "amalg", 0x2210, - "amp", 0x0026, - "and", 0x2227, - "ang", 0x2220, - "ang90", 0x221F, - "angmsd", 0x2221, - "angsph", 0x2222, - "angst", 0x212B, - "Aogon", 0x0104, - "aogon", 0x0105, - "ap", 0x2248, - "ape", 0x224A, - "apos", 0x0027, - "Aring", 0x00C5, - "aring", 0x00E5, - "ast", 0x002A, - "asymp", 0x224D, - "Atilde", 0x00C3, - "atilde", 0x00E3, - "Auml", 0x00C4, - "auml", 0x00E4, - NULL, 0 -}; - -static NameId namesB[]={ - "barwed", 0x22BC, - "Barwed", 0x2306, - "bcong", 0x224C, - "Bcy", 0x0411, - "bcy", 0x0431, - "becaus", 0x2235, - "bepsi", 0x220D, - "bernou", 0x212C, - "beta", 0x03B2, - "beth", 0x2136, - "Bgr", 0x0392, - "bgr", 0x03B2, - "blank", 0x2423, - "blk12", 0x2592, - "blk14", 0x2591, - "blk34", 0x2593, - "block", 0x2588, - "bottom", 0x22A5, - "bowtie", 0x22C8, - "boxdl", 0x2510, - "boxDL", 0x2555, - "boxdL", 0x2556, - "boxDl", 0x2557, - "boxdr", 0x250C, - "boxDR", 0x2552, - "boxDr", 0x2553, - "boxdR", 0x2554, - "boxh", 0x2500, - "boxH", 0x2550, - "boxhd", 0x252C, - "boxhD", 0x2564, - "boxHD", 0x2565, - "boxHd", 0x2566, - "boxhu", 0x2534, - "boxhU", 0x2567, - "boxHU", 0x2568, - "boxHu", 0x2569, - "boxul", 0x2518, - "boxUL", 0x255B, - "boxUl", 0x255C, - "boxuL", 0x255D, - "boxur", 0x2514, - "boxUR", 0x2558, - "boxuR", 0x2559, - "boxUr", 0x255A, - "boxv", 0x2502, - "boxV", 0x2551, - "boxvh", 0x253C, - "boxvH", 0x256A, - "boxVH", 0x256B, - "boxVh", 0x256C, - "boxvl", 0x2524, - "boxvL", 0x2561, - "boxVL", 0x2562, - "boxVl", 0x2563, - "boxvr", 0x251C, - "boxvR", 0x255E, - "boxVR", 0x255F, - "boxVr", 0x2560, - "bprime", 0x2035, - "breve", 0x02D8, - "brvbar", 0x00A6, - "bsim", 0x223D, - "bsime", 0x22CD, - "bsol", 0x005C, - "bull", 0x2022, - "bump", 0x224E, - "bumpe", 0x224F, - NULL, 0 -}; - -static NameId namesC[]={ - "Cacute", 0x0106, - "cacute", 0x0107, - "cap", 0x2229, - "Cap", 0x22D2, - "caret", 0x2041, - "caron", 0x02C7, - "Ccaron", 0x010C, - "ccaron", 0x010D, - "Ccedil", 0x00C7, - "ccedil", 0x00E7, - "Ccirc", 0x0108, - "ccirc", 0x0109, - "Cdot", 0x010A, - "cdot", 0x010B, - "cedil", 0x00B8, - "cent", 0x00A2, - "CHcy", 0x0427, - "chcy", 0x0447, - "check", 0x2713, - "chi", 0x03C7, - "cir", 0x25CB, - "circ", 0x005E, - "cire", 0x2257, - "clubs", 0x2663, - "colon", 0x003A, - "colone", 0x2254, - "comma", 0x002C, - "commat", 0x0040, - "comp", 0x2201, - "compfn", 0x2218, - "cong", 0x2245, - "conint", 0x222E, - "coprod", 0x2210, - "copy", 0x00A9, - "copysr", 0x2117, - "cross", 0x2717, - "cuepr", 0x22DE, - "cuesc", 0x22DF, - "cularr", 0x21B6, - "cup", 0x222A, - "Cup", 0x22D3, - "cupre", 0x227C, - "curarr", 0x21B7, - "curren", 0x00A4, - "cuvee", 0x22CE, - "cuwed", 0x22CF, - NULL, 0 -}; - -static NameId namesD[]={ - "dagger", 0x2020, - "Dagger", 0x2021, - "daleth", 0x2138, - "darr", 0x2193, - "dArr", 0x21D3, - "darr2", 0x21CA, - "dash", 0x2010, - "dashv", 0x22A3, - "dblac", 0x02DD, - "Dcaron", 0x010E, - "dcaron", 0x010F, - "Dcy", 0x0414, - "dcy", 0x0434, - "deg", 0x00B0, - "Delta", 0x0394, - "delta", 0x03B4, - "Dgr", 0x0394, - "dgr", 0x03B4, - "dharl", 0x21C3, - "dharr", 0x21C2, - "diam", 0x22C4, - "diams", 0x2666, - "die", 0x00A8, - "divide", 0x00F7, - "divonx", 0x22C7, - "DJcy", 0x0402, - "djcy", 0x0452, - "dlarr", 0x2199, - "dlcorn", 0x231E, - "dlcrop", 0x230D, - "dollar", 0x0024, - "Dot", 0x00A8, - "dot", 0x02D9, - "DotDot", 0x20DC, - "drarr", 0x2198, - "drcorn", 0x231F, - "drcrop", 0x230C, - "DScy", 0x0405, - "dscy", 0x0455, - "Dstrok", 0x0110, - "dstrok", 0x0111, - "dtri", 0x25BF, - "dtrif", 0x25BE, - "DZcy", 0x040F, - "dzcy", 0x045F, - NULL, 0 -}; - -static NameId namesE[]={ - "Eacgr", 0x0388, - "eacgr", 0x03AD, - "Eacute", 0x00C9, - "eacute", 0x00E9, - "Ecaron", 0x011A, - "ecaron", 0x011B, - "ecir", 0x2256, - "Ecirc", 0x00CA, - "ecirc", 0x00EA, - "ecolon", 0x2255, - "Ecy", 0x042D, - "ecy", 0x044D, - "Edot", 0x0116, - "edot", 0x0117, - "eDot", 0x2251, - "EEacgr", 0x0389, - "eeacgr", 0x03AE, - "EEgr", 0x0397, - "eegr", 0x03B7, - "efDot", 0x2252, - "Egr", 0x0395, - "egr", 0x03B5, - "Egrave", 0x00C8, - "egrave", 0x00E8, - "egs", 0x22DD, - "ell", 0x2113, - "els", 0x22DC, - "Emacr", 0x0112, - "emacr", 0x0113, - "empty", 0x2205, - "emsp", 0x2003, - "emsp13", 0x2004, - "emsp14", 0x2005, - "ENG", 0x014A, - "eng", 0x014B, - "ensp", 0x2002, - "Eogon", 0x0118, - "eogon", 0x0119, - "epsi", 0x220A, - "epsis", 0x220A, - "epsiv", 0x03B5, - "equals", 0x003D, - "equiv", 0x2261, - "erDot", 0x2253, - "esdot", 0x2250, - "eta", 0x03B7, - "ETH", 0x00D0, - "eth", 0x00F0, - "Euml", 0x00CB, - "euml", 0x00EB, - "excl", 0x0021, - "exist", 0x2203, - NULL, 0 -}; - -static NameId namesF[]={ - "Fcy", 0x0424, - "fcy", 0x0444, - "female", 0x2640, - "ffilig", 0xFB03, - "fflig", 0xFB00, - "ffllig", 0xFB04, - "filig", 0xFB01, - "flat", 0x266D, - "fllig", 0xFB02, - "fnof", 0x0192, - "forall", 0x2200, - "fork", 0x22D4, - "frac12", 0x00BD, - "frac13", 0x2153, - "frac14", 0x00BC, - "frac15", 0x2155, - "frac16", 0x2159, - "frac18", 0x215B, - "frac23", 0x2154, - "frac25", 0x2156, - "frac34", 0x00BE, - "frac35", 0x2157, - "frac38", 0x215C, - "frac45", 0x2158, - "frac56", 0x215A, - "frac58", 0x215D, - "frac78", 0x215E, - "frown", 0x2322, - NULL, 0 -}; - -static NameId namesG[]={ - "gacute", 0x01F5, - "Gamma", 0x0393, - "gamma", 0x03B3, - "gammad", 0x03DC, - "gap", 0x2273, - "Gbreve", 0x011E, - "gbreve", 0x011F, - "Gcedil", 0x0122, - "Gcirc", 0x011C, - "gcirc", 0x011D, - "Gcy", 0x0413, - "gcy", 0x0433, - "Gdot", 0x0120, - "gdot", 0x0121, - "ge", 0x2265, - "gE", 0x2267, - "gel", 0x22DB, - "gEl", 0x22DB, - "ges", 0x2265, - "Gg", 0x22D9, - "Ggr", 0x0393, - "ggr", 0x03B3, - "gimel", 0x2137, - "GJcy", 0x0403, - "gjcy", 0x0453, - "gl", 0x2277, - "gnap", 0xE411, - "gne", 0x2269, - "gnE", 0x2269, - "gnsim", 0x22E7, - "grave", 0x0060, - "gsdot", 0x22D7, - "gsim", 0x2273, - "gt", 0x003E, - "Gt", 0x226B, - "gvnE", 0x2269, - NULL, 0 -}; - -static NameId namesH[]={ - "hairsp", 0x200A, - "half", 0x00BD, - "hamilt", 0x210B, - "HARDcy", 0x042A, - "hardcy", 0x044A, - "harr", 0x2194, - "hArr", 0x21D4, - "harrw", 0x21AD, - "Hcirc", 0x0124, - "hcirc", 0x0125, - "hearts", 0x2665, - "hellip", 0x2026, - "horbar", 0x2015, - "Hstrok", 0x0126, - "hstrok", 0x0127, - "hybull", 0x2043, - "hyphen", 0x002D, - NULL, 0 -}; - -static NameId namesI[]={ - "Iacgr", 0x038A, - "iacgr", 0x03AF, - "Iacute", 0x00CD, - "iacute", 0x00ED, - "Icirc", 0x00CE, - "icirc", 0x00EE, - "Icy", 0x0418, - "icy", 0x0438, - "idiagr", 0x0390, - "Idigr", 0x03AA, - "idigr", 0x03CA, - "Idot", 0x0130, - "IEcy", 0x0415, - "iecy", 0x0435, - "iexcl", 0x00A1, - "iff", 0x21D4, - "Igr", 0x0399, - "igr", 0x03B9, - "Igrave", 0x00CC, - "igrave", 0x00EC, - "IJlig", 0x0132, - "ijlig", 0x0133, - "Imacr", 0x012A, - "imacr", 0x012B, - "image", 0x2111, - "incare", 0x2105, - "infin", 0x221E, - "inodot", 0x0131, - "int", 0x222B, - "intcal", 0x22BA, - "IOcy", 0x0401, - "iocy", 0x0451, - "Iogon", 0x012E, - "iogon", 0x012F, - "iota", 0x03B9, - "iquest", 0x00BF, - "isin", 0x220A, - "Itilde", 0x0128, - "itilde", 0x0129, - "Iukcy", 0x0406, - "iukcy", 0x0456, - "Iuml", 0x00CF, - "iuml", 0x00EF, - NULL, 0 -}; - -static NameId namesJ[]={ - "Jcirc", 0x0134, - "jcirc", 0x0135, - "Jcy", 0x0419, - "jcy", 0x0439, - "Jsercy", 0x0408, - "jsercy", 0x0458, - "Jukcy", 0x0404, - "jukcy", 0x0454, - NULL, 0 -}; - -static NameId namesK[]={ - "kappa", 0x03BA, - "kappav", 0x03F0, - "Kcedil", 0x0136, - "kcedil", 0x0137, - "Kcy", 0x041A, - "kcy", 0x043A, - "Kgr", 0x039A, - "kgr", 0x03BA, - "kgreen", 0x0138, - "KHcy", 0x0425, - "khcy", 0x0445, - "KHgr", 0x03A7, - "khgr", 0x03C7, - "KJcy", 0x040C, - "kjcy", 0x045C, - NULL, 0 -}; - -static NameId namesL[]={ - "lAarr", 0x21DA, - "Lacute", 0x0139, - "lacute", 0x013A, - "lagran", 0x2112, - "Lambda", 0x039B, - "lambda", 0x03BB, - "lang", 0x3008, - "lap", 0x2272, - "laquo", 0x00AB, - "larr", 0x2190, - "Larr", 0x219E, - "lArr", 0x21D0, - "larr2", 0x21C7, - "larrhk", 0x21A9, - "larrlp", 0x21AB, - "larrtl", 0x21A2, - "Lcaron", 0x013D, - "lcaron", 0x013E, - "Lcedil", 0x013B, - "lcedil", 0x013C, - "lceil", 0x2308, - "lcub", 0x007B, - "Lcy", 0x041B, - "lcy", 0x043B, - "ldot", 0x22D6, - "ldquo", 0x201C, - "ldquor", 0x201E, - "le", 0x2264, - "lE", 0x2266, - "leg", 0x22DA, - "lEg", 0x22DA, - "les", 0x2264, - "lfloor", 0x230A, - "lg", 0x2276, - "Lgr", 0x039B, - "lgr", 0x03BB, - "lhard", 0x21BD, - "lharu", 0x21BC, - "lhblk", 0x2584, - "LJcy", 0x0409, - "ljcy", 0x0459, - "Ll", 0x22D8, - "Lmidot", 0x013F, - "lmidot", 0x0140, - "lnap", 0xE2A2, - "lne", 0x2268, - "lnE", 0x2268, - "lnsim", 0x22E6, - "lowast", 0x2217, - "lowbar", 0x005F, - "loz", 0x25CA, - "lozf", 0x2726, - "lpar", 0x0028, - "lrarr2", 0x21C6, - "lrhar2", 0x21CB, - "lsh", 0x21B0, - "lsim", 0x2272, - "lsqb", 0x005B, - "lsquo", 0x2018, - "lsquor", 0x201A, - "Lstrok", 0x0141, - "lstrok", 0x0142, - "lt", 0x003C, - "Lt", 0x226A, - "lthree", 0x22CB, - "ltimes", 0x22C9, - "ltri", 0x25C3, - "ltrie", 0x22B4, - "ltrif", 0x25C2, - "lvnE", 0x2268, - NULL, 0 -}; - -static NameId namesM[]={ - "macr", 0x00AF, - "male", 0x2642, - "malt", 0x2720, - "map", 0x21A6, - "marker", 0x25AE, - "Mcy", 0x041C, - "mcy", 0x043C, - "mdash", 0x2014, - "Mgr", 0x039C, - "mgr", 0x03BC, - "micro", 0x00B5, - "mid", 0x2223, - "middot", 0x00B7, - "minus", 0x2212, - "minusb", 0x229F, - "mldr", 0x2026, - "mnplus", 0x2213, - "models", 0x22A7, - "mu", 0x03BC, - "mumap", 0x22B8, - NULL, 0 -}; - -static NameId namesN[]={ - "nabla", 0x2207, - "Nacute", 0x0143, - "nacute", 0x0144, - "nap", 0x2249, - "napos", 0x0149, - "natur", 0x266E, -// "nbsp", 0x00A0, - "nbsp", 32, // make non-breaking space appear as space - "Ncaron", 0x0147, - "ncaron", 0x0148, - "Ncedil", 0x0145, - "ncedil", 0x0146, - "ncong", 0x2247, - "Ncy", 0x041D, - "ncy", 0x043D, - "ndash", 0x2013, - "ne", 0x2260, - "nearr", 0x2197, - "nequiv", 0x2262, - "nexist", 0x2204, - "nge", 0x2271, - "ngE", 0x2271, - "nges", 0x2271, - "Ngr", 0x039D, - "ngr", 0x03BD, - "ngt", 0x226F, - "nharr", 0x21AE, - "nhArr", 0x21CE, - "ni", 0x220D, - "NJcy", 0x040A, - "njcy", 0x045A, - "nlarr", 0x219A, - "nlArr", 0x21CD, - "nldr", 0x2025, - "nle", 0x2270, - "nlE", 0x2270, - "nles", 0x2270, - "nlt", 0x226E, - "nltri", 0x22EA, - "nltrie", 0x22EC, - "nmid", 0x2224, - "not", 0x00AC, - "notin", 0x2209, - "npar", 0x2226, - "npr", 0x2280, - "npre", 0x22E0, - "nrarr", 0x219B, - "nrArr", 0x21CF, - "nrtri", 0x22EB, - "nrtrie", 0x22ED, - "nsc", 0x2281, - "nsce", 0x22E1, - "nsim", 0x2241, - "nsime", 0x2244, - "nsmid", 0xE2AA, - "nspar", 0x2226, - "nsub", 0x2284, - "nsube", 0x2288, - "nsubE", 0x2288, - "nsup", 0x2285, - "nsupe", 0x2289, - "nsupE", 0x2289, - "Ntilde", 0x00D1, - "ntilde", 0x00F1, - "nu", 0x03BD, - "num", 0x0023, - "numero", 0x2116, - "numsp", 0x2007, - "nvdash", 0x22AC, - "nvDash", 0x22AD, - "nVdash", 0x22AE, - "nVDash", 0x22AF, - "nwarr", 0x2196, - NULL, 0 -}; - -static NameId namesO[]={ - "Oacgr", 0x038C, - "oacgr", 0x03CC, - "Oacute", 0x00D3, - "oacute", 0x00F3, - "oast", 0x229B, - "ocir", 0x229A, - "Ocirc", 0x00D4, - "ocirc", 0x00F4, - "Ocy", 0x041E, - "ocy", 0x043E, - "odash", 0x229D, - "Odblac", 0x0150, - "odblac", 0x0151, - "odot", 0x2299, - "OElig", 0x0152, - "oelig", 0x0153, - "ogon", 0x02DB, - "Ogr", 0x039F, - "ogr", 0x03BF, - "Ograve", 0x00D2, - "ograve", 0x00F2, - "OHacgr", 0x038F, - "ohacgr", 0x03CE, - "OHgr", 0x03A9, - "ohgr", 0x03C9, - "ohm", 0x2126, - "olarr", 0x21BA, - "Omacr", 0x014C, - "omacr", 0x014D, - "Omega", 0x03A9, - "omega", 0x03C9, - "ominus", 0x2296, - "oplus", 0x2295, - "or", 0x2228, - "orarr", 0x21BB, - "order", 0x2134, - "ordf", 0x00AA, - "ordm", 0x00BA, - "oS", 0x24C8, - "Oslash", 0x00D8, - "oslash", 0x00F8, - "osol", 0x2298, - "Otilde", 0x00D5, - "otilde", 0x00F5, - "otimes", 0x2297, - "Ouml", 0x00D6, - "ouml", 0x00F6, - NULL, 0 -}; - -static NameId namesP[]={ - "par", 0x2225, - "para", 0x00B6, - "part", 0x2202, - "Pcy", 0x041F, - "pcy", 0x043F, - "percnt", 0x0025, - "period", 0x002E, - "permil", 0x2030, - "perp", 0x22A5, - "Pgr", 0x03A0, - "pgr", 0x03C0, - "PHgr", 0x03A6, - "phgr", 0x03C6, - "Phi", 0x03A6, - "phis", 0x03C6, - "phiv", 0x03D5, - "phmmat", 0x2133, - "phone", 0x260E, - "Pi", 0x03A0, - "pi", 0x03C0, - "piv", 0x03D6, - "planck", 0x210F, - "plus", 0x002B, - "plusb", 0x229E, - "plusdo", 0x2214, - "plusmn", 0x00B1, - "pound", 0x00A3, - "pr", 0x227A, - "prap", 0x227E, - "pre", 0x227C, - "prime", 0x2032, - "Prime", 0x2033, - "prnap", 0x22E8, - "prnE", 0xE2B3, - "prnsim", 0x22E8, - "prod", 0x220F, - "prop", 0x221D, - "prsim", 0x227E, - "PSgr", 0x03A8, - "psgr", 0x03C8, - "Psi", 0x03A8, - "psi", 0x03C8, - "puncsp", 0x2008, - NULL, 0 -}; - -static NameId namesQ[]={ - "quest", 0x003F, - "quot", 0x0022, - NULL, 0 -}; - -static NameId namesR[]={ - "rAarr", 0x21DB, - "Racute", 0x0154, - "racute", 0x0155, - "radic", 0x221A, - "rang", 0x3009, - "raquo", 0x00BB, - "rarr", 0x2192, - "Rarr", 0x21A0, - "rArr", 0x21D2, - "rarr2", 0x21C9, - "rarrhk", 0x21AA, - "rarrlp", 0x21AC, - "rarrtl", 0x21A3, - "rarrw", 0x219D, - "Rcaron", 0x0158, - "rcaron", 0x0159, - "Rcedil", 0x0156, - "rcedil", 0x0157, - "rceil", 0x2309, - "rcub", 0x007D, - "Rcy", 0x0420, - "rcy", 0x0440, - "rdquo", 0x201D, - "rdquor", 0x201C, - "real", 0x211C, - "rect", 0x25AD, - "reg", 0x00AE, - "rfloor", 0x230B, - "Rgr", 0x03A1, - "rgr", 0x03C1, - "rhard", 0x21C1, - "rharu", 0x21C0, - "rho", 0x03C1, - "rhov", 0x03F1, - "ring", 0x02DA, - "rlarr2", 0x21C4, - "rlhar2", 0x21CC, - "rpar", 0x0029, - "rpargt", 0xE291, - "rsh", 0x21B1, - "rsqb", 0x005D, - "rsquo", 0x2019, - "rsquor", 0x2018, - "rthree", 0x22CC, - "rtimes", 0x22CA, - "rtri", 0x25B9, - "rtrie", 0x22B5, - "rtrif", 0x25B8, - "rx", 0x211E, - NULL, 0 -}; - -static NameId namesS[]={ - "Sacute", 0x015A, - "sacute", 0x015B, - "samalg", 0x2210, - "sbsol", 0xFE68, - "sc", 0x227B, - "scap", 0x227F, - "Scaron", 0x0160, - "scaron", 0x0161, - "sccue", 0x227D, - "sce", 0x227D, - "Scedil", 0x015E, - "scedil", 0x015F, - "Scirc", 0x015C, - "scirc", 0x015D, - "scnap", 0x22E9, - "scnE", 0xE2B5, - "scnsim", 0x22E9, - "scsim", 0x227F, - "Scy", 0x0421, - "scy", 0x0441, - "sdot", 0x22C5, - "sdotb", 0x22A1, - "sect", 0x00A7, - "semi", 0x003B, - "setmn", 0x2216, - "sext", 0x2736, - "sfgr", 0x03C2, - "sfrown", 0x2322, - "Sgr", 0x03A3, - "sgr", 0x03C3, - "sharp", 0x266F, - "SHCHcy", 0x0429, - "shchcy", 0x0449, - "SHcy", 0x0428, - "shcy", 0x0448, - "shy", 0x00AD, - "Sigma", 0x03A3, - "sigma", 0x03C3, - "sigmav", 0x03C2, - "sim", 0x223C, - "sime", 0x2243, - "smid", 0xE301, - "smile", 0x2323, - "SOFTcy", 0x042C, - "softcy", 0x044C, - "sol", 0x002F, - "spades", 0x2660, - "spar", 0x2225, - "sqcap", 0x2293, - "sqcup", 0x2294, - "sqsub", 0x228F, - "sqsube", 0x2291, - "sqsup", 0x2290, - "sqsupe", 0x2292, - "squ", 0x25A1, - "square", 0x25A1, - "squf", 0x25AA, - "ssetmn", 0x2216, - "ssmile", 0x2323, - "sstarf", 0x22C6, - "star", 0x22C6, - "starf", 0x2605, - "sub", 0x2282, - "Sub", 0x22D0, - "sube", 0x2286, - "subE", 0x2286, - "subne", 0x228A, - "subnE", 0x228A, - "sum", 0x2211, - "sung", 0x2669, - "sup", 0x2283, - "Sup", 0x22D1, - "sup1", 0x00B9, - "sup2", 0x00B2, - "sup3", 0x00B3, - "supe", 0x2287, - "supE", 0x2287, - "supne", 0x228B, - "supnE", 0x228B, - "szlig", 0x00DF, - NULL, 0 -}; - -static NameId namesT[]={ - "target", 0x2316, - "tau", 0x03C4, - "Tcaron", 0x0164, - "tcaron", 0x0165, - "Tcedil", 0x0162, - "tcedil", 0x0163, - "Tcy", 0x0422, - "tcy", 0x0442, - "tdot", 0x20DB, - "telrec", 0x2315, - "Tgr", 0x03A4, - "tgr", 0x03C4, - "there4", 0x2234, - "Theta", 0x0398, - "thetas", 0x03B8, - "thetav", 0x03D1, - "THgr", 0x0398, - "thgr", 0x03B8, - "thinsp", 0x2009, - "thkap", 0x2248, - "thksim", 0x223C, - "THORN", 0x00DE, - "thorn", 0x00FE, - "tilde", 0x02DC, - "times", 0x00D7, - "timesb", 0x22A0, - "top", 0x22A4, - "tprime", 0x2034, - "trade", 0x2122, - "trie", 0x225C, - "TScy", 0x0426, - "tscy", 0x0446, - "TSHcy", 0x040B, - "tshcy", 0x045B, - "Tstrok", 0x0166, - "tstrok", 0x0167, - "twixt", 0x226C, - NULL, 0 -}; - -static NameId namesU[]={ - "Uacgr", 0x038E, - "uacgr", 0x03CD, - "Uacute", 0x00DA, - "uacute", 0x00FA, - "uarr", 0x2191, - "uArr", 0x21D1, - "uarr2", 0x21C8, - "Ubrcy", 0x040E, - "ubrcy", 0x045E, - "Ubreve", 0x016C, - "ubreve", 0x016D, - "Ucirc", 0x00DB, - "ucirc", 0x00FB, - "Ucy", 0x0423, - "ucy", 0x0443, - "Udblac", 0x0170, - "udblac", 0x0171, - "udiagr", 0x03B0, - "Udigr", 0x03AB, - "udigr", 0x03CB, - "Ugr", 0x03A5, - "ugr", 0x03C5, - "Ugrave", 0x00D9, - "ugrave", 0x00F9, - "uharl", 0x21BF, - "uharr", 0x21BE, - "uhblk", 0x2580, - "ulcorn", 0x231C, - "ulcrop", 0x230F, - "Umacr", 0x016A, - "umacr", 0x016B, - "uml", 0x00A8, - "Uogon", 0x0172, - "uogon", 0x0173, - "uplus", 0x228E, - "upsi", 0x03C5, - "Upsi", 0x03D2, - "urcorn", 0x231D, - "urcrop", 0x230E, - "Uring", 0x016E, - "uring", 0x016F, - "Utilde", 0x0168, - "utilde", 0x0169, - "utri", 0x25B5, - "utrif", 0x25B4, - "Uuml", 0x00DC, - "uuml", 0x00FC, - NULL, 0 -}; - -static NameId namesV[]={ - "varr", 0x2195, - "vArr", 0x21D5, - "Vcy", 0x0412, - "vcy", 0x0432, - "vdash", 0x22A2, - "vDash", 0x22A8, - "Vdash", 0x22A9, - "veebar", 0x22BB, - "vellip", 0x22EE, - "verbar", 0x007C, - "Verbar", 0x2016, - "vltri", 0x22B2, - "vprime", 0x2032, - "vprop", 0x221D, - "vrtri", 0x22B3, - "vsubne", 0x228A, - "vsubnE", 0xE2B8, - "vsupne", 0x228B, - "vsupnE", 0x228B, - "Vvdash", 0x22AA, - NULL, 0 -}; - -static NameId namesW[]={ - "Wcirc", 0x0174, - "wcirc", 0x0175, - "wedgeq", 0x2259, - "weierp", 0x2118, - "wreath", 0x2240, - NULL, 0 -}; - -static NameId namesX[]={ - "xcirc", 0x25CB, - "xdtri", 0x25BD, - "Xgr", 0x039E, - "xgr", 0x03BE, - "xharr", 0x2194, - "xhArr", 0x2194, - "Xi", 0x039E, - "xi", 0x03BE, - "xlArr", 0x21D0, - "xrArr", 0x21D2, - "xutri", 0x25B3, - NULL, 0 -}; - -static NameId namesY[]={ - "Yacute", 0x00DD, - "yacute", 0x00FD, - "YAcy", 0x042F, - "yacy", 0x044F, - "Ycirc", 0x0176, - "ycirc", 0x0177, - "Ycy", 0x042B, - "ycy", 0x044B, - "yen", 0x00A5, - "YIcy", 0x0407, - "yicy", 0x0457, - "YUcy", 0x042E, - "yucy", 0x044E, - "yuml", 0x00FF, - "Yuml", 0x0178, - NULL, 0 -}; - -static NameId namesZ[]={ - "Zacute", 0x0179, - "zacute", 0x017A, - "Zcaron", 0x017D, - "zcaron", 0x017E, - "Zcy", 0x0417, - "zcy", 0x0437, - "Zdot", 0x017B, - "zdot", 0x017C, - "zeta", 0x03B6, - "Zgr", 0x0396, - "zgr", 0x03B6, - "ZHcy", 0x0416, - "zhcy", 0x0436, - NULL, 0 -}; - -// @todo@ order namesTable and names? by frequency -static NameId* namesTable[] = { - namesA, namesB, namesC, namesD, namesE, namesF, namesG, namesH, namesI, - namesJ, namesK, namesL, namesM, namesN, namesO, namesP, namesQ, namesR, - namesS, namesT, namesU, namesV, namesW, namesX, namesY, namesZ, NULL -}; - -int HtmlNamedEntity(unsigned char *p, int length) -{ - int tableIndex = tolower(*p) - 'a'; - if (tableIndex >= 0 && tableIndex < 26) { - NameId* names = namesTable[tableIndex]; - int i; - - for (i = 0; names[i].name; i++){ - if (strncmp(names[i].name, (char *)p, length) == 0){ - return names[i].value; - } - } - } - error("unrecognized character entity \"%.*s\"", length, p); - return -1; -} diff -uNr gdc-0.11/d/root/enum.c gdc-0.12/d/root/enum.c --- gdc-0.11/d/root/enum.c 2005-02-20 16:43:51.000000000 +0100 +++ gdc-0.12/d/root/enum.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,232 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "root.h" -#include "enum.h" -#include "mtype.h" -#include "scope.h" - -/********************************* EnumDeclaration ****************************/ - -EnumDeclaration::EnumDeclaration(Identifier *id, Type *memtype) - : ScopeDsymbol(id) -{ - type = new TypeEnum(this); - this->memtype = memtype; - maxval = 0; - minval = 0x7FFFFFFF; // BUG: long long max? - defaultval = 0; -} - -Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s) -{ - Type *t = NULL; - if (memtype) - t = memtype->syntaxCopy(); - - EnumDeclaration *ed; - if (s) - { ed = (EnumDeclaration *)s; - ed->memtype = t; - } - else - ed = new EnumDeclaration(ident, t); - ScopeDsymbol::syntaxCopy(ed); - return ed; -} - -void EnumDeclaration::semantic(Scope *sc) -{ int i; - integer_t number; - Type *t; - Scope *sce; - - //printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars()); - if (symtab) // if already done - return; - if (!memtype) - memtype = Type::tint32; - parent = sc->scopesym; - memtype = memtype->semantic(loc, sc); - if (!memtype->isintegral()) - error("EnumBaseType must be integral type, not %s", memtype->toChars()); - - t = isAnonymous() ? memtype : type; - symtab = new DsymbolTable(); - sce = sc->push(this); - sce->parent = this; - number = 0; - if (!members) // enum ident; - return; - if (members->dim == 0) - error("enum %s must have at least one member", toChars()); - for (i = 0; i < members->dim; i++) - { - EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); - Expression *e; - - if (!em) - /* The e->semantic(sce) can insert other symbols, such as - * template instances and function literals. - */ - continue; - - //printf("Enum member '%s'\n",em->toChars()); - e = em->value; - if (e) - { - assert(e->dyncast() == DYNCAST_EXPRESSION); - e = e->semantic(sce); - e = e->implicitCastTo(memtype); - e = e->optimize(WANTvalue); - number = e->toInteger(); - e->type = t; - } - else - { // Default is the previous number plus 1 - e = new IntegerExp(em->loc, number, t); - } - em->value = e; - - // Add to symbol table only after evaluating 'value' - if (isAnonymous()) - { //em->addMember((ScopeDsymbol *)parent); - sce->enclosing->insert(em); - em->parent = sce->enclosing->parent; - } - else - em->addMember(this); - - if (number < minval) - minval = number; - if (number > maxval) - maxval = number; - if (i == 0) - defaultval = number; - - number++; - } - - sce->pop(); - //members->print(); -} - -Dsymbol *EnumDeclaration::oneMember() -{ - if (isAnonymous() && members && members->dim) - { - Dsymbol *s = (Dsymbol *)members->data[0]; - s = s->oneMember(); - - // Ignore any additional template instance symbols - for (int j = 1; j < members->dim; j++) - { Dsymbol *sx = (Dsymbol *)members->data[j]; - if (sx->isTemplateInstance()) - continue; - s = NULL; - break; - } - - if (s) - return s; - } - return this; -} - -void EnumDeclaration::toCBuffer(OutBuffer *buf) -{ int i; - - buf->writestring("enum "); - if (ident) - { buf->writestring(ident->toChars()); - buf->writeByte(' '); - } - if (memtype) - { - buf->writestring(": "); - memtype->toCBuffer(buf, NULL); - } - if (!members) - { - buf->writeByte(';'); - buf->writenl(); - return; - } - buf->writenl(); - buf->writeByte('{'); - buf->writenl(); - for (i = 0; i < members->dim; i++) - { - EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); - if (!em) - continue; - buf->writestring(" "); - em->toCBuffer(buf); - buf->writeByte(','); - buf->writenl(); - } - buf->writeByte('}'); - buf->writenl(); -} - -Type *EnumDeclaration::getType() -{ - return type; -} - -char *EnumDeclaration::kind() -{ - return "enum"; -} - -/********************************* EnumMember ****************************/ - -EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value) - : Dsymbol(id) -{ - this->value = value; - this->loc = loc; -} - -Dsymbol *EnumMember::syntaxCopy(Dsymbol *s) -{ - Expression *e = NULL; - if (value) - e = value->syntaxCopy(); - - EnumMember *em; - if (s) - { em = (EnumMember *)s; - em->loc = loc; - em->value = e; - } - else - em = new EnumMember(loc, ident, e); - return em; -} - -void EnumMember::toCBuffer(OutBuffer *buf) -{ - buf->writestring(ident->toChars()); - if (value) - { - buf->writestring(" = "); - value->toCBuffer(buf); - } -} - -char *EnumMember::kind() -{ - return "enum member"; -} - - diff -uNr gdc-0.11/d/root/enum.h gdc-0.12/d/root/enum.h --- gdc-0.11/d/root/enum.h 2005-01-10 04:30:55.000000000 +0100 +++ gdc-0.12/d/root/enum.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,60 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_ENUM_H -#define DMD_ENUM_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" -#include "dsymbol.h" - -struct Identifier; -struct Type; -struct Expression; - -struct EnumDeclaration : ScopeDsymbol -{ - Type *type; // the TypeEnum - Type *memtype; // type of the members - integer_t maxval; - integer_t minval; - integer_t defaultval; // default initializer - - EnumDeclaration(Identifier *id, Type *memtype); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - Dsymbol *oneMember(); - void toCBuffer(OutBuffer *buf); - Type *getType(); - char *kind(); - - EnumDeclaration *isEnumDeclaration() { return this; } - - void toObjFile(); // compile to .obj file - void toDebug(); - int cvMember(unsigned char *p); -}; - - -struct EnumMember : Dsymbol -{ - Expression *value; - - EnumMember(Loc loc, Identifier *id, Expression *value); - Dsymbol *syntaxCopy(Dsymbol *s); - void toCBuffer(OutBuffer *buf); - char *kind(); - - EnumMember *isEnumMember() { return this; } -}; - -#endif /* DMD_ENUM_H */ diff -uNr gdc-0.11/d/root/expression.c gdc-0.12/d/root/expression.c --- gdc-0.11/d/root/expression.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/expression.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,5478 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -// Issues with using -include total.h (defines integer_t) and then complex.h fails... -#undef integer_t - -#include -#include -#include -#include -#include - -#ifdef __APPLE__ -#define integer_t dmd_integer_t -#endif - -#if _WIN32 -#include "..\root\mem.h" -#endif -#ifndef _WIN32 -#include "../root/mem.h" -#endif -#include "port.h" -#include "mtype.h" -#include "init.h" -#include "expression.h" -#include "template.h" -#include "utf.h" -#include "enum.h" -#include "scope.h" -#include "statement.h" -#include "declaration.h" -#include "aggregate.h" -#include "import.h" -#include "id.h" -#include "dsymbol.h" -#include "module.h" - -Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim); - -#define LOGSEMANTIC 0 - -/***************************************** - * Determine if 'this' is available. - * If it is, return the FuncDeclaration that has it. - */ - -FuncDeclaration *hasThis(Scope *sc) -{ FuncDeclaration *fd; - FuncDeclaration *fdthis; - - //printf("hasThis()\n"); - fdthis = sc->parent->isFuncDeclaration(); - //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : ""); - - // Go upwards until we find the enclosing member function - fd = fdthis; - while (1) - { - if (!fd) - { - goto Lno; - } - if (!fd->isNested()) - break; - - Dsymbol *parent = fd->parent; - while (parent) - { - TemplateInstance *ti = parent->isTemplateInstance(); - if (ti) - parent = ti->parent; - else - break; - } - - fd = fd->parent->isFuncDeclaration(); - } - - if (!fd->isThis()) - { //printf("test2 '%s'\n", fd->toChars()); - goto Lno; - } - - assert(fd->vthis); - return fd; - -Lno: - return NULL; // don't have 'this' available -} - - -/*************************************** - * Pull out any properties. - */ - -Expression *resolveProperties(Scope *sc, Expression *e) -{ - if (e->type) - { - Type *t = e->type->toBasetype(); - - if (t->ty == Tfunction) - { - e = new CallExp(e->loc, e); - e = e->semantic(sc); - } - } - return e; -} - -/****************************** - * Perform semantic() on an array of Expressions. - */ - -void arrayExpressionSemantic(Array *a, Scope *sc) -{ - if (a) - { - for (int i = 0; i < a->dim; i++) - { Expression *e = (Expression *)a->data[i]; - - e = e->semantic(sc); - a->data[i] = (void *)e; - } - } -} - -/**************************************** - * Preprocess arguments to function. - */ - -void preFunctionArguments(Loc loc, Scope *sc, Array *arguments) -{ - if (arguments) - { - for (int i = 0; i < arguments->dim; i++) - { Expression *arg = (Expression *)arguments->data[i]; - - if (!arg->type) - { - arg->error("%s is not an expression", arg->toChars()); - arg = new IntegerExp(arg->loc, 0, Type::tint32); - } - - arg = resolveProperties(sc, arg); - arguments->data[i] = (void *) arg; - - arg->rvalue(); -#if 0 - if (arg->type->ty == Tfunction) - { - arg = new AddrExp(arg->loc, arg); - arg = arg->semantic(sc); - arguments->data[i] = (void *) arg; - } -#endif - } - } -} - - -/**************************************** - * Now that we know the exact type of the function we're calling, - * the arguments[] need to be adjusted: - * 1) implicitly convert argument to the corresponding parameter type - * 2) add default arguments for any missing arguments - * 3) do default promotions on arguments corresponding to ... - * 4) add hidden _arguments[] argument - */ - -void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Array *arguments) -{ - unsigned nargs; - unsigned nproto; - unsigned n; - Type *tb; - - assert(arguments); - nargs = arguments ? arguments->dim : 0; - nproto = tf->arguments ? tf->arguments->dim : 0; - - if (nargs > nproto && !tf->varargs) - error(loc, "expected %d arguments, not %d\n", nproto, nargs); - - n = (nargs > nproto) ? nargs : nproto; // maximum - - for (int i = 0; i < n; i++) - { - Expression *arg; - Argument *p; - - if (i < nargs) - arg = (Expression *)arguments->data[i]; - - if (i < nproto) - { - Argument *p = (Argument *)tf->arguments->data[i]; - - if (i >= nargs) - { - if (!p->defaultArg) - { error(loc, "expected %d arguments, not %d\n", nproto, nargs); - break; - } - arg = p->defaultArg->copy(); - arguments->push(arg); - } - - arg = arg->implicitCastTo(p->type); - if (p->inout == Out || p->inout == InOut) - { - // BUG: should check that argument to inout is type 'invariant' - // BUG: assignments to inout should also be type 'invariant' - arg = arg->modifiableLvalue(sc, NULL); - - //if (arg->op == TOKslice) - //arg->error("cannot modify slice %s", arg->toChars()); - - // Don't have a way yet to do a pointer to a bit in array - if (arg->op == TOKarray && - arg->type->toBasetype()->ty == Tbit) - error("cannot have out or inout argument of bit in array"); - } - // Convert static arrays to pointers - if (arg->type->toBasetype()->ty == Tsarray) - { - arg = arg->checkToPointer(); - } - } - else - { - - // If not D linkage, do promotions - if (tf->linkage != LINKd) - { - // Promote bytes, words, etc., to ints - arg = arg->integralPromotions(); - - // Promote floats to doubles - switch (arg->type->ty) - { - case Tfloat32: - arg = arg->castTo(Type::tfloat64); - break; - - case Timaginary32: - arg = arg->castTo(Type::timaginary64); - break; - } - } - - // Convert static arrays to dynamic arrays - tb = arg->type->toBasetype(); - if (tb->ty == Tsarray) - { - arg = arg->castTo(tb->next->arrayOf()); - } - } - arg = arg->optimize(WANTvalue); - arguments->data[i] = (void *) arg; - } - - // If D linkage and variadic, add _arguments[] as first argument - if (tf->linkage == LINKd && tf->varargs) - { - Expression *e; - - e = createTypeInfoArray(sc, (Expression **)&arguments->data[nproto], - arguments->dim - nproto); - arguments->insert(0, e); - } -} - -void argsToCBuffer(OutBuffer *buf, Array *arguments) -{ int i; - - if (arguments) - { - for (i = 0; i < arguments->dim; i++) - { Expression *arg = (Expression *)arguments->data[i]; - - if (i) - buf->writeByte(','); - arg->toCBuffer(buf); - } - } -} - -/******************************** Expression **************************/ - -Expression::Expression(Loc loc, enum TOK op, int size) - : loc(loc) -{ - this->loc = loc; - this->op = op; - this->size = size; - type = NULL; -} - -Expression *Expression::syntaxCopy() -{ - //printf("Expression::syntaxCopy()\n"); - //dump(0); - return copy(); -} - -/********************************* - * Does *not* do a deep copy. - */ - -Expression *Expression::copy() -{ - Expression *e; - if (!size) - printf("No expression copy for: %s\n", toChars()); - e = (Expression *)mem.malloc(size); - return (Expression *)memcpy(e, this, size); -} - -/************************** - * Semantically analyze Expression. - * Determine types, fold constants, etc. - */ - -Expression *Expression::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("Expression::semantic()\n"); -#endif - if (type) - type = type->semantic(loc, sc); - else - type = Type::tvoid; - return this; -} - -void Expression::print() -{ - printf("%s\n", toChars()); - fflush(stdout); -} - -char *Expression::toChars() -{ OutBuffer *buf; - - buf = new OutBuffer(); - toCBuffer(buf); - return buf->toChars(); -} - -void Expression::error(const char *format, ...) -{ - char *p = loc.toChars(); - - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); - - global.errors++; - //fatal(); -} - -void Expression::rvalue() -{ - if (type && type->toBasetype()->ty == Tvoid) - error("voids have no value"); -} - -Expression *Expression::combine(Expression *e1, Expression *e2) -{ - if (e1) - { - if (e2) - { - e1 = new CommaExp(e1->loc, e1, e2); - e1->type = e2->type; - } - } - else - e1 = e2; - return e1; -} - -integer_t Expression::toInteger() -{ - //printf("Expression %s\n", Token::toChars(op)); - error("Integer constant expression expected instead of %s", toChars()); - return 0; -} - -real_t Expression::toReal() -{ - error("Floating point constant expression expected instead of %s", toChars()); - return 0; -} - -real_t Expression::toImaginary() -{ - error("Floating point constant expression expected instead of %s", toChars()); - return 0; -} - -complex_t Expression::toComplex() -{ - error("Floating point constant expression expected instead of %s", toChars()); -#ifdef IN_GCC - return complex_t(real_t(0)); // %% nicer -#else - return 0; -#endif -} - -void Expression::toCBuffer(OutBuffer *buf) -{ - buf->writestring(Token::toChars(op)); -} - -/******************************* - * Give error if we're not an lvalue. - * If we can, convert expression to be an lvalue. - */ - -Expression *Expression::toLvalue(Expression *e) -{ - if (!e) - e = this; - else if (!loc.filename) - loc = e->loc; - error("%s is not an lvalue", e->toChars()); - return this; -} - -Expression *Expression::modifiableLvalue(Scope *sc, Expression *e) -{ - // See if this expression is a modifiable lvalue (i.e. not const) - return toLvalue(e); -} - -void Expression::checkScalar() -{ - if (!type->isscalar()) - error("'%s' is not a scalar, it is a %s", toChars(), type->toChars()); -} - -Expression *Expression::checkIntegral() -{ - if (!type->isintegral()) - { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars()); - return new IntegerExp(0); - } - return this; -} - -void Expression::checkArithmetic() -{ - if (!type->isintegral() && !type->isfloating()) - error("'%s' is not an arithmetic type", toChars()); -} - -void Expression::checkDeprecated(Scope *sc, Dsymbol *s) -{ - s->checkDeprecated(loc, sc); -} - -/***************************** - * Check that expression can be tested for true or false. - */ - -Expression *Expression::checkToBoolean() -{ - // Default is 'yes' - do nothing - -#ifdef DEBUG - if (!type) - dump(0); -#endif - - if (!type->checkBoolean()) - error("expression %s of type %s does not have a boolean value", toChars(), type->toChars()); - return this; -} - -/**************************** - */ - -Expression *Expression::checkToPointer() -{ - Expression *e; - Type *tb; - - //printf("Expression::checkToPointer()\n"); - e = this; - - // If C static array, convert to pointer - tb = type->toBasetype(); - if (tb->ty == Tsarray) - { - e = new AddrExp(loc, this); - e->type = tb->next->pointerTo(); - } - return e; -} - -/****************************** - * Take address of expression. - */ - -Expression *Expression::addressOf() -{ - Expression *e; - - //printf("Expression::addressOf()\n"); - e = toLvalue(NULL); - e = new AddrExp(loc, e); - e->type = type->pointerTo(); - return e; -} - -/****************************** - * If this is a reference, dereference it. - */ - -Expression *Expression::deref() -{ - //printf("Expression::deref()\n"); - if (type->ty == Treference) - { Expression *e; - - e = new PtrExp(loc, this); - e->type = type->next; - return e; - } - return this; -} - -/******************************** - * Does this expression statically evaluate to a boolean TRUE or FALSE? - */ - -int Expression::isBool(int result) -{ - return FALSE; -} - -/******************************** - * Does this expression result in either a 1 or a 0? - */ - -int Expression::isBit() -{ - return FALSE; -} - -Array *Expression::arraySyntaxCopy(Array *exps) -{ Array *a = NULL; - - if (exps) - { - a = new Array(); - a->setDim(exps->dim); - for (int i = 0; i < a->dim; i++) - { Expression *e = (Expression *)exps->data[i]; - - e = e->syntaxCopy(); - a->data[i] = e; - } - } - return a; -} - -/******************************** IntegerExp **************************/ - -IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type) - : Expression(loc, TOKint64, sizeof(IntegerExp)) -{ - if (type && !type->isscalar()) - { - error("integral constant must be scalar type, not %s", type->toChars()); - type = Type::terror; - } - this->type = type; - this->value = value; -} - -IntegerExp::IntegerExp(integer_t value) - : Expression(0, TOKint64, sizeof(IntegerExp)) -{ - this->type = Type::tint32; - this->value = value; -} - -int IntegerExp::equals(Object *o) -{ IntegerExp *ne; - - if (this == o || - (((Expression *)o)->op == TOKint64 && - ((ne = (IntegerExp *)o), type->equals(ne->type)) && - value == ne->value)) - return 1; - return 0; -} - -char *IntegerExp::toChars() -{ - static char buffer[sizeof(value) * 3 + 1]; - - sprintf(buffer, "%lld", value); - return buffer; -} - -integer_t IntegerExp::toInteger() -{ Type *t; - - t = type; - while (t) - { - switch (t->ty) - { - case Tbit: value = (value != 0); break; - case Tint8: value = (d_int8) value; break; - case Tchar: - case Tuns8: value = (d_uns8) value; break; - case Tint16: value = (d_int16) value; break; - case Twchar: - case Tuns16: value = (d_uns16) value; break; - case Tint32: value = (d_int32) value; break; - case Tpointer: - case Tdchar: - case Tuns32: value = (d_uns32) value; break; - case Tint64: value = (d_int64) value; break; - case Tuns64: value = (d_uns64) value; break; - - case Tenum: - { - TypeEnum *te = (TypeEnum *)t; - t = te->sym->memtype; - continue; - } - - case Ttypedef: - { - TypeTypedef *tt = (TypeTypedef *)t; - t = tt->sym->basetype; - continue; - } - - default: - print(); - type->print(); - assert(0); - break; - } - break; - } - return value; -} - -real_t IntegerExp::toReal() -{ - Type *t; - - toInteger(); - t = type->toBasetype(); - if (t->ty == Tuns64) - return (real_t)(d_uns64)value; - else - return (real_t)(d_int64)value; -} - -real_t IntegerExp::toImaginary() -{ - return (real_t) 0; -} - -int IntegerExp::isBool(int result) -{ - return result ? value != 0 : value == 0; -} - -Expression *IntegerExp::semantic(Scope *sc) -{ - if (!type) - { - // Determine what the type of this number is - integer_t number = value; - - if (number & 0x8000000000000000LL) - type = Type::tuns64; - else if (number & 0xFFFFFFFF80000000LL) - type = Type::tint64; - else - type = Type::tint32; - } - else - { type = type->semantic(loc, sc); - } - return this; -} - -Expression *IntegerExp::toLvalue(Expression *e) -{ - if (!e) - e = this; - else if (!loc.filename) - loc = e->loc; - error("constant %s is not an lvalue", e->toChars()); - return this; -} - -void IntegerExp::toCBuffer(OutBuffer *buf) -{ - if (type) - { - if (type->ty == Tenum) - { TypeEnum *te = (TypeEnum *)type; - - buf->printf("cast(%s)", te->sym->toChars()); - } - } - if (value & 0x8000000000000000LL) - buf->printf("0x%llx", value); - else - buf->printf("%lld", value); -} - -/******************************** RealExp **************************/ - -RealExp::RealExp(Loc loc, real_t value, Type *type) - : Expression(loc, TOKfloat64, sizeof(RealExp)) -{ - //printf("RealExp::RealExp(%Lg)\n", value); - this->value = value; - this->type = type; -} - -char *RealExp::toChars() -{ - static char buffer[sizeof(value) * 3 + 8 + 1]; - -#ifdef IN_GCC - value.format(buffer, sizeof(buffer)); -#else - sprintf(buffer, "%Lg", value); -#endif - assert(strlen(buffer) < sizeof(buffer)); - return buffer; -} - -integer_t RealExp::toInteger() -{ -#ifdef IN_GCC - return value.toInt(); -#else - return (integer_t) value; -#endif -} - -real_t RealExp::toReal() -{ - return value; -} - -real_t RealExp::toImaginary() -{ - return 0; -} - -complex_t RealExp::toComplex() -{ - return complex_t(value); -} - -Expression *RealExp::semantic(Scope *sc) -{ - if (!type) - type = Type::tfloat64; - else - type = type->semantic(loc, sc); - return this; -} - -int RealExp::isBool(int result) -{ -#ifdef IN_GCC - return result ? (! value.isZero()) : (value.isZero()); -#else - return result ? (value != 0) - : (value == 0); -#endif -} - -void RealExp::toCBuffer(OutBuffer *buf) -{ -#ifdef IN_GCC - char buffer[3 + 3 * sizeof(value) + 1]; - value.format(buffer, sizeof(buffer)); - buf->writestring(buffer); -#else - buf->printf("%Lg", value); -#endif -} - - -/******************************** ImaginaryExp **************************/ - -ImaginaryExp::ImaginaryExp(Loc loc, real_t value, Type *type) - : Expression(loc, TOKimaginary80, sizeof(ImaginaryExp)) -{ - this->value = value; - this->type = type; -} - -char *ImaginaryExp::toChars() -{ - static char buffer[sizeof(value) * 3 + 8 + 1]; - -#ifdef IN_GCC - value.format(buffer, sizeof(buffer)); - strcat(buffer, "i"); -#else - sprintf(buffer, "%Lgi", value); -#endif - assert(strlen(buffer) < sizeof(buffer)); - return buffer; -} - -integer_t ImaginaryExp::toInteger() -{ - return 0; -} - -real_t ImaginaryExp::toReal() -{ - return 0; -} - -real_t ImaginaryExp::toImaginary() -{ - return value; -} - -complex_t ImaginaryExp::toComplex() -{ -#ifdef __DMC__ - return value * I; -#else - return complex_t(0, value); -#endif -} - -Expression *ImaginaryExp::semantic(Scope *sc) -{ - if (!type) - type = Type::timaginary80; - else - type = type->semantic(loc, sc); - return this; -} - -int ImaginaryExp::isBool(int result) -{ -#ifdef IN_GCC - return result ? (! value.isZero()) : (value.isZero()); -#else - return result ? (value != 0) - : (value == 0); -#endif -} - -void ImaginaryExp::toCBuffer(OutBuffer *buf) -{ -#ifdef IN_GCC - char buffer[3 + 3 * sizeof(value) + 1]; - value.format(buffer, sizeof(buffer)); - strcat(buffer, "i"); // %% buffer - buf->writestring(buffer); -#else - buf->printf("%Lg", value); -#endif -} - - -/******************************** ComplexExp **************************/ - -ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type) - : Expression(loc, TOKcomplex80, sizeof(ComplexExp)) -{ - this->value = value; - this->type = type; - //printf("ComplexExp::ComplexExp(%s)\n", toChars()); -} - -char *ComplexExp::toChars() -{ - static char buffer[sizeof(value) * 3 + 8 + 1]; - -#ifdef IN_GCC - char buf1[sizeof(value) * 3 + 8 + 1]; - char buf2[sizeof(value) * 3 + 8 + 1]; - creall(value).format(buf1, sizeof(buf1)); - cimagl(value).format(buf2, sizeof(buf2)); - sprintf(buffer, "(%s+%si)", buf1, buf2); -#else - sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value)); - assert(strlen(buffer) < sizeof(buffer)); -#endif - return buffer; -} - -integer_t ComplexExp::toInteger() -{ - return (integer_t) value; -} - -real_t ComplexExp::toReal() -{ - return (real_t) value; -} - -real_t ComplexExp::toImaginary() -{ - return cimagl(value); -} - -complex_t ComplexExp::toComplex() -{ - return value; -} - -Expression *ComplexExp::semantic(Scope *sc) -{ - if (!type) - type = Type::tcomplex80; - else - type = type->semantic(loc, sc); - return this; -} - -int ComplexExp::isBool(int result) -{ - return result ? (value != 0) - : (value == 0); -} - -void ComplexExp::toCBuffer(OutBuffer *buf) -{ -#ifdef IN_GCC - char buf1[sizeof(value) * 3 + 8 + 1]; - char buf2[sizeof(value) * 3 + 8 + 1]; - creall(value).format(buf1, sizeof(buf1)); - cimagl(value).format(buf2, sizeof(buf2)); - buf->printf("(%s+%si)", buf1, buf2); -#else - buf->printf("(%Lg+%Lgi)", creall(value), cimagl(value)); -#endif -} - - -/******************************** IdentifierExp **************************/ - -IdentifierExp::IdentifierExp(Loc loc, Identifier *ident) - : Expression(loc, TOKidentifier, sizeof(IdentifierExp)) -{ - this->ident = ident; -} - -Expression *IdentifierExp::semantic(Scope *sc) -{ - Dsymbol *s; - Dsymbol *scopesym; - -#if LOGSEMANTIC - printf("IdentifierExp::semantic('%s')\n", ident->toChars()); -#endif - s = sc->search(ident, &scopesym); - if (s) - { Expression *e; - WithScopeSymbol *withsym; - - // See if it was a with class - withsym = scopesym->isWithScopeSymbol(); - if (withsym) - { - // Same as wthis.ident - e = new VarExp(loc, withsym->withstate->wthis); - e = new DotIdExp(loc, e, ident); - } - else - { - if (!s->parent && scopesym->isArrayScopeSymbol()) - { // Kludge to run semantic() here because - // ArrayScopeSymbol::search() doesn't have access to sc. - s->semantic(sc); - } - e = new DsymbolExp(loc, s); - } - return e->semantic(sc); - } - error("undefined identifier %s", ident->toChars()); - type = Type::terror; - return this; -} - -char *IdentifierExp::toChars() -{ - return ident->toChars(); -} - -void IdentifierExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring(ident->toChars()); -} - -Expression *IdentifierExp::toLvalue(Expression *e) -{ -#if 0 - tym = tybasic(e1->ET->Tty); - if (!(tyscalar(tym) || - tym == TYstruct || - tym == TYarray && e->Eoper == TOKaddr)) - synerr(EM_lvalue); // lvalue expected -#endif - return this; -} - -/******************************** DollarExp **************************/ - -DollarExp::DollarExp(Loc loc) - : IdentifierExp(loc, Id::dollar) -{ -} - -/******************************** DsymbolExp **************************/ - -DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s) - : Expression(loc, TOKdsymbol, sizeof(DsymbolExp)) -{ - this->s = s; -} - -Expression *DsymbolExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("DsymbolExp::semantic('%s')\n", s->toChars()); -#endif - -Lagain: - EnumMember *em; - Expression *e; - VarDeclaration *v; - FuncDeclaration *f; - FuncLiteralDeclaration *fld; - Declaration *d; - ClassDeclaration *cd; - ClassDeclaration *thiscd = NULL; - Import *imp; - Package *pkg; - Type *t; - - //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); - //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); - if (type) - return this; - if (!s->isFuncDeclaration()) // functions are checked after overloading - checkDeprecated(sc, s); - s = s->toAlias(); - //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); - if (!s->isFuncDeclaration()) - checkDeprecated(sc, s); - - if (sc->func) - thiscd = sc->func->parent->isClassDeclaration(); - - // BUG: This should happen after overload resolution for functions, not before - if (s->needThis() && hasThis(sc) /*&& !s->isFuncDeclaration()*/) - { - // Supply an implicit 'this', as in - // this.ident - - DotVarExp *de; - - de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration()); - return de->semantic(sc); - } - - em = s->isEnumMember(); - if (em) - { - e = em->value; - e = e->semantic(sc); - return e; - } - v = s->isVarDeclaration(); - if (v) - { - //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); - if (!type) - type = v->type; - if (v->isConst() && type->toBasetype()->ty != Tsarray) - { - if (v->init) - { - if (v->inuse) - { - error("circular reference to '%s'", v->toChars()); - type = Type::tint32; - return this; - } - ExpInitializer *ei = v->init->isExpInitializer(); - if (ei) - { - e = ei->exp->copy(); // make copy so we can change loc - if (e->op == TOKstring || !e->type) - e = e->semantic(sc); - e = e->implicitCastTo(type); - e->loc = loc; - return e; - } - } - else - { - e = type->defaultInit(); - e->loc = loc; - return e; - } - } - e = new VarExp(loc, v); - e->type = type; - e = e->semantic(sc); - return e->deref(); - } - fld = s->isFuncLiteralDeclaration(); - if (fld) - { //printf("'%s' is a function literal\n", fld->toChars()); - e = new FuncExp(loc, fld); - return e->semantic(sc); - } - f = s->isFuncDeclaration(); - if (f) - { //printf("'%s' is a function\n", f->toChars()); - return new VarExp(loc, f); - } - cd = s->isClassDeclaration(); - if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis()) - { - // We need to add an implicit 'this' if cd is this class or a base class. - DotTypeExp *dte; - - dte = new DotTypeExp(loc, new ThisExp(loc), s); - return dte->semantic(sc); - } - imp = s->isImport(); - if (imp) - { - ScopeExp *ie; - - ie = new ScopeExp(loc, imp->pkg); - return ie->semantic(sc); - } - pkg = s->isPackage(); - if (pkg) - { - ScopeExp *ie; - - ie = new ScopeExp(loc, pkg); - return ie->semantic(sc); - } - Module *mod = s->isModule(); - if (mod) - { - ScopeExp *ie; - - ie = new ScopeExp(loc, mod); - return ie->semantic(sc); - } - - t = s->getType(); - if (t) - { - return new TypeExp(loc, t); - } - - TemplateInstance *ti = s->isTemplateInstance(); - if (ti) - { ti->semantic(sc); - s = ti->inst->toAlias(); - if (!s->isTemplateInstance()) - goto Lagain; - e = new ScopeExp(loc, ti); - e = e->semantic(sc); - return e; - } - - error("%s '%s' is not a variable", s->kind(), s->toChars()); - type = Type::terror; - return this; -} - -char *DsymbolExp::toChars() -{ - return s->toChars(); -} - -void DsymbolExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring(s->toChars()); -} - -Expression *DsymbolExp::toLvalue(Expression *e) -{ -#if 0 - tym = tybasic(e1->ET->Tty); - if (!(tyscalar(tym) || - tym == TYstruct || - tym == TYarray && e->Eoper == TOKaddr)) - synerr(EM_lvalue); // lvalue expected -#endif - return this; -} - -/******************************** ThisExp **************************/ - -ThisExp::ThisExp(Loc loc) - : Expression(loc, TOKthis, sizeof(ThisExp)) -{ - var = NULL; -} - -Expression *ThisExp::semantic(Scope *sc) -{ FuncDeclaration *fd; - FuncDeclaration *fdthis; - int nested = 0; - -#if LOGSEMANTIC - printf("ThisExp::semantic()\n"); -#endif - if (type) - { assert(global.errors || var); - return this; - } - - fdthis = sc->parent->isFuncDeclaration(); - fd = hasThis(sc); - if (!fd) - goto Lerr; - - assert(fd->vthis); - var = fd->vthis; - assert(var->parent); - type = var->type; - if (fd != fdthis) // if nested - { - fdthis->getLevel(loc, fd); - fd->vthis->nestedref = 1; - fd->nestedFrameRef = 1; - } - sc->callSuper |= CSXthis; - return this; - -Lerr: - error("'this' is only allowed in non-static member functions"); - type = Type::tint32; - return this; -} - -int ThisExp::isBool(int result) -{ - return result ? TRUE : FALSE; -} - -void ThisExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring("this"); -} - -Expression *ThisExp::toLvalue(Expression *e) -{ - return this; -} - -/******************************** SuperExp **************************/ - -SuperExp::SuperExp(Loc loc) - : ThisExp(loc) -{ - op = TOKsuper; -} - -Expression *SuperExp::semantic(Scope *sc) -{ FuncDeclaration *fd; - FuncDeclaration *fdthis; - ClassDeclaration *cd; - Dsymbol *s; - -#if LOGSEMANTIC - printf("SuperExp::semantic('%s')\n", toChars()); -#endif - if (type) - return this; - - fdthis = sc->parent->isFuncDeclaration(); - fd = hasThis(sc); - if (!fd) - goto Lerr; - assert(fd->vthis); - var = fd->vthis; - assert(var->parent); - - s = fd->toParent(); - while (s && s->isTemplateInstance()) - s = s->toParent(); - assert(s); - cd = s->isClassDeclaration(); -//printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars()); - if (!cd) - goto Lerr; - if (!cd->baseClass) - { - error("no base class for %s", cd->toChars()); - type = fd->vthis->type; - } - else - { - type = cd->baseClass->type; - } - - if (fd != fdthis) - { - fdthis->getLevel(loc, fd); - fd->vthis->nestedref = 1; - fd->nestedFrameRef = 1; - } - - sc->callSuper |= CSXsuper; - return this; - - -Lerr: - error("'super' is only allowed in non-static class member functions"); - type = Type::tint32; - return this; -} - -void SuperExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring("super"); -} - - -/******************************** NullExp **************************/ - -NullExp::NullExp(Loc loc) - : Expression(loc, TOKnull, sizeof(NullExp)) -{ -} - -Expression *NullExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("NullExp::semantic('%s')\n", toChars()); -#endif - // NULL is the same as (void *)0 - if (!type) - type = Type::tvoid->pointerTo(); - return this; -} - -int NullExp::isBool(int result) -{ - return result ? FALSE : TRUE; -} - -void NullExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring("null"); -} - -/******************************** StringExp **************************/ - -StringExp::StringExp(Loc loc, void *string, unsigned len) - : Expression(loc, TOKstring, sizeof(StringExp)) -{ - this->string = string; - this->len = len; - this->sz = 1; - this->committed = 0; -} - -int StringExp::equals(Object *o) -{ - //printf("StringExp::equals('%s')\n", o->toChars()); - if (o && o->dyncast() == DYNCAST_EXPRESSION) - { Expression *e = (Expression *)o; - - if (e->op == TOKstring) - { - return compare(o) == 0; - } - } - return FALSE; -} - -char *StringExp::toChars() -{ - OutBuffer buf; - char *p; - - toCBuffer(&buf); - p = (char *)buf.data; - buf.data = NULL; - return p; -} - -Expression *StringExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("StringExp::semantic()\n"); -#endif - if (!type) - { - type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex)); - type = type->semantic(loc, sc); - } - return this; -} - -int StringExp::compare(Object *obj) -{ - // Used to sort case statement expressions so we can do an efficient lookup - StringExp *se2 = (StringExp *)(obj); - - // This is a kludge so isExpression() in template.c will return 5 - // for StringExp's. - if (!se2) - return 5; - - assert(se2->op == TOKstring); - - int len1 = len; - int len2 = se2->len; - - if (len1 == len2) - { - switch (sz) - { - case 1: - return strcmp((char *)string, (char *)se2->string); - - case 2: - { unsigned u; - d_wchar *s1 = (d_wchar *)string; - d_wchar *s2 = (d_wchar *)se2->string; - - for (u = 0; u < len; u++) - { - if (s1[u] != s2[u]) - return s1[u] - s2[u]; - } - } - - case 4: - { unsigned u; - d_dchar *s1 = (d_dchar *)string; - d_dchar *s2 = (d_dchar *)se2->string; - - for (u = 0; u < len; u++) - { - if (s1[u] != s2[u]) - return s1[u] - s2[u]; - } - } - break; - - default: - assert(0); - } - } - return len1 - len2; -} - -int StringExp::isBool(int result) -{ - return result ? TRUE : FALSE; -} - -void StringExp::toCBuffer(OutBuffer *buf) -{ unsigned i; - - buf->writeByte('"'); - for (i = 0; i < len;) - { unsigned c; - char *p; - - switch (sz) - { - case 1: - p = utf_decodeChar((unsigned char *)string, len, &i, &c); - break; - case 2: - p = utf_decodeWchar((unsigned short *)string, len, &i, &c); - break; - case 4: - p = NULL; - c = ((unsigned *)string)[i]; - i++; - break; - default: - assert(0); - } - switch (c) - { - case 0: - break; - - case '"': - buf->writeByte('\\'); - default: - if (isprint(c)) - buf->writeByte(c); - else if (c <= 0x7F) - buf->printf("\\x%02x", c); - else if (c <= 0xFFFF) - buf->printf("\\u%04x", c); - else - buf->printf("\\U%08x", c); - continue; - } - break; - } - buf->writeByte('"'); -} - -/************************ TypeDotIdExp ************************************/ - -/* Things like: - * int.size - * foo.size - * (foo).size - * cast(foo).size - */ - -TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident) - : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp)) -{ - this->type = type; - this->ident = ident; -} - -Expression *TypeDotIdExp::syntaxCopy() -{ - TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident); - return te; -} - -Expression *TypeDotIdExp::semantic(Scope *sc) -{ Expression *e; - -#if LOGSEMANTIC - printf("TypeDotIdExp::semantic()\n"); -#endif -#if 0 - type = type->semantic(loc, sc); - e = type->getProperty(loc, ident); -#else - e = new DotIdExp(loc, new TypeExp(loc, type), ident); -#endif - e = e->semantic(sc); - return e; -} - -void TypeDotIdExp::toCBuffer(OutBuffer *buf) -{ - buf->writeByte('('); - type->toCBuffer(buf, NULL); - buf->writeByte(')'); - buf->writeByte('.'); - buf->writestring(ident->toChars()); -} - -/************************************************************/ - -// Mainly just a placeholder - -TypeExp::TypeExp(Loc loc, Type *type) - : Expression(loc, TOKtype, sizeof(TypeExp)) -{ - //printf("TypeExp(): %s\n", type->toChars()); - this->type = type; -} - -void TypeExp::toCBuffer(OutBuffer *buf) -{ - type->toCBuffer(buf, NULL); -} - -/************************************************************/ - -// Mainly just a placeholder - -ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg) - : Expression(loc, TOKimport, sizeof(ScopeExp)) -{ - this->sds = pkg; -} - -Expression *ScopeExp::syntaxCopy() -{ - ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL)); - return se; -} - -Expression *ScopeExp::semantic(Scope *sc) -{ - TemplateInstance *ti; - ScopeDsymbol *sds2; - -#if LOGSEMANTIC - printf("+ScopeExp::semantic('%s')\n", toChars()); -#endif -Lagain: - ti = sds->isTemplateInstance(); - if (ti) -#if 0 - { ti->semantic(sc); - sds = ti->inst; - } -#else - { Dsymbol *s; - ti->semantic(sc); - s = ti->inst->toAlias(); - sds2 = s->isScopeDsymbol(); - if (!sds2) - { - //printf("s = %s, '%s'\n", s->kind(), s->toChars()); - Expression *e = new DsymbolExp(loc, s); - e = e->semantic(sc); - //printf("-1ScopeExp::semantic()\n"); - return e; - } - if (sds2 != sds) - { - sds = sds2; - goto Lagain; - } - //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); - } - else - { - //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); - sds->semantic(sc); - } -#endif - type = Type::tvoid; - //printf("-2ScopeExp::semantic()\n"); - return this; -} - -void ScopeExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring(sds->kind()); - buf->writestring(" "); - buf->writestring(sds->toChars()); -} - -/********************** NewExp **************************************/ - -NewExp::NewExp(Loc loc, Array *newargs, Type *type, Array *arguments) - : Expression(loc, TOKnew, sizeof(NewExp)) -{ - this->newargs = newargs; - this->type = type; - this->arguments = arguments; - member = NULL; - allocator = NULL; -} - -Expression *NewExp::syntaxCopy() -{ - return new NewExp(loc, arraySyntaxCopy(newargs), - type->syntaxCopy(), arraySyntaxCopy(arguments)); -} - - -Expression *NewExp::semantic(Scope *sc) -{ int i; - Type *tb; - -#if LOGSEMANTIC - printf("NewExp::semantic() %s\n", toChars()); - //printf("type: %s\n", type->toChars()); -#endif - type = type->semantic(loc, sc); - tb = type->toBasetype(); - //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco); - - arrayExpressionSemantic(newargs, sc); - preFunctionArguments(loc, sc, newargs); - arrayExpressionSemantic(arguments, sc); - preFunctionArguments(loc, sc, arguments); - - if (tb->ty == Tclass) - { ClassDeclaration *cd; - TypeClass *tc; - FuncDeclaration *f; - TypeFunction *tf; - - tc = (TypeClass *)(tb); - cd = tc->sym->isClassDeclaration(); - if (cd->isInterfaceDeclaration()) - error("cannot create instance of interface %s", cd->toChars()); - if (cd->isAbstract()) - error("cannot create instance of abstract class %s", cd->toChars()); - checkDeprecated(sc, cd); - f = cd->ctor; - if (f) - { - assert(f); - f = f->overloadResolve(loc, arguments); - checkDeprecated(sc, f); - member = f->isCtorDeclaration(); - assert(member); - - cd->accessCheck(loc, sc, member); - - tf = (TypeFunction *)f->type; - type = tf->next; - - if (!arguments) - arguments = new Array(); - functionArguments(loc, sc, tf, arguments); - } - else - { - if (arguments && arguments->dim) - error("no constructor for %s", cd->toChars()); - } - - if (cd->aggNew) - { Expression *e; - - f = cd->aggNew; - - // Prepend the uint size argument to newargs[] - e = new IntegerExp(loc, cd->size(loc), Type::tuns32); - if (!newargs) - newargs = new Array(); - newargs->shift(e); - - f = f->overloadResolve(loc, newargs); - allocator = f->isNewDeclaration(); - assert(allocator); - - tf = (TypeFunction *)f->type; - functionArguments(loc, sc, tf, newargs); - } - else - { - if (newargs && newargs->dim) - error("no allocator for %s", cd->toChars()); - } - - } -#if 1 - else if (tb->ty == Tstruct) - { - TypeStruct *ts = (TypeStruct *)tb; - StructDeclaration *sd = ts->sym; - FuncDeclaration *f = sd->aggNew; - TypeFunction *tf; - - if (f) - { - Expression *e; - - // Prepend the uint size argument to newargs[] - e = new IntegerExp(loc, sd->size(loc), Type::tuns32); - if (!newargs) - newargs = new Array(); - newargs->shift(e); - - f = f->overloadResolve(loc, newargs); - allocator = f->isNewDeclaration(); - assert(allocator); - - tf = (TypeFunction *)f->type; - functionArguments(loc, sc, tf, newargs); - - e = new VarExp(loc, f); - e = new CallExp(loc, e, newargs); - e = e->semantic(sc); - e->type = type->pointerTo(); - return e; - } - - type = type->pointerTo(); - } -#endif - else if (tb->ty == Tarray && (arguments && arguments->dim)) - { Expression *arg; - - arg = (Expression *)arguments->data[0]; - arg = resolveProperties(sc, arg); - arg = arg->implicitCastTo(Type::tindex); - if (arg->op == TOKint64 && (long long)arg->toInteger() < 0) - error("negative array index %s", arg->toChars()); - arguments->data[0] = (void *) arg; - } - else if (tb->isscalar()) - { - type = type->pointerTo(); - } - else - { - error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars()); - type = type->pointerTo(); - } - -//printf("NewExp: '%s'\n", toChars()); -//printf("NewExp:type '%s'\n", type->toChars()); - - return this; -} - -void NewExp::toCBuffer(OutBuffer *buf) -{ int i; - - buf->writestring("new "); - if (newargs && newargs->dim) - { - buf->writeByte('('); - argsToCBuffer(buf, newargs); - buf->writeByte(')'); - } - type->toCBuffer(buf, NULL); - if (arguments && arguments->dim) - { - buf->writeByte('('); - argsToCBuffer(buf, arguments); - buf->writeByte(')'); - } -} - -/********************** SymOffExp **************************************/ - -SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset) - : Expression(loc, TOKsymoff, sizeof(SymOffExp)) -{ - assert(var); - this->var = var; - this->offset = offset; -} - -Expression *SymOffExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("SymOffExp::semantic('%s')\n", toChars()); -#endif - //var->semantic(sc); - type = var->type->pointerTo(); - return this; -} - -int SymOffExp::isBool(int result) -{ - return result ? TRUE : FALSE; -} - -void SymOffExp::toCBuffer(OutBuffer *buf) -{ - if (offset) - buf->printf("(&%s+%u)", var->toChars(), offset); - else - buf->printf("&%s", var->toChars()); -} - -/******************************** VarExp **************************/ - -VarExp::VarExp(Loc loc, Declaration *var) - : Expression(loc, TOKvar, sizeof(VarExp)) -{ - //printf("VarExp(this = %p, '%s')\n", this, var->toChars()); - this->var = var; - this->type = var->type; -} - -int VarExp::equals(Object *o) -{ VarExp *ne; - - if (this == o || - (((Expression *)o)->op == TOKvar && - ((ne = (VarExp *)o), type->equals(ne->type)) && - var == ne->var)) - return 1; - return 0; -} - -Expression *VarExp::semantic(Scope *sc) -{ FuncLiteralDeclaration *fd; - -#if LOGSEMANTIC - printf("VarExp::semantic(%s)\n", toChars()); -#endif - if (!type) - type = var->type; - - VarDeclaration *v = var->isVarDeclaration(); - if (v) - { - if (v->isConst() && type->toBasetype()->ty != Tsarray && v->init) - { - ExpInitializer *ei = v->init->isExpInitializer(); - if (ei) - { - //ei->exp->implicitCastTo(type)->print(); - return ei->exp->implicitCastTo(type); - } - } - if (!v->isDataseg() && v->parent != sc->parent) - { - FuncDeclaration *fdv = v->parent->isFuncDeclaration(); - FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); - - if (fdv && fdthis) - { int level; - - level = fdthis->getLevel(loc, fdv); - v->nestedref = 1; - fdv->nestedFrameRef = 1; - } - } - } -#if 0 - else if ((fd = var->isFuncLiteralDeclaration()) != NULL) - { Expression *e; - e = new FuncExp(loc, fd); - e->type = type; - return e; - } -#endif - return this; -} - -char *VarExp::toChars() -{ - return var->toChars(); -} - -void VarExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring(var->toChars()); -} - -Expression *VarExp::toLvalue(Expression *e) -{ -#if 0 - tym = tybasic(e1->ET->Tty); - if (!(tyscalar(tym) || - tym == TYstruct || - tym == TYarray && e->Eoper == TOKaddr)) - synerr(EM_lvalue); // lvalue expected -#endif - return this; -} - -Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) -{ - //printf("VarExp::modifiableLvalue('%s')\n", var->toChars()); - if (sc->incontract && var->isParameter()) - error("cannot modify parameter '%s' in contract", var->toChars()); - - if (type && type->toBasetype()->ty == Tsarray) - error("cannot change reference to static array '%s'", var->toChars()); - - if (var->isConst()) - error("cannot modify const variable '%s'", var->toChars()); - - // See if this expression is a modifiable lvalue (i.e. not const) - return toLvalue(e); -} - - -/******************************** FuncExp *********************************/ - -FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd) - : Expression(loc, TOKfunction, sizeof(FuncExp)) -{ - this->fd = fd; -} - -Expression *FuncExp::syntaxCopy() -{ - return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL)); -} - -Expression *FuncExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("FuncExp::semantic(%s)\n", toChars()); -#endif - if (!type) - { - fd->semantic(sc); - fd->parent = sc->parent; - if (!global.errors) - { - fd->semantic2(sc); - if (!global.errors) - { - fd->semantic3(sc); - - if (!global.errors && global.params.useInline) - fd->inlineScan(); - } - } - - // Type is a "delegate to" or "pointer to" the function literal - if (fd->isNested()) - { - type = new TypeDelegate(fd->type); - type = type->semantic(loc, sc); - } - else - { - type = fd->type->pointerTo(); - } - } - return this; -} - -char *FuncExp::toChars() -{ - return fd->toChars(); -} - -void FuncExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring(fd->toChars()); -} - - -/******************************** DeclarationExp **************************/ - -DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration) - : Expression(loc, TOKdeclaration, sizeof(DeclarationExp)) -{ - this->declaration = declaration; -} - -Expression *DeclarationExp::syntaxCopy() -{ - return new DeclarationExp(loc, declaration->syntaxCopy(NULL)); -} - -Expression *DeclarationExp::semantic(Scope *sc) -{ - if (type) - return this; - -#if LOGSEMANTIC - printf("DeclarationExp::semantic() %s\n", toChars()); -#endif - - if (declaration->isVarDeclaration()) - { // Do semantic() on initializer first, so: - // int a = a; - // will be illegal. - declaration->semantic(sc); - declaration->parent = sc->parent; - } - - //printf("inserting '%s' %p into sc = %p\n", declaration->toChars(), declaration, sc); - // Insert into both local scope and function scope. - // Must be unique in both. - if (declaration->ident) - { - if (!sc->insert(declaration) || - (declaration->isFuncDeclaration() && !sc->func->localsymtab->insert(declaration))) - //error("declaration %s.%s is already defined", sc->func->toChars(), declaration->toChars()); - error("declaration %s is already defined", declaration->toPrettyChars()); - } - if (!declaration->isVarDeclaration()) - { declaration->semantic(sc); - declaration->parent = sc->parent; - } - if (!global.errors) - { - declaration->semantic2(sc); - if (!global.errors) - { - declaration->semantic3(sc); - - if (!global.errors && global.params.useInline) - declaration->inlineScan(); - } - } - - type = Type::tvoid; - return this; -} - -void DeclarationExp::toCBuffer(OutBuffer *buf) -{ - declaration->toCBuffer(buf); -} - - -/************************ TypeidExp ************************************/ - -/* - * typeid(int) - */ - -TypeidExp::TypeidExp(Loc loc, Type *typeidType) - : Expression(loc, TOKtypeid, sizeof(TypeidExp)) -{ - this->typeidType = typeidType; -} - - -Expression *TypeidExp::syntaxCopy() -{ - return new TypeidExp(loc, typeidType->syntaxCopy()); -} - - -Expression *TypeidExp::semantic(Scope *sc) -{ Expression *e; - -#if LOGSEMANTIC - printf("TypeidExp::semantic()\n"); -#endif - typeidType = typeidType->semantic(loc, sc); - e = typeidType->getTypeInfo(sc); - return e; -} - -void TypeidExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring("typeid("); - typeidType->toCBuffer(buf, NULL); - buf->writeByte(')'); -} - -/************************************************************/ - -HaltExp::HaltExp(Loc loc) - : Expression(loc, TOKhalt, sizeof(HaltExp)) -{ -} - -Expression *HaltExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("HaltExp::semantic()\n"); -#endif - type = Type::tvoid; - return this; -} - -void HaltExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring("halt"); -} - -/************************************************************/ - -UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1) - : Expression(loc, op, size) -{ - this->e1 = e1; -} - -Expression *UnaExp::syntaxCopy() -{ UnaExp *e; - - e = (UnaExp *)copy(); - e->e1 = e->e1->syntaxCopy(); - return e; -} - -Expression *UnaExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("UnaExp::semantic('%s')\n", toChars()); -#endif - e1 = e1->semantic(sc); -// if (!e1->type) -// error("%s has no value", e1->toChars()); - return this; -} - -void UnaExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring(Token::toChars(op)); - e1->toCBuffer(buf); -} - -/************************************************************/ - -BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2) - : Expression(loc, op, size) -{ - this->e1 = e1; - this->e2 = e2; -} - -Expression *BinExp::syntaxCopy() -{ BinExp *e; - - e = (BinExp *)copy(); - e->e1 = e->e1->syntaxCopy(); - e->e2 = e->e2->syntaxCopy(); - return e; -} - -Expression *BinExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("BinExp::semantic('%s')\n", toChars()); -#endif - e1 = e1->semantic(sc); - if (!e1->type) - { - error("%s has no value", e1->toChars()); - e1->type = Type::terror; - } - e2 = e2->semantic(sc); - if (!e2->type) - { - error("%s has no value", e2->toChars()); - e2->type = Type::terror; - } - assert(e1->type); - return this; -} - -Expression *BinExp::semanticp(Scope *sc) -{ - BinExp::semantic(sc); - e1 = resolveProperties(sc, e1); - e2 = resolveProperties(sc, e2); - return this; -} - -/*************************** - * Common semantic routine for some xxxAssignExp's. - */ - -Expression *BinExp::commonSemanticAssign(Scope *sc) -{ Expression *e; - - if (!type) - { - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - type = e1->type; - typeCombine(); - e1->checkArithmetic(); - e2->checkArithmetic(); - } - return this; -} - -Expression *BinExp::commonSemanticAssignIntegral(Scope *sc) -{ Expression *e; - - if (!type) - { - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - type = e1->type; - typeCombine(); - e1->checkIntegral(); - e2->checkIntegral(); - } - return this; -} - - -void BinExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writeByte(' '); - buf->writestring(Token::toChars(op)); - buf->writeByte(' '); - e2->toCBuffer(buf); -} - -int BinExp::isunsigned() -{ - return e1->type->isunsigned() || e2->type->isunsigned(); -} - -/************************************************************/ - -AssertExp::AssertExp(Loc loc, Expression *e) - : UnaExp(loc, TOKassert, sizeof(AssertExp), e) -{ -} - -Expression *AssertExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("AssertExp::semantic('%s')\n", toChars()); -#endif - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - // BUG: see if we can do compile time elimination of the Assert - e1 = e1->checkToBoolean(); - if (!global.params.useAssert && e1->isBool(FALSE)) - { Expression *e = new HaltExp(loc); - e = e->semantic(sc); - return e; - } - type = Type::tvoid; - return this; -} - -void AssertExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring("assert("); - e1->toCBuffer(buf); - buf->writeByte(')'); -} - -/************************************************************/ - -DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) - : UnaExp(loc, TOKdot, sizeof(DotIdExp), e) -{ - this->ident = ident; -} - -Expression *DotIdExp::semantic(Scope *sc) -{ Expression *e; - Expression *eleft; - Expression *eright; - -#if LOGSEMANTIC - printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars()); - //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); -#endif - -//{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } - - /* Special case: rewrite this.id and super.id - * to be classtype.id and baseclasstype.id - * if we have no this pointer. - */ - if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc)) - { ClassDeclaration *cd; - StructDeclaration *sd; - AggregateDeclaration *ad; - - ad = sc->getStructClassScope(); - if (ad) - { - cd = ad->isClassDeclaration(); - if (cd) - { - if (e1->op == TOKthis) - { - e = new TypeDotIdExp(loc, cd->type, ident); - return e->semantic(sc); - } - else if (cd->baseClass && e1->op == TOKsuper) - { - e = new TypeDotIdExp(loc, cd->baseClass->type, ident); - return e->semantic(sc); - } - } - else - { - sd = ad->isStructDeclaration(); - if (sd) - { - if (e1->op == TOKthis) - { - e = new TypeDotIdExp(loc, sd->type, ident); - return e->semantic(sc); - } - } - } - } - } - - UnaExp::semantic(sc); - - e1 = resolveProperties(sc, e1); - - if (e1->op == TOKdotexp) - { - DotExp *de = (DotExp *)e1; - eleft = de->e1; - eright = de->e2; - } - else - { - eleft = NULL; - eright = e1; - } - if (eright->op == TOKimport) // also used for template alias's - { - Dsymbol *s; - ScopeExp *ie = (ScopeExp *)eright; - - s = ie->sds->search(ident, 0); - if (s) - { - s = s->toAlias(); - checkDeprecated(sc, s); - - EnumMember *em = s->isEnumMember(); - if (em) - { - e = em->value; - e = e->semantic(sc); - return e; - } - - VarDeclaration *v = s->isVarDeclaration(); - if (v) - { - //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); - type = v->type; - if (v->isConst()) - { - if (v->init) - { - ExpInitializer *ei = v->init->isExpInitializer(); - if (ei) - { - //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars()); - //ei->exp = ei->exp->semantic(sc); - if (ei->exp->type == type) - { - e = ei->exp->copy(); // make copy so we can change loc - e->loc = loc; - return e; - } - } - } - else if (type->isscalar()) - { - e = type->defaultInit(); - e->loc = loc; - return e; - } - } - if (v->needThis()) - { - if (!eleft) - eleft = new ThisExp(loc); - e = new DotVarExp(loc, eleft, v); - e = e->semantic(sc); - } - else - { - e = new VarExp(loc, v); - if (eleft) - { e = new CommaExp(loc, eleft, e); - e->type = v->type; - } - } - return e->deref(); - } - - FuncDeclaration *f = s->isFuncDeclaration(); - if (f) - { - //printf("it's a function\n"); - if (f->needThis()) - { - if (!eleft) - eleft = new ThisExp(loc); - e = new DotVarExp(loc, eleft, f); - e = e->semantic(sc); - } - else - { - e = new VarExp(loc, f); - if (eleft) - { e = new CommaExp(loc, eleft, e); - e->type = f->type; - } - } - return e; - } - - ScopeDsymbol *sds = s->isScopeDsymbol(); - if (sds) - { - //printf("it's a ScopeDsymbol\n"); - e = new ScopeExp(loc, sds); - e = e->semantic(sc); - if (eleft) - e = new DotExp(loc, eleft, e); - return e; - } - - Import *imp = s->isImport(); - if (imp) - { - ScopeExp *ie; - - ie = new ScopeExp(loc, imp->pkg); - return ie->semantic(sc); - } - - Type *t = s->getType(); - if (t) - { - return new TypeExp(loc, t); - } - - // BUG: handle other cases like in IdentifierExp::semantic() -#ifdef DEBUG - printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind()); -#endif - assert(0); - } - error("undefined identifier %s", toChars()); - type = Type::tvoid; - return this; - } - else if (e1->type->ty == Tpointer && ident != Id::size && - ident != Id::init && ident != Id::__sizeof && - ident != Id::alignof && ident != Id::offsetof) - { - e = new PtrExp(loc, e1); - e->type = e1->type->next; - return e->type->dotExp(sc, e, ident); - } - else - { - e = e1->type->dotExp(sc, e1, ident); - e = e->semantic(sc); - return e; - } -} - -void DotIdExp::toCBuffer(OutBuffer *buf) -{ - //printf("DotIdExp::toCbuffer()\n"); - e1->toCBuffer(buf); - buf->writeByte('.'); - buf->writestring(ident->toChars()); -} - -/************************************************************/ - -DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v) - : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e) -{ - //printf("DotVarExp()\n"); - this->var = v; -} - -Expression *DotVarExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("DotVarExp::semantic('%s')\n", toChars()); -#endif - if (!type) - { - e1 = e1->semantic(sc); - var = var->toAlias()->isDeclaration(); - type = var->type; - assert(type); - - if (!var->isFuncDeclaration()) // do checks after overload resolution - { - AggregateDeclaration *ad = var->parent->isAggregateDeclaration(); - Type *t = e1->type; - - if (ad && !(t->ty == Tpointer && t->next->ty == Tstruct && - ((TypeStruct *)t->next)->sym == ad)) - { - ClassDeclaration *cd = ad->isClassDeclaration(); - - if (!cd || - t->ty != Tclass || - !(((TypeClass *)t)->sym == cd || cd->isBaseOf(((TypeClass *)t)->sym, NULL)) - ) - error("this for %s needs to be type %s not type %s", - var->toChars(), ad->toChars(), t->toChars()); - } - accessCheck(loc, sc, e1, var); - } - } - return this; -} - -Expression *DotVarExp::toLvalue(Expression *e) -{ - return this; -} - -void DotVarExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writeByte('.'); - buf->writestring(var->toChars()); -} - -/************************************************************/ - -/* Things like: - * foo.bar!(args) - */ - -DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti) - : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e) -{ - //printf("DotTemplateInstanceExp()\n"); - this->ti = ti; -} - -Expression *DotTemplateInstanceExp::syntaxCopy() -{ - DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc, - e1->syntaxCopy(), - (TemplateInstance *)ti->syntaxCopy(NULL)); - return de; -} - -Expression *DotTemplateInstanceExp::semantic(Scope *sc) -{ Dsymbol *s; - Dsymbol *s2; - TemplateDeclaration *td; - Expression *e; - Identifier *id; - Type *t1; - Expression *eleft = NULL; - -#if LOGSEMANTIC - printf("DotTemplateInstanceExp::semantic('%s')\n", toChars()); -#endif - //e1->print(); - //print(); - e1 = e1->semantic(sc); - t1 = e1->type; - if (t1) - t1 = t1->toBasetype(); - //t1->print(); - if (e1->op == TOKimport) - { - s = ((ScopeExp *)e1)->sds; - } - else if (e1->op == TOKtype) - { - s = t1->isClassHandle(); - if (!s) - goto L1; - } - else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass)) - { - s = t1->toDsymbol(sc); - eleft = e1; - } - else if (t1 && t1->ty == Tpointer) - { - t1 = t1->next->toBasetype(); - if (t1->ty != Tstruct) - goto L1; - s = t1->toDsymbol(sc); - eleft = e1; - } - else - { - L1: - error("template %s is not a member of %s", ti->toChars(), e1->toChars()); - goto Lerr; - } - - assert(s); - id = (Identifier *)ti->idents.data[0]; - s2 = s->search(id, 0); - if (!s2) - { error("template identifier %s is not a member of %s", id->toChars(), s->ident->toChars()); - goto Lerr; - } - s = s2; - s->semantic(sc); - s = s->toAlias(); - td = s->isTemplateDeclaration(); - if (!td) - { - error("%s is not a template", id->toChars()); - goto Lerr; - } - ti->tempdecl = td; - - if (eleft) - { Declaration *v; - - ti->semantic(sc); - s = ti->inst->toAlias(); - v = s->isDeclaration(); - if (v) - { e = new DotVarExp(loc, eleft, v); - e = e->semantic(sc); - return e; - } - } - - e = new ScopeExp(loc, ti); - if (eleft) - { - e = new DotExp(loc, eleft, e); - } - e = e->semantic(sc); - return e; - -Lerr: - return new IntegerExp(0); -} - -void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writeByte('.'); - ti->toCBuffer(buf); -} - -/************************************************************/ - -DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f) - : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e) -{ - this->func = f; -} - -Expression *DelegateExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("DelegateExp::semantic('%s')\n", toChars()); -#endif - if (!type) - { - e1 = e1->semantic(sc); - type = new TypeDelegate(func->type); - type = type->semantic(loc, sc); - } - return this; -} - -void DelegateExp::toCBuffer(OutBuffer *buf) -{ - buf->writeByte('&'); - if (!func->isNested()) - { e1->toCBuffer(buf); - buf->writeByte('.'); - } - buf->writestring(func->toChars()); -} - -/************************************************************/ - -DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s) - : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e) -{ - this->sym = s; - this->type = s->getType(); -} - -Expression *DotTypeExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("DotTypeExp::semantic('%s')\n", toChars()); -#endif - UnaExp::semantic(sc); - return this; -} - -void DotTypeExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writeByte('.'); - buf->writestring(sym->toChars()); -} - -/************************************************************/ - -ArrowExp::ArrowExp(Loc loc, Expression *e, Identifier *ident) - : UnaExp(loc, TOKarrow, sizeof(ArrowExp), e) -{ - this->ident = ident; -} - -Expression *ArrowExp::semantic(Scope *sc) -{ Expression *e; - -#if LOGSEMANTIC - printf("ArrowExp::semantic('%s')\n", toChars()); -#endif - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - e1 = e1->checkToPointer(); - if (e1->type->ty != Tpointer) - error("pointer expected before ->, not '%s'", e1->type->toChars()); - e = new PtrExp(loc, e1); - e = new DotIdExp(loc, e, ident); - e = e->semantic(sc); - return e; -} - -void ArrowExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writestring("->"); - buf->writestring(ident->toChars()); -} - -/************************************************************/ - -CallExp::CallExp(Loc loc, Expression *e, Array *arguments) - : UnaExp(loc, TOKcall, sizeof(CallExp), e) -{ - this->arguments = arguments; -} - -CallExp::CallExp(Loc loc, Expression *e) - : UnaExp(loc, TOKcall, sizeof(CallExp), e) -{ - this->arguments = NULL; -} - -CallExp::CallExp(Loc loc, Expression *e, Expression *earg1) - : UnaExp(loc, TOKcall, sizeof(CallExp), e) -{ - Array *arguments = new Array(); - arguments->setDim(1); - arguments->data[0] = (void *)earg1; - - this->arguments = arguments; -} - -CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2) - : UnaExp(loc, TOKcall, sizeof(CallExp), e) -{ - Array *arguments = new Array(); - arguments->setDim(2); - arguments->data[0] = (void *)earg1; - arguments->data[1] = (void *)earg2; - - this->arguments = arguments; -} - -Expression *CallExp::syntaxCopy() -{ - return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); -} - - -Expression *CallExp::semantic(Scope *sc) -{ - TypeFunction *tf; - FuncDeclaration *f; - int i; - Type *t1; - -#if LOGSEMANTIC - printf("CallExp::semantic('%s')\n", toChars()); -#endif - if (type) - return this; // semantic() already run -#if 0 -if (arguments && arguments->dim) -{ - Expression *earg = (Expression *)arguments->data[0]; - earg->print(); - if (earg->type) earg->type->print(); -} -#endif - - // Transform array.id(args) into id(array,args) - if (e1->op == TOKdot) - { - // BUG: we should handle array.a.b.c.e(args) too - - DotIdExp *dotid = (DotIdExp *)(e1); - dotid->e1 = dotid->e1->semantic(sc); - assert(dotid->e1); - if (dotid->e1->type) - { - TY e1ty = dotid->e1->type->toBasetype()->ty; - if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray) - { - if (!arguments) - arguments = new Array(); - arguments->shift(dotid->e1); - e1 = new IdentifierExp(dotid->loc, dotid->ident); - } - } - } - -Lagain: - if (e1->op == TOKthis || e1->op == TOKsuper) - { - // semantic() run later for these - } - else - { - UnaExp::semantic(sc); - if (e1->op == TOKimport) - { // Perhaps this should be moved to ScopeExp::semantic() - ScopeExp *se = (ScopeExp *)e1; - e1 = new DsymbolExp(loc, se->sds); - e1 = e1->semantic(sc); - } - } - - if (e1->op == TOKcomma) - { - CommaExp *ce = (CommaExp *)e1; - - e1 = ce->e2; - e1->type = ce->type; - ce->e2 = this; - ce->type = NULL; - return ce->semantic(sc); - } - - t1 = NULL; - if (e1->type) - t1 = e1->type->toBasetype(); - - // Check for call operator overload - if (t1) - { AggregateDeclaration *ad; - FuncDeclaration *fd; - - if (t1->ty == Tclass) - { - ad = ((TypeClass *)t1)->sym; - goto L1; - } - else if (t1->ty == Tstruct) - { - ad = ((TypeStruct *)t1)->sym; - L1: - fd = search_function(ad, Id::call); - if (fd) - { - // Rewrite as e1.call(arguments) - Expression *e = new DotIdExp(loc, e1, Id::call); - e = new CallExp(loc, e, arguments); - e = e->semantic(sc); - return e; - } - } - } - - arrayExpressionSemantic(arguments, sc); - preFunctionArguments(loc, sc, arguments); - - if (e1->op == TOKdotvar && t1->ty == Tfunction) - { - // Do overload resolution - DotVarExp *dve = (DotVarExp *)(e1); - - f = dve->var->isFuncDeclaration(); - assert(f); - f = f->overloadResolve(loc, arguments); - checkDeprecated(sc, f); - accessCheck(loc, sc, dve->e1, f); - if (!f->needThis()) - { - VarExp *ve = new VarExp(loc, f); - e1 = new CommaExp(loc, dve->e1, ve); - e1->type = f->type; - } - else - { - dve->var = f; - e1->type = f->type; - - // See if we need to adjust the 'this' pointer - AggregateDeclaration *ad = f->isThis(); - ClassDeclaration *cd = dve->e1->type->isClassHandle(); - if (ad && cd && ad->isClassDeclaration() && ad != cd && - dve->e1->op != TOKsuper) - { - dve->e1 = dve->e1->castTo(ad->type); //new CastExp(loc, dve->e1, ad->type); - dve->e1 = dve->e1->semantic(sc); - } - } - t1 = e1->type; - } - else if (e1->op == TOKsuper) - { - // Base class constructor call - ClassDeclaration *cd = NULL; - - if (sc->func) - cd = sc->func->toParent()->isClassDeclaration(); - if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration()) - { - error("super class constructor call must be in a constructor"); - type = Type::terror; - return this; - } - else - { - f = cd->baseClass->ctor; - if (!f) - { error("no super class constructor for %s", cd->baseClass->toChars()); - type = Type::terror; - return this; - } - else - { -#if 0 - if (sc->callSuper & (CSXthis | CSXsuper)) - error("reference to this before super()"); -#endif - if (sc->noctor || sc->callSuper & CSXlabel) - error("constructor calls not allowed in loops or after labels"); - if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) - error("multiple constructor calls"); - sc->callSuper |= CSXany_ctor | CSXsuper_ctor; - - f = f->overloadResolve(loc, arguments); - checkDeprecated(sc, f); - e1 = new DotVarExp(e1->loc, e1, f); - e1 = e1->semantic(sc); - t1 = e1->type; - } - } - } - else if (e1->op == TOKthis) - { - // same class constructor call - ClassDeclaration *cd = NULL; - - if (sc->func) - cd = sc->func->toParent()->isClassDeclaration(); - if (!cd || !sc->func->isCtorDeclaration()) - { - error("class constructor call must be in a constructor"); - type = Type::terror; - return this; - } - else - { -#if 0 - if (sc->callSuper & (CSXthis | CSXsuper)) - error("reference to this before super()"); -#endif - if (sc->noctor || sc->callSuper & CSXlabel) - error("constructor calls not allowed in loops or after labels"); - if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) - error("multiple constructor calls"); - sc->callSuper |= CSXany_ctor | CSXthis_ctor; - - f = cd->ctor; - f = f->overloadResolve(loc, arguments); - checkDeprecated(sc, f); - e1 = new DotVarExp(e1->loc, e1, f); - e1 = e1->semantic(sc); - t1 = e1->type; - - // BUG: this should really be done by checking the static - // call graph - if (f == sc->func) - error("cyclic constructor call"); - } - } - else if (!t1) - { - error("function expected before (), not '%s'", e1->toChars()); - type = Type::terror; - return this; - } - else if (t1->ty != Tfunction) - { - if (t1->ty == Tdelegate) - { - assert(t1->next->ty == Tfunction); - tf = (TypeFunction *)(t1->next); - goto Lcheckargs; - } - else if (t1->ty == Tpointer && t1->next->ty == Tfunction) - { Expression *e; - - e = new PtrExp(loc, e1); - t1 = t1->next; - e->type = t1; - e1 = e; - } - else - { error("function expected before (), not '%s'", e1->type->toChars()); - type = Type::terror; - return this; - } - } - else if (e1->op == TOKvar) - { - // Do overload resolution - VarExp *ve = (VarExp *)e1; - - f = ve->var->isFuncDeclaration(); - assert(f); - f = f->overloadResolve(loc, arguments); - checkDeprecated(sc, f); - - if (f->needThis() && hasThis(sc)) - { - // Supply an implicit 'this', as in - // this.ident - - e1 = new DotVarExp(loc, new ThisExp(loc), f); - goto Lagain; - } - - ve->var = f; - ve->type = f->type; - t1 = f->type; - } - assert(t1->ty == Tfunction); - tf = (TypeFunction *)(t1); - -Lcheckargs: - assert(tf->ty == Tfunction); - type = tf->next; - - if (!arguments) - arguments = new Array(); - functionArguments(loc, sc, tf, arguments); - - assert(type); - return this; -} - -void CallExp::toCBuffer(OutBuffer *buf) -{ int i; - - e1->toCBuffer(buf); - buf->writeByte('('); - argsToCBuffer(buf, arguments); - buf->writeByte(')'); -} - - -/************************************************************/ - -AddrExp::AddrExp(Loc loc, Expression *e) - : UnaExp(loc, TOKaddress, sizeof(AddrExp), e) -{ -} - -Expression *AddrExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("AddrExp::semantic('%s')\n", toChars()); -#endif - if (!type) - { - UnaExp::semantic(sc); - e1 = e1->toLvalue(NULL); - if (!e1->type) - { - error("cannot take address of %s", e1->toChars()); - type = Type::tint32; - return this; - } - type = e1->type->pointerTo(); - - // See if this should really be a delegate - if (e1->op == TOKdotvar) - { - DotVarExp *dve = (DotVarExp *)e1; - FuncDeclaration *f = dve->var->isFuncDeclaration(); - - if (f) - { Expression *e; - - e = new DelegateExp(loc, dve->e1, f); - e = e->semantic(sc); - return e; - } - } - else if (e1->op == TOKvar) - { - VarExp *dve = (VarExp *)e1; - FuncDeclaration *f = dve->var->isFuncDeclaration(); - - if (f && f->isNested()) - { Expression *e; - - e = new DelegateExp(loc, e1, f); - e = e->semantic(sc); - return e; - } - } - else if (e1->op == TOKarray) - { - if (e1->type->toBasetype()->ty == Tbit) - error("cannot take address of bit in array"); - } - } - return this; -} - -/************************************************************/ - -PtrExp::PtrExp(Loc loc, Expression *e) - : UnaExp(loc, TOKstar, sizeof(PtrExp), e) -{ - if (e->type) - type = e->type->next; -} - -PtrExp::PtrExp(Loc loc, Expression *e, Type *t) - : UnaExp(loc, TOKstar, sizeof(PtrExp), e) -{ - type = t; -} - -Expression *PtrExp::semantic(Scope *sc) -{ Type *tb; - -#if LOGSEMANTIC - printf("PtrExp::semantic('%s')\n", toChars()); -#endif - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - if (type) - return this; - if (!e1->type) - printf("PtrExp::semantic('%s')\n", toChars()); - tb = e1->type->toBasetype(); - switch (tb->ty) - { - case Tpointer: - type = tb->next; - if (type->isbit()) - { Expression *e; - - // Rewrite *p as p[0] - e = new IndexExp(loc, e1, new IntegerExp(0)); - return e->semantic(sc); - } - break; - - case Tsarray: - case Tarray: - type = tb->next; - e1 = e1->castTo(type->pointerTo()); - break; - - default: - error("can only * a pointer, not a '%s'", e1->type->toChars()); - type = Type::tint32; - break; - } - rvalue(); - return this; -} - -Expression *PtrExp::toLvalue(Expression *e) -{ -#if 0 - tym = tybasic(e1->ET->Tty); - if (!(tyscalar(tym) || - tym == TYstruct || - tym == TYarray && e->Eoper == TOKaddr)) - synerr(EM_lvalue); // lvalue expected -#endif - return this; -} - -void PtrExp::toCBuffer(OutBuffer *buf) -{ - buf->writeByte('*'); - buf->writeByte('('); - e1->toCBuffer(buf); - buf->writeByte(')'); -} - -/************************************************************/ - -NegExp::NegExp(Loc loc, Expression *e) - : UnaExp(loc, TOKneg, sizeof(NegExp), e) -{ -} - -Expression *NegExp::semantic(Scope *sc) -{ Expression *e; - -#if LOGSEMANTIC - printf("NegExp::semantic('%s')\n", toChars()); -#endif - if (!type) - { - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - e = op_overload(sc); - if (e) - return e; - - e1->checkArithmetic(); - type = e1->type; - } - return this; -} - -/************************************************************/ - -UAddExp::UAddExp(Loc loc, Expression *e) - : UnaExp(loc, TOKuadd, sizeof(UAddExp), e) -{ -} - -Expression *UAddExp::semantic(Scope *sc) -{ Expression *e; - -#if LOGSEMANTIC - printf("UAddExp::semantic('%s')\n", toChars()); -#endif - assert(!type); - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - e = op_overload(sc); - if (e) - return e; - e1->checkArithmetic(); - return e1; -} - -/************************************************************/ - -ComExp::ComExp(Loc loc, Expression *e) - : UnaExp(loc, TOKtilde, sizeof(ComExp), e) -{ -} - -Expression *ComExp::semantic(Scope *sc) -{ Expression *e; - - if (!type) - { - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - e = op_overload(sc); - if (e) - return e; - - e1 = e1->checkIntegral(); - type = e1->type; - } - return this; -} - -/************************************************************/ - -NotExp::NotExp(Loc loc, Expression *e) - : UnaExp(loc, TOKnot, sizeof(NotExp), e) -{ -} - -Expression *NotExp::semantic(Scope *sc) -{ - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - e1 = e1->checkToBoolean(); - type = Type::tboolean; - return this; -} - -int NotExp::isBit() -{ - return TRUE; -} - - - -/************************************************************/ - -BoolExp::BoolExp(Loc loc, Expression *e, Type *t) - : UnaExp(loc, TOKnot, sizeof(BoolExp), e) -{ - type = t; -} - -Expression *BoolExp::semantic(Scope *sc) -{ - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - e1 = e1->checkToBoolean(); - type = Type::tboolean; - return this; -} - -int BoolExp::isBit() -{ - return TRUE; -} - -/************************************************************/ - -DeleteExp::DeleteExp(Loc loc, Expression *e) - : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e) -{ -} - -Expression *DeleteExp::semantic(Scope *sc) -{ - Type *tb; - - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - e1 = e1->toLvalue(NULL); - type = Type::tvoid; - - tb = e1->type->toBasetype(); - if (tb->ty == Tclass) - { - TypeClass *tc = (TypeClass *)tb; - ClassDeclaration *cd = tc->sym; - - if (cd->isInterfaceDeclaration() && cd->isCOMclass()) - error("cannot delete instance of COM interface %s", cd->toChars()); - } - else if (tb->ty == Tpointer) - { - tb = tb->next->toBasetype(); - if (tb->ty == Tstruct) - { - TypeStruct *ts = (TypeStruct *)tb; - StructDeclaration *sd = ts->sym; - FuncDeclaration *f = sd->aggDelete; - - if (f) - { - Expression *e; - Expression *ec; - Type *tpv = Type::tvoid->pointerTo(); - - e = e1; - e->type = tpv; - ec = new VarExp(loc, f); - e = new CallExp(loc, ec, e); - return e->semantic(sc); - } - } - } - return this; -} - -Expression *DeleteExp::checkToBoolean() -{ - error("delete does not give a boolean result"); - return this; -} - - -/************************************************************/ - -CastExp::CastExp(Loc loc, Expression *e, Type *t) - : UnaExp(loc, TOKcast, sizeof(CastExp), e) -{ - to = t; -} - -Expression *CastExp::syntaxCopy() -{ - return new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy()); -} - - -Expression *CastExp::semantic(Scope *sc) -{ Expression *e; - BinExp *b; - UnaExp *u; - -#if LOGSEMANTIC - printf("CastExp::semantic('%s')\n", toChars()); -#endif - -//static int x; assert(++x < 10); - - if (type) - return this; - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - to = to->semantic(loc, sc); - - e = op_overload(sc); - if (e) - { - return e->implicitCastTo(to); - } - return e1->castTo(to); -} - -void CastExp::toCBuffer(OutBuffer *buf) -{ - buf->writestring("cast("); - to->toCBuffer(buf, NULL); - buf->writestring(")("); - e1->toCBuffer(buf); - buf->writeByte(')'); -} - - -/************************************************************/ - -SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr) - : UnaExp(loc, TOKslice, sizeof(SliceExp), e1) -{ - this->upr = upr; - this->lwr = lwr; - lengthVar = NULL; -} - -Expression *SliceExp::syntaxCopy() -{ - Expression *lwr = NULL; - if (this->lwr) - lwr = this->lwr->syntaxCopy(); - - Expression *upr = NULL; - if (this->upr) - upr = this->upr->syntaxCopy(); - - return new SliceExp(loc, e1->syntaxCopy(), lwr, upr); -} - -Expression *SliceExp::semantic(Scope *sc) -{ Expression *e; - AggregateDeclaration *ad; - FuncDeclaration *fd; - ScopeDsymbol *sym; - -#if LOGSEMANTIC - printf("SliceExp::semantic('%s')\n", toChars()); -#endif - if (type) - return this; - - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - - e = this; - - Type *t = e1->type->toBasetype(); - if (t->ty == Tpointer) - { - if (!lwr || !upr) - error("need upper and lower bound to slice pointer"); - } - else if (t->ty == Tarray) - { - } - else if (t->ty == Tsarray) - { - } - else if (t->ty == Tclass) - { - ad = ((TypeClass *)t)->sym; - goto L1; - } - else if (t->ty == Tstruct) - { - ad = ((TypeStruct *)t)->sym; - - L1: - fd = search_function(ad, Id::slice); - if (fd) - { - // Rewrite as e1.slice(lwr, upr) - e = new DotIdExp(loc, e1, Id::slice); - - if (lwr) - { - assert(upr); - e = new CallExp(loc, e, lwr, upr); - } - else - { assert(!upr); - e = new CallExp(loc, e); - } - e = e->semantic(sc); - return e; - } - goto Lerror; - } - else - goto Lerror; - - if (t->ty == Tsarray || t->ty == Tarray) - { - sym = new ArrayScopeSymbol(this); - sym->parent = sc->scopesym; - sc = sc->push(sym); - } - - if (lwr) - { lwr = lwr->semantic(sc); - lwr = resolveProperties(sc, lwr); - lwr = lwr->implicitCastTo(Type::tindex); - } - if (upr) - { upr = upr->semantic(sc); - upr = resolveProperties(sc, upr); - upr = upr->implicitCastTo(Type::tindex); - } - - if (t->ty == Tsarray || t->ty == Tarray) - sc->pop(); - - type = t->next->arrayOf(); - return e; - -Lerror: - char *s; - if (t->ty == Tvoid) - s = e1->toChars(); - else - s = t->toChars(); - error("%s cannot be sliced with []", s); - type = Type::terror; - return e; -} - -Expression *SliceExp::toLvalue(Expression *e) -{ - return this; -} - -Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e) -{ - error("slice expression %s is not a modifiable lvalue", toChars()); - return this; -} - -void SliceExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writeByte('['); - if (upr || lwr) - { - if (lwr) - lwr->toCBuffer(buf); - else - buf->writeByte('0'); - buf->writestring(".."); - if (upr) - upr->toCBuffer(buf); - else - buf->writestring("length"); // BUG: should be array.length - } - buf->writeByte(']'); -} - -/********************** ArrayLength **************************************/ - -ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1) - : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1) -{ -} - -Expression *ArrayLengthExp::semantic(Scope *sc) -{ Expression *e; - -#if LOGSEMANTIC - printf("ArrayLengthExp::semantic('%s')\n", toChars()); -#endif - if (!type) - { - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - - type = Type::tindex; - } - return this; -} - -void ArrayLengthExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writestring(".length"); -} - -/*********************** ArrayExp *************************************/ - -// e1 [ i1, i2, i3, ... ] - -ArrayExp::ArrayExp(Loc loc, Expression *e1, Array *args) - : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1) -{ - arguments = args; -} - -Expression *ArrayExp::syntaxCopy() -{ - return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); -} - -Expression *ArrayExp::semantic(Scope *sc) -{ Expression *e; - Type *t1; - -#if LOGSEMANTIC - printf("ArrayExp::semantic('%s')\n", toChars()); -#endif - UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - assert(arguments && arguments->dim); - - t1 = e1->type->toBasetype(); - if (t1->ty != Tclass && t1->ty != Tstruct) - { // Convert to IndexExp - if (arguments->dim != 1) - error("only one index allowed to index %s", t1->toChars()); - e = new IndexExp(loc, e1, (Expression *)arguments->data[0]); - return e->semantic(sc); - } - - // Run semantic() on each argument - for (int i = 0; i < arguments->dim; i++) - { e = (Expression *)arguments->data[i]; - - e = e->semantic(sc); - if (!e->type) - error("%s has no value", e->toChars()); - arguments->data[i] = (void *)e; - } - - e = op_overload(sc); - if (!e) - { error("no [] operator overload for type %s", e1->type->toChars()); - e = e1; - } - return e; -} - - -Expression *ArrayExp::toLvalue(Expression *e) -{ - if (type && type->toBasetype()->ty == Tvoid) - error("voids have no value"); - return this; -} - - -void ArrayExp::toCBuffer(OutBuffer *buf) -{ int i; - - e1->toCBuffer(buf); - buf->writeByte('['); - argsToCBuffer(buf, arguments); - buf->writeByte(']'); -} - -/************************* DotExp ***********************************/ - -DotExp::DotExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2) -{ -} - -Expression *DotExp::semantic(Scope *sc) -{ -#if LOGSEMANTIC - printf("DotExp::semantic('%s')\n", toChars()); -#endif - e1 = e1->semantic(sc); - e2 = e2->semantic(sc); - return this; -} - - -/************************* CommaExp ***********************************/ - -CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2) -{ -} - -Expression *CommaExp::semantic(Scope *sc) -{ - if (!type) - { BinExp::semanticp(sc); - type = e2->type; - } - return this; -} - -Expression *CommaExp::toLvalue(Expression *e) -{ - e2 = e2->toLvalue(NULL); - return this; -} - -int CommaExp::isBool(int result) -{ - return e2->isBool(result); -} - -/************************** IndexExp **********************************/ - -// e1 [ e2 ] - -IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2) -{ - lengthVar = NULL; -} - -Expression *IndexExp::semantic(Scope *sc) -{ Expression *e; - BinExp *b; - UnaExp *u; - Type *t1; - ScopeDsymbol *sym; - -#if LOGSEMANTIC - printf("IndexExp::semantic('%s')\n", toChars()); -#endif - if (type) - return this; - assert(e1->type); // semantic() should already be run on it - e = this; - - // Note that unlike C we do not implement the int[ptr] - - t1 = e1->type->toBasetype(); - - if (t1->ty == Tsarray || t1->ty == Tarray) - { // Create scope for 'length' variable - sym = new ArrayScopeSymbol(this); - sym->parent = sc->scopesym; - sc = sc->push(sym); - } - - e2 = e2->semantic(sc); - if (!e2->type) - { - error("%s has no value", e2->toChars()); - e2->type = Type::terror; - } - e2 = resolveProperties(sc, e2); - - if (t1->ty == Tsarray || t1->ty == Tarray) - sc = sc->pop(); - - switch (t1->ty) - { - case Tpointer: - case Tarray: - e2 = e2->implicitCastTo(Type::tindex); - e->type = t1->next; - break; - - case Tsarray: - { - e2 = e2->implicitCastTo(Type::tindex); - if (t1->next->toBasetype()->ty == Tbit) - { - e->type = t1->next; - break; - } - - TypeSArray *tsa = (TypeSArray *)t1; - - // Do compile time array bounds checking if possible - e2 = e2->optimize(WANTvalue); - if (e2->op == TOKint64) - { - integer_t index = e2->toInteger(); - integer_t length = tsa->dim->toInteger(); - if (index < 0 || index >= length) - error("array index [%lld] is outside array bounds [0 .. %lld]", - index, length); - } - e->type = t1->next; - break; - } - - case Taarray: - { TypeAArray *taa = (TypeAArray *)t1; - - e1 = e1->modifiableLvalue(sc, e1); - e2 = e2->implicitCastTo(taa->index); // type checking - e2 = e2->implicitCastTo(taa->key); // actual argument type - type = taa->next; - break; - } - - default: - error("%s must be an array or pointer type, not %s", - e1->toChars(), e1->type->toChars()); - type = Type::tint32; - break; - } - return e; -} - -Expression *IndexExp::toLvalue(Expression *e) -{ -// if (type && type->toBasetype()->ty == Tvoid) -// error("voids have no value"); - return this; -} - -void IndexExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writeByte('['); - e2->toCBuffer(buf); - buf->writeByte(']'); -} - -/************************* PostIncExp ***********************************/ - -PostIncExp::PostIncExp(Loc loc, Expression *e) - : BinExp(loc, TOKplusplus, sizeof(PostIncExp), e, new IntegerExp(loc, 1, Type::tint32)) -{ -} - -Expression *PostIncExp::semantic(Scope *sc) -{ Expression *e = this; - - if (!type) - { - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e = this; - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - if (e1->type->ty == Tpointer) - e = scaleFactor(); - else - e2 = e2->castTo(e1->type); - e->type = e1->type; - } - return e; -} - -void PostIncExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writestring("++"); -} - -/************************************************************/ - -PostDecExp::PostDecExp(Loc loc, Expression *e) - : BinExp(loc, TOKminusminus, sizeof(PostDecExp), e, new IntegerExp(loc, 1, Type::tint32)) -{ -} - -Expression *PostDecExp::semantic(Scope *sc) -{ Expression *e = this; - - if (!type) - { - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - e = op_overload(sc); - if (e) - return e; - - e = this; - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - if (e1->type->ty == Tpointer) - e = scaleFactor(); - else - e2 = e2->castTo(e1->type); - e->type = e1->type; - } - return e; -} - -void PostDecExp::toCBuffer(OutBuffer *buf) -{ - e1->toCBuffer(buf); - buf->writestring("--"); -} - -/************************************************************/ - -AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2) -{ -} - -Expression *AssignExp::semantic(Scope *sc) -{ Type *t1; - Expression *e1old = e1; - -#if LOGSEMANTIC - printf("AssignExp::semantic('%s')\n", toChars()); -#endif - //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); - - /* Look for operator overloading of a[]=value. - * Do it before semantic() otherwise the a[] will have been - * converted to a.opIndex() already. - */ - if (e1->op == TOKarray) - { Type *t1; - ArrayExp *ae = (ArrayExp *)e1; - AggregateDeclaration *ad; - Identifier *id = Id::index; - FuncDeclaration *fd; - - ae->e1 = ae->e1->semantic(sc); - t1 = ae->e1->type->toBasetype(); - if (t1->ty == Tstruct) - { - ad = ((TypeStruct *)t1)->sym; - goto L1; - } - else if (t1->ty == Tclass) - { - ad = ((TypeClass *)t1)->sym; - L1: - // Rewrite (a[i] = value) to (a.opIndexAssign(value, i)) - fd = search_function(ad, Id::indexass); - if (fd) - { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass); - Array *a = ae->arguments->copy(); - - a->insert(0, e2); - e = new CallExp(loc, e, a); - e = e->semantic(sc); - return e; - } - else - { - // Rewrite (a[i] = value) to (a.opIndex(i, value)) - fd = search_function(ad, id); - if (fd) - { Expression *e = new DotIdExp(loc, ae->e1, id); - - if (!global.params.useDeprecated) - error("operator [] assignment overload with opIndex(i, value) deprecated, use opIndexAssign(value, i)"); - - e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2); - e = e->semantic(sc); - return e; - } - } - } - } - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - assert(e1->type); - t1 = e1->type->toBasetype(); - if (t1->ty == Tfunction) - { // Rewrite f=value to f(value) - Expression *e; - - e = new CallExp(loc, e1, e2); - e = e->semantic(sc); - return e; - } - - e2->rvalue(); - - if (e1->op == TOKarraylength) - { - // e1 is not an lvalue, but we let code generator handle it - ArrayLengthExp *ale = (ArrayLengthExp *)e1; - - ale->e1 = ale->e1->modifiableLvalue(sc, NULL); - } - else if (e1->op == TOKslice) - ; - else - // Try to do a decent error message with the expression - // before it got constant folded - e1 = e1->modifiableLvalue(sc, e1old); - - if (e1->op == TOKslice && - t1->next && - !(t1->next->equals(e2->type->next) /*|| - (t1->next->ty == Tchar && e2->op == TOKstring)*/) - ) - { // memset - e2 = e2->implicitCastTo(t1->next); - } -#if 0 - else if (e1->op == TOKslice && - e2->op == TOKstring && - ((StringExp *)e2)->len == 1) - { // memset - e2 = e2->implicitCastTo(e1->type->next); - } -#endif - else if (t1->ty == Tsarray) - { - error("cannot assign to static array %s", e1->toChars()); - } - else - { - e2 = e2->implicitCastTo(e1->type); - } - type = e1->type; - assert(type); - return this; -} - -Expression *AssignExp::checkToBoolean() -{ - // Things like: - // if (a = b) ... - // are usually mistakes. - - error("'=' does not give a boolean result"); - return this; -} - -/************************************************************/ - -AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) -{ -} - -Expression *AddAssignExp::semantic(Scope *sc) -{ Expression *e; - - if (type) - return this; - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, NULL); - - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - - if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - (tb2->ty == Tarray || tb2->ty == Tsarray) && - tb1->next->equals(tb2->next) - ) - { - type = e1->type; - e = this; - } - else - { - e1->checkScalar(); - if (tb1->ty == Tpointer && tb2->isintegral()) - e = scaleFactor(); - else if (tb1->ty == Tbit) - { -#if 0 - // Need to rethink this - if (e1->op != TOKvar) - { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2 - VarDeclaration *v; - Expression *ea; - Expression *ex; - - char name[6+6+1]; - Identifier *id; - static int idn; - sprintf(name, "__name%d", ++idn); - id = Lexer::idPool(name); - - v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL); - v->semantic(sc); - if (!sc->insert(v)) - assert(0); - v->parent = sc->func; - - ea = new AddrExp(loc, e1); - ea = new AssignExp(loc, new VarExp(loc, v), ea); - - ex = new VarExp(loc, v); - ex = new PtrExp(loc, ex); - e = new AddExp(loc, ex, e2); - e = new CastExp(loc, e, e1->type); - e = new AssignExp(loc, ex->syntaxCopy(), e); - - e = new CommaExp(loc, ea, e); - } - else -#endif - { // Rewrite e1+=e2 to e1=e1+e2 - // BUG: doesn't account for side effects in e1 - // BUG: other assignment operators for bits aren't handled at all - e = new AddExp(loc, e1, e2); - e = new CastExp(loc, e, e1->type); - e = new AssignExp(loc, e1->syntaxCopy(), e); - } - e = e->semantic(sc); - } - else - { - typeCombine(); - type = e1->type; - e1->checkArithmetic(); - e2->checkArithmetic(); - if (type->isreal() || type->isimaginary()) - { - assert(global.errors || e2->type->isfloating()); - e2 = e2->castTo(type); - } - e = this; - } - } - return e; -} - -/************************************************************/ - -MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) -{ -} - -Expression *MinAssignExp::semantic(Scope *sc) -{ Expression *e; - - if (type) - return this; - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - if (e1->type->ty == Tpointer && e2->type->isintegral()) - e = scaleFactor(); - else - { - typeCombine(); - type = e1->type; - e1->checkArithmetic(); - e2->checkArithmetic(); - if (type->isreal() || type->isimaginary()) - { - assert(e2->type->isfloating()); - e2 = e2->castTo(type); - } - e = this; - } - return e; -} - -/************************************************************/ - -CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) -{ -} - -Expression *CatAssignExp::semantic(Scope *sc) -{ Expression *e; - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - if (e1->op == TOKslice) - { SliceExp *se = (SliceExp *)e1; - - if (se->e1->type->toBasetype()->ty == Tsarray) - error("cannot append to static array %s", se->e1->type->toChars()); - } - - e1 = e1->modifiableLvalue(sc, NULL); - - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - - if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - (tb2->ty == Tarray || tb2->ty == Tsarray) && - e2->implicitConvTo(e1->type) - //e1->type->next->equals(e2->type->next) - ) - { // Append array - e2 = e2->castTo(e1->type); - type = e1->type; - e = this; - } - else if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - e2->implicitConvTo(tb1->next) - ) - { // Append element - e2 = e2->castTo(tb1->next); - type = e1->type; - e = this; - } - else - { - error("Can only concatenate arrays, not %s ~= %s", tb1->toChars(), tb2->toChars()); - type = Type::tint32; - e = this; - } - return e; -} - -/************************************************************/ - -MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) -{ -} - -Expression *MulAssignExp::semantic(Scope *sc) -{ Expression *e; - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - type = e1->type; - typeCombine(); - e1->checkArithmetic(); - e2->checkArithmetic(); - if (e2->type->isfloating()) - { Type *t1; - Type *t2; - - t1 = e1->type; - t2 = e2->type; - if (t1->isreal()) - { - if (t2->isimaginary() || t2->iscomplex()) - { - e2 = e2->castTo(t1); - } - } - else if (t1->isimaginary()) - { - if (t2->isimaginary() || t2->iscomplex()) - { - switch (t1->ty) - { - case Timaginary32: t2 = Type::tfloat32; break; - case Timaginary64: t2 = Type::tfloat64; break; - case Timaginary80: t2 = Type::tfloat80; break; - default: - assert(0); - } - e2 = e2->castTo(t2); - } - } - } - return this; -} - -/************************************************************/ - -DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) -{ -} - -Expression *DivAssignExp::semantic(Scope *sc) -{ Expression *e; - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - type = e1->type; - typeCombine(); - e1->checkArithmetic(); - e2->checkArithmetic(); - if (e2->type->isimaginary()) - { Type *t1; - Type *t2; - - t1 = e1->type; - if (t1->isreal() || t1->isimaginary()) - { Expression *e; - - switch (t1->ty) - { - case Timaginary32: t2 = Type::tfloat32; break; - case Timaginary64: t2 = Type::tfloat64; break; - case Timaginary80: t2 = Type::tfloat80; break; - default: - assert(0); - } - e2 = e2->castTo(t2); - e = new AssignExp(loc, e1, e2); - e->type = t1; - return e; - } - } - return this; -} - -/************************************************************/ - -ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) -{ -} - -Expression *ModAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssign(sc); -} - -/************************************************************/ - -ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) -{ -} - -Expression *ShlAssignExp::semantic(Scope *sc) -{ Expression *e; - - //printf("ShlAssignExp::semantic()\n"); - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - type = e1->type; - typeCombine(); - e1->checkIntegral(); - e2 = e2->checkIntegral(); - e2 = e2->castTo(Type::tshiftcnt); - return this; -} - -/************************************************************/ - -ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) -{ -} - -Expression *ShrAssignExp::semantic(Scope *sc) -{ Expression *e; - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - type = e1->type; - typeCombine(); - e1->checkIntegral(); - e2 = e2->checkIntegral(); - e2 = e2->castTo(Type::tshiftcnt); - return this; -} - -/************************************************************/ - -UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) -{ -} - -Expression *UshrAssignExp::semantic(Scope *sc) -{ Expression *e; - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, NULL); - e1->checkScalar(); - type = e1->type; - typeCombine(); - e1->checkIntegral(); - e2 = e2->checkIntegral(); - e2 = e2->castTo(Type::tshiftcnt); - return this; -} - -/************************************************************/ - -AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) -{ -} - -Expression *AndAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssignIntegral(sc); -} - -/************************************************************/ - -OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) -{ -} - -Expression *OrAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssignIntegral(sc); -} - -/************************************************************/ - -XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) -{ -} - -Expression *XorAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssignIntegral(sc); -} - -/************************* AddExp *****************************/ - -AddExp::AddExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2) -{ -} - -Expression *AddExp::semantic(Scope *sc) -{ Expression *e; - -#if LOGSEMANTIC - printf("AddExp::semantic('%s')\n", toChars()); -#endif - if (!type) - { - BinExp::semanticp(sc); - - e = op_overload(sc); - if (e) - return e; - - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - - if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - (tb2->ty == Tarray || tb2->ty == Tsarray) && - tb1->next->equals(tb2->next) - ) - { - type = e1->type; - e = this; - } - else if (tb1->ty == Tpointer && e2->type->isintegral() || - tb2->ty == Tpointer && e1->type->isintegral()) - e = scaleFactor(); - else - { - typeCombine(); - if ((e1->type->isreal() && e2->type->isimaginary()) || - (e1->type->isimaginary() && e2->type->isreal())) - { - switch (type->toBasetype()->ty) - { - case Tfloat32: - case Timaginary32: - type = Type::tcomplex32; - break; - - case Tfloat64: - case Timaginary64: - type = Type::tcomplex64; - break; - - case Tfloat80: - case Timaginary80: - type = Type::tcomplex80; - break; - - default: - assert(0); - } - } - e = this; - } - return e; - } - return this; -} - -/************************************************************/ - -MinExp::MinExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2) -{ -} - -Expression *MinExp::semantic(Scope *sc) -{ Expression *e; - Type *t1; - Type *t2; - -#if LOGSEMANTIC - printf("MinExp::semantic('%s')\n", toChars()); -#endif - if (type) - return this; - - BinExp::semanticp(sc); - - e = op_overload(sc); - if (e) - return e; - - e = this; - t1 = e1->type->toBasetype(); - t2 = e2->type->toBasetype(); - if (t1->ty == Tpointer) - { - if (t2->ty == Tpointer) - { // Need to divide the result by the stride - // Replace (ptr - ptr) with (ptr - ptr) / stride - d_int64 stride; - Expression *e; - - typeCombine(); // make sure pointer types are compatible - type = Type::tptrdiff_t; - stride = t2->next->size(); - e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t)); - e->type = Type::tptrdiff_t; - return e; - } - else if (t2->isintegral()) - e = scaleFactor(); - else - { error("incompatible types for -"); - return new IntegerExp(0); - } - } - else if (t2->ty == Tpointer) - { - type = e2->type; - error("can't subtract pointer from %s", e1->type->toChars()); - return new IntegerExp(0); - } - else - { - typeCombine(); - t1 = e1->type->toBasetype(); - t2 = e2->type->toBasetype(); - if ((t1->isreal() && t2->isimaginary()) || - (t1->isimaginary() && t2->isreal())) - { - switch (type->ty) - { - case Tfloat32: - case Timaginary32: - type = Type::tcomplex32; - break; - - case Tfloat64: - case Timaginary64: - type = Type::tcomplex64; - break; - - case Tfloat80: - case Timaginary80: - type = Type::tcomplex80; - break; - - default: - assert(0); - } - } - } - return e; -} - -/************************* CatExp *****************************/ - -CatExp::CatExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2) -{ -} - -Expression *CatExp::semantic(Scope *sc) -{ Expression *e; - - //printf("CatExp::semantic()\n"); - if (!type) - { - BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - -#if 0 - if (tb1->ty == Tsarray) - e1 = e1->castTo(tb1->next->arrayOf()); - if (tb2->ty == Tsarray) - e2 = e2->castTo(tb2->next->arrayOf()); -#endif - - /* BUG: Should handle things like: - * char c; - * c ~ ' ' - * ' ' ~ c; - */ - - typeCombine(); - -#if 0 - e1->type->print(); - e2->type->print(); - type->print(); - print(); -#endif - if (e1->op == TOKstring && e2->op == TOKstring) - e = optimize(WANTvalue); - else if (e1->type->equals(e2->type) && - (e1->type->toBasetype()->ty == Tarray || - e1->type->toBasetype()->ty == Tsarray)) - { - e = this; - } - else - { - error("Can only concatenate arrays, not (%s ~ %s)", - e1->type->toChars(), e2->type->toChars()); - type = Type::tint32; - e = this; - } - return e; - } - return this; -} - -/************************************************************/ - -MulExp::MulExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2) -{ -} - -Expression *MulExp::semantic(Scope *sc) -{ Expression *e; - - if (type) - return this; - - BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - - typeCombine(); - e1->checkArithmetic(); - e2->checkArithmetic(); - if (type->isfloating()) - { Type *t1 = e1->type; - Type *t2 = e2->type; - - if (t1->isreal()) - { - type = t2; - } - else if (t2->isreal()) - { - type = t1; - } - else if (t1->isimaginary()) - { - if (t2->isimaginary()) - { Expression *e; - - switch (t1->ty) - { - case Timaginary32: type = Type::tfloat32; break; - case Timaginary64: type = Type::tfloat64; break; - case Timaginary80: type = Type::tfloat80; break; - default: assert(0); - } - // iy * iv = -yv - e1->type = type; - e2->type = type; - e = new NegExp(loc, this); - e = e->semantic(sc); - return e; - } - else - type = t2; // t2 is complex - } - else if (t2->isimaginary()) - { - type = t1; // t1 is complex - } - } - return this; -} - -/************************************************************/ - -DivExp::DivExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2) -{ -} - -Expression *DivExp::semantic(Scope *sc) -{ Expression *e; - - if (type) - return this; - - BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - - typeCombine(); - e1->checkArithmetic(); - e2->checkArithmetic(); - if (type->isfloating()) - { Type *t1 = e1->type; - Type *t2 = e2->type; - - if (t1->isreal()) - { - type = t2; - if (t2->isimaginary()) - { Expression *e; - - // x/iv = i(-x/v) - e2->type = t1; - e = new NegExp(loc, this); - e = e->semantic(sc); - return e; - } - } - else if (t2->isreal()) - { - type = t1; - } - else if (t1->isimaginary()) - { - if (t2->isimaginary()) - { - switch (t1->ty) - { - case Timaginary32: type = Type::tfloat32; break; - case Timaginary64: type = Type::tfloat64; break; - case Timaginary80: type = Type::tfloat80; break; - default: assert(0); - } - } - else - type = t2; // t2 is complex - } - else if (t2->isimaginary()) - { - type = t1; // t1 is complex - } - } - return this; -} - -/************************************************************/ - -ModExp::ModExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2) -{ -} - -Expression *ModExp::semantic(Scope *sc) -{ Expression *e; - - if (type) - return this; - - BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - - typeCombine(); - e1->checkArithmetic(); - e2->checkArithmetic(); - return this; -} - -/************************************************************/ - -ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2) -{ -} - -Expression *ShlExp::semantic(Scope *sc) -{ Expression *e; - - //printf("ShlExp::semantic(), type = %p\n", type); - if (!type) - { BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - e1 = e1->checkIntegral(); - e2 = e2->checkIntegral(); - e1 = e1->integralPromotions(); - e2 = e2->castTo(Type::tshiftcnt); - type = e1->type; - } - return this; -} - -/************************************************************/ - -ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2) -{ -} - -Expression *ShrExp::semantic(Scope *sc) -{ Expression *e; - - if (!type) - { BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - e1 = e1->checkIntegral(); - e2 = e2->checkIntegral(); - e1 = e1->integralPromotions(); - e2 = e2->castTo(Type::tshiftcnt); - type = e1->type; - } - return this; -} - -/************************************************************/ - -UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2) -{ -} - -Expression *UshrExp::semantic(Scope *sc) -{ Expression *e; - - if (!type) - { BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - e1 = e1->checkIntegral(); - e2 = e2->checkIntegral(); - e1 = e1->integralPromotions(); - e2 = e2->castTo(Type::tshiftcnt); - type = e1->type; - } - return this; -} - -/************************************************************/ - -AndExp::AndExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKand, sizeof(AndExp), e1, e2) -{ -} - -Expression *AndExp::semantic(Scope *sc) -{ Expression *e; - - if (!type) - { BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - typeCombine(); - e1->checkIntegral(); - e2->checkIntegral(); - } - return this; -} - -/************************************************************/ - -OrExp::OrExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKor, sizeof(OrExp), e1, e2) -{ -} - -Expression *OrExp::semantic(Scope *sc) -{ Expression *e; - - if (!type) - { BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - typeCombine(); - e1->checkIntegral(); - e2->checkIntegral(); - } - return this; -} - -/************************************************************/ - -XorExp::XorExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2) -{ -} - -Expression *XorExp::semantic(Scope *sc) -{ Expression *e; - - if (!type) - { BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - return e; - typeCombine(); - e1->checkIntegral(); - e2->checkIntegral(); - } - return this; -} - - -/************************************************************/ - -OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2) -{ -} - -Expression *OrOrExp::semantic(Scope *sc) -{ - unsigned cs1; - - // same as for AndAnd - e1 = e1->semantic(sc); - cs1 = sc->callSuper; - e2 = e2->semantic(sc); - sc->mergeCallSuper(loc, cs1); - - e1 = resolveProperties(sc, e1); - e2 = resolveProperties(sc, e2); - - e1 = e1->checkToPointer(); - e2 = e2->checkToPointer(); - e1 = e1->checkToBoolean(); - type = Type::tboolean; - if (e1->type->ty == Tvoid) - type = Type::tvoid; - return this; -} - -Expression *OrOrExp::checkToBoolean() -{ - e2 = e2->checkToBoolean(); - return this; -} - -int OrOrExp::isBit() -{ - return TRUE; -} - - -/************************************************************/ - -AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2) -{ -} - -Expression *AndAndExp::semantic(Scope *sc) -{ - unsigned cs1; - - // same as for OrOr - e1 = e1->semantic(sc); - cs1 = sc->callSuper; - e2 = e2->semantic(sc); - sc->mergeCallSuper(loc, cs1); - - e1 = resolveProperties(sc, e1); - e2 = resolveProperties(sc, e2); - - e1 = e1->checkToPointer(); - e2 = e2->checkToPointer(); - e1 = e1->checkToBoolean(); - type = Type::tboolean; - if (e1->type->ty == Tvoid) - type = Type::tvoid; - return this; -} - -Expression *AndAndExp::checkToBoolean() -{ - e2 = e2->checkToBoolean(); - return this; -} - -int AndAndExp::isBit() -{ - return TRUE; -} - - -/************************************************************/ - -InExp::InExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKin, sizeof(InExp), e1, e2) -{ -} - -Expression *InExp::semantic(Scope *sc) -{ - if (type) - return this; - - BinExp::semanticp(sc); - //type = Type::tboolean; - Type *t2b = e2->type->toBasetype(); - if (t2b->ty != Taarray) - { - error("rvalue of in expression must be an associative array, not %s", e2->type->toChars()); - type = Type::terror; - } - else - { - TypeAArray *ta = (TypeAArray *)t2b; - - // Convert key to type of key - e1 = e1->implicitCastTo(ta->index); - - // Return type is pointer to value - type = ta->next->pointerTo(); - } - return this; -} - -int InExp::isBit() -{ - return FALSE; -} - - -/************************************************************/ - -CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, op, sizeof(CmpExp), e1, e2) -{ -} - -Expression *CmpExp::semantic(Scope *sc) -{ Expression *e; - Type *t1; - Type *t2; - -#if LOGSEMANTIC - printf("CmpExp::semantic('%s')\n", toChars()); -#endif - if (type) - return this; - - BinExp::semanticp(sc); - e = op_overload(sc); - if (e) - { - e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32)); - e = e->semantic(sc); - return e; - } - - typeCombine(); - type = Type::tboolean; - - // Special handling for array comparisons - t1 = e1->type->toBasetype(); - t2 = e2->type->toBasetype(); - if ((t1->ty == Tarray || t1->ty == Tsarray) && - (t2->ty == Tarray || t2->ty == Tsarray)) - { - if (!t1->next->equals(t2->next)) - error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); - e = this; - } - else if (t1->ty == Tstruct || t2->ty == Tstruct) - { - error("need member function opCmp() for struct %s to compare", t1->toChars()); - e = this; - } - else - e = this; - return e; -} - -int CmpExp::isBit() -{ - return TRUE; -} - - -/************************************************************/ - -EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, op, sizeof(EqualExp), e1, e2) -{ -} - -Expression *EqualExp::semantic(Scope *sc) -{ Expression *e; - Type *t1; - Type *t2; - - if (type) - return this; - - BinExp::semanticp(sc); - - /* Before checking for operator overloading, check to see if we're - * comparing the addresses of two statics. If so, we can just see - * if they are the same symbol. - */ - if (e1->op == TOKaddress && e2->op == TOKaddress) - { AddrExp *ae1 = (AddrExp *)e1; - AddrExp *ae2 = (AddrExp *)e2; - - if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar) - { VarExp *ve1 = (VarExp *)ae1->e1; - VarExp *ve2 = (VarExp *)ae2->e1; - - if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/) - { - // They are the same, result is 'true' - e = new IntegerExp(loc, 1, Type::tbit); - return e; - } - } - } - - //if (e2->op != TOKnull) - { - e = op_overload(sc); - if (e) - { - if (op == TOKnotequal) - { - e = new NotExp(e->loc, e); - e = e->semantic(sc); - } - return e; - } - } - - e = typeCombine(); - type = Type::tboolean; - - // Special handling for array comparisons - t1 = e1->type->toBasetype(); - t2 = e2->type->toBasetype(); - if ((t1->ty == Tarray || t1->ty == Tsarray) && - (t2->ty == Tarray || t2->ty == Tsarray)) - { - if (!t1->next->equals(t2->next)) - error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); - } - else - { - if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) - { - // Cast both to complex - e1 = e1->castTo(Type::tcomplex80); - e2 = e2->castTo(Type::tcomplex80); - } - } - return e; -} - -int EqualExp::isBit() -{ - return TRUE; -} - - - -/************************************************************/ - -IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, op, sizeof(IdentityExp), e1, e2) -{ -} - -Expression *IdentityExp::semantic(Scope *sc) -{ - if (type) - return this; - - BinExp::semanticp(sc); - type = Type::tboolean; - typeCombine(); - if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) - { - // Cast both to complex - e1 = e1->castTo(Type::tcomplex80); - e2 = e2->castTo(Type::tcomplex80); - } - return this; -} - -int IdentityExp::isBit() -{ - return TRUE; -} - - -/****************************************************************/ - -CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2) - : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2) -{ - this->econd = econd; -} - -Expression *CondExp::syntaxCopy() -{ - return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy()); -} - - -Expression *CondExp::semantic(Scope *sc) -{ Type *t1; - Type *t2; - unsigned cs0; - unsigned cs1; - - if (type) - return this; - - econd = econd->semantic(sc); - econd = resolveProperties(sc, econd); - - - cs0 = sc->callSuper; - e1 = e1->semantic(sc); - e1 = resolveProperties(sc, e1); - cs1 = sc->callSuper; - sc->callSuper = cs0; - e2 = e2->semantic(sc); - e2 = resolveProperties(sc, e2); - sc->mergeCallSuper(loc, cs1); - - - econd = econd->checkToPointer(); - econd = econd->checkToBoolean(); - // If either operand is void, the result is void - t1 = e1->type; - t2 = e2->type; - if (t1->ty == Tvoid || t2->ty == Tvoid) - type = Type::tvoid; - else if (t1 == t2) - type = t1; - else - { - typeCombine(); - } - return this; -} - -Expression *CondExp::toLvalue(Expression *ex) -{ - PtrExp *e; - - // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) - e = new PtrExp(loc, this, type); - - e1 = e1->addressOf(); - e1 = e1->toLvalue(NULL); - - e2 = e2->addressOf(); - e2 = e2->toLvalue(NULL); - - typeCombine(); - - type = e2->type; - return e; -} - -Expression *CondExp::checkToBoolean() -{ - e1 = e1->checkToBoolean(); - e2 = e2->checkToBoolean(); - return this; -} - -void CondExp::toCBuffer(OutBuffer *buf) -{ - econd->toCBuffer(buf); - buf->writestring(" ? "); - e1->toCBuffer(buf); - buf->writestring(" : "); - e2->toCBuffer(buf); -} - - diff -uNr gdc-0.11/d/root/expression.h gdc-0.12/d/root/expression.h --- gdc-0.11/d/root/expression.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/expression.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,1161 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef DMD_EXPRESSION_H -#define DMD_EXPRESSION_H - -#include "mars.h" -#include "identifier.h" -#include "lexer.h" - -struct Type; -struct Scope; -struct VarDeclaration; -struct FuncDeclaration; -struct FuncLiteralDeclaration; -struct Declaration; -struct CtorDeclaration; -struct NewDeclaration; -struct Dsymbol; -struct Import; -struct Module; -struct ScopeDsymbol; -struct InlineCostState; -struct InlineDoState; -struct InlineScanState; -struct Expression; -struct Declaration; -struct AggregateDeclaration; -struct TemplateInstance; - -// Back end -struct IRState; -union tree_node; typedef union tree_node elem; -struct dt_t; - -Expression *resolveProperties(Scope *sc, Expression *e); -void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d); -FuncDeclaration *search_function(AggregateDeclaration *ad, Identifier *funcid); - -struct Expression : Object -{ - Loc loc; // file location - enum TOK op; // handy to minimize use of dynamic_cast - Type *type; // !=NULL means that semantic() has been run - int size; // # of bytes in Expression so we can copy() it - - Expression(Loc loc, enum TOK op, int size); - Expression *copy(); - virtual Expression *syntaxCopy(); - virtual Expression *semantic(Scope *sc); - - int dyncast() { return DYNCAST_EXPRESSION; } // kludge for template.isExpression() - - void print(); - char *toChars(); - virtual void dump(int indent); - void error(const char *format, ...); - void rvalue(); - - static Expression *combine(Expression *e1, Expression *e2); - static Array *arraySyntaxCopy(Array *exps); - - virtual integer_t toInteger(); - virtual real_t toReal(); - virtual real_t toImaginary(); - virtual complex_t toComplex(); - virtual void toCBuffer(OutBuffer *buf); - virtual Expression *toLvalue(Expression *e); - virtual Expression *modifiableLvalue(Scope *sc, Expression *e); - Expression *implicitCastTo(Type *t); - virtual int implicitConvTo(Type *t); - virtual Expression *castTo(Type *t); - void checkScalar(); - Expression *checkIntegral(); - void checkArithmetic(); - void checkDeprecated(Scope *sc, Dsymbol *s); - virtual Expression *checkToBoolean(); - Expression *checkToPointer(); - Expression *addressOf(); - Expression *deref(); - Expression *integralPromotions(); - - virtual Expression *optimize(int result); - #define WANTflags 1 - #define WANTvalue 2 - - virtual Expression *constFold(); - virtual int isConst(); - virtual int isBool(int result); - virtual int isBit(); - - virtual int inlineCost(InlineCostState *ics); - virtual Expression *doInline(InlineDoState *ids); - virtual Expression *inlineScan(InlineScanState *iss); - - // For operator overloading - virtual int isCommutative(); - virtual Identifier *opId(); - virtual Identifier *opId_r(); - - // Back end - virtual elem *toElem(IRState *irs); - virtual dt_t **toDt(dt_t **pdt); -}; - -struct IntegerExp : Expression -{ - integer_t value; - - IntegerExp(Loc loc, integer_t value, Type *type); - IntegerExp(integer_t value); - int equals(Object *o); - Expression *semantic(Scope *sc); - char *toChars(); - void dump(int indent); - integer_t toInteger(); - real_t toReal(); - real_t toImaginary(); - int isConst(); - int isBool(int result); - int implicitConvTo(Type *t); - void toCBuffer(OutBuffer *buf); - Expression *toLvalue(Expression *e); - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -}; - -struct RealExp : Expression -{ - real_t value; - - RealExp(Loc loc, real_t value, Type *type); - Expression *semantic(Scope *sc); - char *toChars(); - integer_t toInteger(); - real_t toReal(); - real_t toImaginary(); - complex_t toComplex(); - int isConst(); - int isBool(int result); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -}; - -struct ImaginaryExp : Expression -{ - real_t value; - - ImaginaryExp(Loc loc, real_t value, Type *type); - Expression *semantic(Scope *sc); - char *toChars(); - integer_t toInteger(); - real_t toReal(); - real_t toImaginary(); - complex_t toComplex(); - int isConst(); - int isBool(int result); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -}; - -struct ComplexExp : Expression -{ - complex_t value; - - ComplexExp(Loc loc, complex_t value, Type *type); - Expression *semantic(Scope *sc); - char *toChars(); - integer_t toInteger(); - real_t toReal(); - real_t toImaginary(); - complex_t toComplex(); - int isConst(); - int isBool(int result); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -}; - -struct IdentifierExp : Expression -{ - Identifier *ident; - Declaration *var; - - IdentifierExp(Loc loc, Identifier *ident); - IdentifierExp(Loc loc, Declaration *var); - Expression *semantic(Scope *sc); - char *toChars(); - void dump(int indent); - void toCBuffer(OutBuffer *buf); - Expression *toLvalue(Expression *e); -}; - -struct DollarExp : IdentifierExp -{ - DollarExp(Loc loc); -}; - -struct DsymbolExp : Expression -{ - Dsymbol *s; - - DsymbolExp(Loc loc, Dsymbol *s); - Expression *semantic(Scope *sc); - char *toChars(); - void dump(int indent); - void toCBuffer(OutBuffer *buf); - Expression *toLvalue(Expression *e); -}; - -struct ThisExp : Expression -{ - Declaration *var; - - ThisExp(Loc loc); - Expression *semantic(Scope *sc); - int isBool(int result); - void toCBuffer(OutBuffer *buf); - Expression *toLvalue(Expression *e); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - //Expression *inlineScan(InlineScanState *iss); - - elem *toElem(IRState *irs); -}; - -struct SuperExp : ThisExp -{ - SuperExp(Loc loc); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - //Expression *inlineScan(InlineScanState *iss); -}; - -struct NullExp : Expression -{ - NullExp(Loc loc); - Expression *semantic(Scope *sc); - int isBool(int result); - void toCBuffer(OutBuffer *buf); - int implicitConvTo(Type *t); - Expression *castTo(Type *t); - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -}; - -struct StringExp : Expression -{ - void *string; // char, wchar, or dchar data - unsigned len; // number of chars, wchars, or dchars - unsigned char sz; // 1: char, 2: wchar, 4: dchar - unsigned char committed; // !=0 if type is committed - - StringExp(Loc loc, void *s, unsigned len); - int equals(Object *o); - char *toChars(); - Expression *semantic(Scope *sc); - int implicitConvTo(Type *t); - Expression *castTo(Type *t); - int compare(Object *obj); - int isBool(int result); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -}; - -struct TypeDotIdExp : Expression -{ - Identifier *ident; - - TypeDotIdExp(Loc loc, Type *type, Identifier *ident); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); -}; - -struct TypeExp : Expression -{ - TypeExp(Loc loc, Type *type); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); -}; - -struct ScopeExp : Expression -{ - ScopeDsymbol *sds; - - ScopeExp(Loc loc, ScopeDsymbol *sds); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - elem *toElem(IRState *irs); - void toCBuffer(OutBuffer *buf); -}; - -struct NewExp : Expression -{ - Array *newargs; // Array of Expression's to call new operator - Array *arguments; // Array of Expression's - CtorDeclaration *member; // constructor function - NewDeclaration *allocator; // allocator function - - NewExp(Loc loc, Array *newargs, Type *type, Array *arguments); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - elem *toElem(IRState *irs); - void toCBuffer(OutBuffer *buf); - - //int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - //Expression *inlineScan(InlineScanState *iss); -}; - -// Offset from symbol - -struct SymOffExp : Expression -{ - Declaration *var; - unsigned offset; - - SymOffExp(Loc loc, Declaration *var, unsigned offset); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - int isConst(); - int isBool(int result); - Expression *doInline(InlineDoState *ids); - - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -}; - -// Variable - -struct VarExp : Expression -{ - Declaration *var; - - VarExp(Loc loc, Declaration *var); - int equals(Object *o); - Expression *semantic(Scope *sc); - void dump(int indent); - char *toChars(); - void toCBuffer(OutBuffer *buf); - Expression *toLvalue(Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); - - //int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - //Expression *inlineScan(InlineScanState *iss); -}; - -// Function/Delegate literal - -struct FuncExp : Expression -{ - FuncLiteralDeclaration *fd; - - FuncExp(Loc loc, FuncLiteralDeclaration *fd); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - char *toChars(); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); - - int inlineCost(InlineCostState *ics); - //Expression *doInline(InlineDoState *ids); - //Expression *inlineScan(InlineScanState *iss); -}; - -// Declaration of a symbol - -struct DeclarationExp : Expression -{ - Dsymbol *declaration; - - DeclarationExp(Loc loc, Dsymbol *declaration); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Expression *inlineScan(InlineScanState *iss); -}; - -struct TypeidExp : Expression -{ - Type *typeidType; - - TypeidExp(Loc loc, Type *typeidType); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); -}; - -struct HaltExp : Expression -{ - HaltExp(Loc loc); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - - elem *toElem(IRState *irs); -}; - -/****************************************************************/ - -struct UnaExp : Expression -{ - Expression *e1; - - UnaExp(Loc loc, enum TOK op, int size, Expression *e1); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - Expression *optimize(int result); - void dump(int indent); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Expression *inlineScan(InlineScanState *iss); - - Expression *op_overload(Scope *sc); // doesn't need to be virtual -}; - -struct BinExp : Expression -{ - Expression *e1; - Expression *e2; - - BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - Expression *semanticp(Scope *sc); - Expression *commonSemanticAssign(Scope *sc); - Expression *commonSemanticAssignIntegral(Scope *sc); - void toCBuffer(OutBuffer *buf); - Expression *scaleFactor(); - Expression *typeCombine(); - Expression *optimize(int result); - int isunsigned(); - void dump(int indent); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Expression *inlineScan(InlineScanState *iss); - - Expression *op_overload(Scope *sc); - - elem *toElemBin(IRState *irs, int op); -}; - -/****************************************************************/ - -struct AssertExp : UnaExp -{ - AssertExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); -}; - -struct DotIdExp : UnaExp -{ - Identifier *ident; - - DotIdExp(Loc loc, Expression *e, Identifier *ident); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - void dump(int i); -}; - -struct DotVarExp : UnaExp -{ - Declaration *var; - - DotVarExp(Loc loc, Expression *e, Declaration *var); - Expression *semantic(Scope *sc); - Expression *toLvalue(Expression *e); - void toCBuffer(OutBuffer *buf); - void dump(int indent); - elem *toElem(IRState *irs); -}; - -struct DotTemplateInstanceExp : UnaExp -{ - TemplateInstance *ti; - - DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - void dump(int indent); -}; - -struct DelegateExp : UnaExp -{ - FuncDeclaration *func; - - DelegateExp(Loc loc, Expression *e, FuncDeclaration *func); - Expression *semantic(Scope *sc); - int implicitConvTo(Type *t); - Expression *castTo(Type *t); - void toCBuffer(OutBuffer *buf); - void dump(int indent); - - int inlineCost(InlineCostState *ics); - elem *toElem(IRState *irs); -}; - -struct DotTypeExp : UnaExp -{ - Dsymbol *sym; // symbol that represents a type - - DotTypeExp(Loc loc, Expression *e, Dsymbol *sym); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); -}; - -struct ArrowExp : UnaExp -{ - Identifier *ident; - - ArrowExp(Loc loc, Expression *e, Identifier *ident); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); -}; - -struct CallExp : UnaExp -{ - Array *arguments; // Array of Expression's - - CallExp(Loc loc, Expression *e, Array *arguments); - CallExp(Loc loc, Expression *e); - CallExp(Loc loc, Expression *e, Expression *earg1); - CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2); - - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Expression *inlineScan(InlineScanState *iss); -}; - -struct AddrExp : UnaExp -{ - AddrExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - elem *toElem(IRState *irs); - int implicitConvTo(Type *t); - Expression *castTo(Type *t); - Expression *optimize(int result); -}; - -struct PtrExp : UnaExp -{ - PtrExp(Loc loc, Expression *e); - PtrExp(Loc loc, Expression *e, Type *t); - Expression *semantic(Scope *sc); - Expression *toLvalue(Expression *e); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); - Expression *optimize(int result); -}; - -struct NegExp : UnaExp -{ - NegExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct UAddExp : UnaExp -{ - UAddExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); -}; - -struct ComExp : UnaExp -{ - ComExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct NotExp : UnaExp -{ - NotExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - Expression *constFold(); - int isBit(); - elem *toElem(IRState *irs); -}; - -struct BoolExp : UnaExp -{ - BoolExp(Loc loc, Expression *e, Type *type); - Expression *semantic(Scope *sc); - Expression *constFold(); - int isBit(); - elem *toElem(IRState *irs); -}; - -struct DeleteExp : UnaExp -{ - DeleteExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - Expression *checkToBoolean(); - elem *toElem(IRState *irs); -}; - -struct CastExp : UnaExp -{ - // Possible to cast to one type while painting to another type - Type *to; // type to cast to - - CastExp(Loc loc, Expression *e, Type *t); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - Expression *optimize(int result); - void toCBuffer(OutBuffer *buf); - Expression *constFold(); - elem *toElem(IRState *irs); - - // For operator overloading - Identifier *opId(); -}; - - -struct SliceExp : UnaExp -{ - Expression *upr; // NULL if implicit 0 - Expression *lwr; // NULL if implicit [length - 1] - VarDeclaration *lengthVar; - - SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - Expression *toLvalue(Expression *e); - Expression *modifiableLvalue(Scope *sc, Expression *e); - void toCBuffer(OutBuffer *buf); - void dump(int indent); - elem *toElem(IRState *irs); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Expression *inlineScan(InlineScanState *iss); -}; - -struct ArrayLengthExp : UnaExp -{ - ArrayLengthExp(Loc loc, Expression *e1); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); -}; - -// e1[a0,a1,a2,a3,...] - -struct ArrayExp : UnaExp -{ - Array *arguments; // Array of Expression's - - ArrayExp(Loc loc, Expression *e1, Array *arguments); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - Expression *toLvalue(Expression *e); - void toCBuffer(OutBuffer *buf); - - // For operator overloading - Identifier *opId(); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Expression *inlineScan(InlineScanState *iss); -}; - -/****************************************************************/ - -struct DotExp : BinExp -{ - DotExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); -}; - -struct CommaExp : BinExp -{ - CommaExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *toLvalue(Expression *e); - int isBool(int result); - Expression *optimize(int result); - elem *toElem(IRState *irs); -}; - -struct IndexExp : BinExp -{ - VarDeclaration *lengthVar; - - IndexExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *toLvalue(Expression *e); - void toCBuffer(OutBuffer *buf); - Expression *doInline(InlineDoState *ids); - - elem *toElem(IRState *irs); -}; - -struct PostIncExp : BinExp -{ - PostIncExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - Identifier *opId(); // For operator overloading - elem *toElem(IRState *irs); -}; - -struct PostDecExp : BinExp -{ - PostDecExp(Loc loc, Expression *e); - Expression *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - Identifier *opId(); // For operator overloading - elem *toElem(IRState *irs); -}; - -struct AssignExp : BinExp -{ - AssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *checkToBoolean(); - elem *toElem(IRState *irs); -}; - -struct AddAssignExp : BinExp -{ - AddAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - Identifier *opId(); // For operator overloading - - elem *toElem(IRState *irs); -}; - -struct MinAssignExp : BinExp -{ - MinAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct CatAssignExp : BinExp -{ - CatAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct MulAssignExp : BinExp -{ - MulAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct DivAssignExp : BinExp -{ - DivAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct ModAssignExp : BinExp -{ - ModAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct ShlAssignExp : BinExp -{ - ShlAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct ShrAssignExp : BinExp -{ - ShrAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct UshrAssignExp : BinExp -{ - UshrAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct AndAssignExp : BinExp -{ - AndAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct OrAssignExp : BinExp -{ - OrAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct XorAssignExp : BinExp -{ - XorAssignExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - - // For operator overloading - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct AddExp : BinExp -{ - AddExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - Expression *optimize(int result); - - // For operator overloading - int isCommutative(); - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct MinExp : BinExp -{ - MinExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - Expression *optimize(int result); - - // For operator overloading - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct CatExp : BinExp -{ - CatExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *optimize(int result); - - // For operator overloading - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct MulExp : BinExp -{ - MulExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - int isCommutative(); - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct DivExp : BinExp -{ - DivExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct ModExp : BinExp -{ - ModExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct ShlExp : BinExp -{ - ShlExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct ShrExp : BinExp -{ - ShrExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct UshrExp : BinExp -{ - UshrExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct AndExp : BinExp -{ - AndExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - int isCommutative(); - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct OrExp : BinExp -{ - OrExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - int isCommutative(); - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct XorExp : BinExp -{ - XorExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - - // For operator overloading - int isCommutative(); - Identifier *opId(); - Identifier *opId_r(); - - elem *toElem(IRState *irs); -}; - -struct OrOrExp : BinExp -{ - OrOrExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *checkToBoolean(); - int isBit(); - Expression *constFold(); - Expression *optimize(int result); - elem *toElem(IRState *irs); -}; - -struct AndAndExp : BinExp -{ - AndAndExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *checkToBoolean(); - int isBit(); - Expression *constFold(); - Expression *optimize(int result); - elem *toElem(IRState *irs); -}; - -struct CmpExp : BinExp -{ - CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - int isBit(); - - // For operator overloading - int isCommutative(); - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -struct InExp : BinExp -{ - InExp(Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - int isBit(); - elem *toElem(IRState *irs); -}; - -// == and != - -struct EqualExp : BinExp -{ - EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - Expression *constFold(); - int isBit(); - - // For operator overloading - int isCommutative(); - Identifier *opId(); - - elem *toElem(IRState *irs); -}; - -// === and !=== - -struct IdentityExp : BinExp -{ - IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); - Expression *semantic(Scope *sc); - int isBit(); - Expression *constFold(); - elem *toElem(IRState *irs); -}; - -/****************************************************************/ - -struct CondExp : BinExp -{ - Expression *econd; - - CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2); - Expression *syntaxCopy(); - Expression *semantic(Scope *sc); - Expression *optimize(int result); - Expression *constFold(); - Expression *toLvalue(Expression *e); - Expression *checkToBoolean(); - void toCBuffer(OutBuffer *buf); - int implicitConvTo(Type *t); - Expression *castTo(Type *t); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Expression *inlineScan(InlineScanState *iss); - - elem *toElem(IRState *irs); -}; - -#endif /* DMD_EXPRESSION_H */ diff -uNr gdc-0.11/d/root/func.c gdc-0.12/d/root/func.c --- gdc-0.11/d/root/func.c 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/root/func.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1987 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include - -#include "mars.h" -#include "init.h" -#include "declaration.h" -#include "attrib.h" -#include "expression.h" -#include "scope.h" -#include "mtype.h" -#include "aggregate.h" -#include "identifier.h" -#include "id.h" -#include "module.h" -#include "statement.h" -#include "template.h" - -#ifdef IN_GCC -#include "d-dmd-gcc.h" -#endif - - -/********************************* FuncDeclaration ****************************/ - -FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type) - : Declaration(id) -{ - this->storage_class = storage_class; - this->type = type; - this->loc = loc; - this->endloc = endloc; - fthrows = NULL; - frequire = NULL; - outId = NULL; - vresult = NULL; - returnLabel = NULL; - fensure = NULL; - fbody = NULL; - localsymtab = NULL; - vthis = NULL; - v_arguments = NULL; - v_argptr = NULL; - parameters = NULL; - labtab = NULL; - overnext = NULL; - vtblIndex = -1; - hasReturnExp = 0; - naked = 0; - inlineStatus = ILSuninitialized; - inlineNest = 0; - inlineAsm = 0; - semanticRun = 0; - nestedFrameRef = 0; - introducing = 0; - fes = NULL; -} - -Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s) -{ - FuncDeclaration *f; - - //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars()); - if (s) - f = (FuncDeclaration *)s; - else - f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy()); - f->outId = outId; - f->frequire = frequire ? frequire->syntaxCopy() : NULL; - f->fensure = fensure ? fensure->syntaxCopy() : NULL; - f->fbody = fbody ? fbody->syntaxCopy() : NULL; - assert(!fthrows); // deprecated - return f; -} - - -// Do the semantic analysis on the external interface to the function. - -void FuncDeclaration::semantic(Scope *sc) -{ TypeFunction *f; - StructDeclaration *sd; - ClassDeclaration *cd; - InterfaceDeclaration *id; - -#if 0 - printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage); - if (isFuncLiteralDeclaration()) - printf("\tFuncLiteralDeclaration()\n"); -#endif - - type = type->semantic(loc, sc); - //type->print(); - if (type->ty != Tfunction) - { - error("%s must be a function", toChars()); - } - f = (TypeFunction *)(type); - - linkage = sc->linkage; -// parent = sc->scopesym; - parent = sc->parent; - protection = sc->protection; - storage_class |= sc->stc; - //printf("storage_class = x%x\n", storage_class); - Dsymbol *parent = toParent(); - - if (isConst() || isAuto()) - error("functions cannot be const or auto"); - - if (isAbstract() && !isVirtual()) - error("non-virtual functions cannot be abstract"); -#if 0 - if (isAbstract() && fbody) - error("abstract functions cannot have bodies"); -#endif - -#if 0 - if (isStaticConstructor() || isStaticDestructor()) - { - if (!isStatic() || type->next->ty != Tvoid) - error("static constructors / destructors must be static void"); - if (f->arguments && f->arguments->dim) - error("static constructors / destructors must have empty parameter list"); - // BUG: check for invalid storage classes - } -#endif - -#ifdef IN_GCC - AggregateDeclaration *ad; - - ad = parent->isAggregateDeclaration(); - if (ad) - ad->methods.push(this); -#endif - sd = parent->isStructDeclaration(); - if (sd) - { - // Verify no constructors, destructors, etc. - if (isCtorDeclaration() || - isDtorDeclaration() - //|| isInvariantDeclaration() - //|| isUnitTestDeclaration() - ) - { - error("special member functions not allowed for %ss", sd->kind()); - } - -#if 0 - if (!sd->inv) - sd->inv = isInvariantDeclaration(); - - if (!sd->aggNew) - sd->aggNew = isNewDeclaration(); - - if (isDelete()) - { - if (sd->aggDelete) - error("multiple delete's for struct %s", sd->toChars()); - sd->aggDelete = (DeleteDeclaration *)(this); - } -#endif - } - - id = parent->isInterfaceDeclaration(); - if (id) - { - storage_class |= STCabstract; - - if (isCtorDeclaration() || - isDtorDeclaration() || - isInvariantDeclaration() || - isUnitTestDeclaration() || isNewDeclaration() || isDelete()) - error("special function not allowed in interface %s", id->toChars()); - if (fbody) - error("function body is not abstract in interface %s", id->toChars()); - } - - cd = parent->isClassDeclaration(); - if (cd) - { int vi; - CtorDeclaration *ctor; - DtorDeclaration *dtor; - InvariantDeclaration *inv; - - if (isCtorDeclaration()) - { -// ctor = (CtorDeclaration *)this; -// if (!cd->ctor) -// cd->ctor = ctor; - return; - } - -#if 0 - dtor = isDtorDeclaration(); - if (dtor) - { - if (cd->dtor) - error("multiple destructors for class %s", cd->toChars()); - cd->dtor = dtor; - } - - inv = isInvariantDeclaration(); - if (inv) - { - cd->inv = inv; - } - - if (isNewDeclaration()) - { - if (!cd->aggNew) - cd->aggNew = (NewDeclaration *)(this); - } - - if (isDelete()) - { - if (cd->aggDelete) - error("multiple delete's for class %s", cd->toChars()); - cd->aggDelete = (DeleteDeclaration *)(this); - } -#endif - - if (storage_class & STCabstract) - cd->isabstract = 1; - - // if static function, do not put in vtbl[] - if (!isVirtual()) - return; - - // Find index of existing function in vtbl[] to override - if (cd->baseClass) - { - for (vi = 0; vi < cd->baseClass->vtbl.dim; vi++) - { - FuncDeclaration *fdv = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration(); - - // BUG: should give error if argument types match, - // but return type does not? - - //printf("\tvtbl[%d]\n", vi); - if (fdv && fdv->ident == ident) - { - int cov = type->covariant(fdv->type); - if (cov) - { - // Override - //printf("\toverride %p with %p\n", fdv, this); - if (cov == 2) - { - //type->print(); - //fdv->type->print(); - //printf("%s %s\n", type->deco, fdv->type->deco); - error("of type %s overrides but is not covariant with %s of type %s", - type->toChars(), fdv->toPrettyChars(), fdv->type->toChars()); - } - if (fdv->isFinal()) - error("cannot override final function %s", fdv->toPrettyChars()); - if (fdv->toParent() == parent) - { - // If both are mixins, then error. - // If either is not, the one that is not overrides - // the other. - if (fdv->parent->isClassDeclaration()) - goto L1; - if (!this->parent->isClassDeclaration()) - error("multiple overrides of same function"); - } - cd->vtbl.data[vi] = (void *)this; - vtblIndex = vi; - goto L1; - } - } - } - } - - // This is an 'introducing' function. - // Append to end of vtbl[] - //printf("\tappend with %p\n", this); - introducing = 1; - vi = cd->vtbl.dim; - cd->vtbl.push(this); - vtblIndex = vi; - - if (isOverride()) - { - error("function %s does not override any", toChars()); - } - - L1: ; - } - else if (isOverride() && !parent->isTemplateInstance()) - error("override only applies to class member functions"); - - /* Do not allow template instances to add virtual functions - * to a class. - */ - if (isVirtual()) - { - TemplateInstance *ti = parent->isTemplateInstance(); - if (ti) - { - // Take care of nested templates - while (1) - { - TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); - if (!ti2) - break; - ti = ti2; - } - - // If it's a member template - ClassDeclaration *cd = ti->tempdecl->isClassMember(); - if (cd) - { - error("cannot use template to add virtual function to class '%s'", cd->toChars()); - } - } - } - - if (isMain()) - { - // Check parameters to see if they are either () or (char[][] args) - if (f->arguments) - { - switch (f->arguments->dim) - { - case 0: - break; - - case 1: - { - Argument *arg0 = (Argument *)f->arguments->data[0]; - if (arg0->type->ty != Tarray || - arg0->type->next->ty != Tarray || - arg0->type->next->next->ty != Tchar) - goto Lmainerr; - break; - } - - default: - goto Lmainerr; - } - } - if (f->varargs) - { - Lmainerr: - error("parameters must be main() or main(char[][] args)"); - } - } -} - -// Do the semantic analysis on the internals of the function. - -void FuncDeclaration::semantic3(Scope *sc) -{ TypeFunction *f; - AggregateDeclaration *ad; - VarDeclaration *argptr = NULL; - - if (!parent) - { - printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc); - assert(0); - } - //printf("FuncDeclaration::semantic3('%s.%s', sc = %p)\n", parent->toChars(), toChars(), sc); - //fflush(stdout); - //{ static int x; if (++x == 2) *(char*)0=0; } - //printf("\tlinkage = %d\n", sc->linkage); - - //printf(" sc->incontract = %d\n", sc->incontract); - if (semanticRun) - return; - semanticRun = 1; - - if (!type || type->ty != Tfunction) - return; - f = (TypeFunction *)(type); - - // Check the 'throws' clause - if (fthrows) - { int i; - - for (i = 0; i < fthrows->dim; i++) - { - Type *t = (Type *)fthrows->data[i]; - - t = t->semantic(loc, sc); - if (!t->isClassHandle()) - error("can only throw classes, not %s", t->toChars()); - } - } - - if (fbody || frequire) - { - // Establish function scope - ScopeDsymbol *ss; - Scope *sc2; - - localsymtab = new DsymbolTable(); - - ss = new ScopeDsymbol(); - ss->parent = sc->scopesym; - sc2 = sc->push(ss); - sc2->func = this; - sc2->parent = this; - sc2->callSuper = 0; - sc2->sbreak = NULL; - sc2->scontinue = NULL; - sc2->fes = fes; - sc2->linkage = LINKd; - - // Declare 'this' - ad = isThis(); - if (ad) - { VarDeclaration *v; - - if (isFuncLiteralDeclaration() && isNested()) - { - error("literals cannot be class members"); - ad = NULL; - } - else - { - assert(!isNested()); // can't be both member and nested - assert(ad->handle); - v = new ThisDeclaration(ad->handle); - v->storage_class |= STCparameter | STCin; - v->semantic(sc2); - if (!sc2->insert(v)) - assert(0); - v->parent = this; - vthis = v; - } - } - else if (isNested()) - { - VarDeclaration *v; - - v = new ThisDeclaration(Type::tvoid->pointerTo()); - v->storage_class |= STCparameter | STCin; - v->semantic(sc2); - if (!sc2->insert(v)) - assert(0); - v->parent = this; - vthis = v; - } - - // Declare hidden variable _arguments[] and _argptr - if (f->varargs) - { Type *t; - - if (f->linkage == LINKd) - { // Declare _arguments[] - t = Type::typeinfo->type->arrayOf(); - v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL); - v_arguments->storage_class = STCparameter | STCin; - v_arguments->semantic(sc2); - sc2->insert(v_arguments); - v_arguments->parent = this; - } - if (f->linkage == LINKd || (parameters && parameters->dim)) - { // Declare _argptr -#ifndef IN_GCC - t = Type::tvoid->pointerTo(); -#else - t = d_gcc_builtin_va_list_d_type; -#endif - argptr = new VarDeclaration(0, t, Id::_argptr, NULL); - argptr->semantic(sc2); - sc2->insert(argptr); - argptr->parent = this; - } - } - - // Declare all the function parameters as variables - if (f->arguments) - { int i; - - parameters = new Array(); - parameters->reserve(f->arguments->dim); - for (i = 0; i < f->arguments->dim; i++) - { Argument *arg; - VarDeclaration *v; - - arg = (Argument *)f->arguments->data[i]; - if (!arg->ident) - error("no identifier for parameter %d of %s", i + 1, toChars()); - else - { - v = new VarDeclaration(0, arg->type, arg->ident, NULL); - v->storage_class |= STCparameter; - switch (arg->inout) - { case In: v->storage_class |= STCin; break; - case Out: v->storage_class |= STCout; break; - case InOut: v->storage_class |= STCin | STCout; break; - default: assert(0); - } - v->semantic(sc2); - if (!sc2->insert(v)) - error("parameter %s.%s is already defined", toChars(), v->toChars()); - else - parameters->push(v); - localsymtab->insert(v); - v->parent = this; - } - } - } - - sc2->incontract++; - - if (frequire) - { - // BUG: need to error if accessing out parameters - // BUG: need to treat parameters as const - // BUG: need to disallow returns and throws - // BUG: verify that all in and inout parameters are read - frequire = frequire->semantic(sc2); - labtab = NULL; // so body can't refer to labels - } - - if (fensure || addPostInvariant()) - { - ScopeDsymbol *sym; - - sym = new ScopeDsymbol(); - sym->parent = sc2->scopesym; - sc2 = sc2->push(sym); - - if (type->next->ty == Tvoid) - { - if (outId) - error("void functions have no result"); - } - else - { - if (!outId) - outId = Id::result; // provide a default - } - - if (outId) - { // Declare result variable - VarDeclaration *v; - Loc loc = this->loc; - - if (fensure) - loc = fensure->loc; - - v = new VarDeclaration(loc, type->next, outId, NULL); - v->noauto = 1; - sc2->incontract--; - v->semantic(sc2); - sc2->incontract++; - if (!sc2->insert(v)) - error("out result %s is already defined", v->toChars()); - v->parent = this; - vresult = v; - - // vresult gets initialized with the function return value - // in ReturnStatement::semantic() - } - - // BUG: need to treat parameters as const - // BUG: need to disallow returns and throws - if (fensure) - { fensure = fensure->semantic(sc2); - labtab = NULL; // so body can't refer to labels - } - - if (!global.params.useOut) - { fensure = NULL; // discard - vresult = NULL; - } - - // Postcondition invariant - if (addPostInvariant()) - { - Expression *e = NULL; - if (isCtorDeclaration()) - { - // Call invariant directly only if it exists - InvariantDeclaration *inv = ad->inv; - ClassDeclaration *cd = ad->isClassDeclaration(); - - while (!inv && cd) - { - cd = cd->baseClass; - if (!cd) - break; - inv = cd->inv; - } - if (inv) - { - e = new DsymbolExp(0, inv); - e = new CallExp(0, e); - e = e->semantic(sc2); - } - } - else - { // Call invariant virtually - ThisExp *v = new ThisExp(0); - v->type = vthis->type; - e = new AssertExp(0, v); - } - if (e) - { - ExpStatement *s = new ExpStatement(0, e); - if (fensure) - fensure = new CompoundStatement(0, s, fensure); - else - fensure = s; - } - } - - if (fensure) - { returnLabel = new LabelDsymbol(Id::returnLabel); - LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure); - ls->isReturnLabel = 1; - returnLabel->statement = ls; - } - sc2 = sc2->pop(); - } - - sc2->incontract--; - - if (fbody) - { - fbody = fbody->semantic(sc2); - int offend = fbody ? fbody->fallOffEnd() : TRUE; - - if (isCtorDeclaration()) - { - ClassDeclaration *cd = isClassMember(); - //printf("callSuper = x%x\n", sc2->callSuper); - - assert(cd || global.errors); - - if (cd && !(sc2->callSuper & CSXany_ctor) && - cd->baseClass && cd->baseClass->ctor) - { - sc2->callSuper = 0; - - // Insert implicit super() at start of fbody - Expression *e1 = new SuperExp(0); - Expression *e = new CallExp(0, e1); - e = e->semantic(sc2); - Statement *s = new ExpStatement(0, e); - fbody = new CompoundStatement(0, s, fbody); - } - } - else if (fes) - { // For foreach(){} body, append a return 0; - Expression *e = new IntegerExp(0); - Statement *s = new ReturnStatement(0, e); - fbody = new CompoundStatement(0, fbody, s); - assert(!returnLabel); - } -// else if (!hasReturnExp && type->next->ty != Tvoid) -// error("expected to return a value of type %s", type->next->toChars()); - else if (type->next->ty != Tvoid && !inlineAsm) - { - if (offend) - { Expression *e; - - if (global.params.warnings) - { printf("warning - "); - error("no return at end of function"); - } - - if (global.params.useAssert && - !global.params.useInline) - { /* Add an assert(0); where the missing return - * should be. - */ - e = new AssertExp(endloc, new IntegerExp(0, 0, Type::tint32)); - } - else - e = new HaltExp(endloc); - e = e->semantic(sc2); - Statement *s = new ExpStatement(0, e); - fbody = new CompoundStatement(0, fbody, s); - } - } - } - - { - Array *a = new Array(); - - // Merge in initialization of 'out' parameters - if (parameters) - { for (int i = 0; i < parameters->dim; i++) - { VarDeclaration *v; - - v = (VarDeclaration *)parameters->data[i]; - if ((v->storage_class & (STCout | STCin)) == STCout) - { - assert(v->init); - ExpInitializer *ie = v->init->isExpInitializer(); - assert(ie); - a->push(new ExpStatement(0, ie->exp)); - } - } - } - - if (argptr) - { // Initialize _argptr to point past non-variadic arg - Expression *e1; - Expression *e; -#ifndef IN_GCC - Type *t = argptr->type; - VarDeclaration *p; - unsigned offset; - - e1 = new VarExp(0, argptr); - if (parameters && parameters->dim) - p = (VarDeclaration *)parameters->data[parameters->dim - 1]; - else - p = v_arguments; // last parameter is _arguments[] - offset = p->type->size(); - offset = (offset + 3) & ~3; // assume stack aligns on 4 - e = new SymOffExp(0, p, offset); - e = new AssignExp(0, e1, e); - e->type = t; -#else - v_argptr = argptr; - e = new DeclarationExp(0, argptr); - e->type = Type::tvoid; -#endif - a->push(new ExpStatement(0, e)); - } - - // Merge contracts together with body into one compound statement - - if (frequire && global.params.useIn) - a->push(frequire); - - // Precondition invariant - if (addPreInvariant()) - { - Expression *e = NULL; - if (isDtorDeclaration()) - { - // Call invariant directly only if it exists - InvariantDeclaration *inv = ad->inv; - ClassDeclaration *cd = ad->isClassDeclaration(); - - while (!inv && cd) - { - cd = cd->baseClass; - if (!cd) - break; - inv = cd->inv; - } - if (inv) - { - e = new DsymbolExp(0, ad->inv); - e = new CallExp(0, e); - e = e->semantic(sc2); - } - } - else - { // Call invariant virtually - ThisExp *v = new ThisExp(0); - v->type = vthis->type; - e = new AssertExp(0, v); - } - if (e) - { - ExpStatement *s = new ExpStatement(0, e); - a->push(s); - } - } - - if (fbody) - a->push(fbody); - - if (fensure) - { - a->push(returnLabel->statement); - - if (type->next->ty != Tvoid) - { - // Create: return vresult; - assert(vresult); - Expression *e = new VarExp(0, vresult); - ReturnStatement *s = new ReturnStatement(0, e); - a->push(s); - } - } - - fbody = new CompoundStatement(0, a); - } - - sc2->pop(); - } -} - -void FuncDeclaration::toHBuffer(OutBuffer *buf) -{ - type->toCBuffer(buf, ident); - buf->writeByte(';'); - buf->writenl(); -} - -void FuncDeclaration::toCBuffer(OutBuffer *buf) -{ - type->toCBuffer(buf, ident); - if (fbody) - { buf->writenl(); - fbody->toCBuffer(buf); - } - else - { buf->writeByte(';'); - buf->writenl(); - } -} - -/**************************************************** - * Determine if 'this' overrides fd. - * Return !=0 if it does. - */ - -int FuncDeclaration::overrides(FuncDeclaration *fd) -{ int result = 0; - - if (fd->ident == ident) - { - int cov = type->covariant(fd->type); - if (cov) - { ClassDeclaration *cd1 = toParent()->isClassDeclaration(); - ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration(); - - if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL)) - result = 1; - } - } - return result; -} - -/**************************************************** - * Overload this FuncDeclaration with the new one f. - * Return !=0 if successful; i.e. no conflict. - */ - -int FuncDeclaration::overloadInsert(Dsymbol *s) -{ - FuncDeclaration *f; - AliasDeclaration *a; - - //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars()); - a = s->isAliasDeclaration(); - if (a) - { - if (overnext) - return overnext->overloadInsert(a); - overnext = a; - return TRUE; - } - f = s->isFuncDeclaration(); - if (!f) - return FALSE; - - if (type && f->type && // can be NULL for overloaded constructors - f->type->covariant(type) && - !isFuncAliasDeclaration()) - { - //printf("\tfalse: conflict %s\n", kind()); - return FALSE; - } - - if (overnext) - return overnext->overloadInsert(f); - overnext = f; - //printf("\ttrue: no conflict\n"); - return TRUE; -} - -/******************************************** - * Find function in overload list that exactly matches t. - */ - -FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t) -{ - FuncDeclaration *f; - Declaration *d; - Declaration *next; - - for (d = this; d; d = next) - { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration(); - - if (fa) - { - FuncDeclaration *f2 = fa->funcalias->overloadExactMatch(t); - if (f2) - return f2; - next = fa->overnext; - } - else - { - AliasDeclaration *a = d->isAliasDeclaration(); - - if (a) - { - Dsymbol *s = a->toAlias(); - next = s->isDeclaration(); - if (next == a) - break; - } - else - { - f = d->isFuncDeclaration(); - if (!f) - break; // BUG: should print error message? - if (t->equals(d->type)) - return f; - next = f->overnext; - } - } - } - return NULL; -} - -/******************************************** - * Decide which function matches the arguments best. - */ - -// Recursive helper function - -void overloadResolveX(Match *m, FuncDeclaration *fstart, Array *arguments) -{ - MATCH match; - Declaration *d; - Declaration *next; - - for (d = fstart; d; d = next) - { - FuncDeclaration *f; - FuncAliasDeclaration *fa; - AliasDeclaration *a; - - fa = d->isFuncAliasDeclaration(); - if (fa) - { - overloadResolveX(m, fa->funcalias, arguments); - next = fa->overnext; - } - else if ((f = d->isFuncDeclaration()) != NULL) - { - next = f->overnext; - if (f == m->lastf) - continue; // skip duplicates - else - { - TypeFunction *tf; - - m->anyf = f; - tf = (TypeFunction *)f->type; - match = (MATCH) tf->callMatch(arguments); - //printf("match = %d\n", match); - if (match != MATCHnomatch) - { - if (match > m->last) - goto LfIsBetter; - - if (match < m->last) - goto LlastIsBetter; - - /* See if one of the matches overrides the other. - */ - if (m->lastf->overrides(f)) - goto LlastIsBetter; - else if (f->overrides(m->lastf)) - goto LfIsBetter; - - Lambiguous: - m->nextf = f; - m->count++; - continue; - - LfIsBetter: - m->last = match; - m->lastf = f; - m->count = 1; - continue; - - LlastIsBetter: - continue; - } - } - } - else if ((a = d->isAliasDeclaration()) != NULL) - { - Dsymbol *s = a->toAlias(); - next = s->isDeclaration(); - if (next == a) - break; - if (next == fstart) - break; - } - else - { d->error("is aliased to a function"); - break; - } - } -} - -FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Array *arguments) -{ - TypeFunction *tf; - Match m; - -#if 0 -printf("FuncDeclaration::overloadResolve('%s')\n", toChars()); -if (arguments) -{ int i; - - for (i = 0; i < arguments->dim; i++) - { Expression *arg; - - arg = (Expression *)arguments->data[i]; - assert(arg->type); - printf("\t%s: ", arg->toChars()); - arg->type->print(); - } -} -#endif - - memset(&m, 0, sizeof(m)); - m.last = MATCHnomatch; - overloadResolveX(&m, this, arguments); - - if (m.count == 1) // exactly one match - { - return m.lastf; - } - else - { - OutBuffer buf; - - if (arguments) - { int i; - OutBuffer argbuf; - - for (i = 0; i < arguments->dim; i++) - { Expression *arg; - - arg = (Expression *)arguments->data[i]; - argbuf.reset(); - assert(arg->type); - arg->type->toCBuffer2(&argbuf, NULL); - if (i) - buf.writeByte(','); - buf.write(&argbuf); - } - } - - if (m.last == MATCHnomatch) - { - tf = (TypeFunction *)type; - - error(loc, "%s does not match argument types (%s)", - Argument::argsTypesToChars(tf->arguments, tf->varargs), - buf.toChars()); - return m.anyf; // as long as it's not a FuncAliasDeclaration - } - else - { -#if 1 - TypeFunction *t1 = (TypeFunction *)m.lastf->type; - TypeFunction *t2 = (TypeFunction *)m.nextf->type; - - error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s", - buf.toChars(), - m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->arguments, t1->varargs), - m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->arguments, t2->varargs)); -#else - error(loc, "overloads %s and %s both match argument list for %s", - m.lastf->type->toChars(), - m.nextf->type->toChars(), - m.lastf->toChars()); -#endif - return m.lastf; - } - } -} - -/******************************** - * Labels are in a separate scope, one per function. - */ - -LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident) -{ Dsymbol *s; - - if (!labtab) - labtab = new DsymbolTable(); // guess we need one - - s = labtab->lookup(ident); - if (!s) - { - s = new LabelDsymbol(ident); - labtab->insert(s); - } - return (LabelDsymbol *)s; -} - -AggregateDeclaration *FuncDeclaration::isThis() -{ AggregateDeclaration *ad; - - //printf("+FuncDeclaration::isThis() '%s'\n", toChars()); - ad = NULL; - if ((storage_class & STCstatic) == 0) - { - ad = isMember2(); - } - //printf("-FuncDeclaration::isThis() %p\n", ad); - return ad; -} - -AggregateDeclaration *FuncDeclaration::isMember2() -{ AggregateDeclaration *ad; - - //printf("+FuncDeclaration::isMember2() '%s'\n", toChars()); - ad = NULL; - for (Dsymbol *s = this; s; s = s->parent) - { -//printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind()); - ad = s->isMember(); - if (ad) -{ //printf("test4\n"); - break; -} - if (!s->parent || - (!s->parent->isTemplateInstance())) -{ //printf("test5\n"); - break; -} - } - //printf("-FuncDeclaration::isMember2() %p\n", ad); - return ad; -} - -/***************************************** - * Determine lexical level difference from 'this' to nested function 'fd'. - * Error if this cannot call fd. - * Returns: - * 0 same level - * -1 increase nesting by 1 (fd is nested within 'this') - * >0 decrease nesting by number - */ - -int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd) -{ int level; - FuncDeclaration *thisfd; - Dsymbol *s; - Dsymbol *fdparent; - - fdparent = fd->toParent(); - if (fdparent == this) - return -1; - thisfd = this; - level = 0; - while (fd != thisfd && fdparent != thisfd->toParent()) - { - if (!thisfd || !thisfd->isNested()) - { - error(loc, "cannot access frame of function %s", fd->toChars()); - return 1; - } - s = thisfd->toParent(); - thisfd = s->isFuncDeclaration(); - level++; - } - return level; -} - -void FuncDeclaration::appendExp(Expression *e) -{ Statement *s; - - s = new ExpStatement(0, e); - appendState(s); -} - -void FuncDeclaration::appendState(Statement *s) -{ CompoundStatement *cs; - - if (!fbody) - { Array *a; - - a = new Array(); - fbody = new CompoundStatement(0, a); - } - cs = fbody->isCompoundStatement(); - cs->statements->push(s); -} - - -int FuncDeclaration::isMain() -{ - return ident && strcmp(ident->toChars(), "main") == 0 && - linkage != LINKc && !isMember() && !isNested(); -} - -int FuncDeclaration::isWinMain() -{ - return ident && strcmp(ident->toChars(), "WinMain") == 0 && - linkage != LINKc && !isMember(); -} - -int FuncDeclaration::isDllMain() -{ - return ident && strcmp(ident->toChars(), "DllMain") == 0 && - linkage != LINKc && !isMember(); -} - -int FuncDeclaration::isExport() -{ - return protection == PROTexport; -} - -int FuncDeclaration::isImportedSymbol() -{ - //printf("isImportedSymbol()\n"); - //printf("protection = %d\n", protection); - return (protection == PROTexport) && !fbody; -} - -// Determine if function goes into virtual function pointer table - -int FuncDeclaration::isVirtual() -{ - //printf("FuncDeclaration::isVirtual(%s)\n", toChars()); - //printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd); - return isMember() && - !(isStatic() || protection == PROTprivate || protection == PROTpackage) && - toParent()->isClassDeclaration(); -} - -int FuncDeclaration::isAbstract() -{ - return storage_class & STCabstract && !fbody; -} - -int FuncDeclaration::isCodeseg() -{ - return TRUE; // functions are always in the code segment -} - -// Determine if function needs -// a static frame pointer to its lexically enclosing function - -int FuncDeclaration::isNested() -{ -// if (!toParent()) printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent); - //printf("\ttoParent() = '%s'\n", toParent()->toChars()); - return ((storage_class & STCstatic) == 0) && - (toParent()->isFuncDeclaration() != NULL); -} - -int FuncDeclaration::needThis() -{ - //printf("FuncDeclaration::needThis() '%s'\n", toChars()); - int i = isThis() != NULL; - //printf("\t%d\n", i); - if (!i && isFuncAliasDeclaration()) - i = ((FuncAliasDeclaration *)this)->funcalias->needThis(); - return i; -} - -int FuncDeclaration::addPreInvariant() -{ - AggregateDeclaration *ad = isThis(); - return (ad && - //ad->isClassDeclaration() && - global.params.useInvariants && - (protection == PROTpublic || protection == PROTexport) && - !naked); -} - -int FuncDeclaration::addPostInvariant() -{ - AggregateDeclaration *ad = isThis(); - return (ad && - ad->inv && - //ad->isClassDeclaration() && - global.params.useInvariants && - (protection == PROTpublic || protection == PROTexport) && - !naked); -} - -/********************************** - * Generate a FuncDeclaration for a runtime library function. - */ - -FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name) -{ - FuncDeclaration *fd; - TypeFunction *tf; - Dsymbol *s; - Identifier *id; - static DsymbolTable *st = NULL; - - //printf("genCfunc(name = '%s')\n", name); - //printf("treturn\n\t"); treturn->print(); - - id = Lexer::idPool(name); - - // See if already in table - if (!st) - st = new DsymbolTable(); - s = st->lookup(id); - if (s) - { - fd = s->isFuncDeclaration(); - assert(fd); - assert(fd->type->next->equals(treturn)); - } - else - { - tf = new TypeFunction(NULL, treturn, 0, LINKc); - fd = new FuncDeclaration(0, 0, id, STCstatic, tf); - fd->protection = PROTpublic; - fd->linkage = LINKc; - - st->insert(fd); - } - return fd; -} - -char *FuncDeclaration::kind() -{ - return "function"; -} - -/****************************** FuncAliasDeclaration ************************/ - -// Used as a way to import a set of functions from another scope into this one. - -FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias) - : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident, - (enum STC)funcalias->storage_class, funcalias->type) -{ - assert(funcalias != this); - this->funcalias = funcalias; -} - -char *FuncAliasDeclaration::kind() -{ - return "function alias"; -} - - -/****************************** FuncLiteralDeclaration ************************/ - -FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, - enum TOK tok, ForeachStatement *fes) - : FuncDeclaration(loc, endloc, NULL, STCundefined, type) -{ - char *id; - - if (fes) - id = "__foreachbody"; - else if (tok == TOKdelegate) - id = "__dgliteral"; - else - id = "__funcliteral"; - this->ident = Identifier::generateId(id); - this->tok = tok; - this->fes = fes; - //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars()); -} - -Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s) -{ - FuncLiteralDeclaration *f; - - //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars()); - if (s) - f = (FuncLiteralDeclaration *)s; - else - f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes); - FuncDeclaration::syntaxCopy(f); - return f; -} - -int FuncLiteralDeclaration::isNested() -{ - //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars()); - return (tok == TOKdelegate); -} - -char *FuncLiteralDeclaration::kind() -{ - // GCC requires the (char*) casts - return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function"; -} - - -/********************************* CtorDeclaration ****************************/ - -CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Array *arguments, int varargs) - : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL) -{ - this->arguments = arguments; - this->varargs = varargs; -} - -Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s) -{ - CtorDeclaration *f; - - f = new CtorDeclaration(loc, endloc, NULL, varargs); - - f->outId = outId; - f->frequire = frequire ? frequire->syntaxCopy() : NULL; - f->fensure = fensure ? fensure->syntaxCopy() : NULL; - f->fbody = fbody ? fbody->syntaxCopy() : NULL; - assert(!fthrows); // deprecated - - f->arguments = Argument::arraySyntaxCopy(arguments); - - return f; -} - - -void CtorDeclaration::semantic(Scope *sc) -{ - ClassDeclaration *cd; - Type *tret; - - //printf("CtorDeclaration::semantic()\n"); - - sc = sc->push(); - sc->stc &= ~STCstatic; // not a static constructor - - parent = sc->parent; - Dsymbol *parent = toParent(); - cd = parent->isClassDeclaration(); - if (!cd) - { - error("constructors only are for class definitions"); - tret = Type::tvoid; - } - else - tret = cd->type; //->referenceTo(); - type = new TypeFunction(arguments, tret, varargs, LINKd); - - sc->flags |= SCOPEctor; - type = type->semantic(loc, sc); - sc->flags &= ~SCOPEctor; - - // Append: - // return this; - // to the function body - if (fbody) - { Expression *e; - Statement *s; - - e = new ThisExp(0); - s = new ReturnStatement(0, e); - fbody = new CompoundStatement(0, fbody, s); - } - - FuncDeclaration::semantic(sc); - - sc->pop(); -} - -char *CtorDeclaration::kind() -{ - return "constructor"; -} - -char *CtorDeclaration::toChars() -{ - return "this"; -} - -int CtorDeclaration::isVirtual() -{ - return FALSE; -} - -int CtorDeclaration::addPreInvariant() -{ - return FALSE; -} - -int CtorDeclaration::addPostInvariant() -{ - return (vthis && global.params.useInvariants); -} - - -/********************************* DtorDeclaration ****************************/ - -DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc) - : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL) -{ -} - -Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s) -{ - DtorDeclaration *dd; - - assert(!s); - dd = new DtorDeclaration(loc, endloc); - return FuncDeclaration::syntaxCopy(dd); -} - - -void DtorDeclaration::semantic(Scope *sc) -{ - ClassDeclaration *cd; - Type *tret; - - sc = sc->push(); - sc->stc &= ~STCstatic; // not a static destructor - - parent = sc->parent; - Dsymbol *parent = toParent(); - cd = parent->isClassDeclaration(); - if (!cd) - { - error("destructors only are for class definitions"); - } - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); - - FuncDeclaration::semantic(sc); - - sc->pop(); -} - -int DtorDeclaration::overloadInsert(Dsymbol *s) -{ - return FALSE; // cannot overload destructors -} - -int DtorDeclaration::addPreInvariant() -{ - return (vthis && global.params.useInvariants); -} - -int DtorDeclaration::addPostInvariant() -{ - return FALSE; -} - -/********************************* StaticCtorDeclaration ****************************/ - -StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc) - : FuncDeclaration(loc, endloc, Id::staticCtor, STCstatic, NULL) -{ -} - -Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s) -{ - StaticCtorDeclaration *scd; - - assert(!s); - scd = new StaticCtorDeclaration(loc, endloc); - return FuncDeclaration::syntaxCopy(scd); -} - - -void StaticCtorDeclaration::semantic(Scope *sc) -{ - ClassDeclaration *cd; - Type *tret; - - cd = sc->scopesym->isClassDeclaration(); - if (!cd) - { - } - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); - - FuncDeclaration::semantic(sc); - - // We're going to need ModuleInfo - Module *m = getModule(); - if (!m) - m = sc->module; - if (m) - { m->needmoduleinfo = 1; -#ifdef IN_GCC - m->strictlyneedmoduleinfo = 1; -#endif - } -} - -AggregateDeclaration *StaticCtorDeclaration::isThis() -{ - return NULL; -} - -int StaticCtorDeclaration::isStaticConstructor() -{ - return TRUE; -} - -int StaticCtorDeclaration::isVirtual() -{ - return FALSE; -} - -int StaticCtorDeclaration::addPreInvariant() -{ - return FALSE; -} - -int StaticCtorDeclaration::addPostInvariant() -{ - return FALSE; -} - -/********************************* StaticDtorDeclaration ****************************/ - -StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc) - : FuncDeclaration(loc, endloc, Id::staticDtor, STCstatic, NULL) -{ -} - -Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s) -{ - StaticDtorDeclaration *sdd; - - assert(!s); - sdd = new StaticDtorDeclaration(loc, endloc); - return FuncDeclaration::syntaxCopy(sdd); -} - - -void StaticDtorDeclaration::semantic(Scope *sc) -{ - ClassDeclaration *cd; - Type *tret; - - cd = sc->scopesym->isClassDeclaration(); - if (!cd) - { - } - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); - - FuncDeclaration::semantic(sc); - - // We're going to need ModuleInfo - Module *m = getModule(); - if (!m) - m = sc->module; - if (m) - { m->needmoduleinfo = 1; -#ifdef IN_GCC - m->strictlyneedmoduleinfo = 1; -#endif - } -} - -AggregateDeclaration *StaticDtorDeclaration::isThis() -{ - return NULL; -} - -int StaticDtorDeclaration::isStaticDestructor() -{ - return TRUE; -} - -int StaticDtorDeclaration::isVirtual() -{ - return FALSE; -} - -int StaticDtorDeclaration::addPreInvariant() -{ - return FALSE; -} - -int StaticDtorDeclaration::addPostInvariant() -{ - return FALSE; -} - -/********************************* InvariantDeclaration ****************************/ - -InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc) - : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL) -{ -} - -Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s) -{ - InvariantDeclaration *id; - - assert(!s); - id = new InvariantDeclaration(loc, endloc); - FuncDeclaration::syntaxCopy(id); - return id; -} - - -void InvariantDeclaration::semantic(Scope *sc) -{ - AggregateDeclaration *ad; - Type *tret; - - parent = sc->parent; - Dsymbol *parent = toParent(); - ad = parent->isAggregateDeclaration(); - if (!ad) - { - error("invariants only are for struct/union/class definitions"); - return; - } - else if (ad->inv) - { - error("more than one invariant for %s", ad->toChars()); - } - ad->inv = this; - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); - - sc->incontract++; - FuncDeclaration::semantic(sc); - sc->incontract--; -} - -int InvariantDeclaration::isVirtual() -{ - return FALSE; -} - -int InvariantDeclaration::addPreInvariant() -{ - return FALSE; -} - -int InvariantDeclaration::addPostInvariant() -{ - return FALSE; -} - - -/********************************* UnitTestDeclaration ****************************/ - -/******************************* - * Generate unique unittest function Id so we can have multiple - * instances per module. - */ - -static Identifier *unitTestId() -{ - static int n; - char buffer[8+3*4+1]; - - sprintf(buffer,"__unittest%d", n); - n++; - return Lexer::idPool(buffer); -} - -UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc) - : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL) -{ -} - -Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s) -{ - UnitTestDeclaration *utd; - - assert(!s); - utd = new UnitTestDeclaration(loc, endloc); - return FuncDeclaration::syntaxCopy(utd); -} - - -void UnitTestDeclaration::semantic(Scope *sc) -{ - if (global.params.useUnitTests) - { - Type *tret; - - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); - FuncDeclaration::semantic(sc); - } - - // We're going to need ModuleInfo even if the unit tests are not - // compiled in, because other modules may import this module and refer - // to this ModuleInfo. - Module *m = getModule(); - if (!m) - m = sc->module; - if (m) - m->needmoduleinfo = 1; -} - -AggregateDeclaration *UnitTestDeclaration::isThis() -{ - return NULL; -} - -int UnitTestDeclaration::isVirtual() -{ - return FALSE; -} - -int UnitTestDeclaration::addPreInvariant() -{ - return FALSE; -} - -int UnitTestDeclaration::addPostInvariant() -{ - return FALSE; -} - - -/********************************* NewDeclaration ****************************/ - -NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Array *arguments, int varargs) - : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL) -{ - this->arguments = arguments; - this->varargs = varargs; -} - -Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s) -{ - NewDeclaration *f; - - f = new NewDeclaration(loc, endloc, NULL, varargs); - - FuncDeclaration::syntaxCopy(f); - - f->arguments = Argument::arraySyntaxCopy(arguments); - - return f; -} - - -void NewDeclaration::semantic(Scope *sc) -{ - ClassDeclaration *cd; - Type *tret; - - //printf("NewDeclaration::semantic()\n"); - - parent = sc->parent; - Dsymbol *parent = toParent(); - cd = parent->isClassDeclaration(); - if (!cd && !parent->isStructDeclaration()) - { - error("new allocators only are for class or struct definitions"); - } - tret = Type::tvoid->pointerTo(); - type = new TypeFunction(arguments, tret, varargs, LINKd); - - type = type->semantic(loc, sc); - - // Check that there is at least one argument of type uint - TypeFunction *tf = (TypeFunction *)type; - if (!tf->arguments || tf->arguments->dim < 1) - { - error("at least one argument of type uint expected"); - } - else - { - Argument *a = (Argument *)tf->arguments->data[0]; - if (!a->type->equals(Type::tuns32)) - error("first argument must be type uint, not %s", a->type->toChars()); - } - - FuncDeclaration::semantic(sc); -} - -char *NewDeclaration::kind() -{ - return "allocator"; -} - -int NewDeclaration::isVirtual() -{ - return FALSE; -} - -int NewDeclaration::addPreInvariant() -{ - return FALSE; -} - -int NewDeclaration::addPostInvariant() -{ - return FALSE; -} - - - -/********************************* DeleteDeclaration ****************************/ - -DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Array *arguments) - : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL) -{ - this->arguments = arguments; -} - -Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s) -{ - DeleteDeclaration *f; - - f = new DeleteDeclaration(loc, endloc, NULL); - - FuncDeclaration::syntaxCopy(f); - - f->arguments = Argument::arraySyntaxCopy(arguments); - - return f; -} - - -void DeleteDeclaration::semantic(Scope *sc) -{ - ClassDeclaration *cd; - - //printf("DeleteDeclaration::semantic()\n"); - - parent = sc->parent; - Dsymbol *parent = toParent(); - cd = parent->isClassDeclaration(); - if (!cd && !parent->isStructDeclaration()) - { - error("new allocators only are for class or struct definitions"); - } - type = new TypeFunction(arguments, Type::tvoid, 0, LINKd); - - type = type->semantic(loc, sc); - - // Check that there is only one argument of type void* - TypeFunction *tf = (TypeFunction *)type; - if (!tf->arguments || tf->arguments->dim != 1) - { - error("one argument of type void* expected"); - } - else - { - Argument *a = (Argument *)tf->arguments->data[0]; - if (!a->type->equals(Type::tvoid->pointerTo())) - error("one argument of type void* expected, not %s", a->type->toChars()); - } - - FuncDeclaration::semantic(sc); -} - -char *DeleteDeclaration::kind() -{ - return "deallocator"; -} - -int DeleteDeclaration::isDelete() -{ - return TRUE; -} - -int DeleteDeclaration::isVirtual() -{ - return FALSE; -} - -int DeleteDeclaration::addPreInvariant() -{ - return FALSE; -} - -int DeleteDeclaration::addPostInvariant() -{ - return FALSE; -} - - - - diff -uNr gdc-0.11/d/root/gnuc.c gdc-0.12/d/root/gnuc.c --- gdc-0.11/d/root/gnuc.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/gnuc.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,55 +0,0 @@ - -// Put functions in here missing from gnu C - -#include "gnuc.h" - -int memicmp(const char *s1, const char *s2, int n) -{ - int result = 0; - - for (int i = 0; i < n; i++) - { char c1 = s1[i]; - char c2 = s2[i]; - - result = c1 - c2; - if (result) - { - if ('A' <= c1 && c1 <= 'Z') - c1 += 'a' - 'A'; - if ('A' <= c2 && c2 <= 'Z') - c2 += 'a' - 'A'; - result = c1 - c2; - if (result) - break; - } - } - return result; -} - -int stricmp(const char *s1, const char *s2) -{ - int result = 0; - - for (;;) - { char c1 = *s1; - char c2 = *s2; - - result = c1 - c2; - if (result) - { - if ('A' <= c1 && c1 <= 'Z') - c1 += 'a' - 'A'; - if ('A' <= c2 && c2 <= 'Z') - c2 += 'a' - 'A'; - result = c1 - c2; - if (result) - break; - } - if (!c1) - break; - s1++; - s2++; - } - return result; -} - diff -uNr gdc-0.11/d/root/gnuc.h gdc-0.12/d/root/gnuc.h --- gdc-0.11/d/root/gnuc.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/gnuc.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,8 +0,0 @@ - -#ifndef _GNUC_H -#define _GNUC_H 1 - -int memicmp(const char *s1, const char *s2, int n); -int stricmp(const char *s1, const char *s2); - -#endif diff -uNr gdc-0.11/d/root/gpl.txt gdc-0.12/d/root/gpl.txt --- gdc-0.11/d/root/gpl.txt 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/gpl.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,248 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 1, February 1989 - - Copyright (C) 1989 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The license agreements of most software companies try to keep users -at the mercy of those companies. By contrast, our General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. The -General Public License applies to the Free Software Foundation's -software and to any other program whose authors commit to using it. -You can use it for your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Specifically, the General Public License is designed to make -sure that you have the freedom to give away or sell copies of free -software, that you receive source code or can get it if you want it, -that you can change the software or use pieces of it in new free -programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of a such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must tell them their rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any program or other work which -contains a notice placed by the copyright holder saying it may be -distributed under the terms of this General Public License. The -"Program", below, refers to any such program or work, and a "work based -on the Program" means either the Program or any work containing the -Program or a portion of it, either verbatim or with modifications. Each -licensee is addressed as "you". - - 1. You may copy and distribute verbatim copies of the Program's source -code as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice and -disclaimer of warranty; keep intact all the notices that refer to this -General Public License and to the absence of any warranty; and give any -other recipients of the Program a copy of this General Public License -along with the Program. You may charge a fee for the physical act of -transferring a copy. - - 2. You may modify your copy or copies of the Program or any portion of -it, and copy and distribute such modifications under the terms of Paragraph -1 above, provided that you also do the following: - - a) cause the modified files to carry prominent notices stating that - you changed the files and the date of any change; and - - b) cause the whole of any work that you distribute or publish, that - in whole or in part contains the Program or any part thereof, either - with or without modifications, to be licensed at no charge to all - third parties under the terms of this General Public License (except - that you may choose to grant warranty protection to some or all - third parties, at your option). - - c) If the modified program normally reads commands interactively when - run, you must cause it, when started running for such interactive use - in the simplest and most usual way, to print or display an - announcement including an appropriate copyright notice and a notice - that there is no warranty (or else, saying that you provide a - warranty) and that users may redistribute the program under these - conditions, and telling the user how to view a copy of this General - Public License. - - d) You may charge a fee for the physical act of transferring a - copy, and you may at your option offer warranty protection in - exchange for a fee. - -Mere aggregation of another independent work with the Program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other work under the scope of these terms. - - 3. You may copy and distribute the Program (or a portion or derivative of -it, under Paragraph 2) in object code or executable form under the terms of -Paragraphs 1 and 2 above provided that you also do one of the following: - - a) accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of - Paragraphs 1 and 2 above; or, - - b) accompany it with a written offer, valid for at least three - years, to give any third party free (except for a nominal charge - for the cost of distribution) a complete machine-readable copy of the - corresponding source code, to be distributed under the terms of - Paragraphs 1 and 2 above; or, - - c) accompany it with the information you received as to where the - corresponding source code may be obtained. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form alone.) - -Source code for a work means the preferred form of the work for making -modifications to it. For an executable file, complete source code means -all the source code for all modules it contains; but, as a special -exception, it need not include source code for modules which are standard -libraries that accompany the operating system on which the executable -file runs, or for standard header files or definitions files that -accompany that operating system. - - 4. You may not copy, modify, sublicense, distribute or transfer the -Program except as expressly provided under this General Public License. -Any attempt otherwise to copy, modify, sublicense, distribute or transfer -the Program is void, and will automatically terminate your rights to use -the Program under this License. However, parties who have received -copies, or rights to use copies, from you under this General Public -License will not have their licenses terminated so long as such parties -remain in full compliance. - - 5. By copying, distributing or modifying the Program (or any work based -on the Program) you indicate your acceptance of this license to do so, -and all its terms and conditions. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the original -licensor to copy, distribute or modify the Program subject to these -terms and conditions. You may not impose any further restrictions on the -recipients' exercise of the rights granted herein. - - 7. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of the license which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -the license, you may choose any version ever published by the Free Software -Foundation. - - 8. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to humanity, the best way to achieve this is to make it -free software which everyone can redistribute and change under these -terms. - - To do so, attach the following notices to the program. It is safest to -attach them to the start of each source file to most effectively convey -the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19xx name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the -appropriate parts of the General Public License. Of course, the -commands you use may be called something other than `show w' and `show -c'; they could even be mouse-clicks or menu items--whatever suits your -program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - program `Gnomovision' (a program to direct compilers to make passes - at assemblers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -That's all there is to it! diff -uNr gdc-0.11/d/root/html.c gdc-0.12/d/root/html.c --- gdc-0.11/d/root/html.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/html.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,731 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 - Modified by Thomas Kuehne, November 2004 -*/ - -/* HTML parser - */ - -#include -#include -#include -#include -#include -#include - -#include "mars.h" -#include "html.h" - -#include -#include "root.h" -//#include "../mars/mars.h" - -//#if __GNUC__ -//int memicmp(const char *s1, const char *s2, int n); -//#endif - -extern int HtmlNamedEntity(unsigned char *p, int length); - -/********************************** - * Determine if beginning of tag identifier - * or a continuation of a tag identifier. - */ - -inline int istagstart(int c) -{ - return (isalpha(c) || c == '_' || c == '!'); -} - -inline int istag(int c) -{ - return (isalnum(c) || c == '_'); -} - -/** - * identify DOS, Linux, Mac, Next and Unicode line endings - * 0 if this is no line seperator - * >0 the length of the seperator - * Note: input has to be UTF-8 - */ -static int isLineSeperator(const unsigned char* p){ - // Linux - if( p[0]=='\n'){ - return 1; - } - - // Mac & Dos - if( p[0]=='\r'){ - return (p[1]=='\n') ? 2 : 1; - } - - // Unicode (line || paragarph sep.) - if( p[0]==0xE2 && p[1]==0x80 && (p[2]==0xA8 || p[2]==0xA9)){ - return 3; - } - - // Next - if( p[0]==0xC2 && p[1]==0x85){ - return 2; - } - - return 0; -} - -/********************************************** - */ - -Html::Html(const char *sourcename, unsigned char *base, unsigned length) -{ - this->sourcename = sourcename; - this->base = base; - p = base; - end = base + length; - linnum = 0; - dbuf = NULL; - inCode = 0; -} - -/********************************************** - * Print error & quit. - */ - -void Html::error(const char *format, ...) -{ - printf("%s:%d: HTML Error: ", sourcename, linnum); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); - - global.errors++; - fatal(); -} - -/********************************************** - * Extract all the code from an HTML file, - * concatenate it all together, and store in buf. - */ - -void Html::extractCode(OutBuffer *buf) -{ - //printf("Html::extractCode()\n"); - dbuf = buf; // save for other routines - buf->reserve(end - p); - inCode = 0; - while (1) - { - //printf("p = %p, *p = x%x\n", p, *p); - switch (*p) - { -#if 0 // strings are not recognized outside of tags - case '"': - case '\'': - skipString(); - continue; - */ -#endif - case '<': - //-OLDOLDREMOVE// if (p[1] == '!' && p[2] == '-' && p[3] == '-') - if (p[1] == '!' && isCommentStart()) - { // Comments start with - * Netscape: comments nest - * w3c: whitespace can appear between -- and > of comment close - */ - -void Html::scanComment() -{ - // Most of the complexity is dealing with the case that - // an arbitrary amount of whitespace can appear between - // the -- and the > of a comment close. - int scangt = 0; - - //printf("scanComment()\n"); - while (1) - { - //scangt = 1; // IE 5.0 compatibility - p++; - switch (*p) - { - case '-': - if (p[1] == '-') - { - if (p[2] == '>') // optimize for most common case - { - p += 3; - break; - } - p++; - scangt = 1; - } - else - scangt = 0; - continue; - - case '>': - if (scangt) - { // found --> - p++; - break; - } - continue; - - case ' ': - case '\t': - case '\f': - case '\v': - // skip white space - continue; - - /* all handled by isLineSeparator - case '\r': - if (p[1] == '\n') - goto Ldefault; - case '\n': - linnum++; // remember to count lines - // Always extract new lines, so that D lexer counts the - // lines right. - dbuf->writeByte(*p); - continue; - */ - - case 0: - case 0x1a: - error("end of file before closing --> of comment"); - break; - - default: - // Ldefault: - int lineSepLength = isLineSeperator(p); - if( lineSepLength>0 ){ - linnum++; // remember to count lines - // Always extract new lines, so that D lexer counts - // the lines right. - dbuf->writeByte('\n'); // BUG: wchar - p+=lineSepLength-1; - continue; - } - scangt = 0; // it's not --> - continue; - } - break; - } - //printf("*p = '%c'\n", *p); -} - - /******************************************** - * Determine if we are at the start of a comment. - * Input: - * p is on the opening '<' - * Returns: - * 0 if not start of a comment - * 1 if start of a comment, p is adjusted to point past -- - */ - -int Html::isCommentStart() -#ifdef __DMC__ - __out(result) - { - if (result == 0) - ; - else if (result == 1) - { - assert(p[-2] == '-' && p[-1] == '-'); - } - else - assert(0); - } - __body -#endif /* __DMC__ */ - { unsigned char *s; - - if (p[0] == '<' && p[1] == '!') - { - for (s = p + 2; 1; s++) - { - switch (*s) - { - case ' ': - case '\t': - case '\r': - case '\f': - case '\v': - // skip white space, even though spec says no - // white space is allowed - continue; - - case '-': - if (s[1] == '-') - { - p = s + 2; - return 1; - } - goto No; - - default: - goto No; - } - } - } - No: - return 0; - } - -/******************************************** - * Convert an HTML character entity into a character. - * Forms are: - * &name; named entity - * &#ddd; decimal - * &#xhhhh; hex - * Input: - * p is on the & - */ - -int Html::charEntity() -{ int c = 0; - int v; - int hex; - unsigned char *pstart = p; - - //printf("Html::charEntity('%c')\n", *p); - if (p[1] == '#') - { - p++; - if (p[1] == 'x' || p[1] == 'X') - { p++; - hex = 1; - } - else - hex = 0; - - if (p[1] == ';') - goto Linvalid; - while (1) - { - p++; - switch (*p) - { - case 0: - case 0x1a: - error("end of file before end of character entity"); - goto Lignore; - - case '\n': - case '\r': - case '<': // tag start - // Termination is assumed - break; - - case ';': - // Termination is explicit - p++; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - v = *p - '0'; - goto Lvalue; - - case 'a': case 'b': case 'c': - case 'd': case 'e': case 'f': - if (!hex) - goto Linvalid; - v = (*p - 'a') + 10; - goto Lvalue; - - case 'A': case 'B': case 'C': - case 'D': case 'E': case 'F': - if (!hex) - goto Linvalid; - v = (*p - 'A') + 10; - goto Lvalue; - - Lvalue: - if (hex) - c = (c << 4) + v; - else - c = (c * 10) + v; - if (c > 0x10FFFF) - { - error("character entity out of range"); - goto Lignore; - } - continue; - - default: - Linvalid: - error("invalid numeric character reference"); - goto Lignore; - } - break; - } - } - else - { - // It's a named entity; gather all characters until ; - unsigned char *idstart = p + 1; - - while (1) - { - p++; - switch (*p) - { - case 0: - case 0x1a: - error("end of file before end of character entity"); - break; - - case '\n': - case '\r': - case '<': // tag start - // Termination is assumed - c = HtmlNamedEntity(idstart, p - idstart); - if (c == -1) - goto Lignore; - break; - - case ';': - // Termination is explicit - c = HtmlNamedEntity(idstart, p - idstart); - if (c == -1) - goto Lignore; - p++; - break; - - default: - continue; - } - break; - } - } - - // Kludge to convert non-breaking space to ascii space - if (c == 160) - c = 32; - return c; -Lignore: - //printf("Lignore\n"); - p = pstart + 1; - return '&'; -} - diff -uNr gdc-0.11/d/root/html.h gdc-0.12/d/root/html.h --- gdc-0.11/d/root/html.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/html.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,35 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -struct OutBuffer; - -struct Html -{ - const char *sourcename; - - unsigned char *base; // pointer to start of buffer - unsigned char *end; // past end of buffer - unsigned char *p; // current character - unsigned linnum; // current line number - OutBuffer *dbuf; // code source buffer - int inCode; // !=0 if in code - - - Html(const char *sourcename, unsigned char *base, unsigned length); - - void error(const char *format, ...); - void extractCode(OutBuffer *buf); - void skipTag(); - void skipString(); - unsigned char *skipWhite(unsigned char *q); - void scanComment(); - int isCommentStart(); - int charEntity(); - static int namedEntity(unsigned char *p, int length); -}; diff -uNr gdc-0.11/d/root/identifier.c gdc-0.12/d/root/identifier.c --- gdc-0.11/d/root/identifier.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/identifier.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,67 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "root.h" -#include "identifier.h" -#include "mars.h" -#include "lexer.h" - -Identifier::Identifier(const char *string, int value) -{ - //printf("Identifier('%s', %d)\n", string, value); - this->string = string; - this->value = value; - this->len = strlen(string); -} - -unsigned Identifier::hashCode() -{ - return String::calcHash(string); -} - -int Identifier::equals(Object *o) -{ - return this == o || memcmp(string,o->toChars(),len+1) == 0; -} - -int Identifier::compare(Object *o) -{ - return memcmp(string, o->toChars(), len + 1); -} - -char *Identifier::toChars() -{ - return (char *)string; -} - -void Identifier::print() -{ - printf("%s",string); -} - -int Identifier::dyncast() -{ - return DYNCAST_IDENTIFIER; -} - -Identifier *Identifier::generateId(char *prefix) -{ OutBuffer buf; - char *id; - static unsigned i; - - buf.writestring(prefix); - buf.printf("%u", ++i); - - id = buf.toChars(); - buf.data = NULL; - return new Identifier(id, TOKidentifier); -} diff -uNr gdc-0.11/d/root/identifier.h gdc-0.12/d/root/identifier.h --- gdc-0.11/d/root/identifier.h 2005-01-10 04:30:55.000000000 +0100 +++ gdc-0.12/d/root/identifier.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,36 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_IDENTIFIER_H -#define DMD_IDENTIFIER_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" - -struct Identifier : Object -{ - int value; - const char *string; - unsigned len; - - Identifier(const char *string, int value); - int equals(Object *o); - unsigned hashCode(); - int compare(Object *o); - void print(); - char *toChars(); - int dyncast(); - - static Identifier *generateId(char *prefix); -}; - -#endif /* DMD_IDENTIFIER_H */ diff -uNr gdc-0.11/d/root/idgen.c gdc-0.12/d/root/idgen.c --- gdc-0.11/d/root/idgen.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/idgen.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,258 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -// Program to generate string files in d data structures. -// Saves much tedious typing, and eliminates typo problems. -// Generates: -// id.h -// id.c - -#include -#include -#include -#include -#include - -struct Msgtable -{ - char *ident; // name to use in DMD source - char *name; // name in D executable -}; - -Msgtable msgtable[] = -{ - { "IUnknown" }, - { "Object" }, - { "object" }, - { "max" }, - { "min" }, - { "This", "this" }, - { "ctor", "_ctor" }, - { "dtor", "_dtor" }, - { "classInvariant", "__invariant" }, - { "unitTest", "_unitTest" }, - { "staticCtor", "_staticCtor" }, - { "staticDtor", "_staticDtor" }, - { "init" }, - { "size" }, - { "__sizeof", "sizeof" }, - { "alignof" }, - { "length" }, - { "ptr" }, - { "dollar", "__dollar" }, - { "offset" }, - { "offsetof" }, - { "ModuleInfo" }, - { "ClassInfo" }, - { "classinfo" }, - { "typeinfo" }, - { "Exception" }, - { "withSym", "__withSym" }, - { "result", "__result" }, - { "returnLabel", "__returnLabel" }, - { "delegate" }, - { "line" }, - { "empty", "" }, - { "p" }, - - { "TypeInfo" }, - { "TypeInfo_Class" }, - { "TypeInfo_Struct" }, - { "TypeInfo_Enum" }, - { "TypeInfo_Typedef" }, - { "TypeInfo_Pointer" }, - { "TypeInfo_Array" }, - { "TypeInfo_StaticArray" }, - { "TypeInfo_AssociativeArray" }, - { "TypeInfo_Function" }, - { "TypeInfo_Delegate" }, - { "_arguments" }, - { "_argptr" }, - - { "LINE", "__LINE__" }, - { "FILE", "__FILE__" }, - { "DATE", "__DATE__" }, - { "TIME", "__TIME__" }, - { "TIMESTAMP", "__TIMESTAMP__" }, - - { "nan" }, - { "infinity" }, - { "dig" }, - { "epsilon" }, - { "mant_dig" }, - { "max_10_exp" }, - { "max_exp" }, - { "min_10_exp" }, - { "min_exp" }, - { "re" }, - { "im" }, - - { "C" }, - { "D" }, - { "Windows" }, - { "Pascal" }, - - { "keys" }, - { "values" }, - { "rehash" }, - - { "sort" }, - { "reverse" }, - { "dup" }, - - // For inline assembler - { "___out", "out" }, - { "___in", "in" }, - { "__int", "int" }, - { "__dollar", "$" }, - { "__LOCAL_SIZE" }, - - // For operator overloads - { "uadd", "opPos" }, - { "neg", "opNeg" }, - { "com", "opCom" }, - { "add", "opAdd" }, - { "add_r", "opAdd_r" }, - { "sub", "opSub" }, - { "sub_r", "opSub_r" }, - { "mul", "opMul" }, - { "mul_r", "opMul_r" }, - { "div", "opDiv" }, - { "div_r", "opDiv_r" }, - { "mod", "opMod" }, - { "mod_r", "opMod_r" }, - { "eq", "opEquals" }, - { "cmp", "opCmp" }, - { "iand", "opAnd" }, - { "iand_r", "opAnd_r" }, - { "ior", "opOr" }, - { "ior_r", "opOr_r" }, - { "ixor", "opXor" }, - { "ixor_r", "opXor_r" }, - { "shl", "opShl" }, - { "shl_r", "opShl_r" }, - { "shr", "opShr" }, - { "shr_r", "opShr_r" }, - { "ushr", "opUShr" }, - { "ushr_r", "opUShr_r" }, - { "cat", "opCat" }, - { "cat_r", "opCat_r" }, - { "addass", "opAddAssign" }, - { "subass", "opSubAssign" }, - { "mulass", "opMulAssign" }, - { "divass", "opDivAssign" }, - { "modass", "opModAssign" }, - { "andass", "opAndAssign" }, - { "orass", "opOrAssign" }, - { "xorass", "opXorAssign" }, - { "shlass", "opShlAssign" }, - { "shrass", "opShrAssign" }, - { "ushrass", "opUShrAssign" }, - { "catass", "opCatAssign" }, - { "postinc", "opPostInc" }, - { "postdec", "opPostDec" }, - { "index", "opIndex" }, - { "indexass", "opIndexAssign" }, - { "slice", "opSlice" }, - { "call", "opCall" }, - { "cast", "opCast" }, - - { "classNew", "new" }, - { "classDelete", "delete" }, - - // For foreach - { "apply", "opApply" }, - - // For pragma's - { "lib" }, - { "msg" }, - - // For toHash - { "tohash", "toHash" }, - - // Special functions - { "alloca" }, -}; - - -int main() -{ - FILE *fp; - unsigned i; - - { - fp = fopen("id.h","w"); - if (!fp) - { printf("can't open id.h\n"); - exit(EXIT_FAILURE); - } - - fprintf(fp, "// File generated by idgen.c\n"); -#if __DMC__ - fprintf(fp, "#pragma once\n"); -#endif - fprintf(fp, "#ifndef DMD_ID_H\n"); - fprintf(fp, "#define DMD_ID_H 1\n"); - fprintf(fp, "struct Identifier;\n"); - fprintf(fp, "struct Id\n"); - fprintf(fp, "{\n"); - - for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++) - { char *id = msgtable[i].ident; - - fprintf(fp," static Identifier *%s;\n", id); - } - - fprintf(fp, " static void initialize();\n"); - fprintf(fp, "};\n"); - fprintf(fp, "#endif\n"); - - fclose(fp); - } - - { - fp = fopen("id.c","w"); - if (!fp) - { printf("can't open id.c\n"); - exit(EXIT_FAILURE); - } - - fprintf(fp, "// File generated by idgen.c\n"); - fprintf(fp, "#include \"id.h\"\n"); - fprintf(fp, "#include \"identifier.h\"\n"); - fprintf(fp, "#include \"lexer.h\"\n"); - - for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++) - { char *id = msgtable[i].ident; - char *p = msgtable[i].name; - - if (!p) - p = id; - fprintf(fp,"Identifier *Id::%s;\n", id); - } - - fprintf(fp, "void Id::initialize()\n"); - fprintf(fp, "{\n"); - - for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++) - { char *id = msgtable[i].ident; - char *p = msgtable[i].name; - - if (!p) - p = id; - fprintf(fp," %s = Lexer::idPool(\"%s\");\n", id, p); - } - - fprintf(fp, "}\n"); - - fclose(fp); - } - - return EXIT_SUCCESS; -} diff -uNr gdc-0.11/d/root/impcnvgen.c gdc-0.12/d/root/impcnvgen.c --- gdc-0.11/d/root/impcnvgen.c 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/root/impcnvgen.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,417 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "mtype.h" - -enum TY impcnvResult[TMAX][TMAX]; -enum TY impcnvType1[TMAX][TMAX]; -enum TY impcnvType2[TMAX][TMAX]; -int impcnvWarn[TMAX][TMAX]; - -int integral_promotion(int t) -{ - switch (t) - { - case Tchar: - case Twchar: - case Tbit: - case Tint8: - case Tuns8: - case Tint16: - case Tuns16: return Tint32; - case Tdchar: return Tuns32; - default: return t; - } -} - -void init() -{ int i, j; - - // Set conversion tables - for (i = 0; i < TMAX; i++) - for (j = 0; j < TMAX; j++) - { impcnvResult[i][j] = Terror; - impcnvType1[i][j] = Terror; - impcnvType2[i][j] = Terror; - impcnvWarn[i][j] = 0; - } - -#define X(t1,t2, nt1,nt2, rt) \ - impcnvResult[t1][t2] = rt; \ - impcnvType1[t1][t2] = nt1; \ - impcnvType2[t1][t2] = nt2; - - /* ======================= */ - - X(Tbit,Tbit, Tint32,Tint32, Tint32) - X(Tbit,Tint8, Tint32,Tint32, Tint32) - X(Tbit,Tuns8, Tint32,Tint32, Tint32) - X(Tbit,Tint16, Tint32,Tint32, Tint32) - X(Tbit,Tuns16, Tint32,Tint32, Tint32) - X(Tbit,Tint32, Tint32,Tint32, Tint32) - X(Tbit,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tbit,Tint64, Tint64,Tint64, Tint64) - X(Tbit,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tbit,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tbit,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tbit,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tbit,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tbit,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tbit,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tbit,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tbit,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tbit,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tint8,Tint8, Tint32,Tint32, Tint32) - X(Tint8,Tuns8, Tint32,Tint32, Tint32) - X(Tint8,Tint16, Tint32,Tint32, Tint32) - X(Tint8,Tuns16, Tint32,Tint32, Tint32) - X(Tint8,Tint32, Tint32,Tint32, Tint32) - X(Tint8,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tint8,Tint64, Tint64,Tint64, Tint64) - X(Tint8,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tint8,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tint8,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tint8,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tint8,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tint8,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tint8,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tint8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tint8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tint8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tuns8,Tuns8, Tint32,Tint32, Tint32) - X(Tuns8,Tint16, Tint32,Tint32, Tint32) - X(Tuns8,Tuns16, Tint32,Tint32, Tint32) - X(Tuns8,Tint32, Tint32,Tint32, Tint32) - X(Tuns8,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tuns8,Tint64, Tint64,Tint64, Tint64) - X(Tuns8,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tuns8,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tuns8,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tuns8,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tuns8,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tuns8,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tuns8,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tuns8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tuns8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tuns8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tint16,Tint16, Tint32,Tint32, Tint32) - X(Tint16,Tuns16, Tint32,Tint32, Tint32) - X(Tint16,Tint32, Tint32,Tint32, Tint32) - X(Tint16,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tint16,Tint64, Tint64,Tint64, Tint64) - X(Tint16,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tint16,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tint16,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tint16,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tint16,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tint16,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tint16,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tint16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tint16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tint16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tuns16,Tuns16, Tint32,Tint32, Tint32) - X(Tuns16,Tint32, Tint32,Tint32, Tint32) - X(Tuns16,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tuns16,Tint64, Tint64,Tint64, Tint64) - X(Tuns16,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tuns16,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tuns16,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tuns16,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tuns16,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tuns16,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tuns16,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tuns16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tuns16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tuns16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tint32,Tint32, Tint32,Tint32, Tint32) - X(Tint32,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tint32,Tint64, Tint64,Tint64, Tint64) - X(Tint32,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tint32,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tint32,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tint32,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tint32,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tint32,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tint32,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tint32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tint32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tint32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tuns32,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tuns32,Tint64, Tint64,Tint64, Tint64) - X(Tuns32,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tuns32,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tuns32,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tuns32,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tuns32,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tuns32,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tuns32,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tuns32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tuns32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tuns32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tint64,Tint64, Tint64,Tint64, Tint64) - X(Tint64,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tint64,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tint64,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tint64,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tint64,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tint64,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tint64,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tint64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tint64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tint64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tuns64,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tuns64,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tuns64,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tuns64,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tuns64,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tuns64,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tuns64,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tuns64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tuns64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tuns64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tfloat32,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tfloat32,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tfloat32,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - - X(Tfloat32,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tfloat32,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tfloat32,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - - X(Tfloat32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tfloat32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tfloat32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tfloat64,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tfloat64,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - - X(Tfloat64,Timaginary32, Tfloat64,Timaginary64, Tfloat64) - X(Tfloat64,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tfloat64,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - - X(Tfloat64,Tcomplex32, Tfloat64,Tcomplex64, Tcomplex64) - X(Tfloat64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tfloat64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tfloat80,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - - X(Tfloat80,Timaginary32, Tfloat80,Timaginary80, Tfloat80) - X(Tfloat80,Timaginary64, Tfloat80,Timaginary80, Tfloat80) - X(Tfloat80,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - - X(Tfloat80,Tcomplex32, Tfloat80,Tcomplex80, Tcomplex80) - X(Tfloat80,Tcomplex64, Tfloat80,Tcomplex80, Tcomplex80) - X(Tfloat80,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Timaginary32,Timaginary32, Timaginary32,Timaginary32, Timaginary32) - X(Timaginary32,Timaginary64, Timaginary64,Timaginary64, Timaginary64) - X(Timaginary32,Timaginary80, Timaginary80,Timaginary80, Timaginary80) - - X(Timaginary32,Tcomplex32, Timaginary32,Tcomplex32, Tcomplex32) - X(Timaginary32,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64) - X(Timaginary32,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Timaginary64,Timaginary64, Timaginary64,Timaginary64, Timaginary64) - X(Timaginary64,Timaginary80, Timaginary80,Timaginary80, Timaginary80) - - X(Timaginary64,Tcomplex32, Timaginary64,Tcomplex64, Tcomplex64) - X(Timaginary64,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64) - X(Timaginary64,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Timaginary80,Timaginary80, Timaginary80,Timaginary80, Timaginary80) - - X(Timaginary80,Tcomplex32, Timaginary80,Tcomplex80, Tcomplex80) - X(Timaginary80,Tcomplex64, Timaginary80,Tcomplex80, Tcomplex80) - X(Timaginary80,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tcomplex32,Tcomplex32, Tcomplex32,Tcomplex32, Tcomplex32) - X(Tcomplex32,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64) - X(Tcomplex32,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tcomplex64,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64) - X(Tcomplex64,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tcomplex80,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80) - -#undef X - -#define Y(t1,t2) impcnvWarn[t1][t2] = 1; - Y(Tint8, Tbit) - Y(Tuns8, Tbit) - Y(Tint16, Tbit) - Y(Tuns16, Tbit) - Y(Tint32, Tbit) - Y(Tuns32, Tbit) - Y(Tint64, Tbit) - Y(Tuns64, Tbit) - - Y(Tuns8, Tint8) - Y(Tint16, Tint8) - Y(Tuns16, Tint8) - Y(Tint32, Tint8) - Y(Tuns32, Tint8) - Y(Tint64, Tint8) - Y(Tuns64, Tint8) - - Y(Tint8, Tuns8) - Y(Tint16, Tuns8) - Y(Tuns16, Tuns8) - Y(Tint32, Tuns8) - Y(Tuns32, Tuns8) - Y(Tint64, Tuns8) - Y(Tuns64, Tuns8) - - Y(Tuns16, Tint16) - Y(Tint32, Tint16) - Y(Tuns32, Tint16) - Y(Tint64, Tint16) - Y(Tuns64, Tint16) - - Y(Tint16, Tuns16) - Y(Tint32, Tuns16) - Y(Tuns32, Tuns16) - Y(Tint64, Tuns16) - Y(Tuns64, Tuns16) - -// Y(Tuns32, Tint32) - Y(Tint64, Tint32) - Y(Tuns64, Tint32) - -// Y(Tint32, Tuns32) - Y(Tint64, Tuns32) - Y(Tuns64, Tuns32) - - Y(Tint64, Tuns64) - Y(Tuns64, Tint64) - - for (i = 0; i < TMAX; i++) - for (j = 0; j < TMAX; j++) - { - if (impcnvResult[i][j] == Terror) - { - impcnvResult[i][j] = impcnvResult[j][i]; - impcnvType1[i][j] = impcnvType2[j][i]; - impcnvType2[i][j] = impcnvType1[j][i]; - } - } -} - -int main() -{ FILE *fp; - int i; - int j; - - init(); - - fp = fopen("impcnvtab.c","w"); - - fprintf(fp,"// This file is generated by impcnvgen.c\n"); - fprintf(fp,"#include \"mtype.h\"\n"); - - fprintf(fp,"unsigned char Type::impcnvResult[TMAX][TMAX] =\n{\n"); - for (i = 0; i < TMAX; i++) - { - for (j = 0; j < TMAX; j++) - { - fprintf(fp, "%d,",impcnvResult[i][j]); - } - fprintf(fp, "\n"); - } - fprintf(fp,"};\n"); - - fprintf(fp,"unsigned char Type::impcnvType1[TMAX][TMAX] =\n{\n"); - for (i = 0; i < TMAX; i++) - { - for (j = 0; j < TMAX; j++) - { - fprintf(fp, "%d,",impcnvType1[i][j]); - } - fprintf(fp, "\n"); - } - fprintf(fp,"};\n"); - - fprintf(fp,"unsigned char Type::impcnvType2[TMAX][TMAX] =\n{\n"); - for (i = 0; i < TMAX; i++) - { - for (j = 0; j < TMAX; j++) - { - fprintf(fp, "%d,",impcnvType2[i][j]); - } - fprintf(fp, "\n"); - } - fprintf(fp,"};\n"); - - fprintf(fp,"unsigned char Type::impcnvWarn[TMAX][TMAX] =\n{\n"); - for (i = 0; i < TMAX; i++) - { - for (j = 0; j < TMAX; j++) - { - fprintf(fp, "%d,",impcnvWarn[i][j]); - } - fprintf(fp, "\n"); - } - fprintf(fp,"};\n"); - - fclose(fp); - return EXIT_SUCCESS; -} diff -uNr gdc-0.11/d/root/import.c gdc-0.12/d/root/import.c --- gdc-0.11/d/root/import.c 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/root/import.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,128 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "root.h" -#include "dsymbol.h" -#include "import.h" -#include "identifier.h" -#include "module.h" -#include "scope.h" - -/********************************* Import ****************************/ - -Import::Import(Loc loc, Array *packages, Identifier *id) - : Dsymbol(id) -{ - this->loc = loc; - this->packages = packages; - this->id = id; - pkg = NULL; - mod = NULL; - - // Kludge to change Import identifier to first package - if (packages && packages->dim) - this->ident = (Identifier *)packages->data[0]; -} - -char *Import::kind() -{ - return "import"; -} - - -Dsymbol *Import::syntaxCopy(Dsymbol *s) -{ - assert(!s); - - Import *si; - - si = new Import(loc, packages, id); - return si; -} - - -void Import::semantic(Scope *sc) -{ - DsymbolTable *dst; - Dsymbol *s; - - //printf("Import::semantic('%s')\n", toChars()); - - // See if existing module - dst = Package::resolve(packages, NULL, &pkg); - - s = dst->lookup(id); - if (s && !s->isModule()) - error("package and module have the same name"); - else - { - mod = (Module *)s; - if (!mod) - { - // Load module - mod = Module::load(loc, packages, id); - mod->importedFrom = sc->module->importedFrom; - dst->insert(id, mod); // id may be different from mod->ident, - // if so then insert alias - } - mod->semantic(); - //printf("import '%s', protection = %d for '%s'\n", toChars(), sc->protection, mod->toChars()); - sc->scopesym->importScope(mod, sc->protection); - - // Modules need a list of each imported module - sc->module->aimports.push(mod); - - if (mod->needmoduleinfo) - sc->module->needmoduleinfo = 1; - } - if (!pkg) - pkg = mod; - -// if (sc->module) -// sc->module->needmoduleinfo = 1; -} - -void Import::semantic2(Scope *sc) -{ - mod->semantic2(); - if (mod->needmoduleinfo) - sc->module->needmoduleinfo = 1; -} - -Dsymbol *Import::search(Identifier *ident, int flags) -{ - // Forward it to the package/module - return pkg->search(ident, flags); -} - -int Import::overloadInsert(Dsymbol *s) -{ - // Allow multiple imports of the same name - return s->isImport() != NULL; -} - -void Import::toCBuffer(OutBuffer *buf) -{ - buf->writestring("import "); - if (packages && packages->dim) - { int i; - - for (i = 0; i < packages->dim; i++) - { Identifier *pid = (Identifier *)packages->data[i]; - - buf->printf("%s.", pid->toChars()); - } - } - buf->printf("%s;", id->toChars()); - buf->writenl(); -} - diff -uNr gdc-0.11/d/root/import.h gdc-0.12/d/root/import.h --- gdc-0.11/d/root/import.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/import.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,45 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_IMPORT_H -#define DMD_IMPORT_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "dsymbol.h" - - -struct Identifier; -struct Scope; -struct OutBuffer; -struct Module; -struct Package; - -struct Import : Dsymbol -{ - Module *mod; - Package *pkg; // leftmost package/module - Array *packages; // array of Identifier's representing packages - Identifier *id; // module Identifier - - Import(Loc loc, Array *packages, Identifier *id); - char *kind(); - Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees - void semantic(Scope *sc); - void semantic2(Scope *sc); - Dsymbol *search(Identifier *ident, int flags); - int overloadInsert(Dsymbol *s); - void toCBuffer(OutBuffer *buf); - - Import *isImport() { return this; } -}; - -#endif /* DMD_IMPORT_H */ diff -uNr gdc-0.11/d/root/inifile.c gdc-0.12/d/root/inifile.c --- gdc-0.11/d/root/inifile.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/inifile.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,233 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com - - -#include -#include -#include -#include - -#include "root.h" - -#define LOG 0 - -char *skipspace(const char *p); - -#if __GNUC__ -char *strupr(char *s) -{ - char *t = s; - - while (*s) - { - *s = toupper(*s); - s++; - } - - return t; -} -#endif /* unix */ - -/***************************** - * Read and analyze .ini file. - * Input: - * argv0 program name (argv[0]) - * inifile .ini file name - */ - -void inifile(char *argv0, char *inifile) -{ - char *path; // need path for @P macro - char *filename; - OutBuffer buf; - int i; - int k; - int envsection = 0; - -#if LOG - printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile); -#endif - if (FileName::absolute(inifile)) - { - path = ""; - filename = inifile; - } - else - { - path = FileName::path(argv0); - filename = FileName::replaceName(argv0, inifile); - -#if LOG - printf("\tpath = '%s', filename = '%s'\n", path, filename); -#endif - } - - File file(filename); - - if (file.read()) - return; // error reading file - - // Parse into lines - int eof = 0; - for (i = 0; i < file.len && !eof; i++) - { - int linestart = i; - - for (; i < file.len; i++) - { - switch (file.buffer[i]) - { - case '\r': - break; - - case '\n': - // Skip if it was preceded by '\r' - if (i && file.buffer[i - 1] == '\r') - goto Lskip; - break; - - case 0: - case 0x1A: - eof = 1; - break; - - default: - continue; - } - break; - } - - // The line is file.buffer[linestart..i] - char *line; - int len; - char *p; - char *pn; - - line = (char *)&file.buffer[linestart]; - len = i - linestart; - - buf.reset(); - - // First, expand the macros. - // Macros are bracketed by % characters. - - for (k = 0; k < len; k++) - { - if (line[k] == '%') - { - int j; - - for (j = k + 1; j < len; j++) - { - if (line[j] == '%') - { - if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0) - { - // %@P% is special meaning the path to the .ini file - p = path; - } - else - { int len = j - k; - char tmp[10]; // big enough most of the time - - if (len <= sizeof(tmp)) - p = tmp; - else - p = (char *)alloca(len); - len--; - memcpy(p, &line[k + 1], len); - p[len] = 0; - strupr(p); - p = getenv(p); - if (!p) - p = ""; - } - buf.writestring(p); - k = j; - goto L1; - } - } - } - buf.writeByte(line[k]); - L1: - ; - } - - // Remove trailing spaces - while (buf.offset && isspace(buf.data[buf.offset - 1])) - buf.offset--; - - p = buf.toChars(); - - // The expanded line is in p. - // Now parse it for meaning. - - p = skipspace(p); - switch (*p) - { - case ';': // comment - case 0: // blank - break; - - case '[': // look for [Environment] - p = skipspace(p + 1); - for (pn = p; isalnum(*pn); pn++) - ; - if (pn - p == 11 && - memicmp(p, "Environment", 11) == 0 && - *skipspace(pn) == ']' - ) - envsection = 1; - else - envsection = 0; - break; - - default: - if (envsection) - { - pn = p; - - // Convert name to upper case; - // remove spaces bracketing = - for (p = pn; *p; p++) - { if (islower(*p)) - *p &= ~0x20; - else if (isspace(*p)) - memmove(p, p + 1, strlen(p)); - else if (*p == '=') - { - p++; - while (isspace(*p)) - memmove(p, p + 1, strlen(p)); - break; - } - } - - putenv(strdup(pn)); -#if LOG - printf("\tputenv('%s')\n", pn); - //printf("getenv(\"TEST\") = '%s'\n",getenv("TEST")); -#endif - } - break; - } - - Lskip: - ; - } -} - -/******************** - * Skip spaces. - */ - -char *skipspace(const char *p) -{ - while (isspace(*p)) - p++; - return (char *)p; -} - diff -uNr gdc-0.11/d/root/init.c gdc-0.12/d/root/init.c --- gdc-0.11/d/root/init.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/init.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,345 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "mars.h" -#include "init.h" -#include "expression.h" -#include "identifier.h" -#include "declaration.h" -#include "aggregate.h" -#include "scope.h" -#include "mtype.h" - - -/********************************** Initializer ************************************/ - -Initializer::Initializer(Loc loc) -{ - this->loc = loc; -} - -Initializer *Initializer::syntaxCopy() -{ - assert(0); // BUG: implement - return NULL; -} - -Initializer *Initializer::semantic(Scope *sc, Type *t) -{ - return this; -} - -Array *Initializer::arraySyntaxCopy(Array *ai) -{ Array *a = NULL; - - if (ai) - { - a = new Array(); - a->setDim(ai->dim); - for (int i = 0; i < a->dim; i++) - { Initializer *e = (Initializer *)ai->data[i]; - - e = e->syntaxCopy(); - a->data[i] = e; - } - } - return a; -} - -/********************************** StructInitializer ************************************/ - -StructInitializer::StructInitializer(Loc loc) - : Initializer(loc) -{ - ad = NULL; -} - -Initializer *StructInitializer::syntaxCopy() -{ - StructInitializer *ai = new StructInitializer(loc); - - assert(field.dim == value.dim); - ai->field.setDim(field.dim); - ai->value.setDim(value.dim); - for (int i = 0; i < field.dim; i++) - { - ai->field.data[i] = field.data[i]; - - Initializer *init = (Initializer *)value.data[i]; - init = init->syntaxCopy(); - ai->value.data[i] = init; - } - return ai; -} - -void StructInitializer::addInit(Identifier *field, Initializer *value) -{ - //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value); - this->field.push(field); - this->value.push(value); -} - -Initializer *StructInitializer::semantic(Scope *sc, Type *t) -{ - TypeStruct *ts; - int errors = 0; - - t = t->toBasetype(); - if (t->ty == Tstruct) - { unsigned i; - unsigned fieldi = 0; - - ts = (TypeStruct *)t; - ad = ts->sym; - for (i = 0; i < field.dim; i++) - { - Identifier *id = (Identifier *)field.data[i]; - Initializer *val = (Initializer *)value.data[i]; - Dsymbol *s; - VarDeclaration *v; - - if (id == NULL) - { - if (fieldi >= ad->fields.dim) - { error(loc, "too many initializers for %s", ad->toChars()); - continue; - } - else - { - s = (Dsymbol *)ad->fields.data[fieldi]; - } - } - else - { - //s = ad->symtab->lookup(id); - s = ad->search(id, 0); - if (!s) - { - error("'%s' is not a member of '%s'", id->toChars(), t->toChars()); - continue; - } - - // Find out which field index it is - for (fieldi = 0; 1; fieldi++) - { - if (fieldi >= ad->fields.dim) - { - s->error("is not a per-instance initializable field"); - break; - } - if (s == (Dsymbol *)ad->fields.data[fieldi]) - break; - } - } - if (s && (v = s->isVarDeclaration()) != NULL) - { - val = val->semantic(sc, v->type); - value.data[i] = (void *)val; - field.data[i] = (void *)v; - } - else - { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); - errors = 1; - } - fieldi++; - } - } - else - { - error(loc, "a struct is not a valid initializer for a %s", t->toChars()); - errors = 1; - } - if (errors) - { - field.setDim(0); - value.setDim(0); - } - return this; -} - - -Expression *StructInitializer::toExpression() -{ - assert(0); - return NULL; -} - - -void StructInitializer::toCBuffer(OutBuffer *buf) -{ -} - -/********************************** ArrayInitializer ************************************/ - -ArrayInitializer::ArrayInitializer(Loc loc) - : Initializer(loc) -{ - dim = 0; - type = NULL; - sem = 0; -} - -Initializer *ArrayInitializer::syntaxCopy() -{ - //printf("ArrayInitializer::syntaxCopy()\n"); - - ArrayInitializer *ai = new ArrayInitializer(loc); - - assert(index.dim == value.dim); - ai->index.setDim(index.dim); - ai->value.setDim(value.dim); - for (int i = 0; i < ai->value.dim; i++) - { Expression *e = (Expression *)index.data[i]; - if (e) - e = e->syntaxCopy(); - ai->index.data[i] = e; - - Initializer *init = (Initializer *)value.data[i]; - init = init->syntaxCopy(); - ai->value.data[i] = init; - } - return ai; -} - -void ArrayInitializer::addInit(Expression *index, Initializer *value) -{ - this->index.push(index); - this->value.push(value); - dim = 0; - type = NULL; -} - -Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) -{ unsigned i; - unsigned length; - - //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); - if (sem) // if semantic() already run - return this; - sem = 1; - type = t; - t = t->toBasetype(); - switch (t->ty) - { - case Tpointer: - case Tsarray: - case Tarray: - break; - - default: - error(loc, "cannot use array to initialize %s", type->toChars()); - return this; - } - - length = 0; - for (i = 0; i < index.dim; i++) - { Expression *idx; - Initializer *val; - - idx = (Expression *)index.data[i]; - if (idx) - { idx = idx->semantic(sc); - idx = idx->optimize(WANTvalue); - index.data[i] = (void *)idx; - length = idx->toInteger(); - } - - val = (Initializer *)value.data[i]; - val = val->semantic(sc, t->next); - value.data[i] = (void *)val; - length++; - if (length > dim) - dim = length; - } - return this; -} - - -Expression *ArrayInitializer::toExpression() -{ - error("array initializers as expressions are not allowed"); - return new IntegerExp(0); -} - - -void ArrayInitializer::toCBuffer(OutBuffer *buf) -{ -} - - -/********************************** ExpInitializer ************************************/ - -ExpInitializer::ExpInitializer(Loc loc, Expression *exp) - : Initializer(loc) -{ - this->exp = exp; -} - -Initializer *ExpInitializer::syntaxCopy() -{ - return new ExpInitializer(loc, exp->syntaxCopy()); -} - -Initializer *ExpInitializer::semantic(Scope *sc, Type *t) -{ - //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); - exp = exp->semantic(sc); - Type *tb = t->toBasetype(); - - /* Look for case of initializing a static array with a too-short - * string literal, such as: - * char[5] foo = "abc"; - * Allow this by doing an explicit cast, which will lengthen the string - * literal. - */ - if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray) - { StringExp *se = (StringExp *)exp; - - if (!se->committed && se->type->ty == Tsarray && - ((TypeSArray *)se->type)->dim->toInteger() < - ((TypeSArray *)t)->dim->toInteger()) - { - exp = se->castTo(t); - goto L1; - } - } - - // Look for the case of statically initializing an array - // with a single member. - if (tb->ty == Tsarray && - !tb->next->equals(exp->type->toBasetype()->next) && - exp->implicitConvTo(tb->next) - ) - { - t = tb->next; - } - - exp = exp->implicitCastTo(t); -L1: - exp = exp->optimize(WANTvalue); - //printf("-ExpInitializer::semantic(): "); exp->print(); - return this; -} - -Expression *ExpInitializer::toExpression() -{ - return exp; -} - - -void ExpInitializer::toCBuffer(OutBuffer *buf) -{ - exp->toCBuffer(buf); -} - - - diff -uNr gdc-0.11/d/root/init.h gdc-0.12/d/root/init.h --- gdc-0.11/d/root/init.h 2005-02-20 16:43:51.000000000 +0100 +++ gdc-0.12/d/root/init.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,92 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef INIT_H -#define INIT_H - -#include "root.h" - -#include "mars.h" - -struct Identifier; -struct Expression; -struct Scope; -struct Type; -struct dt_t; -struct AggregateDeclaration; -struct ExpInitializer; - -struct Initializer : Object -{ - Loc loc; - - Initializer(Loc loc); - virtual Initializer *syntaxCopy(); - virtual Initializer *semantic(Scope *sc, Type *t); - virtual Expression *toExpression() = 0; - virtual void toCBuffer(OutBuffer *buf) = 0; - - static Array *arraySyntaxCopy(Array *ai); - - virtual dt_t *toDt(); - - virtual ExpInitializer *isExpInitializer() { return NULL; } -}; - -struct StructInitializer : Initializer -{ - Array field; // of Identifier *'s before semantic(), VarDeclaration *'s after - Array value; // parallel array of Initializer *'s - AggregateDeclaration *ad; // which aggregate this is for - - StructInitializer(Loc loc); - Initializer *syntaxCopy(); - void addInit(Identifier *field, Initializer *value); - Initializer *semantic(Scope *sc, Type *t); - Expression *toExpression(); - void toCBuffer(OutBuffer *buf); - - dt_t *toDt(); -}; - -struct ArrayInitializer : Initializer -{ - Array index; // of Expression *'s - Array value; // of Initializer *'s - unsigned dim; // length of array being initialized - Type *type; // type that array will be used to initialize - int sem; // !=0 if semantic() is run - - ArrayInitializer(Loc loc); - Initializer *syntaxCopy(); - void addInit(Expression *index, Initializer *value); - Initializer *semantic(Scope *sc, Type *t); - Expression *toExpression(); - void toCBuffer(OutBuffer *buf); - - dt_t *toDt(); - dt_t *toDtBit(); // for bit arrays -}; - -struct ExpInitializer : Initializer -{ - Expression *exp; - - ExpInitializer(Loc loc, Expression *exp); - Initializer *syntaxCopy(); - Initializer *semantic(Scope *sc, Type *t); - Expression *toExpression(); - void toCBuffer(OutBuffer *buf); - - dt_t *toDt(); - - virtual ExpInitializer *isExpInitializer() { return this; } -}; - -#endif diff -uNr gdc-0.11/d/root/inline.c gdc-0.12/d/root/inline.c --- gdc-0.11/d/root/inline.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/inline.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1114 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -// Routines to perform function inlining - -#define LOG 0 - -#include -#include -#include - -#include "id.h" -#include "init.h" -#include "declaration.h" -#include "aggregate.h" -#include "expression.h" -#include "statement.h" -#include "mtype.h" - -/* ========== Compute cost of inlining =============== */ - -/* Walk trees to determine if inlining can be done, and if so, - * if it is too complex to be worth inlining or not. - */ - -struct InlineCostState -{ - int nested; - int hasthis; - FuncDeclaration *fd; -}; - -const int COST_MAX = 250; - -int Statement::inlineCost(InlineCostState *ics) -{ - return COST_MAX; // default is we can't inline it -} - -int ExpStatement::inlineCost(InlineCostState *ics) -{ - return exp ? exp->inlineCost(ics) : 0; -} - -int CompoundStatement::inlineCost(InlineCostState *ics) -{ int cost = 0; - - for (int i = 0; i < statements->dim; i++) - { Statement *s; - - s = (Statement *) statements->data[i]; - if (s) - { - cost += s->inlineCost(ics); - if (cost >= COST_MAX) - break; - } - } - return cost; -} - -int IfStatement::inlineCost(InlineCostState *ics) -{ - int cost; - - cost = condition->inlineCost(ics); - - /* Specifically allow: - * if (condition) - * return exp1; - * else - * return exp2; - * Otherwise, we can't handle return statements nested in if's. - */ - - if (elsebody && ifbody && - ifbody->isReturnStatement() && - elsebody->isReturnStatement()) - { - cost += ifbody->inlineCost(ics); - cost += elsebody->inlineCost(ics); - //printf("cost = %d\n", cost); - } - else - { - ics->nested += 1; - if (ifbody) - cost += ifbody->inlineCost(ics); - if (elsebody) - cost += elsebody->inlineCost(ics); - ics->nested -= 1; - } - return cost; -} - -int ReturnStatement::inlineCost(InlineCostState *ics) -{ - // Can't handle return statements nested in if's - if (ics->nested) - return COST_MAX; - return exp ? exp->inlineCost(ics) : 0; -} - -/* -------------------------- */ - -int arrayInlineCost(InlineCostState *ics, Array *arguments) -{ int cost = 0; - - if (arguments) - { - for (int i = 0; i < arguments->dim; i++) - { Expression *e = (Expression *)arguments->data[i]; - - cost += e->inlineCost(ics); - } - } - return cost; -} - -int Expression::inlineCost(InlineCostState *ics) -{ - return 1; -} - -int ThisExp::inlineCost(InlineCostState *ics) -{ - FuncDeclaration *fd = ics->fd; - if (fd->isNested() || !ics->hasthis) - return COST_MAX; - return 1; -} - -int SuperExp::inlineCost(InlineCostState *ics) -{ - FuncDeclaration *fd = ics->fd; - if (fd->isNested() || !ics->hasthis) - return COST_MAX; - return 1; -} - -int FuncExp::inlineCost(InlineCostState *ics) -{ - // Right now, this makes the function be output to the .obj file twice. - return COST_MAX; -} - -int DelegateExp::inlineCost(InlineCostState *ics) -{ - return COST_MAX; -} - -int DeclarationExp::inlineCost(InlineCostState *ics) -{ int cost = 0; - VarDeclaration *vd; - - vd = declaration->isVarDeclaration(); - if (vd) - { - if (vd->isDataseg()) - return COST_MAX; - cost += 1; - - // Scan initializer (vd->init) - if (vd->init) - { - ExpInitializer *ie = vd->init->isExpInitializer(); - - if (ie) - { - cost += ie->exp->inlineCost(ics); - } - } - } - - // These can contain functions, which when copied, get output twice. - if (declaration->isStructDeclaration() || - declaration->isClassDeclaration() || - declaration->isFuncDeclaration() || - declaration->isTemplateMixin()) - return COST_MAX; - - //printf("DeclarationExp::inlineCost('%s')\n", toChars()); - return cost; -} - -int UnaExp::inlineCost(InlineCostState *ics) -{ - return 1 + e1->inlineCost(ics); -} - -int BinExp::inlineCost(InlineCostState *ics) -{ - return 1 + e1->inlineCost(ics) + e2->inlineCost(ics); -} - -int CallExp::inlineCost(InlineCostState *ics) -{ - return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments); -} - -int SliceExp::inlineCost(InlineCostState *ics) -{ int cost; - - cost = 1 + e1->inlineCost(ics); - if (lwr) - cost += lwr->inlineCost(ics); - if (upr) - cost += upr->inlineCost(ics); - return cost; -} - -int ArrayExp::inlineCost(InlineCostState *ics) -{ - return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments); -} - - -int CondExp::inlineCost(InlineCostState *ics) -{ - return 1 + - e1->inlineCost(ics) + - e2->inlineCost(ics) + - econd->inlineCost(ics); -} - - -/* ======================== Perform the inlining ============================== */ - -/* Inlining is done by: - * o Converting to an Expression - * o Copying the trees of the function to be inlined - * o Renaming the variables - */ - -struct InlineDoState -{ - VarDeclaration *vthis; - Array from; // old Dsymbols - Array to; // parallel array of new Dsymbols - Dsymbol *parent; // new parent -}; - -Expression *Statement::doInline(InlineDoState *ids) -{ - assert(0); - return NULL; // default is we can't inline it -} - -Expression *ExpStatement::doInline(InlineDoState *ids) -{ -#if LOG - if (exp) printf("ExpStatement::doInline() '%s'\n", exp->toChars()); -#endif - return exp ? exp->doInline(ids) : NULL; -} - -Expression *CompoundStatement::doInline(InlineDoState *ids) -{ - Expression *e = NULL; - - for (int i = 0; i < statements->dim; i++) - { Statement *s; - Expression *e2; - - s = (Statement *) statements->data[i]; - if (s) - { - e2 = s->doInline(ids); - e = Expression::combine(e, e2); - if (s->isReturnStatement()) - break; - } - } - return e; -} - -Expression *IfStatement::doInline(InlineDoState *ids) -{ - Expression *econd; - Expression *e1; - Expression *e2; - Expression *e; - - econd = condition->doInline(ids); - assert(econd); - if (ifbody) - e1 = ifbody->doInline(ids); - else - e1 = NULL; - if (elsebody) - e2 = elsebody->doInline(ids); - else - e2 = NULL; - if (e1 && e2) - { - e = new CondExp(econd->loc, econd, e1, e2); - e->type = e1->type; - } - else if (e1) - { - e = new AndAndExp(econd->loc, econd, e1); - e->type = Type::tvoid; - } - else if (e2) - { - e = new OrOrExp(econd->loc, econd, e2); - e->type = Type::tvoid; - } - else - { - e = econd; - } - return e; -} - -Expression *ReturnStatement::doInline(InlineDoState *ids) -{ - return exp ? exp->doInline(ids) : 0; -} - -/* --------------------------------------------------------------- */ - -/****************************** - * Perform doInline() on an array of Expressions. - */ - -Array *arrayExpressiondoInline(Array *a, InlineDoState *ids) -{ Array *newa = NULL; - - if (a) - { - newa = new Array(); - newa->setDim(a->dim); - - for (int i = 0; i < a->dim; i++) - { Expression *e = (Expression *)a->data[i]; - - e = e->doInline(ids); - newa->data[i] = (void *)e; - } - } - return newa; -} - -Expression *Expression::doInline(InlineDoState *ids) -{ - //printf("Expression::doInline(%s): %s\n", Token::toChars(op), toChars()); - return copy(); -} - -Expression *SymOffExp::doInline(InlineDoState *ids) -{ - int i; - - //printf("SymOffExp::doInline(%s)\n", toChars()); - for (i = 0; i < ids->from.dim; i++) - { - if (var == (Declaration *)ids->from.data[i]) - { - SymOffExp *se = (SymOffExp *)copy(); - - se->var = (Declaration *)ids->to.data[i]; - return se; - } - } - return this; -} - -Expression *VarExp::doInline(InlineDoState *ids) -{ - int i; - - //printf("VarExp::doInline(%s)\n", toChars()); - for (i = 0; i < ids->from.dim; i++) - { - if (var == (Declaration *)ids->from.data[i]) - { - VarExp *ve = (VarExp *)copy(); - - ve->var = (Declaration *)ids->to.data[i]; - return ve; - } - } - return this; -} - -Expression *ThisExp::doInline(InlineDoState *ids) -{ - assert(ids->vthis); - - VarExp *ve = new VarExp(loc, ids->vthis); - ve->type = type; - return ve; -} - -Expression *SuperExp::doInline(InlineDoState *ids) -{ - assert(ids->vthis); - - VarExp *ve = new VarExp(loc, ids->vthis); - ve->type = type; - return ve; -} - -Expression *DeclarationExp::doInline(InlineDoState *ids) -{ DeclarationExp *de = (DeclarationExp *)copy(); - VarDeclaration *vd; - - //printf("DeclarationExp::doInline(%s)\n", toChars()); - vd = declaration->isVarDeclaration(); - if (vd) - { - if (vd->isStatic() || vd->isConst()) - ; - else - { - ExpInitializer *ie; - ExpInitializer *ieto; - VarDeclaration *vto; - - vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); - *vto = *vd; - vto->parent = ids->parent; - vto->csym = NULL; - vto->isym = NULL; - - ids->from.push(vd); - ids->to.push(vto); - - ie = vd->init->isExpInitializer(); - assert(ie); - ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); - vto->init = ieto; - - de->declaration = (Dsymbol *) (void *)vto; - } - } - /* This needs work, like DeclarationExp::toElem(), if we are - * to handle TemplateMixin's. For now, we just don't inline them. - */ - return de; -} - -Expression *NewExp::doInline(InlineDoState *ids) -{ - //printf("NewExp::doInline(): %s\n", toChars()); - NewExp *ne = (NewExp *)copy(); - - ne->newargs = arrayExpressiondoInline(ne->newargs, ids); - ne->arguments = arrayExpressiondoInline(ne->arguments, ids); - return ne; -} - -Expression *UnaExp::doInline(InlineDoState *ids) -{ - UnaExp *ue = (UnaExp *)copy(); - - ue->e1 = e1->doInline(ids); - return ue; -} - -Expression *BinExp::doInline(InlineDoState *ids) -{ - BinExp *be = (BinExp *)copy(); - - be->e1 = e1->doInline(ids); - be->e2 = e2->doInline(ids); - return be; -} - -Expression *CallExp::doInline(InlineDoState *ids) -{ - CallExp *ce; - - ce = (CallExp *)copy(); - ce->e1 = e1->doInline(ids); - ce->arguments = arrayExpressiondoInline(arguments, ids); - return ce; -} - - -Expression *IndexExp::doInline(InlineDoState *ids) -{ - IndexExp *are = (IndexExp *)copy(); - - are->e1 = e1->doInline(ids); - - if (lengthVar) - { //printf("lengthVar\n"); - VarDeclaration *vd = lengthVar; - ExpInitializer *ie; - ExpInitializer *ieto; - VarDeclaration *vto; - - vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); - *vto = *vd; - vto->parent = ids->parent; - vto->csym = NULL; - vto->isym = NULL; - - ids->from.push(vd); - ids->to.push(vto); - - if (vd->init) - { - ie = vd->init->isExpInitializer(); - assert(ie); - ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); - vto->init = ieto; - } - - are->lengthVar = (VarDeclaration *) (void *)vto; - } - are->e2 = e2->doInline(ids); - return are; -} - - -Expression *SliceExp::doInline(InlineDoState *ids) -{ - SliceExp *are = (SliceExp *)copy(); - - are->e1 = e1->doInline(ids); - - if (lengthVar) - { //printf("lengthVar\n"); - VarDeclaration *vd = lengthVar; - ExpInitializer *ie; - ExpInitializer *ieto; - VarDeclaration *vto; - - vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); - *vto = *vd; - vto->parent = ids->parent; - vto->csym = NULL; - vto->isym = NULL; - - ids->from.push(vd); - ids->to.push(vto); - - if (vd->init) - { - ie = vd->init->isExpInitializer(); - assert(ie); - ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); - vto->init = ieto; - } - - are->lengthVar = (VarDeclaration *) (void *)vto; - } - if (lwr) - are->lwr = lwr->doInline(ids); - if (upr) - are->upr = upr->doInline(ids); - return are; -} - - -Expression *ArrayExp::doInline(InlineDoState *ids) -{ - ArrayExp *ce; - - ce = (ArrayExp *)copy(); - ce->e1 = e1->doInline(ids); - ce->arguments = arrayExpressiondoInline(arguments, ids); - return ce; -} - - -Expression *CondExp::doInline(InlineDoState *ids) -{ - CondExp *ce = (CondExp *)copy(); - - ce->econd = econd->doInline(ids); - ce->e1 = e1->doInline(ids); - ce->e2 = e2->doInline(ids); - return ce; -} - - -/* ========== Walk the parse trees, and inline expand functions =============== */ - -/* Walk the trees, looking for functions to inline. - * Inline any that can be. - */ - -struct InlineScanState -{ - FuncDeclaration *fd; // function being scanned -}; - -Statement *Statement::inlineScan(InlineScanState *iss) -{ - return this; -} - -Statement *ExpStatement::inlineScan(InlineScanState *iss) -{ -#if LOG - printf("ExpStatement::inlineScan(%s)\n", toChars()); -#endif - if (exp) - exp = exp->inlineScan(iss); - return this; -} - -Statement *CompoundStatement::inlineScan(InlineScanState *iss) -{ - for (int i = 0; i < statements->dim; i++) - { Statement *s; - - s = (Statement *) statements->data[i]; - if (s) - statements->data[i] = (void *)s->inlineScan(iss); - } - return this; -} - -Statement *ScopeStatement::inlineScan(InlineScanState *iss) -{ - if (statement) - statement = statement->inlineScan(iss); - return this; -} - -Statement *WhileStatement::inlineScan(InlineScanState *iss) -{ - condition = condition->inlineScan(iss); - body = body->inlineScan(iss); - return this; -} - - -Statement *DoStatement::inlineScan(InlineScanState *iss) -{ - body = body->inlineScan(iss); - condition = condition->inlineScan(iss); - return this; -} - - -Statement *ForStatement::inlineScan(InlineScanState *iss) -{ - if (init) - init = init->inlineScan(iss); - if (condition) - condition = condition->inlineScan(iss); - if (increment) - increment = increment->inlineScan(iss); - body = body->inlineScan(iss); - return this; -} - - -Statement *ForeachStatement::inlineScan(InlineScanState *iss) -{ - aggr = aggr->inlineScan(iss); - body = body->inlineScan(iss); - return this; -} - - -Statement *IfStatement::inlineScan(InlineScanState *iss) -{ - condition = condition->inlineScan(iss); - if (ifbody) - ifbody = ifbody->inlineScan(iss); - if (elsebody) - elsebody = elsebody->inlineScan(iss); - return this; -} - - -Statement *SwitchStatement::inlineScan(InlineScanState *iss) -{ - //printf("SwitchStatement::inlineScan()\n"); - condition = condition->inlineScan(iss); - body = body->inlineScan(iss); - if (sdefault) - sdefault = (DefaultStatement *)sdefault->inlineScan(iss); - if (cases) - { - for (int i = 0; i < cases->dim; i++) - { Statement *s; - - s = (Statement *) cases->data[i]; - cases->data[i] = (void *)s->inlineScan(iss); - } - } - return this; -} - - -Statement *CaseStatement::inlineScan(InlineScanState *iss) -{ - //printf("CaseStatement::inlineScan()\n"); - exp = exp->inlineScan(iss); - if (statement) - statement = statement->inlineScan(iss); - return this; -} - - -Statement *DefaultStatement::inlineScan(InlineScanState *iss) -{ - if (statement) - statement = statement->inlineScan(iss); - return this; -} - - -Statement *ReturnStatement::inlineScan(InlineScanState *iss) -{ - if (exp) - exp = exp->inlineScan(iss); - return this; -} - - -Statement *SynchronizedStatement::inlineScan(InlineScanState *iss) -{ - if (exp) - exp = exp->inlineScan(iss); - if (body) - body = body->inlineScan(iss); - return this; -} - - -Statement *WithStatement::inlineScan(InlineScanState *iss) -{ - if (exp) - exp = exp->inlineScan(iss); - if (body) - body = body->inlineScan(iss); - return this; -} - - -Statement *TryCatchStatement::inlineScan(InlineScanState *iss) -{ - if (body) - body = body->inlineScan(iss); - if (catches) - { - for (int i = 0; i < catches->dim; i++) - { Catch *c = (Catch *)catches->data[i]; - - if (c->handler) - c->handler = c->handler->inlineScan(iss); - } - } - return this; -} - - -Statement *TryFinallyStatement::inlineScan(InlineScanState *iss) -{ - if (body) - body = body->inlineScan(iss); - if (finalbody) - finalbody = finalbody->inlineScan(iss); - return this; -} - - -Statement *ThrowStatement::inlineScan(InlineScanState *iss) -{ - if (exp) - exp = exp->inlineScan(iss); - return this; -} - - -Statement *VolatileStatement::inlineScan(InlineScanState *iss) -{ - if (statement) - statement = statement->inlineScan(iss); - return this; -} - - -Statement *LabelStatement::inlineScan(InlineScanState *iss) -{ - if (statement) - statement = statement->inlineScan(iss); - return this; -} - -/* -------------------------- */ - -void arrayInlineScan(InlineScanState *iss, Array *arguments) -{ - if (arguments) - { - for (int i = 0; i < arguments->dim; i++) - { Expression *e = (Expression *)arguments->data[i]; - - e = e->inlineScan(iss); - arguments->data[i] = (void *)e; - } - } -} - -Expression *Expression::inlineScan(InlineScanState *iss) -{ - return this; -} - -Expression *DeclarationExp::inlineScan(InlineScanState *iss) -{ - // Should scan variable initializers - return this; -} - -Expression *UnaExp::inlineScan(InlineScanState *iss) -{ - e1 = e1->inlineScan(iss); - return this; -} - -Expression *BinExp::inlineScan(InlineScanState *iss) -{ - e1 = e1->inlineScan(iss); - e2 = e2->inlineScan(iss); - return this; -} - - -Expression *CallExp::inlineScan(InlineScanState *iss) -{ Expression *e = this; - - //printf("CallExp::inlineScan()\n"); - e1 = e1->inlineScan(iss); - arrayInlineScan(iss, arguments); - - if (e1->op == TOKvar) - { - VarExp *ve = (VarExp *)e1; - FuncDeclaration *fd = ve->var->isFuncDeclaration(); - - if (fd && fd != iss->fd && fd->canInline(0)) - { - e = fd->doInline(iss, NULL, arguments); - } - } - else if (e1->op == TOKdotvar) - { - DotVarExp *dve = (DotVarExp *)e1; - FuncDeclaration *fd = dve->var->isFuncDeclaration(); - - if (fd && fd != iss->fd && fd->canInline(1)) - { - e = fd->doInline(iss, dve->e1, arguments); - } - } - - return e; -} - - -Expression *SliceExp::inlineScan(InlineScanState *iss) -{ - e1 = e1->inlineScan(iss); - if (lwr) - lwr = lwr->inlineScan(iss); - if (upr) - upr = upr->inlineScan(iss); - return this; -} - - -Expression *ArrayExp::inlineScan(InlineScanState *iss) -{ Expression *e = this; - - //printf("ArrayExp::inlineScan()\n"); - e1 = e1->inlineScan(iss); - arrayInlineScan(iss, arguments); - - return e; -} - - -Expression *CondExp::inlineScan(InlineScanState *iss) -{ - econd = econd->inlineScan(iss); - e1 = e1->inlineScan(iss); - e2 = e2->inlineScan(iss); - return this; -} - - -/* ========== =============== */ - -void FuncDeclaration::inlineScan() -{ - InlineScanState iss; - -#if LOG - printf("FuncDeclaration::inlineScan('%s')\n", toChars()); -#endif - memset(&iss, 0, sizeof(iss)); - iss.fd = this; - if (fbody) - { - inlineNest++; - fbody = fbody->inlineScan(&iss); - inlineNest--; - } -} - -int FuncDeclaration::canInline(int hasthis) -{ - InlineCostState ics; - int cost; - -#define CANINLINE_LOG 0 - -#if CANINLINE_LOG - printf("FuncDeclaration::canInline('%s')\n", toChars()); -#endif - - if (inlineNest || !semanticRun) - { -#if CANINLINE_LOG - printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun); -#endif - return 0; - } - - switch (inlineStatus) - { - case ILSyes: -#if CANINLINE_LOG - printf("\tyes\n"); -#endif - return 1; - - case ILSno: -#if CANINLINE_LOG - printf("\t2: no\n"); -#endif - return 0; - - case ILSuninitialized: - break; - - default: - assert(0); - } - - assert(type->ty == Tfunction); - TypeFunction *tf = (TypeFunction *)(type); - - if ( -#if 0 - isCtorDeclaration() || // cannot because need to convert: - // return; - // to: - // return this; -#endif - isSynchronized() || - isImportedSymbol() || - !fbody || - tf->varargs || // no variadic parameter lists - nestedFrameRef || // no nested references to this frame - (isVirtual() && !isFinal()) - ) - { - goto Lno; - } - - /* If any parameters are Tsarray's (which are passed by reference) - * or out parameters (also passed by reference), don't do inlining. - */ - if (parameters) - { - for (int i = 0; i < parameters->dim; i++) - { - VarDeclaration *v = (VarDeclaration *)parameters->data[i]; - if (v->isOut() || v->type->toBasetype()->ty == Tsarray) - goto Lno; - } - } - - memset(&ics, 0, sizeof(ics)); - ics.hasthis = hasthis; - ics.fd = this; - cost = fbody->inlineCost(&ics); -#if CANINLINE_LOG - printf("cost = %d\n", cost); -#endif - if (cost >= COST_MAX) - goto Lno; - - inlineScan(); - -Lyes: - inlineStatus = ILSyes; -#if CANINLINE_LOG - printf("\tyes\n"); -#endif - return 1; - -Lno: - inlineStatus = ILSno; -#if CANINLINE_LOG - printf("\tno\n"); -#endif - return 0; -} - -Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, Array *arguments) -{ - InlineDoState ids; - DeclarationExp *de; - Expression *e = NULL; - -#if LOG - printf("FuncDeclaration::doInline('%s')\n", toChars()); -#endif - - memset(&ids, 0, sizeof(ids)); - ids.parent = iss->fd; - - // Set up vthis - if (ethis) - { - VarDeclaration *vthis; - ExpInitializer *ei; - VarExp *ve; - - if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer) - { - ethis = ethis->addressOf(); - } - - ei = new ExpInitializer(ethis->loc, ethis); - - vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei); - vthis->storage_class = STCin; - vthis->linkage = LINKd; - vthis->parent = iss->fd; - - ve = new VarExp(vthis->loc, vthis); - ve->type = vthis->type; - - ei->exp = new AssignExp(vthis->loc, ve, ethis); - ei->exp->type = ve->type; - - ids.vthis = vthis; - } - - // Set up parameters - if (ethis) - { - e = new DeclarationExp(0, ids.vthis); - e->type = Type::tvoid; - } - - if (arguments && arguments->dim) - { - assert(parameters->dim == arguments->dim); - - for (int i = 0; i < arguments->dim; i++) - { - VarDeclaration *vfrom = (VarDeclaration *)parameters->data[i]; - VarDeclaration *vto; - Expression *arg = (Expression *)arguments->data[i]; - ExpInitializer *ei; - VarExp *ve; - - ei = new ExpInitializer(arg->loc, arg); - - vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei); - vto->storage_class |= vfrom->storage_class & (STCin | STCout); - vto->linkage = vfrom->linkage; - vto->parent = iss->fd; - //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class); - //printf("vto->parent = '%s'\n", iss->fd->toChars()); - - ve = new VarExp(vto->loc, vto); - ve->type = vto->type; - - ei->exp = new AssignExp(vto->loc, ve, arg); - ei->exp->type = ve->type; - - ids.from.push(vfrom); - ids.to.push(vto); - - de = new DeclarationExp(0, vto); - de->type = Type::tvoid; - - e = Expression::combine(e, de); - } - } - - inlineNest++; - Expression *eb = fbody->doInline(&ids); - inlineNest--; -//eb->type->print(); -//eb->print(); -//eb->dump(0); - return Expression::combine(e, eb); -} - - - diff -uNr gdc-0.11/d/root/lexer.c gdc-0.12/d/root/lexer.c --- gdc-0.11/d/root/lexer.c 2005-04-24 18:48:31.000000000 +0200 +++ gdc-0.12/d/root/lexer.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,2285 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -/* Lexical Analyzer */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef IN_GCC - -#include -#include "../root/mem.h" - -#else - -#if __GNUC__ -#include -extern "C" long double strtold(const char *p,char **endp); -#endif - -#if _WIN32 -#include "..\root\mem.h" -#elif ! defined(_WIN32) -#include "../root/mem.h" -#else -#error "fix this" -#endif - -#endif - -#include "stringtable.h" - -#include "lexer.h" -#include "utf.h" -#include "identifier.h" -#include "id.h" -#include "module.h" - -#if _WIN32 && __DMC__ -// from \dm\src\include\setlocal.h -extern "C" char * __cdecl __locale_decpoint; -#endif - -extern int isUniAlpha(unsigned u); -extern int HtmlNamedEntity(unsigned char *p, int length); - -#define LS 0x2028 // UTF line separator -#define PS 0x2029 // UTF paragraph separator - -/******************************************** - * Do our own char maps - */ - -static unsigned char cmtable[256]; - -const int CMoctal = 0x1; -const int CMhex = 0x2; -const int CMidchar = 0x4; - -inline unsigned char isoctal (unsigned char c) { return cmtable[c] & CMoctal; } -inline unsigned char ishex (unsigned char c) { return cmtable[c] & CMhex; } -inline unsigned char isidchar(unsigned char c) { return cmtable[c] & CMidchar; } - -static void cmtable_init() -{ - for (unsigned c = 0; c < sizeof(cmtable) / sizeof(cmtable[0]); c++) - { - if ('0' <= c && c <= '7') - cmtable[c] |= CMoctal; - if (isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) - cmtable[c] |= CMhex; - if (isalnum(c) || c == '_') - cmtable[c] |= CMidchar; - } -} - - -/******************************************************/ - -char *Token::tochars[TOKMAX]; - -void *Token::operator new(size_t size) -{ Token *t; - - if (Lexer::freelist) - { - t = Lexer::freelist; - Lexer::freelist = t->next; - return t; - } - - return ::operator new(size); -} - -void Token::print() -{ - printf("%s\n", toChars()); -} - -char *Token::toChars() -{ char *p; - static char buffer[3 + 3 * sizeof(value) + 1]; - - p = buffer; - switch (value) - { - case TOKint32v: - sprintf(buffer,"%ld",(d_int32)int64value); - break; - - case TOKuns32v: - case TOKcharv: - case TOKwcharv: - case TOKdcharv: - sprintf(buffer,"%luU",(d_uns32)uns64value); - break; - - case TOKint64v: - sprintf(buffer,"%lldL",int64value); - break; - - case TOKuns64v: - sprintf(buffer,"%lluUL",uns64value); - break; - -#if IN_GCC - case TOKfloat32v: - case TOKfloat64v: - case TOKfloat80v: - float80value.format(buffer, sizeof(buffer)); - break; - case TOKimaginary32v: - case TOKimaginary64v: - case TOKimaginary80v: - float80value.format(buffer, sizeof(buffer)); - // %% buffer - strcat(buffer, "i"); - break; -#else - case TOKfloat32v: - sprintf(buffer,"%Lgf", float80value); - break; - - case TOKfloat64v: - sprintf(buffer,"%Lg", float80value); - break; - - case TOKfloat80v: - sprintf(buffer,"%gL", float80value); - break; - - case TOKimaginary32v: - sprintf(buffer,"%Lgfi", float80value); - break; - - case TOKimaginary64v: - sprintf(buffer,"%Lgi", float80value); - break; - - case TOKimaginary80v: - sprintf(buffer,"%gLi", float80value); - break; -#endif - - - case TOKstring: -#if CSTRINGS - p = string; -#else - p = (char *)ustring; -#endif - break; - - case TOKidentifier: - case TOKenum: - case TOKstruct: - case TOKimport: - CASE_BASIC_TYPES: - p = ident->toChars(); - break; - - default: - p = toChars(value); - break; - } - return p; -} - -char *Token::toChars(enum TOK value) -{ char *p; - static char buffer[3 + 3 * sizeof(value) + 1]; - - p = tochars[value]; - if (!p) - { sprintf(buffer,"TOK%d",value); - p = buffer; - } - return p; -} - -/******************************************************/ - -Token *Lexer::freelist = NULL; -StringTable Lexer::stringtable; -OutBuffer Lexer::stringbuffer; - -Lexer::Lexer(Module *mod, unsigned char *base, unsigned length) - : loc(mod, 1) -{ - //printf("Lexer::Lexer(%p,%d)\n",base,length); - //printf("lexer.mod = %p, %p\n", mod, this->loc.mod); - memset(&token,0,sizeof(token)); - this->base = base; - this->end = base + length; - p = base; - this->mod = mod; - //initKeywords(); -} - -#if 0 -unsigned Lexer::locToLine(Loc loc) -{ - unsigned linnum = 1; - unsigned char *s; - unsigned char *p = base + loc; - - for (s = base; s != p; s++) - { - if (*s == '\n') - linnum++; - } - return linnum; -} -#endif - -void Lexer::error(const char *format, ...) -{ - char *p = loc.toChars(); - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); - - global.errors++; - if (global.errors > 20) // moderate blizzard of cascading messages - fatal(); -} - -TOK Lexer::nextToken() -{ Token *t; - - if (token.next) - { - t = token.next; - memcpy(&token,t,sizeof(Token)); - t->next = freelist; - freelist = t; - } - else - { - scan(&token); - } - //token.print(); - return token.value; -} - -Token *Lexer::peek(Token *ct) -{ Token *t; - - if (ct->next) - t = ct->next; - else - { - t = new Token(); - scan(t); - t->next = NULL; - ct->next = t; - } - return t; -} - -/**************************** - * Turn next token in buffer into a token. - */ - -void Lexer::scan(Token *t) -{ - while (1) - { - t->ptr = p; - //printf("p = %p, *p = '%c'\n",p,*p); - switch (*p) - { - case 0: - case 0x1A: - t->value = TOKeof; // end of file - return; - - case ' ': - case '\t': - case '\v': - case '\f': - p++; - continue; // skip white space - - case '\r': - p++; - if (*p != '\n') // if CR stands by itself - loc.linnum++; - continue; // skip white space - - case '\n': - p++; - loc.linnum++; - continue; // skip white space - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - t->value = number(t); - return; - -#if CSTRINGS - case '\'': - t->value = charConstant(t, 0); - return; - - case '"': - t->value = stringConstant(t,0); - return; - - case 'l': - case 'L': - if (p[1] == '\'') - { - p++; - t->value = charConstant(t, 1); - return; - } - else if (p[1] == '"') - { - p++; - t->value = stringConstant(t, 1); - return; - } -#else - case '\'': - t->value = charConstant(t,0); - return; - - case 'r': - if (p[1] != '"') - goto case_ident; - p++; - case '`': - t->value = wysiwygStringConstant(t, *p); - return; - - case 'x': - if (p[1] != '"') - goto case_ident; - p++; - t->value = hexStringConstant(t); - return; - - - case '"': - t->value = escapeStringConstant(t,0); - return; - - case '\\': // escaped string literal - { unsigned c; - - stringbuffer.reset(); - do - { - p++; - c = escapeSequence(); - stringbuffer.writeUTF8(c); - } while (*p == '\\'); - t->len = stringbuffer.offset; - stringbuffer.writeByte(0); - t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset); - memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); - t->value = TOKstring; - return; - } - - case 'l': - case 'L': -#endif - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'm': case 'n': case 'o': - case 'p': case 'q': /*case 'r':*/ case 's': case 't': - case 'u': case 'v': case 'w': /*case 'x':*/ case 'y': - case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': - case '_': - case_ident: - { unsigned char c; - StringValue *sv; - Identifier *id; - - do - { - c = *++p; - } while (isidchar(c) || (c & 0x80 && isUniAlpha(decodeUTF()))); - sv = stringtable.update((char *)t->ptr, p - t->ptr); - id = (Identifier *) sv->ptrvalue; - if (!id) - { id = new Identifier(sv->lstring.string,TOKidentifier); - sv->ptrvalue = id; - } - t->ident = id; - t->value = (enum TOK) id->value; - if (*t->ptr == '_') // if special identifier token - { - static char date[11+1]; - static char time[8+1]; - static char timestamp[24+1]; - - if (!date[0]) // lazy evaluation - { time_t t; - char *p; - - ::time(&t); - p = ctime(&t); - assert(p); - sprintf(date, "%.6s %.4s", p + 4, p + 20); - sprintf(time, "%.8s", p + 11); - sprintf(timestamp, "%.24s", p); - } - - if (id == Id::FILE) - { - t->value = TOKstring; - t->ustring = (unsigned char *)(loc.filename ? loc.filename : mod->ident->toChars()); - goto Llen; - } - else if (id == Id::LINE) - { - t->value = TOKint64v; - t->uns64value = loc.linnum; - } - else if (id == Id::DATE) - { - t->value = TOKstring; - t->ustring = (unsigned char *)date; - goto Llen; - } - else if (id == Id::TIME) - { - t->value = TOKstring; - t->ustring = (unsigned char *)time; - goto Llen; - } - else if (id == Id::TIMESTAMP) - { - t->value = TOKstring; - t->ustring = (unsigned char *)timestamp; - Llen: - t->len = strlen((char *)t->ustring); - } - } - //printf("t->value = %d\n",t->value); - return; - } - - case '/': - p++; - switch (*p) - { - case '=': - p++; - t->value = TOKdivass; - return; - - case '*': - p++; - while (1) - { - while (1) - { unsigned char c = *p; - switch (c) - { - case '/': - break; - - case '\n': - loc.linnum++; - p++; - continue; - - case '\r': - p++; - if (*p != '\n') - loc.linnum++; - continue; - - case 0: - case 0x1A: - error("unterminated /* */ comment"); - p = end; - t->value = TOKeof; - return; - - default: - if (c & 0x80) - { unsigned u = decodeUTF(); - if (u == PS || u == LS) - loc.linnum++; - } - p++; - continue; - } - break; - } - p++; - if (p[-2] == '*' && p - 3 != t->ptr) - break; - } - continue; - - case '/': - while (1) - { unsigned char c = *++p; - switch (c) - { - case '\n': - break; - - case '\r': - if (p[1] == '\n') - p++; - break; - - case 0: - case 0x1A: - p = end; - t->value = TOKeof; - return; - - default: - if (c & 0x80) - { unsigned u = decodeUTF(); - if (u == PS || u == LS) - break; - } - continue; - } - break; - } - p++; - loc.linnum++; - continue; - - case '+': - { int nest; - - p++; - nest = 1; - while (1) - { unsigned char c = *p; - switch (c) - { - case '/': - p++; - if (*p == '+') - { - p++; - nest++; - } - continue; - - case '+': - p++; - if (*p == '/') - { - p++; - if (--nest == 0) - break; - } - continue; - - case '\r': - p++; - if (*p != '\n') - loc.linnum++; - continue; - - case '\n': - loc.linnum++; - p++; - continue; - - case 0: - case 0x1A: - error("unterminated /+ +/ comment"); - p = end; - t->value = TOKeof; - return; - - default: - if (c & 0x80) - { unsigned u = decodeUTF(); - if (u == PS || u == LS) - loc.linnum++; - } - p++; - continue; - } - break; - } - continue; - } - } - t->value = TOKdiv; - return; - - case '.': - p++; - if (isdigit(*p)) - { - p--; - t->value = inreal(t); - } - else if (p[0] == '.') - { - if (p[1] == '.') - { p += 2; - t->value = TOKdotdotdot; - } - else - { p++; - t->value = TOKslice; - } - } - else - t->value = TOKdot; - return; - - case '&': - p++; - if (*p == '=') - { p++; - t->value = TOKandass; - } - else if (*p == '&') - { p++; - t->value = TOKandand; - } - else - t->value = TOKand; - return; - - case '|': - p++; - if (*p == '=') - { p++; - t->value = TOKorass; - } - else if (*p == '|') - { p++; - t->value = TOKoror; - } - else - t->value = TOKor; - return; - - case '-': - p++; - if (*p == '=') - { p++; - t->value = TOKminass; - } -#if 0 - else if (*p == '>') - { p++; - t->value = TOKarrow; - } -#endif - else if (*p == '-') - { p++; - t->value = TOKminusminus; - } - else - t->value = TOKmin; - return; - - case '+': - p++; - if (*p == '=') - { p++; - t->value = TOKaddass; - } - else if (*p == '+') - { p++; - t->value = TOKplusplus; - } - else - t->value = TOKadd; - return; - - case '<': - p++; - if (*p == '=') - { p++; - t->value = TOKle; // <= - } - else if (*p == '<') - { p++; - if (*p == '=') - { p++; - t->value = TOKshlass; // <<= - } - else - t->value = TOKshl; // << - } - else if (*p == '>') - { p++; - if (*p == '=') - { p++; - t->value = TOKleg; // <>= - } - else - t->value = TOKlg; // <> - } - else - t->value = TOKlt; // < - return; - - case '>': - p++; - if (*p == '=') - { p++; - t->value = TOKge; // >= - } - else if (*p == '>') - { p++; - if (*p == '=') - { p++; - t->value = TOKshrass; // >>= - } - else if (*p == '>') - { p++; - if (*p == '=') - { p++; - t->value = TOKushrass; // >>>= - } - else - t->value = TOKushr; // >>> - } - else - t->value = TOKshr; // >> - } - else - t->value = TOKgt; // > - return; - - case '!': - p++; - if (*p == '=') - { p++; - if (*p == '=') - { p++; - t->value = TOKnotidentity; // !== - } - else - t->value = TOKnotequal; // != - } - else if (*p == '<') - { p++; - if (*p == '>') - { p++; - if (*p == '=') - { p++; - t->value = TOKunord; // !<>= - } - else - t->value = TOKue; // !<> - } - else if (*p == '=') - { p++; - t->value = TOKug; // !<= - } - else - t->value = TOKuge; // !< - } - else if (*p == '>') - { p++; - if (*p == '=') - { p++; - t->value = TOKul; // !>= - } - else - t->value = TOKule; // !> - } - else - t->value = TOKnot; // ! - return; - - case '=': - p++; - if (*p == '=') - { p++; - if (*p == '=') - { p++; - t->value = TOKidentity; // === - } - else - t->value = TOKequal; // == - } - else - t->value = TOKassign; // = - return; - -#define SINGLE(c,tok) case c: p++; t->value = tok; return; - - SINGLE('(', TOKlparen) - SINGLE(')', TOKrparen) - SINGLE('[', TOKlbracket) - SINGLE(']', TOKrbracket) - SINGLE('{', TOKlcurly) - SINGLE('}', TOKrcurly) - SINGLE('?', TOKquestion) - SINGLE(',', TOKcomma) - SINGLE(';', TOKsemicolon) - SINGLE(':', TOKcolon) - SINGLE('$', TOKdollar) - -#undef SINGLE - -#define DOUBLE(c1,tok1,c2,tok2) \ - case c1: \ - p++; \ - if (*p == c2) \ - { p++; \ - t->value = tok2; \ - } \ - else \ - t->value = tok1; \ - return; - - DOUBLE('*', TOKmul, '=', TOKmulass) - DOUBLE('%', TOKmod, '=', TOKmodass) - DOUBLE('^', TOKxor, '=', TOKxorass) - DOUBLE('~', TOKtilde, '=', TOKcatass) - -#undef DOUBLE - - case '#': - p++; - pragma(); - continue; - - default: - { unsigned char c = *p; - - if (c & 0x80) - { unsigned u = decodeUTF(); - - // Check for start of unicode identifier - if (isUniAlpha(u)) - goto case_ident; - - if (u == PS || u == LS) - { - loc.linnum++; - p++; - continue; - } - } - if (isprint(c)) - error("unsupported char '%c'", c); - else - error("unsupported char 0x%02x", c); - p++; - continue; - } - } - } -} - -/******************************************* - * Parse escape sequence. - */ - -unsigned Lexer::escapeSequence() -{ unsigned c; - int n; - int ndigits; - - c = *p; - switch (c) - { - case '\'': - case '"': - case '?': - case '\\': - Lconsume: - p++; - break; - - case 'a': c = 7; goto Lconsume; - case 'b': c = 8; goto Lconsume; - case 'f': c = 12; goto Lconsume; - case 'n': c = 10; goto Lconsume; - case 'r': c = 13; goto Lconsume; - case 't': c = 9; goto Lconsume; - case 'v': c = 11; goto Lconsume; - - case 'u': - ndigits = 4; - goto Lhex; - case 'U': - ndigits = 8; - goto Lhex; - case 'x': - ndigits = 2; - Lhex: - p++; - c = *p; - if (ishex(c)) - { unsigned v; - - n = 0; - v = 0; - while (1) - { - if (isdigit(c)) - c -= '0'; - else if (islower(c)) - c -= 'a' - 10; - else - c -= 'A' - 10; - v = v * 16 + c; - c = *++p; - if (++n == ndigits) - break; - if (!ishex(c)) - { error("escape hex sequence has %d hex digits instead of %d", n, ndigits); - break; - } - } - if (ndigits != 2 && !utf_isValidDchar(v)) - error("invalid UTF character \\U%08x", v); - c = v; - } - else - error("undefined escape hex sequence \\%c\n",c); - break; - - case '&': // named character entity - for (unsigned char *idstart = ++p; 1; p++) - { - switch (*p) - { - case ';': - c = HtmlNamedEntity(idstart, p - idstart); - if (c == ~0) - { error("unnamed character entity &%.*s;", p - idstart, idstart); - c = ' '; - } - p++; - break; - - default: - if (isalpha(*p) || - (p != idstart + 1 && isdigit(*p))) - continue; - error("unterminated named entity"); - break; - } - break; - } - break; - - case 0: - case 0x1A: // end of file - c = '\\'; - break; - - default: - if (isoctal(c)) - { unsigned char v; - - n = 0; - v = 0; - do - { - v = v * 8 + (c - '0'); - c = *++p; - } while (++n < 3 && isoctal(c)); - c = v; - } - else - error("undefined escape sequence \\%c\n",c); - break; - } - return c; -} - -/************************************** - */ - -TOK Lexer::wysiwygStringConstant(Token *t, int tc) -{ unsigned c; - Loc start = loc; - - p++; - stringbuffer.reset(); - while (1) - { - c = *p++; - switch (c) - { - case '\n': - loc.linnum++; - break; - - case '\r': - if (*p == '\n') - continue; // ignore - c = '\n'; // treat EndOfLine as \n character - loc.linnum++; - break; - - case 0: - case 0x1A: - error("unterminated string constant starting at %s", start.toChars()); - t->ustring = (unsigned char *)""; - t->len = 0; - return TOKstring; - - case '"': - case '`': - if (c == tc) - { - t->len = stringbuffer.offset; - stringbuffer.writeByte(0); - t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset); - memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); - return TOKstring; - } - break; - - default: - if (c & 0x80) - { p--; - unsigned u = decodeUTF(); - p++; - if (u == PS || u == LS) - loc.linnum++; - } - break; - } - stringbuffer.writeByte(c); - } -} - -/************************************** - * Lex hex strings: - * x"0A ae 34FE BD" - */ - -TOK Lexer::hexStringConstant(Token *t) -{ unsigned c; - Loc start = loc; - unsigned n = 0; - unsigned v; - - p++; - stringbuffer.reset(); - while (1) - { - c = *p++; - switch (c) - { - case ' ': - case '\t': - case '\v': - case '\f': - continue; // skip white space - - case '\r': - if (*p == '\n') - continue; // ignore - // Treat isolated '\r' as if it were a '\n' - case '\n': - loc.linnum++; - continue; - - case 0: - case 0x1A: - error("unterminated string constant starting at %s", start.toChars()); - t->ustring = (unsigned char *)""; - t->len = 0; - return TOKstring; - - case '"': - if (n & 1) - { error("odd number (%d) of hex characters in hex string", n); - stringbuffer.writeByte(v); - } - t->len = stringbuffer.offset; - stringbuffer.writeByte(0); - t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset); - memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); - return TOKstring; - - default: - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'a' && c <= 'f') - c -= 'a' - 10; - else if (c >= 'A' && c <= 'F') - c -= 'A' - 10; - else if (c & 0x80) - { p--; - unsigned u = decodeUTF(); - p++; - if (u == PS || u == LS) - loc.linnum++; - else - error("non-hex character \\u%x", u); - } - else - error("non-hex character '%c'", c); - if (n & 1) - { v = (v << 4) | c; - stringbuffer.writeByte(v); - } - else - v = c; - n++; - break; - } - } -} - -/************************************** - */ - -TOK Lexer::escapeStringConstant(Token *t, int wide) -{ unsigned c; - Loc start = loc; - - p++; - stringbuffer.reset(); - while (1) - { - c = *p++; - switch (c) - { - case '\\': - switch (*p) - { - case 'u': - case 'U': - case '&': - c = escapeSequence(); - stringbuffer.writeUTF8(c); - continue; - - default: - c = escapeSequence(); - break; - } - break; - - case '\n': - loc.linnum++; - break; - - case '\r': - if (*p == '\n') - continue; // ignore - c = '\n'; // treat EndOfLine as \n character - loc.linnum++; - break; - - case '"': - t->len = stringbuffer.offset; - stringbuffer.writeByte(0); - t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset); - memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); - return TOKstring; - - case 0: - case 0x1A: - p--; - error("unterminated string constant starting at %s", start.toChars()); - t->ustring = (unsigned char *)""; - t->len = 0; - return TOKstring; - - default: - if (c & 0x80) - { - p--; - c = decodeUTF(); - if (c == LS || c == PS) - { c = '\n'; - loc.linnum++; - } - p++; - stringbuffer.writeUTF8(c); - continue; - } - break; - } - stringbuffer.writeByte(c); - } -} - -/************************************** - */ - -TOK Lexer::charConstant(Token *t, int wide) -{ - unsigned c; - TOK tk = TOKcharv; - - //printf("Lexer::charConstant\n"); - p++; - c = *p++; - switch (c) - { - case '\\': - switch (*p) - { - case 'u': - t->uns64value = escapeSequence(); - tk = TOKwcharv; - break; - - case 'U': - case '&': - t->uns64value = escapeSequence(); - tk = TOKdcharv; - break; - - default: - t->uns64value = escapeSequence(); - break; - } - break; - - case '\n': - L1: - loc.linnum++; - case '\r': - case 0: - case 0x1A: - case '\'': - error("unterminated character constant"); - return tk; - - default: - if (c & 0x80) - { - p--; - c = decodeUTF(); - p++; - if (c == LS || c == PS) - goto L1; - if (c < 0xD800 || (c >= 0xE000 && c < 0xFFFE)) - tk = TOKwcharv; - else - tk = TOKdcharv; - } - t->uns64value = c; - break; - } - - if (*p != '\'') - { error("unterminated character constant"); - return tk; - } - p++; - return tk; -} - -/*************************************** - * Read \u or \U unicode sequence - * Input: - * u 'u' or 'U' - */ - -unsigned Lexer::wchar(unsigned u) -{ - unsigned value; - unsigned n; - unsigned char c; - unsigned nchars; - - nchars = (u == 'U') ? 8 : 4; - value = 0; - for (n = 0; 1; n++) - { - ++p; - if (n == nchars) - break; - c = *p; - if (!ishex(c)) - { error("\\%c sequence must be followed by %d hex characters", u, nchars); - break; - } - if (isdigit(c)) - c -= '0'; - else if (islower(c)) - c -= 'a' - 10; - else - c -= 'A' - 10; - value <<= 4; - value |= c; - } - return value; -} - -/************************************** - * Read in a number. - * If it's an integer, store it in tok.TKutok.Vlong. - * integers can be decimal, octal or hex - * Handle the suffixes U, UL, LU, L, etc. - * If it's double, store it in tok.TKutok.Vdouble. - * Returns: - * TKnum - * TKdouble,... - */ - -TOK Lexer::number(Token *t) -{ - // We use a state machine to collect numbers - enum STATE { STATE_initial, STATE_0, STATE_decimal, STATE_octal, STATE_octale, - STATE_hex, STATE_binary, STATE_hex0, STATE_binary0, - STATE_hexh, STATE_error }; - enum STATE state; - - enum FLAGS - { FLAGS_decimal = 1, // decimal - FLAGS_unsigned = 2, // u or U suffix - FLAGS_long = 4, // l or L suffix - }; - enum FLAGS flags = FLAGS_decimal; - - int i; - int base; - unsigned c; - unsigned char *start; - integer_t n; - TOK result; - - //printf("Lexer::number()\n"); - state = STATE_initial; - base = 0; - stringbuffer.reset(); - start = p; - while (1) - { - c = *p; - switch (state) - { - case STATE_initial: // opening state - if (c == '0') - state = STATE_0; - else - state = STATE_decimal; - break; - - case STATE_0: - flags = (FLAGS) (flags & ~FLAGS_decimal); - switch (c) - { -#if ZEROH - case 'H': // 0h - case 'h': - goto hexh; -#endif - case 'X': - case 'x': - state = STATE_hex0; - break; - - case '.': - if (p[1] == '.') // .. is a separate token - goto done; - case 'i': - case 'f': - case 'F': - goto real; -#if ZEROH - case 'E': - case 'e': - goto case_hex; -#endif - case 'B': - case 'b': - state = STATE_binary0; - break; - - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - state = STATE_octal; - break; - -#if ZEROH - case '8': case '9': case 'A': - case 'C': case 'D': case 'F': - case 'a': case 'c': case 'd': case 'f': - case_hex: - state = STATE_hexh; - break; -#endif - case '_': - state = STATE_octal; - p++; - continue; - - default: - goto done; - } - break; - - case STATE_decimal: // reading decimal number - if (!isdigit(c)) - { -#if ZEROH - if (ishex(c) - || c == 'H' || c == 'h' - ) - goto hexh; -#endif - if (c == '_') // ignore embedded _ - { p++; - continue; - } - if (c == '.' && p[1] != '.') - goto real; - else if (c == 'i' || c == 'f' || c == 'F' || - c == 'e' || c == 'E') - { - real: // It's a real number. Back up and rescan as a real - p = start; - return inreal(t); - } - goto done; - } - break; - - case STATE_hex0: // reading hex number - case STATE_hex: - if (!ishex(c)) - { - if (c == '_') // ignore embedded _ - { p++; - continue; - } - if (c == '.' && p[1] != '.') - goto real; - if (c == 'P' || c == 'p' || c == 'i') - goto real; - if (state == STATE_hex0) - error("Hex digit expected, not '%c'", c); - goto done; - } - state = STATE_hex; - break; - -#if ZEROH - hexh: - state = STATE_hexh; - case STATE_hexh: // parse numbers like 0FFh - if (!ishex(c)) - { - if (c == 'H' || c == 'h') - { - p++; - base = 16; - goto done; - } - else - { - // Check for something like 1E3 or 0E24 - if (memchr((char *)stringbuffer.data, 'E', stringbuffer.offset) || - memchr((char *)stringbuffer.data, 'e', stringbuffer.offset)) - goto real; - error("Hex digit expected, not '%c'", c); - goto done; - } - } - break; -#endif - - case STATE_octal: // reading octal number - case STATE_octale: // reading octal number with non-octal digits - if (!isoctal(c)) - { -#if ZEROH - if (ishex(c) - || c == 'H' || c == 'h' - ) - goto hexh; -#endif - if (c == '_') // ignore embedded _ - { p++; - continue; - } - if (c == '.' && p[1] != '.') - goto real; - if (c == 'i') - goto real; - if (isdigit(c)) - { - state = STATE_octale; - } - else - goto done; - } - break; - - case STATE_binary0: // starting binary number - case STATE_binary: // reading binary number - if (c != '0' && c != '1') - { -#if ZEROH - if (ishex(c) - || c == 'H' || c == 'h' - ) - goto hexh; -#endif - if (c == '_') // ignore embedded _ - { p++; - continue; - } - if (state == STATE_binary0) - { error("binary digit expected"); - state = STATE_error; - break; - } - else - goto done; - } - state = STATE_binary; - break; - - case STATE_error: // for error recovery - if (!isdigit(c)) // scan until non-digit - goto done; - break; - - default: - assert(0); - } - stringbuffer.writeByte(c); - p++; - } -done: - stringbuffer.writeByte(0); // terminate string - if (state == STATE_octale) - error("Octal digit expected"); - - if (stringbuffer.offset == 1 && (state == STATE_decimal || state == STATE_0)) - n = stringbuffer.data[0] - '0'; - else - { - // Convert string to integer -#if __DMC__ - errno = 0; - n = strtoull((char *)stringbuffer.data,NULL,base); - if (errno == ERANGE) - error("integer overflow"); -#else - // Not everybody implements strtoull() - char *p = (char *)stringbuffer.data; - int r = 10, d; - - if (*p == '0') - { - if (p[1] == 'x' || p[1] == 'X') - p += 2, r = 16; - else if (p[1] == 'b' || p[1] == 'B') - p += 2, r = 2; - else if (isdigit(p[1])) - p += 1, r = 8; - } - - n = 0; - while (1) - { - if (*p >= '0' && *p <= '9') - d = *p - '0'; - else if (*p >= 'a' && *p <= 'z') - d = *p - 'a' + 10; - else if (*p >= 'A' && *p <= 'Z') - d = *p - 'A' + 10; - else - break; - if (d >= r) - break; - if (n * r + d < n) - { - error ("integer overflow"); - break; - } - - n = n * r + d; - p++; - } -#endif - } - - // Parse trailing 'u', 'U', 'l' or 'L' in any combination - while (1) - { unsigned char f; - - switch (*p) - { case 'U': - case 'u': - f = FLAGS_unsigned; - goto L1; - case 'L': - case 'l': - f = FLAGS_long; - L1: - p++; - if (flags & f) - error("unrecognized token"); - flags = (FLAGS) (flags | f); - continue; - default: - break; - } - break; - } - - assert(sizeof(long) == 4); // some dependencies - switch (flags) - { - case 0: - if (n & 0x8000000000000000LL) - result = TOKuns64v; - else if (n & 0xFFFFFFFF00000000LL) - result = TOKint64v; - else if (n & 0x80000000) - result = TOKuns32v; - else - result = TOKint32v; - break; - - case FLAGS_decimal: - if (n & 0x8000000000000000LL) - { error("signed integer overflow"); - result = TOKuns64v; - } - else if (n & 0xFFFFFFFF80000000LL) - result = TOKint64v; - else - result = TOKint32v; - break; - - case FLAGS_unsigned: - case FLAGS_decimal | FLAGS_unsigned: - if (n & 0xFFFFFFFF00000000LL) - result = TOKuns64v; - else - result = TOKuns32v; - break; - - case FLAGS_decimal | FLAGS_long: - if (n & 0x8000000000000000LL) - { error("signed integer overflow"); - result = TOKuns64v; - } - else - result = TOKint64v; - break; - - case FLAGS_long: - if (n & 0x8000000000000000LL) - result = TOKuns64v; - else - result = TOKint64v; - break; - - case FLAGS_unsigned | FLAGS_long: - case FLAGS_decimal | FLAGS_unsigned | FLAGS_long: - result = TOKuns64v; - break; - - default: - #ifdef DEBUG - printf("%x\n",flags); - #endif - assert(0); - } - t->uns64value = n; - return result; -} - -/************************************** - * Read in characters, converting them to real. - * Bugs: - * Exponent overflow not detected. - * Too much requested precision is not detected. - */ - -TOK Lexer::inreal(Token *t) -#ifdef __DMC__ -__in -{ - assert(*p == '.' || isdigit(*p)); -} -__out (result) -{ - switch (result) - { - case TOKfloat32v: - case TOKfloat64v: - case TOKfloat80v: - case TOKimaginary32v: - case TOKimaginary64v: - case TOKimaginary80v: - break; - - default: - assert(0); - } -} -__body -#endif /* __DMC__ */ -{ int dblstate; - unsigned c; - char hex; // is this a hexadecimal-floating-constant? - TOK result; - - //printf("Lexer::inreal()\n"); - stringbuffer.reset(); - dblstate = 0; - hex = 0; -Lnext: - while (1) - { - // Get next char from input - c = *p++; - //printf("dblstate = %d, c = '%c'\n", dblstate, c); - while (1) - { - switch (dblstate) - { - case 0: // opening state - if (c == '0') - dblstate = 9; - else if (c == '.') - dblstate = 3; - else - dblstate = 1; - break; - - case 9: - dblstate = 1; - if (c == 'X' || c == 'x') - { hex++; - break; - } - case 1: // digits to left of . - case 3: // digits to right of . - case 7: // continuing exponent digits - if (!isdigit(c) && !(hex && isxdigit(c))) - { - if (c == '_') - goto Lnext; // ignore embedded '_' - dblstate++; - continue; - } - break; - - case 2: // no more digits to left of . - if (c == '.') - { dblstate++; - break; - } - case 4: // no more digits to right of . - if ((c == 'E' || c == 'e') || - hex && (c == 'P' || c == 'p')) - { dblstate = 5; - hex = 0; // exponent is always decimal - break; - } - if (hex) - error("binary-exponent-part required"); - goto done; - - case 5: // looking immediately to right of E - dblstate++; - if (c == '-' || c == '+') - break; - case 6: // 1st exponent digit expected - if (!isdigit(c)) - error("exponent expected"); - dblstate++; - break; - - case 8: // past end of exponent digits - goto done; - } - break; - } - stringbuffer.writeByte(c); - } -done: - p--; - - stringbuffer.writeByte(0); - -#if _WIN32 && __DMC__ - char *save = __locale_decpoint; - __locale_decpoint = "."; -#endif -#ifdef IN_GCC - t->float80value = real_t::parse((char *)stringbuffer.data, real_t::LongDouble); -#else - t->float80value = strtold((char *)stringbuffer.data, NULL); -#endif - errno = 0; - switch (*p) - { - case 'F': - case 'f': -#ifdef IN_GCC - real_t::parse((char *)stringbuffer.data, real_t::Float); -#else - strtof((char *)stringbuffer.data, NULL); -#endif - result = TOKfloat32v; - p++; - break; - - default: -#ifdef IN_GCC - real_t::parse((char *)stringbuffer.data, real_t::Double); -#else - strtod((char *)stringbuffer.data, NULL); -#endif - result = TOKfloat64v; - break; - - case 'L': - case 'l': - result = TOKfloat80v; - p++; - break; - } - if (*p == 'i' || *p == 'I') - { - p++; - switch (result) - { - case TOKfloat32v: - result = TOKimaginary32v; - break; - case TOKfloat64v: - result = TOKimaginary64v; - break; - case TOKfloat80v: - result = TOKimaginary80v; - break; - } - } -#if _WIN32 && __DMC__ - __locale_decpoint = save; -#endif - if (errno == ERANGE) - error("number is not representable"); - return result; -} - -/********************************************* - * Do pragma. - * Currently, the only pragma supported is: - * #line linnum [filespec] - */ - -void Lexer::pragma() -{ - Token tok; - int linnum; - char *filespec = NULL; - - scan(&tok); - if (tok.value != TOKidentifier || tok.ident != Id::line) - goto Lerr; - - scan(&tok); - if (tok.value != TOKint32v) - goto Lerr; - linnum = tok.uns64value - 1; - - while (1) - { - switch (*p) - { - case 0: - case 0x1A: - case '\n': - Lnewline: - loc.linnum = linnum; - return; - - case '\r': - p++; - if (*p != '\n') - loc.linnum = linnum; - continue; - - case ' ': - case '\t': - case '\v': - case '\f': - p++; - continue; // skip white space - - case '"': - if (filespec) - goto Lerr; - stringbuffer.reset(); - p++; - while (1) - { unsigned c; - - c = *p; - switch (c) - { - case '\n': - case '\r': - case 0: - case 0x1A: - goto Lerr; - - case '"': - stringbuffer.writeByte(0); - filespec = mem.strdup((char *)stringbuffer.data); - loc.filename = filespec; - p++; - break; - - default: - if (c & 0x80) - { unsigned u = decodeUTF(); - if (u == PS || u == LS) - goto Lerr; - } - stringbuffer.writeByte(c); - p++; - continue; - } - break; - } - continue; - - default: - if (*p & 0x80) - { unsigned u = decodeUTF(); - if (u == PS || u == LS) - goto Lnewline; - } - goto Lerr; - } - } - -Lerr: - error("#line integer [\"filespec\"]\\n expected"); -} - - -/******************************************** - * Decode UTF character. - * Issue error messages for invalid sequences. - * Return decoded character, advance p to last character in UTF sequence. - */ - -unsigned Lexer::decodeUTF() -{ - dchar_t u; - unsigned char c; - unsigned char *s = p; - unsigned len; - unsigned idx; - char *msg; - - c = *s; - if (!(c & 0x80)) - return c; - - // Check length of remaining string up to 6 UTF-8 characters - for (len = 1; len < 6 && s[len]; len++) - ; - - idx = 0; - msg = utf_decodeChar(s, len, &idx, &u); - p += idx - 1; - if (msg) - { - error(msg); - } - return u; -} - -/******************************************** - * Create an identifier in the string table. - */ - -Identifier *Lexer::idPool(const char *s) -{ unsigned len; - Identifier *id; - StringValue *sv; - - len = strlen(s); - sv = stringtable.update(s, len); - id = (Identifier *) sv->ptrvalue; - if (!id) - { - id = new Identifier(sv->lstring.string, TOKidentifier); - sv->ptrvalue = id; - } - return id; -} - -/**************************************** - */ - -struct Keyword -{ char *name; - enum TOK value; -}; - -static Keyword keywords[] = -{ -// { "", TOK }, - - { "this", TOKthis }, - { "super", TOKsuper }, - { "assert", TOKassert }, - { "null", TOKnull }, - { "true", TOKtrue }, - { "false", TOKfalse }, - { "cast", TOKcast }, - { "new", TOKnew }, - { "delete", TOKdelete }, - { "throw", TOKthrow }, - { "module", TOKmodule }, - { "pragma", TOKpragma }, - { "typeof", TOKtypeof }, - { "typeid", TOKtypeid }, - - { "template", TOKtemplate }, - { "instance", TOKinstance }, - - { "void", TOKvoid }, - { "byte", TOKint8 }, - { "ubyte", TOKuns8 }, - { "short", TOKint16 }, - { "ushort", TOKuns16 }, - { "int", TOKint32 }, - { "uint", TOKuns32 }, - { "long", TOKint64 }, - { "ulong", TOKuns64 }, - { "cent", TOKcent, }, - { "ucent", TOKucent, }, - { "float", TOKfloat32 }, - { "double", TOKfloat64 }, - { "real", TOKfloat80 }, - - { "bit", TOKbit }, - { "char", TOKchar }, - { "wchar", TOKwchar }, - { "dchar", TOKdchar }, - - { "ifloat", TOKimaginary32 }, - { "idouble", TOKimaginary64 }, - { "ireal", TOKimaginary80 }, - - { "cfloat", TOKcomplex32 }, - { "cdouble", TOKcomplex64 }, - { "creal", TOKcomplex80 }, - - { "delegate", TOKdelegate }, - { "function", TOKfunction }, - - { "is", TOKidentity }, - { "if", TOKif }, - { "else", TOKelse }, - { "while", TOKwhile }, - { "for", TOKfor }, - { "do", TOKdo }, - { "switch", TOKswitch }, - { "case", TOKcase }, - { "default", TOKdefault }, - { "break", TOKbreak }, - { "continue", TOKcontinue }, - { "synchronized", TOKsynchronized }, - { "return", TOKreturn }, - { "goto", TOKgoto }, - { "try", TOKtry }, - { "catch", TOKcatch }, - { "finally", TOKfinally }, - { "with", TOKwith }, - { "asm", TOKasm }, - { "foreach", TOKforeach }, - - { "struct", TOKstruct }, - { "class", TOKclass }, - { "interface", TOKinterface }, - { "union", TOKunion }, - { "enum", TOKenum }, - { "import", TOKimport }, - { "mixin", TOKmixin }, - { "static", TOKstatic }, - /*{ "virtual", TOKvirtual },*/ - { "final", TOKfinal }, - { "const", TOKconst }, - { "typedef", TOKtypedef }, - { "alias", TOKalias }, - { "override", TOKoverride }, - { "abstract", TOKabstract }, - { "volatile", TOKvolatile }, - { "debug", TOKdebug }, - { "deprecated", TOKdeprecated }, - { "in", TOKin }, - { "out", TOKout }, - { "inout", TOKinout }, - { "auto", TOKauto }, - - { "align", TOKalign }, - { "extern", TOKextern }, - { "private", TOKprivate }, - { "package", TOKpackage }, - { "protected", TOKprotected }, - { "public", TOKpublic }, - { "export", TOKexport }, - - { "body", TOKbody }, - { "invariant", TOKinvariant }, - { "unittest", TOKunittest }, - { "version", TOKversion }, -}; - -void Lexer::initKeywords() -{ StringValue *sv; - unsigned u; - enum TOK v; - - cmtable_init(); - - for (u = 0; u < sizeof(keywords) / sizeof(keywords[0]); u++) - { char *s; - - //printf("keyword[%d] = '%s'\n",u, keywords[u].name); - s = keywords[u].name; - v = keywords[u].value; - sv = stringtable.insert(s, strlen(s)); - sv->ptrvalue = (void *) new Identifier(sv->lstring.string,v); - - //printf("tochars[%d] = '%s'\n",v, s); - Token::tochars[v] = s; - } - - Token::tochars[TOKeof] = "EOF"; - Token::tochars[TOKlcurly] = "{"; - Token::tochars[TOKrcurly] = "}"; - Token::tochars[TOKlparen] = "("; - Token::tochars[TOKrparen] = ")"; - Token::tochars[TOKlbracket] = "["; - Token::tochars[TOKrbracket] = "]"; - Token::tochars[TOKsemicolon] = ";"; - Token::tochars[TOKcolon] = ":"; - Token::tochars[TOKcomma] = ","; - Token::tochars[TOKdot] = "."; - Token::tochars[TOKxor] = "^"; - Token::tochars[TOKxorass] = "^="; - Token::tochars[TOKassign] = "="; - Token::tochars[TOKlt] = "<"; - Token::tochars[TOKgt] = ">"; - Token::tochars[TOKle] = "<="; - Token::tochars[TOKge] = ">="; - Token::tochars[TOKequal] = "=="; - Token::tochars[TOKnotequal] = "!="; -// Token::tochars[TOKidentity] = "==="; - Token::tochars[TOKnotidentity] = "!=="; - - Token::tochars[TOKunord] = "!<>="; - Token::tochars[TOKue] = "!<>"; - Token::tochars[TOKlg] = "<>"; - Token::tochars[TOKleg] = "<>="; - Token::tochars[TOKule] = "!>"; - Token::tochars[TOKul] = "!>="; - Token::tochars[TOKuge] = "!<"; - Token::tochars[TOKug] = "!<="; - - Token::tochars[TOKnot] = "!"; - Token::tochars[TOKshl] = "<<"; - Token::tochars[TOKshr] = ">>"; - Token::tochars[TOKushr] = ">>>"; - Token::tochars[TOKadd] = "+"; - Token::tochars[TOKmin] = "-"; - Token::tochars[TOKmul] = "*"; - Token::tochars[TOKdiv] = "/"; - Token::tochars[TOKmod] = "%"; - Token::tochars[TOKslice] = ".."; - Token::tochars[TOKdotdotdot] = "..."; - Token::tochars[TOKand] = "&"; - Token::tochars[TOKandand] = "&&"; - Token::tochars[TOKor] = "|"; - Token::tochars[TOKoror] = "||"; - Token::tochars[TOKarray] = "[]"; - Token::tochars[TOKindex] = "[]"; - Token::tochars[TOKaddress] = "#"; - Token::tochars[TOKstar] = "*"; - Token::tochars[TOKtilde] = "~"; - Token::tochars[TOKdollar] = "$"; - Token::tochars[TOKcast] = "cast"; - Token::tochars[TOKplusplus] = "++"; - Token::tochars[TOKminusminus] = "--"; - Token::tochars[TOKtype] = "type"; - Token::tochars[TOKquestion] = "?"; - Token::tochars[TOKneg] = "-"; - Token::tochars[TOKuadd] = "+"; - Token::tochars[TOKvar] = "var"; - Token::tochars[TOKaddass] = "+="; - Token::tochars[TOKminass] = "-="; - Token::tochars[TOKmulass] = "*="; - Token::tochars[TOKdivass] = "/="; - Token::tochars[TOKmodass] = "%="; - Token::tochars[TOKshlass] = "<<="; - Token::tochars[TOKshrass] = ">>="; - Token::tochars[TOKushrass] = ">>>="; - Token::tochars[TOKandass] = "&="; - Token::tochars[TOKorass] = "|="; - Token::tochars[TOKcatass] = "~="; - Token::tochars[TOKcat] = "~"; - Token::tochars[TOKcall] = "call"; - - Token::tochars[TOKorass] = "|="; - - // For debugging - Token::tochars[TOKdotexp] = "dotexp"; - Token::tochars[TOKdotti] = "dotti"; - Token::tochars[TOKdotvar] = "dotvar"; - Token::tochars[TOKdottype] = "dottype"; - Token::tochars[TOKsymoff] = "symoff"; - Token::tochars[TOKtypedot] = "typedot"; - Token::tochars[TOKarraylength] = "arraylength"; - Token::tochars[TOKstring] = "string"; -} diff -uNr gdc-0.11/d/root/lexer.h gdc-0.12/d/root/lexer.h --- gdc-0.11/d/root/lexer.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/lexer.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,260 +0,0 @@ - - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef DMD_LEXER_H -#define DMD_LEXER_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" -#include "mars.h" - -struct StringTable; -struct Identifier; -struct Module; - -/* Tokens: - ( ) - [ ] - { } - < > <= >= == != === !== - << >> <<= >>= >>> >>>= - + - += -= - * / % *= /= %= - & | ^ &= |= ^= - = ! ~ - ++ -- - . -> : , - ? && || - */ - -enum TOK -{ - TOKreserved, - - // Other - TOKlparen, TOKrparen, - TOKlbracket, TOKrbracket, - TOKlcurly, TOKrcurly, - TOKcolon, TOKneg, - TOKsemicolon, TOKdotdotdot, - TOKeof, TOKcast, - TOKnull, TOKassert, - TOKtrue, TOKfalse, - TOKarray, TOKcall, - TOKaddress, TOKtypedot, - TOKtype, TOKthrow, - TOKnew, TOKdelete, - TOKstar, TOKsymoff, - TOKvar, TOKdotvar, - TOKdotti, TOKdotexp, - TOKdottype, TOKslice, - TOKarraylength, TOKversion, - TOKmodule, TOKdollar, - TOKtemplate, TOKinstance, - TOKdeclaration, TOKtypeof, - TOKpragma, TOKdsymbol, - TOKtypeid, TOKuadd, - - // Operators - TOKlt, TOKgt, - TOKle, TOKge, - TOKequal, TOKnotequal, - TOKidentity, TOKnotidentity, - TOKindex, - - // NCEG floating point compares - // !<>= <> <>= !> !>= !< !<= !<> - TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue, - - TOKshl, TOKshr, - TOKshlass, TOKshrass, - TOKushr, TOKushrass, - TOKcat, TOKcatass, // ~ ~= - TOKadd, TOKmin, TOKaddass, TOKminass, - TOKmul, TOKdiv, TOKmod, - TOKmulass, TOKdivass, TOKmodass, - TOKand, TOKor, TOKxor, - TOKandass, TOKorass, TOKxorass, - TOKassign, TOKnot, TOKtilde, - TOKplusplus, TOKminusminus, - TOKdot, TOKarrow, TOKcomma, - TOKquestion, TOKandand, TOKoror, - - // Numeric literals - TOKint32v, TOKuns32v, - TOKint64v, TOKuns64v, - TOKfloat32v, TOKfloat64v, TOKfloat80v, - TOKimaginary32v, TOKimaginary64v, TOKimaginary80v, - - // Char constants - TOKcharv, TOKwcharv, TOKdcharv, - - // Leaf operators - TOKidentifier, TOKstring, - TOKthis, TOKsuper, - TOKhalt, - - // Basic types - TOKvoid, - TOKint8, TOKuns8, - TOKint16, TOKuns16, - TOKint32, TOKuns32, - TOKint64, TOKuns64, - TOKfloat32, TOKfloat64, TOKfloat80, - TOKimaginary32, TOKimaginary64, TOKimaginary80, - TOKcomplex32, TOKcomplex64, TOKcomplex80, - TOKchar, TOKwchar, TOKdchar, TOKbit, - TOKcent, TOKucent, - - // Aggregates - TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport, - TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction, - TOKmixin, - - TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport, - TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile, - TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, - TOKauto, TOKpackage, - - // Statements - TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch, - TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith, - TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally, - TOKasm, TOKforeach, - - // Contracts - TOKbody, TOKinvariant, - - // Testing - TOKunittest, - - TOKMAX -}; - -#define CASE_BASIC_TYPES \ - case TOKwchar: case TOKdchar: \ - case TOKbit: case TOKchar: \ - case TOKint8: case TOKuns8: \ - case TOKint16: case TOKuns16: \ - case TOKint32: case TOKuns32: \ - case TOKint64: case TOKuns64: \ - case TOKfloat32: case TOKfloat64: case TOKfloat80: \ - case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \ - case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \ - case TOKvoid - -#define CASE_BASIC_TYPES_X(t) \ - case TOKvoid: t = Type::tvoid; goto LabelX; \ - case TOKint8: t = Type::tint8; goto LabelX; \ - case TOKuns8: t = Type::tuns8; goto LabelX; \ - case TOKint16: t = Type::tint16; goto LabelX; \ - case TOKuns16: t = Type::tuns16; goto LabelX; \ - case TOKint32: t = Type::tint32; goto LabelX; \ - case TOKuns32: t = Type::tuns32; goto LabelX; \ - case TOKint64: t = Type::tint64; goto LabelX; \ - case TOKuns64: t = Type::tuns64; goto LabelX; \ - case TOKfloat32: t = Type::tfloat32; goto LabelX; \ - case TOKfloat64: t = Type::tfloat64; goto LabelX; \ - case TOKfloat80: t = Type::tfloat80; goto LabelX; \ - case TOKimaginary32: t = Type::timaginary32; goto LabelX; \ - case TOKimaginary64: t = Type::timaginary64; goto LabelX; \ - case TOKimaginary80: t = Type::timaginary80; goto LabelX; \ - case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \ - case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \ - case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \ - case TOKbit: t = Type::tbit; goto LabelX; \ - case TOKchar: t = Type::tchar; goto LabelX; \ - case TOKwchar: t = Type::twchar; goto LabelX; \ - case TOKdchar: t = Type::tdchar; goto LabelX; \ - LabelX - -struct Token -{ - Token *next; - unsigned char *ptr; // pointer to first character of this token within buffer - enum TOK value; - union - { - // Integers - d_int32 int32value; - d_uns32 uns32value; - d_int64 int64value; - d_uns64 uns64value; - - // Floats -#ifdef IN_GCC - // real_t float80value; // can't use this in a union! -#else - d_float80 float80value; -#endif - - struct - { unsigned char *ustring; // UTF8 string - unsigned len; - }; - Identifier *ident; - }; -#ifdef IN_GCC - real_t float80value; // can't use this in a union! -#endif - - static char *tochars[TOKMAX]; - static void *operator new(size_t sz); - - void print(); - char *toChars(); - static char *toChars(enum TOK); -}; - -struct Lexer -{ - static StringTable stringtable; - static OutBuffer stringbuffer; - static Token *freelist; - - Loc loc; // for error messages - - unsigned char *base; // pointer to start of buffer - unsigned char *end; // past end of buffer - unsigned char *p; // current character - Token token; - Module *mod; - - Lexer(Module *mod, unsigned char *base, unsigned length); - - static void initKeywords(); - static Identifier *idPool(const char *s); - - TOK nextToken(); - void scan(Token *t); - Token *peek(Token *t); - unsigned escapeSequence(); - TOK wysiwygStringConstant(Token *t, int tc); - TOK hexStringConstant(Token *t); - TOK escapeStringConstant(Token *t, int wide); - TOK charConstant(Token *t, int wide); - unsigned wchar(unsigned u); - TOK number(Token *t); - TOK inreal(Token *t); - void error(const char *format, ...); - void pragma(); - unsigned decodeUTF(); -}; - -#endif /* DMD_LEXER_H */ diff -uNr gdc-0.11/d/root/link.c gdc-0.12/d/root/link.c --- gdc-0.11/d/root/link.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/link.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,317 +0,0 @@ - - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#include -#include -#include -#include -#include -#include - -#if _WIN32 -#include -#endif - -#if linux -#include -#include -#include -#endif - -#include "root.h" - -#include "mars.h" - -#if linux -#include "mem.h" -#endif - -int executecmd(char *cmd, char *args, int useenv); -int executearg0(char *cmd, char *args); - -/***************************** - * Run the linker. Return status of execution. - */ - -int runLINK() -{ -#if _WIN32 - char *p; - int i; - int status; - OutBuffer cmdbuf; - - global.params.libfiles->push((void *) "user32"); - global.params.libfiles->push((void *) "kernel32"); - - for (i = 0; i < global.params.objfiles->dim; i++) - { - if (i) - cmdbuf.writeByte('+'); - p = (char *)global.params.objfiles->data[i]; - char *ext = FileName::ext(p); - if (ext) - cmdbuf.write(p, ext - p - 1); - else - cmdbuf.writestring(p); - } - cmdbuf.writeByte(','); - if (global.params.exefile) - cmdbuf.writestring(global.params.exefile); - - cmdbuf.writeByte(','); -// if (mapfile) -// cmdbuf.writestring(output); - cmdbuf.writeByte(','); - - for (i = 0; i < global.params.libfiles->dim; i++) - { - if (i) - cmdbuf.writeByte('+'); - cmdbuf.writestring((char *) global.params.libfiles->data[i]); - } - - if (global.params.deffile) - { - cmdbuf.writeByte(','); - cmdbuf.writestring(global.params.deffile); - } - - /* Eliminate unnecessary trailing commas */ - while (1) - { i = cmdbuf.offset; - if (!i || cmdbuf.data[i - 1] != ',') - break; - cmdbuf.offset--; - } - - if (global.params.resfile) - { - cmdbuf.writestring("/RC:"); - cmdbuf.writestring(global.params.resfile); - } - -#if 0 - if (mapfile) - cmdbuf.writestring("/m"); - if (debuginfo) - cmdbuf.writestring("/li"); - if (codeview) - { - cmdbuf.writestring("/co"); - if (codeview3) - cmdbuf.writestring(":3"); - } -#else - if (global.params.symdebug) - cmdbuf.writestring("/co"); -#endif - - cmdbuf.writestring("/noi"); - for (i = 0; i < global.params.linkswitches->dim; i++) - { - cmdbuf.writestring((char *) global.params.linkswitches->data[i]); - } - cmdbuf.writeByte(';'); - - p = cmdbuf.toChars(); - - char *linkcmd = getenv("LINKCMD"); - if (!linkcmd) - linkcmd = "link"; - status = executecmd(linkcmd, p, 1); - return status; -#elif linux - pid_t childpid; - int i; - int status; - - // Build argv[] - Array argv; - - argv.push((void *)"gcc"); - argv.insert(1, global.params.objfiles); - - // None of that a.out stuff. Use explicit exe file name, or - // generate one from name of first source file. - argv.push((void *)"-o"); - if (global.params.exefile) - { - argv.push(global.params.exefile); - } - else - { // Generate exe file name from first obj name - char *n = (char *)global.params.objfiles->data[0]; - char *e; - char *ex; - - n = FileName::name(n); - e = FileName::ext(n); - if (e) - { - e--; // back up over '.' - ex = (char *)mem.malloc(e - n + 1); - memcpy(ex, n, e - n); - ex[e - n] = 0; - } - else - ex = (char *)"a.out"; // no extension, so give up - argv.push(ex); - } - - argv.insert(argv.dim, global.params.libfiles); - - if (global.params.symdebug) - argv.push((void *)"-g"); - - argv.push((void *)"-lphobos"); // turns into /usr/lib/libphobos.a - argv.push((void *)"-lpthread"); - argv.push((void *)"-lm"); - - for (i = 0; i < global.params.linkswitches->dim; i++) - { - argv.push((void *)"-Xlinker"); - argv.push((void *) global.params.linkswitches->data[i]); - } - - // Print it - for (i = 0; i < argv.dim; i++) - printf("%s ", (char *)argv.data[i]); - printf("\n"); - fflush(stdout); - - argv.push(NULL); - childpid = fork(); - if (childpid == 0) - { - execvp((char *)argv.data[0], (char **)argv.data); - perror((char *)argv.data[0]); // failed to execute - return -1; - } - - waitpid(childpid, &status, 0); - - status=WEXITSTATUS(status); - if (status) - printf("--- errorlevel %d\n", status); - return status; -#else - printf ("Linking is not yet supported for this version of DMD.\n"); - return -1; -#endif -} - - -/****************************** - * Execute a rule. Return the status. - * cmd program to run - * args arguments to cmd, as a string - * useenv if cmd knows about _CMDLINE environment variable - */ - -#if _WIN32 -int executecmd(char *cmd, char *args, int useenv) -{ - int status; - char *buff; - size_t len; - -// if (global.params.verbose) - { - printf("%s %s\n",cmd,args); - fflush(stdout); - } - - if ((len = strlen(args)) > 255) - { char *q; - static char envname[] = "@_CMDLINE"; - - envname[0] = '@'; - switch (useenv) - { case 0: goto L1; - case 2: envname[0] = '%'; break; - } - q = (char *) alloca(sizeof(envname) + len + 1); - sprintf(q,"%s=%s", envname + 1, args); - status = putenv(q); - if (status == 0) - args = envname; - else - { - L1: - error("command line length of %d is too long",len); - } - } - - status = executearg0(cmd,args); -#if _WIN32 - if (status == -1) - status = spawnlp(0,cmd,cmd,args,NULL); -#endif - if (global.params.verbose) - printf("\n"); - if (status) - { - if (status == -1) - printf("Can't run '%s', check PATH\n", cmd); - else - printf("--- errorlevel %d\n", status); - } - return status; -} -#endif - -/************************************** - * Attempt to find command to execute by first looking in the directory - * where DMD was run from. - * Returns: - * -1 did not find command there - * !=-1 exit status from command - */ - -#if _WIN32 -int executearg0(char *cmd, char *args) -{ - char *file; - char *argv0 = global.params.argv0; - - //printf("argv0='%s', cmd='%s', args='%s'\n",argv0,cmd,args); - - // If cmd is fully qualified, we don't do this - if (FileName::absolute(cmd)) - return -1; - - file = FileName::replaceName(argv0, cmd); - - //printf("spawning '%s'\n",file); -#if _WIN32 - return spawnl(0,file,file,args,NULL); -#elif linux - char *full; - int cmdl = strlen(cmd); - - full = (char*) mem.malloc(cmdl + strlen(args) + 2); - if (full == NULL) - return 1; - strcpy(full, cmd); - full [cmdl] = ' '; - strcpy(full + cmdl + 1, args); - - int result = system(full); - - mem.free(full); - return result; -#else - assert(0); -#endif -} -#endif - diff -uNr gdc-0.11/d/root/lstring.c gdc-0.12/d/root/lstring.c --- gdc-0.11/d/root/lstring.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/lstring.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,59 +0,0 @@ -// lstring.c - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include - -#include "dchar.h" -#include "mem.h" -#include "lstring.h" - -Lstring Lstring::zero = LSTRING_EMPTY(); - -Lstring *Lstring::ctor(const dchar *p, unsigned length) -{ - Lstring *s; - - s = alloc(length); - memcpy(s->string, p, length * sizeof(dchar)); - return s; -} - -Lstring *Lstring::alloc(unsigned length) -{ - Lstring *s; - - s = (Lstring *)mem.malloc(size(length)); - s->length = length; - s->string[length] = 0; - return s; -} - -Lstring *Lstring::append(const Lstring *s) -{ - Lstring *t; - - if (!s->length) - return this; - t = alloc(length + s->length); - memcpy(t->string, string, length * sizeof(dchar)); - memcpy(t->string + length, s->string, s->length * sizeof(dchar)); - return t; -} - -Lstring *Lstring::substring(int start, int end) -{ - Lstring *t; - - if (start == end) - return &zero; - t = alloc(end - start); - memcpy(t->string, string + start, (end - start) * sizeof(dchar)); - return t; -} diff -uNr gdc-0.11/d/root/lstring.h gdc-0.12/d/root/lstring.h --- gdc-0.11/d/root/lstring.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/lstring.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,72 +0,0 @@ - -// lstring.h -// length-prefixed strings - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef LSTRING_H -#define LSTRING_H 1 - -#include "dchar.h" - -struct Lstring -{ - unsigned length; - - // Disable warning about nonstandard extension - #pragma warning (disable : 4200) - dchar string[]; - - static Lstring zero; // 0 length string - - // No constructors because we want to be able to statically - // initialize Lstring's, and Lstrings are of variable size. - - #if M_UNICODE - #define LSTRING(p,length) { length, L##p } - #else - #define LSTRING(p,length) { length, p } - #endif - -#if __GNUC__ - #define LSTRING_EMPTY() { 0 } -#else - #define LSTRING_EMPTY() LSTRING("", 0) -#endif - - static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); } - static Lstring *ctor(const dchar *p, unsigned length); - static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); } - static Lstring *alloc(unsigned length); - Lstring *clone(); - - unsigned len() { return length; } - - dchar *toDchars() { return string; } - - unsigned hash() { return Dchar::calcHash(string, length); } - unsigned ihash() { return Dchar::icalcHash(string, length); } - - static int cmp(const Lstring *s1, const Lstring *s2) - { - int c = s2->length - s1->length; - return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length); - } - - static int icmp(const Lstring *s1, const Lstring *s2) - { - int c = s2->length - s1->length; - return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length); - } - - Lstring *append(const Lstring *s); - Lstring *substring(int start, int end); -}; - -#endif diff -uNr gdc-0.11/d/root/mangle.c gdc-0.12/d/root/mangle.c --- gdc-0.11/d/root/mangle.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/mangle.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,192 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include -#include - -#include "root.h" - -#include "init.h" -#include "declaration.h" -#include "aggregate.h" -#include "mtype.h" -#include "attrib.h" -#include "template.h" -#include "id.h" - -char *Declaration::mangle() -#if __DMC__ - __out(result) - { - int len = strlen(result); - - assert(len > 0); - //printf("mangle: '%s' => '%s'\n", toChars(), result); - for (int i = 0; i < len; i++) - { - assert(result[i] == '_' || isalnum(result[i]) || result[i] & 0x80); - } - } - __body -#endif - { - OutBuffer buf; - char *id; - Dsymbol *s; - - //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage); - if (!parent || parent->isModule()) // if at global scope - { - // If it's not a D declaration, no mangling - switch (linkage) - { - case LINKd: - break; - - case LINKc: - case LINKwindows: - case LINKpascal: - case LINKcpp: - return ident->toChars(); - - case LINKdefault: - error("forward declaration"); - return ident->toChars(); - - default: - printf("'%s', linkage = %d\n", toChars(), linkage); - assert(0); - } - } - - s = this; - do - { - //printf("s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent); - if (s->ident) - { - FuncDeclaration *fd = s->isFuncDeclaration(); - if (s != this && fd) - { - id = fd->mangle(); - buf.prependstring(id); - goto L1; - } - else - { - id = s->ident->toChars(); - int len = strlen(id); - char tmp[sizeof(len) * 3 + 1]; - buf.prependstring(id); - sprintf(tmp, "%d", len); - buf.prependstring(tmp); - } - } - else - buf.prependstring("0"); - s = s->parent; - } while (s); - - buf.prependstring("_D"); - L1: - //printf("deco = '%s'\n", type->deco); - buf.writestring(type->deco); - - id = buf.toChars(); - buf.data = NULL; - return id; - } - -char *FuncDeclaration::mangle() -#if __DMC__ - __out(result) - { - assert(strlen(result) > 0); - } - __body -#endif - { - if (isMain()) - return "_Dmain"; - - return Declaration::mangle(); - } - -char *StructDeclaration::mangle() -{ - //printf("StructDeclaration::mangle() '%s'\n", toChars()); - return Dsymbol::mangle(); -} - - -char *TypedefDeclaration::mangle() -{ - //printf("TypedefDeclaration::mangle() '%s'\n", toChars()); - return Dsymbol::mangle(); -} - - -char *ClassDeclaration::mangle() -{ - Dsymbol *parentsave = parent; - - //printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars()); - - /* These are reserved to the compiler, so keep simple - * names for them. - */ - if (ident == Id::TypeInfo || - ident == Id::TypeInfo_Struct || - ident == Id::TypeInfo_Class || - ident == Id::TypeInfo_Typedef || - ident == Id::Exception || - ident == Id::Object || - ident == Id::ClassInfo || - ident == Id::ModuleInfo || - memcmp(ident->toChars(), "TypeInfo_", 9) == 0 - ) - parent = NULL; - - char *id = Dsymbol::mangle(); - parent = parentsave; - return id; -} - - -char *TemplateInstance::mangle() -{ - //printf("TemplateInstance::mangle() '%s'\n", toChars()); - return Dsymbol::mangle(); -} - - - -char *Dsymbol::mangle() -{ - OutBuffer buf; - char *id; - - //printf("Dsymbol::mangle() '%s'\n", toChars()); - id = ident ? ident->toChars() : toChars(); - if (parent) - { - //printf(" parent = '%s', kind = '%s'\n", parent->mangle(), parent->kind()); - buf.writestring(parent->mangle()); - } - buf.printf("%d%s", strlen(id), id); - //buf.writestring("_"); - //buf.writestring(id); - id = buf.toChars(); - buf.data = NULL; - return id; -} - - diff -uNr gdc-0.11/d/root/mars.c gdc-0.12/d/root/mars.c --- gdc-0.11/d/root/mars.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/mars.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,706 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include -#include -#include - -#if __DMC__ -#include -#endif - -#if linux -#include -#endif - -#include "mem.h" -#include "root.h" - -#include "mars.h" -#include "module.h" -#include "mtype.h" -#include "id.h" -#include "debcond.h" - -void getenv_setargv(const char *envvar, int *pargc, char** *pargv); - -Global global; - -Global::Global() -{ - mars_ext = "d"; - sym_ext = "d"; - -#if _WIN32 - obj_ext = "obj"; -#elif linux - obj_ext = "o"; -#else -#error "fix this" -#endif - - copyright = "Copyright (c) 1999-2005 by Digital Mars"; - written = "written by Walter Bright"; - version = "v0.121"; - global.structalign = 8; - - memset(¶ms, 0, sizeof(Param)); -} - -char *Loc::toChars() -{ - OutBuffer buf; - char *p; - - if (filename) - { - buf.printf("%s", filename); - } - - if (linnum) - buf.printf("(%d)", linnum); - buf.writeByte(0); - return (char *)buf.extractData(); -} - -Loc::Loc(Module *mod, unsigned linnum) -{ - this->linnum = linnum; - this->filename = mod ? mod->srcfile->toChars() : NULL; -} - -/************************************** - * Print error message and exit. - */ - -void error(Loc loc, const char *format, ...) -{ - char *p = loc.toChars(); - - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - printf("Error: "); - vprintf(format, ap); - va_end( ap ); - printf("\n"); - fflush(stdout); - - global.errors++; -} - -/*************************************** - * Call this after printing out fatal error messages to clean up and exit - * the compiler. - */ - -void fatal() -{ -#if 0 - *(char *)0 = 0; -#endif - exit(EXIT_FAILURE); -} - -extern void backend_init(); -extern void backend_term(); - -void usage() -{ - printf("Digital Mars D Compiler %s\n%s %s\n", - global.version, global.copyright, global.written); - printf("\ -Documentation: www.digitalmars.com/d/index.html\n\ -Usage:\n\ - dmd files.d ... { -switch }\n\ -\n\ - files.d D source files\n\ - -c do not link\n\ - -d allow deprecated features\n\ - -g add symbolic debug info\n\ - -v verbose\n\ - -O optimize\n\ - -odobjdir write object files to directory objdir\n\ - -offilename name output file to filename\n\ - -op do not strip paths from source file\n\ - -Ipath where to look for imports\n\ - -Llinkerflag pass linkerflag to link\n\ - -debug compile in debug code\n\ - -debug=level compile in debug code <= level\n\ - -debug=ident compile in debug code identified by ident\n\ - -inline do function inlining\n\ - -profile profile runtime performance of generated code\n\ - -release compile release version\n\ - -unittest compile in unit tests\n\ - -version=level compile in version code >= level\n\ - -version=ident compile in version code identified by ident\n\ - -w enable warnings\n\ -"); -} - -int main(int argc, char *argv[]) -{ - int i; - Array files; - char *p; - Module *m; - int status = EXIT_SUCCESS; - - // Initialization - Type::init(); - Id::initialize(); - Module::init(); - - backend_init(); - -#if __DMC__ // DMC unique support for response files - if (response_expand(&argc,&argv)) // expand response files - error("can't open response file"); -#endif - - files.reserve(argc - 1); - - // Set default values - global.params.argv0 = argv[0]; - global.params.link = 1; - global.params.useAssert = 1; - global.params.useInvariants = 1; - global.params.useIn = 1; - global.params.useOut = 1; - global.params.useArrayBounds = 1; - global.params.useSwitchError = 1; - global.params.useInline = 0; - - global.params.linkswitches = new Array(); - global.params.libfiles = new Array(); - global.params.objfiles = new Array(); - - // Predefine version identifiers - VersionCondition::addPredefinedGlobalIdent("DigitalMars"); -#if _WIN32 - VersionCondition::addPredefinedGlobalIdent("Windows"); - VersionCondition::addPredefinedGlobalIdent("Win32"); -#endif -#if linux - VersionCondition::addPredefinedGlobalIdent("linux"); - global.params.isLinux = 1; -#endif /* linux */ - VersionCondition::addPredefinedGlobalIdent("X86"); - VersionCondition::addPredefinedGlobalIdent("LittleEndian"); - VersionCondition::addPredefinedGlobalIdent("D_InlineAsm"); - VersionCondition::addPredefinedGlobalIdent("all"); - -#if _WIN32 - inifile(argv[0], "sc.ini"); -#endif -#if linux - inifile(argv[0], "/etc/dmd.conf"); -#endif - getenv_setargv("DFLAGS", &argc, &argv); - -#if 0 - for (i = 0; i < argc; i++) - { - printf("argv[%d] = '%s'\n", i, argv[i]); - } -#endif - - for (i = 1; i < argc; i++) - { - p = argv[i]; - if (*p == '-') - { - if (strcmp(p + 1, "d") == 0) - global.params.useDeprecated = 1; - else if (strcmp(p + 1, "c") == 0) - global.params.link = 0; - else if (strcmp(p + 1, "g") == 0) - global.params.symdebug = 1; - else if (strcmp(p + 1, "gt") == 0) - { error("use -profile instead of -gt\n"); - global.params.trace = 1; - } - else if (strcmp(p + 1, "profile") == 0) - global.params.trace = 1; - else if (strcmp(p + 1, "v") == 0) - global.params.verbose = 1; - else if (strcmp(p + 1, "w") == 0) - global.params.warnings = 1; - else if (strcmp(p + 1, "O") == 0) - global.params.optimize = 1; - else if (p[1] == 'o') - { - switch (p[2]) - { - case 'd': - if (!p[3]) - goto Lnoarg; - global.params.objdir = p + 3; - break; - case 'f': - if (!p[3]) - goto Lnoarg; - global.params.objname = p + 3; - break; - case 'p': - if (p[3]) - goto Lerror; - global.params.preservePaths = 1; - break; - - case 0: - error("-o no longer supported, use -of or -od"); - break; - - default: - goto Lerror; - } - } - else if (strcmp(p + 1, "inline") == 0) - global.params.useInline = 1; - else if (strcmp(p + 1, "release") == 0) - global.params.release = 1; - else if (strcmp(p + 1, "unittest") == 0) - global.params.useUnitTests = 1; - else if (p[1] == 'I') - { - if (!global.params.imppath) - global.params.imppath = new Array(); - global.params.imppath->push(p + 2); - } - else if (memcmp(p + 1, "debug", 5) == 0) - { - // Parse: - // -debug - // -debug=number - // -debug=identifier - if (p[6] == '=') - { - if (isdigit(p[7])) - { long level; - - errno = 0; - level = strtol(p + 7, &p, 10); - if (*p || errno || level > INT_MAX) - goto Lerror; - DebugCondition::setGlobalLevel((int)level); - } - else if (isalpha(p[7]) || p[7] == '_') - DebugCondition::addGlobalIdent(p + 7); - else - goto Lerror; - } - else if (p[6]) - goto Lerror; - else - global.params.debuglevel = 1; - } - else if (memcmp(p + 1, "version", 5) == 0) - { - // Parse: - // -version=number - // -version=identifier - if (p[8] == '=') - { - if (isdigit(p[9])) - { long level; - - errno = 0; - level = strtol(p + 9, &p, 10); - if (*p || errno || level > INT_MAX) - goto Lerror; - VersionCondition::setGlobalLevel((int)level); - } - else if (isalpha(p[9]) || p[9] == '_') - VersionCondition::addGlobalIdent(p + 9); - else - goto Lerror; - } - else - goto Lerror; - } - else if (strcmp(p + 1, "-b") == 0) - global.params.debugb = 1; - else if (strcmp(p + 1, "-c") == 0) - global.params.debugc = 1; - else if (strcmp(p + 1, "-f") == 0) - global.params.debugf = 1; - else if (strcmp(p + 1, "-r") == 0) - global.params.debugr = 1; - else if (strcmp(p + 1, "-x") == 0) - global.params.debugx = 1; - else if (strcmp(p + 1, "-y") == 0) - global.params.debugy = 1; - else if (p[1] == 'L') - { - global.params.linkswitches->push(p + 2); - } - else - { - Lerror: - error("unrecognized switch '%s'", argv[i]); - continue; - - Lnoarg: - error("argument expected for switch '%s'", argv[i]); - continue; - } - } - else - files.push(p); - } - if (global.errors) - { - fatal(); - } - if (files.dim == 0) - { usage(); - return EXIT_FAILURE; - } - - if (global.params.release) - { global.params.useInvariants = 0; - global.params.useIn = 0; - global.params.useOut = 0; - global.params.useAssert = 0; - global.params.useArrayBounds = 0; - global.params.useSwitchError = 0; - } - - if (global.params.useUnitTests) - global.params.useAssert = 1; - - if (global.params.link) - { - global.params.exefile = global.params.objname; - global.params.objname = NULL; - } - else - { - if (global.params.objname && files.dim > 1) - { - error("multiple source files, but only one .obj name"); - fatal(); - } - } - - //printf("%d source files\n",files.dim); - - // Build import search path - if (global.params.imppath) - { - for (i = 0; i < global.params.imppath->dim; i++) - { - char *path = (char *)global.params.imppath->data[i]; - Array *a = FileName::splitPath(path); - - if (a) - { - if (!global.path) - global.path = new Array(); - global.path->append(a); - } - } - } - - // Create Modules - Array modules; - modules.reserve(files.dim); - for (i = 0; i < files.dim; i++) - { Identifier *id; - char *ext; - char *name; - - p = (char *) files.data[i]; - -#if _WIN32 - // Convert / to \ so linker will work - for (int i = 0; p[i]; i++) - { - if (p[i] == '/') - p[i] = '\\'; - } -#endif - - p = FileName::name(p); // strip path - ext = FileName::ext(p); - if (ext) - { -#if TARGET_LINUX - if (strcmp(ext, "o") == 0) -#else - if (stricmp(ext, "obj") == 0) -#endif - { - global.params.objfiles->push(files.data[i]); - continue; - } - -#if TARGET_LINUX - if (strcmp(ext, "a") == 0) -#else - if (stricmp(ext, "lib") == 0) -#endif - { - global.params.libfiles->push(files.data[i]); - continue; - } - -#if !TARGET_LINUX - if (stricmp(ext, "res") == 0) - { - global.params.resfile = (char *)files.data[i]; - continue; - } - - if (stricmp(ext, "def") == 0) - { - global.params.deffile = (char *)files.data[i]; - continue; - } - - if (stricmp(ext, "exe") == 0) - { - global.params.exefile = (char *)files.data[i]; - continue; - } -#endif - - if (stricmp(ext, "d") == 0 || - stricmp(ext, "htm") == 0 || - stricmp(ext, "html") == 0) - { - ext--; // skip onto '.' - assert(*ext == '.'); - name = (char *)mem.malloc((ext - p) + 1); - memcpy(name, p, ext - p); - name[ext - p] = 0; // strip extension - - if (name[0] == 0 || - strcmp(name, "..") == 0 || - strcmp(name, ".") == 0) - { - Linvalid: - error("invalid file name '%s'", (char *)files.data[i]); - fatal(); - } - } - else - { error("unrecognized file extension %s\n", ext); - fatal(); - } - } - else - { name = p; - if (!*name) - goto Linvalid; - } - - id = new Identifier(name, 0); - m = new Module((char *) files.data[i], id); - modules.push(m); - - global.params.objfiles->push(m->objfile->name->str); - } - - // Read files, parse them - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("parse %s\n", m->toChars()); - m->deleteObjFile(); - m->read(); - m->parse(); - } - if (global.errors) - fatal(); - - // Do semantic analysis - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("semantic %s\n", m->toChars()); - m->semantic(); - } - if (global.errors) - fatal(); - - // Do pass 2 semantic analysis - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("semantic2 %s\n", m->toChars()); - m->semantic2(); - } - if (global.errors) - fatal(); - - // Do pass 3 semantic analysis - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("semantic3 %s\n", m->toChars()); - m->semantic3(); - } - if (global.errors) - fatal(); - - // Scan for functions to inline - if (global.params.useInline) - { - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("inline scan %s\n", m->toChars()); - m->inlineScan(); - } - } - if (global.errors) - fatal(); - - // Generate output files - for (i = 0; i < modules.dim; i++) - { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("code %s\n", m->toChars()); - m->genobjfile(); -// m->gensymfile(); - if (global.errors) - m->deleteObjFile(); - } - - backend_term(); - if (global.errors) - fatal(); - - if (global.params.link) - status = runLINK(); - - return status; -} - - - -/*********************************** - * Parse and append contents of environment variable envvar - * to argc and argv[]. - * The string is separated into arguments, processing \ and ". - */ - -void getenv_setargv(const char *envvar, int *pargc, char** *pargv) -{ - char *env; - char *p; - Array *argv; - int argc; - - int wildcard; // do wildcard expansion - int instring; - int slash; - char c; - - env = getenv(envvar); - if (!env) - return; - - env = mem.strdup(env); // create our own writable copy - - argc = *pargc; - argv = new Array(); - argv->setDim(argc); - - for (int i = 0; i < argc; i++) - argv->data[i] = (void *)(*pargv)[i]; - - while (1) - { - wildcard = 1; - switch (*env) - { - case ' ': - case '\t': - env++; - break; - - case 0: - goto Ldone; - - case '"': - wildcard = 0; - default: - argv->push(env); - argc++; - p = env; - slash = 0; - instring = 0; - c = 0; - - while (1) - { - c = *env++; - switch (c) - { - case '"': - p -= (slash >> 1); - if (slash & 1) - { p--; - goto Laddc; - } - instring ^= 1; - slash = 0; - continue; - - case ' ': - case '\t': - if (instring) - goto Laddc; - *p = 0; - //if (wildcard) - //wildcardexpand(); // not implemented - break; - - case '\\': - slash++; - *p++ = c; - continue; - - case 0: - *p = 0; - //if (wildcard) - //wildcardexpand(); // not implemented - goto Ldone; - - default: - Laddc: - slash = 0; - *p++ = c; - continue; - } - break; - } - } - } - -Ldone: - *pargc = argc; - *pargv = (char **)argv->data; -} - - diff -uNr gdc-0.11/d/root/mars.h gdc-0.12/d/root/mars.h --- gdc-0.11/d/root/mars.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/mars.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,217 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef DMD_MARS_H -#define DMD_MARS_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -struct Array; - -// Put command line switches in here -struct Param -{ - char link; // perform link - char trace; // insert profiling hooks - char verbose; // verbose compile - char symdebug; // insert debug symbolic information - char optimize; // run optimizer - char cpu; // target CPU - char isX86_64; // generate X86_64 bit code - char isLinux; // generate code for linux - char scheduler; // which scheduler to use - char useDeprecated; // allow use of deprecated features - char useAssert; // generate runtime code for assert()'s - char useInvariants; // generate class invariant checks - char useIn; // generate precondition checks - char useOut; // generate postcondition checks - char useArrayBounds; // generate array bounds checks - char useSwitchError; // check for switches without a default - char useUnitTests; // generate unittest code - char useInline; // inline expand functions - char release; // build release version - char preservePaths; // !=0 means don't strip path from source file - char warnings; // enable warnings - - char *argv0; // program name - Array *imppath; // array of char*'s of where to look for import modules - char *objdir; // .obj file output directory - char *objname; // .obj file output name - - unsigned debuglevel; // debug level - Array *debugids; // debug identifiers - - unsigned versionlevel; // version level - Array *versionids; // version identifiers - - bool dump_source; - - // Hidden debug switches - char debuga; - char debugb; - char debugc; - char debugf; - char debugr; - char debugw; - char debugx; - char debugy; - - // Linker stuff - Array *objfiles; - Array *linkswitches; - Array *libfiles; - char *deffile; - char *resfile; - char *exefile; -}; - -struct Global -{ - char *mars_ext; - char *sym_ext; - char *obj_ext; - char *copyright; - char *written; - Array *path; // Array of char*'s which form the import lookup path - int structalign; - char *version; - - Param params; - unsigned errors; // number of errors reported so far - - Global(); -}; - -extern Global global; - -#if __GNUC__ -//#define memicmp strncasecmp -//#define stricmp strcasecmp -#endif - -#ifdef __DMC__ -typedef _Complex long double complex_t; -#else -#ifndef IN_GCC -#include "complex_t.h" -#endif -#ifdef __APPLE__ -//#include "complex.h"//This causes problems with include the c++ and not the C "complex.h" -#define integer_t dmd_integer_t -#endif -#endif - -typedef unsigned long long integer_t; - -typedef signed char d_int8; -typedef unsigned char d_uns8; -typedef short d_int16; -typedef unsigned short d_uns16; -typedef int d_int32; -typedef unsigned d_uns32; -typedef long long d_int64; -typedef unsigned long long d_uns64; - -typedef float d_float32; -typedef double d_float64; -typedef long double d_float80; - -// Note: this will be 2 bytes on Win32 systems, and 4 bytes under linux. -typedef d_uns8 d_char; -typedef d_uns16 d_wchar; -typedef d_uns32 d_dchar; - -#ifdef IN_GCC -#include "d-gcc-real.h" -#else -typedef long double real_t; -#endif -// Modify OutBuffer::writewchar to write the correct size of wchar -#if _WIN32 -#define writewchar writeword -#endif - -// This needs a configuration test... -#ifndef _WIN32 -#define writewchar write4 -#endif - -#ifdef IN_GCC -#include "d-gcc-complex_t.h" -#endif - -struct Module; - -//typedef unsigned Loc; // file location -struct Loc -{ - char *filename; - unsigned linnum; - - Loc() - { - linnum = 0; - filename = NULL; - } - - Loc(int x) - { - linnum = x; - filename = NULL; - } - - Loc(Module *mod, unsigned linnum); - - char *toChars(); -}; - -#ifndef GCC_SAFE_DMD -#define TRUE 1 -#define FALSE 0 -#endif - -#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry - // in interface vtbl[]'s -#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears - // in the inheritance graph multiple - // times, only one is used - -enum LINK -{ - LINKdefault, - LINKd, - LINKc, - LINKcpp, - LINKwindows, - LINKpascal, -}; - -enum DYNCAST -{ - DYNCAST_OBJECT, - DYNCAST_EXPRESSION, - DYNCAST_DSYMBOL, - DYNCAST_TYPE, - DYNCAST_IDENTIFIER, -}; - -void error(Loc loc, const char *format, ...); -void fatal(); -int runLINK(); -void inifile(char *argv0, char *inifile); - -#endif /* DMD_MARS_H */ diff -uNr gdc-0.11/d/root/mem.c gdc-0.12/d/root/mem.c --- gdc-0.11/d/root/mem.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/mem.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,138 +0,0 @@ - -/* Copyright (c) 2000 Digital Mars */ -/* All Rights Reserved */ - -#include -#include -#include - -#if linux -#include "../root/mem.h" -#else -#include "mem.h" -#endif - -/* This implementation of the storage allocator uses the standard C allocation package. - */ - -Mem mem; - -void Mem::init() -{ -} - -char *Mem::strdup(const char *s) -{ - char *p; - - if (s) - { - p = ::strdup(s); - if (p) - return p; - error(); - } - return NULL; -} - -void *Mem::malloc(size_t size) -{ void *p; - - if (!size) - p = NULL; - else - { - p = ::malloc(size); - if (!p) - error(); - } - return p; -} - -void *Mem::calloc(size_t size, size_t n) -{ void *p; - - if (!size || !n) - p = NULL; - else - { - p = ::calloc(size, n); - if (!p) - error(); - } - return p; -} - -void *Mem::realloc(void *p, size_t size) -{ - if (!size) - { if (p) - { ::free(p); - p = NULL; - } - } - else if (!p) - { - p = ::malloc(size); - if (!p) - error(); - } - else - { - p = ::realloc(p, size); - if (!p) - error(); - } - return p; -} - -void Mem::free(void *p) -{ - if (p) - ::free(p); -} - -void *Mem::mallocdup(void *o, size_t size) -{ void *p; - - if (!size) - p = NULL; - else - { - p = ::malloc(size); - if (!p) - error(); - else - memcpy(p,o,size); - } - return p; -} - -void Mem::error() -{ - printf("Error: out of memory\n"); - exit(EXIT_FAILURE); -} - -void Mem::fullcollect() -{ -} - -void Mem::mark(void *pointer) -{ - (void) pointer; // necessary for VC /W4 -} - -/* =================================================== */ - -void * operator new(size_t m_size) -{ - return malloc(m_size); -} - -void operator delete(void *p) -{ - free(p); -} - - diff -uNr gdc-0.11/d/root/mem.h gdc-0.12/d/root/mem.h --- gdc-0.11/d/root/mem.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/mem.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,57 +0,0 @@ -// Copyright (C) 2000-2001 by Chromium Communications -// All Rights Reserved - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef ROOT_MEM_H -#define ROOT_MEM_H - -#include // for size_t - -typedef void (*FINALIZERPROC)(void* pObj, void* pClientData); - -struct GC; // thread specific allocator - -struct Mem -{ - GC *gc; // pointer to our thread specific allocator - Mem() { gc = NULL; } - - void init(); - - // Derive from Mem to get these storage allocators instead of global new/delete - void * operator new(size_t m_size); - void * operator new(size_t m_size, Mem *mem); - void * operator new(size_t m_size, GC *gc); - void operator delete(void *p); - - void * operator new[](size_t m_size); - void operator delete[](void *p); - - char *strdup(const char *s); - void *malloc(size_t size); - void *malloc_uncollectable(size_t size); - void *calloc(size_t size, size_t n); - void *realloc(void *p, size_t size); - void free(void *p); - void free_uncollectable(void *p); - void *mallocdup(void *o, size_t size); - void error(); - void check(void *p); // validate pointer - void fullcollect(); // do full garbage collection - void fullcollectNoStack(); // do full garbage collection, no scan stack - void mark(void *pointer); - void addroots(char* pStart, char* pEnd); - void removeroots(char* pStart); - void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData); - void setStackBottom(void *bottom); - GC *getThreadGC(); // get apartment allocator for this thread -}; - -extern Mem mem; - -#endif /* ROOT_MEM_H */ diff -uNr gdc-0.11/d/root/module.c gdc-0.12/d/root/module.c --- gdc-0.11/d/root/module.c 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/root/module.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,798 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include -#include -#ifndef alloca -#include -#endif - -#include "mars.h" -#include "module.h" -#include "parse.h" -#include "scope.h" -#include "identifier.h" -#include "id.h" -#include "import.h" -#include "dsymbol.h" - -#define MARS 1 -#include "html.h" - -#ifdef IN_GCC -#include "d-dmd-gcc.h" -#endif - -ClassDeclaration *Module::moduleinfo; - -DsymbolTable *Module::modules; - -Array Module::deferred; // deferred Dsymbol's needing semantic() run on them - -void Module::init() -{ - modules = new DsymbolTable(); -} - -Module::Module(char *filename, Identifier *ident) - : Package(ident) -{ - FileName *srcfilename; - FileName *cfilename; - FileName *hfilename; - FileName *objfilename; - FileName *symfilename; - -// printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars()); - this->arg = filename; - md = NULL; - errors = 0; - members = NULL; - isHtml = 0; - needmoduleinfo = 0; -#ifdef IN_GCC - strictlyneedmoduleinfo = 0; -#endif - insearch = 0; - searchCacheIdent = NULL; - searchCacheSymbol = NULL; - searchCacheFlags = 0; - semanticdone = 0; - decldefs = NULL; - vmoduleinfo = NULL; - massert = NULL; - marray = NULL; - sctor = NULL; - sdtor = NULL; - stest = NULL; - sfilename = NULL; - importedFrom = this; - srcfile = NULL; - - debuglevel = 0; - debugids = NULL; - versionlevel = 0; - versionids = NULL; - - srcfilename = FileName::defaultExt(filename, global.mars_ext); - if (!srcfilename->equalsExt(global.mars_ext)) - { - if (srcfilename->equalsExt("html") || srcfilename->equalsExt("htm")) - isHtml = 1; - else - { error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext); - fatal(); - } - } - - char *argobj; - if (global.params.objname) - argobj = global.params.objname; - else if (global.params.preservePaths) - argobj = filename; - else - argobj = FileName::name(filename); - if (!FileName::absolute(argobj)) - argobj = FileName::combine(global.params.objdir, argobj); - if (global.params.objname) - objfilename = new FileName(argobj, 0); - else - objfilename = FileName::forceExt(argobj, global.obj_ext); - - symfilename = FileName::forceExt(filename, global.sym_ext); - - srcfile = new File(srcfilename); - objfile = new File(objfilename); - symfile = new File(symfilename); -} - -void Module::deleteObjFile() -{ - objfile->remove(); -} - -Module::~Module() -{ -} - -char *Module::kind() -{ - return "module"; -} - -Module *Module::load(Loc loc, Array *packages, Identifier *ident) -{ Module *m; - char *filename; - - //printf("Module::load(ident = '%s')\n", ident->toChars()); - - // Build module filename by turning: - // foo.bar.baz - // into: - // foo\bar\baz - filename = ident->toChars(); - if (packages && packages->dim) - { - OutBuffer buf; - int i; - - for (i = 0; i < packages->dim; i++) - { Identifier *pid = (Identifier *)packages->data[i]; - - buf.writestring(pid->toChars()); -#if _WIN32 - buf.writeByte('\\'); -#else - buf.writeByte('/'); -#endif - } - buf.writestring(filename); - buf.writeByte(0); - filename = (char *)buf.extractData(); - } - - m = new Module(filename, ident); - m->loc = loc; - - // Find the sym file - char *s; - s = FileName::searchPath(global.path, m->symfile->toChars(), 1); - if (s) - m->symfile = new File(s); - - // BUG: the sym file is actually a source file that is - // parsed. Someday make it a real symbol table - m->srcfile = m->symfile; - m->read(); - m->parse(); - -#ifdef IN_GCC - d_gcc_magic_module(m); -#endif - - return m; -} - -void Module::read() -{ - //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars()); - srcfile->readv(); -} - -inline unsigned readwordLE(unsigned short *p) -{ -#if __I86__ - return *p; -#else - return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0]; -#endif -} - -inline unsigned readwordBE(unsigned short *p) -{ - return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1]; -} - -inline unsigned readlongLE(unsigned *p) -{ -#if __I86__ - return *p; -#else - return ((unsigned char *)p)[0] | - (((unsigned char *)p)[1] << 8) | - (((unsigned char *)p)[2] << 16) | - (((unsigned char *)p)[3] << 24); -#endif -} - -inline unsigned readlongBE(unsigned *p) -{ - return ((unsigned char *)p)[3] | - (((unsigned char *)p)[2] << 8) | - (((unsigned char *)p)[1] << 16) | - (((unsigned char *)p)[0] << 24); -} - -void Module::parse(bool dump_source) -{ char *srcname; - unsigned char *buf; - unsigned buflen; - unsigned le; - unsigned bom; - - //printf("Module::parse()\n"); - - srcname = srcfile->name->toChars(); - //printf("Module::parse(srcname = '%s')\n", srcname); - - buf = srcfile->buffer; - buflen = srcfile->len; - - if (buflen >= 2) - { - /* Convert all non-UTF-8 formats to UTF-8. - * BOM : http://www.unicode.org/faq/utf_bom.html - * 00 00 FE FF UTF-32BE, big-endian - * FF FE 00 00 UTF-32LE, little-endian - * FE FF UTF-16BE, big-endian - * FF FE UTF-16LE, little-endian - * EF BB BF UTF-8 - */ - - bom = 1; // assume there's a BOM - if (buf[0] == 0xFF && buf[1] == 0xFE) - { - if (buflen >= 4 && buf[2] == 0 && buf[3] == 0) - { // UTF-32LE - le = 1; - - Lutf32: - OutBuffer dbuf; - unsigned *pu = (unsigned *)(buf); - unsigned *pumax = &pu[buflen / 4]; - - if (buflen & 3) - { error("odd length of UTF-32 char source %u", buflen); - fatal(); - } - - dbuf.reserve(buflen / 4); - for (pu += bom; pu < pumax; pu++) - { unsigned u; - - u = le ? readlongLE(pu) : readlongBE(pu); - if (u & ~0x7F) - { - if (u > 0x10FFFF) - { error("UTF-32 value %08x greater than 0x10FFFF", u); - fatal(); - } - dbuf.writeUTF8(u); - } - else - dbuf.writeByte(u); - } - dbuf.writeByte(0); // add 0 as sentinel for scanner - buflen = dbuf.offset - 1; // don't include sentinel in count - buf = (unsigned char *) dbuf.extractData(); - } - else - { // UTF-16LE (X86) - // Convert it to UTF-8 - le = 1; - - Lutf16: - OutBuffer dbuf; - unsigned short *pu = (unsigned short *)(buf); - unsigned short *pumax = &pu[buflen / 2]; - - if (buflen & 1) - { error("odd length of UTF-16 char source %u", buflen); - fatal(); - } - - dbuf.reserve(buflen / 2); - for (pu += bom; pu < pumax; pu++) - { unsigned u; - - u = le ? readwordLE(pu) : readwordBE(pu); - if (u & ~0x7F) - { if (u >= 0xD800 && u <= 0xDBFF) - { unsigned u2; - - if (++pu > pumax) - { error("surrogate UTF-16 high value %04x at EOF", u); - fatal(); - } - u2 = le ? readwordLE(pu) : readwordBE(pu); - if (u2 < 0xDC00 || u2 > 0xDFFF) - { error("surrogate UTF-16 low value %04x out of range", u2); - fatal(); - } - u = (u - 0xD7C0) << 10; - u |= (u2 - 0xDC00); - } - else if (u >= 0xDC00 && u <= 0xDFFF) - { error("unpaired surrogate UTF-16 value %04x", u); - fatal(); - } - else if (u == 0xFFFE || u == 0xFFFF) - { error("illegal UTF-16 value %04x", u); - fatal(); - } - dbuf.writeUTF8(u); - } - else - dbuf.writeByte(u); - } - dbuf.writeByte(0); // add 0 as sentinel for scanner - buflen = dbuf.offset - 1; // don't include sentinel in count - buf = (unsigned char *) dbuf.extractData(); - } - } - else if (buf[0] == 0xFE && buf[1] == 0xFF) - { // UTF-16BE - le = 0; - goto Lutf16; - } - else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF) - { // UTF-32BE - le = 0; - goto Lutf32; - } - else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) - { // UTF-8 - - buf += 3; - buflen -= 3; - } - else - { - /* There is no BOM. Make use of Arcane Jill's insight that - * the first char of D source must be ASCII to - * figure out the encoding. - */ - - bom = 0; - if (buflen >= 4) - { if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0) - { // UTF-32LE - le = 1; - goto Lutf32; - } - else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) - { // UTF-32BE - le = 0; - goto Lutf32; - } - } - if (buflen >= 2) - { - if (buf[1] == 0) - { // UTF-16LE - le = 1; - goto Lutf16; - } - else if (buf[0] == 0) - { // UTF-16BE - le = 0; - goto Lutf16; - } - } - - // It's UTF-8 - } - } - -#ifdef IN_GCC - // dump utf-8 encoded source - if(dump_source){ - // %% srcname could contain a path ... - d_gcc_dump_source(srcname, "utf-8", buf, buflen); - } -#endif /* IN_GCC */ - if (isHtml) - { - OutBuffer *dbuf = new OutBuffer(); - Html h(srcname, buf, buflen); - h.extractCode(dbuf); - buf = dbuf->data; - buflen = dbuf->offset; -#ifdef IN_GCC - // dump extracted source - if(dump_source){ - d_gcc_dump_source(srcname, "d.utf-8", buf, buflen); - } -#endif - } - Parser p(this, buf, buflen); - members = p.parseModule(); - md = p.md; - - DsymbolTable *dst; - - if (md) - { this->ident = md->id; - dst = Package::resolve(md->packages, &this->parent, NULL); - } - else - { - dst = modules; - - for (char* p = this->ident->toChars(); *p; p++) - { - if (*p != '_' && !isalnum(*p)) - { error("has non-identifier characters in filename, use module declaration instead"); - break; - } - } - } - - // Update global list of modules - if (!dst->insert(this)) - { - if (md) - error(loc, "is in multiple packages %s", md->toChars()); - else - error(loc, "is in multiple defined"); - } -} - -void Module::semantic() -{ int i; - - if (semanticdone) - return; - - //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); - semanticdone = 1; - - // Note that modules get their own scope, from scratch. - // This is so regardless of where in the syntax a module - // gets imported, it is unaffected by context. - Scope *sc = Scope::createGlobal(this); // create root scope - - //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); - - // Add import of "object" if this module isn't "object" - if (ident != Id::object) - { - Import *im = new Import(0, NULL, Id::object); - members->shift(im); - } - - // Add all symbols into module's symbol table - symtab = new DsymbolTable(); - for (i = 0; i < members->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)members->data[i]; - s->addMember(sc->scopesym); - } - - // Pass 1 semantic routines: do public side of the definition - for (i = 0; i < members->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)members->data[i]; - //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars()); - s->semantic(sc); - - runDeferredSemantic(); - } - - sc = sc->pop(); - sc->pop(); - //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); -} - -void Module::semantic2() -{ int i; - - if (deferred.dim) - { - for (int i = 0; i < deferred.dim; i++) - { - Dsymbol *sd = (Dsymbol *)deferred.data[i]; - - sd->error("unable to resolve forward reference"); - } - return; - } - //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent); - if (semanticdone >= 2) - return; - assert(semanticdone == 1); - semanticdone = 2; - - // Note that modules get their own scope, from scratch. - // This is so regardless of where in the syntax a module - // gets imported, it is unaffected by context. - Scope *sc = Scope::createGlobal(this); // create root scope - //printf("Module = %p\n", sc.scopesym); - - // Pass 2 semantic routines: do initializers and function bodies - for (i = 0; i < members->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)members->data[i]; - s->semantic2(sc); - } - - sc = sc->pop(); - sc->pop(); - //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent); -} - -void Module::semantic3() -{ int i; - - //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent); - if (semanticdone >= 3) - return; - assert(semanticdone == 2); - semanticdone = 3; - - // Note that modules get their own scope, from scratch. - // This is so regardless of where in the syntax a module - // gets imported, it is unaffected by context. - Scope *sc = Scope::createGlobal(this); // create root scope - //printf("Module = %p\n", sc.scopesym); - - // Pass 3 semantic routines: do initializers and function bodies - for (i = 0; i < members->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)members->data[i]; - s->semantic3(sc); - } - - sc = sc->pop(); - sc->pop(); -} - -void Module::inlineScan() -{ int i; - - if (semanticdone >= 4) - return; - assert(semanticdone == 3); - semanticdone = 4; - - // Note that modules get their own scope, from scratch. - // This is so regardless of where in the syntax a module - // gets imported, it is unaffected by context. - //printf("Module = %p\n", sc.scopesym); - - for (i = 0; i < members->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)members->data[i]; - //if (global.params.verbose) - //printf("inline scan symbol %s\n", s->toChars()); - - s->inlineScan(); - } -} - -void Module::gensymfile() -{ - OutBuffer buf; - int i; - - //printf("Module::gensymfile()\n"); - - buf.printf("// Sym file generated from '%s'", srcfile->toChars()); - buf.writenl(); - - for (i = 0; i < members->dim; i++) - { - Dsymbol *s; - - s = (Dsymbol *)members->data[i]; - s->toCBuffer(&buf); - } - - // Transfer image to file - symfile->setbuffer(buf.data, buf.offset); - buf.data = NULL; - - symfile->writev(); -} - -/********************************** - * Determine if we need to generate an instance of ModuleInfo - * for this Module. - */ - -int Module::needModuleInfo() -{ - return needmoduleinfo; -} - -Dsymbol *Module::search(Identifier *ident, int flags) -{ - /* Since modules can be circularly referenced, - * need to stop infinite recursive searches. - */ - - Dsymbol *s; - if (insearch) - s = NULL; - else if (searchCacheIdent == ident && searchCacheFlags == flags) - s = searchCacheSymbol; - else - { - insearch = 1; - s = ScopeDsymbol::search(ident, flags); - insearch = 0; - - searchCacheIdent = ident; - searchCacheSymbol = s; - searchCacheFlags = flags; - } - return s; -} - -/******************************************* - * Can't run semantic on s now, try again later. - */ - -void Module::addDeferredSemantic(Dsymbol *s) -{ - // Don't add it if it is already there - for (int i = 0; i < deferred.dim; i++) - { - Dsymbol *sd = (Dsymbol *)deferred.data[i]; - - if (sd == s) - return; - } - - //printf("Module::addDeferredSemantic('%s')\n", s->toChars()); - deferred.push(s); -} - -/****************************************** - * Run semantic() on deferred symbols. - */ - -void Module::runDeferredSemantic() -{ - size_t len; - - static int nested; - if (nested) - return; - //if (deferred.dim) printf("Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); - nested++; - - do - { - len = deferred.dim; - if (!len) - break; - - Dsymbol **todo; - Dsymbol *tmp; - if (len == 1) - { - todo = &tmp; - } - else - { - todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *)); - assert(todo); - } - memcpy(todo, deferred.data, len * sizeof(Dsymbol *)); - deferred.setDim(0); - - for (int i = 0; i < len; i++) - { - Dsymbol *s = todo[i]; - - s->semantic(NULL); - } - } while (deferred.dim < len); // while making progress - nested--; -} - -/* =========================== ModuleDeclaration ===================== */ - -ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id) -{ - this->packages = packages; - this->id = id; -} - -char *ModuleDeclaration::toChars() -{ - OutBuffer buf; - int i; - - if (packages && packages->dim) - { - for (i = 0; i < packages->dim; i++) - { Identifier *pid = (Identifier *)packages->data[i]; - - buf.writestring(pid->toChars()); - buf.writeByte('.'); - } - } - buf.writestring(id->toChars()); - buf.writeByte(0); - return (char *)buf.extractData(); -} - -/* =========================== Package ===================== */ - -Package::Package(Identifier *ident) - : ScopeDsymbol(ident) -{ -} - - -char *Package::kind() -{ - return "package"; -} - - -DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg) -{ - DsymbolTable *dst = Module::modules; - Dsymbol *parent = NULL; - - //printf("Package::resolve()\n"); - if (ppkg) - *ppkg = NULL; - - if (packages) - { int i; - - for (i = 0; i < packages->dim; i++) - { Identifier *pid = (Identifier *)packages->data[i]; - Dsymbol *p; - - p = dst->lookup(pid); - if (!p) - { - p = new Package(pid); - dst->insert(p); - p->parent = parent; - ((ScopeDsymbol *)p)->symtab = new DsymbolTable(); - } - else - { - assert(p->isPackage()); - if (p->isModule()) - { p->error("module and package have the same name"); - fatal(); - break; - } - } - parent = p; - dst = ((Package *)p)->symtab; - if (ppkg && !*ppkg) - *ppkg = (Package *)p; - } - if (pparent) - { - *pparent = parent; - } - } - return dst; -} diff -uNr gdc-0.11/d/root/module.h gdc-0.12/d/root/module.h --- gdc-0.11/d/root/module.h 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/root/module.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,144 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef DMD_MODULE_H -#define DMD_MODULE_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" -#include "dsymbol.h" - -struct ModuleInfoDeclaration; -struct ClassDeclaration; -struct ModuleDeclaration; - -// Back end -union tree_node; typedef union tree_node elem; - -struct Package : ScopeDsymbol -{ - Package(Identifier *ident); - char *kind(); - - static DsymbolTable *resolve(Array *packages, Dsymbol **pparent, Package **ppkg); - - Package *isPackage() { return this; } - - virtual void semantic(Scope *sc) { } -}; - -struct Module : Package -{ - static DsymbolTable *modules; // All modules - static Array deferred; // deferred Dsymbol's needing semantic() run on them - static void init(); - - static ClassDeclaration *moduleinfo; - - - const char *arg; // original argument name - ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration - File *srcfile; // input source file - File *objfile; // output .obj file - File *symfile; // output symbol file - unsigned errors; // if any errors in file - int isHtml; // if it is an HTML file - int needmoduleinfo; -#ifdef IN_GCC - int strictlyneedmoduleinfo; -#endif - - int insearch; - Identifier *searchCacheIdent; - Dsymbol *searchCacheSymbol; // cached value of search - int searchCacheFlags; // cached flags - - int semanticdone; // has semantic() been done? - Module *importedFrom; // module from command line we're imported from, - // i.e. a module that will be taken all the - // way to an object file - - Array *decldefs; // top level declarations for this Module - - Array aimports; // all imported modules - - ModuleInfoDeclaration *vmoduleinfo; - - unsigned debuglevel; // debug level - Array *debugids; // debug identifiers - - unsigned versionlevel; // version level - Array *versionids; // version identifiers - - - Module(char *arg, Identifier *ident); - ~Module(); - - static Module *load(Loc loc, Array *packages, Identifier *ident); - - char *kind(); - void read(); // read file - void parse(bool dump_source = false); // syntactic parse - void semantic(); // semantic analysis - void semantic2(); // pass 2 semantic analysis - void semantic3(); // pass 3 semantic analysis - void inlineScan(); // scan for functions to inline - void genobjfile(); - void gensymfile(); - int needModuleInfo(); - Dsymbol *search(Identifier *ident, int flags); - void deleteObjFile(); - void addDeferredSemantic(Dsymbol *s); - void runDeferredSemantic(); - - // Back end - - Symbol *sctor; // module constructor - Symbol *sdtor; // module destructor - Symbol *stest; // module unit test - - Symbol *sfilename; // symbol for filename - - Symbol *massert; // module assert function - Symbol *toModuleAssert(); // get module assert function - - Symbol *marray; // module array bounds function - Symbol *toModuleArray(); // get module array bounds function - - - static Symbol *gencritsec(); - elem *toEfilename(); - - Symbol *toSymbol(); - void genmoduleinfo(); - - Module *isModule() { return this; } -}; - - -struct ModuleDeclaration -{ - Identifier *id; - Array *packages; // array of Identifier's representing packages - - ModuleDeclaration(Array *packages, Identifier *id); - - char *toChars(); -}; - -#endif /* DMD_MODULE_H */ diff -uNr gdc-0.11/d/root/mtype.c gdc-0.12/d/root/mtype.c --- gdc-0.11/d/root/mtype.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/mtype.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,4097 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -// Issues with using -include total.h (defines integer_t) and then complex.h fails... -#undef integer_t - -#include -#include -#ifndef alloca -#include -#endif - -#ifdef __DMC__ -#include -#endif - -#include -// TODO%% this undefines signbit and includes is the wrong complex.h anyway -// -- not sure why this is needed, anyway -// don't need to worry about all this if the 'nan negative by default' issue is resolved -#ifndef __GNUC__ -// includes the wrong complex.h in C++ -#include -#endif - -#ifdef __APPLE__ -#include -static double zero = 0; -#elif __GNUC__ -#include -// %% shouldn't be necessary -//#include -//#include -static double zero = 0; -#endif - -#ifndef NAN -#define NAN (nan("0")) -#endif -#ifndef INFINITY -#define INFINITY (infinity()) -#endif - - - -#ifdef __APPLE__ -#define integer_t dmd_integer_t -#endif - - -#include "mem.h" - -#include "mtype.h" -#include "scope.h" -#include "init.h" -#include "expression.h" -#include "attrib.h" -#include "declaration.h" -#include "template.h" -#include "id.h" -#include "enum.h" -#include "import.h" -#include "aggregate.h" - -FuncDeclaration *hasThis(Scope *sc); - - -#define LOGDOTEXP 0 // log ::dotExp() -#define LOGDEFAULTINIT 0 // log ::defaultInit() - -/* These have default values for 32 bit code, they get - * adjusted for 64 bit code. - */ - -int PTRSIZE = 4; -int REALSIZE = 10; -int Tsize_t = Tuns32; -int Tptrdiff_t = Tint32; - -/***************************** Type *****************************/ - -ClassDeclaration *Type::typeinfo; -ClassDeclaration *Type::typeinfoclass; -ClassDeclaration *Type::typeinfostruct; -ClassDeclaration *Type::typeinfotypedef; -ClassDeclaration *Type::typeinfopointer; -ClassDeclaration *Type::typeinfoarray; -ClassDeclaration *Type::typeinfostaticarray; -ClassDeclaration *Type::typeinfoassociativearray; -ClassDeclaration *Type::typeinfoenum; -ClassDeclaration *Type::typeinfofunction; -ClassDeclaration *Type::typeinfodelegate; - -Type *Type::basic[TMAX]; -unsigned char Type::mangleChar[TMAX]; -StringTable Type::stringtable; - - -Type::Type(TY ty, Type *next) -{ - this->ty = ty; - this->next = next; - this->deco = NULL; - this->pto = NULL; - this->rto = NULL; - this->arrayof = NULL; - this->vtinfo = NULL; - this->ctype = NULL; -} - -Type *Type::syntaxCopy() -{ - print(); - printf("ty = %d\n", ty); - assert(0); - return this; -} - -int Type::equals(Object *o) -{ Type *t; - - t = (Type *)o; - if (this == o || - (t && deco == t->deco) && // deco strings are unique - deco != NULL) // and semantic() has been run - { - return 1; - } - //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco); - return 0; -} - - -void Type::init() -{ int i; - int j; - - Lexer::initKeywords(); - - mangleChar[Tarray] = 'A'; - mangleChar[Tsarray] = 'G'; - mangleChar[Taarray] = 'H'; - mangleChar[Tpointer] = 'P'; - mangleChar[Treference] = 'R'; - mangleChar[Tfunction] = 'F'; - mangleChar[Tident] = 'I'; - mangleChar[Tclass] = 'C'; - mangleChar[Tstruct] = 'S'; - mangleChar[Tenum] = 'E'; - mangleChar[Ttypedef] = 'T'; - mangleChar[Tdelegate] = 'D'; - - mangleChar[Tnone] = 'n'; - mangleChar[Tvoid] = 'v'; - mangleChar[Tint8] = 'g'; - mangleChar[Tuns8] = 'h'; - mangleChar[Tint16] = 's'; - mangleChar[Tuns16] = 't'; - mangleChar[Tint32] = 'i'; - mangleChar[Tuns32] = 'k'; - mangleChar[Tint64] = 'l'; - mangleChar[Tuns64] = 'm'; - mangleChar[Tfloat32] = 'f'; - mangleChar[Tfloat64] = 'd'; - mangleChar[Tfloat80] = 'e'; - - mangleChar[Timaginary32] = 'o'; - mangleChar[Timaginary64] = 'p'; - mangleChar[Timaginary80] = 'j'; - mangleChar[Tcomplex32] = 'q'; - mangleChar[Tcomplex64] = 'r'; - mangleChar[Tcomplex80] = 'c'; - - mangleChar[Tbit] = 'b'; - mangleChar[Tascii] = 'a'; - mangleChar[Twchar] = 'u'; - mangleChar[Tdchar] = 'w'; - - mangleChar[Tinstance] = '@'; - mangleChar[Terror] = '@'; - mangleChar[Ttypeof] = '@'; - - for (i = 0; i < TMAX; i++) - { if (!mangleChar[i]) - printf("ty = %d\n", i); - assert(mangleChar[i]); - } - - // Set basic types - static TY basetab[] = - { Tvoid, Tint8, Tuns8, Tint16, Tuns16, Tint32, Tuns32, Tint64, Tuns64, - Tfloat32, Tfloat64, Tfloat80, - Timaginary32, Timaginary64, Timaginary80, - Tcomplex32, Tcomplex64, Tcomplex80, - Tbit, - Tascii, Twchar, Tdchar }; - - for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++) - basic[basetab[i]] = new TypeBasic(basetab[i]); - basic[Terror] = basic[Tint32]; - - if (global.params.isX86_64) - { - PTRSIZE = 8; - if (global.params.isLinux) - REALSIZE = 10; - else - REALSIZE = 8; - Tsize_t = Tuns64; - Tptrdiff_t = Tint64; - } - else - { - PTRSIZE = 4; - REALSIZE = 10; - Tsize_t = Tuns32; - Tptrdiff_t = Tint32; - } -} - -d_uns64 Type::size() -{ - return size(0); -} - -d_uns64 Type::size(Loc loc) -{ - error(loc, "no size for type %s", toChars()); - return 0; -} - -unsigned Type::alignsize() -{ - return size(0); -} - -Type *Type::semantic(Loc loc, Scope *sc) -{ - if (next) - next = next->semantic(loc,sc); - return merge(); -} - -Type *Type::pointerTo() -{ - if (!pto) - { Type *t; - - t = new TypePointer(this); - pto = t->merge(); - } - return pto; -} - -Type *Type::referenceTo() -{ - if (!rto) - { Type *t; - - t = new TypeReference(this); - rto = t->merge(); - } - return rto; -} - -Type *Type::arrayOf() -{ - if (!arrayof) - { Type *t; - - t = new TypeDArray(this); - arrayof = t->merge(); - } - return arrayof; -} - -Dsymbol *Type::toDsymbol(Scope *sc) -{ - return NULL; -} - -/******************************* - * If this is a shell around another type, - * get that other type. - */ - -Type *Type::toBasetype() -{ - return this; -} - -/******************************** - * Name mangling. - */ - -void Type::toDecoBuffer(OutBuffer *buf) -{ - buf->writeByte(mangleChar[ty]); - if (next) - { - assert(next != this); - //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty); - next->toDecoBuffer(buf); - } -} - -/******************************** - * Name mangling. - */ - -void Type::toTypeInfoBuffer(OutBuffer *buf) -{ - assert(0); - buf->writeByte(mangleChar[ty]); -} - -/******************************** - * For pretty-printing a type. - */ - -char *Type::toChars() -{ OutBuffer *buf; - - buf = new OutBuffer(); - toCBuffer2(buf, NULL); - return buf->toChars(); -} - -void Type::toCBuffer(OutBuffer *buf, Identifier *ident) -{ - OutBuffer tbuf; - - toCBuffer2(&tbuf, ident); - buf->write(&tbuf); -} - -void Type::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ -// buf->prependbyte(' '); - buf->prependstring(toChars()); - if (ident) - { buf->writeByte(' '); - buf->writestring(ident->toChars()); - } -} - -/************************************ - */ - -Type *Type::merge() -{ Type *t; - - //printf("merge(%s)\n", toChars()); - t = this; - assert(t); - if (!deco) - { - OutBuffer buf; - StringValue *sv; - - if (next) - next = next->merge(); - toDecoBuffer(&buf); - sv = stringtable.update((char *)buf.data, buf.offset); - if (sv->ptrvalue) - { t = (Type *) sv->ptrvalue; - assert(t->deco); - //printf("old value, deco = '%s' %p\n", t->deco, t->deco); - } - else - { - sv->ptrvalue = this; - deco = sv->lstring.string; - //printf("new value, deco = '%s' %p\n", t->deco, t->deco); - } - } - return t; -} - -int Type::isbit() -{ - return FALSE; -} - -int Type::isintegral() -{ - return FALSE; -} - -int Type::isfloating() -{ - return FALSE; -} - -int Type::isreal() -{ - return FALSE; -} - -int Type::isimaginary() -{ - return FALSE; -} - -int Type::iscomplex() -{ - return FALSE; -} - -int Type::isscalar() -{ - return FALSE; -} - -int Type::isunsigned() -{ - return FALSE; -} - -ClassDeclaration *Type::isClassHandle() -{ - return NULL; -} - -int Type::isauto() -{ - return FALSE; -} - -int Type::isString() -{ - return FALSE; -} - -int Type::checkBoolean() -{ - return isscalar(); -} - -/********************************* - * Check type to see if it is based on a deprecated symbol. - */ - -void Type::checkDeprecated(Loc loc, Scope *sc) -{ - Type *t; - Dsymbol *s; - - for (t = this; t; t = t->next) - { - s = t->toDsymbol(sc); - if (s) - s->checkDeprecated(loc, sc); - } -} - - -Expression *Type::defaultInit() -{ -#if LOGDEFAULTINIT - printf("Type::defaultInit() '%s'\n", toChars()); -#endif - return NULL; -} - -int Type::isZeroInit() -{ - return 0; // assume not -} - -int Type::isBaseOf(Type *t) -{ - return 0; // assume not -} - -/******************************** - * Determine if 'this' can be implicitly converted - * to type 'to'. - * Returns: - * 0 can't convert - * 1 can convert using implicit conversions - * 2 this and to are the same type - */ - -int Type::implicitConvTo(Type *to) -{ - //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to); - //printf("\tthis->next=%p, to->next=%p\n", this->next, to->next); - if (this == to) - return MATCHexact; -// if (to->ty == Tvoid) -// return 1; - return 0; -} - -Expression *Type::getProperty(Loc loc, Identifier *ident) -{ Expression *e; - -#if LOGDOTEXP - printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars()); -#endif - if (ident == Id::__sizeof) - { - e = new IntegerExp(loc, size(loc), Type::tsize_t); - } - else if (ident == Id::size) - { - if (!global.params.useDeprecated) - error(loc, ".size property is deprecated, use .sizeof"); - e = new IntegerExp(loc, size(loc), Type::tsize_t); - } - else if (ident == Id::alignof) - { - e = new IntegerExp(loc, alignsize(), Type::tsize_t); - } - else if (ident == Id::typeinfo) - { - if (!global.params.useDeprecated) - error(loc, ".typeinfo deprecated, use typeid(type)"); - e = getTypeInfo(NULL); - } - else if (ident == Id::init) - { - e = defaultInit(); - e->loc = loc; - } - else - { - error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars()); - e = new IntegerExp(loc, 1, Type::tint32); - } - return e; -} - -Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ VarDeclaration *v = NULL; - -#if LOGDOTEXP - printf("Type::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); -#endif - if (e->op == TOKdotvar) - { - DotVarExp *dv = (DotVarExp *)e; - v = dv->var->isVarDeclaration(); - } - else if (e->op == TOKvar) - { - VarExp *ve = (VarExp *)e; - v = ve->var->isVarDeclaration(); - } - if (v) - { - if (ident == Id::offset) - { - if (!global.params.useDeprecated) - error(e->loc, ".offset deprecated, use .offsetof"); - goto Loffset; - } - else if (ident == Id::offsetof) - { - Loffset: - if (v->storage_class & STCfield) - { - e = new IntegerExp(e->loc, v->offset, Type::tint32); - return e; - } - } - else if (ident == Id::init) - { - if (v->init) - { - e = v->init->toExpression(); - if (e->op == TOKassign) - { - e = ((AssignExp *)e)->e2; - } - return e; - } - } - } - return getProperty(e->loc, ident); -} - -unsigned Type::memalign(unsigned salign) -{ - return salign; -} - -void Type::error(Loc loc, const char *format, ...) -{ - char *p = loc.toChars(); - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); - - global.errors++; - //fatal(); -} - -Identifier *Type::getTypeInfoIdent(int internal) -{ - // _init_10TypeInfo_%s - OutBuffer buf; - Identifier *id; - char *name; - int len; - - //toTypeInfoBuffer(&buf); - if (internal) - { buf.writeByte(mangleChar[ty]); - if (ty == Tarray) - buf.writeByte(mangleChar[next->ty]); - } - else - toDecoBuffer(&buf); - name = (char *)alloca(15 + sizeof(len) * 3 + buf.offset + 1); - buf.writeByte(0); - len = strlen((char *)buf.data); - sprintf(name, "_init_%dTypeInfo_%s", 9 + len, buf.data); - id = Lexer::idPool(name); - return id; -} - -TypeBasic *Type::isTypeBasic() -{ - return NULL; -} - - -void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) -{ - Type *t; - - t = semantic(loc, sc); - *pt = t; - *pe = NULL; - *ps = NULL; -} - -/* ============================= TypeBasic =========================== */ - -TypeBasic::TypeBasic(TY ty) - : Type(ty, NULL) -{ char *c; - char *d; - unsigned flags; - -#define TFLAGSintegral 1 -#define TFLAGSfloating 2 -#define TFLAGSunsigned 4 -#define TFLAGSreal 8 -#define TFLAGSimaginary 0x10 -#define TFLAGScomplex 0x20 - - flags = 0; - switch (ty) - { - case Tvoid: d = Token::toChars(TOKvoid); - c = "void"; - break; - - case Tint8: d = Token::toChars(TOKint8); - c = "byte"; - flags |= TFLAGSintegral; - break; - - case Tuns8: d = Token::toChars(TOKuns8); - c = "ubyte"; - flags |= TFLAGSintegral | TFLAGSunsigned; - break; - - case Tint16: d = Token::toChars(TOKint16); - c = "short"; - flags |= TFLAGSintegral; - break; - - case Tuns16: d = Token::toChars(TOKuns16); - c = "ushort"; - flags |= TFLAGSintegral | TFLAGSunsigned; - break; - - case Tint32: d = Token::toChars(TOKint32); - c = "int"; - flags |= TFLAGSintegral; - break; - - case Tuns32: d = Token::toChars(TOKuns32); - c = "uint"; - flags |= TFLAGSintegral | TFLAGSunsigned; - break; - - case Tfloat32: d = Token::toChars(TOKfloat32); - c = "float"; - flags |= TFLAGSfloating | TFLAGSreal; - break; - - case Tint64: d = Token::toChars(TOKint64); - c = "long"; - flags |= TFLAGSintegral; - break; - - case Tuns64: d = Token::toChars(TOKuns64); - c = "ulong"; - flags |= TFLAGSintegral | TFLAGSunsigned; - break; - - case Tfloat64: d = Token::toChars(TOKfloat64); - c = "double"; - flags |= TFLAGSfloating | TFLAGSreal; - break; - - case Tfloat80: d = Token::toChars(TOKfloat80); - c = "real"; - flags |= TFLAGSfloating | TFLAGSreal; - break; - - case Timaginary32: d = Token::toChars(TOKimaginary32); - c = "ifloat"; - flags |= TFLAGSfloating | TFLAGSimaginary; - break; - - case Timaginary64: d = Token::toChars(TOKimaginary64); - c = "idouble"; - flags |= TFLAGSfloating | TFLAGSimaginary; - break; - - case Timaginary80: d = Token::toChars(TOKimaginary80); - c = "ireal"; - flags |= TFLAGSfloating | TFLAGSimaginary; - break; - - case Tcomplex32: d = Token::toChars(TOKcomplex32); - c = "cfloat"; - flags |= TFLAGSfloating | TFLAGScomplex; - break; - - case Tcomplex64: d = Token::toChars(TOKcomplex64); - c = "cdouble"; - flags |= TFLAGSfloating | TFLAGScomplex; - break; - - case Tcomplex80: d = Token::toChars(TOKcomplex80); - c = "creal"; - flags |= TFLAGSfloating | TFLAGScomplex; - break; - - - case Tbit: d = Token::toChars(TOKbit); - c = "bit"; - flags |= TFLAGSintegral | TFLAGSunsigned; - break; - - case Tascii: d = Token::toChars(TOKchar); - c = "char"; - flags |= TFLAGSintegral | TFLAGSunsigned; - break; - - case Twchar: d = Token::toChars(TOKwchar); - c = "wchar"; - flags |= TFLAGSintegral | TFLAGSunsigned; - break; - - case Tdchar: d = Token::toChars(TOKdchar); - c = "dchar"; - flags |= TFLAGSintegral | TFLAGSunsigned; - break; - - default: assert(0); - } - this->dstring = d; - this->cstring = c; - this->flags = flags; - merge(); -} - -Type *TypeBasic::syntaxCopy() -{ - // No semantic analysis done on basic types, no need to copy - return this; -} - - -char *TypeBasic::toChars() -{ - return dstring; -} - -void TypeBasic::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - buf->prependstring(cstring); - if (ident) - { buf->writeByte(' '); - buf->writestring(ident->toChars()); - } -} - -d_uns64 TypeBasic::size(Loc loc) -{ unsigned size; - - //printf("TypeBasic::size()\n"); - switch (ty) - { - case Tint8: - case Tuns8: size = 1; break; - case Tint16: - case Tuns16: size = 2; break; - case Tint32: - case Tuns32: - case Tfloat32: - case Timaginary32: - size = 4; break; - case Tint64: - case Tuns64: - case Tfloat64: - case Timaginary64: - size = 8; break; - case Tfloat80: - case Timaginary80: - size = REALSIZE; break; - case Tcomplex32: - size = 8; break; - case Tcomplex64: - size = 16; break; - case Tcomplex80: - size = REALSIZE * 2; break; - - case Tvoid: - //size = Type::size(); // error message - size = 1; - break; - - case Tbit: size = 1; break; - case Tascii: size = 1; break; - case Twchar: size = 2; break; - case Tdchar: size = 4; break; - - default: - assert(0); - break; - } - //printf("TypeBasic::size() = %d\n", size); - return size; -} - -unsigned TypeBasic::alignsize() -{ unsigned sz; - - switch (ty) - { - case Tfloat80: - case Timaginary80: - case Tcomplex80: - sz = 2; - break; - - default: - sz = size(0); - break; - } - return sz; -} - - -Expression *TypeBasic::getProperty(Loc loc, Identifier *ident) -{ - Expression *e; - d_int64 ivalue; -#ifdef IN_GCC - real_t fvalue; -#else - d_float80 fvalue; -#endif - - //printf("TypeBasic::getProperty('%s')\n", ident->toChars()); - if (ident == Id::max) - { - switch (ty) - { - case Tint8: ivalue = 0x7F; goto Livalue; - case Tuns8: ivalue = 0xFF; goto Livalue; - case Tint16: ivalue = 0x7FFFUL; goto Livalue; - case Tuns16: ivalue = 0xFFFFUL; goto Livalue; - case Tint32: ivalue = 0x7FFFFFFFUL; goto Livalue; - case Tuns32: ivalue = 0xFFFFFFFFUL; goto Livalue; - case Tint64: ivalue = 0x7FFFFFFFFFFFFFFFLL; goto Livalue; - case Tuns64: ivalue = 0xFFFFFFFFFFFFFFFFULL; goto Livalue; - case Tbit: ivalue = 1; goto Livalue; - case Tascii: ivalue = 0xFF; goto Livalue; - case Twchar: ivalue = 0xFFFFUL; goto Livalue; - case Tdchar: ivalue = 0x10FFFFUL; goto Livalue; - - case Tcomplex32: - case Timaginary32: -#ifdef IN_GCC - // %% lazy, fix -#define FLT_MAX real_t_properties[real_t::Float].maxval; -#define DBL_MAX real_t_properties[real_t::Double].maxval; -#define LDBL_MAX real_t_properties[real_t::LongDouble].maxval; -#define FLT_MIN real_t_properties[real_t::Float].minval; -#define DBL_MIN real_t_properties[real_t::Double].minval; -#define LDBL_MIN real_t_properties[real_t::LongDouble].minval; -#define FLT_DIG real_t_properties[real_t::Float].dig; -#define DBL_DIG real_t_properties[real_t::Double].dig; -#define LDBL_DIG real_t_properties[real_t::LongDouble].dig; -#define FLT_MANT_DIG real_t_properties[real_t::Float].mant_dig; -#define DBL_MANT_DIG real_t_properties[real_t::Double].mant_dig; -#define LDBL_MANT_DIG real_t_properties[real_t::LongDouble].mant_dig; -#define FLT_MAX_10_EXP real_t_properties[real_t::Float].max_10_exp; -#define DBL_MAX_10_EXP real_t_properties[real_t::Double].max_10_exp; -#define LDBL_MAX_10_EXP real_t_properties[real_t::LongDouble].max_10_exp; -#define FLT_MIN_10_EXP real_t_properties[real_t::Float].min_10_exp; -#define DBL_MIN_10_EXP real_t_properties[real_t::Double].min_10_exp; -#define LDBL_MIN_10_EXP real_t_properties[real_t::LongDouble].min_10_exp; -#define FLT_MAX_EXP real_t_properties[real_t::Float].max_exp; -#define DBL_MAX_EXP real_t_properties[real_t::Double].max_exp; -#define LDBL_MAX_EXP real_t_properties[real_t::LongDouble].max_exp; -#define FLT_MIN_EXP real_t_properties[real_t::Float].min_exp; -#define DBL_MIN_EXP real_t_properties[real_t::Double].min_exp; -#define LDBL_MIN_EXP real_t_properties[real_t::LongDouble].min_exp; -#define FLT_EPSILON real_t_properties[real_t::Float].epsilonval; -#define DBL_EPSILON real_t_properties[real_t::Double].epsilonval; -#define LDBL_EPSILON real_t_properties[real_t::LongDouble].epsilonval; - - -#endif - case Tfloat32: fvalue = FLT_MAX; goto Lfvalue; - case Tcomplex64: - case Timaginary64: - case Tfloat64: fvalue = DBL_MAX; goto Lfvalue; - case Tcomplex80: - case Timaginary80: - case Tfloat80: fvalue = LDBL_MAX; goto Lfvalue; - } - } - else if (ident == Id::min) - { - switch (ty) - { - case Tint8: ivalue = -128; goto Livalue; - case Tuns8: ivalue = 0; goto Livalue; - case Tint16: ivalue = -32768; goto Livalue; - case Tuns16: ivalue = 0; goto Livalue; - case Tint32: ivalue = -2147483647L - 1; goto Livalue; - case Tuns32: ivalue = 0; goto Livalue; - case Tint64: ivalue = (-9223372036854775807LL-1LL); goto Livalue; - case Tuns64: ivalue = 0; goto Livalue; - case Tbit: ivalue = 0; goto Livalue; - case Tascii: ivalue = 0; goto Livalue; - case Twchar: ivalue = 0; goto Livalue; - case Tdchar: ivalue = 0; goto Livalue; - - case Tcomplex32: - case Timaginary32: - case Tfloat32: fvalue = FLT_MIN; goto Lfvalue; - case Tcomplex64: - case Timaginary64: - case Tfloat64: fvalue = DBL_MIN; goto Lfvalue; - case Tcomplex80: - case Timaginary80: - case Tfloat80: fvalue = LDBL_MIN; goto Lfvalue; - } - } - else if (ident == Id::nan) - { - switch (ty) - { - case Tcomplex32: - case Tcomplex64: - case Tcomplex80: - case Timaginary32: - case Timaginary64: - case Timaginary80: - case Tfloat32: - case Tfloat64: - case Tfloat80: -#ifdef IN_GCC - // mode doesn't matter, will be converted in RealExp anyway - fvalue = real_t::getnan(real_t::LongDouble); -#elif __GNUC__ - { // gcc nan's have the sign bit set by default, so turn it off - // Need the volatile to prevent gcc from doing incorrect - // constant folding. - volatile d_float80 foo; - foo = NAN; - // This doesn't seem to be the case on the systems I'm using %% - if ( signbit(foo) ) - foo = -foo; - fvalue = foo; - } -#else - fvalue = NAN; -#endif - goto Lfvalue; - } - } - else if (ident == Id::infinity) - { - switch (ty) - { - case Tcomplex32: - case Tcomplex64: - case Tcomplex80: - case Timaginary32: - case Timaginary64: - case Timaginary80: - case Tfloat32: - case Tfloat64: - case Tfloat80: -#ifdef IN_GCC - fvalue = real_t::getinfinity(); -#elif __GNUC__ - fvalue = 1 / zero; -#else - fvalue = INFINITY; -#endif - goto Lfvalue; - } - } - else if (ident == Id::dig) - { - switch (ty) - { - case Tcomplex32: - case Timaginary32: - case Tfloat32: ivalue = FLT_DIG; goto Lint; - case Tcomplex64: - case Timaginary64: - case Tfloat64: ivalue = DBL_DIG; goto Lint; - case Tcomplex80: - case Timaginary80: - case Tfloat80: ivalue = LDBL_DIG; goto Lint; - } - } - else if (ident == Id::epsilon) - { - switch (ty) - { - case Tcomplex32: - case Timaginary32: - case Tfloat32: fvalue = FLT_EPSILON; goto Lfvalue; - case Tcomplex64: - case Timaginary64: - case Tfloat64: fvalue = DBL_EPSILON; goto Lfvalue; - case Tcomplex80: - case Timaginary80: - case Tfloat80: fvalue = LDBL_EPSILON; goto Lfvalue; - } - } - else if (ident == Id::mant_dig) - { - switch (ty) - { - case Tcomplex32: - case Timaginary32: - case Tfloat32: ivalue = FLT_MANT_DIG; goto Lint; - case Tcomplex64: - case Timaginary64: - case Tfloat64: ivalue = DBL_MANT_DIG; goto Lint; - case Tcomplex80: - case Timaginary80: - case Tfloat80: ivalue = LDBL_MANT_DIG; goto Lint; - } - } - else if (ident == Id::max_10_exp) - { - switch (ty) - { - case Tcomplex32: - case Timaginary32: - case Tfloat32: ivalue = FLT_MAX_10_EXP; goto Lint; - case Tcomplex64: - case Timaginary64: - case Tfloat64: ivalue = DBL_MAX_10_EXP; goto Lint; - case Tcomplex80: - case Timaginary80: - case Tfloat80: ivalue = LDBL_MAX_10_EXP; goto Lint; - } - } - else if (ident == Id::max_exp) - { - switch (ty) - { - case Tcomplex32: - case Timaginary32: - case Tfloat32: ivalue = FLT_MAX_EXP; goto Lint; - case Tcomplex64: - case Timaginary64: - case Tfloat64: ivalue = DBL_MAX_EXP; goto Lint; - case Tcomplex80: - case Timaginary80: - case Tfloat80: ivalue = LDBL_MAX_EXP; goto Lint; - } - } - else if (ident == Id::min_10_exp) - { - switch (ty) - { - case Tcomplex32: - case Timaginary32: - case Tfloat32: ivalue = FLT_MIN_10_EXP; goto Lint; - case Tcomplex64: - case Timaginary64: - case Tfloat64: ivalue = DBL_MIN_10_EXP; goto Lint; - case Tcomplex80: - case Timaginary80: - case Tfloat80: ivalue = LDBL_MIN_10_EXP; goto Lint; - } - } - else if (ident == Id::min_exp) - { - switch (ty) - { - case Tcomplex32: - case Timaginary32: - case Tfloat32: ivalue = FLT_MIN_EXP; goto Lint; - case Tcomplex64: - case Timaginary64: - case Tfloat64: ivalue = DBL_MIN_EXP; goto Lint; - case Tcomplex80: - case Timaginary80: - case Tfloat80: ivalue = LDBL_MIN_EXP; goto Lint; - } - } - -Ldefault: - return Type::getProperty(loc, ident); - -Livalue: - e = new IntegerExp(0, ivalue, this); - return e; - -Lfvalue: - if (isreal()) - e = new RealExp(0, fvalue, this); - else if (isimaginary()) - e = new ImaginaryExp(0, fvalue, this); - else - { - complex_t cvalue; - -#if __DMC__ - cvalue = fvalue + fvalue * I; -#else - cvalue.re = fvalue; - cvalue.im = fvalue; -#endif - e = new ComplexExp(0, cvalue, this); - } - return e; - -Lint: - e = new IntegerExp(0, ivalue, Type::tint32); - return e; -} - -Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ -#if LOGDOTEXP - printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); -#endif - Type *t; - - if (ident == Id::re) - { - switch (ty) - { - case Tcomplex32: t = tfloat32; goto L1; - case Tcomplex64: t = tfloat64; goto L1; - case Tcomplex80: t = tfloat80; goto L1; - L1: - e = e->castTo(t); - break; - - case Tfloat32: - case Tfloat64: - case Tfloat80: - break; - - case Timaginary32: t = tfloat32; goto L2; - case Timaginary64: t = tfloat64; goto L2; - case Timaginary80: t = tfloat80; goto L2; - L2: - e = new RealExp(0, 0, t); - break; - - default: - return Type::getProperty(e->loc, ident); - } - } - else if (ident == Id::im) - { Type *t2; - - switch (ty) - { - case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3; - case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3; - case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3; - L3: - e = e->castTo(t); - e->type = t2; - break; - - case Timaginary32: t = tfloat32; goto L4; - case Timaginary64: t = tfloat64; goto L4; - case Timaginary80: t = tfloat80; goto L4; - L4: - e->type = t; - break; - - case Tfloat32: - case Tfloat64: - case Tfloat80: - e = new RealExp(0, 0, this); - break; - - default: - return Type::getProperty(e->loc, ident); - } - } - else - { - return Type::dotExp(sc, e, ident); - } - return e; -} - -Expression *TypeBasic::defaultInit() -{ integer_t value = 0; - -#if LOGDEFAULTINIT - printf("TypeBasic::defaultInit() '%s'\n", toChars()); -#endif - switch (ty) - { - case Tchar: - value = 0xFF; - break; - - case Twchar: - case Tdchar: - value = 0xFFFF; - break; - - case Timaginary32: - case Timaginary64: - case Timaginary80: - case Tfloat32: - case Tfloat64: - case Tfloat80: - case Tcomplex32: - case Tcomplex64: - case Tcomplex80: - return getProperty(0, Id::nan); - } - return new IntegerExp(0, value, this); -} - -int TypeBasic::isZeroInit() -{ - switch (ty) - { - case Tchar: - case Twchar: - case Tdchar: - case Timaginary32: - case Timaginary64: - case Timaginary80: - case Tfloat32: - case Tfloat64: - case Tfloat80: - case Tcomplex32: - case Tcomplex64: - case Tcomplex80: - return 0; // no - } - return 1; // yes -} - -int TypeBasic::isbit() -{ - return (ty == Tbit); -} - -int TypeBasic::isintegral() -{ - //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags); - return flags & TFLAGSintegral; -} - -int TypeBasic::isfloating() -{ - return flags & TFLAGSfloating; -} - -int TypeBasic::isreal() -{ - return flags & TFLAGSreal; -} - -int TypeBasic::isimaginary() -{ - return flags & TFLAGSimaginary; -} - -int TypeBasic::iscomplex() -{ - return flags & TFLAGScomplex; -} - -int TypeBasic::isunsigned() -{ - return flags & TFLAGSunsigned; -} - -int TypeBasic::isscalar() -{ - return flags & (TFLAGSintegral | TFLAGSfloating); -} - -int TypeBasic::implicitConvTo(Type *to) -{ - //printf("TypeBasic::implicitConvTo(%s)\n", to->toChars()); - if (this == to) - return MATCHexact; - if (to->ty == Tvoid) - return MATCHnomatch; - if (!to->isTypeBasic()) - return MATCHnomatch; - if (ty == Tvoid /*|| to->ty == Tvoid*/) - return MATCHnomatch; - if (to->ty == Tbit) - return MATCHnomatch; - TypeBasic *tob = (TypeBasic *)to; - if (flags & TFLAGSfloating) - { - // Disallow implicit conversion of floating point to integer - if (tob->flags & TFLAGSintegral) - return MATCHnomatch; - - assert(tob->flags & TFLAGSfloating); - - // Disallow implicit conversion from complex to non-complex - if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex)) - return MATCHnomatch; - - // Allow implicit conversion of real or imaginary to complex - if (flags & (TFLAGSreal | TFLAGSimaginary) && - tob->flags & TFLAGScomplex) - return MATCHconvert; - - // Disallow implicit conversion to-from real and imaginary - if ((flags & (TFLAGSreal | TFLAGSimaginary)) != - (tob->flags & (TFLAGSreal | TFLAGSimaginary))) - return MATCHnomatch; - } - return MATCHconvert; -} - -TypeBasic *TypeBasic::isTypeBasic() -{ - return (TypeBasic *)this; -} - -/***************************** TypeArray *****************************/ - -TypeArray::TypeArray(TY ty, Type *next) - : Type(ty, next) -{ -} - -Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ - Type *n = this->next->toBasetype(); // uncover any typedef's - -#if LOGDOTEXP - printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); -#endif - if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar)) - { - Expression *ec; - FuncDeclaration *fd; - Array *arguments; - char *nm; - static char *name[2] = { "_adReverseChar", "_adReverseWchar" }; - - nm = name[n->ty == Twchar]; - fd = FuncDeclaration::genCfunc(Type::tindex, nm); - ec = new VarExp(0, fd); - e = e->castTo(n->arrayOf()); // convert to dynamic array - arguments = new Array(); - arguments->push(e); - e = new CallExp(e->loc, ec, arguments); - e->type = next->arrayOf(); - } - else if (ident == Id::reverse || ident == Id::dup) - { - Expression *ec; - FuncDeclaration *fd; - Array *arguments; - int size = next->size(e->loc); - char *nm; - static char *name[2][2] = { { "_adReverse", "_adDup" }, - { "_adReverseBit", "_adDupBit" } }; - - assert(size); - nm = name[n->ty == Tbit][ident == Id::dup]; - fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), nm); - ec = new VarExp(0, fd); - e = e->castTo(n->arrayOf()); // convert to dynamic array - arguments = new Array(); - arguments->push(e); - if (next->ty != Tbit) - arguments->push(new IntegerExp(0, size, Type::tint32)); - e = new CallExp(e->loc, ec, arguments); - e->type = next->arrayOf(); - } - else if (ident == Id::sort) - { - Expression *ec; - FuncDeclaration *fd; - Array *arguments; - - fd = FuncDeclaration::genCfunc(tint32->arrayOf(), - (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort")); - ec = new VarExp(0, fd); - e = e->castTo(n->arrayOf()); // convert to dynamic array - arguments = new Array(); - arguments->push(e); - if (next->ty != Tbit) - arguments->push(n->ty == Tsarray - ? n->getTypeInfo(sc) // don't convert to dynamic array - : n->getInternalTypeInfo(sc)); - e = new CallExp(e->loc, ec, arguments); - e->type = next->arrayOf(); - } - else - { - e = Type::dotExp(sc, e, ident); - } - return e; -} - -void TypeArray::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ -#if 1 - OutBuffer buf2; - toPrettyBracket(&buf2); - buf->prependstring(buf2.toChars()); - if (ident) - { - buf->writestring(ident->toChars()); - } - next->toCBuffer2(buf, NULL); -#elif 1 - // The D way - Type *t; - OutBuffer buf2; - for (t = this; 1; t = t->next) - { TypeArray *ta; - - ta = dynamic_cast(t); - if (!ta) - break; - ta->toPrettyBracket(&buf2); - } - buf->prependstring(buf2.toChars()); - if (ident) - { - buf2.writestring(ident->toChars()); - } - t->toCBuffer2(buf, NULL); -#else - // The C way - if (buf->offset) - { buf->bracket('(', ')'); - assert(!ident); - } - else if (ident) - buf->writestring(ident->toChars()); - Type *t = this; - do - { Expression *dim; - buf->writeByte('['); - dim = ((TypeSArray *)t)->dim; - if (dim) - buf->printf("%lld", dim->toInteger()); - buf->writeByte(']'); - t = t->next; - } while (t->ty == Tsarray); - t->toCBuffer2(buf, NULL); -#endif -} - -/***************************** TypeSArray *****************************/ - -TypeSArray::TypeSArray(Type *t, Expression *dim) - : TypeArray(Tsarray, t) -{ - //printf("TypeSArray(%s)\n", dim->toChars()); - this->dim = dim; -} - -Type *TypeSArray::syntaxCopy() -{ - Type *t = next->syntaxCopy(); - Expression *e = dim->syntaxCopy(); - t = new TypeSArray(t, e); - return t; -} - -d_uns64 TypeSArray::size(Loc loc) -{ integer_t sz; - - if (!dim) - return Type::size(loc); - sz = dim->toInteger(); - if (next->toBasetype()->ty == Tbit) // if array of bits - { - if (sz + 31 < sz) - goto Loverflow; - sz = ((sz + 31) & ~31) / 8; // size in bytes, rounded up to 32 bit dwords - } - else - { integer_t n, n2; - - n = next->size(); - n2 = n * sz; - if (n && (n2 / n) != sz) - goto Loverflow; - sz = n2; - } - return sz; - -Loverflow: - error(loc, "index %lld overflow for static array", sz); - return 1; -} - -unsigned TypeSArray::alignsize() -{ - return next->alignsize(); -} - -Type *TypeSArray::semantic(Loc loc, Scope *sc) -{ - //printf("TypeSArray::semantic() %s\n", toChars()); - next = next->semantic(loc,sc); - if (dim) - { integer_t n, n2; - - dim = dim->semantic(sc); - dim = dim->constFold(); - integer_t d1 = dim->toInteger(); - dim = dim->castTo(tsize_t); - dim = dim->constFold(); - integer_t d2 = dim->toInteger(); - - if (d1 != d2) - goto Loverflow; - if (next->ty == Tbit && (d2 + 31) < d2) - goto Loverflow; - else if (next->isintegral() || - next->isfloating() || - next->ty == Tpointer || - next->ty == Tarray || - next->ty == Tsarray || - next->ty == Taarray || - next->ty == Tclass) - { - /* Only do this for types that don't need to have semantic() - * run on them for the size, since they may be forward referenced. - */ - n = next->size(loc); - n2 = n * d2; - if ((int)n2 < 0) - goto Loverflow; - if (n && n2 / n != d2) - { - Loverflow: - error(loc, "index %lld overflow for static array", d1); - dim = new IntegerExp(0, 1, tsize_t); - } - } - } - switch (next->ty) - { - case Tfunction: - case Tnone: - error(loc, "can't have array of %s", next->toChars()); - break; - } - if (next->isauto()) - error(loc, "cannot have array of auto %s", next->toChars()); - return merge(); -} - -void TypeSArray::toDecoBuffer(OutBuffer *buf) -{ - buf->writeByte(mangleChar[ty]); - if (dim) - buf->printf("%llu", dim->toInteger()); - if (next) - next->toDecoBuffer(buf); -} - -void TypeSArray::toTypeInfoBuffer(OutBuffer *buf) -{ - buf->writeByte(mangleChar[Tarray]); - if (next) - next->toTypeInfoBuffer(buf); -} - -void TypeSArray::toPrettyBracket(OutBuffer *buf) -{ - buf->printf("[%s]", dim->toChars()); -} - -Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ -#if LOGDOTEXP - printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); -#endif - if (ident == Id::length) - { - e = dim; - } - else if (ident == Id::ptr) - { - e = e->castTo(next->pointerTo()); - } - else - { - e = TypeArray::dotExp(sc, e, ident); - } - return e; -} - -int TypeSArray::isString() -{ - return next->ty == Tascii || next->ty == Twchar || next->ty == Tdchar; -} - -unsigned TypeSArray::memalign(unsigned salign) -{ - return next->memalign(salign); -} - -int TypeSArray::implicitConvTo(Type *to) -{ - //printf("TypeSArray::implicitConvTo()\n"); - - // Allow implicit conversion of static array to pointer or dynamic array - if ((to->ty == Tpointer || to->ty == Tarray) && - (to->next->ty == Tvoid || next->equals(to->next) - /*|| to->next->isBaseOf(next)*/)) - { - return 1; - } -#if 0 - if (to->ty == Tsarray) - { - TypeSArray *tsa = (TypeSArray *)to; - - if (next->equals(tsa->next) && dim->equals(tsa->dim)) - { - return 1; - } - } -#endif - return Type::implicitConvTo(to); -} - -Expression *TypeSArray::defaultInit() -{ -#if LOGDEFAULTINIT - printf("TypeSArray::defaultInit() '%s'\n", toChars()); -#endif - return next->defaultInit(); -} - -/***************************** TypeDArray *****************************/ - -TypeDArray::TypeDArray(Type *t) - : TypeArray(Tarray, t) -{ - //printf("TypeDArray(t = %p)\n", t); -} - -Type *TypeDArray::syntaxCopy() -{ - Type *t = next->syntaxCopy(); - if (t == next) - t = this; - else - t = new TypeDArray(t); - return t; -} - -d_uns64 TypeDArray::size(Loc loc) -{ - //printf("TypeDArray::size()\n"); - return PTRSIZE * 2; -} - -unsigned TypeDArray::alignsize() -{ - // A DArray consists of two ptr-sized values, so align it on pointer size - // boundary - return PTRSIZE; -} - -Type *TypeDArray::semantic(Loc loc, Scope *sc) -{ Type *tn = next; - - tn = next->semantic(loc,sc); - switch (tn->ty) - { - case Tfunction: - case Tnone: - error(loc, "can't have array of %s", tn->toChars()); - break; - } - if (tn->isauto()) - error(loc, "cannot have array of auto %s", tn->toChars()); - if (next != tn) - //deco = NULL; // redo - return tn->arrayOf(); - return merge(); -} - -void TypeDArray::toDecoBuffer(OutBuffer *buf) -{ - buf->writeByte(mangleChar[ty]); - if (next) - next->toDecoBuffer(buf); -} - -void TypeDArray::toTypeInfoBuffer(OutBuffer *buf) -{ - buf->writeByte(mangleChar[ty]); - if (next) - next->toTypeInfoBuffer(buf); -} - -void TypeDArray::toPrettyBracket(OutBuffer *buf) -{ - buf->writestring("[]"); -} - -Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ -#if LOGDOTEXP - printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); -#endif - if (ident == Id::length) - { - if (e->op == TOKstring) - { StringExp *se = (StringExp *)e; - - return new IntegerExp(se->loc, se->len, Type::tindex); - } - e = new ArrayLengthExp(e->loc, e); - e->type = Type::tsize_t; - return e; - } - else if (ident == Id::ptr) - { - e = e->castTo(next->pointerTo()); - return e; - } - else - { - e = TypeArray::dotExp(sc, e, ident); - } - return e; -} - -int TypeDArray::isString() -{ - return next->ty == Tascii || next->ty == Twchar || next->ty == Tdchar; -} - -int TypeDArray::implicitConvTo(Type *to) -{ - //printf("TypeDArray::implicitConvTo()\n"); - - // Allow implicit conversion of array to pointer - if (to->ty == Tpointer && (to->next->ty == Tvoid || next->equals(to->next) /*|| to->next->isBaseOf(next)*/)) - { - return MATCHconvert; - } - if (to->ty == Tarray) - { - if (to->next->isBaseOf(next) || to->next->ty == Tvoid) - return MATCHconvert; - } - return Type::implicitConvTo(to); -} - -Expression *TypeDArray::defaultInit() -{ -#if LOGDEFAULTINIT - printf("TypeDArray::defaultInit() '%s'\n", toChars()); -#endif - Expression *e; - e = new NullExp(0); - e->type = this; - return e; -} - -int TypeDArray::checkBoolean() -{ - return TRUE; -} - -/***************************** TypeAArray *****************************/ - -TypeAArray::TypeAArray(Type *t, Type *index) - : TypeArray(Taarray, t) -{ - this->index = index; - this->key = NULL; -} - -Type *TypeAArray::syntaxCopy() -{ - Type *t = next->syntaxCopy(); - Type *ti = index->syntaxCopy(); - if (t == next && ti == index) - t = this; - else - t = new TypeAArray(t, ti); - return t; -} - -d_uns64 TypeAArray::size(Loc loc) -{ - return PTRSIZE * 2; -} - - -Type *TypeAArray::semantic(Loc loc, Scope *sc) -{ - //printf("TypeAArray::semantic()\n"); - - // Deal with the case where we thought the index was a type, but - // in reality it was an expression. - if (index->ty == Tident) - { - Expression *e; - Type *t; - Dsymbol *s; - - index->resolve(loc, sc, &e, &t, &s); - if (e) - { // It was an expression - - // Rewrite as a static array - TypeSArray *tsa; - - tsa = new TypeSArray(next, e); - return tsa->semantic(loc,sc); - } - else if (t) - index = t; - else - index->error(loc, "index is not a type or an expression"); - } - else - index = index->semantic(loc,sc); - - // Compute key type; the purpose of the key type is to - // minimize the permutations of runtime library - // routines as much as possible. - key = index->toBasetype(); - switch (key->ty) - { -#if 0 - case Tint8: - case Tuns8: - case Tint16: - case Tuns16: - key = tint32; - break; -#endif - - case Tsarray: -#if 0 - // Convert to Tarray - key = key->next->arrayOf(); - break; -#endif - case Tbit: - case Tfunction: - case Tvoid: - case Tnone: - error(loc, "can't have associative array key of %s", key->toChars()); - break; - } - next = next->semantic(loc,sc); - switch (next->toBasetype()->ty) - { - case Tfunction: - case Tnone: - error(loc, "can't have associative array of %s", next->toChars()); - break; - } - if (next->isauto()) - error(loc, "cannot have array of auto %s", next->toChars()); - - return merge(); -} - -Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ -#if LOGDOTEXP - printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); -#endif - if (ident == Id::length) - { - Expression *ec; - FuncDeclaration *fd; - Array *arguments; - - fd = FuncDeclaration::genCfunc(Type::tsize_t, "_aaLen"); - ec = new VarExp(0, fd); - arguments = new Array(); - arguments->push(e); - e = new CallExp(e->loc, ec, arguments); - e->type = fd->type->next; - } - else if (ident == Id::keys) - { - Expression *ec; - FuncDeclaration *fd; - Array *arguments; - char aakeys[7+3*sizeof(int)+1]; - int size = key->size(e->loc); - - assert(size); -#if 0 - if (size == 1 || size == 2 || size == 4 || size == 8) - { - sprintf(aakeys, "_aaKeys%d", size); - size = 0; - } - else -#endif - strcpy(aakeys, "_aaKeys"); - fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), aakeys); - ec = new VarExp(0, fd); - arguments = new Array(); - arguments->push(e); - if (size) - arguments->push(new IntegerExp(0, size, Type::tint32)); - e = new CallExp(e->loc, ec, arguments); - e->type = index->arrayOf(); - } - else if (ident == Id::values) - { - Expression *ec; - FuncDeclaration *fd; - Array *arguments; - - fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), "_aaValues"); - ec = new VarExp(0, fd); - arguments = new Array(); - arguments->push(e); - arguments->push(new IntegerExp(0, key->size(e->loc), Type::tint32)); - arguments->push(new IntegerExp(0, next->size(e->loc), Type::tint32)); - e = new CallExp(e->loc, ec, arguments); - e->type = next->arrayOf(); - } - else if (ident == Id::rehash) - { - Expression *ec; - FuncDeclaration *fd; - Array *arguments; - - fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), "_aaRehash"); - ec = new VarExp(0, fd); - arguments = new Array(); - arguments->push(e->addressOf()); - arguments->push(key->getInternalTypeInfo(sc)); - e = new CallExp(e->loc, ec, arguments); - e->type = this; - } - else - { - e = Type::dotExp(sc, e, ident); - } - return e; -} - -void TypeAArray::toDecoBuffer(OutBuffer *buf) -{ - buf->writeByte(mangleChar[ty]); - index->toDecoBuffer(buf); - next->toDecoBuffer(buf); -} - -void TypeAArray::toPrettyBracket(OutBuffer *buf) -{ - buf->writeByte('['); - { OutBuffer ibuf; - - index->toCBuffer2(&ibuf, NULL); - buf->write(&ibuf); - } - buf->writeByte(']'); -} - -Expression *TypeAArray::defaultInit() -{ -#if LOGDEFAULTINIT - printf("TypeAArray::defaultInit() '%s'\n", toChars()); -#endif - Expression *e; - e = new NullExp(0); - e->type = this; - return e; -} - -int TypeAArray::checkBoolean() -{ - return TRUE; -} - -/***************************** TypePointer *****************************/ - -TypePointer::TypePointer(Type *t) - : Type(Tpointer, t) -{ -} - -Type *TypePointer::syntaxCopy() -{ - Type *t = next->syntaxCopy(); - if (t == next) - t = this; - else - t = new TypePointer(t); - return t; -} - -Type *TypePointer::semantic(Loc loc, Scope *sc) -{ - //printf("TypePointer::semantic()\n"); - Type *n = next->semantic(loc, sc); - if (n != next) - deco = NULL; - next = n; - return merge(); -} - - -d_uns64 TypePointer::size(Loc loc) -{ - return PTRSIZE; -} - -void TypePointer::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - //printf("TypePointer::toCBuffer2() next = %d\n", next->ty); - buf->prependstring("*"); - if (ident) - { - buf->writestring(ident->toChars()); - } - next->toCBuffer2(buf, NULL); -} - -int TypePointer::implicitConvTo(Type *to) -{ - //printf("TypePointer::implicitConvTo()\n"); - - if (this == to) - return MATCHexact; - if (to->ty == Tpointer && to->next) - { - if (to->next->ty == Tvoid) - return MATCHconvert; - -#if 0 - if (to->next->isBaseOf(next)) - return MATCHconvert; -#endif - - if (next->ty == Tfunction && to->next->ty == Tfunction) - { TypeFunction *tf; - TypeFunction *tfto; - - tf = (TypeFunction *)(next); - tfto = (TypeFunction *)(to->next); - return tfto->equals(tf) ? MATCHexact : MATCHnomatch; - } - } -// if (to->ty == Tvoid) -// return MATCHconvert; - return MATCHnomatch; -} - -int TypePointer::isscalar() -{ - return TRUE; -} - -Expression *TypePointer::defaultInit() -{ -#if LOGDEFAULTINIT - printf("TypePointer::defaultInit() '%s'\n", toChars()); -#endif - Expression *e; - e = new NullExp(0); - e->type = this; - return e; -} - -int TypePointer::isZeroInit() -{ - return 1; -} - - -/***************************** TypeReference *****************************/ - -TypeReference::TypeReference(Type *t) - : Type(Treference, t) -{ - if (t->ty == Tbit) - error(0,"cannot make reference to a bit"); - // BUG: what about references to static arrays? -} - -Type *TypeReference::syntaxCopy() -{ - Type *t = next->syntaxCopy(); - if (t == next) - t = this; - else - t = new TypeReference(t); - return t; -} - -d_uns64 TypeReference::size(Loc loc) -{ - return PTRSIZE; -} - -void TypeReference::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - buf->prependstring("&"); - if (ident) - { - buf->writestring(ident->toChars()); - } - next->toCBuffer2(buf, NULL); -} - -Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ -#if LOGDOTEXP - printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); -#endif - - // References just forward things along - return next->dotExp(sc, e, ident); -} - -Expression *TypeReference::defaultInit() -{ -#if LOGDEFAULTINIT - printf("TypeReference::defaultInit() '%s'\n", toChars()); -#endif - Expression *e; - e = new NullExp(0); - e->type = this; - return e; -} - -int TypeReference::isZeroInit() -{ - return 1; -} - - -/***************************** TypeFunction *****************************/ - -TypeFunction::TypeFunction(Array *arguments, Type *treturn, int varargs, enum LINK linkage) - : Type(Tfunction, treturn) -{ - this->arguments = arguments; - this->varargs = varargs; - this->linkage = linkage; -} - -Type *TypeFunction::syntaxCopy() -{ - Type *treturn = next->syntaxCopy(); - Array *args = Argument::arraySyntaxCopy(arguments); - Type *t = new TypeFunction(args, treturn, varargs, linkage); - return t; -} - -/******************************* - * Returns: - * 0 types are distinct - * 1 this is covariant with t - * 2 arguments match as far as overloading goes, - * but types are not covariant - */ - -int Type::covariant(Type *t) -{ - int inoutmismatch = 0; - - if (equals(t)) - goto Lcovariant; - if (ty != Tfunction || t->ty != Tfunction) - goto Ldistinct; - - { - TypeFunction *t1 = (TypeFunction *)this; - TypeFunction *t2 = (TypeFunction *)t; - - if (t1->varargs != t2->varargs) - goto Ldistinct; - - if (t1->arguments && t2->arguments) - { - if (t1->arguments->dim != t2->arguments->dim) - goto Ldistinct; - - for (int i = 0; i < t1->arguments->dim; i++) - { Argument *arg1 = (Argument *)t1->arguments->data[i]; - Argument *arg2 = (Argument *)t2->arguments->data[i]; - - if (!arg1->type->equals(arg2->type)) - goto Ldistinct; - if (arg1->inout != arg2->inout) - inoutmismatch = 1; - } - } - else if (t1->arguments != t2->arguments) - goto Ldistinct; - - // The argument lists match - if (inoutmismatch) - goto Lnotcovariant; - if (t1->linkage != t2->linkage) - goto Lnotcovariant; - - Type *t1n = t1->next; - Type *t2n = t2->next; - - if (t1n->equals(t2n)) - goto Lcovariant; - if (t1n->ty != Tclass || t2n->ty != Tclass) - goto Lnotcovariant; - if (t1n->implicitConvTo(t2n)) - goto Lcovariant; - goto Lnotcovariant; - } - -Lcovariant: - return 1; - -Ldistinct: - return 0; - -Lnotcovariant: - return 2; -} - -void TypeFunction::toDecoBuffer(OutBuffer *buf) -{ unsigned char mc; - - switch (linkage) - { - case LINKd: mc = 'F'; break; - case LINKc: mc = 'U'; break; - case LINKwindows: mc = 'W'; break; - case LINKpascal: mc = 'V'; break; - case LINKcpp: mc = 'T'; break; - default: - assert(0); - } - buf->writeByte(mc); - // Write arguments - if (arguments) - { int i; - - for (i = 0; i < arguments->dim; i++) - { Argument *arg; - - arg = (Argument *)arguments->data[i]; - switch (arg->inout) - { case In: - break; - case Out: - buf->writeByte('J'); - break; - case InOut: - buf->writeByte('K'); - break; - default: - assert(0); - } - arg->type->toDecoBuffer(buf); - } - } - buf->writeByte(varargs ? 'Y' : 'Z'); // mark end of arg list - next->toDecoBuffer(buf); -} - -void TypeFunction::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - char *p; - - switch (linkage) - { - case LINKd: p = NULL; break; - case LINKc: p = "C "; break; - case LINKwindows: p = "Windows "; break; - case LINKpascal: p = "Pascal "; break; - case LINKcpp: p = "C++ "; break; - default: - assert(0); - } - - if (buf->offset) - { - if (p) - buf->prependstring(p); - buf->bracket('(', ')'); - assert(!ident); - } - else - { - if (p) - buf->writestring(p); - if (ident) - { buf->writeByte(' '); - buf->writestring(ident->toChars()); - } - } - argsToCBuffer(buf); - next->toCBuffer2(buf, NULL); -} - -void TypeFunction::argsToCBuffer(OutBuffer *buf) -{ - buf->writeByte('('); - if (arguments) - { int i; - OutBuffer argbuf; - - for (i = 0; i < arguments->dim; i++) - { Argument *arg; - - if (i) - buf->writeByte(','); - arg = (Argument *)arguments->data[i]; - if (arg->inout == Out) - buf->writestring("out "); - else if (arg->inout == InOut) - buf->writestring("inout "); - argbuf.reset(); - arg->type->toCBuffer2(&argbuf, arg->ident); - if (arg->defaultArg) - { - argbuf.writestring(" = "); - arg->defaultArg->toCBuffer(&argbuf); - } - buf->write(&argbuf); - } - if (varargs) - { - if (i) - buf->writeByte(','); - buf->writestring("..."); - } - } - buf->writeByte(')'); -} - -Type *TypeFunction::semantic(Loc loc, Scope *sc) -{ - if (deco) // if semantic() already run - { - //printf("already done\n"); - return this; - } - linkage = sc->linkage; - next = next->semantic(loc,sc); - if (next->toBasetype()->ty == Tsarray) - error(loc, "functions cannot return static array %s", next->toChars()); - if (next->isauto() && !(sc->flags & SCOPEctor)) - error(loc, "functions cannot return auto %s", next->toChars()); - - if (arguments) - { int i; - - for (i = 0; i < arguments->dim; i++) - { Argument *arg; - Type *t; - - arg = (Argument *)arguments->data[i]; - arg->type = arg->type->semantic(loc,sc); - t = arg->type->toBasetype(); - if (arg->inout != In) - { - if (t->ty == Tsarray) - error(loc, "cannot have out or inout parameter of type %s", t->toChars()); - } - if (t->ty == Tvoid) - error(loc, "cannot have parameter of type %s", arg->type->toChars()); - - if (arg->defaultArg) - { - arg->defaultArg = arg->defaultArg->semantic(sc); - arg->defaultArg = resolveProperties(sc, arg->defaultArg); - arg->defaultArg = arg->defaultArg->implicitCastTo(arg->type); - } - } - } - deco = merge()->deco; - - if (varargs && linkage != LINKd && !(arguments && arguments->dim)) - error(loc, "variadic functions with non-C linkage must have at least one parameter"); - - /* Don't return merge(), because arg identifiers and default args - * can be different - * even though the types match - */ - return this; -} - -/******************************** - * Assume 'toargs' are being matched to function 'this' - * Determine match level. - * Returns: - * 0 no match - * 1 match with conversions - * 2 exact match - */ - -int TypeFunction::callMatch(Array *toargs) -{ - unsigned u; - unsigned nargsf; - unsigned nargst; - int match; - - //printf("TypeFunction::callMatch()\n"); - match = 2; // assume exact match - - nargsf = arguments ? arguments->dim : 0; - nargst = toargs ? toargs->dim : 0; - if (nargsf == nargst) - ; - else if (nargst > nargsf) - { - if (!varargs) - goto Nomatch; // too many args; no match - match = 1; // match ... with a "conversion" match level - } - - for (u = 0; u < nargsf; u++) - { int m; - Argument *af; - Expression *ae; - - // BUG: what about out and inout? - - af = (Argument *)arguments->data[u]; - assert(af); - if (u >= nargst) - { - if (af->defaultArg) - continue; - goto Nomatch; // not enough arguments - } - ae = (Expression *)toargs->data[u]; - assert(ae); - m = ae->implicitConvTo(af->type); - //printf("\tm = %d\n", m); - if (m == 0) - goto Nomatch; // no match for this argument - if (m < match) - match = m; // pick worst match - } - - //printf("match = %d\n", match); - return match; - -Nomatch: - //printf("no match\n"); - return 0; -} - -/***************************** TypeDelegate *****************************/ - -TypeDelegate::TypeDelegate(Type *t) - : Type(Tfunction, t) -{ - ty = Tdelegate; -} - -Type *TypeDelegate::syntaxCopy() -{ - Type *t = next->syntaxCopy(); - if (t == next) - t = this; - else - t = new TypeDelegate(t); - return t; -} - -Type *TypeDelegate::semantic(Loc loc, Scope *sc) -{ - if (deco) // if semantic() already run - { - //printf("already done\n"); - return this; - } - next = next->semantic(loc,sc); - return merge(); -} - -d_uns64 TypeDelegate::size(Loc loc) -{ - return PTRSIZE * 2; -} - -void TypeDelegate::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ -#if 1 - OutBuffer args; - TypeFunction *tf = (TypeFunction *)next; - - tf->argsToCBuffer(&args); - buf->prependstring(args.toChars()); - buf->prependstring(" delegate"); - if (ident) - { - buf->writestring(ident->toChars()); - } - next->next->toCBuffer2(buf, NULL); -#else - next->toCBuffer2(buf, Id::delegate); - if (ident) - { - buf->writestring(ident->toChars()); - } -#endif -} - -Expression *TypeDelegate::defaultInit() -{ -#if LOGDEFAULTINIT - printf("TypeDelegate::defaultInit() '%s'\n", toChars()); -#endif - Expression *e; - e = new NullExp(0); - e->type = this; - return e; -} - -int TypeDelegate::isZeroInit() -{ - return 1; -} - -int TypeDelegate::checkBoolean() -{ - return TRUE; -} - - - -/***************************** TypeQualified *****************************/ - -TypeQualified::TypeQualified(TY ty, Loc loc) - : Type(ty, NULL) -{ - this->loc = loc; -} - -void TypeQualified::syntaxCopyHelper(TypeQualified *t) -{ - idents.setDim(t->idents.dim); - for (int i = 0; i < idents.dim; i++) - { - Identifier *id = (Identifier *)t->idents.data[i]; - if (id->dyncast() != DYNCAST_IDENTIFIER) - { - TemplateInstance *ti = (TemplateInstance *)id; - - ti = (TemplateInstance *)ti->syntaxCopy(NULL); - id = (Identifier *)ti; - } - idents.data[i] = id; - } -} - - -void TypeQualified::addIdent(Identifier *ident) -{ - idents.push(ident); -} - -void TypeQualified::toCBuffer2Helper(OutBuffer *buf, Identifier *ident) -{ - int i; - - for (i = 0; i < idents.dim; i++) - { Identifier *id = (Identifier *)idents.data[i]; - - buf->writeByte('.'); - - if (id->dyncast() != DYNCAST_IDENTIFIER) - { - TemplateInstance *ti = (TemplateInstance *)id; - ti->toCBuffer(buf); - } - else - buf->writestring(id->toChars()); - } -} - -d_uns64 TypeQualified::size(Loc loc) -{ - error(this->loc, "size of type %s is not known", toChars()); - return 1; -} - -/************************************* - * Takes an array of Identifiers and figures out if - * it represents a Type or an Expression. - * Output: - * if expression, *pe is set - * if type, *pt is set - */ - -void TypeQualified::resolveHelper(Loc loc, Scope *sc, - Dsymbol *s, Dsymbol *scopesym, - Expression **pe, Type **pt, Dsymbol **ps) -{ - Identifier *id = NULL; - int i; - VarDeclaration *v; - EnumMember *em; - Type *t; - Expression *e; - - //printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars()); - //printf("\tscopesym = '%s'\n", scopesym->toChars()); - *pe = NULL; - *pt = NULL; - *ps = NULL; - if (s) - { - //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); - s = s->toAlias(); - //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); - for (i = 0; i < idents.dim; i++) - { Dsymbol *sm; - - id = (Identifier *)idents.data[i]; - if (id->dyncast() != DYNCAST_IDENTIFIER) - { - // It's a template instance - //printf("\ttemplate instance id\n"); - TemplateDeclaration *td; - TemplateInstance *ti = (TemplateInstance *)id; - id = (Identifier *)ti->idents.data[0]; - sm = s->search(id, 0); - if (!sm) - { error(loc, "template identifier %s is not a member of %s", id->toChars(), s->toChars()); - return; - } - sm = sm->toAlias(); - td = sm->isTemplateDeclaration(); - if (!td) - { - error(loc, "%s is not a template", id->toChars()); - return; - } - ti->tempdecl = td; - ti->semantic(sc); - sm = ti->toAlias(); - } - else - sm = s->search(id, 0); -//printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind()); -//printf("getType = '%s'\n", s->getType()->toChars()); - if (!sm) - { -#if 0 - if (s->isAliasDeclaration() && this->ty == Tident) - { - *pt = this; - return; - } -#endif - t = s->getType(); - if (!t && s->isDeclaration()) - t = s->isDeclaration()->type; - if (t) - { -//<<>> - sm = t->toDsymbol(sc); - if (sm) - { sm = sm->search(id, 0); - if (sm) - goto L2; - } - e = t->getProperty(loc, id); - i++; - for (; i < idents.dim; i++) - { - id = (Identifier *)idents.data[i]; - e = e->type->dotExp(sc, e, id); - } - *pe = e; - } - else - error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars()); - return; - } - L2: - s = sm->toAlias(); - } - - v = s->isVarDeclaration(); - if (v) - { - // It's not a type, it's an expression - if (v->isConst() && v->getExpInitializer()) - { - ExpInitializer *ei = v->getExpInitializer(); - assert(ei); - *pe = ei->exp->copy(); // make copy so we can change loc - (*pe)->loc = loc; - } - else - { -#if 0 - WithScopeSymbol *withsym; - if (scopesym && (withsym = scopesym->isWithScopeSymbol()) != NULL) - { - // Same as wthis.ident - e = new VarExp(loc, withsym->withstate->wthis); - e = new DotIdExp(loc, e, ident); - //assert(0); // BUG: should handle this - } - else -#endif - *pe = new VarExp(loc, v); - } - return; - } - em = s->isEnumMember(); - if (em) - { - // It's not a type, it's an expression - *pe = em->value->copy(); - return; - } - -L1: - t = s->getType(); - if (!t) - { - // If the symbol is an import, try looking inside the import - Import *si; - - si = s->isImport(); - if (si) - { - s = si->search(s->ident, 0); - if (s) - goto L1; - s = si; - } - *ps = s; - return; - } - if (t->ty == Tident && t != this) - { - Scope *scx; - - for (scx = sc; 1; scx = scx->enclosing) - { - if (!scx) - { error(loc, "forward reference to '%s'", t->toChars()); - return; - } - if (scx->scopesym == scopesym) - break; - } - ((TypeIdentifier *)t)->resolve(loc, scx, pe, &t, ps); - } - *pt = t->merge(); - } - if (!s) - { - error(loc, "identifier '%s' is not defined", toChars()); - } -} - -/***************************** TypeIdentifier *****************************/ - -TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident) - : TypeQualified(Tident, loc) -{ - this->ident = ident; -} - - -Type *TypeIdentifier::syntaxCopy() -{ - TypeIdentifier *t; - - t = new TypeIdentifier(loc, ident); - t->syntaxCopyHelper(this); - return t; -} - -void TypeIdentifier::toDecoBuffer(OutBuffer *buf) -{ unsigned len; - char *name; - - name = ident->toChars(); - //len = strlen(name); - //buf->printf("%c%d%s", mangleChar[ty], len, name); - buf->printf("%c%s", mangleChar[ty], name); -} - -void TypeIdentifier::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - OutBuffer tmp; - - tmp.writestring(this->ident->toChars()); - toCBuffer2Helper(&tmp, NULL); - buf->prependstring(tmp.toChars()); - if (ident) - { buf->writeByte(' '); - buf->writestring(ident->toChars()); - } -} - -/************************************* - * Takes an array of Identifiers and figures out if - * it represents a Type or an Expression. - * Output: - * if expression, *pe is set - * if type, *pt is set - */ - -void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) -{ Dsymbol *s; - Dsymbol *scopesym; - - //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars()); - s = sc->search(ident, &scopesym); - resolveHelper(loc, sc, s, scopesym, pe, pt, ps); -} - -/***************************************** - * See if type resolves to a symbol, if so, - * return that symbol. - */ - -Dsymbol *TypeIdentifier::toDsymbol(Scope *sc) -{ - Dsymbol *s; - Dsymbol *scopesym; - - //printf("TypeIdentifier::toDsymbol('%s')\n", toChars()); - if (!sc) - return NULL; - //printf("ident = '%s'\n", ident->toChars()); - s = sc->search(ident, &scopesym); - if (s) - { - s = s->toAlias(); - for (int i = 0; i < idents.dim; i++) - { Identifier *id; - Dsymbol *sm; - - id = (Identifier *)idents.data[i]; - //printf("\tid = '%s'\n", id->toChars()); - if (id->dyncast() != DYNCAST_IDENTIFIER) - { - // It's a template instance - //printf("\ttemplate instance id\n"); - TemplateDeclaration *td; - TemplateInstance *ti = (TemplateInstance *)id; - id = (Identifier *)ti->idents.data[0]; - sm = s->search(id, 0); - if (!sm) - { error(loc, "template identifier %s is not a member of %s", id->toChars(), s->toChars()); - break; - } - sm = sm->toAlias(); - td = sm->isTemplateDeclaration(); - if (!td) - { - error(loc, "%s is not a template", id->toChars()); - break; - } - ti->tempdecl = td; - ti->semantic(sc); - sm = ti->toAlias(); - } - else - sm = s->search(id, 0); - s = sm; - - if (!s) // failed to find a symbol - break; - s = s->toAlias(); - } - } - return s; -} - -Type *TypeIdentifier::semantic(Loc loc, Scope *sc) -{ - Type *t; - Expression *e; - Dsymbol *s; - - //printf("TypeIdentifier::semantic(%s)\n", toChars()); - resolve(loc, sc, &e, &t, &s); - if (t) - { - if (t->ty == Ttypedef) - { TypeTypedef *tt = (TypeTypedef *)t; - - if (tt->sym->sem == 1) - error(loc, "circular reference of typedef %s", tt->toChars()); - } - } - else - { -#ifdef DEBUG - printf("1: "); -#endif - if (s) - { - s->error(loc, "is used as a type"); - } - else - error(loc, "%s is used as a type", toChars()); - t = tvoid; - } - //t->print(); - return t; -} - -/***************************** TypeInstance *****************************/ - -TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst) - : TypeQualified(Tinstance, loc) -{ - this->tempinst = tempinst; -} - -Type *TypeInstance::syntaxCopy() -{ - TypeInstance *t; - - t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL)); - t->syntaxCopyHelper(this); - return t; -} - - -void TypeInstance::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - OutBuffer tmp; - - tempinst->toCBuffer(&tmp); - toCBuffer2Helper(&tmp, NULL); - buf->prependstring(tmp.toChars()); - if (ident) - { buf->writeByte(' '); - buf->writestring(ident->toChars()); - } -} - -void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) -{ - // Note close similarity to TypeIdentifier::resolve() - - Dsymbol *s; - - *pe = NULL; - *pt = NULL; - *ps = NULL; - -#if 0 - if (!idents.dim) - { - error(loc, "template instance '%s' has no identifier", toChars()); - return; - } -#endif - //id = (Identifier *)idents.data[0]; - //printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars()); - s = tempinst; - if (s) - s->semantic(sc); - resolveHelper(loc, sc, s, NULL, pe, pt, ps); - //printf("pt = '%s'\n", (*pt)->toChars()); -} - -Type *TypeInstance::semantic(Loc loc, Scope *sc) -{ - Type *t; - Expression *e; - Dsymbol *s; - - //printf("TypeInstance::semantic(%s)\n", toChars()); - resolve(loc, sc, &e, &t, &s); - if (!t) - { -#ifdef DEBUG - printf("2: "); -#endif - error(loc, "%s is used as a type", toChars()); - t = tvoid; - } - return t; -} - - -/***************************** TypeTypeof *****************************/ - -TypeTypeof::TypeTypeof(Loc loc, Expression *exp) - : TypeQualified(Ttypeof, loc) -{ - this->exp = exp; -} - -Type *TypeTypeof::syntaxCopy() -{ - TypeTypeof *t; - - t = new TypeTypeof(loc, exp->syntaxCopy()); - t->syntaxCopyHelper(this); - return t; -} - -Dsymbol *TypeTypeof::toDsymbol(Scope *sc) -{ - Type *t; - - t = semantic(0, sc); - return t->toDsymbol(sc); -} - -void TypeTypeof::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - OutBuffer tmp; - - tmp.writestring("typeof("); - exp->toCBuffer(&tmp); - tmp.writeByte(')'); - toCBuffer2Helper(&tmp, NULL); - buf->prependstring(tmp.toChars()); - if (ident) - { buf->writeByte(' '); - buf->writestring(ident->toChars()); - } -} - -Type *TypeTypeof::semantic(Loc loc, Scope *sc) -{ Expression *e; - Type *t; - - //printf("TypeTypeof::semantic()\n"); - - /* Special case for typeof(this) and typeof(super) since both - * should work even if they are not inside a non-static member function - */ - if (exp->op == TOKthis || exp->op == TOKsuper) - { - // Find enclosing struct or class - for (Dsymbol *s = sc->parent; 1; s = s->parent) - { - ClassDeclaration *cd; - StructDeclaration *sd; - - if (!s) - { - error(loc, "%s is not in a struct or class scope", exp->toChars()); - goto Lerr; - } - cd = s->isClassDeclaration(); - if (cd) - { - if (exp->op == TOKsuper) - { - cd = cd->baseClass; - if (!cd) - { error(loc, "class %s has no 'super'", s->toChars()); - goto Lerr; - } - } - t = cd->type; - break; - } - sd = s->isStructDeclaration(); - if (sd) - { - if (exp->op == TOKsuper) - { - error(loc, "struct %s has no 'super'", sd->toChars()); - goto Lerr; - } - t = sd->type->pointerTo(); - break; - } - } - } - else - { - - exp = exp->semantic(sc); - t = exp->type; - if (!t) - { - error(loc, "expression (%s) has no type", exp->toChars()); - goto Lerr; - } - } - - if (idents.dim) - { - error(loc, ".property not implemented for typeof"); - goto Lerr; - } - return t; - -Lerr: - return tvoid; -} - - -/***************************** TypeEnum *****************************/ - -TypeEnum::TypeEnum(EnumDeclaration *sym) - : Type(Tenum, NULL) -{ - this->sym = sym; -} - -char *TypeEnum::toChars() -{ - return sym->toChars(); -} - -Type *TypeEnum::semantic(Loc loc, Scope *sc) -{ - sym->semantic(sc); - return merge(); -} - -d_uns64 TypeEnum::size(Loc loc) -{ - if (!sym->memtype) - { - error(loc, "enum %s is forward referenced", sym->toChars()); - return 4; - } - return sym->memtype->size(loc); -} - -unsigned TypeEnum::alignsize() -{ - if (!sym->memtype) - { - error(0, "enum %s is forward referenced", sym->toChars()); - return 4; - } - return sym->memtype->alignsize(); -} - -Dsymbol *TypeEnum::toDsymbol(Scope *sc) -{ - return sym; -} - -Type *TypeEnum::toBasetype() -{ - if (!sym->memtype) - { - error(0, "enum %s is forward referenced", sym->toChars()); - return tint32; - } - return sym->memtype->toBasetype(); -} - -void TypeEnum::toDecoBuffer(OutBuffer *buf) -{ char *name; - - name = sym->mangle(); - buf->printf("%c%s", mangleChar[ty], name); -} - -void TypeEnum::toTypeInfoBuffer(OutBuffer *buf) -{ - toBasetype()->toTypeInfoBuffer(buf); -} - -void TypeEnum::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - buf->prependbyte(' '); - buf->prependstring(sym->toChars()); - if (ident) - buf->writestring(ident->toChars()); -} - -Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ - EnumMember *m; - Dsymbol *s; - Expression *em; - -#if LOGDOTEXP - printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars()); -#endif - s = sym->symtab->lookup(ident); - if (!s) - { - return getProperty(e->loc, ident); - } - m = s->isEnumMember(); - em = m->value->copy(); - em->loc = e->loc; - return em; -} - -Expression *TypeEnum::getProperty(Loc loc, Identifier *ident) -{ Expression *e; - - if (ident == Id::max) - { - e = new IntegerExp(0, sym->maxval, this); - } - else if (ident == Id::min) - { - e = new IntegerExp(0, sym->minval, this); - } - else - { - assert(sym->memtype); - e = sym->memtype->getProperty(loc, ident); - } - return e; -} - -int TypeEnum::isintegral() -{ - return sym->memtype->isintegral(); -} - -int TypeEnum::isfloating() -{ - return sym->memtype->isfloating(); -} - -int TypeEnum::isunsigned() -{ - return sym->memtype->isunsigned(); -} - -int TypeEnum::isscalar() -{ - return sym->memtype->isscalar(); -} - -int TypeEnum::implicitConvTo(Type *to) -{ int m; - - //printf("TypeEnum::implicitConvTo()\n"); - if (this->equals(to)) - m = 2; // exact match - else if (sym->memtype->implicitConvTo(to)) - m = 1; // match with conversions - else - m = 0; // no match - return m; -} - -Expression *TypeEnum::defaultInit() -{ -#if LOGDEFAULTINIT - printf("TypeEnum::defaultInit() '%s'\n", toChars()); -#endif - // Initialize to first member of enum - Expression *e; - e = new IntegerExp(0, sym->defaultval, this); - return e; -} - -int TypeEnum::isZeroInit() -{ - return (sym->defaultval == 0); -} - - -/***************************** TypeTypedef *****************************/ - -TypeTypedef::TypeTypedef(TypedefDeclaration *sym) - : Type(Ttypedef, NULL) -{ - this->sym = sym; -} - -Type *TypeTypedef::syntaxCopy() -{ - return this; -} - -char *TypeTypedef::toChars() -{ - return sym->toChars(); -} - -Type *TypeTypedef::semantic(Loc loc, Scope *sc) -{ - //printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem); - sym->semantic(sc); - return merge(); -} - -d_uns64 TypeTypedef::size(Loc loc) -{ - return sym->basetype->size(loc); -} - -unsigned TypeTypedef::alignsize() -{ - return sym->basetype->alignsize(); -} - -Dsymbol *TypeTypedef::toDsymbol(Scope *sc) -{ - return sym; -} - -void TypeTypedef::toDecoBuffer(OutBuffer *buf) -{ unsigned len; - char *name; - - name = sym->mangle(); - //len = strlen(name); - //buf->printf("%c%d%s", mangleChar[ty], len, name); - buf->printf("%c%s", mangleChar[ty], name); -} - -void TypeTypedef::toTypeInfoBuffer(OutBuffer *buf) -{ - sym->basetype->toTypeInfoBuffer(buf); -} - -void TypeTypedef::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars()); - buf->prependstring(sym->toChars()); - if (ident) - { buf->writeByte(' '); - buf->writestring(ident->toChars()); - } -} - -Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ -#if LOGDOTEXP - printf("TypeTypedef::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars()); -#endif - if (ident == Id::init) - { - if (e->op == TOKvar) - { - VarExp *ve = (VarExp *)e; - VarDeclaration *v = ve->var->isVarDeclaration(); - - assert(v); - if (v->init) - return v->init->toExpression(); - } - return defaultInit(); - } - return sym->basetype->dotExp(sc, e, ident); -} - -int TypeTypedef::isbit() -{ - return sym->basetype->isbit(); -} - -int TypeTypedef::isintegral() -{ - //printf("TypeTypedef::isintegral()\n"); - //printf("sym = '%s'\n", sym->toChars()); - //printf("basetype = '%s'\n", sym->basetype->toChars()); - return sym->basetype->isintegral(); -} - -int TypeTypedef::isfloating() -{ - return sym->basetype->isfloating(); -} - -int TypeTypedef::isunsigned() -{ - return sym->basetype->isunsigned(); -} - -int TypeTypedef::isscalar() -{ - return sym->basetype->isscalar(); -} - -int TypeTypedef::checkBoolean() -{ - return sym->basetype->checkBoolean(); -} - -Type *TypeTypedef::toBasetype() -{ - return sym->basetype->toBasetype(); -} - -int TypeTypedef::implicitConvTo(Type *to) -{ int m; - - //printf("TypeTypedef::implicitConvTo()\n"); - if (this->equals(to)) - m = 2; // exact match - else if (sym->basetype->implicitConvTo(to)) - m = 1; // match with conversions - else - m = 0; // no match - return m; -} - -Expression *TypeTypedef::defaultInit() -{ Expression *e; - Type *bt; - -#if LOGDEFAULTINIT - printf("TypeTypedef::defaultInit() '%s'\n", toChars()); -#endif - if (sym->init) - { - //sym->init->toExpression()->print(); - return sym->init->toExpression(); - } - bt = sym->basetype; - e = bt->defaultInit(); - e->type = this; - while (bt->ty == Tsarray) - { - e->type = bt->next; - bt = bt->next->toBasetype(); - } - return e; -} - -int TypeTypedef::isZeroInit() -{ - if (sym->init) - return 0; // assume not - return sym->basetype->isZeroInit(); -} - -/***************************** TypeStruct *****************************/ - -TypeStruct::TypeStruct(StructDeclaration *sym) - : Type(Tstruct, NULL) -{ - this->sym = sym; -} - -char *TypeStruct::toChars() -{ - //printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco); - return sym->toChars(); -} - -Type *TypeStruct::syntaxCopy() -{ - return this; -} - -Type *TypeStruct::semantic(Loc loc, Scope *sc) -{ - //printf("TypeStruct::semantic('%s')\n", sym->toChars()); - - /* Cannot do semantic for sym because scope chain may not - * be right. - */ - //sym->semantic(sc); - - return merge(); -} - -d_uns64 TypeStruct::size(Loc loc) -{ - return sym->size(loc); -} - -unsigned TypeStruct::alignsize() -{ unsigned sz; - - sym->size(0); // give error for forward references - sz = sym->alignsize; - if (sz > sym->structalign) - sz = sym->structalign; - return sz; -} - -Dsymbol *TypeStruct::toDsymbol(Scope *sc) -{ - return sym; -} - -void TypeStruct::toDecoBuffer(OutBuffer *buf) -{ unsigned len; - char *name; - - name = sym->mangle(); - //len = strlen(name); - //buf->printf("%c%d%s", mangleChar[ty], len, name); - buf->printf("%c%s", mangleChar[ty], name); -} - -void TypeStruct::toTypeInfoBuffer(OutBuffer *buf) -{ - toDecoBuffer(buf); -} - - -void TypeStruct::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - buf->prependbyte(' '); - buf->prependstring(sym->toChars()); - if (ident) - buf->writestring(ident->toChars()); -} - -Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ unsigned offset; - - Expression *b; - VarDeclaration *v; - Dsymbol *s; - DotVarExp *de; - Declaration *d; - -#if LOGDOTEXP - printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); -#endif - if (!sym->members) - { - error(e->loc, "struct %s is forward referenced", sym->toChars()); - return new IntegerExp(e->loc, 0, Type::tint32); - } - - if (e->op == TOKdotexp) - { DotExp *de = (DotExp *)e; - - if (de->e1->op == TOKimport) - { - ScopeExp *se = (ScopeExp *)de->e1; - - s = se->sds->search(ident, 0); - e = de->e1; - goto L1; - } - } - - s = sym->search(ident, 0); -L1: - if (!s) - { - return getProperty(e->loc, ident); - } - s = s->toAlias(); - - v = s->isVarDeclaration(); - if (v && v->isConst()) - { ExpInitializer *ei = v->getExpInitializer(); - - if (ei) - return ei->exp; - } - - if (s->getType()) - { - //return new DotTypeExp(e->loc, e, s); - return new TypeExp(e->loc, s->getType()); - } - - EnumMember *em = s->isEnumMember(); - if (em) - { - assert(em->value); - return em->value->copy(); - } - - TemplateMixin *tm = s->isTemplateMixin(); - if (tm) - { Expression *de; - - de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm)); - de->type = e->type; - return de; - } - - if (s->isTemplateDeclaration()) - { - s->error("templates don't have properties"); - return e; - } - - d = s->isDeclaration(); -#ifdef DEBUG - if (!d) - printf("d = %s '%s'\n", s->kind(), s->toChars()); -#endif - assert(d); - - if (e->op == TOKtype) - { FuncDeclaration *fd = sc->func; - - if (d->needThis() && fd && fd->vthis) - { - e = new DotVarExp(e->loc, new ThisExp(e->loc), d); - e = e->semantic(sc); - return e; - } - return new VarExp(e->loc, d); - } - - if (d->isStatic()) - { - // (e, d) - b = new VarExp(e->loc, d); - e = new CommaExp(e->loc, e, b); - e->type = d->type; - return e; - } - - if (v) - { - if (v->toParent() != sym) - sym->error(e->loc, "'%s' is not a member", v->toChars()); - - // *(&e + offset) - b = new AddrExp(e->loc, e); - b->type = e->type->pointerTo(); - b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32)); - b->type = v->type->pointerTo(); - e = new PtrExp(e->loc, b); - e->type = v->type; - return e; - } - - de = new DotVarExp(e->loc, e, d); - return de->semantic(sc); -} - -unsigned TypeStruct::memalign(unsigned salign) -{ - sym->size(0); // give error for forward references - return sym->structalign; -} - -Expression *TypeStruct::defaultInit() -{ Symbol *s; - Declaration *d; - -#if LOGDEFAULTINIT - printf("TypeStruct::defaultInit() '%s'\n", toChars()); -#endif - s = sym->toInitializer(); - d = new SymbolDeclaration(sym->loc, s); - assert(d); - d->type = this; - return new VarExp(sym->loc, d); -} - -int TypeStruct::isZeroInit() -{ - return sym->zeroInit; -} - - -/***************************** TypeClass *****************************/ - -TypeClass::TypeClass(ClassDeclaration *sym) - : Type(Tclass, NULL) -{ - this->sym = sym; -} - -char *TypeClass::toChars() -{ - return sym->toPrettyChars(); -} - -Type *TypeClass::syntaxCopy() -{ - return this; -} - -Type *TypeClass::semantic(Loc loc, Scope *sc) -{ - //printf("TypeClass::semantic(%s)\n", sym->toChars()); - if (sym->scope) - sym->semantic(sym->scope); - return merge(); -} - -d_uns64 TypeClass::size(Loc loc) -{ - return PTRSIZE; -} - -Dsymbol *TypeClass::toDsymbol(Scope *sc) -{ - return sym; -} - -void TypeClass::toDecoBuffer(OutBuffer *buf) -{ unsigned len; - char *name; - - name = sym->mangle(); - //printf("TypeClass::toDecoBuffer('%s') = '%s'\n", toChars(), name); - //len = strlen(name); - //buf->printf("%c%d%s", mangleChar[ty], len, name); - buf->printf("%c%s", mangleChar[ty], name); -} - -void TypeClass::toCBuffer2(OutBuffer *buf, Identifier *ident) -{ - buf->prependbyte(' '); - buf->prependstring(sym->toChars()); - if (ident) - buf->writestring(ident->toChars()); -} - -Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident) -{ unsigned offset; - - Expression *b; - VarDeclaration *v; - Dsymbol *s; - DotVarExp *de; - Declaration *d; - -#if LOGDOTEXP - printf("TypeClass::dotExp(e='%s', ident='%s')\n", e->toChars(), ident->toChars()); -#endif - - if (e->op == TOKdotexp) - { DotExp *de = (DotExp *)e; - - if (de->e1->op == TOKimport) - { - ScopeExp *se = (ScopeExp *)de->e1; - - s = se->sds->search(ident, 0); - e = de->e1; - goto L1; - } - } - - s = sym->search(ident, 0); -L1: - if (!s) - { - // See if it's a base class - ClassDeclaration *cbase; - for (cbase = sym->baseClass; cbase; cbase = cbase->baseClass) - { - if (cbase->ident->equals(ident)) - { - e = new DotTypeExp(0, e, cbase); - return e; - } - } - - if (ident == Id::classinfo) - { - Type *t; - - assert(ClassDeclaration::classinfo); - t = ClassDeclaration::classinfo->type; - if (e->op == TOKtype || e->op == TOKdottype) - { - if (!sym->vclassinfo) - sym->vclassinfo = new ClassInfoDeclaration(sym); - e = new VarExp(e->loc, sym->vclassinfo); - e = e->addressOf(); - e->type = t; // do this so we don't get redundant dereference - } - else - { - e = new PtrExp(e->loc, e); - e->type = t->pointerTo(); - if (sym->isInterfaceDeclaration()) - { - if (sym->isCOMclass()) - error(e->loc, "no .classinfo for COM interface objects"); - e->type = e->type->pointerTo(); - e = new PtrExp(e->loc, e); - e->type = t->pointerTo(); - } - e = new PtrExp(e->loc, e, t); - } - return e; - } - - if (ident == Id::typeinfo) - { - if (!global.params.useDeprecated) - error(e->loc, ".typeinfo deprecated, use typeid(type)"); - return getTypeInfo(sc); - } - return getProperty(e->loc, ident); - } - s = s->toAlias(); - v = s->isVarDeclaration(); - if (v && v->isConst()) - { ExpInitializer *ei = v->getExpInitializer(); - - if (ei) - return ei->exp; - } - - if (s->getType()) - { -// if (e->op == TOKtype) - return new TypeExp(e->loc, s->getType()); -// return new DotTypeExp(e->loc, e, s); - } - - EnumMember *em = s->isEnumMember(); - if (em) - { - assert(em->value); - return em->value->copy(); - } - - TemplateMixin *tm = s->isTemplateMixin(); - if (tm) - { Expression *de; - - de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm)); - de->type = e->type; - return de; - } - - d = s->isDeclaration(); - if (!d) - { - e->error("%s.%s is not a declaration", e->toChars(), ident->toChars()); - return new IntegerExp(e->loc, 1, Type::tint32); - } - - if (e->op == TOKtype) - { - VarExp *ve; - - if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration())) - { - if (sc->func) - { - ClassDeclaration *thiscd; - thiscd = sc->func->toParent()->isClassDeclaration(); - - if (thiscd) - { - ClassDeclaration *cd = e->type->isClassHandle(); - - if (cd == thiscd) - { - e = new ThisExp(e->loc); - e = new DotTypeExp(e->loc, e, cd); - de = new DotVarExp(e->loc, e, d); - e = de->semantic(sc); - return e; - } - else if (!cd || !cd->isBaseOf(thiscd, NULL)) - e->error("'this' is required, but %s is not a base class of %s", e->type->toChars(), thiscd->toChars()); - } - } - - de = new DotVarExp(e->loc, new ThisExp(e->loc), d); - e = de->semantic(sc); - return e; - } - else - ve = new VarExp(e->loc, d); - return ve; - } - - if (d->isDataseg()) - { - // (e, d) - VarExp *ve; - - accessCheck(e->loc, sc, e, d); - ve = new VarExp(e->loc, d); - e = new CommaExp(e->loc, e, ve); - e->type = d->type; - return e; - } - - if (d->parent && d->toParent()->isModule()) - { - // (e, d) - VarExp *ve; - - ve = new VarExp(e->loc, d); - e = new CommaExp(e->loc, e, ve); - e->type = d->type; - return e; - } - - de = new DotVarExp(e->loc, e, d); - return de->semantic(sc); -} - -ClassDeclaration *TypeClass::isClassHandle() -{ - return sym; -} - -int TypeClass::isauto() -{ - return sym->isauto; -} - -int TypeClass::isBaseOf(Type *t) -{ - if (t->ty == Tclass) - { ClassDeclaration *cd; - - cd = ((TypeClass *)t)->sym; - if (sym->isBaseOf(cd, NULL)) - return 1; - } - return 0; -} - -int TypeClass::implicitConvTo(Type *to) -{ - //printf("TypeClass::implicitConvTo('%s')\n", to->toChars()); - if (this == to) - return 2; - - ClassDeclaration *cdto = to->isClassHandle(); - if (cdto && cdto->isBaseOf(sym, NULL)) - { //printf("is base\n"); - return 1; - } - - // Allow conversion to (void *) - if (to->ty == Tpointer && to->next->ty == Tvoid) - return 1; - -// if (to->ty == Tvoid) -// return MATCHconvert; - return 0; -} - -Expression *TypeClass::defaultInit() -{ -#if LOGDEFAULTINIT - printf("TypeClass::defaultInit() '%s'\n", toChars()); -#endif - Expression *e; - e = new NullExp(0); - e->type = this; - return e; -} - -int TypeClass::isZeroInit() -{ - return 1; -} - -int TypeClass::checkBoolean() -{ - return TRUE; -} - - - -/***************************** Argument *****************************/ - -Argument::Argument(enum InOut inout, Type *type, Identifier *ident, Expression *defaultArg) -{ - this->type = type; - this->ident = ident; - this->inout = inout; - this->defaultArg = defaultArg; -} - -Argument *Argument::syntaxCopy() -{ - Argument *a = new Argument(inout, - type->syntaxCopy(), - ident, - defaultArg ? defaultArg->syntaxCopy() : NULL); - return a; -} - -Array *Argument::arraySyntaxCopy(Array *args) -{ Array *a = NULL; - - if (args) - { - a = new Array(); - a->setDim(args->dim); - for (int i = 0; i < a->dim; i++) - { Argument *arg = (Argument *)args->data[i]; - - arg = arg->syntaxCopy(); - a->data[i] = (void *)arg; - } - } - return a; -} - -char *Argument::argsTypesToChars(Array *args, int varargs) -{ OutBuffer *buf; - - buf = new OutBuffer(); - - buf->writeByte('('); - if (args) - { int i; - OutBuffer argbuf; - - for (i = 0; i < args->dim; i++) - { Argument *arg; - - if (i) - buf->writeByte(','); - arg = (Argument *)args->data[i]; - argbuf.reset(); - arg->type->toCBuffer2(&argbuf, NULL); - buf->write(&argbuf); - } - if (varargs) - { - if (i) - buf->writeByte(','); - buf->writestring("..."); - } - } - buf->writeByte(')'); - - return buf->toChars(); -} - diff -uNr gdc-0.11/d/root/mtype.h gdc-0.12/d/root/mtype.h --- gdc-0.11/d/root/mtype.h 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/mtype.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,615 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef DMD_MTYPE_H -#define DMD_MTYPE_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" -#include "stringtable.h" - -#include "expression.h" - -struct Scope; -struct Identifier; -struct Expression; -struct StructDeclaration; -struct ClassDeclaration; -struct VarDeclaration; -struct EnumDeclaration; -struct TypedefDeclaration; -struct TypeInfoDeclaration; -struct Dsymbol; -struct TemplateInstance; -enum LINK; - -struct TypeBasic; - -// Back end -union tree_node; typedef union tree_node TYPE; -typedef TYPE type; -struct Symbol; - -enum TY -{ - Tarray, // dynamic array - Tsarray, // static array - Taarray, // associative array - Tpointer, - Treference, - Tfunction, - Tident, - Tclass, - Tstruct, - Tenum, - Ttypedef, - Tdelegate, - - Tnone, - Tvoid, - Tint8, - Tuns8, - Tint16, - Tuns16, - Tint32, - Tuns32, - Tint64, - Tuns64, - Tfloat32, - Tfloat64, - Tfloat80, - - Timaginary32, - Timaginary64, - Timaginary80, - - Tcomplex32, - Tcomplex64, - Tcomplex80, - - Tbit, - Tchar, - Twchar, - Tdchar, - - Terror, - Tinstance, - Ttypeof, - TMAX -}; - -#define Tascii Tchar - -extern int Tsize_t; -extern int Tptrdiff_t; - -enum MATCH -{ - MATCHnomatch, // no match - MATCHconvert, // match with conversions - MATCHexact // exact match -}; - - -struct Type : Object -{ - TY ty; - Type *next; - char *deco; - Type *pto; // merged pointer to this type - Type *rto; // reference to this type - Type *arrayof; // array of this type - TypeInfoDeclaration *vtinfo; // TypeInfo object for this Type - - type *ctype; // for back end - - #define tvoid basic[Tvoid] - #define tint8 basic[Tint8] - #define tuns8 basic[Tuns8] - #define tint16 basic[Tint16] - #define tuns16 basic[Tuns16] - #define tint32 basic[Tint32] - #define tuns32 basic[Tuns32] - #define tint64 basic[Tint64] - #define tuns64 basic[Tuns64] - #define tfloat32 basic[Tfloat32] - #define tfloat64 basic[Tfloat64] - #define tfloat80 basic[Tfloat80] - - #define timaginary32 basic[Timaginary32] - #define timaginary64 basic[Timaginary64] - #define timaginary80 basic[Timaginary80] - - #define tcomplex32 basic[Tcomplex32] - #define tcomplex64 basic[Tcomplex64] - #define tcomplex80 basic[Tcomplex80] - - #define tbit basic[Tbit] - #define tchar basic[Tchar] - #define twchar basic[Twchar] - #define tdchar basic[Tdchar] - - // Some special types - #define tshiftcnt tint32 // right side of shift expression - #define tboolean tint32 // result of boolean expression - #define tindex tint32 // array/ptr index - #define tvoidptr tint32 // size for void* - #define terror basic[Terror] // for error recovery - - #define tsize_t basic[Tsize_t] // matches size_t alias - #define tptrdiff_t basic[Tptrdiff_t] // matches ptrdiff_t alias - - static ClassDeclaration *typeinfo; - static ClassDeclaration *typeinfoclass; - static ClassDeclaration *typeinfostruct; - static ClassDeclaration *typeinfotypedef; - static ClassDeclaration *typeinfopointer; - static ClassDeclaration *typeinfoarray; - static ClassDeclaration *typeinfostaticarray; - static ClassDeclaration *typeinfoassociativearray; - static ClassDeclaration *typeinfoenum; - static ClassDeclaration *typeinfofunction; - static ClassDeclaration *typeinfodelegate; - - static Type *basic[TMAX]; - static unsigned char mangleChar[TMAX]; - static StringTable stringtable; - - // These tables are for implicit conversion of binary ops; - // the indices are the type of operand one, followed by operand two. - static unsigned char impcnvResult[TMAX][TMAX]; - static unsigned char impcnvType1[TMAX][TMAX]; - static unsigned char impcnvType2[TMAX][TMAX]; - - // If !=0, give warning on implicit conversion - static unsigned char impcnvWarn[TMAX][TMAX]; - - Type(TY ty, Type *next); - virtual Type *syntaxCopy(); - int equals(Object *o); - int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType() - int covariant(Type *t); - char *toChars(); - static void init(); - d_uns64 size(); - virtual d_uns64 size(Loc loc); - virtual unsigned alignsize(); - virtual Type *semantic(Loc loc, Scope *sc); - virtual void toDecoBuffer(OutBuffer *buf); - virtual void toTypeInfoBuffer(OutBuffer *buf); - Type *merge(); - void toCBuffer(OutBuffer *buf, Identifier *ident); - virtual void toCBuffer2(OutBuffer *buf, Identifier *ident); - virtual int isbit(); - virtual int isintegral(); - virtual int isfloating(); // real, imaginary, or complex - virtual int isreal(); - virtual int isimaginary(); - virtual int iscomplex(); - virtual int isscalar(); - virtual int isunsigned(); - virtual int isauto(); - virtual int isString(); - virtual int checkBoolean(); // if can be converted to boolean value - void checkDeprecated(Loc loc, Scope *sc); - Type *pointerTo(); - Type *referenceTo(); - Type *arrayOf(); - virtual Dsymbol *toDsymbol(Scope *sc); - virtual Type *toBasetype(); - virtual int isBaseOf(Type *t); - virtual int implicitConvTo(Type *to); - virtual ClassDeclaration *isClassHandle(); - virtual Expression *getProperty(Loc loc, Identifier *ident); - virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - virtual unsigned memalign(unsigned salign); - virtual Expression *defaultInit(); - virtual int isZeroInit(); // if initializer is 0 - virtual dt_t **toDt(dt_t **pdt); - Identifier *getTypeInfoIdent(int internal); - virtual MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); - virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); - Expression *getInternalTypeInfo(Scope *sc); - Expression *getTypeInfo(Scope *sc); - virtual TypeInfoDeclaration *getTypeInfoDeclaration(); - virtual int builtinTypeInfo(); - - static void error(Loc loc, const char *format, ...); - - // For backend - virtual unsigned totym(); - virtual type *toCtype(); - virtual type *toCParamtype(); - virtual Symbol *toSymbol(); - - // For eliminating dynamic_cast - virtual TypeBasic *isTypeBasic(); -}; - -struct TypeBasic : Type -{ - char *dstring; - char *cstring; - unsigned flags; - - TypeBasic(TY ty); - Type *syntaxCopy(); - d_uns64 size(Loc loc); - unsigned alignsize(); - Expression *getProperty(Loc loc, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - char *toChars(); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - int isintegral(); - int isbit(); - int isfloating(); - int isreal(); - int isimaginary(); - int iscomplex(); - int isscalar(); - int isunsigned(); - int implicitConvTo(Type *to); - Expression *defaultInit(); - int isZeroInit(); - int builtinTypeInfo(); - - // For eliminating dynamic_cast - TypeBasic *isTypeBasic(); -}; - -struct TypeArray : Type -{ - TypeArray(TY ty, Type *next); - virtual void toPrettyBracket(OutBuffer *buf) = 0; - void toCBuffer2(OutBuffer *buf, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); -}; - -// Static array, one with a fixed dimension -struct TypeSArray : TypeArray -{ - Expression *dim; - - TypeSArray(Type *t, Expression *dim); - Type *syntaxCopy(); - d_uns64 size(Loc loc); - unsigned alignsize(); - Type *semantic(Loc loc, Scope *sc); - void toDecoBuffer(OutBuffer *buf); - void toTypeInfoBuffer(OutBuffer *buf); - void toPrettyBracket(OutBuffer *buf); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - int isString(); - unsigned memalign(unsigned salign); - int implicitConvTo(Type *to); - Expression *defaultInit(); - dt_t **toDt(dt_t **pdt); - MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - type *toCtype(); - type *toCParamtype(); -}; - -// Dynamic array, no dimension -struct TypeDArray : TypeArray -{ - TypeDArray(Type *t); - Type *syntaxCopy(); - d_uns64 size(Loc loc); - unsigned alignsize(); - Type *semantic(Loc loc, Scope *sc); - void toDecoBuffer(OutBuffer *buf); - void toTypeInfoBuffer(OutBuffer *buf); - void toPrettyBracket(OutBuffer *buf); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - int isString(); - int checkBoolean(); - int implicitConvTo(Type *to); - Expression *defaultInit(); - int builtinTypeInfo(); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - type *toCtype(); -}; - -struct TypeAArray : TypeArray -{ - Type *index; // key type for type checking - Type *key; // actual key type - - TypeAArray(Type *t, Type *index); - Type *syntaxCopy(); - d_uns64 size(Loc loc); - Type *semantic(Loc loc, Scope *sc); - void toDecoBuffer(OutBuffer *buf); - void toPrettyBracket(OutBuffer *buf); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - Expression *defaultInit(); - MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); - int checkBoolean(); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - // Back end - Symbol *aaGetSymbol(char *func, int flags); - - type *toCtype(); -}; - -struct TypePointer : Type -{ - TypePointer(Type *t); - Type *syntaxCopy(); - Type *semantic(Loc loc, Scope *sc); - d_uns64 size(Loc loc); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - int implicitConvTo(Type *to); - int isscalar(); - Expression *defaultInit(); - int isZeroInit(); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - type *toCtype(); -}; - -struct TypeReference : Type -{ - TypeReference(Type *t); - Type *syntaxCopy(); - d_uns64 size(Loc loc); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - Expression *defaultInit(); - int isZeroInit(); -}; - -enum RET -{ - RETregs = 1, // returned in registers - RETstack = 2, // returned on stack -}; - -struct TypeFunction : Type -{ - Array *arguments; // Array of Argument's - int varargs; // if variable number of arguments - enum LINK linkage; // calling convention - - TypeFunction(Array *arguments, Type *treturn, int varargs, enum LINK linkage); - Type *syntaxCopy(); - Type *semantic(Loc loc, Scope *sc); - void toDecoBuffer(OutBuffer *buf); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - void argsToCBuffer(OutBuffer *buf); - MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - int callMatch(Array *toargs); - type *toCtype(); - enum RET retStyle(); - - unsigned totym(); -}; - -struct TypeDelegate : Type -{ - TypeDelegate(Type *t); - Type *syntaxCopy(); - Type *semantic(Loc loc, Scope *sc); - d_uns64 size(Loc loc); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - Expression *defaultInit(); - int isZeroInit(); - int checkBoolean(); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - type *toCtype(); -}; - -struct TypeQualified : Type -{ - Loc loc; - Array idents; // array of Identifier's representing ident.ident.ident etc. - - TypeQualified(TY ty, Loc loc); - void syntaxCopyHelper(TypeQualified *t); - void addIdent(Identifier *ident); - void toCBuffer2Helper(OutBuffer *buf, Identifier *ident); - d_uns64 size(Loc loc); - void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym, - Expression **pe, Type **pt, Dsymbol **ps); -}; - -struct TypeIdentifier : TypeQualified -{ - Identifier *ident; - - TypeIdentifier(Loc loc, Identifier *ident); - Type *syntaxCopy(); - //char *toChars(); - void toDecoBuffer(OutBuffer *buf); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); - Dsymbol *toDsymbol(Scope *sc); - Type *semantic(Loc loc, Scope *sc); - MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); -}; - -/* Similar to TypeIdentifier, but with a TemplateInstance as the root - */ -struct TypeInstance : TypeQualified -{ - TemplateInstance *tempinst; - - TypeInstance(Loc loc, TemplateInstance *tempinst); - Type *syntaxCopy(); - //char *toChars(); - //void toDecoBuffer(OutBuffer *buf); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); - Type *semantic(Loc loc, Scope *sc); - MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); -}; - -struct TypeTypeof : TypeQualified -{ - Expression *exp; - - TypeTypeof(Loc loc, Expression *exp); - Type *syntaxCopy(); - Dsymbol *toDsymbol(Scope *sc); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - Type *semantic(Loc loc, Scope *sc); -}; - -struct TypeStruct : Type -{ - StructDeclaration *sym; - - TypeStruct(StructDeclaration *sym); - d_uns64 size(Loc loc); - unsigned alignsize(); - char *toChars(); - Type *syntaxCopy(); - Type *semantic(Loc loc, Scope *sc); - Dsymbol *toDsymbol(Scope *sc); - void toDecoBuffer(OutBuffer *buf); - void toTypeInfoBuffer(OutBuffer *buf); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - unsigned memalign(unsigned salign); - Expression *defaultInit(); - int isZeroInit(); - dt_t **toDt(dt_t **pdt); - MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - type *toCtype(); -}; - -struct TypeEnum : Type -{ - EnumDeclaration *sym; - - TypeEnum(EnumDeclaration *sym); - d_uns64 size(Loc loc); - unsigned alignsize(); - char *toChars(); - Type *semantic(Loc loc, Scope *sc); - Dsymbol *toDsymbol(Scope *sc); - void toDecoBuffer(OutBuffer *buf); - void toTypeInfoBuffer(OutBuffer *buf); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - Expression *getProperty(Loc loc, Identifier *ident); - int isintegral(); - int isfloating(); - int isscalar(); - int isunsigned(); - int implicitConvTo(Type *to); - Type *toBasetype(); - Expression *defaultInit(); - int isZeroInit(); - MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - type *toCtype(); -}; - -struct TypeTypedef : Type -{ - TypedefDeclaration *sym; - - TypeTypedef(TypedefDeclaration *sym); - Type *syntaxCopy(); - d_uns64 size(Loc loc); - unsigned alignsize(); - char *toChars(); - Type *semantic(Loc loc, Scope *sc); - Dsymbol *toDsymbol(Scope *sc); - void toDecoBuffer(OutBuffer *buf); - void toTypeInfoBuffer(OutBuffer *buf); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - int isbit(); - int isintegral(); - int isfloating(); - int isscalar(); - int isunsigned(); - int checkBoolean(); - Type *toBasetype(); - int implicitConvTo(Type *to); - Expression *defaultInit(); - int isZeroInit(); - dt_t **toDt(dt_t **pdt); - MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - type *toCtype(); - type *toCParamtype(); -}; - -struct TypeClass : Type -{ - ClassDeclaration *sym; - - TypeClass(ClassDeclaration *sym); - d_uns64 size(Loc loc); - char *toChars(); - Type *syntaxCopy(); - Type *semantic(Loc loc, Scope *sc); - Dsymbol *toDsymbol(Scope *sc); - void toDecoBuffer(OutBuffer *buf); - void toCBuffer2(OutBuffer *buf, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - ClassDeclaration *isClassHandle(); - int isBaseOf(Type *t); - int implicitConvTo(Type *to); - Expression *defaultInit(); - int isZeroInit(); - MATCH deduceType(Type *tparam, Array *parameters, Array *atypes); - int isauto(); - int checkBoolean(); - TypeInfoDeclaration *getTypeInfoDeclaration(); - - type *toCtype(); - - Symbol *toSymbol(); -}; - -enum InOut { In, Out, InOut }; - -struct Argument : Object -{ - enum InOut inout; - Type *type; - Identifier *ident; - Expression *defaultArg; - - Argument(enum InOut inout, Type *type, Identifier *ident, Expression *defaultArg); - Argument *syntaxCopy(); - static Array *arraySyntaxCopy(Array *args); - static char *argsTypesToChars(Array *args, int varargs); -}; - -extern int PTRSIZE; -extern int REALSIZE; -extern int Tsize_t; -extern int Tptrdiff_t; - -#endif /* DMD_MTYPE_H */ diff -uNr gdc-0.11/d/root/opover.c gdc-0.12/d/root/opover.c --- gdc-0.11/d/root/opover.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/opover.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,426 +0,0 @@ -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - - -// Issues with using -include total.h (defines integer_t) and then complex.h fails... -#undef integer_t - -#include -#include -#include -#include -#include - -#ifdef __APPLE__ -#define integer_t dmd_integer_t -#endif - -#ifndef _WIN32 -#include "../root/mem.h" -#endif -#if _WIN32 -#include "..\root\mem.h" -#endif - -#include "port.h" -#include "mtype.h" -#include "init.h" -#include "expression.h" -#include "id.h" -#include "declaration.h" -#include "aggregate.h" - -static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id); - -/******************************** Expression **************************/ - - -/*********************************** - * Determine if operands of binary op can be reversed - * to fit operator overload. - */ - -int Expression::isCommutative() -{ - return FALSE; // default is no reverse -} - -/*********************************** - * Get Identifier for operator overload. - */ - -Identifier *Expression::opId() -{ - assert(0); - return NULL; -} - -/*********************************** - * Get Identifier for reverse operator overload, - * NULL if not supported for this operator. - */ - -Identifier *Expression::opId_r() -{ - return NULL; -} - -/************************* Operators *****************************/ - -Identifier *UAddExp::opId() { return Id::uadd; } - -Identifier *NegExp::opId() { return Id::neg; } - -Identifier *ComExp::opId() { return Id::com; } - -Identifier *CastExp::opId() { return Id::cast; } - -Identifier *PostIncExp::opId() { return Id::postinc; } - -Identifier *PostDecExp::opId() { return Id::postdec; } - -int AddExp::isCommutative() { return TRUE; } -Identifier *AddExp::opId() { return Id::add; } -Identifier *AddExp::opId_r() { return Id::add_r; } - -Identifier *MinExp::opId() { return Id::sub; } -Identifier *MinExp::opId_r() { return Id::sub_r; } - -int MulExp::isCommutative() { return TRUE; } -Identifier *MulExp::opId() { return Id::mul; } -Identifier *MulExp::opId_r() { return Id::mul_r; } - -Identifier *DivExp::opId() { return Id::div; } -Identifier *DivExp::opId_r() { return Id::div_r; } - -Identifier *ModExp::opId() { return Id::mod; } -Identifier *ModExp::opId_r() { return Id::mod_r; } - -Identifier *ShlExp::opId() { return Id::shl; } -Identifier *ShlExp::opId_r() { return Id::shl_r; } - -Identifier *ShrExp::opId() { return Id::shr; } -Identifier *ShrExp::opId_r() { return Id::shr_r; } - -Identifier *UshrExp::opId() { return Id::ushr; } -Identifier *UshrExp::opId_r() { return Id::ushr_r; } - -int AndExp::isCommutative() { return TRUE; } -Identifier *AndExp::opId() { return Id::iand; } -Identifier *AndExp::opId_r() { return Id::iand_r; } - -int OrExp::isCommutative() { return TRUE; } -Identifier *OrExp::opId() { return Id::ior; } -Identifier *OrExp::opId_r() { return Id::ior_r; } - -int XorExp::isCommutative() { return TRUE; } -Identifier *XorExp::opId() { return Id::ixor; } -Identifier *XorExp::opId_r() { return Id::ixor_r; } - -Identifier *CatExp::opId() { return Id::cat; } -Identifier *CatExp::opId_r() { return Id::cat_r; } - -Identifier * AddAssignExp::opId() { return Id::addass; } -Identifier * MinAssignExp::opId() { return Id::subass; } -Identifier * MulAssignExp::opId() { return Id::mulass; } -Identifier * DivAssignExp::opId() { return Id::divass; } -Identifier * ModAssignExp::opId() { return Id::modass; } -Identifier * AndAssignExp::opId() { return Id::andass; } -Identifier * OrAssignExp::opId() { return Id::orass; } -Identifier * XorAssignExp::opId() { return Id::xorass; } -Identifier * ShlAssignExp::opId() { return Id::shlass; } -Identifier * ShrAssignExp::opId() { return Id::shrass; } -Identifier *UshrAssignExp::opId() { return Id::ushrass; } -Identifier * CatAssignExp::opId() { return Id::catass; } - -int EqualExp::isCommutative() { return TRUE; } -Identifier *EqualExp::opId() { return Id::eq; } - -int CmpExp::isCommutative() { return TRUE; } -Identifier *CmpExp::opId() { return Id::cmp; } - -Identifier *ArrayExp::opId() { return Id::index; } - - -/************************************ - * Operator overload. - * Check for operator overload, if so, replace - * with function call. - * Return NULL if not an operator overload. - */ - -Expression *UnaExp::op_overload(Scope *sc) -{ - AggregateDeclaration *ad; - FuncDeclaration *fd; - Type *t1 = e1->type->toBasetype(); - - if (t1->ty == Tclass) - { - ad = ((TypeClass *)t1)->sym; - goto L1; - } - else if (t1->ty == Tstruct) - { - ad = ((TypeStruct *)t1)->sym; - - L1: - fd = search_function(ad, opId()); - if (fd) - { - if (op == TOKarray) - { - Expression *e; - ArrayExp *ae = (ArrayExp *)this; - - e = new DotIdExp(loc, e1, fd->ident); - e = new CallExp(loc, e, ae->arguments); - e = e->semantic(sc); - return e; - } - else - { - // Rewrite +e1 as e1.add() - return build_overload(loc, sc, e1, NULL, fd->ident); - } - } - } - return NULL; -} - - -Expression *BinExp::op_overload(Scope *sc) -{ - //printf("BinExp::op_overload() (%s)\n", toChars()); - - AggregateDeclaration *ad; - Type *t1 = e1->type->toBasetype(); - Type *t2 = e2->type->toBasetype(); - Identifier *id = opId(); - Identifier *id_r = opId_r(); - - Match m; - Array args1; - Array args2; - int argsset = 0; - - AggregateDeclaration *ad1; - if (t1->ty == Tclass) - ad1 = ((TypeClass *)t1)->sym; - else if (t1->ty == Tstruct) - ad1 = ((TypeStruct *)t1)->sym; - else - ad1 = NULL; - - AggregateDeclaration *ad2; - if (t2->ty == Tclass) - ad2 = ((TypeClass *)t2)->sym; - else if (t2->ty == Tstruct) - ad2 = ((TypeStruct *)t2)->sym; - else - ad2 = NULL; - - FuncDeclaration *fd = NULL; - FuncDeclaration *fd_r = NULL; - if (ad1 && id) - { - fd = search_function(ad1, id); - } - if (ad2 && id_r) - { - fd_r = search_function(ad2, id_r); - } - - if (fd || fd_r) - { - /* Try: - * a.opfunc(b) - * b.opfunc_r(a) - * and see which is better. - */ - Expression *e; - FuncDeclaration *lastf; - - args1.setDim(1); - args1.data[0] = (void*) e1; - args2.setDim(1); - args2.data[0] = (void*) e2; - argsset = 1; - - memset(&m, 0, sizeof(m)); - m.last = MATCHnomatch; - overloadResolveX(&m, fd, &args2); - lastf = m.lastf; - overloadResolveX(&m, fd_r, &args1); - - if (m.count > 1) - { - // Error, ambiguous - error("overloads %s and %s both match argument list for %s", - m.lastf->type->toChars(), - m.nextf->type->toChars(), - m.lastf->toChars()); - } - else if (m.last == MATCHnomatch) - { - m.lastf = m.anyf; - } - - if (op == TOKplusplus || op == TOKminusminus) - // Kludge because operator overloading regards e++ and e-- - // as unary, but it's implemented as a binary. - // Rewrite (e1 ++ e2) as e1.postinc() - // Rewrite (e1 -- e2) as e1.postdec() - e = build_overload(loc, sc, e1, NULL, id); - else if (lastf && m.lastf == lastf || m.last == MATCHnomatch) - // Rewrite (e1 op e2) as e1.opfunc(e2) - e = build_overload(loc, sc, e1, e2, id); - else - // Rewrite (e1 op e2) as e2.opfunc_r(e1) - e = build_overload(loc, sc, e2, e1, id_r); - return e; - } - - if (isCommutative()) - { - fd = NULL; - fd_r = NULL; - if (ad1 && id_r) - { - fd_r = search_function(ad1, id_r); - } - if (ad2 && id) - { - fd = search_function(ad2, id); - } - - if (fd || fd_r) - { - /* Try: - * a.opfunc_r(b) - * b.opfunc(a) - * and see which is better. - */ - Expression *e; - FuncDeclaration *lastf; - - if (!argsset) - { args1.setDim(1); - args1.data[0] = (void*) e1; - args2.setDim(1); - args2.data[0] = (void*) e2; - } - - memset(&m, 0, sizeof(m)); - m.last = MATCHnomatch; - overloadResolveX(&m, fd_r, &args2); - lastf = m.lastf; - overloadResolveX(&m, fd, &args1); - - if (m.count > 1) - { - // Error, ambiguous - error("overloads %s and %s both match argument list for %s", - m.lastf->type->toChars(), - m.nextf->type->toChars(), - m.lastf->toChars()); - } - else if (m.last == MATCHnomatch) - { - m.lastf = m.anyf; - } - - if (lastf && m.lastf == lastf || - id_r && m.last == MATCHnomatch) - // Rewrite (e1 op e2) as e1.opfunc_r(e2) - e = build_overload(loc, sc, e1, e2, id_r); - else - // Rewrite (e1 op e2) as e2.opfunc(e1) - e = build_overload(loc, sc, e2, e1, id); - - // When reversing operands of comparison operators, - // need to reverse the sense of the op - switch (op) - { - case TOKlt: op = TOKgt; break; - case TOKgt: op = TOKlt; break; - case TOKle: op = TOKge; break; - case TOKge: op = TOKle; break; - - // Floating point compares - case TOKule: op = TOKuge; break; - case TOKul: op = TOKug; break; - case TOKuge: op = TOKule; break; - case TOKug: op = TOKul; break; - - // These are symmetric - case TOKunord: - case TOKlg: - case TOKleg: - case TOKue: - break; - } - - return e; - } - } - - return NULL; -} - -/*********************************** - * Utility to build a function call out of this reference and argument. - */ - -static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id) -{ - Expression *e; - - //printf("build_overload(id = '%s')\n", id->toChars()); - //earg->print(); - //earg->type->print(); - e = new DotIdExp(loc, ethis, id); - - if (earg) - e = new CallExp(loc, e, earg); - else - e = new CallExp(loc, e); - - e = e->semantic(sc); - return e; -} - -/*************************************** - * Search for function funcid in aggregate ad. - */ - -FuncDeclaration *search_function(AggregateDeclaration *ad, Identifier *funcid) -{ - Dsymbol *s; - FuncDeclaration *fd; - - s = ad->search(funcid, 0); - if (s) - { Dsymbol *s2; - - //printf("search_function: s = '%s'\n", s->kind()); - s2 = s->toAlias(); - //printf("search_function: s2 = '%s'\n", s2->kind()); - fd = s2->isFuncDeclaration(); - if (fd && fd->type->ty == Tfunction) - return fd; - - } - return NULL; -} diff -uNr gdc-0.11/d/root/optimize.c gdc-0.12/d/root/optimize.c --- gdc-0.11/d/root/optimize.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/optimize.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,298 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include - -#include "mem.h" -#include "root.h" - -#include "lexer.h" -#include "mtype.h" -#include "expression.h" -#include "declaration.h" -#include "aggregate.h" - - -Expression *Expression::optimize(int result) -{ - return this; -} - -Expression *UnaExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - if (e1->isConst() == 1) - e = constFold(); - else - e = this; - return e; -} - -Expression *AddrExp::optimize(int result) -{ Expression *e; - - //printf("AddrExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(result); - // Convert &*ex to ex - if (e1->op == TOKstar) - { Expression *ex; - - ex = ((PtrExp *)e1)->e1; - if (type->equals(ex->type)) - e = ex; - else - { - e = ex->copy(); - e->type = type; - } - return e; - } - if (e1->op == TOKvar) - { VarExp *ve = (VarExp *)e1; - if (!ve->var->isOut() && !ve->var->isImportedSymbol()) - { - e = new SymOffExp(loc, ve->var, 0); - e->type = type; - return e; - } - } - if (e1->op == TOKindex) - { // Convert &array[n] to #array+n - IndexExp *ae = (IndexExp *)e1; - - if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar) - { - integer_t index = ae->e2->toInteger(); - VarExp *ve = (VarExp *)ae->e1; - if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit - && !ve->var->isImportedSymbol()) - { - TypeSArray *ts = (TypeSArray *)ve->type; - integer_t dim = ts->dim->toInteger(); - if (index < 0 || index >= dim) - error("array index %lld is out of bounds [0..%lld]", index, dim); - e = new SymOffExp(loc, ve->var, index * ts->next->size()); - e->type = type; - return e; - } - } - } - return this; -} - -Expression *PtrExp::optimize(int result) -{ - e1 = e1->optimize(result); - // Convert *&ex to ex - if (e1->op == TOKaddress) - { Expression *e; - Expression *ex; - - ex = ((AddrExp *)e1)->e1; - if (type->equals(ex->type)) - e = ex; - else - { - e = ex->copy(); - e->type = type; - } - return e; - } - return this; -} - -Expression *CastExp::optimize(int result) -{ - if (e1->op == TOKstring && - (type->ty == Tpointer || type->ty == Tarray) && - type->next->equals(e1->type->next) - ) - { - e1->type = type; - return e1; - } - if (e1->op == TOKnull && - (type->ty == Tpointer || type->ty == Tclass)) - { - e1->type = type; - return e1; - } - - if (result == WANTflags && type->ty == Tclass && e1->type->ty == Tclass) - { - // See if we can remove an unnecessary cast - ClassDeclaration *cdfrom; - ClassDeclaration *cdto; - int offset; - - cdfrom = e1->type->isClassHandle(); - cdto = type->isClassHandle(); - if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) - { - e1->type = type; - return e1; - } - } - - Expression *e; - - e1 = e1->optimize(result); - if (e1->isConst()) - e = constFold(); - else - e = this; - return e; -} - -Expression *BinExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() == 1 && e2->isConst() == 1) - e = constFold(); - else - e = this; - return e; -} - -Expression *AddExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() && e2->isConst()) - e = constFold(); - else - e = this; - return e; -} - -Expression *MinExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() && e2->isConst()) - e = constFold(); - else - e = this; - return e; -} - -Expression *CommaExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(0); - e2 = e2->optimize(result); - if (!e1) - { - e = e2; - if (e) - e->type = type; - } - else - e = this; - return e; -} - -Expression *AndAndExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(WANTflags); - e2 = e2->optimize(WANTflags); - e = this; - if (e1->isBool(FALSE)) - e = new IntegerExp(loc, 0, type); - else if (e1->isConst()) - { - if (e2->isConst()) - e = constFold(); - else if (e1->isBool(TRUE)) - e = new BoolExp(loc, e2, type); - } - return e; -} - -Expression *OrOrExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(WANTflags); - e2 = e2->optimize(WANTflags); - e = this; - if (e1->isBool(TRUE)) - e = new IntegerExp(loc, 1, type); - else if (e1->isConst()) - { - if (e2->isConst()) - e = constFold(); - else if (e1->isBool(FALSE)) - e = new BoolExp(loc, e2, type); - } - return e; -} - -Expression *CatExp::optimize(int result) -{ Expression *e; - - //printf("CatExp::optimize(%d)\n", result); - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->op == TOKstring && e2->op == TOKstring) - { - // Concatenate the strings - void *s; - StringExp *es1 = (StringExp *)e1; - StringExp *es2 = (StringExp *)e2; - StringExp *es; - Type *t; - - assert(es1->sz == es2->sz); - s = mem.malloc((es1->len + es2->len + 1) * es1->sz); - memcpy(s, es1->string, es1->len * es1->sz); - memcpy((unsigned char *)s + es1->len, es2->string, es2->len * es1->sz); - - // Add terminating 0 - memset((unsigned char *)s + es1->len + es2->len, 0, es1->sz); - - es = new StringExp(loc, s, es1->len + es2->len); - es->sz = es1->sz; - es->committed = es1->committed | es2->committed; - if (es1->committed) - t = es1->type; - else - t = es2->type; - es->type = new TypeSArray(t->next, new IntegerExp(0, es1->len + es2->len, Type::tindex)); - e = es; - } - else - e = this; - return e; -} - - -Expression *CondExp::optimize(int result) -{ Expression *e; - - econd = econd->optimize(WANTflags); - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (econd->isBool(TRUE)) - e = e1; - else if (econd->isBool(FALSE)) - e = e2; - else - e = this; - return e; -} - - diff -uNr gdc-0.11/d/root/parse.c gdc-0.12/d/root/parse.c --- gdc-0.11/d/root/parse.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/parse.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,4378 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include - -#include "mem.h" -#include "lexer.h" -#include "parse.h" -#include "init.h" -#include "attrib.h" -#include "debcond.h" -#include "mtype.h" -#include "template.h" -#include "staticassert.h" -#include "expression.h" -#include "statement.h" -#include "module.h" -#include "dsymbol.h" -#include "import.h" -#include "declaration.h" -#include "aggregate.h" -#include "enum.h" -#include "id.h" -#include "version.h" - -// How multiple declarations are parsed. -// If 1, treat as C. -// If 0, treat: -// int *p, i; -// as: -// int* p; -// int* i; -#define CDECLSYNTAX 0 - -// Support C cast syntax: -// (type)(expression) -#define CCASTSYNTAX 1 - -// Support D cast syntax: -// cast(type)(expression) -#define DCASTSYNTAX 1 - -// Support C array declarations, such as -// int a[3][4]; -#define CARRAYDECL 1 - -// Support left-to-right array declarations -#define LTORARRAYDECL 1 - -// Suppor references -#define REFERENCES 0 - -/************************************ - * These control how parseStatement() works. - */ - -enum ParseStatementFlags -{ - PSsemi = 1, // empty ';' statements are allowed - PSscope = 2, // start a new scope - PScurly = 4, // { } statement is required - PScurlyscope = 8, // { } starts a new scope -}; - - -Parser::Parser(Module *module, unsigned char *base, unsigned length) - : Lexer(module, base, length) -{ - //printf("Parser::Parser()\n"); - md = NULL; - linkage = LINKd; - endloc = 0; - inBrackets = 0; - nextToken(); // start up the scanner -} - -Array *Parser::parseModule() -{ - Array *decldefs; - - // ModuleDeclation leads off - if (token.value == TOKmodule) - { - nextToken(); - if (token.value != TOKidentifier) - { error("Identifier expected following module"); - goto Lerr; - } - else - { - Array *a = NULL; - Identifier *id; - - id = token.ident; - while (nextToken() == TOKdot) - { - if (!a) - a = new Array(); - a->push(id); - nextToken(); - if (token.value != TOKidentifier) - { error("Identifier expected following package"); - goto Lerr; - } - id = token.ident; - } - - md = new ModuleDeclaration(a, id); - - if (token.value != TOKsemicolon) - error("';' expected following module declaration instead of %s", token.toChars()); - nextToken(); - } - } - - decldefs = parseDeclDefs(0); - if (token.value != TOKeof) - { error("unrecognized declaration"); - goto Lerr; - } - return decldefs; - -Lerr: - while (token.value != TOKsemicolon && token.value != TOKeof) - nextToken(); - nextToken(); - return new Array(); -} - -Array *Parser::parseDeclDefs(int once) -{ Dsymbol *s; - Array *decldefs; - Array *a; - enum PROT prot; - unsigned stc; - - //printf("Parser::parseDeclDefs()\n"); - decldefs = new Array(); - do - { - switch (token.value) - { - case TOKenum: - s = parseEnum(); - break; - - case TOKstruct: - case TOKunion: - case TOKclass: - case TOKinterface: - s = parseAggregate(); - break; - - case TOKimport: - s = parseImport(decldefs); - break; - - case TOKtemplate: - s = (Dsymbol *)parseTemplateDeclaration(); - break; - - case TOKmixin: - s = parseMixin(); - break; - - case TOKinstance: // Deprecated - if (isDeclaration(&token, 2, TOKreserved, NULL)) - { - //printf("it's a declaration\n"); - goto Ldeclaration; - } - else - { - // instance foo(bar) ident; - - TemplateInstance *ti; - - //printf("it's an alias\n"); - ti = parseTemplateInstance(); - s = (Dsymbol *)ti; - if (ti) - { - if (token.value == TOKidentifier) - { - s = (Dsymbol *)new AliasDeclaration(loc, token.ident, ti); - nextToken(); - } - } - if (token.value != TOKsemicolon) - error("';' expected after template instance"); - } - break; - - CASE_BASIC_TYPES: - case TOKalias: - case TOKtypedef: - case TOKidentifier: - case TOKtypeof: - case TOKdot: - Ldeclaration: - a = parseDeclaration(); - decldefs->append(a); - continue; - - case TOKthis: - s = parseCtor(); - break; - - case TOKtilde: - s = parseDtor(); - break; - - case TOKinvariant: - s = parseInvariant(); - break; - - case TOKunittest: - s = parseUnitTest(); - break; - - case TOKnew: - s = parseNew(); - break; - - case TOKdelete: - s = parseDelete(); - break; - - case TOKeof: - case TOKrcurly: - return decldefs; - - case TOKstatic: - nextToken(); - if (token.value == TOKthis) - s = parseStaticCtor(); - else if (token.value == TOKtilde) - s = parseStaticDtor(); - else if (token.value == TOKassert) - s = parseStaticAssert(); - else - { stc = STCstatic; - goto Lstc2; - } - break; - - case TOKconst: stc = STCconst; goto Lstc; - case TOKfinal: stc = STCfinal; goto Lstc; - case TOKauto: stc = STCauto; goto Lstc; - case TOKoverride: stc = STCoverride; goto Lstc; - case TOKabstract: stc = STCabstract; goto Lstc; - case TOKsynchronized: stc = STCsynchronized; goto Lstc; - case TOKdeprecated: stc = STCdeprecated; goto Lstc; - - Lstc: - nextToken(); - Lstc2: - switch (token.value) - { - case TOKconst: stc |= STCconst; goto Lstc; - case TOKfinal: stc |= STCfinal; goto Lstc; - case TOKauto: stc |= STCauto; goto Lstc; - case TOKoverride: stc |= STCoverride; goto Lstc; - case TOKabstract: stc |= STCabstract; goto Lstc; - case TOKsynchronized: stc |= STCsynchronized; goto Lstc; - case TOKdeprecated: stc |= STCdeprecated; goto Lstc; - } - a = parseBlock(); - s = new StorageClassDeclaration(stc, a); - break; - - - case TOKprivate: prot = PROTprivate; goto Lprot; - case TOKpackage: prot = PROTpackage; goto Lprot; - case TOKprotected: prot = PROTprotected; goto Lprot; - case TOKpublic: prot = PROTpublic; goto Lprot; - case TOKexport: prot = PROTexport; goto Lprot; - - Lprot: - nextToken(); - a = parseBlock(); - s = new ProtDeclaration(prot, a); - break; - - case TOKalign: - { unsigned n; - - s = NULL; - nextToken(); - if (token.value == TOKlparen) - { - nextToken(); - if (token.value == TOKint32v) - n = (unsigned)token.uns64value; - else - { error("integer expected, not %s", token.toChars()); - n = 1; - } - nextToken(); - check(TOKrparen); - } - else - n = global.structalign; // default - - a = parseBlock(); - s = new AlignDeclaration(n, a); - break; - } - - case TOKpragma: - { Identifier *ident; - Array *args = NULL; - - nextToken(); - check(TOKlparen); - if (token.value != TOKidentifier) - { error("pragma(identifier expected"); - goto Lerror; - } - ident = token.ident; - nextToken(); - if (token.value == TOKcomma) - args = parseArguments(); // pragma(identifier, args...) - else - check(TOKrparen); // pragma(identifier) - - if (token.value == TOKsemicolon) - a = NULL; - else - a = parseBlock(); - s = new PragmaDeclaration(loc, ident, args, a); - break; - } - - case TOKextern: - { enum LINK link = LINKdefault; - enum LINK linksave; - - s = NULL; - nextToken(); - if (token.value == TOKlparen) - { - nextToken(); - if (token.value == TOKidentifier) - { Identifier *id = token.ident; - - nextToken(); - if (id == Id::Windows) - link = LINKwindows; - else if (id == Id::Pascal) - link = LINKpascal; - else if (id == Id::D) - link = LINKd; - else if (id == Id::C) - { - link = LINKc; - if (token.value == TOKplusplus) - { link = LINKcpp; - nextToken(); - } - } - else - { - error("valid linkage identifiers are D, C, C++, Pascal, Windows"); - link = LINKd; - break; - } - } - else - { - link = LINKd; // default - } - check(TOKrparen); - } - else - { stc = STCextern; - goto Lstc2; - } - linksave = linkage; - linkage = link; - a = parseBlock(); - linkage = linksave; - s = new LinkDeclaration(link, a); - break; - } - - case TOKdebug: - { DebugCondition *condition; - Array *aelse; - - nextToken(); - if (token.value == TOKassign) - { - nextToken(); - if (token.value == TOKidentifier) - s = new DebugSymbol(token.ident); - else if (token.value == TOKint32v) - s = new DebugSymbol((unsigned)token.uns64value); - else - { error("identifier or integer expected, not %s", token.toChars()); - s = NULL; - } - nextToken(); - if (token.value != TOKsemicolon) - error("semicolon expected"); - nextToken(); - break; - } - - if (token.value == TOKlparen) - { - nextToken(); - condition = parseDebugCondition(); - check(TOKrparen); - } - else - condition = new DebugCondition(mod, 1, NULL); - a = parseBlock(); - aelse = NULL; - if (token.value == TOKelse) - { nextToken(); - aelse = parseBlock(); - } - s = new DebugDeclaration(condition, a, aelse); - break; - } - - case TOKversion: - { VersionCondition *condition; - Array *aelse; - - nextToken(); - if (token.value == TOKassign) - { - nextToken(); - if (token.value == TOKidentifier) - s = new VersionSymbol(token.ident); - else if (token.value == TOKint32v) - s = new VersionSymbol((unsigned)token.uns64value); - else - { error("identifier or integer expected, not %s", token.toChars()); - s = NULL; - } - nextToken(); - if (token.value != TOKsemicolon) - error("semicolon expected"); - nextToken(); - break; - } - - if (token.value == TOKlparen) - { - nextToken(); - condition = parseVersionCondition(); - check(TOKrparen); - } - else - { error("(condition) expected following version"); - condition = NULL; - } - a = parseBlock(); - aelse = NULL; - if (token.value == TOKelse) - { nextToken(); - aelse = parseBlock(); - } - s = new VersionDeclaration(condition, a, aelse); - break; - } - - case TOKsemicolon: // empty declaration - nextToken(); - continue; - - default: - error("Declaration expected, not '%s'",token.toChars()); - Lerror: - while (token.value != TOKsemicolon && token.value != TOKeof) - nextToken(); - nextToken(); - s = NULL; - continue; - } - if (s) - decldefs->push(s); - } while (!once); - return decldefs; -} - -/******************************************** - * Parse declarations after an align, protection, or extern decl. - */ - -Array *Parser::parseBlock() -{ - Array *a = NULL; - Dsymbol *s; - - //printf("parseBlock()\n"); - switch (token.value) - { - case TOKsemicolon: - error("declaration expected following attribute, not ';'"); - nextToken(); - break; - - case TOKlcurly: - nextToken(); - a = parseDeclDefs(0); - if (token.value != TOKrcurly) - { /* { */ - error("matching '}' expected, not %s", token.toChars()); - } - else - nextToken(); - break; - - case TOKcolon: - nextToken(); -#if 1 - a = NULL; -#else - a = parseDeclDefs(0); // grab declarations up to closing curly bracket -#endif - break; - - default: - a = parseDeclDefs(1); - break; - } - return a; -} - -/********************************** - * Parse a static assertion. - */ - -StaticAssert *Parser::parseStaticAssert() -{ - Loc loc = this->loc; - Expression *exp; - - //printf("parseStaticAssert()\n"); - nextToken(); - check(TOKlparen); - exp = parseExpression(); - check(TOKrparen); - check(TOKsemicolon); - return new StaticAssert(loc, exp); -} - -/************************************** - * Parse a debug conditional - */ - -DebugCondition *Parser::parseDebugCondition() -{ - unsigned level = 1; - Identifier *id = NULL; - - if (token.value == TOKidentifier) - id = token.ident; - else if (token.value == TOKint32v) - level = (unsigned)token.uns64value; - else - error("identifier or integer expected, not %s", token.toChars()); - nextToken(); - - return new DebugCondition(mod, level, id); -} - -/************************************** - * Parse a version conditional - */ - -VersionCondition *Parser::parseVersionCondition() -{ - unsigned level = 1; - Identifier *id = NULL; - - if (token.value == TOKidentifier) - id = token.ident; - else if (token.value == TOKint32v) - level = (unsigned)token.uns64value; - else - error("identifier or integer expected, not %s", token.toChars()); - nextToken(); - - return new VersionCondition(mod, level, id); -} - -/***************************************** - * Parse a constructor definition: - * this(arguments) { body } - * Current token is 'this'. - */ - -CtorDeclaration *Parser::parseCtor() -{ - CtorDeclaration *f; - Array *arguments; - int varargs; - Loc loc = this->loc; - - nextToken(); - arguments = parseParameters(&varargs); - f = new CtorDeclaration(loc, 0, arguments, varargs); - parseContracts(f); - return f; -} - -/***************************************** - * Parse a destructor definition: - * ~this() { body } - * Current token is '~'. - */ - -DtorDeclaration *Parser::parseDtor() -{ - DtorDeclaration *f; - Loc loc = this->loc; - - nextToken(); - check(TOKthis); - check(TOKlparen); - check(TOKrparen); - - f = new DtorDeclaration(loc, 0); - parseContracts(f); - return f; -} - -/***************************************** - * Parse a static constructor definition: - * static this() { body } - * Current token is 'this'. - */ - -StaticCtorDeclaration *Parser::parseStaticCtor() -{ - StaticCtorDeclaration *f; - Loc loc = this->loc; - - nextToken(); - check(TOKlparen); - check(TOKrparen); - - f = new StaticCtorDeclaration(loc, 0); - parseContracts(f); - return f; -} - -/***************************************** - * Parse a static destructor definition: - * static ~this() { body } - * Current token is '~'. - */ - -StaticDtorDeclaration *Parser::parseStaticDtor() -{ - StaticDtorDeclaration *f; - Loc loc = this->loc; - - nextToken(); - check(TOKthis); - check(TOKlparen); - check(TOKrparen); - - f = new StaticDtorDeclaration(loc, 0); - parseContracts(f); - return f; -} - -/***************************************** - * Parse an invariant definition: - * invariant { body } - * Current token is 'invariant'. - */ - -InvariantDeclaration *Parser::parseInvariant() -{ - InvariantDeclaration *f; - Loc loc = this->loc; - - nextToken(); - //check(TOKlparen); // don't require () - //check(TOKrparen); - - f = new InvariantDeclaration(loc, 0); - f->fbody = parseStatement(PScurly); - return f; -} - -/***************************************** - * Parse a unittest definition: - * unittest { body } - * Current token is 'unittest'. - */ - -UnitTestDeclaration *Parser::parseUnitTest() -{ - UnitTestDeclaration *f; - Statement *body; - Loc loc = this->loc; - - nextToken(); - - body = parseStatement(PScurly); - - f = new UnitTestDeclaration(loc, this->loc); - f->fbody = body; - return f; -} - -/***************************************** - * Parse a new definition: - * new(arguments) { body } - * Current token is 'new'. - */ - -NewDeclaration *Parser::parseNew() -{ - NewDeclaration *f; - Array *arguments; - int varargs; - Loc loc = this->loc; - - nextToken(); - arguments = parseParameters(&varargs); - f = new NewDeclaration(loc, 0, arguments, varargs); - parseContracts(f); - return f; -} - -/***************************************** - * Parse a delete definition: - * delete(arguments) { body } - * Current token is 'delete'. - */ - -DeleteDeclaration *Parser::parseDelete() -{ - DeleteDeclaration *f; - Array *arguments; - int varargs; - Loc loc = this->loc; - - nextToken(); - arguments = parseParameters(&varargs); - if (varargs) - error("... not allowed in delete function parameter list"); - f = new DeleteDeclaration(loc, 0, arguments); - parseContracts(f); - return f; -} - -/********************************************** - * Parse parameter list. - */ - -Array *Parser::parseParameters(int *pvarargs) -{ - Array *arguments = new Array(); - int varargs = 0; - int hasdefault = 0; - - check(TOKlparen); - while (1) - { Type *tb; - Identifier *ai; - Type *at; - Argument *a; - enum InOut inout; - Expression *ae; - - ai = NULL; - inout = In; // parameter is "in" by default - switch (token.value) - { - case TOKrparen: - break; - - case TOKdotdotdot: - varargs = 1; - nextToken(); - break; - - case TOKin: - inout = In; - nextToken(); - goto L1; - - case TOKout: - inout = Out; - nextToken(); - goto L1; - - case TOKinout: - inout = InOut; - nextToken(); - goto L1; - - default: - L1: - tb = parseBasicType(); - at = parseDeclarator(tb, &ai); - if (token.value == TOKassign) // = defaultArg - { nextToken(); - ae = parseAssignExp(); - hasdefault = 1; - } - else - { if (hasdefault) - error("default argument expected for %s", - ai ? ai->toChars() : at->toChars()); - ae = NULL; - } - a = new Argument(inout, at, ai, ae); - arguments->push(a); - if (token.value == TOKcomma) - { nextToken(); - continue; - } - break; - } - break; - } - check(TOKrparen); - *pvarargs = varargs; - return arguments; -} - -/************************************* - */ - -EnumDeclaration *Parser::parseEnum() -{ EnumDeclaration *e; - Identifier *id; - Type *t; - - //printf("Parser::parseEnum()\n"); - nextToken(); - if (token.value == TOKidentifier) - { id = token.ident; - nextToken(); - } - else - id = NULL; - - if (token.value == TOKcolon) - { - nextToken(); - t = parseBasicType(); - } - else - t = NULL; - - e = new EnumDeclaration(id, t); - if (token.value == TOKsemicolon && id) - nextToken(); - else if (token.value == TOKlcurly) - { - //printf("enum definition\n"); - e->members = new Array(); - nextToken(); - while (token.value != TOKrcurly) - { - if (token.value == TOKidentifier) - { EnumMember *em; - Expression *value; - Identifier *ident; - - ident = token.ident; - value = NULL; - nextToken(); - if (token.value == TOKassign) - { - nextToken(); - value = parseAssignExp(); - } - em = new EnumMember(loc, ident, value); - e->members->push(em); - if (token.value == TOKrcurly) - ; - else - check(TOKcomma); - } - else - { error("enum member expected"); - nextToken(); - } - } - nextToken(); - } - else - error("enum declaration is invalid"); - - return e; -} - -Dsymbol *Parser::parseAggregate() -{ AggregateDeclaration *a = NULL; - int anon = 0; - enum TOK tok; - Identifier *id; - Array *tpl = NULL; - - //printf("Parser::parseAggregate()\n"); - tok = token.value; - nextToken(); - if (token.value != TOKidentifier) - { id = NULL; - } - else - { id = token.ident; - nextToken(); - - if (token.value == TOKlparen) - { // Class template declaration. - - // Gather template parameter list - tpl = parseTemplateParameterList(); - } - } - - switch (tok) - { case TOKclass: - case TOKinterface: - { - Array *baseclasses = NULL; - BaseClass *b; - - if (!id) - error("anonymous classes not allowed"); - - // Collect base class(es) - b = NULL; - if (token.value == TOKcolon) - { enum PROT protection = PROTpublic; - - baseclasses = new Array(); - while (1) - { - nextToken(); - switch (token.value) - { - case TOKidentifier: - case TOKinstance: - break; - case TOKprivate: - protection = PROTprivate; - continue; - case TOKpackage: - protection = PROTpackage; - continue; - case TOKprotected: - protection = PROTprotected; - continue; - case TOKpublic: - protection = PROTpublic; - continue; - default: - error("base classes expected following ':'"); - return NULL; - } - b = new BaseClass(parseBasicType(), protection); - baseclasses->push(b); - if (token.value != TOKcomma) - break; - protection = PROTpublic; - } - if (token.value != TOKlcurly) - error("members expected"); - } - - if (tok == TOKclass) - a = new ClassDeclaration(loc, id, baseclasses); - else - a = new InterfaceDeclaration(loc, id, baseclasses); - break; - } - - case TOKstruct: - if (id) - a = new StructDeclaration(loc, id); - else - anon = 1; - break; - - case TOKunion: - if (id) - a = new UnionDeclaration(loc, id); - else - anon = 2; - break; - - default: - assert(0); - break; - } - if (a && token.value == TOKsemicolon) - { nextToken(); - } - else if (token.value == TOKlcurly) - { - //printf("aggregate definition\n"); - nextToken(); - Array *decl = parseDeclDefs(0); - if (token.value != TOKrcurly) - error("struct member expected"); - nextToken(); - if (anon) - { - /* Anonymous structs/unions are more like attributes. - */ - return new AnonDeclaration(anon - 1, decl); - } - else - a->members = decl; - } - else - { - error("{ } expected following aggregate declaration"); - a = new StructDeclaration(loc, NULL); - } - - if (tpl) - { Array *decldefs; - TemplateDeclaration *tempdecl; - - // Wrap a template around the aggregate declaration - decldefs = new Array(); - decldefs->push(a); - tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs); - return tempdecl; - } - - return a; -} - -/************************************** - * Parse a TemplateDeclaration. - */ - -TemplateDeclaration *Parser::parseTemplateDeclaration() -{ - TemplateDeclaration *tempdecl; - Identifier *id; - Array *tpl; - Array *decldefs; - Loc loc = this->loc; - - nextToken(); - if (token.value != TOKidentifier) - { error("TemplateIdentifier expected following template"); - goto Lerr; - } - id = token.ident; - nextToken(); - tpl = parseTemplateParameterList(); - if (!tpl) - goto Lerr; - - if (token.value != TOKlcurly) - { error("members of template declaration expected"); - goto Lerr; - } - else - { - nextToken(); - decldefs = parseDeclDefs(0); - if (token.value != TOKrcurly) - { error("template member expected"); - goto Lerr; - } - nextToken(); - } - - tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs); - return tempdecl; - -Lerr: - return NULL; -} - -/****************************************** - * Parse template parameter list. - */ - -Array *Parser::parseTemplateParameterList() -{ - Array *tpl; - - if (token.value != TOKlparen) - { error("parenthesized TemplateParameterList expected following TemplateIdentifier"); - goto Lerr; - } - tpl = new Array(); - nextToken(); - - // Get TemplateParameterList - if (token.value != TOKrparen) - { - while (1) - { TemplateParameter *tp; - Identifier *tp_ident = NULL; - Type *tp_spectype = NULL; - Type *tp_valtype = NULL; - Type *tp_defaulttype = NULL; - Expression *tp_specvalue = NULL; - Expression *tp_defaultvalue = NULL; - Token *t; - - // Get TemplateParameter - - // First, look ahead to see if it is a TypeParameter or a ValueParameter - t = peek(&token); - if (token.value == TOKalias) - { // AliasParameter - nextToken(); - if (token.value != TOKidentifier) - { error("Identifier expected for template parameter"); - goto Lerr; - } - tp_ident = token.ident; - nextToken(); - if (token.value == TOKcolon) // : Type - { - nextToken(); - tp_spectype = parseBasicType(); - tp_spectype = parseDeclarator(tp_spectype, NULL); - } - if (token.value == TOKassign) // = Type - { - nextToken(); - tp_defaulttype = parseBasicType(); - tp_defaulttype = parseDeclarator(tp_defaulttype, NULL); - } - tp = new TemplateAliasParameter(loc, tp_ident, tp_spectype, tp_defaulttype); - } - else if (t->value == TOKcolon || t->value == TOKassign || - t->value == TOKcomma || t->value == TOKrparen) - { // TypeParameter - if (token.value != TOKidentifier) - { error("Identifier expected for template parameter"); - goto Lerr; - } - tp_ident = token.ident; - nextToken(); - if (token.value == TOKcolon) // : Type - { - nextToken(); - tp_spectype = parseBasicType(); - tp_spectype = parseDeclarator(tp_spectype, NULL); - } - if (token.value == TOKassign) // = Type - { - nextToken(); - tp_defaulttype = parseBasicType(); - tp_defaulttype = parseDeclarator(tp_defaulttype, NULL); - } - tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype); - } - else - { // ValueParameter - tp_valtype = parseBasicType(); - tp_valtype = parseDeclarator(tp_valtype, &tp_ident); - if (!tp_ident) - { - error("no identifier for template value parameter"); - goto Lerr; - } - if (token.value == TOKcolon) // : CondExpression - { - nextToken(); - tp_specvalue = parseCondExp(); - } - if (token.value == TOKassign) // = CondExpression - { - nextToken(); - tp_defaultvalue = parseCondExp(); - } - tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue); - } - tpl->push(tp); - if (token.value != TOKcomma) - break; - nextToken(); - } - } - check(TOKrparen); - return tpl; - -Lerr: - return NULL; -} - -/************************************** - * Parse a TemplateInstance. - */ - -TemplateInstance *Parser::parseTemplateInstance() -{ - TemplateInstance *tempinst; - Identifier *id; - - //printf("parseTemplateInstance()\n"); - nextToken(); - if (token.value == TOKdot) - { - id = Id::empty; - } - else if (token.value == TOKidentifier) - { id = token.ident; - nextToken(); - } - else - { error("TemplateIdentifier expected following instance"); - goto Lerr; - } - tempinst = new TemplateInstance(loc, id); - while (token.value == TOKdot) - { nextToken(); - if (token.value == TOKidentifier) - tempinst->addIdent(token.ident); - else - { error("identifier expected following '.' instead of '%s'", token.toChars()); - goto Lerr; - } - nextToken(); - } - tempinst->tiargs = parseTemplateArgumentList(); - - if (!global.params.useDeprecated) - error("instance is deprecated, use %s", tempinst->toChars()); - return tempinst; - -Lerr: - return NULL; -} - -/****************************************** - * Parse template mixin. - * mixin Foo; - * mixin Foo!(args); - * mixin a.b.c!(args).Foo!(args); - * mixin Foo!(args) identifier; - */ - -Dsymbol *Parser::parseMixin() -{ - TemplateMixin *tm; - Identifier *id; - TypeTypeof *tqual; - Array *tiargs; - Array *idents; - - //printf("parseMixin()\n"); - nextToken(); - - tqual = NULL; - if (token.value == TOKdot) - { - id = Id::empty; - } - else - { - if (token.value == TOKtypeof) - { Expression *exp; - - nextToken(); - check(TOKlparen); - exp = parseExpression(); - check(TOKrparen); - tqual = new TypeTypeof(loc, exp); - check(TOKdot); - } - if (token.value != TOKidentifier) - { - error("identifier expected, not %s", token.toChars()); - goto Lerr; - } - id = token.ident; - nextToken(); - } - - idents = new Array(); - while (1) - { - tiargs = NULL; - if (token.value == TOKnot) - { - nextToken(); - tiargs = parseTemplateArgumentList(); - } - - if (token.value != TOKdot) - break; - - if (tiargs) - { TemplateInstance *tempinst = new TemplateInstance(loc, id); - tempinst->tiargs = tiargs; - id = (Identifier *)tempinst; - tiargs = NULL; - } - idents->push(id); - - nextToken(); - if (token.value != TOKidentifier) - { error("identifier expected following '.' instead of '%s'", token.toChars()); - break; - } - id = token.ident; - nextToken(); - } - idents->push(id); - - if (token.value == TOKidentifier) - { - id = token.ident; - nextToken(); - } - else - id = NULL; - - tm = new TemplateMixin(loc, id, tqual, idents, tiargs); - if (token.value != TOKsemicolon) - error("';' expected after mixin"); - nextToken(); - - return tm; - -Lerr: - return NULL; -} - -/****************************************** - * Parse template argument list. - * Input: - * current token is opening '(' - * Output: - * current token is one after closing ')' - */ - -Array *Parser::parseTemplateArgumentList() -{ - Array *tiargs = new Array(); - if (token.value != TOKlparen) - { error("!(TemplateArgumentList) expected following TemplateIdentifier"); - return tiargs; - } - nextToken(); - - // Get TemplateArgumentList - if (token.value != TOKrparen) - { - while (1) - { - // See if it is an Expression or a Type - if (isDeclaration(&token, 0, TOKreserved, NULL)) - { // Type - Type *ta; - - // Get TemplateArgument - ta = parseBasicType(); - ta = parseDeclarator(ta, NULL); - tiargs->push(ta); - } - else - { // Expression - Expression *ea; - - ea = parseAssignExp(); - tiargs->push(ea); - } - if (token.value != TOKcomma) - break; - nextToken(); - } - } - check(TOKrparen, "template argument list"); - return tiargs; -} - -Import *Parser::parseImport(Array *decldefs) -{ Import *s; - Identifier *id; - Array *a; - Loc loc; - - //printf("Parser::parseImport()\n"); - do - { - nextToken(); - if (token.value != TOKidentifier) - { error("Identifier expected following import"); - break; - } - - loc = this->loc; - a = NULL; - id = token.ident; - while (nextToken() == TOKdot) - { - if (!a) - a = new Array(); - a->push(id); - nextToken(); - if (token.value != TOKidentifier) - { error("Identifier expected following package"); - break; - } - id = token.ident; - } - - s = new Import(loc, a, token.ident); - decldefs->push(s); - } while (token.value == TOKcomma); - - if (token.value == TOKsemicolon) - nextToken(); - else - { - error("';' expected"); - nextToken(); - } - - return NULL; -} - -Type *Parser::parseBasicType() -{ Type *t; - Identifier *id; - TypeQualified *tid; - TemplateInstance *tempinst; - - //printf("parseBasicType()\n"); - switch (token.value) - { - CASE_BASIC_TYPES_X(t): - nextToken(); - break; - - case TOKidentifier: - id = token.ident; - nextToken(); - if (token.value == TOKnot) - { - nextToken(); - tempinst = new TemplateInstance(loc, id); - tempinst->tiargs = parseTemplateArgumentList(); - tid = new TypeInstance(loc, tempinst); - goto Lident2; - } - Lident: - tid = new TypeIdentifier(loc, id); - Lident2: - while (token.value == TOKdot) - { nextToken(); - if (token.value != TOKidentifier) - { error("identifier expected following '.' instead of '%s'", token.toChars()); - break; - } - id = token.ident; - nextToken(); - if (token.value == TOKnot) - { - nextToken(); - tempinst = new TemplateInstance(loc, id); - tempinst->tiargs = parseTemplateArgumentList(); - tid->addIdent((Identifier *)tempinst); - } - else - tid->addIdent(id); - } - t = tid; - break; - - case TOKdot: - id = Id::empty; - goto Lident; - - case TOKinstance: - { // Deprecated - tempinst = parseTemplateInstance(); - if (!tempinst) // if error - { t = Type::tvoid; - break; - } - - tid = new TypeInstance(loc, tempinst); - goto Lident2; - } - - case TOKtypeof: - { Expression *exp; - - nextToken(); - check(TOKlparen); - exp = parseExpression(); - check(TOKrparen); - tid = new TypeTypeof(loc, exp); - goto Lident2; - } - - default: - error("basic type expected, not %s", token.toChars()); - t = Type::tint32; - break; - } - return t; -} - -Type *Parser::parseBasicType2(Type *t) -{ Expression *e; - Type *ts; - Type *ta; - - //printf("parseBasicType2()\n"); - while (1) - { - switch (token.value) - { - case TOKmul: - t = new TypePointer(t); - nextToken(); - continue; - -#if REFERENCES - case TOKand: - t = new TypeReference(t); - nextToken(); - continue; -#endif - case TOKlbracket: -#if LTORARRAYDECL - // Handle []. Make sure things like - // int[3][1] a; - // is (array[1] of array[3] of int) - nextToken(); - if (token.value == TOKrbracket) - { - t = new TypeDArray(t); // [] - nextToken(); - } - else if (isDeclaration(&token, 0, TOKrbracket, NULL)) - { // It's an associative array declaration - Type *index; - - //printf("it's an associative array\n"); - index = parseBasicType(); - index = parseDeclarator(index, NULL); // [ type ] - t = new TypeAArray(t, index); - check(TOKrbracket); - } - else - { - //printf("it's [expression]\n"); - e = parseExpression(); // [ expression ] - t = new TypeSArray(t,e); - check(TOKrbracket); - } - continue; -#else - // Handle []. Make sure things like - // int[3][1] a; - // is (array[3] of array[1] of int) - ts = t; - while (token.value == TOKlbracket) - { - nextToken(); - if (token.value == TOKrbracket) - { - ta = new TypeDArray(t); // [] - nextToken(); - } - else if (isDeclaration(&token, 0, TOKrbracket, NULL)) - { // It's an associative array declaration - Type *index; - - //printf("it's an associative array\n"); - index = parseBasicType(); - index = parseDeclarator(index, NULL); // [ type ] - check(TOKrbracket); - ta = new TypeAArray(t, index); - } - else - { - //printf("it's [expression]\n"); - e = parseExpression(); // [ expression ] - ta = new TypeSArray(t,e); - check(TOKrbracket); - } - Type **pt; - for (pt = &ts; *pt != t; pt = &(*pt)->next) - ; - *pt = ta; - } - t = ts; - continue; -#endif - - case TOKdelegate: - case TOKfunction: - { // Handle delegate declaration: - // t delegate(parameter list) - // t function(parameter list) - Array *arguments; - int varargs; - enum TOK save = token.value; - - nextToken(); - arguments = parseParameters(&varargs); - t = new TypeFunction(arguments, t, varargs, linkage); - if (save == TOKdelegate) - t = new TypeDelegate(t); - else - t = new TypePointer(t); // pointer to function - continue; - } - - default: - ts = t; - break; - } - break; - } - return ts; -} - -Type *Parser::parseDeclarator(Type *t, Identifier **pident) -{ Expression *e; - Type *ts; - Type *ta; - Type **pt; - - //printf("parseDeclarator(t = %p)\n", t); - while (1) - { - switch (token.value) - { - case TOKmul: - t = new TypePointer(t); - nextToken(); - continue; - -#if REFERENCES - case TOKand: - t = new TypeReference(t); - nextToken(); - continue; -#endif - - case TOKlbracket: -#if LTORARRAYDECL - // Handle []. Make sure things like - // int[3][1] a; - // is (array[1] of array[3] of int) - nextToken(); - if (token.value == TOKrbracket) - { - t = new TypeDArray(t); // [] - nextToken(); - } - else if (isDeclaration(&token, 0, TOKrbracket, NULL)) - { // It's an associative array declaration - Type *index; - - //printf("it's an associative array\n"); - index = parseBasicType(); - index = parseDeclarator(index, NULL); // [ type ] - t = new TypeAArray(t, index); - check(TOKrbracket); - } - else - { - //printf("it's [expression]\n"); - e = parseExpression(); // [ expression ] - t = new TypeSArray(t,e); - check(TOKrbracket); - } - continue; -#else - // Handle []. Make sure things like - // int[3][1] a; - // is (array[3] of array[1] of int) - ts = t; - while (token.value == TOKlbracket) - { - nextToken(); - if (token.value == TOKrbracket) - { - ta = new TypeDArray(t); // [] - nextToken(); - } - else if (isDeclaration(&token, 0, TOKrbracket, NULL)) - { // It's an associative array declaration - Type *index; - - //printf("it's an associative array\n"); - index = parseBasicType(); - index = parseDeclarator(index, NULL); // [ type ] - check(TOKrbracket); - ta = new TypeAArray(t, index); - } - else - { - //printf("it's [expression]\n"); - e = parseExpression(); // [ expression ] - ta = new TypeSArray(t,e); - check(TOKrbracket); - } - for (pt = &ts; *pt != t; pt = &(*pt)->next) - ; - *pt = ta; - } - t = ts; - continue; -#endif - - case TOKidentifier: - if (pident) - *pident = token.ident; - else - error("unexpected identifer '%s' in declarator", token.ident->toChars()); - ts = t; - nextToken(); - break; - - case TOKlparen: - nextToken(); - ts = parseDeclarator(t, pident); - check(TOKrparen); - break; - - case TOKdelegate: - case TOKfunction: - { // Handle delegate declaration: - // t delegate(parameter list) - // t function(parameter list) - Array *arguments; - int varargs; - enum TOK save = token.value; - - nextToken(); - arguments = parseParameters(&varargs); - t = new TypeFunction(arguments, t, varargs, linkage); - if (save == TOKdelegate) - t = new TypeDelegate(t); - else - t = new TypePointer(t); // pointer to function - continue; - } - default: - ts = t; - break; - } - break; - } - - while (1) - { - switch (token.value) - { -#if CARRAYDECL - case TOKlbracket: - // This is the old C-style post [] syntax. - // Should we disallow it? - nextToken(); - if (token.value == TOKrbracket) - { - ta = new TypeDArray(t); // [] - nextToken(); - } - else if (isDeclaration(&token, 0, TOKrbracket, NULL)) - { // It's an associative array declaration - Type *index; - - //printf("it's an associative array\n"); - index = parseBasicType(); - index = parseDeclarator(index, NULL); // [ type ] - check(TOKrbracket); - ta = new TypeAArray(t, index); - } - else - { - //printf("it's [expression]\n"); - e = parseExpression(); // [ expression ] - ta = new TypeSArray(t,e); - check(TOKrbracket); - } - for (pt = &ts; *pt != t; pt = &(*pt)->next) - ; - *pt = ta; - continue; -#endif - case TOKlparen: - { Array *arguments; - int varargs; - - arguments = parseParameters(&varargs); - ta = new TypeFunction(arguments, t, varargs, linkage); - for (pt = &ts; *pt != t; pt = &(*pt)->next) - ; - *pt = ta; - continue; - } - } - break; - } - - return ts; -} - -/********************************** - * Return array of Declaration *'s. - */ - -Array *Parser::parseDeclaration() -{ - enum STC storage_class; - enum STC sc; - Type *ts; - Type *t; - Type *tfirst; - Identifier *ident; - Array *a; - enum TOK tok; - - //printf("parseDeclaration()\n"); - switch (token.value) - { - case TOKtypedef: - case TOKalias: - tok = token.value; - nextToken(); - break; - - default: - tok = TOKreserved; - break; - } - - storage_class = STCundefined; - while (1) - { - switch (token.value) - { - case TOKconst: sc = STCconst; goto L1; - case TOKstatic: sc = STCstatic; goto L1; - case TOKfinal: sc = STCfinal; goto L1; - case TOKauto: sc = STCauto; goto L1; - case TOKoverride: sc = STCoverride; goto L1; - case TOKabstract: sc = STCabstract; goto L1; - case TOKsynchronized: sc = STCsynchronized; goto L1; - case TOKdeprecated: sc = STCdeprecated; goto L1; - L1: - if (storage_class & sc) - error("redundant storage class '%s'", token.toChars()); - storage_class = (STC) (storage_class | sc); - nextToken(); - continue; - } - break; - } - - a = new Array(); - ts = parseBasicType(); - ts = parseBasicType2(ts); - tfirst = NULL; - - while (1) - { - Loc loc = this->loc; - - ident = NULL; - t = parseDeclarator(ts,&ident); - assert(t); - if (!tfirst) - tfirst = t; - else if (t != tfirst) - error("multiple declarations must have the same type, not %s and %s", - tfirst->toChars(), t->toChars()); - if (!ident) - error("no identifier for declarator %s", t->toChars()); - - if (tok == TOKtypedef || tok == TOKalias) - { Declaration *v; - Initializer *init; - - init = NULL; - if (token.value == TOKassign) - { - nextToken(); - init = parseInitializer(); - } - if (tok == TOKtypedef) - v = new TypedefDeclaration(ident, t, init); - else - { if (init) - error("alias cannot have initializer"); - v = new AliasDeclaration(loc, ident, t); - } - v->storage_class = storage_class; - a->push(v); - switch (token.value) - { case TOKsemicolon: - nextToken(); - break; - - case TOKcomma: - nextToken(); - continue; - - default: - error("semicolon expected to close %s declaration", Token::toChars(tok)); - break; - } - } - else if (t->ty == Tfunction) - { FuncDeclaration *f; - - f = new FuncDeclaration(loc, 0, ident, storage_class, t); - a->push(f); - parseContracts(f); - } - else - { VarDeclaration *v; - Initializer *init; - - init = NULL; - if (token.value == TOKassign) - { - nextToken(); - init = parseInitializer(); - } - v = new VarDeclaration(loc, t, ident, init); - v->storage_class = storage_class; - a->push(v); - switch (token.value) - { case TOKsemicolon: - nextToken(); - break; - - case TOKcomma: - nextToken(); - continue; - - default: - error("semicolon expected, not '%s'", token.toChars()); - break; - } - } - break; - } - return a; -} - -/***************************************** - * Parse contracts following function declaration. - */ - -void Parser::parseContracts(FuncDeclaration *f) -{ - Type *tb; - enum LINK linksave = linkage; - - // The following is irrelevant, as it is overridden by sc->linkage in - // TypeFunction::semantic - linkage = LINKd; // nested functions have D linkage -L1: - switch (token.value) - { - case TOKlcurly: - if (f->frequire || f->fensure) - error("missing body { ... } after in or out"); - f->fbody = parseStatement(PSsemi); - f->endloc = endloc; - break; - - case TOKbody: - nextToken(); - f->fbody = parseStatement(PScurly); - f->endloc = endloc; - break; - - case TOKsemicolon: - if (f->frequire || f->fensure) - error("missing body { ... } after in or out"); - nextToken(); - break; - -#if 0 // Do we want this for function declarations, so we can do: - // int x, y, foo(), z; - case TOKcomma: - nextToken(); - continue; -#endif - -#if 0 // Dumped feature - case TOKthrow: - if (!f->fthrows) - f->fthrows = new Array(); - nextToken(); - check(TOKlparen); - while (1) - { - tb = parseBasicType(); - f->fthrows->push(tb); - if (token.value == TOKcomma) - { nextToken(); - continue; - } - break; - } - check(TOKrparen); - goto L1; -#endif - - case TOKin: - nextToken(); - if (f->frequire) - error("redundant 'in' statement"); - f->frequire = parseStatement(PScurly | PSscope); - goto L1; - - case TOKout: - // parse: out (identifier) { statement } - nextToken(); - if (token.value != TOKlcurly) - { - check(TOKlparen); - if (token.value != TOKidentifier) - error("(identifier) following 'out' expected, not %s", token.toChars()); - f->outId = token.ident; - nextToken(); - check(TOKrparen); - } - if (f->fensure) - error("redundant 'out' statement"); - f->fensure = parseStatement(PScurly | PSscope); - goto L1; - - default: - error("semicolon expected following function declaration"); - break; - } - linkage = linksave; -} - -/***************************************** - */ - -Initializer *Parser::parseInitializer() -{ - StructInitializer *is; - ArrayInitializer *ia; - ExpInitializer *ie; - Expression *e; - Identifier *id; - Initializer *value; - int comma; - Loc loc = this->loc; - Token *t; - - switch (token.value) - { - case TOKlcurly: - is = new StructInitializer(loc); - nextToken(); - comma = 0; - while (1) - { - switch (token.value) - { - case TOKidentifier: - if (comma == 1) - error("comma expected separating field initializers"); - t = peek(&token); - if (t->value == TOKcolon) - { - id = token.ident; - nextToken(); - nextToken(); // skip over ':' - } - else - { id = NULL; - } - value = parseInitializer(); - is->addInit(id, value); - comma = 1; - continue; - - case TOKcomma: - nextToken(); - comma = 2; - continue; - - case TOKrcurly: // allow trailing comma's - nextToken(); - break; - - default: - value = parseInitializer(); - is->addInit(NULL, value); - comma = 1; - continue; - //error("found '%s' instead of field initializer", token.toChars()); - //break; - } - break; - } - return is; - - case TOKlbracket: - ia = new ArrayInitializer(loc); - nextToken(); - comma = 0; - while (1) - { - switch (token.value) - { - default: - if (comma == 1) - { error("comma expected separating array initializers, not %s", token.toChars()); - nextToken(); - break; - } - e = parseAssignExp(); - if (!e) - break; - if (token.value == TOKcolon) - { - nextToken(); - value = parseInitializer(); - } - else - { value = new ExpInitializer(e->loc, e); - e = NULL; - } - ia->addInit(e, value); - comma = 1; - continue; - - case TOKlcurly: - case TOKlbracket: - if (comma == 1) - error("comma expected separating array initializers, not %s", token.toChars()); - value = parseInitializer(); - ia->addInit(NULL, value); - comma = 1; - continue; - - case TOKcomma: - nextToken(); - comma = 2; - continue; - - case TOKrbracket: // allow trailing comma's - nextToken(); - break; - - case TOKeof: - error("found '%s' instead of array initializer", token.toChars()); - break; - } - break; - } - return ia; - - default: - e = parseAssignExp(); - ie = new ExpInitializer(loc, e); - return ie; - } -} - - -/***************************************** - * Input: - * flags PSxxxx - */ - -Statement *Parser::parseStatement(int flags) -{ Statement *s; - Token *t; - Loc loc = this->loc; - - //printf("parseStatement()\n"); - - if (flags & PScurly && token.value != TOKlcurly) - error("statement expected to be { }, not %s", token.toChars()); - - switch (token.value) - { - case TOKidentifier: - // Need to look ahead to see if it is a declaration, label, or expression - t = peek(&token); - if (t->value == TOKcolon) - { // It's a label - Identifier *ident; - - ident = token.ident; - nextToken(); - nextToken(); - s = parseStatement(PSsemi); - s = new LabelStatement(loc, ident, s); - break; - } - // fallthrough to TOKdot - case TOKdot: - case TOKtypeof: - if (isDeclaration(&token, 2, TOKreserved, NULL)) - goto Ldeclaration; - else - goto Lexp; - break; - - case TOKassert: - case TOKthis: - case TOKsuper: - case TOKint32v: - case TOKuns32v: - case TOKint64v: - case TOKuns64v: - case TOKfloat32v: - case TOKfloat64v: - case TOKfloat80v: - case TOKimaginary32v: - case TOKimaginary64v: - case TOKimaginary80v: - case TOKcharv: - case TOKwcharv: - case TOKdcharv: - case TOKnull: - case TOKtrue: - case TOKfalse: - case TOKstring: - case TOKlparen: -#if DCASTSYNTAX - case TOKcast: -#endif - case TOKmul: - case TOKmin: - case TOKadd: - case TOKplusplus: - case TOKminusminus: - case TOKnew: - case TOKdelete: - case TOKdelegate: - case TOKfunction: - case TOKtypeid: - Lexp: - { Expression *exp; - - exp = parseExpression(); - check(TOKsemicolon, "statement"); - s = new ExpStatement(loc, exp); - break; - } - - case TOKinstance: // Deprecated - /* Three cases: - * 1) Declaration - * 2) Template Instance Alias - * 3) Expression - */ - if (isDeclaration(&token, 2, TOKreserved, NULL)) - { - //printf("it's a declaration\n"); - goto Ldeclaration; - } - else - { - if (isTemplateInstance(&token, &t) && t->value == TOKidentifier) - { // case 2 - TemplateInstance *ti; - AliasDeclaration *a; - - ti = parseTemplateInstance(); - assert(ti); - assert(token.value == TOKidentifier); - - a = new AliasDeclaration(loc, token.ident, ti); - s = new DeclarationStatement(loc, a); - nextToken(); - if (token.value != TOKsemicolon) - error("';' expected after template instance, not %s", token.toChars()); - } - else - goto Lexp; // case 3 - } - break; - - case TOKstatic: - { // Look ahead to see if it's static assert() - Token *t; - - t = peek(&token); - if (t->value == TOKassert) - { - nextToken(); - s = new StaticAssertStatement(parseStaticAssert()); - break; - } - goto Ldeclaration; - } - - CASE_BASIC_TYPES: - case TOKtypedef: - case TOKalias: - case TOKconst: - case TOKauto: -// case TOKtypeof: - Ldeclaration: - { Array *a; - - a = parseDeclaration(); - if (a->dim > 1) - { - Array *as = new Array(); - as->reserve(a->dim); - for (int i = 0; i < a->dim; i++) - { - Dsymbol *d = (Dsymbol *)a->data[i]; - s = new DeclarationStatement(loc, d); - as->push(s); - } - s = new CompoundStatement(loc, as); - } - else if (a->dim == 1) - { - Dsymbol *d = (Dsymbol *)a->data[0]; - s = new DeclarationStatement(loc, d); - } - else - assert(0); - if (flags & PSscope) - s = new ScopeStatement(loc, s); - break; - } - - case TOKstruct: - case TOKunion: - case TOKclass: - case TOKinterface: - { Dsymbol *d; - - d = parseAggregate(); - s = new DeclarationStatement(loc, d); - break; - } - - case TOKenum: - { Dsymbol *d; - - d = parseEnum(); - s = new DeclarationStatement(loc, d); - break; - } - - case TOKmixin: - { Dsymbol *d; - - d = parseMixin(); - s = new DeclarationStatement(loc, d); - break; - } - - case TOKlcurly: - { Array *statements; - - nextToken(); - statements = new Array(); - while (token.value != TOKrcurly) - { - statements->push(parseStatement(PSsemi | PScurlyscope)); - } - endloc = this->loc; - s = new CompoundStatement(loc, statements); - if (flags & (PSscope | PScurlyscope)) - s = new ScopeStatement(loc, s); - nextToken(); - break; - } - - case TOKwhile: - { Expression *condition; - Statement *body; - - nextToken(); - check(TOKlparen); - condition = parseExpression(); - check(TOKrparen); - body = parseStatement(PSscope); - s = new WhileStatement(loc, condition, body); - break; - } - - case TOKsemicolon: - if (!(flags & PSsemi)) - error("use '{ }' for an empty statement, not a ';'"); - nextToken(); - s = new ExpStatement(loc, NULL); - break; - - case TOKdo: - { Statement *body; - Expression *condition; - - nextToken(); - body = parseStatement(PSscope); - check(TOKwhile); - check(TOKlparen); - condition = parseExpression(); - check(TOKrparen); - s = new DoStatement(loc, body, condition); - break; - } - - case TOKfor: - { - Statement *init; - Expression *condition; - Expression *increment; - Statement *body; - - nextToken(); - check(TOKlparen); - if (token.value == TOKsemicolon) - { init = NULL; - nextToken(); - } - else - { init = parseStatement(0); - } - if (token.value == TOKsemicolon) - { - condition = NULL; - nextToken(); - } - else - { - condition = parseExpression(); - check(TOKsemicolon, "for condition"); - } - if (token.value == TOKrparen) - { increment = NULL; - nextToken(); - } - else - { increment = parseExpression(); - check(TOKrparen); - } - body = parseStatement(0); - s = new ForStatement(loc, init, condition, increment, body); - break; - } - - case TOKforeach: - { - Array *arguments; - - Statement *d; - Statement *body; - Expression *aggr; - - nextToken(); - check(TOKlparen); - - arguments = new Array(); - - while (1) - { - Type *tb; - Identifier *ai = NULL; - Type *at; - enum InOut inout; - Argument *a; - - inout = In; - if (token.value == TOKinout) - { inout = InOut; - nextToken(); - } - tb = parseBasicType(); - at = parseDeclarator(tb, &ai); - if (!ai) - error("no identifier for declarator %s", at->toChars()); - a = new Argument(inout, at, ai, NULL); - arguments->push(a); - if (token.value == TOKcomma) - { nextToken(); - continue; - } - break; - } - check(TOKsemicolon); - - aggr = parseExpression(); - check(TOKrparen); - body = parseStatement(0); - s = new ForeachStatement(loc, arguments, aggr, body); - break; - } - - case TOKif: - { Expression *condition; - Statement *ifbody; - Statement *elsebody; - - nextToken(); - check(TOKlparen); - condition = parseExpression(); - check(TOKrparen); - ifbody = parseStatement(PSscope); - if (token.value == TOKelse) - { - nextToken(); - elsebody = parseStatement(PSscope); - } - else - elsebody = NULL; - s = new IfStatement(loc, condition, ifbody, elsebody); - break; - } - - case TOKdebug: - { Condition *condition; - Statement *ifbody; - Statement *elsebody; - - nextToken(); - if (token.value == TOKlparen) - { - nextToken(); - condition = parseDebugCondition(); - check(TOKrparen); - } - else - condition = new DebugCondition(mod, 1, NULL); - ifbody = parseStatement(PSsemi); - if (token.value == TOKelse) - { - nextToken(); - elsebody = parseStatement(PSsemi); - } - else - elsebody = NULL; - s = new ConditionalStatement(loc, condition, ifbody, elsebody); - break; - } - - case TOKversion: - { Condition *condition; - Statement *ifbody; - Statement *elsebody; - - nextToken(); - if (token.value == TOKlparen) - { - nextToken(); - condition = parseVersionCondition(); - check(TOKrparen); - } - else - { error("(condition) expected after version"); - condition = NULL; - } - ifbody = parseStatement(PSsemi); - if (token.value == TOKelse) - { - nextToken(); - elsebody = parseStatement(PSsemi); - } - else - elsebody = NULL; - s = new ConditionalStatement(loc, condition, ifbody, elsebody); - break; - } - - case TOKpragma: - { Identifier *ident; - Array *args = NULL; - Statement *body; - - nextToken(); - check(TOKlparen); - if (token.value != TOKidentifier) - { error("pragma(identifier expected"); - goto Lerror; - } - ident = token.ident; - nextToken(); - if (token.value == TOKcomma) - args = parseArguments(); // pragma(identifier, args...); - else - check(TOKrparen); // pragma(identifier); - body = parseStatement(PSsemi); - s = new PragmaStatement(loc, ident, args, body); - break; - } - - case TOKswitch: - { Expression *condition; - Statement *body; - - nextToken(); - check(TOKlparen); - condition = parseExpression(); - check(TOKrparen); - body = parseStatement(PSscope); - s = new SwitchStatement(loc, condition, body); - break; - } - - case TOKcase: - { Expression *exp; - Array *statements; - Array cases; // array of Expression's - - while (1) - { - nextToken(); - exp = parseAssignExp(); - cases.push(exp); - if (token.value != TOKcomma) - break; - } - check(TOKcolon); - - statements = new Array(); - while (token.value != TOKcase && - token.value != TOKdefault && - token.value != TOKrcurly) - { - statements->push(parseStatement(PSsemi | PScurlyscope)); - } - s = new CompoundStatement(loc, statements); - s = new ScopeStatement(loc, s); - - // Keep cases in order by building the case statements backwards - for (int i = cases.dim; i; i--) - { - exp = (Expression *)cases.data[i - 1]; - s = new CaseStatement(loc, exp, s); - } - break; - } - - case TOKdefault: - { - Array *statements; - - nextToken(); - check(TOKcolon); - - statements = new Array(); - while (token.value != TOKcase && - token.value != TOKdefault && - token.value != TOKrcurly) - { - statements->push(parseStatement(PSsemi | PScurlyscope)); - } - s = new CompoundStatement(loc, statements); - s = new ScopeStatement(loc, s); - s = new DefaultStatement(loc, s); - break; - } - - case TOKreturn: - { Expression *exp; - - nextToken(); - if (token.value == TOKsemicolon) - exp = NULL; - else - exp = parseExpression(); - check(TOKsemicolon, "return statement"); - s = new ReturnStatement(loc, exp); - break; - } - - case TOKbreak: - { Identifier *ident; - - nextToken(); - if (token.value == TOKidentifier) - { ident = token.ident; - nextToken(); - } - else - ident = NULL; - check(TOKsemicolon, "break statement"); - s = new BreakStatement(loc, ident); - break; - } - - case TOKcontinue: - { Identifier *ident; - - nextToken(); - if (token.value == TOKidentifier) - { ident = token.ident; - nextToken(); - } - else - ident = NULL; - check(TOKsemicolon, "continue statement"); - s = new ContinueStatement(loc, ident); - break; - } - - case TOKgoto: - { Identifier *ident; - - nextToken(); - if (token.value == TOKdefault) - { - nextToken(); - s = new GotoDefaultStatement(loc); - } - else if (token.value == TOKcase) - { - Expression *exp = NULL; - - nextToken(); - if (token.value != TOKsemicolon) - exp = parseExpression(); - s = new GotoCaseStatement(loc, exp); - } - else - { - if (token.value != TOKidentifier) - { error("Identifier expected following goto"); - ident = NULL; - } - else - { ident = token.ident; - nextToken(); - } - s = new GotoStatement(loc, ident); - } - check(TOKsemicolon, "goto statement"); - break; - } - - case TOKsynchronized: - { Expression *exp; - Statement *body; - - nextToken(); - if (token.value == TOKlparen) - { - nextToken(); - exp = parseExpression(); - check(TOKrparen); - } - else - exp = NULL; - body = parseStatement(PSscope); - s = new SynchronizedStatement(loc, exp, body); - break; - } - - case TOKwith: - { Expression *exp; - Statement *body; - - nextToken(); - check(TOKlparen); - exp = parseExpression(); - check(TOKrparen); - body = parseStatement(PSscope); - s = new WithStatement(loc, exp, body); - break; - } - - case TOKtry: - { Statement *body; - Array *catches = NULL; - Statement *finalbody = NULL; - - nextToken(); - body = parseStatement(PSscope); - while (token.value == TOKcatch) - { - Statement *handler; - Catch *c; - Type *t; - Identifier *id; - Loc loc = this->loc; - - nextToken(); - if (token.value == TOKlcurly) - { - t = NULL; - id = NULL; - } - else - { - check(TOKlparen); - t = parseBasicType(); - id = NULL; - t = parseDeclarator(t, &id); - check(TOKrparen); - } - handler = parseStatement(0); - c = new Catch(loc, t, id, handler); - if (!catches) - catches = new Array(); - catches->push(c); - } - - if (token.value == TOKfinally) - { nextToken(); - finalbody = parseStatement(0); - } - - s = body; - if (!catches && !finalbody) - error("catch or finally expected following try"); - else - { if (catches) - s = new TryCatchStatement(loc, body, catches); - if (finalbody) - s = new TryFinallyStatement(loc, s, finalbody); - } - break; - } - - case TOKthrow: - { Expression *exp; - - nextToken(); - exp = parseExpression(); - check(TOKsemicolon, "throw statement"); - s = new ThrowStatement(loc, exp); - break; - } - - case TOKvolatile: - nextToken(); - s = parseStatement(PSsemi | PSscope); - s = new VolatileStatement(loc, s); - break; - - case TOKasm: - { Array *statements; - Identifier *label; - Loc labelloc; - Token *toklist; - Token **ptoklist; - - // Parse the asm block into a sequence of AsmStatements, - // each AsmStatement is one instruction. - // Separate out labels. - // Defer parsing of AsmStatements until semantic processing. - - nextToken(); - check(TOKlcurly); - toklist = NULL; - ptoklist = &toklist; - label = NULL; - statements = new Array(); - while (1) - { - switch (token.value) - { - case TOKidentifier: - if (!toklist) - { - // Look ahead to see if it is a label - t = peek(&token); - if (t->value == TOKcolon) - { // It's a label - label = token.ident; - labelloc = this->loc; - nextToken(); - nextToken(); - continue; - } - } - goto Ldefault; - - case TOKrcurly: - if (toklist || label) - { - error("asm statements must end in ';'"); - } - break; - - case TOKsemicolon: - s = NULL; - if (toklist || label) - { // Create AsmStatement from list of tokens we've saved - s = new AsmStatement(this->loc, toklist); - toklist = NULL; - ptoklist = &toklist; - if (label) - { s = new LabelStatement(labelloc, label, s); - label = NULL; - } - statements->push(s); - } - nextToken(); - continue; - - case TOKeof: - error("matching '}' expected, not end of file"); - break; - - default: - Ldefault: - *ptoklist = new Token(); - memcpy(*ptoklist, &token, sizeof(Token)); - ptoklist = &(*ptoklist)->next; - *ptoklist = NULL; - - nextToken(); - continue; - } - break; - } - s = new CompoundStatement(loc, statements); - nextToken(); - break; - } - - default: - error("found '%s' instead of statement", token.toChars()); - Lerror: - while (token.value != TOKsemicolon && token.value != TOKeof) - nextToken(); - nextToken(); - s = NULL; - break; - } - - return s; -} - -void Parser::check(enum TOK value) -{ - if (token.value != value) - error("found '%s' when expecting '%s'", token.toChars(), Token::toChars(value)); - nextToken(); -} - -void Parser::check(enum TOK value, char *string) -{ - if (token.value != value) - error("found '%s' when expecting '%s' following '%s'", - token.toChars(), Token::toChars(value), string); - nextToken(); -} - -/************************************ - * Determine if the scanner is sitting on the start of a declaration. - * Input: - * needId 0 no identifier - * 1 identifier optional - * 2 must have identifier - */ - -int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt) -{ - int haveId = 0; - - if (!isBasicType(&t)) - return FALSE; - if (!isDeclarator(&t, &haveId, endtok)) - return FALSE; - if ( needId == 1 || - (needId == 0 && !haveId) || - (needId == 2 && haveId)) - { if (pt) - *pt = t; - return TRUE; - } - else - return FALSE; -} - -int Parser::isBasicType(Token **pt) -{ - // This code parallels parseBasicType() - Token *t = *pt; - Token *t2; - int parens; - - switch (t->value) - { - CASE_BASIC_TYPES: - t = peek(t); - break; - - case TOKidentifier: - t = peek(t); - if (t->value == TOKnot) - { - goto L4; - } - goto L3; - while (1) - { - L2: - t = peek(t); - L3: - if (t->value == TOKdot) - { - Ldot: - t = peek(t); - if (t->value != TOKidentifier) - goto Lfalse; - t = peek(t); - if (t->value != TOKnot) - goto L3; - L4: - t = peek(t); - if (t->value != TOKlparen) - goto Lfalse; - if (!skipParens(t, &t)) - goto Lfalse; - } - else - break; - } - break; - - case TOKdot: - goto Ldot; - - case TOKinstance: // Deprecated - // Handle cases like: - // instance Foo(int).bar x; - // But remember that: - // instance Foo(int) x; - // is not a type, but is an AliasDeclaration declaration. - if (!isTemplateInstance(t, &t)) - goto Lfalse; // invalid syntax for template instance - if (t->value == TOKdot) - goto Ldot; - goto Lfalse; - - case TOKtypeof: - /* typeof(exp).identifier... - */ - t = peek(t); - if (t->value != TOKlparen) - goto Lfalse; - if (!skipParens(t, &t)) - goto Lfalse; - goto L2; - - default: - goto Lfalse; - } - *pt = t; - return TRUE; - -Lfalse: - return FALSE; -} - -int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) -{ // This code parallels parseDeclarator() - Token *t = *pt; - int parens; - - if (t->value == TOKassign) - return FALSE; - - while (1) - { - parens = FALSE; - switch (t->value) - { - case TOKmul: - case TOKand: - t = peek(t); - continue; - - case TOKlbracket: - t = peek(t); - if (t->value == TOKrbracket) - { - t = peek(t); - } - else if (isDeclaration(t, 0, TOKrbracket, &t)) - { // It's an associative array declaration - t = peek(t); - } - else - { - // [ expression ] - if (!isExpression(&t)) - return FALSE; - if (t->value != TOKrbracket) - return FALSE; - t = peek(t); - } - continue; - - case TOKidentifier: - if (*haveId) - return FALSE; - *haveId = TRUE; - t = peek(t); - break; - - case TOKlparen: - t = peek(t); - - if (t->value == TOKrparen) - return FALSE; // () is not a declarator - - /* Regard ( identifier ) as not a declarator - * BUG: what about ( *identifier ) in - * f(*p)(x); - * where f is a class instance with overloaded () ? - * Should we just disallow C-style function pointer declarations? - */ - if (t->value == TOKidentifier) - { Token *t2 = peek(t); - if (t2->value == TOKrparen) - return FALSE; - } - - - if (!isDeclarator(&t, haveId, TOKrparen)) - return FALSE; - t = peek(t); - parens = TRUE; - break; - - case TOKdelegate: - case TOKfunction: - t = peek(t); - if (!isParameters(&t)) - return FALSE; - continue; - } - break; - } - - while (1) - { - switch (t->value) - { -#if CARRAYDECL - case TOKlbracket: - parens = FALSE; - t = peek(t); - if (t->value == TOKrbracket) - { - t = peek(t); - } - else if (isDeclaration(t, 0, TOKrbracket, &t)) - { // It's an associative array declaration - t = peek(t); - } - else - { - // [ expression ] - if (!isExpression(&t)) - return FALSE; - if (t->value != TOKrbracket) - return FALSE; - t = peek(t); - } - continue; -#endif - - case TOKlparen: - parens = FALSE; - if (!isParameters(&t)) - return FALSE; - continue; - - // Valid tokens that follow a declaration - case TOKrparen: - case TOKrbracket: - case TOKassign: - case TOKcomma: - case TOKsemicolon: - case TOKlcurly: - case TOKin: - // The !parens is to disallow unnecessary parentheses - if (!parens && (endtok == TOKreserved || endtok == t->value)) - { *pt = t; - return TRUE; - } - return FALSE; - - default: - return FALSE; - } - } -} - - -int Parser::isParameters(Token **pt) -{ // This code parallels parseParameters() - Token *t = *pt; - int tmp; - - //printf("isParameters()\n"); - if (t->value != TOKlparen) - return FALSE; - - t = peek(t); - while (1) - { - switch (t->value) - { - case TOKrparen: - break; - - case TOKdotdotdot: - t = peek(t); - break; - - case TOKin: - case TOKout: - case TOKinout: - t = peek(t); - default: - if (!isBasicType(&t)) - return FALSE; - tmp = FALSE; - if (!isDeclarator(&t, &tmp, TOKreserved)) - return FALSE; - if (t->value == TOKassign) - { t = peek(t); - if (!isExpression(&t)) - return FALSE; - continue; - } - if (t->value == TOKcomma) - { t = peek(t); - continue; - } - break; - } - break; - } - if (t->value != TOKrparen) - return FALSE; - t = peek(t); - *pt = t; - return TRUE; -} - -int Parser::isExpression(Token **pt) -{ - // This is supposed to determine if something is an expression. - // What it actually does is scan until a closing right bracket - // is found. - - Token *t = *pt; - int nest = 0; - - for (;; t = peek(t)) - { - switch (t->value) - { - case TOKlbracket: - nest++; - continue; - - case TOKrbracket: - if (--nest >= 0) - continue; - break; - - case TOKcomma: - case TOKrparen: - if (nest) - continue; - break; - - case TOKeof: - return FALSE; - - default: - continue; - } - break; - } - - *pt = t; - return TRUE; -} - -/********************************************** - * Skip over - * instance foo.bar(parameters...) - * Output: - * if (pt), *pt is set to the token following the closing ) - * Returns: - * 1 it's valid instance syntax - * 0 invalid instance syntax - */ - -int Parser::isTemplateInstance(Token *t, Token **pt) -{ - t = peek(t); - if (t->value != TOKdot) - { - if (t->value != TOKidentifier) - goto Lfalse; - t = peek(t); - } - while (t->value == TOKdot) - { - t = peek(t); - if (t->value != TOKidentifier) - goto Lfalse; - t = peek(t); - } - if (t->value != TOKlparen) - goto Lfalse; - - // Skip over the template arguments - while (1) - { - while (1) - { - t = peek(t); - switch (t->value) - { - case TOKlparen: - if (!skipParens(t, &t)) - goto Lfalse; - continue; - case TOKrparen: - break; - case TOKcomma: - break; - case TOKeof: - case TOKsemicolon: - goto Lfalse; - default: - continue; - } - break; - } - - if (t->value != TOKcomma) - break; - } - if (t->value != TOKrparen) - goto Lfalse; - t = peek(t); - if (pt) - *pt = t; - return 1; - -Lfalse: - return 0; -} - -/******************************************* - * Skip parens, brackets. - * Input: - * t is on opening ( - * Output: - * *pt is set to closing token, which is ')' on success - * Returns: - * !=0 successful - * 0 some parsing error - */ - -int Parser::skipParens(Token *t, Token **pt) -{ - int parens = 0; - - while (1) - { - switch (t->value) - { - case TOKlparen: - parens++; - break; - - case TOKrparen: - parens--; - if (parens < 0) - goto Lfalse; - if (parens == 0) - goto Ldone; - break; - - case TOKeof: - case TOKsemicolon: - goto Lfalse; - - default: - break; - } - t = peek(t); - } - - Ldone: - if (*pt) - *pt = t; - return 1; - - Lfalse: - return 0; -} - -/********************************* Expression Parser ***************************/ - -Expression *Parser::parsePrimaryExp() -{ Expression *e; - Type *t; - Identifier *id; - Loc loc = this->loc; - - switch (token.value) - { - case TOKidentifier: - id = token.ident; - nextToken(); - if (token.value == TOKnot) - { // identifier!(template-argument-list) - TemplateInstance *tempinst; - - tempinst = new TemplateInstance(loc, id); - nextToken(); - tempinst->tiargs = parseTemplateArgumentList(); - e = new ScopeExp(loc, tempinst); - } - else - e = new IdentifierExp(loc, id); - break; - - case TOKdollar: - if (!inBrackets) - error("'$' is valid only inside [] of index or slice"); - e = new DollarExp(loc); - nextToken(); - break; - - case TOKdot: - // Signal global scope '.' operator with "" identifier - e = new IdentifierExp(loc, Id::empty); - break; - - case TOKthis: - e = new ThisExp(loc); - nextToken(); - break; - - case TOKsuper: - e = new SuperExp(loc); - nextToken(); - break; - - case TOKint32v: - e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32); - nextToken(); - break; - - case TOKuns32v: - e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32); - nextToken(); - break; - - case TOKint64v: - e = new IntegerExp(loc, token.int64value, Type::tint64); - nextToken(); - break; - - case TOKuns64v: - e = new IntegerExp(loc, token.uns64value, Type::tuns64); - nextToken(); - break; - - case TOKfloat32v: - e = new RealExp(loc, token.float80value, Type::tfloat32); - nextToken(); - break; - - case TOKfloat64v: - e = new RealExp(loc, token.float80value, Type::tfloat64); - nextToken(); - break; - - case TOKfloat80v: - e = new RealExp(loc, token.float80value, Type::tfloat80); - nextToken(); - break; - - case TOKimaginary32v: - e = new ImaginaryExp(loc, token.float80value, Type::timaginary32); - nextToken(); - break; - - case TOKimaginary64v: - e = new ImaginaryExp(loc, token.float80value, Type::timaginary64); - nextToken(); - break; - - case TOKimaginary80v: - e = new ImaginaryExp(loc, token.float80value, Type::timaginary80); - nextToken(); - break; - - case TOKnull: - e = new NullExp(loc); - nextToken(); - break; - - case TOKtrue: - e = new IntegerExp(loc, 1, Type::tbit); - nextToken(); - break; - - case TOKfalse: - e = new IntegerExp(loc, 0, Type::tbit); - nextToken(); - break; - - case TOKcharv: - e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tchar); - nextToken(); - break; - - case TOKwcharv: - e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::twchar); - nextToken(); - break; - - case TOKdcharv: - e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar); - nextToken(); - break; - - case TOKstring: - { unsigned char *s; - unsigned len; - - // cat adjacent strings - s = token.ustring; - len = token.len; - while (1) - { - nextToken(); - if (token.value == TOKstring) - { unsigned len1; - unsigned len2; - unsigned char *s2; - - len1 = len; - len2 = token.len; - len = len1 + len2; - s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char)); - memcpy(s2, s, len1 * sizeof(unsigned char)); - memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char)); - s = s2; - } - else - break; - } - e = new StringExp(loc, s, len); - break; - } - - CASE_BASIC_TYPES_X(t): - nextToken(); - L1: - check(TOKdot, t->toChars()); - if (token.value != TOKidentifier) - { error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars()); - goto Lerr; - } - e = new TypeDotIdExp(loc, t, token.ident); - nextToken(); - break; - - case TOKtypeof: - { Expression *exp; - - nextToken(); - check(TOKlparen); - exp = parseExpression(); - check(TOKrparen); - t = new TypeTypeof(loc, exp); - goto L1; - } - - case TOKtypeid: - { Type *t; - - nextToken(); - check(TOKlparen, "typeid"); - t = parseBasicType(); - t = parseDeclarator(t,NULL); // ( type ) - check(TOKrparen); - e = new TypeidExp(loc, t); - break; - } - - case TOKassert: - nextToken(); - check(TOKlparen, "assert"); - e = parseAssignExp(); - check(TOKrparen); - e = new AssertExp(loc, e); - break; - - case TOKinstance: // Deprecated - { TemplateInstance *tempinst; - - tempinst = parseTemplateInstance(); - if (!tempinst) - return NULL; - e = new ScopeExp(loc, tempinst); - break; - } - - case TOKfunction: - case TOKdelegate: - { - /* function type(parameters) { body } - * delegate type(parameters) { body } - */ - Array *arguments; - int varargs; - FuncLiteralDeclaration *fd; - Type *t; - enum TOK save = token.value; - - nextToken(); - if (token.value == TOKlcurly) - { // default to void() - t = Type::tvoid; - varargs = 0; - arguments = new Array(); - } - else - { - if (token.value == TOKlparen) - t = Type::tvoid; // default to void return type - else - { - t = parseBasicType(); - t = parseBasicType2(t); // function return type - } - arguments = parseParameters(&varargs); - } - t = new TypeFunction(arguments, t, varargs, linkage); - fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL); - parseContracts(fd); - e = new FuncExp(loc, fd); - break; - } - - default: - error("expression expected, not '%s'", token.toChars()); - Lerr: - // Anything for e, as long as it's not NULL - e = new IntegerExp(loc, 0, Type::tint32); - nextToken(); - break; - } - return parsePostExp(e); -} - -Expression *Parser::parsePostExp(Expression *e) -{ - Loc loc; - - while (1) - { - loc = this->loc; - switch (token.value) - { - case TOKdot: - nextToken(); - if (token.value == TOKidentifier) - { Identifier *id = token.ident; - - nextToken(); - if (token.value == TOKnot) - { // identifier!(template-argument-list) - TemplateInstance *tempinst; - - tempinst = new TemplateInstance(loc, id); - nextToken(); - tempinst->tiargs = parseTemplateArgumentList(); - e = new DotTemplateInstanceExp(loc, e, tempinst); - } - else - e = new DotIdExp(loc, e, id); - continue; - } - else - error("identifier expected following '.', not '%s'", token.toChars()); - break; -#if 0 - case TOKarrow: - nextToken(); - if (token.value == TOKidentifier) - e = new ArrowExp(loc, e, token.ident); - else - error("identifier expected following '->', not '%s'", token.toChars()); - break; -#endif - - case TOKplusplus: - e = new PostIncExp(loc, e); - break; - - case TOKminusminus: - e = new PostDecExp(loc, e); - break; - - case TOKlparen: - e = new CallExp(loc, e, parseArguments()); - continue; - - case TOKlbracket: - { // array dereferences: - // array[index] - // array[] - // array[lwr .. upr] - Expression *index; - Expression *upr; - - inBrackets++; - nextToken(); - if (token.value == TOKrbracket) - { // array[] - e = new SliceExp(loc, e, NULL, NULL); - nextToken(); - } - else - { - index = parseAssignExp(); - if (token.value == TOKslice) - { // array[lwr .. upr] - nextToken(); - upr = parseAssignExp(); - e = new SliceExp(loc, e, index, upr); - } - else - { // array[index, i2, i3, i4, ...] - Array *arguments = new Array(); - arguments->push(index); - if (token.value == TOKcomma) - { - nextToken(); - while (1) - { Expression *arg; - - arg = parseAssignExp(); - arguments->push(arg); - if (token.value == TOKrbracket) - break; - check(TOKcomma); - } - } - e = new ArrayExp(loc, e, arguments); - } - check(TOKrbracket); - inBrackets--; - } - continue; - } - - default: - return e; - } - nextToken(); - } -} - -Expression *Parser::parseUnaryExp() -{ Expression *e; - Loc loc = this->loc; - - switch (token.value) - { - case TOKand: - nextToken(); - e = parseUnaryExp(); - e = new AddrExp(loc, e); - break; - - case TOKplusplus: - nextToken(); - e = parseUnaryExp(); - e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32)); - break; - - case TOKminusminus: - nextToken(); - e = parseUnaryExp(); - e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32)); - break; - - case TOKmul: - nextToken(); - e = parseUnaryExp(); - e = new PtrExp(loc, e); - break; - - case TOKmin: - nextToken(); - e = parseUnaryExp(); - e = new NegExp(loc, e); - break; - - case TOKadd: - nextToken(); - e = parseUnaryExp(); - e = new UAddExp(loc, e); - break; - - case TOKnot: - nextToken(); - e = parseUnaryExp(); - e = new NotExp(loc, e); - break; - - case TOKtilde: - nextToken(); - e = parseUnaryExp(); - e = new ComExp(loc, e); - break; - - case TOKdelete: - nextToken(); - e = parseUnaryExp(); - e = new DeleteExp(loc, e); - break; - - case TOKnew: - { Type *t; - Array *newargs; - Array *arguments = NULL; - - nextToken(); - newargs = NULL; - if (token.value == TOKlparen) - { - newargs = parseArguments(); - } - -#if LTORARRAYDECL - t = parseBasicType(); - t = parseBasicType2(t); - if (t->ty == Taarray) - { - Type *index = ((TypeAArray *)t)->index; - - if (index->ty == Tident) - { - TypeIdentifier *ti = (TypeIdentifier *)index; - int i; - Expression *e; - Identifier *id = ti->ident; - - e = new IdentifierExp(loc, id); - for (i = 0; i < ti->idents.dim; i++) - { - id = (Identifier *)ti->idents.data[i]; - e = new DotIdExp(loc, e, id); - } - - arguments = new Array(); - arguments->push(e); - t = new TypeDArray(t->next); - } - else - { - error("need size of rightmost array, not type %s", index->toChars()); - return new NullExp(loc); - } - } - else if (t->ty == Tsarray) - { - TypeSArray *tsa = (TypeSArray *)t; - Expression *e = tsa->dim; - - arguments = new Array(); - arguments->push(e); - t = new TypeDArray(t->next); - } - else if (token.value == TOKlparen) - { - arguments = parseArguments(); - } -#else - t = parseBasicType(); - while (token.value == TOKmul) - { t = new TypePointer(t); - nextToken(); - } - if (token.value == TOKlbracket) - { - Expression *e; - - nextToken(); - e = parseAssignExp(); - arguments = new Array(); - arguments->push(e); - check(TOKrbracket); - t = parseDeclarator(t, NULL); - t = new TypeDArray(t); - } - else if (token.value == TOKlparen) - arguments = parseArguments(); -#endif - e = new NewExp(loc, newargs, t, arguments); - break; - } -#if DCASTSYNTAX - case TOKcast: // cast(type) expression - { Type *t; - - nextToken(); - check(TOKlparen); - t = parseBasicType(); - t = parseDeclarator(t,NULL); // ( type ) - check(TOKrparen); - - // if .identifier - if (token.value == TOKdot) - { - nextToken(); - if (token.value != TOKidentifier) - { error("Identifier expected following cast(type)."); - return NULL; - } - // cast(type).ident - e = new TypeDotIdExp(loc, t, token.ident); - nextToken(); - } - else - { - e = parseUnaryExp(); - e = new CastExp(loc, e, t); - } - - break; - } -#endif - case TOKlparen: - { Token *tk; - - nextToken(); -#if CCASTSYNTAX - // If cast - if (isDeclaration(&token, 0, TOKrparen, &tk)) - { - tk = peek(tk); // skip over right parenthesis - switch (tk->value) - { - case TOKdot: - case TOKplusplus: - case TOKminusminus: - case TOKnot: - case TOKtilde: - case TOKdelete: - case TOKnew: - case TOKlparen: - case TOKidentifier: - case TOKthis: - case TOKsuper: - case TOKint32v: - case TOKuns32v: - case TOKint64v: - case TOKuns64v: - case TOKfloat32v: - case TOKfloat64v: - case TOKfloat80v: - case TOKimaginary32v: - case TOKimaginary64v: - case TOKimaginary80v: - case TOKnull: - case TOKtrue: - case TOKfalse: - case TOKcharv: - case TOKwcharv: - case TOKdcharv: - case TOKstring: - case TOKand: - case TOKmul: - case TOKmin: - case TOKadd: - case TOKfunction: - case TOKdelegate: - case TOKtypeof: - CASE_BASIC_TYPES: // (type)int.size - { // (type) una_exp - Type *t; - - t = parseBasicType(); - t = parseDeclarator(t,NULL); - check(TOKrparen); - - // if .identifier - if (token.value == TOKdot) - { - nextToken(); - if (token.value != TOKidentifier) - { error("Identifier expected following (type)."); - return NULL; - } - e = new TypeDotIdExp(loc, t, token.ident); - nextToken(); - } - else - { - e = parseUnaryExp(); - e = new CastExp(loc, e, t); - error("C style cast illegal, use %s", e->toChars()); - } - return e; - } - } - } -#endif - // ( expression ) - e = parseExpression(); - check(TOKrparen); - e = parsePostExp(e); - break; - } - default: - e = parsePrimaryExp(); - break; - } - assert(e); - return e; -} - -Expression *Parser::parseMulExp() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - e = parseUnaryExp(); - while (1) - { - switch (token.value) - { - case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue; - case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; - case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; - - default: - break; - } - break; - } - return e; -} - -Expression *Parser::parseAddExp() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - e = parseMulExp(); - while (1) - { - switch (token.value) - { - case TOKadd: nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue; - case TOKmin: nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue; - case TOKtilde: nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue; - - default: - break; - } - break; - } - return e; -} - -Expression *Parser::parseShiftExp() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - e = parseAddExp(); - while (1) - { - switch (token.value) - { - case TOKshl: nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2); continue; - case TOKshr: nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2); continue; - case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue; - - default: - break; - } - break; - } - return e; -} - -Expression *Parser::parseRelExp() -{ Expression *e; - Expression *e2; - enum TOK op; - Loc loc = this->loc; - - e = parseShiftExp(); - while (1) - { - switch (token.value) - { - case TOKlt: - case TOKle: - case TOKgt: - case TOKge: - case TOKunord: - case TOKlg: - case TOKleg: - case TOKule: - case TOKul: - case TOKuge: - case TOKug: - case TOKue: - op = token.value; - nextToken(); - e2 = parseShiftExp(); - e = new CmpExp(op, loc, e, e2); - continue; - - case TOKin: - nextToken(); - e2 = parseShiftExp(); - e = new InExp(loc, e, e2); - continue; - - default: - break; - } - break; - } - return e; -} - -Expression *Parser::parseEqualExp() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - e = parseRelExp(); - while (1) - { enum TOK value = token.value; - - switch (value) - { - case TOKequal: - case TOKnotequal: - nextToken(); - e2 = parseRelExp(); - e = new EqualExp(value, loc, e, e2); - continue; - - case TOKidentity: - case TOKnotidentity: - nextToken(); - e2 = parseRelExp(); - e = new IdentityExp(value, loc, e, e2); - continue; - - default: - break; - } - break; - } - return e; -} - -Expression *Parser::parseAndExp() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - e = parseEqualExp(); - while (token.value == TOKand) - { - nextToken(); - e2 = parseEqualExp(); - e = new AndExp(loc,e,e2); - loc = this->loc; - } - return e; -} - -Expression *Parser::parseXorExp() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - e = parseAndExp(); - while (token.value == TOKxor) - { - nextToken(); - e2 = parseAndExp(); - e = new XorExp(loc, e, e2); - } - return e; -} - -Expression *Parser::parseOrExp() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - e = parseXorExp(); - while (token.value == TOKor) - { - nextToken(); - e2 = parseXorExp(); - e = new OrExp(loc, e, e2); - } - return e; -} - -Expression *Parser::parseAndAndExp() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - e = parseOrExp(); - while (token.value == TOKandand) - { - nextToken(); - e2 = parseOrExp(); - e = new AndAndExp(loc, e, e2); - } - return e; -} - -Expression *Parser::parseOrOrExp() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - e = parseAndAndExp(); - while (token.value == TOKoror) - { - nextToken(); - e2 = parseAndAndExp(); - e = new OrOrExp(loc, e, e2); - } - return e; -} - -Expression *Parser::parseCondExp() -{ Expression *e; - Expression *e1; - Expression *e2; - Loc loc = this->loc; - - e = parseOrOrExp(); - if (token.value == TOKquestion) - { - nextToken(); - e1 = parseExpression(); - check(TOKcolon); - e2 = parseCondExp(); - e = new CondExp(loc, e, e1, e2); - } - return e; -} - -Expression *Parser::parseAssignExp() -{ Expression *e; - Expression *e2; - Loc loc; - - e = parseCondExp(); - while (1) - { - loc = this->loc; - switch (token.value) - { -#define X(tok,ector) \ - case tok: nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue; - - X(TOKassign, AssignExp); - X(TOKaddass, AddAssignExp); - X(TOKminass, MinAssignExp); - X(TOKmulass, MulAssignExp); - X(TOKdivass, DivAssignExp); - X(TOKmodass, ModAssignExp); - X(TOKandass, AndAssignExp); - X(TOKorass, OrAssignExp); - X(TOKxorass, XorAssignExp); - X(TOKshlass, ShlAssignExp); - X(TOKshrass, ShrAssignExp); - X(TOKushrass, UshrAssignExp); - X(TOKcatass, CatAssignExp); - -#undef X - default: - break; - } - break; - } - return e; -} - -Expression *Parser::parseExpression() -{ Expression *e; - Expression *e2; - Loc loc = this->loc; - - //printf("Parser::parseExpression()\n"); - e = parseAssignExp(); - while (token.value == TOKcomma) - { - nextToken(); - e2 = parseAssignExp(); - e = new CommaExp(loc, e, e2); - loc = this->loc; - } - return e; -} - - -/************************* - * Collect argument list. - * Assume current token is '('. - */ - -Array *Parser::parseArguments() -{ // function call - Array *arguments; - Expression *arg; - - arguments = new Array(); - //if (token.value == TOKlparen) - { - nextToken(); - if (token.value != TOKrparen) - { - while (1) - { - arg = parseAssignExp(); - arguments->push(arg); - if (token.value == TOKrparen) - break; - check(TOKcomma); - } - } - check(TOKrparen); - } - return arguments; -} - -/********************************* ***************************/ - diff -uNr gdc-0.11/d/root/parse.h gdc-0.12/d/root/parse.h --- gdc-0.11/d/root/parse.h 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/root/parse.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,112 +0,0 @@ - -// Copyright (c) 1999-2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_PARSE_H -#define DMD_PARSE_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "lexer.h" -#include "enum.h" - -struct Type; -struct Expression; -struct Declaration; -struct Statement; -struct Import; -struct Initializer; -struct FuncDeclaration; -struct CtorDeclaration; -struct DtorDeclaration; -struct StaticCtorDeclaration; -struct StaticDtorDeclaration; -struct InvariantDeclaration; -struct UnitTestDeclaration; -struct NewDeclaration; -struct DeleteDeclaration; -struct DebugCondition; -struct VersionCondition; -struct Module; -struct ModuleDeclaration; -struct TemplateDeclaration; -struct TemplateInstance; -struct StaticAssert; - -struct Parser : Lexer -{ - ModuleDeclaration *md; - enum LINK linkage; - Loc endloc; // set to location of last right curly - int inBrackets; // inside [] of array index or slice - - Parser(Module *module, unsigned char *base, unsigned length); - - Array *parseModule(); - Array *parseDeclDefs(int once); - Array *parseBlock(); - TemplateDeclaration *parseTemplateDeclaration(); - Array *parseTemplateParameterList(); - TemplateInstance *parseTemplateInstance(); - Dsymbol *parseMixin(); - Array *parseTemplateArgumentList(); - StaticAssert *parseStaticAssert(); - DebugCondition *parseDebugCondition(); - VersionCondition *parseVersionCondition(); - CtorDeclaration *parseCtor(); - DtorDeclaration *parseDtor(); - StaticCtorDeclaration *parseStaticCtor(); - StaticDtorDeclaration *parseStaticDtor(); - InvariantDeclaration *parseInvariant(); - UnitTestDeclaration *parseUnitTest(); - NewDeclaration *parseNew(); - DeleteDeclaration *parseDelete(); - Array *parseParameters(int *pvarargs); - EnumDeclaration *parseEnum(); - Dsymbol *parseAggregate(); - Import *parseImport(Array *decldefs); - Type *parseBasicType(); - Type *parseBasicType2(Type *t); - Type *parseDeclarator(Type *t, Identifier **pident); - Array *parseDeclaration(); - void parseContracts(FuncDeclaration *f); - Statement *parseStatement(int flags); - Initializer *parseInitializer(); - void check(enum TOK value); - void check(enum TOK value, char *string); - int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt); - int isBasicType(Token **pt); - int isDeclarator(Token **pt, int *haveId, enum TOK endtok); - int isParameters(Token **pt); - int isExpression(Token **pt); - int isTemplateInstance(Token *t, Token **pt); - int skipParens(Token *t, Token **pt); - - Expression *parseExpression(); - Expression *parsePrimaryExp(); - Expression *parseUnaryExp(); - Expression *parsePostExp(Expression *e); - Expression *parseMulExp(); - Expression *parseAddExp(); - Expression *parseShiftExp(); - Expression *parseRelExp(); - Expression *parseEqualExp(); - Expression *parseAndExp(); - Expression *parseXorExp(); - Expression *parseOrExp(); - Expression *parseAndAndExp(); - Expression *parseOrOrExp(); - Expression *parseCondExp(); - Expression *parseAssignExp(); - - Array *parseArguments(); -}; - -#endif /* DMD_PARSE_H */ diff -uNr gdc-0.11/d/root/port.h gdc-0.12/d/root/port.h --- gdc-0.11/d/root/port.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/port.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,58 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com - -#ifndef PORT_H -#define PORT_H - -// Portable wrapper around compiler/system specific things. -// The idea is to minimize #ifdef's in the app code. - -#ifndef TYPEDEFS -#define TYPEDEFS - -#include - -#if _MSC_VER -typedef __int64 longlong; -typedef unsigned __int64 ulonglong; -#else -typedef long long longlong; -typedef unsigned long long ulonglong; -#endif - -#endif - -typedef double d_time; - -struct Port -{ - static double nan; - static double infinity; - static double dbl_max; - static double dbl_min; - - static int isnan(double); - static int isfinite(double); - static int isinfinity(double); - static int signbit(double); - - static double floor(double); - static double pow(double x, double y); - - static ulonglong strtoull(const char *p, char **pend, int base); - - static char *ull_to_string(char *buffer, ulonglong ull); - static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull); - - // Convert ulonglong to double - static double ull_to_double(ulonglong ull); - - // Get locale-dependent list separator - static char *list_separator(); - static wchar_t *wlist_separator(); -}; - -#endif diff -uNr gdc-0.11/d/root/readme.txt gdc-0.12/d/root/readme.txt --- gdc-0.11/d/root/readme.txt 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/readme.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,27 +0,0 @@ - - The D Programming Language - Compiler Front End Source - Copyright (c) 1999-2002, by Digital Mars - www.digitalmars.com - All Rights Reserved - - -This is the source code to the front end Digital Mars D compiler. -It covers the lexical analysis, parsing, and semantic analysis -of the D Programming Language defined in the documents at -www.digitalmars.com/d/ - -The optimizer, code generator, and object file generator are not part -of this source, hence the source does not currently constitute a complete, -compilable program. However, many people have expressed a strong interested -in producing a D compiler with the GNU compiler sources. This release should -enable that. - -These sources are free, they are redistributable and modifiable -under the terms of the GNU General Public License (attached as gpl.txt), -or the Artistic License (attached as artistic.txt). - -It does not apply to anything else distributed by Digital Mars, -including D compiler executables. - --Walter Bright diff -uNr gdc-0.11/d/root/root.c gdc-0.12/d/root/root.c --- gdc-0.11/d/root/root.c 2005-04-12 05:16:27.000000000 +0200 +++ gdc-0.12/d/root/root.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1771 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include -#include -#include -#include -#ifndef alloca -#include -#endif - -#if _MSC_VER -#include -#endif - -#if _WIN32 -#include -#endif - -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#endif - -#include "port.h" -#include "root.h" -#include "dchar.h" -#include "mem.h" - -#if 0 //__SC__ //def DEBUG -extern "C" void __cdecl _assert(void *e, void *f, unsigned line) -{ - printf("Assert('%s','%s',%d)\n",e,f,line); - fflush(stdout); - *(char *)0 = 0; -} -#endif - -/************************************* - * Convert wchar string to ascii string. - */ - -char *wchar2ascii(wchar_t *us) -{ - return wchar2ascii(us, wcslen(us)); -} - -char *wchar2ascii(wchar_t *us, unsigned len) -{ - unsigned i; - char *p; - - p = (char *)mem.malloc(len + 1); - for (i = 0; i <= len; i++) - p[i] = (char) us[i]; - return p; -} - -int wcharIsAscii(wchar_t *us) -{ - return wcharIsAscii(us, wcslen(us)); -} - -int wcharIsAscii(wchar_t *us, unsigned len) -{ - unsigned i; - - for (i = 0; i <= len; i++) - { - if (us[i] & ~0xFF) // if high bits set - return 0; // it's not ascii - } - return 1; -} - - -/*********************************** - * Compare length-prefixed strings (bstr). - */ - -int bstrcmp(unsigned char *b1, unsigned char *b2) -{ - return (*b1 == *b2 && memcmp(b1 + 1, b2 + 1, *b2) == 0) ? 0 : 1; -} - -/*************************************** - * Convert bstr into a malloc'd string. - */ - -char *bstr2str(unsigned char *b) -{ - char *s; - unsigned len; - - len = *b; - s = (char *) mem.malloc(len + 1); - s[len] = 0; - return (char *)memcpy(s,b + 1,len); -} - -/************************************** - * Print error message and exit. - */ - -void error(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - printf("Error: "); - vprintf(format, ap); - va_end( ap ); - printf("\n"); - fflush(stdout); - - exit(EXIT_FAILURE); -} - -#if M_UNICODE -void error(const dchar *format, ...) -{ - va_list ap; - - va_start(ap, format); - printf("Error: "); - vwprintf(format, ap); - va_end( ap ); - printf("\n"); - fflush(stdout); - - exit(EXIT_FAILURE); -} -#endif - -void error_mem() -{ - error("out of memory"); -} - -/************************************** - * Print warning message. - */ - -void warning(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - printf("Warning: "); - vprintf(format, ap); - va_end( ap ); - printf("\n"); - fflush(stdout); -} - -/****************************** Object ********************************/ - -int Object::equals(Object *o) -{ - return o == this; -} - -unsigned Object::hashCode() -{ - return (int) this; -} - -int Object::compare(Object *obj) -{ - return this - obj; -} - -void Object::print() -{ - printf("%s %p\n", toChars(), this); -} - -char *Object::toChars() -{ - return "Object"; -} - -dchar *Object::toDchars() -{ -#if M_UNICODE - return L"Object"; -#else - return toChars(); -#endif -} - -int Object::dyncast() -{ - return 0; -} - -void Object::toBuffer(OutBuffer *b) -{ - b->writestring("Object"); -} - -void Object::mark() -{ -} - -/****************************** String ********************************/ - -String::String(char *str, int ref) -{ - this->str = ref ? str : mem.strdup(str); - this->ref = ref; -} - -String::~String() -{ - mem.free(str); -} - -void String::mark() -{ - mem.mark(str); -} - -unsigned String::calcHash(const char *str, unsigned len) -{ - unsigned hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(unsigned char *)str; - return hash; - - case 2: - hash *= 37; - hash += *(unsigned short *)str; - return hash; - - case 3: - hash *= 37; - hash += (*(unsigned short *)str << 8) + - ((unsigned char *)str)[2]; - return hash; - - default: - hash *= 37; - hash += *(long *)str; - str += 4; - len -= 4; - break; - } - } -} - -unsigned String::calcHash(const char *str) -{ - return calcHash(str, strlen(str)); -} - -unsigned String::hashCode() -{ - return calcHash(str, strlen(str)); -} - -unsigned String::len() -{ - return strlen(str); -} - -int String::equals(Object *obj) -{ - return strcmp(str,((String *)obj)->str) == 0; -} - -int String::compare(Object *obj) -{ - return strcmp(str,((String *)obj)->str); -} - -char *String::toChars() -{ - return str; -} - -void String::print() -{ - printf("String '%s'\n",str); -} - - -/****************************** FileName ********************************/ - -FileName::FileName(char *str, int ref) - : String(str,ref) -{ -} - -char *FileName::combine(char *path, char *name) -{ char *f; - size_t pathlen; - size_t namelen; - - if (!path || !*path) - return name; - pathlen = strlen(path); - namelen = strlen(name); - f = (char *)mem.malloc(pathlen + 1 + namelen + 1); - memcpy(f, path, pathlen); -#ifndef _WIN32 - if (path[pathlen - 1] != '/') - { f[pathlen] = '/'; - pathlen++; - } -#endif -#if _WIN32 - if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':') - { f[pathlen] = '\\'; - pathlen++; - } -#endif - memcpy(f + pathlen, name, namelen + 1); - return f; -} - -FileName::FileName(char *path, char *name) - : String(combine(path,name),1) -{ -} - -// Split a path into an Array of paths -Array *FileName::splitPath(const char *path) -{ - char c = 0; // unnecessary initializer is for VC /W4 - const char *p; - OutBuffer buf; - Array *array; - - array = new Array(); - if (path) - { - p = path; - do - { char instring = 0; - - while (isspace(*p)) // skip leading whitespace - p++; - buf.reserve(strlen(p) + 1); // guess size of path - for (; ; p++) - { - c = *p; - switch (c) - { - case '"': - instring ^= 1; // toggle inside/outside of string - continue; - -#if MACINTOSH - case ',': -#endif -#if _WIN32 - case ';': -#endif -#ifndef _WIN32 - case ':': -#endif - p++; - break; // note that ; cannot appear as part - // of a path, quotes won't protect it - - case 0x1A: // ^Z means end of file - case 0: - break; - - case '\r': - continue; // ignore carriage returns - -#ifndef _WIN32 - case '~': - buf.writestring(getenv("HOME")); - continue; -#endif - - case ' ': - case '\t': // tabs in filenames? - if (!instring) // if not in string - break; // treat as end of path - default: - buf.writeByte(c); - continue; - } - break; - } - if (buf.offset) // if path is not empty - { - buf.writeByte(0); // to asciiz - array->push(buf.extractData()); - } - } while (c); - } - return array; -} - -unsigned FileName::hashCode() -{ -#ifndef _WIN32 - // darwin HFS is case insensitive, though... - return String::hashCode(); -#endif -#if _WIN32 - // We need a different hashCode because it must be case-insensitive - unsigned len = strlen(str); - unsigned hash = 0; - unsigned char *s = (unsigned char *)str; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(unsigned char *)s | 0x20; - return hash; - - case 2: - hash *= 37; - hash += *(unsigned short *)s | 0x2020; - return hash; - - case 3: - hash *= 37; - hash += ((*(unsigned short *)s << 8) + - ((unsigned char *)s)[2]) | 0x202020; - break; - - default: - hash *= 37; - hash += *(long *)s | 0x20202020; - s += 4; - len -= 4; - break; - } - } -#endif -} - -int FileName::compare(Object *obj) -{ -#ifndef _WIN32 - return String::compare(obj); -#endif -#if _WIN32 - return stricmp(str,((FileName *)obj)->str); -#endif -} - -int FileName::equals(Object *obj) -{ -#ifndef _WIN32 - return String::equals(obj); -#endif -#if _WIN32 - return stricmp(str,((FileName *)obj)->str) == 0; -#endif -} - -/************************************ - * Return !=0 if absolute path name. - */ - -int FileName::absolute(const char *name) -{ -#if _WIN32 - return (*name == '\\') || - (*name == '/') || - (*name && name[1] == ':'); -#endif -#ifndef _WIN32 - return (*name == '/'); -#endif -} - -/******************************** - * Return filename extension (read-only). - * If there isn't one, return NULL. - */ - -char *FileName::ext(const char *str) -{ - char *e; - size_t len = strlen(str); - - e = (char *)str + len; - for (;;) - { - switch (*e) - { case '.': - return e + 1; -#ifndef _WIN32 - case '/': - break; -#endif -#if _WIN32 - case '\\': - case ':': - break; -#endif - default: - if (e == str) - break; - e--; - continue; - } - return NULL; - } -} - -char *FileName::ext() -{ - return ext(str); -} - -/******************************** - * Return filename name excluding path (read-only). - */ - -char *FileName::name(const char *str) -{ - char *e; - size_t len = strlen(str); - - e = (char *)str + len; - for (;;) - { - switch (*e) - { -#ifndef _WIN32 - case '/': - return e + 1; -#endif -#if _WIN32 - case '\\': - case ':': - return e + 1; -#endif - default: - if (e == str) - break; - e--; - continue; - } - return e; - } -} - -char *FileName::name() -{ - return name(str); -} - -/************************************** - * Return path portion of str. - * Path will does not include trailing path separator. - */ - -char *FileName::path(const char *str) -{ - char *n = name(str); - char *path; - size_t pathlen; - - if (n > str) - { -#ifndef _WIN32 - if (n[-1] == '/') - n--; -#endif -#if _WIN32 - if (n[-1] == '\\') - n--; -#endif - } - pathlen = n - str; - path = (char *)mem.malloc(pathlen + 1); - memcpy(path, str, pathlen); - path[pathlen] = 0; - return path; -} - -/************************************** - * Replace filename portion of path. - */ - -char *FileName::replaceName(char *path, char *name) -{ char *f; - char *n; - size_t pathlen; - size_t namelen; - - if (absolute(name)) - return name; - - n = FileName::name(path); - if (n == path) - return name; - pathlen = n - path; - namelen = strlen(name); - f = (char *)mem.malloc(pathlen + 1 + namelen + 1); - memcpy(f, path, pathlen); -#ifndef _WIN32 - if (path[pathlen - 1] != '/') - { f[pathlen] = '/'; - pathlen++; - } -#endif -#if _WIN32 - if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':') - { f[pathlen] = '\\'; - pathlen++; - } -#endif - memcpy(f + pathlen, name, namelen + 1); - return f; -} - -/*************************** - */ - -FileName *FileName::defaultExt(const char *name, const char *ext) -{ - char *e; - char *s; - size_t len; - size_t extlen; - - e = FileName::ext(name); - if (e) // if already has an extension - return new FileName((char *)name, 0); - - len = strlen(name); - extlen = strlen(ext); - s = (char *)alloca(len + 1 + extlen + 1); - memcpy(s,name,len); - s[len] = '.'; - memcpy(s + len + 1, ext, extlen + 1); - return new FileName(s, 0); -} - -/*************************** - */ - -FileName *FileName::forceExt(const char *name, const char *ext) -{ - char *e; - char *s; - size_t len; - size_t extlen; - - e = FileName::ext(name); - if (e) // if already has an extension - { - len = e - name; - extlen = strlen(ext); - - s = (char *)alloca(len + extlen + 1); - memcpy(s,name,len); - memcpy(s + len, ext, extlen + 1); - return new FileName(s, 0); - } - else - return defaultExt(name, ext); // doesn't have one -} - -/****************************** - * Return !=0 if extensions match. - */ - -int FileName::equalsExt(const char *ext) -{ const char *e; - - e = FileName::ext(); - if (!e && !ext) - return 1; - if (!e || !ext) - return 0; -#ifndef _WIN32 - return strcmp(e,ext) == 0; -#endif -#if _WIN32 - return stricmp(e,ext) == 0; -#endif -} - -/************************************* - * Copy file from this to to. - */ - -void FileName::CopyTo(FileName *to) -{ - File file(this); - -#if _WIN32 - file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); // keep same file time -#endif -#ifndef _WIN32 - file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time -#endif - file.readv(); - file.name = to; - file.writev(); -} - -/************************************* - * Search Path for file. - * Input: - * cwd if !=0, search current directory before searching path - */ - -char *FileName::searchPath(Array *path, char *name, int cwd) -{ - if (absolute(name)) - { - return exists(name) ? name : NULL; - } - if (cwd) - { - if (exists(name)) - return name; - } - if (path) - { unsigned i; - - for (i = 0; i < path->dim; i++) - { - char *p = (char *)path->data[i]; - char *n = combine(p, name); - - if (exists(n)) - return n; - } - } - return NULL; -} - -int FileName::exists(const char *name) -{ -#ifndef _WIN32 - struct stat st; - - if (stat(name, &st) < 0) - return 0; - if (S_ISDIR(st.st_mode)) - return 2; - return 1; -#endif -#if _WIN32 - DWORD dw; - int result; - - dw = GetFileAttributesA(name); - if (dw == -1L) - result = 0; - else if (dw & FILE_ATTRIBUTE_DIRECTORY) - result = 2; - else - result = 1; - return result; -#endif -} - -/****************************** File ********************************/ - -File::File(FileName *n) -{ - ref = 0; - buffer = NULL; - len = 0; - touchtime = NULL; - name = n; -} - -File::File(char *n) -{ - ref = 0; - buffer = NULL; - len = 0; - touchtime = NULL; - name = new FileName(n, 0); -} - -File::~File() -{ - if (buffer) - { - if (ref == 0) - mem.free(buffer); -#if _WIN32 - else if (ref == 2) - UnmapViewOfFile(buffer); -#endif - } - if (touchtime) - mem.free(touchtime); -} - -void File::mark() -{ - mem.mark(buffer); - mem.mark(touchtime); - mem.mark(name); -} - -/************************************* - */ - -int File::read() -{ -#ifndef _WIN32 - off_t size; - ssize_t numread; - int fd; - struct stat buf; - int result = 0; - char *name; - - name = this->name->toChars(); - //printf("File::read('%s')\n",name); - fd = open(name, O_RDONLY); - if (fd == -1) - { result = errno; - //printf("\topen error, errno = %d\n",errno); - goto err1; - } - - if (!ref) - mem.free(buffer); - ref = 0; // we own the buffer now - - //printf("\tfile opened\n"); - if (fstat(fd, &buf)) - { - printf("\tfstat error, errno = %d\n",errno); - goto err2; - } - size = buf.st_size; - buffer = (unsigned char *) mem.malloc(size + 2); - if (!buffer) - { - printf("\tmalloc error, errno = %d\n",errno); - goto err2; - } - - numread = ::read(fd, buffer, size); - if (numread != size) - { - printf("\tread error, errno = %d\n",errno); - goto err2; - } - - if (touchtime) - memcpy(touchtime, &buf, sizeof(buf)); - - if (close(fd) == -1) - { - printf("\tclose error, errno = %d\n",errno); - goto err; - } - - len = size; - - // Always store a wchar ^Z past end of buffer so scanner has a sentinel - buffer[size] = 0x1A; - buffer[size + 1] = 0; - return 0; - -err2: - close(fd); -err: - mem.free(buffer); - buffer = NULL; - len = 0; - -err1: - result = 1; - return result; -#endif -#if _WIN32 - DWORD size; - DWORD numread; - HANDLE h; - int result = 0; - char *name; - - name = this->name->toChars(); - h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0); - if (h == INVALID_HANDLE_VALUE) - goto err1; - - if (!ref) - mem.free(buffer); - ref = 0; - - size = GetFileSize(h,NULL); - buffer = (unsigned char *) mem.malloc(size + 2); - if (!buffer) - goto err2; - - if (ReadFile(h,buffer,size,&numread,NULL) != TRUE) - goto err2; - - if (numread != size) - goto err2; - - if (touchtime) - { - if (!GetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime)) - goto err2; - } - - if (!CloseHandle(h)) - goto err; - - len = size; - - // Always store a wchar ^Z past end of buffer so scanner has a sentinel - buffer[size] = 0x1A; - buffer[size + 1] = 0; - return 0; - -err2: - CloseHandle(h); -err: - mem.free(buffer); - buffer = NULL; - len = 0; - -err1: - result = 1; - return result; -#endif -} - -/***************************** - * Read a file with memory mapped file I/O. - */ - -int File::mmread() -{ -#ifndef _WIN32 - return read(); -#endif -#if _WIN32 - HANDLE hFile; - HANDLE hFileMap; - DWORD size; - char *name; - - name = this->name->toChars(); - hFile = CreateFile(name, GENERIC_READ, - FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - goto Lerr; - size = GetFileSize(hFile, NULL); - //printf(" file created, size %d\n", size); - - hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,size,NULL); - if (CloseHandle(hFile) != TRUE) - goto Lerr; - - if (hFileMap == NULL) - goto Lerr; - - //printf(" mapping created\n"); - - if (!ref) - mem.free(buffer); - ref = 2; - buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL); - if (CloseHandle(hFileMap) != TRUE) - goto Lerr; - if (buffer == NULL) // mapping view failed - goto Lerr; - - len = size; - //printf(" buffer = %p\n", buffer); - - return 0; - -Lerr: - return GetLastError(); // failure -#endif -} - -/********************************************* - * Write a file. - * Returns: - * 0 success - */ - -int File::write() -{ -#ifndef _WIN32 - int fd; - ssize_t numwritten; - char *name; - - name = this->name->toChars(); - fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0660); - if (fd == -1) - goto err; - - numwritten = ::write(fd, buffer, len); - if (len != numwritten) - goto err2; - - if (close(fd) == -1) - goto err; - - if (touchtime) - { struct utimbuf ubuf; - - ubuf.actime = ((struct stat *)touchtime)->st_atime; - ubuf.modtime = ((struct stat *)touchtime)->st_mtime; - if (utime(name, &ubuf)) - goto err; - } - return 0; - -err2: - close(fd); -err: - return 1; -#endif -#if _WIN32 - HANDLE h; - DWORD numwritten; - char *name; - - name = this->name->toChars(); - h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); - if (h == INVALID_HANDLE_VALUE) - goto err; - - if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) - goto err2; - - if (len != numwritten) - goto err2; - - if (touchtime) { - SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime); - } - if (!CloseHandle(h)) - goto err; - return 0; - -err2: - CloseHandle(h); -err: - return 1; -#endif -} - -/********************************************* - * Append to a file. - * Returns: - * 0 success - */ - -int File::append() -{ -#ifndef _WIN32 - return 1; -#endif -#if _WIN32 - HANDLE h; - DWORD numwritten; - char *name; - - name = this->name->toChars(); - h = CreateFileA(name,GENERIC_WRITE,0,NULL,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); - if (h == INVALID_HANDLE_VALUE) - goto err; - -#if 1 - SetFilePointer(h, 0, NULL, FILE_END); -#else // INVALID_SET_FILE_POINTER doesn't seem to have a definition - if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) - goto err; -#endif - - if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) - goto err2; - - if (len != numwritten) - goto err2; - - if (touchtime) { - SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime); - } - if (!CloseHandle(h)) - goto err; - return 0; - -err2: - CloseHandle(h); -err: - return 1; -#endif -} - -/************************************** - */ - -void File::readv() -{ - if (read()) - error("Error reading file '%s'\n",name->toChars()); -} - -/************************************** - */ - -void File::mmreadv() -{ - if (mmread()) - readv(); -} - -void File::writev() -{ - if (write()) - error("Error writing file '%s'\n",name->toChars()); -} - -void File::appendv() -{ - if (write()) - error("Error appending to file '%s'\n",name->toChars()); -} - -/******************************************* - * Return !=0 if file exists. - * 0: file doesn't exist - * 1: normal file - * 2: directory - */ - -int File::exists() -{ -#ifndef _WIN32 - return 0; -#endif -#if _WIN32 - DWORD dw; - int result; - char *name; - - name = this->name->toChars(); - if (touchtime) - dw = ((WIN32_FIND_DATAA *)touchtime)->dwFileAttributes; - else - dw = GetFileAttributesA(name); - if (dw == -1L) - result = 0; - else if (dw & FILE_ATTRIBUTE_DIRECTORY) - result = 2; - else - result = 1; - return result; -#endif -} - -void File::remove() -{ -#ifndef _WIN32 - ::remove(this->name->toChars()); -#endif -#if _WIN32 - DeleteFileA(this->name->toChars()); -#endif -} - -Array *File::match(char *n) -{ - return match(new FileName(n, 0)); -} - -Array *File::match(FileName *n) -{ -#ifndef _WIN32 - return NULL; -#endif -#if _WIN32 - HANDLE h; - WIN32_FIND_DATAA fileinfo; - Array *a; - char *c; - char *name; - - a = new Array(); - c = n->toChars(); - name = n->name(); - h = FindFirstFileA(c,&fileinfo); - if (h != INVALID_HANDLE_VALUE) - { - do - { - // Glue path together with name - char *fn; - File *f; - - fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1); - memcpy(fn, c, name - c); - strcpy(fn + (name - c), fileinfo.cFileName); - f = new File(fn); - f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); - memcpy(f->touchtime, &fileinfo, sizeof(fileinfo)); - a->push(f); - } while (FindNextFileA(h,&fileinfo) != FALSE); - FindClose(h); - } - return a; -#endif -} - -int File::compareTime(File *f) -{ -#ifndef _WIN32 - return 0; -#endif -#if _WIN32 - if (!touchtime) - stat(); - if (!f->touchtime) - f->stat(); - return CompareFileTime(&((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime, &((WIN32_FIND_DATAA *)f->touchtime)->ftLastWriteTime); -#endif -} - -void File::stat() -{ -#ifndef _WIN32 - if (!touchtime) - { - touchtime = mem.calloc(1, sizeof(struct stat)); - } -#endif -#if _WIN32 - HANDLE h; - - if (!touchtime) - { - touchtime = mem.calloc(1, sizeof(WIN32_FIND_DATAA)); - } - h = FindFirstFileA(name->toChars(),(WIN32_FIND_DATAA *)touchtime); - if (h != INVALID_HANDLE_VALUE) - { - FindClose(h); - } -#endif -} - -void File::checkoffset(size_t offset, size_t nbytes) -{ - if (offset > len || offset + nbytes > len) - error("Corrupt file '%s': offset x%x off end of file",toChars(),offset); -} - -char *File::toChars() -{ - return name->toChars(); -} - - -/************************* OutBuffer *************************/ - -OutBuffer::OutBuffer() -{ - data = NULL; - offset = 0; - size = 0; -} - -OutBuffer::~OutBuffer() -{ - mem.free(data); -} - -void *OutBuffer::extractData() -{ - void *p; - - p = (void *)data; - data = NULL; - offset = 0; - size = 0; - return p; -} - -void OutBuffer::mark() -{ - mem.mark(data); -} - -void OutBuffer::reserve(unsigned nbytes) -{ - //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); - if (size - offset < nbytes) - { - size = (offset + nbytes) * 2; - data = (unsigned char *)mem.realloc(data, size); - } -} - -void OutBuffer::reset() -{ - offset = 0; -} - -void OutBuffer::setsize(unsigned size) -{ - offset = size; -} - -void OutBuffer::write(const void *data, unsigned nbytes) -{ - reserve(nbytes); - memcpy(this->data + offset, data, nbytes); - offset += nbytes; -} - -void OutBuffer::writebstring(unsigned char *string) -{ - write(string,*string + 1); -} - -void OutBuffer::writestring(char *string) -{ - write(string,strlen(string)); -} - -void OutBuffer::writedstring(const char *string) -{ -#if M_UNICODE - for (; *string; string++) - { - writedchar(*string); - } -#else - write(string,strlen(string)); -#endif -} - -void OutBuffer::writedstring(const wchar_t *string) -{ -#if M_UNICODE - write(string,wcslen(string) * sizeof(wchar_t)); -#else - for (; *string; string++) - { - writedchar(*string); - } -#endif -} - -void OutBuffer::prependstring(char *string) -{ unsigned len; - - len = strlen(string); - reserve(len); - memmove(data + len, data, offset); - memcpy(data, string, len); - offset += len; -} - -void OutBuffer::writenl() -{ -#if _WIN32 -#if M_UNICODE - write4(0x000A000D); // newline is CR,LF on Microsoft OS's -#else - writeword(0x0A0D); // newline is CR,LF on Microsoft OS's -#endif -#else -#if M_UNICODE - writeword('\n'); -#else - writeByte('\n'); -#endif -#endif -} - -void OutBuffer::writeByte(unsigned b) -{ - reserve(1); - this->data[offset] = (unsigned char)b; - offset++; -} - -void OutBuffer::writeUTF8(unsigned b) -{ - reserve(6); - if (b <= 0x7F) - { - this->data[offset] = (unsigned char)b; - offset++; - } - else if (b <= 0x7FF) - { - this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0); - this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80); - offset += 2; - } - else if (b <= 0xFFFF) - { - this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0); - this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); - this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80); - offset += 3; - } - else if (b <= 0x1FFFFF) - { - this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0); - this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); - this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); - this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80); - offset += 4; - } - else if (b <= 0x3FFFFFF) - { - this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8); - this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80); - this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); - this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); - this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80); - offset += 5; - } - else if (b <= 0x7FFFFFFF) - { - this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC); - this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80); - this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80); - this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); - this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); - this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80); - offset += 6; - } - else - assert(0); -} - -void OutBuffer::writedchar(unsigned b) -{ - reserve(Dchar_mbmax * sizeof(dchar)); - offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) - - this->data; -} - -void OutBuffer::prependbyte(unsigned b) -{ - reserve(1); - memmove(data + 1, data, offset); - data[0] = (unsigned char)b; - offset++; -} - -void OutBuffer::writeword(unsigned w) -{ - reserve(2); - *(unsigned short *)(this->data + offset) = (unsigned short)w; - offset += 2; -} - -void OutBuffer::writeUTF16(unsigned w) -{ - reserve(4); - if (w <= 0xFFFF) - { - *(unsigned short *)(this->data + offset) = (unsigned short)w; - offset += 2; - } - else if (w <= 0x10FFFF) - { - *(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0); - *(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00); - offset += 4; - } - else - assert(0); -} - -void OutBuffer::write4(unsigned w) -{ - reserve(4); - *(unsigned long *)(this->data + offset) = w; - offset += 4; -} - -void OutBuffer::write(OutBuffer *buf) -{ - if (buf) - { reserve(buf->offset); - memcpy(data + offset, buf->data, buf->offset); - offset += buf->offset; - } -} - -void OutBuffer::write(Object *obj) -{ - if (obj) - { - writestring(obj->toChars()); - } -} - -void OutBuffer::fill0(unsigned nbytes) -{ - reserve(nbytes); - memset(data + offset,0,nbytes); - offset += nbytes; -} - -void OutBuffer::align(unsigned size) -{ unsigned nbytes; - - nbytes = ((offset + size - 1) & ~(size - 1)) - offset; - fill0(nbytes); -} - -void OutBuffer::vprintf(const char *format, va_list args) -{ - char buffer[128]; - char *p; - unsigned psize; - int count; - - p = buffer; - psize = sizeof(buffer); - for (;;) - { -#if _WIN32 - count = _vsnprintf(p,psize,format,args); - if (count != -1) - break; - psize *= 2; -#endif -#ifndef _WIN32 - count = vsnprintf(p,psize,format,args); - if (count == -1) - psize *= 2; - else if (count >= psize) - psize = count + 1; - else - break; -#endif - p = (char *) alloca(psize); // buffer too small, try again with larger size - } - write(p,count); -} - -#if M_UNICODE -void OutBuffer::vprintf(const wchar_t *format, va_list args) -{ - dchar buffer[128]; - dchar *p; - unsigned psize; - int count; - - p = buffer; - psize = sizeof(buffer) / sizeof(buffer[0]); - for (;;) - { -#if _WIN32 - count = _vsnwprintf(p,psize,format,args); - if (count != -1) - break; - psize *= 2; -#endif -#ifndef _WIN32 - count = vsnwprintf(p,psize,format,args); - if (count == -1) - psize *= 2; - else if (count >= psize) - psize = count + 1; - else - break; -#endif - p = (dchar *) alloca(psize * 2); // buffer too small, try again with larger size - } - write(p,count * 2); -} -#endif - -void OutBuffer::printf(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - vprintf(format,ap); - va_end(ap); -} - -#if M_UNICODE -void OutBuffer::printf(const wchar_t *format, ...) -{ - va_list ap; - va_start(ap, format); - vprintf(format,ap); - va_end(ap); -} -#endif - -void OutBuffer::bracket(char left, char right) -{ - reserve(2); - memmove(data + 1, data, offset); - data[0] = left; - data[offset + 1] = right; - offset += 2; -} - -void OutBuffer::spread(unsigned offset, unsigned nbytes) -{ - reserve(nbytes); - memmove(data + offset + nbytes, data + offset, - this->offset - offset); - this->offset += nbytes; -} - -char *OutBuffer::toChars() -{ - writeByte(0); - return (char *)data; -} - -/********************************* Bits ****************************/ - -Bits::Bits() -{ - data = NULL; - bitdim = 0; - allocdim = 0; -} - -Bits::~Bits() -{ - mem.free(data); -} - -void Bits::mark() -{ - mem.mark(data); -} - -void Bits::resize(unsigned bitdim) -{ - unsigned allocdim; - unsigned mask; - - allocdim = (bitdim + 31) / 32; - data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0])); - if (this->allocdim < allocdim) - memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0])); - - // Clear other bits in last word - mask = (1 << (bitdim & 31)) - 1; - if (mask) - data[allocdim - 1] &= ~mask; - - this->bitdim = bitdim; - this->allocdim = allocdim; -} - -void Bits::set(unsigned bitnum) -{ - data[bitnum / 32] |= 1 << (bitnum & 31); -} - -void Bits::clear(unsigned bitnum) -{ - data[bitnum / 32] &= ~(1 << (bitnum & 31)); -} - -int Bits::test(unsigned bitnum) -{ - return data[bitnum / 32] & (1 << (bitnum & 31)); -} - -void Bits::set() -{ unsigned mask; - - memset(data, ~0, allocdim * sizeof(data[0])); - - // Clear other bits in last word - mask = (1 << (bitdim & 31)) - 1; - if (mask) - data[allocdim - 1] &= mask; -} - -void Bits::clear() -{ - memset(data, 0, allocdim * sizeof(data[0])); -} - -void Bits::copy(Bits *from) -{ - assert(bitdim == from->bitdim); - memcpy(data, from->data, allocdim * sizeof(data[0])); -} - -Bits *Bits::clone() -{ - Bits *b; - - b = new Bits(); - b->resize(bitdim); - b->copy(this); - return b; -} - -void Bits::sub(Bits *b) -{ - unsigned u; - - for (u = 0; u < allocdim; u++) - data[u] &= ~b->data[u]; -} - - - - - - - - - - - - - - - diff -uNr gdc-0.11/d/root/root.h gdc-0.12/d/root/root.h --- gdc-0.11/d/root/root.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/root.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,351 +0,0 @@ - - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef ROOT_H -#define ROOT_H - -#include -#include - -#if __SC__ -#pragma once -#endif - -#include "dchar.h" - -char *wchar2ascii(wchar_t *); -int wcharIsAscii(wchar_t *); -char *wchar2ascii(wchar_t *, unsigned len); -int wcharIsAscii(wchar_t *, unsigned len); - -int bstrcmp(unsigned char *s1, unsigned char *s2); -char *bstr2str(unsigned char *b); -#ifndef GCC_SAFE_DMD -void error(const char *format, ...); -void error(const wchar_t *format, ...); -void warning(const char *format, ...); -#endif - -#ifndef TYPEDEFS -#define TYPEDEFS - -#if _MSC_VER -typedef __int64 longlong; -typedef unsigned __int64 ulonglong; -#else -typedef long long longlong; -typedef unsigned long long ulonglong; -#endif - -#endif - -longlong randomx(); - -/* - * Root of our class library. - */ - -struct OutBuffer; -struct Array; - -struct Object -{ - Object() { } - virtual ~Object() { } - - virtual int equals(Object *o); - - /** - * Returns a hash code, useful for things like building hash tables of Objects. - */ - virtual unsigned hashCode(); - - /** - * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj. - * Useful for sorting Objects. - */ - virtual int compare(Object *obj); - - /** - * Pretty-print an Object. Useful for debugging the old-fashioned way. - */ - virtual void print(); - - virtual char *toChars(); - virtual dchar *toDchars(); - virtual void toBuffer(OutBuffer *buf); - - /** - * Used as a replacement for dynamic_cast. Returns a unique number - * defined by the library user. For Object, the return value is 0. - */ - virtual int dyncast(); - - /** - * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap. - */ - /*virtual*/ // not used, disable for now - void mark(); -}; - -struct String : Object -{ - int ref; // != 0 if this is a reference to someone else's string - char *str; // the string itself - - String(char *str, int ref = 1); - - ~String(); - - static unsigned calcHash(const char *str, unsigned len); - static unsigned calcHash(const char *str); - unsigned hashCode(); - unsigned len(); - int equals(Object *obj); - int compare(Object *obj); - char *toChars(); - void print(); - void mark(); -}; - -struct FileName : String -{ - FileName(char *str, int ref); - FileName(char *path, char *name); - unsigned hashCode(); - int equals(Object *obj); - int compare(Object *obj); - static int absolute(const char *name); - static char *ext(const char *); - char *ext(); - static char *name(const char *); - char *name(); - static char *path(const char *); - static char *replaceName(char *path, char *name); - - static char *combine(char *path, char *name); - static Array *splitPath(const char *path); - static FileName *defaultExt(const char *name, const char *ext); - static FileName *forceExt(const char *name, const char *ext); - int equalsExt(const char *ext); - - void CopyTo(FileName *to); - static char *searchPath(Array *path, char *name, int cwd); - static int exists(const char *name); -}; - -struct File : Object -{ - int ref; // != 0 if this is a reference to someone else's buffer - unsigned char *buffer; // data for our file - unsigned len; // amount of data in buffer[] - void *touchtime; // system time to use for file - - FileName *name; // name of our file - - File(char *); - File(FileName *); - ~File(); - - void mark(); - - char *toChars(); - - /* Read file, return !=0 if error - */ - - int read(); - - /* Write file, either succeed or fail - * with error message & exit. - */ - - void readv(); - - /* Read file, return !=0 if error - */ - - int mmread(); - - /* Write file, either succeed or fail - * with error message & exit. - */ - - void mmreadv(); - - /* Write file, return !=0 if error - */ - - int write(); - - /* Write file, either succeed or fail - * with error message & exit. - */ - - void writev(); - - /* Return !=0 if file exists. - * 0: file doesn't exist - * 1: normal file - * 2: directory - */ - - /* Append to file, return !=0 if error - */ - - int append(); - - /* Append to file, either succeed or fail - * with error message & exit. - */ - - void appendv(); - - /* Return !=0 if file exists. - * 0: file doesn't exist - * 1: normal file - * 2: directory - */ - - int exists(); - - /* Given wildcard filespec, return an array of - * matching File's. - */ - - static Array *match(char *); - static Array *match(FileName *); - - // Compare file times. - // Return <0 this < f - // =0 this == f - // >0 this > f - int File::compareTime(File *f); - - // Read system file statistics - void File::stat(); - - /* Set buffer - */ - - void setbuffer(void *buffer, unsigned len) - { - this->buffer = (unsigned char *)buffer; - this->len = len; - } - - void checkoffset(size_t offset, size_t nbytes); - - void remove(); // delete file -}; - -struct OutBuffer : Object -{ - unsigned char *data; - unsigned offset; - unsigned size; - - OutBuffer(); - ~OutBuffer(); - void *extractData(); - void mark(); - - void reserve(unsigned nbytes); - void setsize(unsigned size); - void reset(); - void write(const void *data, unsigned nbytes); - void writebstring(unsigned char *string); - void writestring(char *string); - void writedstring(const char *string); - void writedstring(const wchar_t *string); - void prependstring(char *string); - void writenl(); // write newline - void writeByte(unsigned b); - void writebyte(unsigned b) { writeByte(b); } - void writeUTF8(unsigned b); - void writedchar(unsigned b); - void prependbyte(unsigned b); - void writeword(unsigned w); - void writeUTF16(unsigned w); - void write4(unsigned w); - void write(OutBuffer *buf); - void write(Object *obj); - void fill0(unsigned nbytes); - void align(unsigned size); - void vprintf(const char *format, va_list args); - void printf(const char *format, ...); -#if M_UNICODE - void vprintf(const unsigned short *format, va_list args); - void printf(const unsigned short *format, ...); -#endif - void bracket(char left, char right); - void spread(unsigned offset, unsigned nbytes); - char *toChars(); - char *extractString(); -}; - -struct Array : Object -{ - unsigned dim; - unsigned allocdim; - void **data; - - Array(); - ~Array(); - void mark(); - char *toChars(); - - void reserve(unsigned nentries); - void setDim(unsigned newdim); - void fixDim(); - void push(void *ptr); - void *pop(); - void shift(void *ptr); - void insert(unsigned index, void *ptr); - void insert(unsigned index, Array *a); - void append(Array *a); - void remove(unsigned i); - void zero(); - void *tos(); - void sort(); - Array *copy(); -}; - -struct Bits : Object -{ - unsigned bitdim; - unsigned allocdim; - unsigned *data; - - Bits(); - ~Bits(); - void mark(); - - void resize(unsigned bitdim); - - void set(unsigned bitnum); - void clear(unsigned bitnum); - int test(unsigned bitnum); - - void set(); - void clear(); - void copy(Bits *from); - Bits *clone(); - - void sub(Bits *b); -}; - -#endif diff -uNr gdc-0.11/d/root/scope.c gdc-0.12/d/root/scope.c --- gdc-0.11/d/root/scope.c 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/scope.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,314 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "root.h" - -#include "mars.h" -#include "init.h" -#include "identifier.h" -#include "scope.h" -#include "attrib.h" -#include "dsymbol.h" -#include "declaration.h" -#include "aggregate.h" -#include "module.h" -#include "id.h" - -Scope *Scope::freelist = NULL; - -void *Scope::operator new(size_t size) -{ Scope *s; - - if (freelist) - { - s = freelist; - freelist = s->enclosing; - return s; - } - - return ::operator new(size); -} - -Scope::Scope() -{ // Create root scope - - this->module = NULL; - this->scopesym = NULL; - this->enclosing = NULL; - this->parent = NULL; - this->sw = NULL; - this->tf = NULL; - this->sbreak = NULL; - this->scontinue = NULL; - this->fes = NULL; - this->structalign = global.structalign; - this->func = NULL; - this->slabel = NULL; - this->linkage = LINKd; - this->protection = PROTpublic; - this->stc = 0; - this->offset = 0; - this->inunion = 0; - this->incontract = 0; - this->nofree = 0; - this->noctor = 0; - this->callSuper = 0; - this->flags = 0; - this->anonAgg = NULL; -} - -Scope::Scope(Scope *enclosing) -{ - this->module = enclosing->module; - this->func = enclosing->func; - this->parent = enclosing->parent; - this->scopesym = NULL; - this->sw = enclosing->sw; - this->tf = enclosing->tf; - this->sbreak = enclosing->sbreak; - this->scontinue = enclosing->scontinue; - this->fes = enclosing->fes; - this->structalign = enclosing->structalign; - this->enclosing = enclosing; - this->slabel = NULL; - this->linkage = enclosing->linkage; - this->protection = enclosing->protection; - this->stc = enclosing->stc; - this->offset = 0; - this->inunion = enclosing->inunion; - this->incontract = enclosing->incontract; - this->nofree = 0; - this->noctor = enclosing->noctor; - this->callSuper = enclosing->callSuper; - this->flags = 0; - this->anonAgg = NULL; - assert(this != enclosing); -} - -Scope *Scope::createGlobal(Module *module) -{ - Scope *sc; - - sc = new Scope(); - sc->module = module; - sc->scopesym = new ScopeDsymbol(); - sc->scopesym->symtab = new DsymbolTable(); - - // Add top level package as member of this global scope - Dsymbol *m = module; - while (m->parent) - m = m->parent; - m->addMember(sc->scopesym); - m->parent = NULL; // got changed by addMember() - - // Create the module scope underneath the global scope - sc = sc->push(module); - sc->parent = module; - return sc; -} - -Scope *Scope::push() -{ Scope *s; - - s = new Scope(this); - assert(this != s); - return s; -} - -Scope *Scope::push(ScopeDsymbol *ss) -{ Scope *s; - - s = push(); - s->scopesym = ss; - return s; -} - -Scope *Scope::pop() -{ - Scope *enc = enclosing; - - if (enclosing) - enclosing->callSuper |= callSuper; - - if (!nofree) - { enclosing = freelist; - freelist = this; - } - - return enc; -} - -void Scope::mergeCallSuper(Loc loc, unsigned cs) -{ - // This does a primitive flow analysis to support the restrictions - // regarding when and how constructors can appear. - // It merges the results of two paths. - // The two paths are callSuper and cs; the result is merged into callSuper. - - if (cs != callSuper) - { int a; - int b; - - callSuper |= cs & (CSXany_ctor | CSXlabel); - if (cs & CSXreturn) - { - } - else if (callSuper & CSXreturn) - { - callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel)); - } - else - { - a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0; - b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0; - if (a != b) - error(loc, "one path skips constructor"); - callSuper |= cs; - } - } -} - -Dsymbol *Scope::search(Identifier *ident, Dsymbol **pscopesym) -{ Dsymbol *s; - Scope *sc; - - //printf("Scope::search(%p, '%s')\n", this, ident->toChars()); - if (ident == Id::empty) - { - // Look for module scope - for (sc = this; sc; sc = sc->enclosing) - { - assert(sc != sc->enclosing); - if (sc->scopesym) - { - s = sc->scopesym->isModule(); - if (s) - { - //printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars()); - if (pscopesym) - *pscopesym = sc->scopesym; - return s; - } - } - } - return NULL; - } - - for (sc = this; sc; sc = sc->enclosing) - { - assert(sc != sc->enclosing); - if (sc->scopesym) - { - //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind()); - s = sc->scopesym->search(ident, 0); - if (s) - { - if (global.params.warnings && - ident == Id::length && - sc->scopesym->isArrayScopeSymbol() && - sc->enclosing && - sc->enclosing->search(ident, NULL)) - { - printf("warning - "); - error("array 'length' hides other 'length' name in outer scope"); - } - - //printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind()); - if (pscopesym) - *pscopesym = sc->scopesym; - return s; - } - } - } - - return NULL; -} - -Dsymbol *Scope::insert(Dsymbol *s) -{ Scope *sc; - - for (sc = this; sc; sc = sc->enclosing) - { - //printf("\tsc = %p\n", sc); - if (sc->scopesym) - { - //printf("\t\tsc->scopesym = %p\n", sc->scopesym); - if (!sc->scopesym->symtab) - sc->scopesym->symtab = new DsymbolTable(); - return sc->scopesym->symtab->insert(s); - } - } - assert(0); - return NULL; -} - -/******************************************** - * Search enclosing scopes for ClassDeclaration. - */ - -ClassDeclaration *Scope::getClassScope() -{ Scope *sc; - - for (sc = this; sc; sc = sc->enclosing) - { - ClassDeclaration *cd; - - if (sc->scopesym) - { - cd = sc->scopesym->isClassDeclaration(); - if (cd) - return cd; - } - } - return NULL; -} - -/******************************************** - * Search enclosing scopes for ClassDeclaration. - */ - -AggregateDeclaration *Scope::getStructClassScope() -{ Scope *sc; - - for (sc = this; sc; sc = sc->enclosing) - { - AggregateDeclaration *ad; - - if (sc->scopesym) - { - ad = sc->scopesym->isClassDeclaration(); - if (ad) - return ad; - else - { ad = sc->scopesym->isStructDeclaration(); - if (ad) - return ad; - } - } - } - return NULL; -} - -/******************************************* - * For TemplateDeclarations, we need to remember the Scope - * where it was declared. So mark the Scope as not - * to be free'd. - */ - -void Scope::setNoFree() -{ Scope *sc; - - for (sc = this; sc; sc = sc->enclosing) - { - sc->nofree = 1; - } -} diff -uNr gdc-0.11/d/root/scope.h gdc-0.12/d/root/scope.h --- gdc-0.11/d/root/scope.h 2005-04-17 15:49:49.000000000 +0200 +++ gdc-0.12/d/root/scope.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,93 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_SCOPE_H -#define DMD_SCOPE_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -struct Dsymbol; -struct ScopeDsymbol; -struct Array; -struct Identifier; -struct Module; -struct Statement; -struct SwitchStatement; -struct TryFinallyStatement; -struct LabelStatement; -struct ForeachStatement; -struct ClassDeclaration; -struct AggregateDeclaration; -struct AnonymousAggregateDeclaration; -struct FuncDeclaration; -enum LINK; -enum PROT; - -struct Scope -{ - Scope *enclosing; // enclosing Scope - - Module *module; // Root module - ScopeDsymbol *scopesym; // current symbol - FuncDeclaration *func; // function we are in - Dsymbol *parent; // parent to use - LabelStatement *slabel; // enclosing labelled statement - SwitchStatement *sw; // enclosing switch statement - TryFinallyStatement *tf; // enclosing try finally statement - Statement *sbreak; // enclosing statement that supports "break" - Statement *scontinue; // enclosing statement that supports "continue" - ForeachStatement *fes; // if nested function for ForeachStatement, this is it - unsigned offset; // next offset to use in aggregate - int inunion; // we're processing members of a union - int incontract; // we're inside contract code - int nofree; // set if shouldn't free it - int noctor; // set if constructor calls aren't allowed - unsigned callSuper; // primitive flow analysis for constructors -#define CSXthis_ctor 1 // called this() -#define CSXsuper_ctor 2 // called super() -#define CSXthis 4 // referenced this -#define CSXsuper 8 // referenced super -#define CSXlabel 0x10 // seen a label -#define CSXreturn 0x20 // seen a return statement -#define CSXany_ctor 0x40 // either this() or super() was called - - unsigned structalign; // alignment for struct members - enum LINK linkage; // linkage for external functions - enum PROT protection; // protection for class members - unsigned stc; // storage class - unsigned flags; -#define SCOPEctor 1 // constructor type - - AnonymousAggregateDeclaration *anonAgg; // for temporary analysis - - static Scope *freelist; - static void *operator new(size_t sz); - static Scope *createGlobal(Module *module); - - Scope(); - Scope(Module *module); - Scope(Scope *enclosing); - - Scope *push(); - Scope *push(ScopeDsymbol *ss); - Scope *pop(); - - void mergeCallSuper(Loc loc, unsigned cs); - - Dsymbol *search(Identifier *ident, Dsymbol **pscopesym); - Dsymbol *insert(Dsymbol *s); - - ClassDeclaration *getClassScope(); - AggregateDeclaration *getStructClassScope(); - void setNoFree(); -}; - -#endif /* DMD_SCOPE_H */ diff -uNr gdc-0.11/d/root/statement.c gdc-0.12/d/root/statement.c --- gdc-0.11/d/root/statement.c 2005-04-26 03:45:07.000000000 +0200 +++ gdc-0.12/d/root/statement.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,2473 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include -#include - -#include "mem.h" - -#include "statement.h" -#include "expression.h" -#include "debcond.h" -#include "init.h" -#include "staticassert.h" -#include "mtype.h" -#include "scope.h" -#include "declaration.h" -#include "aggregate.h" -#include "id.h" - - -/******************************** Statement ***************************/ - -Statement::Statement(Loc loc) - : loc(loc) -{ -} - -Statement *Statement::syntaxCopy() -{ - assert(0); - return NULL; -} - -void Statement::print() -{ - printf("%s\n", toChars()); - fflush(stdout); -} - -char *Statement::toChars() -{ OutBuffer *buf; - - buf = new OutBuffer(); - toCBuffer(buf); - return buf->toChars(); -} - -void Statement::toCBuffer(OutBuffer *buf) -{ - buf->printf("Statement::toCBuffer()"); - buf->writenl(); -} - -Statement *Statement::semantic(Scope *sc) -{ - return this; -} - -// Same as semantic(), but do create a new scope - -Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue) -{ Scope *scd; - Statement *s; - - scd = sc->push(); - if (sbreak) - scd->sbreak = sbreak; - if (scontinue) - scd->scontinue = scontinue; - s = semantic(scd); - scd->pop(); - return s; -} - -void Statement::error(const char *format, ...) -{ - char *p = loc.toChars(); - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); - - global.errors++; - fatal(); -} - -int Statement::hasBreak() -{ - return FALSE; -} - -int Statement::hasContinue() -{ - return FALSE; -} - -// TRUE if statement uses exception handling - -int Statement::usesEH() -{ - return FALSE; -} - -// TRUE if statement may fall off the end without a throw or return - -int Statement::fallOffEnd() -{ - return TRUE; -} - -// TRUE if statement 'comes from' somewhere else, like a goto - -int Statement::comeFrom() -{ - return FALSE; -} - -/**************************************** - * If this statement has code that needs to run in a finally clause - * at the end of the current scope, return that code in the form of - * a Statement. - */ - -Statement *Statement::callAutoDtor() -{ - //printf("Statement::callAutoDtor()\n"); - //print(); - return NULL; -} - -/********************************* - * Flatten out the scope by presenting the statement - * as an array of statements. - * Returns NULL if no flattening necessary. - */ - -Array *Statement::flatten() -{ - return NULL; -} - -/******************************** ExpStatement ***************************/ - -ExpStatement::ExpStatement(Loc loc, Expression *exp) - : Statement(loc) -{ - this->exp = exp; -} - -Statement *ExpStatement::syntaxCopy() -{ - Expression *e = exp ? exp->syntaxCopy() : NULL; - ExpStatement *es = new ExpStatement(loc, e); - return es; -} - -void ExpStatement::toCBuffer(OutBuffer *buf) -{ - if (exp) - exp->toCBuffer(buf); - buf->writeByte(';'); - buf->writenl(); -} - -Statement *ExpStatement::semantic(Scope *sc) -{ - if (exp) - exp = exp->semantic(sc); - return this; -} - -int ExpStatement::fallOffEnd() -{ - if (exp && exp->op == TOKassert) - { AssertExp *a = (AssertExp *)exp; - - if (a->e1->isBool(FALSE)) // if it's an assert(0) - return FALSE; - } - return TRUE; -} - -/******************************** DeclarationStatement ***************************/ - -DeclarationStatement::DeclarationStatement(Loc loc, Dsymbol *declaration) - : ExpStatement(loc, new DeclarationExp(loc, declaration)) -{ -} - -DeclarationStatement::DeclarationStatement(Loc loc, Expression *exp) - : ExpStatement(loc, exp) -{ -} - -Statement *DeclarationStatement::syntaxCopy() -{ - DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy()); - return ds; -} - -Statement *DeclarationStatement::callAutoDtor() -{ - //printf("DeclarationStatement::callAutoDtor()\n"); - //print(); - - if (exp) - { - if (exp->op == TOKdeclaration) - { - DeclarationExp *de = (DeclarationExp *)(exp); - VarDeclaration *v = de->declaration->isVarDeclaration(); - if (v) - { Expression *e; - - e = v->callAutoDtor(); - if (e) - { - //printf("dtor is: "); e->print(); - return new ExpStatement(loc, e); - } - } - } - } - return NULL; -} - -void DeclarationStatement::toCBuffer(OutBuffer *buf) -{ - buf->printf("DeclarationStatement::toCBuffer()"); - buf->writenl(); -} - - -/******************************** CompoundStatement ***************************/ - -CompoundStatement::CompoundStatement(Loc loc, Array *s) - : Statement(loc) -{ - statements = s; -} - -CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2) - : Statement(loc) -{ - statements = new Array(); - statements->reserve(2); - statements->push(s1); - statements->push(s2); -} - -Statement *CompoundStatement::syntaxCopy() -{ - Array *a = new Array(); - a->setDim(statements->dim); - for (int i = 0; i < statements->dim; i++) - { Statement *s = (Statement *)statements->data[i]; - if (s) - s = s->syntaxCopy(); - a->data[i] = s; - } - CompoundStatement *cs = new CompoundStatement(loc, a); - return cs; -} - - -Statement *CompoundStatement::semantic(Scope *sc) -{ Statement *s; - - //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc); - for (int i = 0; i < statements->dim; i++) - { - L1: - s = (Statement *) statements->data[i]; - if (s) - { Array *a = s->flatten(); - - if (a) - { - statements->remove(i); - statements->insert(i, a); - if (i >= statements->dim) - break; - goto L1; - } - - s = s->semantic(sc); - statements->data[i] = s; - if (s) - { - Statement *finalbody; - - finalbody = s->callAutoDtor(); - if (finalbody) - { - if (i + 1 == statements->dim) - { - statements->push(finalbody); - } - else - { - // The rest of the statements form the body of a try-finally - Statement *body; - Array *a = new Array(); - - for (int j = i + 1; j < statements->dim; j++) - { - a->push(statements->data[j]); - } - body = new CompoundStatement(0, a); - s = new TryFinallyStatement(0, body, finalbody); - s = s->semantic(sc); - statements->data[i + 1] = s; - statements->setDim(i + 2); - break; - } - } - } - } - } - if (statements->dim == 1) - return s; - return this; -} - -Array *CompoundStatement::flatten() -{ - return statements; -} - -void CompoundStatement::toCBuffer(OutBuffer *buf) -{ int i; - - for (i = 0; i < statements->dim; i++) - { Statement *s; - - s = (Statement *) statements->data[i]; - if (s) - s->toCBuffer(buf); - } -} - -int CompoundStatement::usesEH() -{ - for (int i = 0; i < statements->dim; i++) - { Statement *s; - - s = (Statement *) statements->data[i]; - if (s && s->usesEH()) - return TRUE; - } - return FALSE; -} - -int CompoundStatement::fallOffEnd() -{ int falloff = TRUE; - - //printf("CompoundStatement::fallOffEnd()\n"); - for (int i = 0; i < statements->dim; i++) - { Statement *s = (Statement *)statements->data[i]; - - if (!s) - continue; - - if (!falloff && global.params.warnings && !s->comeFrom()) - { - printf("warning - "); - s->error("statement is not reachable"); - } - falloff = s->fallOffEnd(); - } - return falloff; -} - - -/******************************** ScopeStatement ***************************/ - -ScopeStatement::ScopeStatement(Loc loc, Statement *s) - : Statement(loc) -{ - this->statement = s; -} - -Statement *ScopeStatement::syntaxCopy() -{ - Statement *s; - - s = statement ? statement->syntaxCopy() : NULL; - s = new ScopeStatement(loc, s); - return s; -} - - -Statement *ScopeStatement::semantic(Scope *sc) -{ ScopeDsymbol *sym; - - //printf("ScopeStatement::semantic(sc = %p)\n", sc); - if (statement) - { Array *a; - - sym = new ScopeDsymbol(); - sym->parent = sc->scopesym; - sc = sc->push(sym); - - a = statement->flatten(); - if (a) - { - statement = new CompoundStatement(loc, a); - } - - statement = statement->semantic(sc); - if (statement) - { - Statement *finalbody; - finalbody = statement->callAutoDtor(); - if (finalbody) - { - //printf("adding finalbody\n"); - statement = new CompoundStatement(loc, statement, finalbody); - } - } - - sc->pop(); - } - return this; -} - -int ScopeStatement::fallOffEnd() -{ - return statement ? statement->fallOffEnd() : TRUE; -} - -void ScopeStatement::toCBuffer(OutBuffer *buf) -{ - buf->writeByte('{'); - buf->writenl(); - - if (statement) - statement->toCBuffer(buf); - - buf->writeByte('}'); - buf->writenl(); -} - -/******************************** WhileStatement ***************************/ - -WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b) - : Statement(loc) -{ - condition = c; - body = b; -} - -Statement *WhileStatement::syntaxCopy() -{ - WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body->syntaxCopy()); - return s; -} - - -Statement *WhileStatement::semantic(Scope *sc) -{ - condition = condition->semantic(sc); - condition = resolveProperties(sc, condition); - condition = condition->checkToBoolean(); - - sc->noctor++; - body = body->semanticScope(sc, this, this); - sc->noctor--; - - return this; -} - -int WhileStatement::hasBreak() -{ - return TRUE; -} - -int WhileStatement::hasContinue() -{ - return TRUE; -} - -int WhileStatement::usesEH() -{ - return body->usesEH(); -} - -int WhileStatement::fallOffEnd() -{ - body->fallOffEnd(); - return TRUE; -} - -/******************************** DoStatement ***************************/ - -DoStatement::DoStatement(Loc loc, Statement *b, Expression *c) - : Statement(loc) -{ - body = b; - condition = c; -} - -Statement *DoStatement::syntaxCopy() -{ - DoStatement *s = new DoStatement(loc, body->syntaxCopy(), condition->syntaxCopy()); - return s; -} - - -Statement *DoStatement::semantic(Scope *sc) -{ - sc->noctor++; - body = body->semanticScope(sc, this, this); - sc->noctor--; - condition = condition->semantic(sc); - condition = resolveProperties(sc, condition); - condition = condition->checkToBoolean(); - return this; -} - -int DoStatement::hasBreak() -{ - return TRUE; -} - -int DoStatement::hasContinue() -{ - return TRUE; -} - -int DoStatement::usesEH() -{ - return body->usesEH(); -} - -int DoStatement::fallOffEnd() -{ - body->fallOffEnd(); - return TRUE; -} - -/******************************** ForStatement ***************************/ - -ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body) - : Statement(loc) -{ - this->init = init; - this->condition = condition; - this->increment = increment; - this->body = body; -} - -Statement *ForStatement::syntaxCopy() -{ - Statement *i = NULL; - if (init) - i = init->syntaxCopy(); - Expression *c = NULL; - if (condition) - c = condition->syntaxCopy(); - Expression *inc = NULL; - if (increment) - inc = increment->syntaxCopy(); - ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy()); - return s; -} - -Statement *ForStatement::semantic(Scope *sc) -{ ScopeDsymbol *sym; - - sym = new ScopeDsymbol(); - sym->parent = sc->scopesym; - sc = sc->push(sym); - if (init) - init = init->semantic(sc); - if (!condition) - // Use a default value - condition = new IntegerExp(loc, 1, Type::tboolean); - sc->noctor++; - condition = condition->semantic(sc); - condition = resolveProperties(sc, condition); - condition = condition->checkToBoolean(); - if (increment) - increment = increment->semantic(sc); - - sc->sbreak = this; - sc->scontinue = this; - body = body->semantic(sc); - sc->noctor--; - - sc->pop(); - return this; -} - -int ForStatement::hasBreak() -{ - return TRUE; -} - -int ForStatement::hasContinue() -{ - return TRUE; -} - -int ForStatement::usesEH() -{ - return (init && init->usesEH()) || body->usesEH(); -} - -int ForStatement::fallOffEnd() -{ - body->fallOffEnd(); - return TRUE; -} - -/******************************** ForeachStatement ***************************/ - -ForeachStatement::ForeachStatement(Loc loc, Array *arguments, - Expression *aggr, Statement *body) - : Statement(loc) -{ - this->arguments = arguments; - this->aggr = aggr; - this->body = body; - - this->key = NULL; - this->value = NULL; -} - -Statement *ForeachStatement::syntaxCopy() -{ - Array *args = Argument::arraySyntaxCopy(arguments); - Expression *exp = aggr->syntaxCopy(); - ForeachStatement *s = new ForeachStatement(loc, args, exp, body->syntaxCopy()); - return s; -} - -Statement *ForeachStatement::semantic(Scope *sc) -{ - ScopeDsymbol *sym; - Statement *s = this; - int dim = arguments->dim; - int i; - TypeAArray *taa = NULL; - - Type *tn = NULL; - Type *tnv = NULL; - - aggr = aggr->semantic(sc); - aggr = resolveProperties(sc, aggr); - - sym = new ScopeDsymbol(); - sym->parent = sc->scopesym; - sc = sc->push(sym); - - sc->noctor++; - - Type *tab = aggr->type->toBasetype(); - switch (tab->ty) - { - case Tarray: - case Tsarray: - if (dim < 1 || dim > 2) - { - error("only one or two arguments for array foreach"); - break; - } - - /* Look for special case of parsing char types out of char type - * array. - */ - tn = tab->next->toBasetype(); - if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) - { Argument *arg; - - i = (dim == 1) ? 0 : 1; // index of value - arg = (Argument *)arguments->data[i]; - arg->type = arg->type->semantic(loc, sc); - tnv = arg->type->toBasetype(); - if (tnv->ty != tn->ty && - (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar)) - { - if (arg->inout == InOut) - error("foreach: value of UTF conversion cannot be inout"); - if (dim == 2) - { arg = (Argument *)arguments->data[0]; - if (arg->inout == InOut) - error("foreach: key cannot be inout"); - } - goto Lapply; - } - } - - for (i = 0; i < dim; i++) - { // Declare args - Argument *arg = (Argument *)arguments->data[i]; - VarDeclaration *var; - - var = new VarDeclaration(0, arg->type, arg->ident, NULL); - var->storage_class |= STCforeach; - switch (arg->inout) - { case In: var->storage_class |= STCin; break; - case Out: var->storage_class |= STCout; break; - case InOut: var->storage_class |= STCin | STCout; break; - } - var->semantic(sc); - if (!sc->insert(var)) - error("%s already defined", var->ident->toChars()); - - if (dim == 2 && i == 0) - key = var; - else - value = var; - } - - sc->sbreak = this; - sc->scontinue = this; - body = body->semantic(sc); - - if (!value->type->equals(tab->next)) - { - if (aggr->op == TOKstring) - aggr = aggr->implicitCastTo(value->type->arrayOf()); - else - error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars()); - } - - if (value->storage_class & STCout && value->type->toBasetype()->ty == Tbit) - error("foreach: value cannot be out and type bit"); - - if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) - { - error("foreach: key type must be int or uint, not %s", key->type->toChars()); - } - - if (key && key->storage_class & STCout) - error("foreach: key cannot be out"); - break; - - case Taarray: - taa = (TypeAArray *)tab; - if (dim < 1 || dim > 2) - { - error("only one or two arguments for associative array foreach"); - break; - } - case Tclass: - case Tstruct: - Lapply: - { FuncDeclaration *fdapply; - Array *args; - Expression *ec; - Expression *e; - FuncLiteralDeclaration *fld; - Argument *a; - Type *t; - Expression *flde; - Identifier *id; - - // Need a variable to hold value from any return statements in body. - if (!sc->func->vresult && sc->func->type->next != Type::tvoid) - { VarDeclaration *v; - - v = new VarDeclaration(loc, sc->func->type->next, Id::result, NULL); - v->noauto = 1; - v->semantic(sc); - if (!sc->insert(v)) - assert(0); - v->parent = sc->func; - sc->func->vresult = v; - } - - /* Turn body into the function literal: - * int delegate(inout T arg) { body } - */ - args = new Array(); - for (i = 0; i < dim; i++) - { Argument *arg = (Argument *)arguments->data[i]; - - arg->type = arg->type->semantic(loc, sc); - if (arg->inout == InOut) - id = arg->ident; - else - { // Make a copy of the inout argument so it isn't - // a reference. - VarDeclaration *v; - Initializer *ie; - char applyArg[10 + 4 + 1]; - - sprintf(applyArg, "__applyArg%d", i); - id = Lexer::idPool(applyArg); - - ie = new ExpInitializer(0, new IdentifierExp(0, id)); - v = new VarDeclaration(0, arg->type, arg->ident, ie); - s = new DeclarationStatement(0, v); - body = new CompoundStatement(loc, s, body); - } - a = new Argument(InOut, arg->type, id, NULL); - args->push(a); - } - t = new TypeFunction(args, Type::tint32, 0, LINKd); - fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this); - fld->fbody = body; - flde = new FuncExp(loc, fld); - flde = flde->semantic(sc); - - // Resolve any forward referenced goto's - for (int i = 0; i < gotos.dim; i++) - { CompoundStatement *cs = (CompoundStatement *)gotos.data[i]; - GotoStatement *gs = (GotoStatement *)cs->statements->data[0]; - - if (!gs->label->statement) - { // 'Promote' it to this scope, and replace with a return - cases.push(gs); - s = new ReturnStatement(0, new IntegerExp(cases.dim + 1)); - cs->statements->data[0] = (void *)s; - } - } - - if (tab->ty == Taarray) - { - // Check types - Argument *arg = (Argument *)arguments->data[0]; - if (dim == 2) - { - if (arg->inout == InOut) - error("foreach: index cannot be inout"); - if (!arg->type->equals(taa->index)) - error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars()); - arg = (Argument *)arguments->data[1]; - } - if (!arg->type->equals(taa->next)) - error("foreach: value must be type %s, not %s", taa->next->toChars(), arg->type->toChars()); - - /* Call: - * _aaApply(aggr, keysize, flde) - */ - if (dim == 2) - fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply2"); - else - fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply"); - ec = new VarExp(0, fdapply); - args = new Array(); - args->push(aggr); - args->push(new IntegerExp(0, taa->key->size(), Type::tint32)); - args->push(flde); - e = new CallExp(loc, ec, args); - e->type = Type::tindex; // don't run semantic() on e - } - else if (tab->ty == Tarray || tab->ty == Tsarray) - { - /* Call: - * _aApply(aggr, flde) - */ - static char fntab[9][3] = - { "cc","cw","cd", - "wc","cc","wd", - "dc","dw","dd" - }; - char fdname[10 + 1]; - int flag; - - switch (tn->ty) - { - case Tchar: flag = 0; break; - case Twchar: flag = 3; break; - case Tdchar: flag = 6; break; - default: assert(0); - } - switch (tnv->ty) - { - case Tchar: flag += 0; break; - case Twchar: flag += 1; break; - case Tdchar: flag += 2; break; - default: assert(0); - } - int j = sprintf(fdname, "_aApply%.*s%d", 2, fntab[flag], dim); - assert(j < sizeof(fdname)); - fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); - - ec = new VarExp(0, fdapply); - args = new Array(); - if (tab->ty == Tsarray) - aggr = aggr->castTo(tn->arrayOf()); - args->push(aggr); - args->push(flde); - e = new CallExp(loc, ec, args); - e->type = Type::tindex; // don't run semantic() on e - } - else - { - /* Call: - * aggr.apply(flde) - */ - ec = new DotIdExp(loc, aggr, Id::apply); - args = new Array(); - args->push(flde); - e = new CallExp(loc, ec, args); - e = e->semantic(sc); - if (e->type != Type::tint32) - error("apply() function for %s must return an int", tab->toChars()); - } - - if (!cases.dim) - // Easy case, a clean exit from the loop - s = new ExpStatement(loc, e); - else - { // Construct a switch statement around the return value - // of the apply function. - Array *a = new Array(); - - // default: break; takes care of cases 0 and 1 - s = new BreakStatement(0, NULL); - s = new DefaultStatement(0, s); - a->push(s); - - // cases 2... - for (int i = 0; i < cases.dim; i++) - { - s = (Statement *)cases.data[i]; - s = new CaseStatement(0, new IntegerExp(i + 2), s); - a->push(s); - } - - s = new CompoundStatement(loc, a); - s = new SwitchStatement(loc, e, s); - s = s->semantic(sc); - } - break; - } - - default: - error("foreach: %s is not an aggregate type", aggr->type->toChars()); - break; - } - sc->noctor--; - sc->pop(); - return s; -} - -int ForeachStatement::hasBreak() -{ - return TRUE; -} - -int ForeachStatement::hasContinue() -{ - return TRUE; -} - -int ForeachStatement::usesEH() -{ - return body->usesEH(); -} - -int ForeachStatement::fallOffEnd() -{ - body->fallOffEnd(); - return TRUE; -} - -/******************************** IfStatement ***************************/ - -IfStatement::IfStatement(Loc loc, Expression *condition, Statement *ifbody, Statement *elsebody) - : Statement(loc) -{ - this->condition = condition; - this->ifbody = ifbody; - this->elsebody = elsebody; -} - -Statement *IfStatement::syntaxCopy() -{ - Statement *e = NULL; - if (elsebody) - e = elsebody->syntaxCopy(); - IfStatement *s = new IfStatement(loc, condition->syntaxCopy(), ifbody->syntaxCopy(), e); - return s; -} - -Statement *IfStatement::semantic(Scope *sc) -{ - condition = condition->semantic(sc); - condition = resolveProperties(sc, condition); - condition = condition->checkToBoolean(); - - // If we can short-circuit evaluate the if statement, don't do the - // semantic analysis of the skipped code. - // This feature allows a limited form of conditional compilation. - condition = condition->optimize(WANTflags); -#if 0 - /* Don't do this because of: - * if (0) { Label: ... ; } else { ... ; goto Label; } - */ - if (condition->isBool(FALSE)) - { Statement *s; - - s = new ExpStatement(loc, condition); - if (elsebody) - { elsebody = elsebody->semanticScope(sc, NULL, NULL); - s = new CompoundStatement(loc, s, elsebody); - } - return s; - } - else if (condition->isBool(TRUE)) - { Statement *s; - - s = new ExpStatement(loc, condition); - ifbody = ifbody->semanticScope(sc, NULL, NULL); - s = new CompoundStatement(loc, s, ifbody); - return s; - } - else -#endif - { // Evaluate at runtime - unsigned cs0 = sc->callSuper; - unsigned cs1; - - ifbody = ifbody->semanticScope(sc, NULL, NULL); - cs1 = sc->callSuper; - sc->callSuper = cs0; - if (elsebody) - elsebody = elsebody->semanticScope(sc, NULL, NULL); - sc->mergeCallSuper(loc, cs1); - } - return this; -} - -int IfStatement::usesEH() -{ - return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); -} - -int IfStatement::fallOffEnd() -{ - if (!ifbody || ifbody->fallOffEnd() || - !elsebody || elsebody->fallOffEnd()) - return TRUE; - return FALSE; -} - - -void IfStatement::toCBuffer(OutBuffer *buf) -{ - buf->printf("IfStatement::toCBuffer()"); - buf->writenl(); -} - -/******************************** ConditionalStatement ***************************/ - -ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody) - : Statement(loc) -{ - this->condition = condition; - this->ifbody = ifbody; - this->elsebody = elsebody; -} - -Statement *ConditionalStatement::syntaxCopy() -{ - Statement *e = NULL; - if (elsebody) - e = elsebody->syntaxCopy(); - ConditionalStatement *s = new ConditionalStatement(loc, - condition, ifbody->syntaxCopy(), e); - return s; -} - -Statement *ConditionalStatement::semantic(Scope *sc) -{ - //condition = condition->semantic(sc); - - // If we can short-circuit evaluate the if statement, don't do the - // semantic analysis of the skipped code. - // This feature allows a limited form of conditional compilation. - if (condition->isBool(FALSE)) - { - if (elsebody) - elsebody = elsebody->semantic(sc); - return elsebody; - } - else if (condition->isBool(TRUE)) - { - ifbody = ifbody->semantic(sc); - return ifbody; - } - else - { Statement *s; - - // Evaluate at runtime - s = new IfStatement(loc, condition->toExpr(), ifbody, elsebody); - s = s->semantic(sc); - return s; - } - return this; -} - -int ConditionalStatement::usesEH() -{ - return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); -} - -void ConditionalStatement::toCBuffer(OutBuffer *buf) -{ - buf->printf("ConditionalStatement::toCBuffer()"); - buf->writenl(); -} - - -/******************************** PragmaStatement ***************************/ - -PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Array *args, Statement *body) - : Statement(loc) -{ - this->ident = ident; - this->args = args; - this->body = body; -} - -Statement *PragmaStatement::syntaxCopy() -{ - Statement *b = NULL; - if (body) - b = body->syntaxCopy(); - PragmaStatement *s = new PragmaStatement(loc, - ident, Expression::arraySyntaxCopy(args), b); - return s; -} - -Statement *PragmaStatement::semantic(Scope *sc) -{ // Should be merged with PragmaDeclaration - if (ident == Id::msg) - { - if (args) - { - for (size_t i = 0; i < args->dim; i++) - { - Expression *e = (Expression *)args->data[i]; - - e = e->semantic(sc); - if (e->op == TOKstring) - { - StringExp *se = (StringExp *)e; - printf("%.*s", se->len, se->string); - } - else - error("string expected for message, not '%s'", e->toChars()); - } - printf("\n"); - } - } - else if (ident == Id::lib) - { - if (!args || args->dim != 1) - error("string expected for library name"); - else - { - Expression *e = (Expression *)args->data[0]; - - e = e->semantic(sc); - args->data[0] = (void *)e; - if (e->op != TOKstring) - error("string expected for library name, not '%s'", e->toChars()); - } - } - else - error("unrecognized pragma(%s)", ident->toChars()); - - if (body) - { - body = body->semantic(sc); - } - return body; -} - -int PragmaStatement::usesEH() -{ - return body && body->usesEH(); -} - -int PragmaStatement::fallOffEnd() -{ - if (body) - return body->fallOffEnd(); - return TRUE; -} - -void PragmaStatement::toCBuffer(OutBuffer *buf) -{ - buf->printf("PragmaStatement::toCBuffer()"); - buf->writenl(); -} - - -/******************************** StaticAssertStatement ***************************/ - -StaticAssertStatement::StaticAssertStatement(StaticAssert *sa) - : Statement(sa->loc) -{ - this->sa = sa; -} - -Statement *StaticAssertStatement::syntaxCopy() -{ - StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL)); - return s; -} - -Statement *StaticAssertStatement::semantic(Scope *sc) -{ - sa->semantic2(sc); - return NULL; -} - -void StaticAssertStatement::toCBuffer(OutBuffer *buf) -{ - sa->toCBuffer(buf); -} - - -/******************************** SwitchStatement ***************************/ - -SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b) - : Statement(loc) -{ - condition = c; - body = b; - sdefault = NULL; - cases = NULL; -} - -Statement *SwitchStatement::syntaxCopy() -{ - SwitchStatement *s = new SwitchStatement(loc, - condition->syntaxCopy(), body->syntaxCopy()); - return s; -} - -Statement *SwitchStatement::semantic(Scope *sc) -{ - //printf("SwitchStatement::semantic(%p)\n", this); - assert(!cases); // ensure semantic() is only run once - condition = condition->semantic(sc); - condition = resolveProperties(sc, condition); - if (condition->type->isString()) - { - // If it's not an array, cast it to one - if (condition->type->ty != Tarray) - { - condition = condition->implicitCastTo(condition->type->next->arrayOf()); - } - } - else - { condition = condition->integralPromotions(); - condition->checkIntegral(); - } - - sc = sc->push(); - sc->sbreak = this; - sc->sw = this; - - cases = new Array(); - sc->noctor++; // BUG: should use Scope::mergeCallSuper() for each case instead - body = body->semantic(sc); - sc->noctor--; - - // Resolve any goto case's with exp - for (int i = 0; i < gotoCases.dim; i++) - { - GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i]; - - if (!gcs->exp) - { - gcs->error("no case statement following goto case;"); - break; - } - - for (Scope *scx = sc; scx; scx = scx->enclosing) - { - if (!scx->sw) - continue; - for (int j = 0; j < scx->sw->cases->dim; j++) - { - CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j]; - - if (cs->exp->equals(gcs->exp)) - { - gcs->cs = cs; - goto Lfoundcase; - } - } - } - gcs->error("case %s not found", gcs->exp->toChars()); - - Lfoundcase: - ; - } - - if (!sc->sw->sdefault) - { - if (global.params.warnings) - { printf("warning - "); - error("switch statement has no default"); - } - - // Generate runtime error if the default is hit - Array *a = new Array(); - CompoundStatement *cs; - Statement *s; - - if (global.params.useSwitchError) - s = new SwitchErrorStatement(loc); - else - { Expression *e = new HaltExp(loc); - s = new ExpStatement(loc, e); - } - - a->reserve(4); - a->push(body); - a->push(new BreakStatement(loc, NULL)); - sc->sw->sdefault = new DefaultStatement(loc, s); - a->push(sc->sw->sdefault); - cs = new CompoundStatement(loc, a); - body = cs; - } - - sc->pop(); - return this; -} - -int SwitchStatement::hasBreak() -{ - return TRUE; -} - -int SwitchStatement::usesEH() -{ - return body->usesEH(); -} - -int SwitchStatement::fallOffEnd() -{ - body->fallOffEnd(); - return TRUE; -} - -/******************************** CaseStatement ***************************/ - -CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s) - : Statement(loc) -{ - this->exp = exp; - this->statement = s; - cblock = NULL; -} - -Statement *CaseStatement::syntaxCopy() -{ - CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy()); - return s; -} - -Statement *CaseStatement::semantic(Scope *sc) -{ SwitchStatement *sw = sc->sw; - - exp = exp->semantic(sc); - if (sw) - { int i; - - exp = exp->implicitCastTo(sw->condition->type); - exp = exp->constFold(); - if (exp->op != TOKstring && exp->op != TOKint64) - { - error("case must be a string or an integral constant, not %s", exp->toChars()); - exp = new IntegerExp(0); - } - - for (i = 0; i < sw->cases->dim; i++) - { - CaseStatement *cs = (CaseStatement *)sw->cases->data[i]; - - //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars()); - if (cs->exp->equals(exp)) - { error("duplicate case %s in switch statement", exp->toChars()); - break; - } - } - - sw->cases->push(this); - - // Resolve any goto case's with no exp to this case statement - for (i = 0; i < sw->gotoCases.dim; i++) - { - GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i]; - - if (!gcs->exp) - { - gcs->cs = this; - sw->gotoCases.remove(i); // remove from array - } - } - } - else - error("case not in switch statement"); - statement = statement->semantic(sc); - return this; -} - -int CaseStatement::compare(Object *obj) -{ - // Sort cases so we can do an efficient lookup - CaseStatement *cs2 = (CaseStatement *)(obj); - - return exp->compare(cs2->exp); -} - -int CaseStatement::usesEH() -{ - return statement->usesEH(); -} - -int CaseStatement::fallOffEnd() -{ - return statement->fallOffEnd(); -} - -int CaseStatement::comeFrom() -{ - return TRUE; -} - -/******************************** DefaultStatement ***************************/ - -DefaultStatement::DefaultStatement(Loc loc, Statement *s) - : Statement(loc) -{ - this->statement = s; - cblock = NULL; -} - -Statement *DefaultStatement::syntaxCopy() -{ - DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy()); - return s; -} - -Statement *DefaultStatement::semantic(Scope *sc) -{ - if (sc->sw) - { - if (sc->sw->sdefault) - { - error("switch statement already has a default"); - } - sc->sw->sdefault = this; - } - else - error("default not in switch statement"); - statement = statement->semantic(sc); - return this; -} - -int DefaultStatement::usesEH() -{ - return statement->usesEH(); -} - -int DefaultStatement::fallOffEnd() -{ - return statement->fallOffEnd(); -} - -int DefaultStatement::comeFrom() -{ - return TRUE; -} - -/******************************** GotoDefaultStatement ***************************/ - -GotoDefaultStatement::GotoDefaultStatement(Loc loc) - : Statement(loc) -{ - sw = NULL; -} - -Statement *GotoDefaultStatement::syntaxCopy() -{ - GotoDefaultStatement *s = new GotoDefaultStatement(loc); - return s; -} - -Statement *GotoDefaultStatement::semantic(Scope *sc) -{ - sw = sc->sw; - if (!sw) - error("goto default not in switch statement"); - return this; -} - -int GotoDefaultStatement::fallOffEnd() -{ - return FALSE; -} - -/******************************** GotoCaseStatement ***************************/ - -GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp) - : Statement(loc) -{ - cs = NULL; - this->exp = exp; -} - -Statement *GotoCaseStatement::syntaxCopy() -{ - Expression *e = exp ? exp->syntaxCopy() : NULL; - GotoCaseStatement *s = new GotoCaseStatement(loc, e); - return s; -} - -Statement *GotoCaseStatement::semantic(Scope *sc) -{ - if (exp) - exp = exp->semantic(sc); - - if (!sc->sw) - error("goto case not in switch statement"); - else - { - sc->sw->gotoCases.push(this); - if (exp) - { - exp = exp->implicitCastTo(sc->sw->condition->type); - exp = exp->constFold(); - } - } - return this; -} - -int GotoCaseStatement::fallOffEnd() -{ - return FALSE; -} - -/******************************** SwitchErrorStatement ***************************/ - -SwitchErrorStatement::SwitchErrorStatement(Loc loc) - : Statement(loc) -{ -} - -int SwitchErrorStatement::fallOffEnd() -{ - return FALSE; -} - -/******************************** ReturnStatement ***************************/ - -ReturnStatement::ReturnStatement(Loc loc, Expression *exp) - : Statement(loc) -{ - this->exp = exp; -} - -Statement *ReturnStatement::syntaxCopy() -{ - Expression *e = NULL; - if (exp) - e = exp->syntaxCopy(); - ReturnStatement *s = new ReturnStatement(loc, e); - return s; -} - -Statement *ReturnStatement::semantic(Scope *sc) -{ - FuncDeclaration *fd = sc->parent->isFuncDeclaration(); - FuncDeclaration *fdx = fd; - Type *tret = fd->type->next; - Type *tbret = tret->toBasetype(); - - Scope *scx = sc; - if (sc->fes) - { - Statement *s; - - // Find scope of function foreach is in - for (; 1; scx = scx->enclosing) - { - assert(scx); - if (scx->func != fd) - { fdx = scx->func; - break; - } - } - - if (exp) - { exp = exp->semantic(sc); - exp = resolveProperties(sc, exp); - exp = exp->implicitCastTo(fdx->type->next); - } - if (!exp || exp->op == TOKint64 || exp->op == TOKfloat64 || - exp->op == TOKimaginary80 || exp->op == TOKcomplex80 || - exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull || - exp->op == TOKstring) - { - sc->fes->cases.push(this); - s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); - } - else if (fdx->type->next->toBasetype() == Type::tvoid) - { - Statement *s1; - Statement *s2; - - s = new ReturnStatement(0, NULL); - sc->fes->cases.push(s); - - // Construct: { exp; return cases.dim + 1; } - s1 = new ExpStatement(loc, exp); - s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); - s = new CompoundStatement(loc, s1, s2); - } - else - { - VarExp *v; - Statement *s1; - Statement *s2; - - // Construct: return vresult; - assert(fdx->vresult); - v = new VarExp(0, fdx->vresult); - s = new ReturnStatement(0, v); - sc->fes->cases.push(s); - - // Construct: { vresult = exp; return cases.dim + 1; } - v = new VarExp(0, fdx->vresult); - exp = new AssignExp(loc, v, exp); - exp = exp->semantic(sc); - s1 = new ExpStatement(loc, exp); - s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); - s = new CompoundStatement(loc, s1, s2); - } - return s; - } - - if (sc->incontract) - error("return statements cannot be in contracts"); - if (sc->tf) - error("return statements cannot be in finally bodies"); - - if (fd->isCtorDeclaration()) - { - // Constructors implicitly do: - // return this; - if (exp && exp->op != TOKthis) - error("cannot return expression from constructor"); - exp = new ThisExp(0); - } - - if (exp) - { - fd->hasReturnExp = 1; - - if (fd->returnLabel && tbret->ty != Tvoid) - { - assert(fd->vresult); - VarExp *v = new VarExp(0, fd->vresult); - - exp = resolveProperties(sc, exp); - exp = new AssignExp(loc, v, exp); - exp = exp->semantic(sc); - } - else - { - exp = exp->semantic(sc); - exp = resolveProperties(sc, exp); - if (tbret->ty != Tvoid) - exp = exp->implicitCastTo(tret); - } - } - else if (tbret->ty != Tvoid) // if non-void return - error("return expression expected"); - - /* BUG: need to issue an error on: - * this - * { if (x) return; - * super(); - * } - */ - - if (sc->callSuper & CSXany_ctor && - !(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor))) - error("return without calling constructor"); - - sc->callSuper |= CSXreturn; - - // See if all returns are instead to be replaced with a goto returnLabel; - if (fd->returnLabel) - { - GotoStatement *gs = new GotoStatement(loc, Id::returnLabel); - - gs->label = fd->returnLabel; - if (exp) - { Statement *s; - - s = new ExpStatement(loc, exp); - return new CompoundStatement(loc, s, gs); - } - return gs; - } - - if (exp && tbret->ty == Tvoid) - { Statement *s; - - s = new ExpStatement(loc, exp); - exp = NULL; - return new CompoundStatement(loc, s, this); - } - - return this; -} - -int ReturnStatement::fallOffEnd() -{ - return FALSE; -} - -void ReturnStatement::toCBuffer(OutBuffer *buf) -{ - buf->printf("return "); - if (exp) - exp->toCBuffer(buf); - buf->writeByte(';'); - buf->writenl(); -} - -/******************************** BreakStatement ***************************/ - -BreakStatement::BreakStatement(Loc loc, Identifier *ident) - : Statement(loc) -{ - this->ident = ident; -} - -Statement *BreakStatement::syntaxCopy() -{ - BreakStatement *s = new BreakStatement(loc, ident); - return s; -} - -Statement *BreakStatement::semantic(Scope *sc) -{ - if (ident) - { - Scope *scx; - FuncDeclaration *thisfunc = sc->func; - - for (scx = sc; scx; scx = scx->enclosing) - { - LabelStatement *ls; - - if (scx->func != thisfunc) // if in enclosing function - { - if (sc->fes) // if this is the body of a foreach - { - /* Post this statement to the fes, and replace - * it with a return value that caller will put into - * a switch. Caller will figure out where the break - * label actually is. - * Case numbers start with 2, not 0, as 0 is continue - * and 1 is break. - */ - Statement *s; - sc->fes->cases.push(this); - s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); - return s; - } - break; // can't break to it - } - - ls = scx->slabel; - if (ls && ls->ident == ident) - { - Statement *s = ls->statement; - - if (!s->hasBreak()) - error("label '%s' has no break", ident->toChars()); - if (ls->tf != sc->tf) - error("cannot break out of finally block"); - return this; - } - } - error("enclosing label '%s' for break not found", ident->toChars()); - } - else if (!sc->sbreak) - { - if (sc->fes) - { Statement *s; - - // Replace break; with return 1; - s = new ReturnStatement(0, new IntegerExp(1)); - return s; - } - error("break is not inside a loop or switch"); - } - return this; -} - -int BreakStatement::fallOffEnd() -{ - return FALSE; -} - -/******************************** ContinueStatement ***************************/ - -ContinueStatement::ContinueStatement(Loc loc, Identifier *ident) - : Statement(loc) -{ - this->ident = ident; -} - -Statement *ContinueStatement::syntaxCopy() -{ - ContinueStatement *s = new ContinueStatement(loc, ident); - return s; -} - -Statement *ContinueStatement::semantic(Scope *sc) -{ - if (ident) - { - Scope *scx; - FuncDeclaration *thisfunc = sc->func; - - for (scx = sc; scx; scx = scx->enclosing) - { - LabelStatement *ls; - - if (scx->func != thisfunc) // if in enclosing function - { - if (sc->fes) // if this is the body of a foreach - { - /* Post this statement to the fes, and replace - * it with a return value that caller will put into - * a switch. Caller will figure out where the break - * label actually is. - * Case numbers start with 2, not 0, as 0 is continue - * and 1 is break. - */ - Statement *s; - sc->fes->cases.push(this); - s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); - return s; - } - break; // can't continue to it - } - - ls = scx->slabel; - if (ls && ls->ident == ident) - { - Statement *s = ls->statement; - - if (!s->hasContinue()) - error("label '%s' has no continue", ident->toChars()); - if (ls->tf != sc->tf) - error("cannot continue out of finally block"); - return this; - } - } - error("enclosing label '%s' for continue not found", ident->toChars()); - } - else if (!sc->scontinue) - { - if (sc->fes) - { Statement *s; - - // Replace continue; with return 0; - s = new ReturnStatement(0, new IntegerExp(0)); - return s; - } - error("continue is not inside a loop"); - } - return this; -} - -int ContinueStatement::fallOffEnd() -{ - return FALSE; -} - -/******************************** SynchronizedStatement ***************************/ - -SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body) - : Statement(loc) -{ - this->exp = exp; - this->body = body; - this->esync = NULL; -} - -SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body) - : Statement(loc) -{ - this->exp = NULL; - this->body = body; - this->esync = esync; -} - -Statement *SynchronizedStatement::syntaxCopy() -{ - Expression *e = exp ? exp->syntaxCopy() : NULL; - SynchronizedStatement *s = new SynchronizedStatement(loc, e, body->syntaxCopy()); - return s; -} - -Statement *SynchronizedStatement::semantic(Scope *sc) -{ - if (exp) - { ClassDeclaration *cd; - - exp = exp->semantic(sc); - exp = resolveProperties(sc, exp); - cd = exp->type->isClassHandle(); - if (!cd) - error("can only synchronize on class objects, not '%s'", exp->type->toChars()); - if (cd->isInterfaceDeclaration()) - { Type *t = new TypeIdentifier(0, Id::Object); - - t = t->semantic(0, sc); - exp = new CastExp(loc, exp, t); - exp = exp->semantic(sc); - } - } - body = body->semantic(sc); - return this; -} - -int SynchronizedStatement::hasBreak() -{ - return FALSE; //TRUE; -} - -int SynchronizedStatement::hasContinue() -{ - return FALSE; //TRUE; -} - -int SynchronizedStatement::usesEH() -{ - return TRUE; -} - -int SynchronizedStatement::fallOffEnd() -{ - return body->fallOffEnd(); -} - -/******************************** WithStatement ***************************/ - -WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body) - : Statement(loc) -{ - this->exp = exp; - this->body = body; - wthis = NULL; -} - -Statement *WithStatement::syntaxCopy() -{ - WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body->syntaxCopy()); - return s; -} - -Statement *WithStatement::semantic(Scope *sc) -{ ScopeDsymbol *sym; - Initializer *init; - - exp = exp->semantic(sc); - if (exp->op == TOKimport) - { ScopeExp *es = (ScopeExp *)exp; - - sym = es->sds; - } - else - { Type *t = exp->type; - - assert(t); - t = t->toBasetype(); - if (t->isClassHandle()) - { - init = new ExpInitializer(loc, exp); - wthis = new VarDeclaration(loc, exp->type, Id::withSym, init); - wthis->semantic(sc); - - sym = new WithScopeSymbol(this); - sym->parent = sc->scopesym; - } - else if (t->ty == Tstruct) - { - Expression *e = exp->addressOf(); - init = new ExpInitializer(loc, e); - wthis = new VarDeclaration(loc, e->type, Id::withSym, init); - wthis->semantic(sc); - sym = new WithScopeSymbol(this); - sym->parent = sc->scopesym; - } - else - { error("with expressions must be class objects, not '%s'", exp->type->toChars()); - return NULL; - } - } - sc = sc->push(sym); - - body = body->semantic(sc); - - sc->pop(); - - return this; -} - -void WithStatement::toCBuffer(OutBuffer *buf) -{ - buf->writestring("with ("); - exp->toCBuffer(buf); - buf->writestring(")\n{\n"); - body->toCBuffer(buf); - buf->writestring("\n}\n"); -} - -int WithStatement::usesEH() -{ - return body->usesEH(); -} - -int WithStatement::fallOffEnd() -{ - return body->fallOffEnd(); -} - -/******************************** TryCatchStatement ***************************/ - -TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches) - : Statement(loc) -{ - this->body = body; - this->catches = catches; -} - -Statement *TryCatchStatement::syntaxCopy() -{ - Array *a = new Array(); - a->setDim(catches->dim); - for (int i = 0; i < a->dim; i++) - { Catch *c; - - c = (Catch *)catches->data[i]; - c = c->syntaxCopy(); - a->data[i] = c; - } - TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a); - return s; -} - -Statement *TryCatchStatement::semantic(Scope *sc) -{ - body = body->semanticScope(sc, NULL /*this*/, NULL); - - for (int i = 0; i < catches->dim; i++) - { Catch *c; - - c = (Catch *)catches->data[i]; - c->semantic(sc); - - // Determine if current catch 'hides' any previous catches - for (int j = 0; j < i; j++) - { Catch *cj = (Catch *)catches->data[j]; - char *si = c->loc.toChars(); - char *sj = cj->loc.toChars(); - - if (c->type->implicitConvTo(cj->type)) - error("catch at %s hides catch at %s", sj, si); - } - } - return this; -} - -int TryCatchStatement::hasBreak() -{ - return FALSE; //TRUE; -} - -int TryCatchStatement::usesEH() -{ - return TRUE; -} - -int TryCatchStatement::fallOffEnd() -{ - int result = FALSE; - - if (body) - result = body->fallOffEnd(); - for (int i = 0; i < catches->dim; i++) - { Catch *c; - - c = (Catch *)catches->data[i]; - if (c->handler) - result |= c->handler->fallOffEnd(); - } - return result; -} - -/******************************** Catch ***************************/ - -Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler) -{ - //printf("Catch(loc = %s)\n", loc.toChars()); - this->loc = loc; - this->type = t; - this->ident = id; - this->handler = handler; - var = NULL; -} - -Catch *Catch::syntaxCopy() -{ - Catch *c = new Catch(loc, - (type ? type->syntaxCopy() : NULL), - ident, - (handler ? handler->syntaxCopy() : NULL)); - return c; -} - -void Catch::semantic(Scope *sc) -{ ScopeDsymbol *sym; - - //printf("Catch::semantic()\n"); - -#ifndef IN_GCC - if (sc->tf) - { - /* This is because the _d_local_unwind() gets the stack munged - * up on this. The workaround is to place any try-catches into - * a separate function, and call that. - * To fix, have the compiler automatically convert the finally - * body into a nested function. - */ - error(loc, "cannot put catch statement inside finally block"); - } -#endif - - sym = new ScopeDsymbol(); - sym->parent = sc->scopesym; - sc = sc->push(sym); - - if (!type) - type = new TypeIdentifier(0, Id::Object); - type = type->semantic(loc, sc); - if (!type->isClassHandle()) - error("can only catch class objects, not '%s'", type->toChars()); - else if (ident) - { - var = new VarDeclaration(loc, type, ident, NULL); - var->parent = sc->parent; - sc->insert(var); - } - handler = handler->semantic(sc); - - sc->pop(); -} - -/******************************** TryFinallyStatement ***************************/ - -TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody) - : Statement(loc) -{ - this->body = body; - this->finalbody = finalbody; -} - -Statement *TryFinallyStatement::syntaxCopy() -{ - TryFinallyStatement *s = new TryFinallyStatement(loc, - body->syntaxCopy(), finalbody->syntaxCopy()); - return s; -} - -Statement *TryFinallyStatement::semantic(Scope *sc) -{ - body = body->semantic(sc); - sc = sc->push(); - sc->tf = this; - sc->sbreak = NULL; - sc->scontinue = NULL; // no break or continue out of finally block - finalbody = finalbody->semantic(sc); - sc->pop(); - return this; -} - -void TryFinallyStatement::toCBuffer(OutBuffer *buf) -{ - buf->printf("try\n{\n"); - body->toCBuffer(buf); - buf->printf("}\nfinally\n{\n"); - finalbody->toCBuffer(buf); - buf->writeByte('}'); - buf->writenl(); -} - -int TryFinallyStatement::hasBreak() -{ - return FALSE; //TRUE; -} - -int TryFinallyStatement::hasContinue() -{ - return FALSE; //TRUE; -} - -int TryFinallyStatement::usesEH() -{ - return TRUE; -} - -int TryFinallyStatement::fallOffEnd() -{ int result; - - result = body->fallOffEnd(); - if (finalbody) - result = finalbody->fallOffEnd(); - return result; -} - -/******************************** ThrowStatement ***************************/ - -ThrowStatement::ThrowStatement(Loc loc, Expression *exp) - : Statement(loc) -{ - this->exp = exp; -} - -Statement *ThrowStatement::syntaxCopy() -{ - ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy()); - return s; -} - -Statement *ThrowStatement::semantic(Scope *sc) -{ - //printf("ThrowStatement::semantic()\n"); - if (sc->incontract) - error("Throw statements cannot be in contracts"); - exp = exp->semantic(sc); - exp = resolveProperties(sc, exp); - if (!exp->type->toBasetype()->isClassHandle()) - error("can only throw class objects, not type %s", exp->type->toChars()); - return this; -} - -int ThrowStatement::fallOffEnd() -{ - return FALSE; -} - -void ThrowStatement::toCBuffer(OutBuffer *buf) -{ - buf->printf("throw "); - exp->toCBuffer(buf); - buf->writeByte(';'); - buf->writenl(); -} - -/******************************** VolatileStatement **************************/ - -VolatileStatement::VolatileStatement(Loc loc, Statement *statement) - : Statement(loc) -{ - this->statement = statement; -} - -Statement *VolatileStatement::syntaxCopy() -{ - VolatileStatement *s = new VolatileStatement(loc, statement); - return s; -} - -Statement *VolatileStatement::semantic(Scope *sc) -{ - statement = statement->semantic(sc); - return this; -} - -Array *VolatileStatement::flatten() -{ - Array *a; - - a = statement->flatten(); - if (a) - { for (int i = 0; i < a->dim; i++) - { Statement *s = (Statement *)a->data[i]; - - s = new VolatileStatement(loc, s); - a->data[i] = s; - } - } - - return a; -} - -int VolatileStatement::fallOffEnd() -{ - return statement->fallOffEnd(); -} - - - -/******************************** GotoStatement ***************************/ - -GotoStatement::GotoStatement(Loc loc, Identifier *ident) - : Statement(loc) -{ - this->ident = ident; - this->label = NULL; - this->tf = NULL; -} - -Statement *GotoStatement::syntaxCopy() -{ - GotoStatement *s = new GotoStatement(loc, ident); - return s; -} - -Statement *GotoStatement::semantic(Scope *sc) -{ FuncDeclaration *fd = sc->parent->isFuncDeclaration(); - - //printf("GotoStatement::semantic()\n"); - tf = sc->tf; - label = fd->searchLabel(ident); - if (!label->statement && sc->fes) - { - /* Either the goto label is forward referenced or it - * is in the function that the enclosing foreach is in. - * Can't know yet, so wrap the goto in a compound statement - * so we can patch it later, and add it to a 'look at this later' - * list. - */ - Array *a = new Array(); - Statement *s; - - a->push(this); - s = new CompoundStatement(loc, a); - sc->fes->gotos.push(s); // 'look at this later' list - return s; - } - if (label->statement && label->statement->tf != sc->tf) - error("cannot goto in or out of finally block"); - return this; -} - -int GotoStatement::fallOffEnd() -{ - return FALSE; -} - -/******************************** LabelStatement ***************************/ - -LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) - : Statement(loc) -{ - this->ident = ident; - this->statement = statement; - this->tf = NULL; - this->lblock = NULL; - this->isReturnLabel = 0; -} - -Statement *LabelStatement::syntaxCopy() -{ - LabelStatement *s = new LabelStatement(loc, ident, statement->syntaxCopy()); - return s; -} - -Statement *LabelStatement::semantic(Scope *sc) -{ LabelDsymbol *ls; - FuncDeclaration *fd = sc->parent->isFuncDeclaration(); - - //printf("LabelStatement::semantic()\n"); - ls = fd->searchLabel(ident); - if (ls->statement) - error("Label '%s' already defined", ls->toChars()); - else - ls->statement = this; - tf = sc->tf; - sc = sc->push(); - sc->scopesym = sc->enclosing->scopesym; - sc->callSuper |= CSXlabel; - sc->slabel = this; - statement = statement->semantic(sc); - sc->pop(); - return this; -} - -Array *LabelStatement::flatten() -{ - Array *a; - - a = statement->flatten(); - if (a) - { - if (!a->dim) - { - a->push(new ExpStatement(loc, NULL)); - } - Statement *s = (Statement *)a->data[0]; - - s = new LabelStatement(loc, ident, s); - a->data[0] = s; - } - - return a; -} - - -int LabelStatement::usesEH() -{ - return statement->usesEH(); -} - -int LabelStatement::fallOffEnd() -{ - return statement ? statement->fallOffEnd() : TRUE; -} - -int LabelStatement::comeFrom() -{ - return TRUE; -} - - -/******************************** LabelDsymbol ***************************/ - -LabelDsymbol::LabelDsymbol(Identifier *ident) - : Dsymbol(ident) -{ - statement = NULL; - asmLabelNum = 0; -} - -LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? -{ - return this; -} - - diff -uNr gdc-0.11/d/root/statement.h gdc-0.12/d/root/statement.h --- gdc-0.11/d/root/statement.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/statement.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,627 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#ifndef DMD_STATEMENT_H -#define DMD_STATEMENT_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" - -#include "dsymbol.h" - -struct OutBuffer; -struct Scope; -struct Expression; -struct LabelDsymbol; -struct Identifier; -struct DeclarationStatement; -struct DefaultStatement; -struct VarDeclaration; -struct Condition; -struct Module; -struct Token; -struct InlineCostState; -struct InlineDoState; -struct InlineScanState; -struct ReturnStatement; -struct CompoundStatement; -struct Argument; -struct StaticAssert; - -// Back end -struct IRState; -struct Blockx; -union tree_node; typedef union tree_node block; -union tree_node; typedef union tree_node elem; -struct code; - -struct Statement : Object -{ - Loc loc; - - Statement(Loc loc); - virtual Statement *syntaxCopy(); - - void print(); - char *toChars(); - - void error(const char *format, ...); - virtual void toCBuffer(OutBuffer *buf); - virtual Statement *semantic(Scope *sc); - Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue); - virtual int hasBreak(); - virtual int hasContinue(); - virtual int usesEH(); - virtual int fallOffEnd(); - virtual int comeFrom(); - virtual Statement *callAutoDtor(); - virtual Array *flatten(); - - virtual int inlineCost(InlineCostState *ics); - virtual Expression *doInline(InlineDoState *ids); - virtual Statement *inlineScan(InlineScanState *iss); - - // Back end - virtual void toIR(IRState *irs); - - // Avoid dynamic_cast - virtual DeclarationStatement *isDeclarationStatement() { return NULL; } - virtual CompoundStatement *isCompoundStatement() { return NULL; } - virtual ReturnStatement *isReturnStatement() { return NULL; } -}; - -struct ExpStatement : Statement -{ - Expression *exp; - - ExpStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf); - Statement *semantic(Scope *sc); - int fallOffEnd(); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct DeclarationStatement : ExpStatement -{ - // Doing declarations as an expression, rather than a statement, - // makes inlining functions much easier. - - DeclarationStatement(Loc loc, Dsymbol *s); - DeclarationStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf); - Statement *callAutoDtor(); - - DeclarationStatement *isDeclarationStatement() { return this; } -}; - -struct CompoundStatement : Statement -{ - Array *statements; - - CompoundStatement(Loc loc, Array *s); - CompoundStatement(Loc loc, Statement *s1, Statement *s2); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf); - Statement *semantic(Scope *sc); - int usesEH(); - int fallOffEnd(); - Array *flatten(); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); - - CompoundStatement *isCompoundStatement() { return this; } -}; - -#if 0 -// Same as CompoundStatement, but introduces a new scope - -struct BlockStatement : CompoundStatement -{ - BlockStatement(Loc loc, Array *s); - BlockStatement(Loc loc, Statement *s1, Statement *s2); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf); - Statement *semantic(Scope *sc); - - void toIR(IRState *irs); -}; -#endif - -struct ScopeStatement : Statement -{ - Statement *statement; - - ScopeStatement(Loc loc, Statement *s); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf); - Statement *semantic(Scope *sc); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct WhileStatement : Statement -{ - Expression *condition; - Statement *body; - - WhileStatement(Loc loc, Expression *c, Statement *b); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct DoStatement : Statement -{ - Statement *body; - Expression *condition; - - DoStatement(Loc loc, Statement *b, Expression *c); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct ForStatement : Statement -{ - Statement *init; - Expression *condition; - Expression *increment; - Statement *body; - - ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct ForeachStatement : Statement -{ - Array *arguments; // array of Argument*'s - Expression *aggr; - Statement *body; - - VarDeclaration *key; - VarDeclaration *value; - - Array cases; // put breaks, continues, gotos and returns here - Array gotos; // forward referenced goto's go here - - ForeachStatement(Loc loc, Array *arguments, Expression *aggr, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct IfStatement : Statement -{ - Expression *condition; - Statement *ifbody; - Statement *elsebody; - - IfStatement(Loc loc, Expression *condition, Statement *ifbody, Statement *elsebody); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - int usesEH(); - int fallOffEnd(); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct ConditionalStatement : Statement -{ - Condition *condition; - Statement *ifbody; - Statement *elsebody; - - ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int usesEH(); - - void toCBuffer(OutBuffer *buf); -}; - -struct PragmaStatement : Statement -{ - Identifier *ident; - Array *args; // array of Expression's - Statement *body; - - PragmaStatement(Loc loc, Identifier *ident, Array *args, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int usesEH(); - int fallOffEnd(); - - void toCBuffer(OutBuffer *buf); -}; - -struct StaticAssertStatement : Statement -{ - StaticAssert *sa; - - StaticAssertStatement(StaticAssert *sa); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - - void toCBuffer(OutBuffer *buf); -}; - -struct SwitchStatement : Statement -{ - Expression *condition; - Statement *body; - DefaultStatement *sdefault; - - Array gotoCases; // array of unresolved GotoCaseStatement's - Array *cases; // array of CaseStatement's - - SwitchStatement(Loc loc, Expression *c, Statement *b); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int usesEH(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct CaseStatement : Statement -{ - Expression *exp; - Statement *statement; - int index; // which case it is (since we sort this) - block *cblock; // back end: label for the block - - CaseStatement(Loc loc, Expression *exp, Statement *s); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int compare(Object *obj); - int usesEH(); - int fallOffEnd(); - int comeFrom(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct DefaultStatement : Statement -{ - Statement *statement; - block *cblock; // back end: label for the block - - DefaultStatement(Loc loc, Statement *s); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int usesEH(); - int fallOffEnd(); - int comeFrom(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct GotoDefaultStatement : Statement -{ - SwitchStatement *sw; - - GotoDefaultStatement(Loc loc); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int fallOffEnd(); - - void toIR(IRState *irs); -}; - -struct GotoCaseStatement : Statement -{ - Expression *exp; // NULL, or which case to goto - CaseStatement *cs; // case statement it resolves to - - GotoCaseStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int fallOffEnd(); - - void toIR(IRState *irs); -}; - -struct SwitchErrorStatement : Statement -{ - SwitchErrorStatement(Loc loc); - int fallOffEnd(); - - void toIR(IRState *irs); -}; - -struct ReturnStatement : Statement -{ - Expression *exp; - - ReturnStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf); - Statement *semantic(Scope *sc); - int fallOffEnd(); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); - - ReturnStatement *isReturnStatement() { return this; } -}; - -struct BreakStatement : Statement -{ - Identifier *ident; - - BreakStatement(Loc loc, Identifier *ident); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int fallOffEnd(); - - void toIR(IRState *irs); -}; - -struct ContinueStatement : Statement -{ - Identifier *ident; - - ContinueStatement(Loc loc, Identifier *ident); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int fallOffEnd(); - - void toIR(IRState *irs); -}; - -struct SynchronizedStatement : Statement -{ - Expression *exp; - Statement *body; - - SynchronizedStatement(Loc loc, Expression *exp, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - -// Back end - elem *esync; - SynchronizedStatement(Loc loc, elem *esync, Statement *body); - void toIR(IRState *irs); -}; - -struct WithStatement : Statement -{ - Expression *exp; - Statement *body; - VarDeclaration *wthis; - - WithStatement(Loc loc, Expression *exp, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - int usesEH(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct TryCatchStatement : Statement -{ - Statement *body; - Array *catches; - - TryCatchStatement(Loc loc, Statement *body, Array *catches); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int usesEH(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct Catch : Object -{ - Loc loc; - Type *type; - Identifier *ident; - VarDeclaration *var; - Statement *handler; - - Catch(Loc loc, Type *t, Identifier *id, Statement *handler); - Catch *syntaxCopy(); - void semantic(Scope *sc); -}; - -struct TryFinallyStatement : Statement -{ - Statement *body; - Statement *finalbody; - - TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct ThrowStatement : Statement -{ - Expression *exp; - - ThrowStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct VolatileStatement : Statement -{ - Statement *statement; - - VolatileStatement(Loc loc, Statement *statement); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Array *flatten(); - int fallOffEnd(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct GotoStatement : Statement -{ - Identifier *ident; - LabelDsymbol *label; - TryFinallyStatement *tf; - - GotoStatement(Loc loc, Identifier *ident); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int fallOffEnd(); - - void toIR(IRState *irs); -}; - -struct LabelStatement : Statement -{ - Identifier *ident; - Statement *statement; - TryFinallyStatement *tf; - block *lblock; // back end - int isReturnLabel; - - LabelStatement(Loc loc, Identifier *ident, Statement *statement); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Array *flatten(); - int usesEH(); - int fallOffEnd(); - int comeFrom(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct LabelDsymbol : Dsymbol -{ - LabelStatement *statement; - unsigned asmLabelNum; // GCC-specific - - LabelDsymbol(Identifier *ident); - LabelDsymbol *isLabel(); -}; - -struct AsmStatement : Statement -{ - Token *tokens; - code *asmcode; - unsigned asmalign; // alignment of this statement - unsigned refparam; // !=0 if function parameter is referenced - unsigned naked; // !=0 if function is to be naked - unsigned regs; // mask of registers modified - - AsmStatement(Loc loc, Token *tokens); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int comeFrom(); - - void toCBuffer(OutBuffer *buf); - - void toIR(IRState *irs); -}; - -#endif /* DMD_STATEMENT_H */ diff -uNr gdc-0.11/d/root/staticassert.c gdc-0.12/d/root/staticassert.c --- gdc-0.11/d/root/staticassert.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/staticassert.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,74 +0,0 @@ - -// Copyright (c) 1999-2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "dsymbol.h" -#include "staticassert.h" -#include "expression.h" -#include "id.h" - -/********************************* AttribDeclaration ****************************/ - -StaticAssert::StaticAssert(Loc loc, Expression *exp) - : Dsymbol(Id::empty) -{ - this->loc = loc; - this->exp = exp; -} - -Dsymbol *StaticAssert::syntaxCopy(Dsymbol *s) -{ - StaticAssert *sa; - - assert(!s); - sa = new StaticAssert(loc, exp->syntaxCopy()); - return sa; -} - -void StaticAssert::addMember(ScopeDsymbol *sd) -{ -} - -void StaticAssert::semantic(Scope *sc) -{ -} - -void StaticAssert::semantic2(Scope *sc) -{ - Expression *e; - - e = exp->semantic(sc); - e = e->constFold(); - if (e->isBool(FALSE)) - error("(%s) is false", exp->toChars()); -} - -void StaticAssert::inlineScan() -{ -} - -void StaticAssert::toObjFile() -{ -} - -char *StaticAssert::kind() -{ - return "static assert"; -} - -void StaticAssert::toCBuffer(OutBuffer *buf) -{ - buf->writestring(kind()); - buf->writeByte('('); - exp->toCBuffer(buf); - buf->writestring(");"); - buf->writenl(); -} diff -uNr gdc-0.11/d/root/staticassert.h gdc-0.12/d/root/staticassert.h --- gdc-0.11/d/root/staticassert.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/staticassert.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,37 +0,0 @@ - -// Copyright (c) 1999-2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_STATICASSERT_H -#define DMD_STATICASSERT_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "dsymbol.h" - -struct Expression; - -struct StaticAssert : Dsymbol -{ - Expression *exp; - - StaticAssert(Loc loc, Expression *exp); - - Dsymbol *syntaxCopy(Dsymbol *s); - void addMember(ScopeDsymbol *sd); - void semantic(Scope *sc); - void semantic2(Scope *sc); - void inlineScan(); - void toObjFile(); - char *kind(); - void toCBuffer(OutBuffer *buf); -}; - -#endif diff -uNr gdc-0.11/d/root/stringtable.c gdc-0.12/d/root/stringtable.c --- gdc-0.11/d/root/stringtable.c 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/stringtable.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,138 +0,0 @@ -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#include -#include -#include - -#include "root.h" -#include "mem.h" -#include "dchar.h" -#include "lstring.h" -#include "stringtable.h" - -StringTable::StringTable(unsigned size) -{ - table = (void **)mem.calloc(size, sizeof(void *)); - tabledim = size; - count = 0; -} - -StringTable::~StringTable() -{ - unsigned i; - - // Zero out dangling pointers to help garbage collector. - // Should zero out StringEntry's too. - for (i = 0; i < count; i++) - table[i] = NULL; - - mem.free(table); - table = NULL; -} - -struct StringEntry -{ - StringEntry *left; - StringEntry *right; - unsigned hash; - - StringValue value; - - static StringEntry *alloc(const dchar *s, unsigned len); -}; - -StringEntry *StringEntry::alloc(const dchar *s, unsigned len) -{ - StringEntry *se; - - se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len)); - se->value.lstring.length = len; - se->hash = Dchar::calcHash(s,len); - memcpy(se->value.lstring.string, s, len * sizeof(dchar)); - return se; -} - -void **StringTable::search(const dchar *s, unsigned len) -{ - unsigned hash; - unsigned u; - int cmp; - StringEntry **se; - - //printf("StringTable::search(%p,%d)\n",s,len); - hash = Dchar::calcHash(s,len); - u = hash % tabledim; - se = (StringEntry **)&table[u]; - //printf("\thash = %d, u = %d\n",hash,u); - while (*se) - { - cmp = (*se)->hash - hash; - if (cmp == 0) - { - cmp = (*se)->value.lstring.len() - len; - if (cmp == 0) - { - cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len); - if (cmp == 0) - break; - } - } - if (cmp < 0) - se = &(*se)->left; - else - se = &(*se)->right; - } - //printf("\treturn %p, %p\n",se, (*se)); - return (void **)se; -} - -StringValue *StringTable::lookup(const dchar *s, unsigned len) -{ StringEntry *se; - - se = *(StringEntry **)search(s,len); - if (se) - return &se->value; - else - return NULL; -} - -StringValue *StringTable::update(const dchar *s, unsigned len) -{ StringEntry **pse; - StringEntry *se; - - pse = (StringEntry **)search(s,len); - se = *pse; - if (!se) // not in table: so create new entry - { - se = StringEntry::alloc(s, len); - *pse = se; - } - return &se->value; -} - -StringValue *StringTable::insert(const dchar *s, unsigned len) -{ StringEntry **pse; - StringEntry *se; - - pse = (StringEntry **)search(s,len); - se = *pse; - if (se) - return NULL; // error: already in table - else - { - se = StringEntry::alloc(s, len); - *pse = se; - } - return &se->value; -} - - - - diff -uNr gdc-0.11/d/root/stringtable.h gdc-0.12/d/root/stringtable.h --- gdc-0.11/d/root/stringtable.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/stringtable.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,48 +0,0 @@ -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#ifndef STRINGTABLE_H -#define STRINGTABLE_H - -#if __SC__ -#pragma once -#endif - -#include "root.h" -#include "dchar.h" -#include "lstring.h" - -struct StringValue -{ - union - { int intvalue; - void *ptrvalue; - dchar *string; - }; - Lstring lstring; -}; - -struct StringTable : Object -{ - void **table; - unsigned count; - unsigned tabledim; - - StringTable(unsigned size = 37); - ~StringTable(); - - StringValue *lookup(const dchar *s, unsigned len); - StringValue *insert(const dchar *s, unsigned len); - StringValue *update(const dchar *s, unsigned len); - -private: - void **search(const dchar *s, unsigned len); -}; - -#endif diff -uNr gdc-0.11/d/root/struct.c gdc-0.12/d/root/struct.c --- gdc-0.11/d/root/struct.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/struct.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,448 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "root.h" -#include "aggregate.h" -#include "scope.h" -#include "mtype.h" -#include "declaration.h" -#include "module.h" -#include "id.h" -#include "statement.h" - -/********************************* AggregateDeclaration ****************************/ - -AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) - : ScopeDsymbol(id) -{ - this->loc = loc; - - type = NULL; - handle = NULL; - structsize = 0; // size of struct - alignsize = 0; // size of struct for alignment purposes - structalign = 0; // struct member alignment in effect - sizeok = 0; // size not determined yet - isdeprecated = 0; - inv = NULL; - aggNew = NULL; - aggDelete = NULL; - - stag = NULL; - sinit = NULL; - scope = NULL; -} - -void AggregateDeclaration::semantic2(Scope *sc) -{ int i; - - //printf("AggregateDeclaration::semantic2(%s)\n", toChars()); - if (members) - { - sc = sc->push(this); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic2(sc); - } - sc->pop(); - } -} - -void AggregateDeclaration::semantic3(Scope *sc) -{ int i; - - //printf("AggregateDeclaration::semantic3(%s)\n", toChars()); - if (members) - { - sc = sc->push(this); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic3(sc); - } - sc->pop(); - } -} - -void AggregateDeclaration::inlineScan() -{ int i; - - //printf("AggregateDeclaration::inlineScan(%s)\n", toChars()); - if (members) - { - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - //printf("inline scan aggregate symbol '%s'\n", s->toChars()); - s->inlineScan(); - } - } -} - -unsigned AggregateDeclaration::size(Loc loc) -{ - //printf("AggregateDeclaration::size() = %d\n", structsize); - if (!members) - error(loc, "unknown size"); - if (sizeok != 1) - { error(loc, "no size yet for forward reference"); - //*(char*)0=0; - } - return structsize; -} - -Type *AggregateDeclaration::getType() -{ - return type; -} - -int AggregateDeclaration::isDeprecated() -{ - return isdeprecated; -} - -/**************************** - * Do byte or word alignment as necessary. - * Align sizes of 0, as we may not know array sizes yet. - */ - -void AggregateDeclaration::alignmember(unsigned salign, unsigned size, unsigned *poffset) -{ - //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset); - if (salign > 1) - { int sa; - - switch (size) - { case 1: - break; - case 2: - case_2: - *poffset = (*poffset + 1) & ~1; // align to word - break; - case 3: - case 4: - if (salign == 2) - goto case_2; - *poffset = (*poffset + 3) & ~3; // align to dword - break; - default: - *poffset = (*poffset + salign - 1) & ~(salign - 1); - break; - } - } - //printf("result = %d\n",offset); -} - - -void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) -{ - unsigned memsize; // size of member - unsigned memalignsize; // size of member for alignment purposes - unsigned xalign; // alignment boundaries - - //printf("AggregateDeclaration::addField('%s')\n", v->toChars()); - - // Check for forward referenced types which will fail the size() call - Type *t = v->type->toBasetype(); - if (t->ty == Tstruct /*&& isStructDeclaration()*/) - { TypeStruct *ts = (TypeStruct *)t; - - if (ts->sym->sizeok != 1) - { - sizeok = 2; // cannot finish; flag as forward referenced - return; - } - } - - memsize = v->type->size(loc); - memalignsize = v->type->alignsize(); - xalign = v->type->memalign(sc->structalign); - alignmember(xalign, memalignsize, &sc->offset); - v->offset = sc->offset; - sc->offset += memsize; - if (sc->offset > structsize) - structsize = sc->offset; - if (sc->structalign < memalignsize) - memalignsize = sc->structalign; - if (alignsize < memalignsize) - alignsize = memalignsize; - //printf("\talignsize = %d\n", alignsize); - - v->storage_class |= STCfield; - //printf(" addField '%s' to '%s' at offset %d\n", v->toChars(), toChars(), v->offset); - fields.push(v); -} - - -/********************************* StructDeclaration ****************************/ - -StructDeclaration::StructDeclaration(Loc loc, Identifier *id) - : AggregateDeclaration(loc, id) -{ - zeroInit = 0; // assume false until we do semantic processing - - // For forward references - type = new TypeStruct(this); -} - -Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s) -{ - StructDeclaration *sd; - - if (s) - sd = (StructDeclaration *)s; - else - sd = new StructDeclaration(loc, ident); - ScopeDsymbol::syntaxCopy(sd); - return sd; -} - -void StructDeclaration::semantic(Scope *sc) -{ int i; - Scope *sc2; - - //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); - assert(type); - if (!members) // if forward reference - return; - - if (symtab) - { if (!scope) - return; // semantic() already completed - } - else - symtab = new DsymbolTable(); - - Scope *scx = NULL; - if (scope) - { sc = scope; - scx = scope; // save so we don't make redundant copies - scope = NULL; - } - - parent = sc->parent; - handle = type->pointerTo(); - structalign = sc->structalign; - assert(!isAnonymous()); - if (sc->stc & STCabstract) - error("structs, unions cannot be abstract"); - - if (sizeok == 0) // if not already done the addMember step - { - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); - s->addMember(this); - } - } - - sizeok = 0; - sc2 = sc->push(this); - sc2->parent = this; - if (isUnionDeclaration()) - sc2->inunion = 1; - sc2->stc = 0; - int members_dim = members->dim; - for (i = 0; i < members_dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic(sc2); - if (isUnionDeclaration()) - sc2->offset = 0; - if (sizeok == 2) - break; - } - - /* The TypeInfo_Struct is expecting an opEquals and opCmp with - * a parameter that is a pointer to the struct. But if there - * isn't one, but is an opEquals or opCmp with a value, write - * another that is a shell around the value: - * int opCmp(struct *p) { return opCmp(*p); } - */ - - TypeFunction *tfeqptr; - { - Array *arguments = new Array; - Argument *arg = new Argument(In, handle, Id::p, NULL); - - arguments->push(arg); - tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc); - } - - TypeFunction *tfeq; - { - Array *arguments = new Array; - Argument *arg = new Argument(In, type, NULL, NULL); - - arguments->push(arg); - tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeq = (TypeFunction *)tfeq->semantic(0, sc); - } - - Identifier *id = Id::eq; - for (int i = 0; i < 2; i++) - { - FuncDeclaration *fdx = search_function(this, id); - if (fdx) - { FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr); - if (!fd) - { fd = fdx->overloadExactMatch(tfeq); - if (fd) - { // Create the thunk, fdptr - FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr); - Expression *e = new IdentifierExp(loc, Id::p); - e = new PtrExp(loc, e); - Array *args = new Array(); - args->push(e); - e = new IdentifierExp(loc, id); - e = new CallExp(loc, e, args); - fdptr->fbody = new ReturnStatement(loc, e); - members->push(fdptr); - fdptr->addMember(this); - fdptr->semantic(sc2); - } - } - } - - id = Id::cmp; - } - - - sc2->pop(); - - if (sizeok == 2) - { // semantic() failed because of forward references. - // Unwind what we did, and defer it for later - fields.setDim(0); - structsize = 0; - alignsize = 0; - structalign = 0; - - scope = scx ? scx : new Scope(*sc); - scope->setNoFree(); - scope->module->addDeferredSemantic(this); - return; - } - - // 0 sized struct's are set to 1 byte - if (structsize == 0) - { - structsize = 1; - alignsize = 1; - } - - // Round struct size up to next alignsize boundary. - // This will ensure that arrays of structs will get their internals - // aligned properly. - structsize = (structsize + alignsize - 1) & ~(alignsize - 1); - - sizeok = 1; - - //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); - - // Determine if struct is all zeros or not - zeroInit = 1; - for (i = 0; i < fields.dim; i++) - { - Dsymbol *s = (Dsymbol *)fields.data[i]; - VarDeclaration *vd = s->isVarDeclaration(); - if (vd) - { - if (vd->init) - { - // Should examine init to see if it is really all 0's - zeroInit = 0; - break; - } - else - { - if (!vd->type->isZeroInit()) - { - zeroInit = 0; - break; - } - } - } - } - - /* Look for special member functions. - */ - inv = (InvariantDeclaration *)search(Id::classInvariant, 0); - aggNew = (NewDeclaration *)search(Id::classNew, 0); - aggDelete = (DeleteDeclaration *)search(Id::classDelete, 0); - - if (sc->func) - { - semantic2(sc); - semantic3(sc); - } -} - -void StructDeclaration::toCBuffer(OutBuffer *buf) -{ int i; - - buf->printf("%s %s", kind(), toChars()); - if (!members) - { - buf->writeByte(';'); - buf->writenl(); - return; - } - buf->writenl(); - buf->writeByte('{'); - buf->writenl(); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - - buf->writestring(" "); - s->toCBuffer(buf); - } - buf->writeByte('}'); - buf->writenl(); -} - - -char *StructDeclaration::kind() -{ - return "struct"; -} - -/********************************* UnionDeclaration ****************************/ - -UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id) - : StructDeclaration(loc, id) -{ -} - -Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s) -{ - UnionDeclaration *ud; - - if (s) - ud = (UnionDeclaration *)s; - else - ud = new UnionDeclaration(loc, ident); - StructDeclaration::syntaxCopy(ud); - return ud; -} - - -char *UnionDeclaration::kind() -{ - return "union"; -} - - diff -uNr gdc-0.11/d/root/template.c gdc-0.12/d/root/template.c --- gdc-0.11/d/root/template.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/template.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,2346 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -// Handle template implementation - -#include -#include - -#include "root.h" -#include "mem.h" -#include "stringtable.h" - -#include "mtype.h" -#include "template.h" -#include "init.h" -#include "expression.h" -#include "scope.h" -#include "module.h" -#include "aggregate.h" -#include "declaration.h" -#include "dsymbol.h" -#include "mars.h" -#include "dsymbol.h" -#include "identifier.h" - -#define LOG 0 - -/******************************************** - * These functions substitute for dynamic_cast. dynamic_cast does not work - * on earlier versions of gcc. - */ - -static Expression *isExpression(Object *o) -{ - //return dynamic_cast(o); - if (!o || o->dyncast() != DYNCAST_EXPRESSION) - return NULL; - return (Expression *)o; -} - -static Dsymbol *isDsymbol(Object *o) -{ - //return dynamic_cast(o); - if (!o || o->dyncast() != DYNCAST_DSYMBOL) - return NULL; - return (Dsymbol *)o; -} - -static Type *isType(Object *o) -{ - //return dynamic_cast(o); - if (!o || o->dyncast() != DYNCAST_TYPE) - return NULL; - return (Type *)o; -} - -/* ======================== TemplateDeclaration ============================= */ - -TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, Array *parameters, Array *decldefs) - : ScopeDsymbol(id) -{ -#if LOG - printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id->toChars()); -#endif -#if 0 - if (parameters) - for (int i = 0; i < parameters->dim; i++) - { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; - TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); - - if (ttp) - { - printf("\tparameter[%d] = %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : ""); - } - } -#endif - this->loc = loc; - this->parameters = parameters; - this->members = decldefs; - this->overnext = NULL; - this->scope = NULL; -} - -Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *) -{ - TemplateDeclaration *td; - Array *p; - Array *d; - - p = NULL; - if (parameters) - { - p = new Array(); - p->setDim(parameters->dim); - for (int i = 0; i < p->dim; i++) - { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; - p->data[i] = (void *)tp->syntaxCopy(); - } - } - d = Dsymbol::arraySyntaxCopy(members); - td = new TemplateDeclaration(loc, ident, p, d); - return td; -} - -void TemplateDeclaration::semantic(Scope *sc) -{ -#if LOG - printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars()); -#endif - if (scope) - return; // semantic() already run - - if (sc->func) - { - error("cannot declare template at function scope %s", sc->func->toChars()); - } - - if (global.params.useArrayBounds && sc->module) - { - // Generate this function as it may be used - // when template is instantiated in other modules - sc->module->toModuleArray(); - } - - if (global.params.useAssert && sc->module) - { - // Generate this function as it may be used - // when template is instantiated in other modules - sc->module->toModuleAssert(); - } - - /* Remember Scope for later instantiations, but make - * a copy since attributes can change. - */ - this->scope = new Scope(*sc); - this->scope->setNoFree(); - - // Set up scope for parameters - ScopeDsymbol *paramsym = new ScopeDsymbol(); - paramsym->parent = sc->parent; - Scope *paramscope = sc->push(paramsym); - - for (int i = 0; i < parameters->dim; i++) - { - TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; - - tp->semantic(paramscope); - } - - paramscope->pop(); - - /* BUG: should check: - * o no virtual functions or non-static data members of classes - */ -} - -char *TemplateDeclaration::kind() -{ - return "template"; -} - -/********************************** - * Overload existing TemplateDeclaration 'this' with the new one 's'. - * Return !=0 if successful; i.e. no conflict. - */ - -int TemplateDeclaration::overloadInsert(Dsymbol *s) -{ - TemplateDeclaration **pf; - TemplateDeclaration *f; - -#if LOG - printf("TemplateDeclaration::overloadInsert('%s')\n", s->toChars()); -#endif - f = s->isTemplateDeclaration(); - if (!f) - return FALSE; - TemplateDeclaration *pthis = this; - for (pf = &pthis; *pf; pf = &(*pf)->overnext) - { - // Conflict if TemplateParameter's match - // Will get caught anyway later with TemplateInstance, but - // should check it now. - TemplateDeclaration *f2 = *pf; - - if (f->parameters->dim != f2->parameters->dim) - goto Lcontinue; - - for (int i = 0; i < f->parameters->dim; i++) - { TemplateParameter *p1 = (TemplateParameter *)f->parameters->data[i]; - TemplateParameter *p2 = (TemplateParameter *)f2->parameters->data[i]; - - if (!p1->overloadMatch(p2)) - goto Lcontinue; - } - -#if LOG - printf("\tfalse: conflict\n"); -#endif - return FALSE; - - Lcontinue: - ; - } - - - *pf = f; -#if LOG - printf("\ttrue: no conflict\n"); -#endif - return TRUE; -} - -/*************************************** - * Given that ti is an instance of this TemplateDeclaration, - * deduce the types of the parameters to this, and store - * those deduced types in dedtypes[]. - * Input: - * flag 1: don't do semantic() because of dummy types - * Return match level. - */ - -MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, - Array *dedtypes, int flag) -{ MATCH m; - int dim = dedtypes->dim; - -#if LOG - printf("+TemplateDeclaration::matchWithInstance(this = %p, ti = %p)\n", this, ti); -#endif - dedtypes->zero(); - - -//printf("TemplateDeclaration::matchWithInstance(this = %p, ti = %p)\n", this, ti); -//printf("dim = %d, parameters->dim = %d\n", dim, parameters->dim); -//if (ti->tiargs->dim) -//printf("ti->tiargs->dim = %d, [0] = %p\n", ti->tiargs->dim, ti->tiargs->data[0]); - - assert(dim == parameters->dim); - assert(dim >= ti->tiargs->dim); - - // Set up scope for parameters - assert(scope); - ScopeDsymbol *paramsym = new ScopeDsymbol(); - paramsym->parent = scope->parent; - Scope *paramscope = scope->push(paramsym); - - // Attempt type deduction - m = MATCHexact; - for (int i = 0; i < dim; i++) - { MATCH m2; - TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; - Object *oarg; - Declaration *sparam; - - if (i < ti->tiargs->dim) - oarg = (Object *)ti->tiargs->data[i]; - else - { // Look for default argument instead - oarg = tp->defaultArg(paramscope); - if (!oarg) - goto Lnomatch; - } -#if 0 - printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null"); - TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); - if (ttp) - printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : ""); -#endif - - m2 = tp->matchArg(paramscope, oarg, i, parameters, dedtypes, &sparam); - if (m2 == MATCHnomatch) - { //printf("\tmatchArg() for parameter %i failed\n", i); - goto Lnomatch; - } - - if (m2 < m) - m = m2; - - if (!flag) - sparam->semantic(paramscope); - if (!paramscope->insert(sparam)) - goto Lnomatch; - } - - if (!flag) - { - // Any parameter left without a type gets the type of its corresponding arg - for (int i = 0; i < dim; i++) - { - if (!dedtypes->data[i]) - { assert(i < ti->tiargs->dim); - dedtypes->data[i] = ti->tiargs->data[i]; - } - } - } - -#if 0 - // Print out the results - printf("--------------------------\n"); - printf("template %s\n", toChars()); - printf("instance %s\n", ti->toChars()); - if (m) - { - for (int i = 0; i < dim; i++) - { - TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; - Object *oarg; - - printf(" [%d]", i); - - if (i < ti->tiargs->dim) - oarg = (Object *)ti->tiargs->data[i]; - else - oarg = NULL; - tp->print(oarg, (Object *)dedtypes->data[i]); - } - } - else - goto Lnomatch; -#endif - -#if LOG - printf(" match = %d\n", m); -#endif - goto Lret; - -Lnomatch: -#if LOG - printf(" no match\n"); -#endif - m = MATCHnomatch; - -Lret: - paramscope->pop(); -#if LOG - printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m); -#endif - return m; -} - -/******************************************** - * Determine partial specialization order of 'this' vs td2. - * Returns: - * 1 this is at least as specialized as td2 - * 0 td2 is more specialized than this - */ - -int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2) -{ - /* This works by taking the template parameters to this template - * declaration and feeding them to td2 as if it were a template - * instance. - * If it works, then this template is at least as specialized - * as td2. - */ - - TemplateInstance ti(0, ident); // create dummy template instance - Array dedtypes; - -#define LOG_LEASTAS 0 - -#if LOG_LEASTAS - printf("%s.leastAsSpecialized(%s)\n", toChars(), td2->toChars()); -#endif - - // Set type arguments to dummy template instance to be types - // generated from the parameters to this template declaration - ti.tiargs = new Array(); - ti.tiargs->setDim(parameters->dim); - for (int i = 0; i < ti.tiargs->dim; i++) - { - TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; - - ti.tiargs->data[i] = tp->dummyArg(); - } - - // Temporary Array to hold deduced types - dedtypes.setDim(parameters->dim); - - // Attempt a type deduction - if (td2->matchWithInstance(&ti, &dedtypes, 1)) - { -#if LOG_LEASTAS - printf(" matches, so is least as specialized\n"); -#endif - return 1; - } -#if LOG_LEASTAS - printf(" doesn't match, so is not as specialized\n"); -#endif - return 0; -} - -void TemplateDeclaration::toCBuffer(OutBuffer *buf) -{ - int i; - - buf->writestring("template "); - buf->writestring(ident->toChars()); - buf->writeByte('('); - for (i = 0; i < parameters->dim; i++) - { - TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; - if (i) - buf->writeByte(','); - tp->toCBuffer(buf); - } - buf->writeByte(')'); -} - - -char *TemplateDeclaration::toChars() -{ - OutBuffer buf; - char *s; - - toCBuffer(&buf); - s = buf.toChars(); - buf.data = NULL; - return s + 9; // kludge to skip over 'template ' -} - -/* ======================== Type ============================================ */ - -/* These form the heart of template argument deduction. - * Given 'this' being the argument to the template instance, - * it is matched against the template declaration parameter specialization - * 'tparam' to determine the type to be used for the parameter. - */ - -MATCH Type::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - //printf("Type::deduceType()\n"); - //printf("\tthis = %d, ", ty); print(); - //printf("\ttparam = %d, ", tparam->ty); tparam->print(); - if (!tparam) - goto Lnomatch; - - if (this == tparam) - goto Lexact; - - if (tparam->ty == Tident) - { - TypeIdentifier *tident = (TypeIdentifier *)tparam; - - //printf("\ttident = '%s'\n", tident->toChars()); - if (tident->idents.dim > 0) - goto Lnomatch; - - // Determine which parameter tparam is - Identifier *id = tident->ident; - int i; - for (i = 0; 1; i++) - { - if (i == parameters->dim) - goto Lnomatch; - TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; - - if (tp->ident->equals(id)) - { // Found the corresponding parameter - Type *at = (Type *)dedtypes->data[i]; - if (!at) - { - dedtypes->data[i] = (void *)this; - goto Lexact; - } - if (equals(at)) - goto Lexact; - else - goto Lnomatch; - } - } - } - - if (ty != tparam->ty) - goto Lnomatch; - - if (next) - return next->deduceType(tparam->next, parameters, dedtypes); - -Lexact: - return MATCHexact; - -Lnomatch: - return MATCHnomatch; -} - -MATCH TypeSArray::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - // Extra check that array dimensions must match - if (tparam && tparam->ty == Tsarray) - { - TypeSArray *tp = (TypeSArray *)tparam; - if (dim->toInteger() != tp->dim->toInteger()) - return MATCHnomatch; - } - return Type::deduceType(tparam, parameters, dedtypes); -} - -MATCH TypeAArray::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - // Extra check that index type must match - if (tparam && tparam->ty == Taarray) - { - TypeAArray *tp = (TypeAArray *)tparam; - if (!index->deduceType(tp->index, parameters, dedtypes)) - return MATCHnomatch; - } - return Type::deduceType(tparam, parameters, dedtypes); -} - -MATCH TypeFunction::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - // Extra check that function characteristics must match - if (tparam && tparam->ty == Tfunction) - { - TypeFunction *tp = (TypeFunction *)tparam; - if (varargs != tp->varargs || - linkage != tp->linkage || - arguments->dim != tp->arguments->dim) - return MATCHnomatch; - for (int i = 0; i < arguments->dim; i++) - { - Argument *a = (Argument *)arguments->data[i]; - Argument *ap = (Argument *)tp->arguments->data[i]; - if (a->inout != ap->inout || - !a->type->deduceType(ap->type, parameters, dedtypes)) - return MATCHnomatch; - } - } - return Type::deduceType(tparam, parameters, dedtypes); -} - -MATCH TypeIdentifier::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - // Extra check - if (tparam && tparam->ty == Tident) - { - TypeIdentifier *tp = (TypeIdentifier *)tparam; - - for (int i = 0; i < idents.dim; i++) - { - Identifier *id1 = (Identifier *)idents.data[i]; - Identifier *id2 = (Identifier *)tp->idents.data[i]; - - if (!id1->equals(id2)) - return MATCHnomatch; - } - } - return Type::deduceType(tparam, parameters, dedtypes); -} - -MATCH TypeInstance::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - // Extra check - if (tparam && tparam->ty == Tinstance) - { - TypeInstance *tp = (TypeInstance *)tparam; - - for (int i = 0; i < idents.dim; i++) - { - Identifier *id1 = (Identifier *)idents.data[i]; - Identifier *id2 = (Identifier *)tp->idents.data[i]; - - if (!id1->equals(id2)) - return MATCHnomatch; - } - - for (int i = 0; i < tempinst->tiargs->dim; i++) - { - Type *t1 = (Type *)tempinst->tiargs->data[i]; - Type *t2 = (Type *)tp->tempinst->tiargs->data[i]; - - if (!t1->deduceType(t2, parameters, dedtypes)) - return MATCHnomatch; - } - } - return Type::deduceType(tparam, parameters, dedtypes); -} - -MATCH TypeStruct::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - // Extra check - if (tparam && tparam->ty == Tstruct) - { - TypeStruct *tp = (TypeStruct *)tparam; - - if (sym != tp->sym) - return MATCHnomatch; - } - return Type::deduceType(tparam, parameters, dedtypes); -} - -MATCH TypeEnum::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - // Extra check - if (tparam && tparam->ty == Tenum) - { - TypeEnum *tp = (TypeEnum *)tparam; - - if (sym != tp->sym) - return MATCHnomatch; - } - return Type::deduceType(tparam, parameters, dedtypes); -} - -MATCH TypeTypedef::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - // Extra check - if (tparam && tparam->ty == Ttypedef) - { - TypeTypedef *tp = (TypeTypedef *)tparam; - - if (sym != tp->sym) - return MATCHnomatch; - } - return Type::deduceType(tparam, parameters, dedtypes); -} - -MATCH TypeClass::deduceType(Type *tparam, Array *parameters, Array *dedtypes) -{ - //printf("TypeClass::deduceType()\n"); - - // Extra check - if (tparam && tparam->ty == Tclass) - { - TypeClass *tp = (TypeClass *)tparam; - -#if 1 - //printf("\t%d\n", (MATCH) implicitConvTo(tp)); - return (MATCH) implicitConvTo(tp); -#else - if (sym != tp->sym) - return MATCHnomatch; -#endif - } - return Type::deduceType(tparam, parameters, dedtypes); -} - -/* ======================== TemplateParameter =============================== */ - -TemplateParameter::TemplateParameter(Loc loc, Identifier *ident) -{ - this->loc = loc; - this->ident = ident; -} - -TemplateTypeParameter *TemplateParameter::isTemplateTypeParameter() -{ - return NULL; -} - -TemplateValueParameter *TemplateParameter::isTemplateValueParameter() -{ - return NULL; -} - -TemplateAliasParameter *TemplateParameter::isTemplateAliasParameter() -{ - return NULL; -} - -/* ======================== TemplateTypeParameter =========================== */ - -// type-parameter - -TemplateTypeParameter::TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, - Type *defaultType) - : TemplateParameter(loc, ident) -{ - this->ident = ident; - this->specType = specType; - this->defaultType = defaultType; -} - -TemplateTypeParameter *TemplateTypeParameter::isTemplateTypeParameter() -{ - return this; -} - -TemplateParameter *TemplateTypeParameter::syntaxCopy() -{ - TemplateTypeParameter *tp = new TemplateTypeParameter(loc, ident, specType, defaultType); - if (tp->specType) - tp->specType = specType->syntaxCopy(); - if (defaultType) - tp->defaultType = defaultType->syntaxCopy(); - return tp; -} - -void TemplateTypeParameter::semantic(Scope *sc) -{ - //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars()); - TypeIdentifier *ti = new TypeIdentifier(loc, ident); - Declaration *sparam = new AliasDeclaration(loc, ident, ti); - if (!sc->insert(sparam)) - error(loc, "parameter '%s' multiply defined", ident->toChars()); - - if (specType) - { - specType = specType->semantic(loc, sc); - } -#if 0 // Don't do semantic() until instantiation - if (defaultType) - { - defaultType = defaultType->semantic(loc, sc); - } -#endif -} - -int TemplateTypeParameter::overloadMatch(TemplateParameter *tp) -{ - TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); - - if (ttp) - { - if (specType != ttp->specType) - goto Lnomatch; - - if (specType && !specType->equals(ttp->specType)) - goto Lnomatch; - - return 1; // match - } - -Lnomatch: - return 0; -} - - -MATCH TemplateTypeParameter::matchArg(Scope *sc, Object *oarg, - int i, Array *parameters, Array *dedtypes, Declaration **psparam) -{ - //printf("TemplateTypeParameter::matchArg()\n"); - - Type *t; - MATCH m = MATCHexact; - Type *ta = isType(oarg); - if (!ta) - goto Lnomatch; - - t = (Type *)dedtypes->data[i]; - - if (specType) - { - //printf("\tcalling deduceType(), specType is %s\n", specType->toChars()); - MATCH m2 = ta->deduceType(specType, parameters, dedtypes); - if (m2 == MATCHnomatch) - { //printf("\tfailed deduceType\n"); - goto Lnomatch; - } - - if (m2 < m) - m = m2; - t = (Type *)dedtypes->data[i]; - } - else if (t) - { // Must match already deduced type - - if (!t->equals(ta)) - goto Lnomatch; - } - - if (!t) - { - dedtypes->data[i] = ta; - t = ta; - } - *psparam = new AliasDeclaration(loc, ident, t); - return m; - -Lnomatch: - *psparam = NULL; - return MATCHnomatch; -} - - -void TemplateTypeParameter::print(Object *oarg, Object *oded) -{ - printf(" %s\n", ident->toChars()); - - Type *t = isType(oarg); - Type *ta = isType(oded); - - assert(ta); - - if (specType) - printf("\tSpecialization: %s\n", specType->toChars()); - if (defaultType) - printf("\tDefault: %s\n", defaultType->toChars()); - printf("\tArgument: %s\n", t ? t->toChars() : "NULL"); - printf("\tDeduced Type: %s\n", ta->toChars()); -} - - -void TemplateTypeParameter::toCBuffer(OutBuffer *buf) -{ - buf->writestring(ident->toChars()); - if (specType) - { - buf->writestring(" : "); - specType->toCBuffer(buf, NULL); - } - if (defaultType) - { - buf->writestring(" = "); - defaultType->toCBuffer(buf, NULL); - } -} - - -void *TemplateTypeParameter::dummyArg() -{ Type *t; - - if (specType) - t = specType; - else - { // Use this for alias-parameter's too (?) - t = new TypeIdentifier(loc, ident); - } - return (void *)t; -} - - -Object *TemplateTypeParameter::defaultArg(Scope *sc) -{ - Type *t; - - t = defaultType; - if (t) - { - t = t->syntaxCopy(); - t = t->semantic(loc, sc); - } - return t; -} - -/* ======================== TemplateAliasParameter ========================== */ - -// alias-parameter - -Dsymbol *TemplateAliasParameter::sdummy = NULL; - -TemplateAliasParameter::TemplateAliasParameter(Loc loc, Identifier *ident, Type *specAliasT, Type *defaultAlias) - : TemplateParameter(loc, ident) -{ - this->ident = ident; - this->specAliasT = specAliasT; - this->defaultAlias = defaultAlias; - - this->specAlias = NULL; -} - -TemplateAliasParameter *TemplateAliasParameter::isTemplateAliasParameter() -{ - return this; -} - -TemplateParameter *TemplateAliasParameter::syntaxCopy() -{ - TemplateAliasParameter *tp = new TemplateAliasParameter(loc, ident, specAliasT, defaultAlias); - if (tp->specAliasT) - tp->specAliasT = specAliasT->syntaxCopy(); - if (defaultAlias) - tp->defaultAlias = defaultAlias->syntaxCopy(); - return tp; -} - -void TemplateAliasParameter::semantic(Scope *sc) -{ - TypeIdentifier *ti = new TypeIdentifier(loc, ident); - Declaration *sparam = new AliasDeclaration(loc, ident, ti); - if (!sc->insert(sparam)) - error(loc, "parameter '%s' multiply defined", ident->toChars()); - - if (specAliasT) - { - specAlias = specAliasT->toDsymbol(sc); - if (!specAlias) - error("%s is not a symbol", specAliasT->toChars()); - } -#if 0 // Don't do semantic() until instantiation - if (defaultAlias) - defaultAlias = defaultAlias->semantic(loc, sc); -#endif -} - -int TemplateAliasParameter::overloadMatch(TemplateParameter *tp) -{ - TemplateAliasParameter *tap = tp->isTemplateAliasParameter(); - - if (tap) - { - if (specAlias != tap->specAlias) - goto Lnomatch; - - return 1; // match - } - -Lnomatch: - return 0; -} - -MATCH TemplateAliasParameter::matchArg(Scope *sc, - Object *oarg, int i, Array *parameters, Array *dedtypes, Declaration **psparam) -{ - Dsymbol *sa; - - //printf("TemplateAliasParameter::matchArg()\n"); - Expression *ea = isExpression(oarg); - if (ea) - { // Try to convert Expression to symbol - if (ea->op == TOKvar) - sa = ((VarExp *)ea)->var; - else if (ea->op == TOKfunction) - sa = ((FuncExp *)ea)->fd; - else - goto Lnomatch; - } - else - { // Try to convert Type to symbol - Type *ta = isType(oarg); - if (ta) - sa = ta->toDsymbol(NULL); - else - sa = isDsymbol(oarg); // if already a symbol - } - - if (!sa) - goto Lnomatch; - - if (specAlias) - { - if (!sa || sa == sdummy) - goto Lnomatch; - if (sa != specAlias) - goto Lnomatch; - } - else if (dedtypes->data[i]) - { // Must match already deduced symbol - Dsymbol *s = (Dsymbol *)dedtypes->data[i]; - - if (!sa || s != sa) - goto Lnomatch; - } - dedtypes->data[i] = sa; - - *psparam = new AliasDeclaration(loc, ident, sa); - return MATCHexact; - -Lnomatch: - *psparam = NULL; - return MATCHnomatch; -} - - -void TemplateAliasParameter::print(Object *oarg, Object *oded) -{ - printf(" %s\n", ident->toChars()); - - Dsymbol *sa = isDsymbol(oded); - assert(sa); - - printf("\tArgument alias: %s\n", sa->toChars()); -} - -void TemplateAliasParameter::toCBuffer(OutBuffer *buf) -{ - buf->writestring("alias "); - buf->writestring(ident->toChars()); - if (specAliasT) - { - buf->writestring(" : "); - specAliasT->toCBuffer(buf, NULL); - } - if (defaultAlias) - { - buf->writestring(" = "); - defaultAlias->toCBuffer(buf, NULL); - } -} - - -void *TemplateAliasParameter::dummyArg() -{ Dsymbol *s; - - s = specAlias; - if (!s) - { - if (!sdummy) - sdummy = new Dsymbol(); - s = sdummy; - } - return (void*)s; -} - - -Object *TemplateAliasParameter::defaultArg(Scope *sc) -{ - Dsymbol *s = NULL; - - if (defaultAlias) - { - s = defaultAlias->toDsymbol(sc); - if (!s) - error("%s is not a symbol", defaultAlias->toChars()); - } - return s; -} - -/* ======================== TemplateValueParameter ========================== */ - -// value-parameter - -Expression *TemplateValueParameter::edummy = NULL; - -TemplateValueParameter::TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, - Expression *specValue, Expression *defaultValue) - : TemplateParameter(loc, ident) -{ - this->ident = ident; - this->valType = valType; - this->specValue = specValue; - this->defaultValue = defaultValue; -} - -TemplateValueParameter *TemplateValueParameter::isTemplateValueParameter() -{ - return this; -} - -TemplateParameter *TemplateValueParameter::syntaxCopy() -{ - TemplateValueParameter *tp = - new TemplateValueParameter(loc, ident, valType, specValue, defaultValue); - tp->valType = valType->syntaxCopy(); - if (specValue) - tp->specValue = specValue->syntaxCopy(); - if (defaultValue) - tp->defaultValue = defaultValue->syntaxCopy(); - return tp; -} - -void TemplateValueParameter::semantic(Scope *sc) -{ - Declaration *sparam = new VarDeclaration(loc, valType, ident, NULL); - if (!sc->insert(sparam)) - error(loc, "parameter '%s' multiply defined", ident->toChars()); - - sparam->semantic(sc); - valType = valType->semantic(loc, sc); - if (!valType->isintegral() && valType->ty != Tident) - error(loc, "integral type expected for value-parameter, not %s", valType->toChars()); - - if (specValue) - { Expression *e = specValue; - - e = e->semantic(sc); - e = e->implicitCastTo(valType); - e = e->constFold(); - if (e->op == TOKint64) - specValue = e; - //e->toInteger(); - } - -#if 0 // defer semantic analysis to arg match - if (defaultValue) - { Expression *e = defaultValue; - - e = e->semantic(sc); - e = e->implicitCastTo(valType); - e = e->constFold(); - if (e->op == TOKint64) - defaultValue = e; - //e->toInteger(); - } -#endif -} - -int TemplateValueParameter::overloadMatch(TemplateParameter *tp) -{ - TemplateValueParameter *tvp = tp->isTemplateValueParameter(); - - if (tvp) - { - if (valType != tvp->valType) - goto Lnomatch; - - if (valType && !valType->equals(tvp->valType)) - goto Lnomatch; - - if (specValue != tvp->specValue) - goto Lnomatch; - - return 1; // match - } - -Lnomatch: - return 0; -} - - -MATCH TemplateValueParameter::matchArg(Scope *sc, - Object *oarg, int i, Array *parameters, Array *dedtypes, Declaration **psparam) -{ - Initializer *init; - Declaration *sparam; - Expression *ei = isExpression(oarg); - if (!ei && oarg) - goto Lnomatch; - - if (specValue) - { - if (!ei || ei == edummy) - goto Lnomatch; - - Expression *e = specValue; - e = e->semantic(sc); - e = e->implicitCastTo(valType); - e = e->constFold(); - if (!ei->equals(e)) - goto Lnomatch; - } - else if (dedtypes->data[i]) - { // Must match already deduced value - Expression *e = (Expression *)dedtypes->data[i]; - - if (!ei || !ei->equals(e)) - goto Lnomatch; - } - dedtypes->data[i] = ei; - - init = new ExpInitializer(loc, ei); - sparam = new VarDeclaration(loc, valType, ident, init); - sparam->storage_class = STCconst; - *psparam = sparam; - return MATCHexact; - -Lnomatch: - *psparam = NULL; - return MATCHnomatch; -} - - -void TemplateValueParameter::print(Object *oarg, Object *oded) -{ - printf(" %s\n", ident->toChars()); - - Expression *ea = isExpression(oded); - - if (specValue) - printf("\tSpecialization: %s\n", specValue->toChars()); - printf("\tArgument Value: %s\n", ea ? ea->toChars() : "NULL"); -} - - -void TemplateValueParameter::toCBuffer(OutBuffer *buf) -{ - valType->toCBuffer(buf, ident); - if (specValue) - { - buf->writestring(" : "); - specValue->toCBuffer(buf); - } - if (defaultValue) - { - buf->writestring(" = "); - defaultValue->toCBuffer(buf); - } -} - - -void *TemplateValueParameter::dummyArg() -{ Expression *e; - - e = specValue; - if (!e) - { - // Create a dummy value - if (!edummy) - edummy = new IntegerExp(0); - e = edummy; - } - return (void *)e; -} - - -Object *TemplateValueParameter::defaultArg(Scope *sc) -{ - Expression *e; - - e = defaultValue; - if (e) - { - e = e->syntaxCopy(); - e = e->semantic(sc); - } - return e; -} - -/* ======================== TemplateInstance ================================ */ - -TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) - : ScopeDsymbol(NULL) -{ -#if LOG - printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident->toChars() : "null"); -#endif - this->loc = loc; - this->idents.push(ident); - this->tiargs = NULL; - this->tempdecl = NULL; - this->inst = NULL; - this->argsym = NULL; - this->aliasdecl = NULL; - this->semanticdone = 0; -} - - -Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s) -{ - TemplateInstance *ti; - int i; - - if (s) - ti = (TemplateInstance *)s; - else - ti = new TemplateInstance(loc, (Identifier *)idents.data[0]); - - ti->idents.setDim(idents.dim); - for (i = 1; i < idents.dim; i++) - ti->idents.data[i] = idents.data[i]; - - ti->tiargs = new Array(); - ti->tiargs->setDim(tiargs->dim); - for (i = 0; i < tiargs->dim; i++) - { - Type *ta = isType((Object *)tiargs->data[i]); - if (ta) - ti->tiargs->data[i] = ta->syntaxCopy(); - else - { - Expression *ea = isExpression((Object *)tiargs->data[i]); - assert(ea); - ti->tiargs->data[i] = ea->syntaxCopy(); - } - } - - ScopeDsymbol::syntaxCopy(ti); - return ti; -} - - -void TemplateInstance::addIdent(Identifier *ident) -{ - idents.push(ident); -} - -#ifdef IN_GCC -// This is needed for -femit-templates=private work-around. We -// must ensure the TemplateInstance ends up as a member of the -// module that is being compiled so that the template instance's -// toObjfile is called. -extern Module * getCurrentModule(); -#endif - -void TemplateInstance::semantic(Scope *sc) -{ -#if LOG - printf("+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); -#endif - if (inst) // if semantic() was already run - { -#if LOG - printf("-TemplateInstance::semantic('%s', this=%p)\n", inst->toChars(), inst); -#endif - return; - } - - if (semanticdone != 0) - { - error(loc, "recursive template expansion"); -// inst = this; - return; - } - semanticdone = 1; - -#if LOG - printf("\tdo semantic\n"); -#endif - // Run semantic on each argument, place results in tiargs[] - semanticTiargs(sc); - - tempdecl = findTemplateDeclaration(sc); - if (!tempdecl || global.errors) - { inst = this; - return; // error recovery - } - - /* See if there is an existing TemplateInstantiation that already - * implements the typeargs. If so, just refer to that one instead. - */ - - for (int i = 0; i < tempdecl->instances.dim; i++) - { - TemplateInstance *ti = (TemplateInstance *)tempdecl->instances.data[i]; -#if LOG - printf("\tchecking for match with instance %d (%p): '%s'\n", i, ti, ti->toChars()); -#endif - assert(tdtypes.dim == ti->tdtypes.dim); - - for (int j = 0; j < tdtypes.dim; j++) - { Object *o1 = (Object *)tdtypes.data[j]; - Object *o2 = (Object *)ti->tdtypes.data[j]; - Type *t1 = isType(o1); - Type *t2 = isType(o2); - Expression *e1 = isExpression(o1); - Expression *e2 = isExpression(o2); - Dsymbol *s1 = isDsymbol(o1); - Dsymbol *s2 = isDsymbol(o2); - - /* A proper implementation of the various equals() overrides - * should make it possible to just do o1->equals(o2), but - * we'll do that another day. - */ - - if (t1) - { - /* if t1 is an instance of ti, then give error - * about recursive expansions. - */ - Dsymbol *s = t1->toDsymbol(sc); - if (s && s->parent) - { TemplateInstance *ti1 = s->parent->isTemplateInstance(); - if (ti1 && ti1->tempdecl == tempdecl) - { - for (Scope *sc1 = sc; sc1; sc1 = sc1->enclosing) - { - if (sc1->scopesym == ti1) - { - error("recursive template expansion for template argument %s", t1->toChars()); - return; - } - } - } - } - - if (!t2 || !t1->equals(t2)) - goto L1; - } - else if (e1) - { - if (!e2 || !e1->equals(e2)) - goto L1; - } - else if (s1) - { - if (!s2 || !s1->equals(s2)) - goto L1; - } - } - - // It's a match - inst = ti; - parent = ti->parent; -#if LOG - printf("\tit's a match with instance %p\n", inst); -#endif - return; - - L1: - ; - } - - /* So, we need to implement 'this' instance. - */ -#if LOG - printf("\timplement template instance '%s'\n", toChars()); -#endif - unsigned errorsave = global.errors; - inst = this; - tempdecl->instances.push(this); - parent = tempdecl->parent; - //printf("parent = '%s'\n", parent->kind()); - - ident = genIdent(); // need an identifier for name mangling purposes. - - // Add 'this' to the enclosing scope's members[] so the semantic routines - // will get called on the instance members -#if 1 - { Array *a; - int i; -#ifdef IN_GCC - // For gcc, always add it the module that is being compiled - a = getCurrentModule()->members; -#else - - if (sc->scopesym && sc->scopesym->members && !sc->scopesym->isTemplateMixin()) - { - //printf("\t1: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars()); - a = sc->scopesym->members; - } - else - { - //printf("\t2: adding to module %s\n", sc->module->importedFrom->toChars()); - a = sc->module->importedFrom->members; - } -#endif - for (i = 0; 1; i++) - { - if (i == a->dim) - { - a->push(this); - break; - } - if (this == (Dsymbol *)a->data[i]) // if already in Array - break; - } - } -#endif - - // Copy the syntax trees from the TemplateDeclaration - members = Dsymbol::arraySyntaxCopy(tempdecl->members); - - // Create our own scope for the template parameters - Scope *scope = tempdecl->scope; - if (!scope) - { - error("forward reference to template declaration %s\n", tempdecl->toChars()); - return; - } - -#if LOG - printf("\tcreate scope for template parameters '%s'\n", toChars()); -#endif - argsym = new ScopeDsymbol(); - argsym->parent = scope->parent; - scope = scope->push(argsym); - - // Declare each template parameter as an alias for the argument type - declareParameters(scope); - - // Add members of template instance to template instance symbol table -// parent = scope->scopesym; - symtab = new DsymbolTable(); - for (int i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; -#if LOG - printf("\tadding member '%s' %p to '%s'\n", s->toChars(), s, this->toChars()); -#endif - s->addMember(this); - } - - /* See if there is only one member of template instance, and that - * member has the same name as the template instance. - * If so, this template instance becomes an alias for that member. - */ - //printf("members->dim = %d\n", members->dim); - if (members->dim) - { - Dsymbol *s = (Dsymbol *)members->data[0]; - s = s->oneMember(); - - // Ignore any additional template instance symbols - for (int j = 1; j < members->dim; j++) - { Dsymbol *sx = (Dsymbol *)members->data[j]; - if (sx->isTemplateInstance()) - continue; - s = NULL; - break; - } - - if (s) - { - //printf("s->kind = '%s'\n", s->kind()); - //s->print(); - //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars()); - if (s->ident && s->ident->equals(tempdecl->ident)) - { - //printf("setting aliasdecl\n"); - aliasdecl = new AliasDeclaration(loc, s->ident, s); - } - } - } - - // Do semantic() analysis on template instance members -#if LOG - printf("\tdo semantic() on template instance members '%s'\n", toChars()); -#endif - Scope *sc2; - sc2 = scope->push(this); - sc2->parent = this; - for (int i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic(sc2); - } - - /* The problem is when to parse the initializer for a variable. - * Perhaps VarDeclaration::semantic() should do it like it does - * for initializers inside a function. - */ -// if (sc->parent->isFuncDeclaration()) - - semantic2(sc2); - - if (sc->func) - { - semantic3(sc2); - } - - sc2->pop(); - - scope->pop(); - - // Give additional context info if error occurred during instantiation - if (global.errors != errorsave) - error("error instantiating"); - -#if LOG - printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); -#endif -} - - -void TemplateInstance::semanticTiargs(Scope *sc) -{ - // Run semantic on each argument, place results in tiargs[] - for (int j = 0; j < tiargs->dim; j++) - { Type *ta = isType((Object *)tiargs->data[j]); - Expression *ea; - Dsymbol *sa; - - if (ta) - { - // It might really be an Expression or an Alias - ta->resolve(loc, sc, &ea, &ta, &sa); - if (ea) - tiargs->data[j] = ea; - else if (sa) - tiargs->data[j] = sa; - else if (ta) - tiargs->data[j] = ta; - else - { - assert(global.errors); - tiargs->data[j] = Type::terror; - } - } - else - { - ea = isExpression((Object *)tiargs->data[j]); - assert(ea); - ea = ea->semantic(sc); - ea = ea->constFold(); - tiargs->data[j] = ea; - } - //printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]); - } -} - -/********************************************** - * Find template declaration corresponding to template instance. - */ - -TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) -{ - if (!tempdecl) - { - /* Given: - * instance foo.bar.abc( ... ) - * figure out which TemplateDeclaration foo.bar.abc refers to. - */ - Dsymbol *s; - Dsymbol *scopesym; - Identifier *id; - int i; - - id = (Identifier *)idents.data[0]; - s = sc->search(id, &scopesym); - if (s) - { -#if LOG - printf("It's an instance of '%s'\n", s->toChars()); -#endif - s = s->toAlias(); - for (i = 1; i < idents.dim; i++) - { Dsymbol *sm; - - id = (Identifier *)idents.data[i]; - sm = s->search(id, 0); - if (!sm) - { - s = NULL; - break; - } - s = sm->toAlias(); - } - } - if (!s) - { error("identifier '%s' is not defined", id->toChars()); - return NULL; - } - - /* It should be a TemplateDeclaration, not some other symbol - */ - tempdecl = s->isTemplateDeclaration(); - if (!tempdecl) - { - error("%s is not a template declaration, it is a %s", id->toChars(), s->kind()); - return NULL; - } - } - else - assert(tempdecl->isTemplateDeclaration()); - - /* Since there can be multiple TemplateDeclaration's with the same - * name, look for the best match. - */ - TemplateDeclaration *td_ambig = NULL; - TemplateDeclaration *td_best = NULL; - MATCH m_best = MATCHnomatch; - Array dedtypes; - - for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) - { - MATCH m; - -//if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->data[0]); - - // If more arguments than parameters, - // then this is no match. - if (td->parameters->dim < tiargs->dim) - continue; - - dedtypes.setDim(td->parameters->dim); - if (!td->scope) - { - error("forward reference to template"); - return NULL; - } - m = td->matchWithInstance(this, &dedtypes, 0); - if (!m) // no match at all - continue; - -#if 0 - if (m < m_best) - goto Ltd_best; - if (m > m_best) - goto Ltd; -#else - if (!m_best) - goto Ltd; -#endif - { - // Disambiguate by picking the most specialized TemplateDeclaration - int c1 = td->leastAsSpecialized(td_best); - int c2 = td_best->leastAsSpecialized(td); - //printf("c1 = %d, c2 = %d\n", c1, c2); - - if (c1 && !c2) - goto Ltd; - else if (!c1 && c2) - goto Ltd_best; - else - goto Lambig; - } - - Lambig: // td_best and td are ambiguous - td_ambig = td; - continue; - - Ltd_best: // td_best is the best match so far - continue; - - Ltd: // td is the new best match - td_best = td; - m_best = m; - tdtypes.setDim(dedtypes.dim); - memcpy(tdtypes.data, dedtypes.data, tdtypes.dim * sizeof(void *)); - continue; - } - - if (!td_best) - { - error("does not match any template declaration"); - return NULL; - } - if (td_ambig) - { - error("matches more than one template declaration"); - } - - /* The best match is td_best - */ - tempdecl = td_best; -#if LOG - printf("\tIt's a match with template declaration '%s'\n", tempdecl->toChars()); -#endif - return tempdecl; -} - - -/**************************************** - * This instance needs an identifier for name mangling purposes. - * Create one by taking the template declaration name and adding - * the type signature for it. - */ - -Identifier *TemplateInstance::genIdent() -{ OutBuffer buf; - char *id; - - //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); - buf.writestring(tempdecl->ident->toChars()); - buf.writeByte('_'); - for (int i = 0; i < tiargs->dim; i++) - { Object *o = (Object *)tiargs->data[i]; - //Object *o = (Object *)tdtypes.data[i]; - Type *ta = isType(o); - Expression *ea = isExpression(o); - Dsymbol *sa = isDsymbol(o); - if (ta) - { - if (ta->deco) - buf.writestring(ta->deco); - else - assert(global.errors); - } - else if (ea) - { - if (ea->op == TOKvar) - { - sa = ((VarExp *)ea)->var; - ea = NULL; - goto Lsa; - } - if (ea->op == TOKfunction) - { - sa = ((FuncExp *)ea)->fd; - ea = NULL; - goto Lsa; - } - buf.writeByte('_'); - buf.printf("%llu", ea->toInteger()); - } - else if (sa) - { - Lsa: - Declaration *d = sa->isDeclaration(); - if (d && !d->isDataseg() && !d->isFuncDeclaration() && !isTemplateMixin()) - { - error("cannot use local '%s' as template parameter", d->toChars()); - } - if (d && !d->type->deco) - error("forward reference of %s", d->toChars()); - else - { - char *p = sa->mangle(); - buf.printf("__%u_%s", strlen(p) + 1, p); - } - } - else - assert(0); - } - id = buf.toChars(); - buf.data = NULL; - return new Identifier(id, TOKidentifier); -} - - -/**************************************************** - * Declare parameters of template instance, initialize them with the - * template instance arguments. - */ - -void TemplateInstance::declareParameters(Scope *scope) -{ - //printf("TemplateInstance::declareParameters()\n"); - for (int i = 0; i < tdtypes.dim; i++) - { - TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i]; - //Object *o = (Object *)tiargs->data[i]; - Object *o = (Object *)tdtypes.data[i]; - Type *targ = isType(o); - Expression *ea = isExpression(o); - Dsymbol *sa = isDsymbol(o); - Dsymbol *s; - - if (targ) - { - Type *tded = isType((Object *)tdtypes.data[i]); - - assert(tded); - s = new AliasDeclaration(0, tp->ident, tded); - } - else if (sa) - { - //printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars()); - s = new AliasDeclaration(0, tp->ident, sa); - } - else if (ea) - { - // tdtypes.data[i] always matches ea here - Initializer *init = new ExpInitializer(loc, ea); - TemplateValueParameter *tvp = tp->isTemplateValueParameter(); - assert(tvp); - - VarDeclaration *v = new VarDeclaration(0, tvp->valType, tp->ident, init); - v->storage_class = STCconst; - s = v; - } - else - assert(0); - if (!scope->insert(s)) - error("declaration %s is already defined", tp->ident->toChars()); - s->semantic(scope); - } -} - - -void TemplateInstance::semantic2(Scope *sc) -{ int i; - - if (semanticdone >= 2) - return; - semanticdone = 2; -#if LOG - printf("+TemplateInstance::semantic2('%s')\n", toChars()); -#endif - if (members) - { - sc = tempdecl->scope; - assert(sc); - sc = sc->push(argsym); - sc = sc->push(this); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; -#if LOG -printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); -#endif - s->semantic2(sc); - } - sc = sc->pop(); - sc->pop(); - } -#if LOG - printf("-TemplateInstance::semantic2('%s')\n", toChars()); -#endif -} - -void TemplateInstance::semantic3(Scope *sc) -{ int i; - - if (semanticdone >= 3) - return; - semanticdone = 3; -#if LOG - printf("TemplateInstance::semantic3('%s')\n", toChars()); -#endif - if (members) - { - sc = tempdecl->scope; - sc = sc->push(argsym); - sc = sc->push(this); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic3(sc); - } - sc = sc->pop(); - sc->pop(); - } -} - -void TemplateInstance::toObjFile() -{ int i; - -#if LOG - printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this); -#endif - if (members) - { - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->toObjFile(); - } - } -} - -void TemplateInstance::inlineScan() -{ int i; - -#if LOG - printf("TemplateInstance::inlineScan('%s')\n", toChars()); -#endif - if (members) - { - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->inlineScan(); - } - } -} - -void TemplateInstance::toCBuffer(OutBuffer *buf) -{ - int i; - - for (i = 0; i < idents.dim; i++) - { Identifier *id = (Identifier *)idents.data[i]; - - if (i) - buf->writeByte('.'); - buf->writestring(id->toChars()); - } - buf->writestring("!("); - if (nest) - buf->writestring("..."); - else - { - nest++; - for (i = 0; i < tiargs->dim; i++) - { - if (i) - buf->writeByte(','); - Object *oarg = (Object *)tiargs->data[i]; - Type *t = isType(oarg); - Expression *e = isExpression(oarg); - Dsymbol *s = isDsymbol(oarg); - if (t) - t->toCBuffer(buf, NULL); - else if (e) - e->toCBuffer(buf); - else if (s) - { - char *p = s->ident ? s->ident->toChars() : s->toChars(); - buf->writestring(p); - } - else if (!oarg) - { - buf->writestring("NULL"); - } - else - { -#ifdef DEBUG - printf("tiargs[%d] = %p\n", i, oarg); -#endif - assert(0); - } - } - nest--; - } - buf->writeByte(')'); -} - - -Dsymbol *TemplateInstance::toAlias() -{ -#if LOG - printf("TemplateInstance::toAlias()\n"); -#endif - if (!inst) - { error("cannot resolve forward reference"); - return this; - } - - if (inst != this) - return inst->toAlias(); - - if (aliasdecl) - return aliasdecl->toAlias(); - - return inst; -} - -AliasDeclaration *TemplateInstance::isAliasDeclaration() -{ - return aliasdecl; -} - -char *TemplateInstance::kind() -{ - return "template instance"; -} - -char *TemplateInstance::toChars() -{ - OutBuffer buf; - char *s; - - toCBuffer(&buf); - s = buf.toChars(); - buf.data = NULL; - return s; - //return s + 9; // kludge to skip over 'instance ' -} - -/* ======================== TemplateMixin ================================ */ - -TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, TypeTypeof *tqual, - Array *idents, Array *tiargs) - : TemplateInstance(loc, (Identifier *)idents->data[idents->dim - 1]) -{ - //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : ""); - this->ident = ident; - this->tqual = tqual; - this->idents = idents; - this->tiargs = tiargs ? tiargs : new Array(); -} - -Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) -{ TemplateMixin *tm; - - Array *ids = new Array(); - ids->setDim(idents->dim); - for (int i = 0; i < idents->dim; i++) - { // Matches TypeQualified::syntaxCopyHelper() - Identifier *id = (Identifier *)idents->data[i]; - if (id->dyncast() != DYNCAST_IDENTIFIER) - { - TemplateInstance *ti = (TemplateInstance *)id; - - ti = (TemplateInstance *)ti->syntaxCopy(NULL); - id = (Identifier *)ti; - } - ids->data[i] = id; - } - - tm = new TemplateMixin(loc, ident, - (TypeTypeof *)(tqual ? tqual->syntaxCopy() : NULL), - ids, tiargs); - TemplateInstance::syntaxCopy(tm); - return tm; -} - -void TemplateMixin::semantic(Scope *sc) -{ -#if LOG - printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); -#endif - if (semanticdone) - return; - semanticdone = 1; -#if LOG - printf("\tdo semantic\n"); -#endif - // Run semantic on each argument, place results in tiargs[] - semanticTiargs(sc); - - // Follow qualifications to find the TemplateDeclaration - { Dsymbol *s; - int i; - Identifier *id; - - if (tqual) - { s = tqual->toDsymbol(sc); - i = 0; - } - else - { - i = 1; - id = (Identifier *)idents->data[0]; - if (id->dyncast() == DYNCAST_IDENTIFIER) - { - s = sc->search(id, NULL); - } - else - { - TemplateInstance *ti = (TemplateInstance *)id; - ti->semantic(sc); - s = ti; - } - } - - for (; i < idents->dim; i++) - { Dsymbol *sm; - - if (!s) - break; - s = s->toAlias(); - id = (Identifier *)idents->data[i]; - if (id->dyncast() == DYNCAST_IDENTIFIER) - { - sm = s->search(id, 0); - } - else - { - // It's a template instance - //printf("\ttemplate instance id\n"); - TemplateDeclaration *td; - TemplateInstance *ti = (TemplateInstance *)id; - id = (Identifier *)ti->idents.data[0]; - sm = s->search(id, 0); - if (!sm) - { error("template identifier %s is not a member of %s", id->toChars(), s->toChars()); - return; - } - sm = sm->toAlias(); - td = sm->isTemplateDeclaration(); - if (!td) - { - error("%s is not a template", id->toChars()); - inst = this; - return; - } - ti->tempdecl = td; - ti->semantic(sc); - sm = ti->toAlias(); - } - s = sm; - } - if (!s) - { - error("is not defined"); - inst = this; - return; - } - tempdecl = s->toAlias()->isTemplateDeclaration(); - if (!tempdecl) - { - error("%s is not a template", s->toChars()); - inst = this; - return; - } - } - - tempdecl = findTemplateDeclaration(sc); - if (!tempdecl) - { inst = this; - return; // error recovery - } - - if (!ident) - ident = genIdent(); - - inst = this; - parent = sc->parent; - - // Copy the syntax trees from the TemplateDeclaration - members = Dsymbol::arraySyntaxCopy(tempdecl->members); - if (!members) - return; - - symtab = new DsymbolTable(); - - // Add members to enclosing scope, as well as this scope - for (unsigned i = 0; i < members->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)members->data[i]; - s->addMember(this); - //sc->insert(s); - //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); - //printf("s->parent = %s\n", s->parent->toChars()); - if (isAnonymous()) - { -#if 0 - if (sc->parent != sc->scopesym) - { - if (!sc->insert(s)) - error("%s is multiply defined", s->toChars()); - } - else - s->addMember((ScopeDsymbol *)sc->parent); -#endif - //s->parent = parent; - } - } - -// if (isAnonymous()) - { - ScopeDsymbol *sds = (ScopeDsymbol *)sc->scopesym; - - sds->importScope(this, PROTpublic); - } - -#if LOG - printf("\tcreate scope for template parameters '%s'\n", toChars()); -#endif - Scope *scx = sc; -// if (!isAnonymous()) - { - scx = sc->push(this); - scx->parent = this; - } - argsym = new ScopeDsymbol(); - argsym->parent = scx->parent; - Scope *scope = scx->push(argsym); - - // Declare each template parameter as an alias for the argument type - declareParameters(scope); - - // Do semantic() analysis on template instance members -#if LOG - printf("\tdo semantic() on template instance members '%s'\n", toChars()); -#endif - Scope *sc2; - sc2 = scope->push(this); - sc2->offset = sc->offset; - for (int i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic(sc2); - } - sc->offset = sc2->offset; - - /* The problem is when to parse the initializer for a variable. - * Perhaps VarDeclaration::semantic() should do it like it does - * for initializers inside a function. - */ -// if (sc->parent->isFuncDeclaration()) - - semantic2(sc2); - - if (sc->func) - { - semantic3(sc2); - } - - sc2->pop(); - - scope->pop(); - -// if (!isAnonymous()) - { - scx->pop(); - } -#if LOG - printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); -#endif -} - -void TemplateMixin::semantic2(Scope *sc) -{ int i; - - if (semanticdone >= 2) - return; - semanticdone = 2; -#if LOG - printf("+TemplateMixin::semantic2('%s')\n", toChars()); -#endif - if (members) - { - assert(sc); - sc = sc->push(argsym); - sc = sc->push(this); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; -#if LOG -printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); -#endif - s->semantic2(sc); - } - sc = sc->pop(); - sc->pop(); - } -#if LOG - printf("-TemplateMixin::semantic2('%s')\n", toChars()); -#endif -} - -void TemplateMixin::semantic3(Scope *sc) -{ int i; - - if (semanticdone >= 3) - return; - semanticdone = 3; -#if LOG - printf("TemplateMixin::semantic3('%s')\n", toChars()); -#endif - if (members) - { - sc = sc->push(argsym); - sc = sc->push(this); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic3(sc); - } - sc = sc->pop(); - sc->pop(); - } -} - -void TemplateMixin::inlineScan() -{ - TemplateInstance::inlineScan(); -} - -char *TemplateMixin::kind() -{ - return "mixin"; -} - -Dsymbol *TemplateMixin::oneMember() -{ - return Dsymbol::oneMember(); -} - -void TemplateMixin::toCBuffer(OutBuffer *buf) -{ - //buf->writestring("mixin "); - if (tqual) - { tqual->toCBuffer(buf, NULL); - buf->writeByte('.'); - } - for (int i = 0; i + 1 < idents->dim; i++) - { Identifier *id = (Identifier *)idents->data[i]; - - buf->writestring(id->toChars()); - buf->writeByte('.'); - } - TemplateInstance::toCBuffer(buf); - if (ident) - { - buf->writeByte(' '); - buf->writestring(ident->toChars()); - } -} - - -void TemplateMixin::toObjFile() -{ - //printf("TemplateMixin::toObjFile('%s')\n", toChars()); - TemplateInstance::toObjFile(); -} - diff -uNr gdc-0.11/d/root/template.h gdc-0.12/d/root/template.h --- gdc-0.11/d/root/template.h 2005-04-17 21:16:12.000000000 +0200 +++ gdc-0.12/d/root/template.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,229 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_TEMPLATE_H -#define DMD_TEMPLATE_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" -#include "dsymbol.h" - -struct OutBuffer; -struct Identifier; -struct TemplateInstance; -struct TemplateParameter; -struct TemplateTypeParameter; -struct TemplateValueParameter; -struct TemplateAliasParameter; -struct Type; -struct Scope; -struct Expression; -struct AliasDeclaration; -enum MATCH; - -struct TemplateDeclaration : ScopeDsymbol -{ - Array *parameters; // array of TemplateParameter's - Array instances; // array of TemplateInstance's - - TemplateDeclaration *overnext; // next overloaded TemplateDeclaration - Scope *scope; - - TemplateDeclaration(Loc loc, Identifier *id, Array *parameters, Array *decldefs); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - int overloadInsert(Dsymbol *s); - void toCBuffer(OutBuffer *buf); - char *kind(); - char *toChars(); - - MATCH matchWithInstance(TemplateInstance *ti, Array *atypes, int flag); - int leastAsSpecialized(TemplateDeclaration *td2); - - TemplateDeclaration *isTemplateDeclaration() { return this; } -}; - -struct TemplateParameter -{ - /* For type-parameter: - * template Foo(ident) // specType is set to NULL - * template Foo(ident : specType) - * For value-parameter: - * template Foo(valType ident) // specValue is set to NULL - * template Foo(valType ident : specValue) - * For alias-parameter: - * template Foo(alias ident) - */ - - Loc loc; - Identifier *ident; - - TemplateParameter(Loc loc, Identifier *ident); - - virtual TemplateTypeParameter *isTemplateTypeParameter(); - virtual TemplateValueParameter *isTemplateValueParameter(); - virtual TemplateAliasParameter *isTemplateAliasParameter(); - - virtual TemplateParameter *syntaxCopy() = 0; - virtual void semantic(Scope *) = 0; - virtual void print(Object *oarg, Object *oded) = 0; - virtual void toCBuffer(OutBuffer *buf) = 0; - virtual Object *defaultArg(Scope *sc) = 0; - - /* If TemplateParameter's match as far as overloading goes. - */ - virtual int overloadMatch(TemplateParameter *) = 0; - - /* Match actual argument against parameter. - */ - virtual MATCH matchArg(Scope *sc, Object *oarg, int i, Array *parameters, Array *dedtypes, Declaration **psparam) = 0; - - /* Create dummy argument based on parameter. - */ - virtual void *dummyArg() = 0; -}; - -struct TemplateTypeParameter : TemplateParameter -{ - /* Syntax: - * ident : specType = defaultType - */ - Type *specType; // type parameter: if !=NULL, this is the type specialization - Type *defaultType; - - TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType); - - TemplateTypeParameter *isTemplateTypeParameter(); - TemplateParameter *syntaxCopy(); - void semantic(Scope *); - void print(Object *oarg, Object *oded); - void toCBuffer(OutBuffer *buf); - Object *defaultArg(Scope *sc); - int overloadMatch(TemplateParameter *); - MATCH matchArg(Scope *sc, Object *oarg, int i, Array *parameters, Array *dedtypes, Declaration **psparam); - void *dummyArg(); -}; - -struct TemplateValueParameter : TemplateParameter -{ - /* Syntax: - * valType ident : specValue = defaultValue - */ - - Type *valType; - Expression *specValue; - Expression *defaultValue; - - static Expression *edummy; - - TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue); - - TemplateValueParameter *isTemplateValueParameter(); - TemplateParameter *syntaxCopy(); - void semantic(Scope *); - void print(Object *oarg, Object *oded); - void toCBuffer(OutBuffer *buf); - Object *defaultArg(Scope *sc); - int overloadMatch(TemplateParameter *); - MATCH matchArg(Scope *sc, Object *oarg, int i, Array *parameters, Array *dedtypes, Declaration **psparam); - void *dummyArg(); -}; - -struct TemplateAliasParameter : TemplateParameter -{ - /* Syntax: - * ident : specAlias = defaultAlias - */ - - Type *specAliasT; - Dsymbol *specAlias; - - Type *defaultAlias; - - static Dsymbol *sdummy; - - TemplateAliasParameter(Loc loc, Identifier *ident, Type *specAliasT, Type *defaultAlias); - - TemplateAliasParameter *isTemplateAliasParameter(); - TemplateParameter *syntaxCopy(); - void semantic(Scope *); - void print(Object *oarg, Object *oded); - void toCBuffer(OutBuffer *buf); - Object *defaultArg(Scope *sc); - int overloadMatch(TemplateParameter *); - MATCH matchArg(Scope *sc, Object *oarg, int i, Array *parameters, Array *dedtypes, Declaration **psparam); - void *dummyArg(); -}; - -struct TemplateInstance : ScopeDsymbol -{ - /* Given: - * instance foo.bar.abc(int, char, 10*10) - */ - Array idents; // Array of Identifiers [foo, bar, abc] - Array *tiargs; // Array of Types/Expressions of template instance arguments [int, char, 10*10] - - TemplateDeclaration *tempdecl; // referenced by foo.bar.abc - TemplateInstance *inst; // refer to existing instance - Array tdtypes; // types corresponding to TemplateDeclaration.parameters - ScopeDsymbol *argsym; // argument symbol table - AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its - // sole member - int semanticdone; // has semantic() been done? - int nest; // for recursion detection - - TemplateInstance(Loc loc, Identifier *temp_id); - Dsymbol *syntaxCopy(Dsymbol *); - void addIdent(Identifier *ident); - void semantic(Scope *sc); - void semantic2(Scope *sc); - void semantic3(Scope *sc); - void inlineScan(); - void toCBuffer(OutBuffer *buf); - Dsymbol *toAlias(); // resolve real symbol - char *kind(); - char *toChars(); - char *mangle(); - - void toObjFile(); // compile to .obj file - - // Internal - void semanticTiargs(Scope *sc); - TemplateDeclaration *findTemplateDeclaration(Scope *sc); - void declareParameters(Scope *sc); - Identifier *genIdent(); - - TemplateInstance *isTemplateInstance() { return this; } - AliasDeclaration *isAliasDeclaration(); -}; - -struct TemplateMixin : TemplateInstance -{ - Array *idents; - TypeTypeof *tqual; - - TemplateMixin(Loc loc, Identifier *ident, TypeTypeof *tqual, Array *idents, Array *tiargs); - Dsymbol *syntaxCopy(Dsymbol *s); - void semantic(Scope *sc); - void semantic2(Scope *sc); - void semantic3(Scope *sc); - void inlineScan(); - char *kind(); - Dsymbol *oneMember(); - void toCBuffer(OutBuffer *buf); - - void toObjFile(); // compile to .obj file - - TemplateMixin *isTemplateMixin() { return this; } -}; - -#endif /* DMD_TEMPLATE_H */ diff -uNr gdc-0.11/d/root/tocsym.c gdc-0.12/d/root/tocsym.c --- gdc-0.11/d/root/tocsym.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/tocsym.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,665 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include -#include -#ifndef alloca -#include -#endif - -#include "mars.h" -#include "module.h" -#include "mtype.h" -#include "declaration.h" -#include "statement.h" -#include "enum.h" -#include "aggregate.h" -#include "init.h" -#include "attrib.h" -#include "lexer.h" -#include "dsymbol.h" - -#include - -// Back end -#include "cc.h" -#include "global.h" -#include "oper.h" -#include "code.h" -#include "type.h" -#include "dt.h" -#include "cgcv.h" -#include "outbuf.h" -#include "irstate.h" - -void slist_add(Symbol *s); -void slist_reset(); - -/********************************* SymbolDeclaration ****************************/ - -SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s) - : Declaration(new Identifier(s->Sident, TOKidentifier)) -{ - this->loc = loc; - sym = s; - storage_class |= STCconst; -} - -Symbol *SymbolDeclaration::toSymbol() -{ - return sym; -} - -/************************************* - * Helper - */ - -Symbol *Dsymbol::toSymbolX(const char *prefix, int sclass, type *t) -{ - Symbol *s; - char *id; - char *n; - - n = mangle(); //ident->toChars(); - id = (char *) alloca(strlen(prefix) + strlen(n) + 1); - sprintf(id,"%s%s", prefix, n); - s = symbol_name(id, sclass, t); - return s; -} - -/************************************* - */ - -Symbol *Dsymbol::toSymbol() -{ - printf("Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind()); - assert(0); // BUG: implement - return NULL; -} - -/********************************* - * Generate import symbol from symbol. - */ - -Symbol *Dsymbol::toImport() -{ - if (!isym) - { - if (!csym) - csym = toSymbol(); - isym = toImport(csym); - } - return isym; -} - -/************************************* - */ - -Symbol *Dsymbol::toImport(Symbol *sym) -{ - char *id; - char *n; - Symbol *s; - type *t; - - //printf("Dsymbol::toImport('%s')\n", sym->Sident); - n = sym->Sident; - id = (char *) alloca(6 + strlen(n) + 5 + 1); - if (sym->Stype->Tmangle == mTYman_std) - { - sprintf(id,"_imp__%s@%d",n,type_paramsize(sym->Stype)); - } - else if (sym->Stype->Tmangle == mTYman_d) - sprintf(id,"_imp_%s",n); - else - sprintf(id,"_imp__%s",n); - t = type_alloc(TYnptr | mTYconst); - t->Tnext = sym->Stype; - t->Tnext->Tcount++; - t->Tmangle = mTYman_c; - t->Tcount++; - s = symbol_calloc(id); - s->Stype = t; - s->Sclass = SCextern; - s->Sfl = FLextern; - slist_add(s); - return s; -} - -/************************************* - */ - -Symbol *VarDeclaration::toSymbol() -{ - //printf("VarDeclaration::toSymbol(%s)\n", toChars()); - //if (needThis()) *(char*)0=0; - assert(!needThis()); - if (!csym) - { Symbol *s; - TYPE *t; - const char *id; - mangle_t m; - - if (isDataseg()) - id = mangle(); - else - id = ident->toChars(); - s = symbol_calloc(id); - - if (storage_class & STCout) - t = type_fake(TYnptr); - else if (isParameter()) - t = type->toCParamtype(); - else - t = type->toCtype(); - t->Tcount++; - - if (isDataseg()) - { - s->Sclass = SCextern; - s->Sfl = FLextern; - slist_add(s); - } - else - { - s->Sclass = SCauto; - s->Sfl = FLauto; - - if (nestedref) - { - /* Symbol is accessed by a nested function. Make sure - * it is not put in a register, and that the optimizer - * assumes it is modified across function calls and pointer - * dereferences. - */ - //printf("\tnested ref, not register\n"); - type_setcv(&t, t->Tty | mTYvolatile); - } - } - if (storage_class & STCconst) - { - // Insert const modifiers - tym_t tym = 0; - - if (storage_class & STCconst) - tym |= mTYconst; - type_setcv(&t, tym); - } - switch (linkage) - { - case LINKwindows: - m = mTYman_std; - break; - - case LINKpascal: - m = mTYman_pas; - break; - - case LINKc: - m = mTYman_c; - break; - - case LINKd: - m = mTYman_d; - break; - - case LINKcpp: - m = mTYman_cpp; - break; - - default: - printf("linkage = %d\n", linkage); - assert(0); - } - type_setmangle(&t, m); - s->Stype = t; - - csym = s; - } - return csym; -} - -/************************************* - */ - -Symbol *ClassInfoDeclaration::toSymbol() -{ - return cd->toSymbol(); -} - -/************************************* - */ - -Symbol *ModuleInfoDeclaration::toSymbol() -{ - return mod->toSymbol(); -} - -/************************************* - */ - -Symbol *TypeInfoDeclaration::toSymbol() -{ - //printf("TypeInfoDeclaration::toSymbol(%s), linkage = %d\n", toChars(), linkage); - return VarDeclaration::toSymbol(); -} - -/************************************* - */ - -Symbol *FuncDeclaration::toSymbol() -{ - if (!csym) - { Symbol *s; - TYPE *t; - const char *id; - -#if 0 - id = ident->toChars(); -#else - id = mangle(); -#endif - //printf("FuncDeclaration::toSymbol(%s)\n", toChars()); - //printf("\tid = '%s'\n", id); - //printf("\ttype = %s\n", type->toChars()); - s = symbol_calloc(id); - slist_add(s); - - { func_t *f; - - s->Sclass = SCglobal; - symbol_func(s); - f = s->Sfunc; - f->Fstartline.Slinnum = loc.linnum; - if (endloc.linnum) - f->Fendline.Slinnum = endloc.linnum; - else - f->Fendline.Slinnum = loc.linnum; - t = type->toCtype(); - } - - mangle_t msave = t->Tmangle; - if (isMain()) - { - t->Tty = TYnfunc; - t->Tmangle = mTYman_c; - } - else - { - switch (linkage) - { - case LINKwindows: - t->Tmangle = mTYman_std; - break; - - case LINKpascal: - t->Tmangle = mTYman_pas; - break; - - case LINKc: - t->Tmangle = mTYman_c; - break; - - case LINKd: - t->Tmangle = mTYman_d; - break; - - case LINKcpp: - t->Tmangle = mTYman_cpp; - break; - - default: - printf("linkage = %d\n", linkage); - assert(0); - } - } - if (msave) - assert(msave == t->Tmangle); - //printf("Tty = %d, mangle = x%x\n", t->Tty, t->Tmangle); - t->Tcount++; - s->Stype = t; - //s->Sfielddef = this; - - csym = s; - } - return csym; -} - -/************************************* - */ - -Symbol *FuncDeclaration::toThunkSymbol(int offset) -{ - Symbol *sthunk; - - toSymbol(); - -#if 0 - char *id; - char *n; - type *t; - - n = sym->Sident; - id = (char *) alloca(8 + 5 + strlen(n) + 1); - sprintf(id,"_thunk%d__%s", offset, n); - s = symbol_calloc(id); - slist_add(s); - s->Stype = csym->Stype; - s->Stype->Tcount++; -#endif - sthunk = symbol_generate(SCstatic, csym->Stype); - sthunk->Sflags |= SFLimplem; - cod3_thunk(sthunk, csym, 0, TYnptr, -offset, -1, 0); - return sthunk; -} - - -/**************************************** - * Create a static symbol we can hang DT initializers onto. - */ - -Symbol *static_sym() -{ - Symbol *s; - type *t; - - t = type_alloc(TYint); - t->Tcount++; - s = symbol_calloc("internal"); - s->Sclass = SCstatic; - s->Sfl = FLextern; - s->Sflags |= SFLnodebug; - s->Stype = t; -#if ELFOBJ // Burton - s->Sseg = DATA; -#endif /* ELFOBJ */ - slist_add(s); - return s; -} - -/************************************** - * Fake a struct symbol. - */ - -Classsym *fake_classsym(char *name) -{ TYPE *t; - Classsym *scc; - - scc = (Classsym *)symbol_calloc("ClassInfo"); - scc->Sclass = SCstruct; - scc->Sstruct = struct_calloc(); - scc->Sstruct->Sstructalign = 8; - //scc->Sstruct->ptrtype = TYnptr; - scc->Sstruct->Sflags = STRglobal; - - t = type_alloc(TYstruct); - t->Tflags |= TFsizeunknown | TFforward; - t->Ttag = scc; // structure tag name - assert(t->Tmangle == 0); - t->Tmangle = mTYman_c; - t->Tcount++; - scc->Stype = t; - slist_add(scc); - return scc; -} - -/************************************* - * Create the "ClassInfo" symbol - */ - -static Classsym *scc; - -Symbol *ClassDeclaration::toSymbol() -{ - if (!csym) - { - Symbol *s; - - if (!scc) - scc = fake_classsym("ClassInfo"); - - s = toSymbolX("_Class_", SCextern, scc->Stype); - s->Sfl = FLextern; - s->Sflags |= SFLnodebug; - csym = s; - slist_add(s); - } - return csym; -} - -/************************************* - * Create the "InterfaceInfo" symbol - */ - -Symbol *InterfaceDeclaration::toSymbol() -{ - if (!csym) - { - Symbol *s; - - if (!scc) - scc = fake_classsym("ClassInfo"); - - s = toSymbolX("_Interface_", SCextern, scc->Stype); - s->Sfl = FLextern; - s->Sflags |= SFLnodebug; - csym = s; - slist_add(s); - } - return csym; -} - -/************************************* - * Create the "ModuleInfo" symbol - */ - -Symbol *Module::toSymbol() -{ - if (!csym) - { - Symbol *s; - static Classsym *scc; - - if (!scc) - scc = fake_classsym("ModuleInfo"); - - s = toSymbolX("_ModuleInfo_", SCextern, scc->Stype); - s->Sfl = FLextern; - s->Sflags |= SFLnodebug; - csym = s; - slist_add(s); - } - return csym; -} - -/************************************* - * This is accessible via the ClassData, but since it is frequently - * needed directly (like for rtti comparisons), make it directly accessible. - */ - -Symbol *ClassDeclaration::toVtblSymbol() -{ - if (!vtblsym) - { - Symbol *s; - TYPE *t; - - if (!csym) - toSymbol(); - - t = type_alloc(TYnptr | mTYconst); - t->Tnext = tsvoid; - t->Tnext->Tcount++; - t->Tmangle = mTYman_c; - s = toSymbolX("_vtbl_", SCextern, t); - s->Sflags |= SFLnodebug; - s->Sfl = FLextern; - vtblsym = s; - slist_add(s); - } - return vtblsym; -} - -/********************************** - * Create the static initializer for the struct/class. - */ - -Symbol *AggregateDeclaration::toInitializer() -{ - char *id; - char *n; - Symbol *s; - Classsym *stag; - - if (!sinit) - { - n = mangle(); - stag = fake_classsym(n); - - id = (char *) alloca(6 + strlen(n) + 1); - sprintf(id,"_init_%s",n); - s = symbol_calloc(id); - s->Stype = stag->Stype; - s->Sclass = SCextern; - s->Sfl = FLextern; - s->Sflags |= SFLnodebug; - slist_add(s); - sinit = s; - } - return sinit; -} - - -/****************************************** - */ - -Symbol *Module::toModuleAssert() -{ - if (!massert) - { - type *t; - - t = type_alloc(TYjfunc); - t->Tflags |= TFprototype | TFfixed; - t->Tmangle = mTYman_d; - t->Tnext = tsvoid; - tsvoid->Tcount++; - - massert = toSymbolX("_assert_", SCextern, t); - massert->Sfl = FLextern; - massert->Sflags |= SFLnodebug; - slist_add(massert); - } - return massert; -} - -/****************************************** - */ - -Symbol *Module::toModuleArray() -{ - if (!marray) - { - type *t; - - t = type_alloc(TYjfunc); - t->Tflags |= TFprototype | TFfixed; - t->Tmangle = mTYman_d; - t->Tnext = tsvoid; - tsvoid->Tcount++; - - marray = toSymbolX("_array_", SCextern, t); - marray->Sfl = FLextern; - marray->Sflags |= SFLnodebug; - slist_add(marray); - } - return marray; -} - -/******************************************** - * Determine the right symbol to look up - * an associative array element. - * Input: - * flags 0 don't add value signature - * 1 add value signature - */ - -Symbol *TypeAArray::aaGetSymbol(char *func, int flags) -#if __DMC__ - __in - { - assert(func); - assert((flags & ~1) == 0); - } - __out (result) - { - assert(result); - } - __body -#endif - { - int sz; - char *id; - type *t; - Symbol *s; - int i; - - // Dumb linear symbol table - should use associative array! - static Array *sarray = NULL; - - //printf("aaGetSymbol(func = '%s', flags = %d, key = %p)\n", func, flags, key); -#if 0 - OutBuffer buf; - key->toKeyBuffer(&buf); - - sz = next->size(); // it's just data, so we only care about the size - sz = (sz + 3) & ~3; // reduce proliferation of library routines - id = (char *)alloca(3 + strlen(func) + buf.offset + sizeof(sz) * 3 + 1); - buf.writeByte(0); - if (flags & 1) - sprintf(id, "_aa%s%s%d", func, buf.data, sz); - else - sprintf(id, "_aa%s%s", func, buf.data); -#else - id = (char *)alloca(3 + strlen(func) + 1); - sprintf(id, "_aa%s", func); -#endif - if (!sarray) - sarray = new Array(); - - // See if symbol is already in sarray - for (i = 0; i < sarray->dim; i++) - { s = (Symbol *)sarray->data[i]; - if (strcmp(id, s->Sident) == 0) - return s; // use existing Symbol - } - - // Create new Symbol - - s = symbol_calloc(id); - slist_add(s); - s->Sclass = SCextern; - s->Ssymnum = -1; - symbol_func(s); - - t = type_alloc(TYnfunc); - t->Tflags = TFprototype | TFfixed; - t->Tmangle = mTYman_c; - t->Tparamtypes = NULL; - t->Tnext = next->toCtype(); - t->Tnext->Tcount++; - t->Tcount++; - s->Stype = t; - - sarray->push(s); // remember it - return s; - } - diff -uNr gdc-0.11/d/root/todt.c gdc-0.12/d/root/todt.c --- gdc-0.11/d/root/todt.c 2005-04-17 14:44:07.000000000 +0200 +++ gdc-0.12/d/root/todt.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,801 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -/* A dt_t is a simple structure representing data to be added - * to the data segment of the output object file. As such, - * it is a list of initialized bytes, 0 data, and offsets from - * other symbols. - * Each D symbol and type can be converted into a dt_t so it can - * be written to the data segment. - */ - -#undef integer_t -#include -#include -#include -#include -#include - -#ifdef __APPLE__ -#define integer_t dmd_integer_t -#endif - -#include "lexer.h" -#include "mtype.h" -#include "expression.h" -#include "init.h" -#include "enum.h" -#include "aggregate.h" -#include "declaration.h" - - -// Back end -#ifndef IN_GCC -#include "cc.h" -#include "el.h" -#include "oper.h" -#include "global.h" -#include "code.h" -#include "type.h" -#endif -#include "dt.h" - -extern Symbol *static_sym(); - -/* ================================================================ */ - -dt_t *Initializer::toDt() -{ - assert(0); - return NULL; -} - - -dt_t *StructInitializer::toDt() -{ - Array dts; - unsigned i; - unsigned j; - dt_t *dt; - dt_t *d; - dt_t **pdtend; - unsigned offset; - - //printf("StructInitializer::toDt('%s')\n", toChars()); - dts.setDim(ad->fields.dim); - dts.zero(); - - for (i = 0; i < field.dim; i++) - { - VarDeclaration *v = (VarDeclaration *)field.data[i]; - Initializer *val = (Initializer *)value.data[i]; - - //printf("field[%d] = %s\n", i, v->toChars()); - - for (j = 0; 1; j++) - { - assert(j < dts.dim); - //printf(" adfield[%d] = %s\n", j, ((VarDeclaration *)ad->fields.data[j])->toChars()); - if ((VarDeclaration *)ad->fields.data[j] == v) - { - if (dts.data[j]) - error("field %s of %s already initialized", v->toChars(), ad->toChars()); - dts.data[j] = (void *)val->toDt(); - break; - } - } - } - - dt = NULL; - pdtend = &dt; - offset = 0; - for (j = 0; j < dts.dim; j++) - { - VarDeclaration *v = (VarDeclaration *)ad->fields.data[j]; - - d = (dt_t *)dts.data[j]; - if (!d) - { // An instance specific initializer was not provided. - // Look to see if there's a default initializer from the - // struct definition - VarDeclaration *v = (VarDeclaration *)ad->fields.data[j]; - - if (v->init) - { - d = v->init->toDt(); - } - else if (v->offset >= offset) - { - unsigned k; - unsigned offset2 = v->offset + v->type->size(); - // Make sure this field does not overlap any explicitly - // initialized field. - for (k = j + 1; 1; k++) - { - if (k == dts.dim) // didn't find any overlap - { v->type->toDt(&d); // provide default initializer - break; - } - VarDeclaration *v2 = (VarDeclaration *)ad->fields.data[k]; - - if (v2->offset < offset2 && dts.data[k]) - break; // overlap - } - } - } - if (d) - { - if (v->offset < offset) - error("duplicate union initialization for %s", v->toChars()); - else - { unsigned sz = dt_size(d); - - if (offset < v->offset) - pdtend = dtnzeros(pdtend, v->offset - offset); - pdtend = dtcat(pdtend, d); - assert(sz <= v->type->size()); - offset = v->offset + sz; - } - } - } - if (offset < ad->structsize) - dtnzeros(pdtend, ad->structsize - offset); - - return dt; -} - - -dt_t *ArrayInitializer::toDt() -{ - //printf("ArrayInitializer::toDt('%s')\n", toChars()); - Type *tb = type->toBasetype(); - Type *tn = tb->next->toBasetype(); - - if (tn->ty == Tbit) - return toDtBit(); - - Array dts; - unsigned size; - unsigned length; - unsigned i; - dt_t *dt; - dt_t *d; - dt_t **pdtend; - - //printf("dim = %d\n", dim); - dts.setDim(dim); - dts.zero(); - - size = tn->size(); - - length = 0; - for (i = 0; i < index.dim; i++) - { Expression *idx; - Initializer *val; - - idx = (Expression *)index.data[i]; - if (idx) - length = idx->toInteger(); - //printf("index[%d] = %p, length = %d\n", i, idx, length); - - val = (Initializer *)value.data[i]; - dt = val->toDt(); - if (dts.data[length]) - error("duplicate initializations for index %d", length); - dts.data[length] = (void *)dt; - length++; - } - - d = NULL; - pdtend = &d; - for (i = 0; i < dim; i++) - { - dt = (dt_t *)dts.data[i]; - if (dt) - pdtend = dtcat(pdtend, dt); - else - pdtend = tn->toDt(pdtend); - } - switch (tb->ty) - { - case Tsarray: - { unsigned tadim; - TypeSArray *ta = (TypeSArray *)tb; - - tadim = ta->dim->toInteger(); - if (dim < tadim) - pdtend = dtnzeros(pdtend, size * (tadim - dim)); // pad out end of array - else if (dim > tadim) - error("too many initializers %d for array[%d]", dim, tadim); - break; - } - - case Tpointer: - case Tarray: - // Create symbol, and then refer to it - Symbol *s; - s = static_sym(); - s->Sdt = d; - outdata(s); - - d = NULL; - if (tb->ty == Tarray) - dtdword(&d, dim); - dtxoff(&d, s, 0, TYnptr); - break; - - default: - assert(0); - } - return d; -} - - -dt_t *ArrayInitializer::toDtBit() -{ - unsigned size; - unsigned length; - unsigned i; - unsigned tadim; - dt_t *d; - dt_t **pdtend; - Type *tb = type->toBasetype(); - - Bits databits; - Bits initbits; - - if (tb->ty == Tsarray) - { - /* The 'dim' for ArrayInitializer is only the maximum dimension - * seen in the initializer, not the type. So, for static arrays, - * use instead the dimension of the type in order - * to get the whole thing. - */ - integer_t value = ((TypeSArray*)tb)->dim->toInteger(); - tadim = value; - assert(tadim == value); // truncation overflow should already be checked - databits.resize(tadim); - initbits.resize(tadim); - } - else - { - databits.resize(dim); - initbits.resize(dim); - } - - /* The default initializer may be something other than zero. - */ - if (tb->next->defaultInit()->toInteger()) - databits.set(); - - size = sizeof(databits.data[0]); - - length = 0; - for (i = 0; i < index.dim; i++) - { Expression *idx; - Initializer *val; - Expression *eval; - - idx = (Expression *)index.data[i]; - if (idx) - { integer_t value; - value = idx->toInteger(); - length = value; - if (length != value) - { error("index overflow %llu", value); - length = 0; - } - } - assert(length < dim); - - val = (Initializer *)value.data[i]; - eval = val->toExpression(); - if (initbits.test(length)) - error("duplicate initializations for index %d", length); - initbits.set(length); - if (eval->toInteger()) // any non-zero value is boolean 'true' - databits.set(length); - else - databits.clear(length); // boolean 'false' - length++; - } - - d = NULL; -#ifdef IN_GCC - pdtend = dtnbits(&d, databits.allocdim * size, (char *)databits.data, sizeof(databits.data[0])); -#else - pdtend = dtnbytes(&d, databits.allocdim * size, (char *)databits.data); -#endif - switch (tb->ty) - { - case Tsarray: - { - if (dim > tadim) - error("too many initializers %d for array[%d]", dim, tadim); - else - { - tadim = (tadim + 31) / 32; - if (databits.allocdim < tadim) - pdtend = dtnzeros(pdtend, size * (tadim - databits.allocdim)); // pad out end of array - } - break; - } - - case Tpointer: - case Tarray: - // Create symbol, and then refer to it - Symbol *s; - s = static_sym(); - s->Sdt = d; - outdata(s); - - d = NULL; - if (tb->ty == Tarray) - dtdword(&d, dim); - dtxoff(&d, s, 0, TYnptr); - break; - - default: - assert(0); - } - return d; -} - - -dt_t *ExpInitializer::toDt() -{ - dt_t *dt = NULL; - - exp = exp->optimize(WANTvalue); - exp->toDt(&dt); - return dt; -} - -/* ================================================================ */ - -dt_t **Expression::toDt(dt_t **pdt) -{ - //printf("Expression::toDt() %d\n", op); - error("non-constant expression %s", toChars()); - pdt = dtnzeros(pdt, 1); - return pdt; -} - -#ifndef IN_GCC - -dt_t **IntegerExp::toDt(dt_t **pdt) -{ unsigned sz; - - //printf("IntegerExp::toDt() %d\n", op); - sz = type->size(); - if (value == 0) - pdt = dtnzeros(pdt, sz); - else - pdt = dtnbytes(pdt, sz, (char *)&value); - return pdt; -} - -dt_t **RealExp::toDt(dt_t **pdt) -{ - d_float32 fvalue; - d_float64 dvalue; - d_float80 evalue; - - //printf("RealExp::toDt(%Lg)\n", value); - switch (type->toBasetype()->ty) - { - case Tfloat32: - fvalue = value; - pdt = dtnbytes(pdt,4,(char *)&fvalue); - break; - - case Tfloat64: - dvalue = value; - pdt = dtnbytes(pdt,8,(char *)&dvalue); - break; - - case Tfloat80: - evalue = value; - pdt = dtnbytes(pdt,10,(char *)&evalue); - break; - - default: - printf("%s\n", toChars()); - type->print(); - assert(0); - break; - } - return pdt; -} - -dt_t **ImaginaryExp::toDt(dt_t **pdt) -{ - d_float32 fvalue; - d_float64 dvalue; - d_float80 evalue; - - switch (type->toBasetype()->ty) - { - case Timaginary32: - fvalue = value; - pdt = dtnbytes(pdt,4,(char *)&fvalue); - break; - - case Timaginary64: - dvalue = value; - pdt = dtnbytes(pdt,8,(char *)&dvalue); - break; - - case Timaginary80: - evalue = value; - pdt = dtnbytes(pdt,10,(char *)&evalue); - break; - - default: - assert(0); - break; - } - return pdt; -} - -dt_t **ComplexExp::toDt(dt_t **pdt) -{ - d_float32 fvalue; - d_float64 dvalue; - d_float80 evalue; - - switch (type->toBasetype()->ty) - { - case Tcomplex32: - fvalue = creall(value); - pdt = dtnbytes(pdt,4,(char *)&fvalue); - fvalue = cimagl(value); - pdt = dtnbytes(pdt,4,(char *)&fvalue); - break; - - case Tcomplex64: - dvalue = creall(value); - pdt = dtnbytes(pdt,8,(char *)&dvalue); - dvalue = cimagl(value); - pdt = dtnbytes(pdt,8,(char *)&dvalue); - break; - - case Tcomplex80: - evalue = creall(value); - pdt = dtnbytes(pdt,10,(char *)&evalue); - evalue = cimagl(value); - pdt = dtnbytes(pdt,10,(char *)&evalue); - break; - - default: - assert(0); - break; - } - return pdt; -} - - -#endif - -dt_t **NullExp::toDt(dt_t **pdt) -{ - assert(type); - return dtnzeros(pdt, type->size()); -} - -dt_t **StringExp::toDt(dt_t **pdt) -{ - Type *t = type->toBasetype(); - - // BUG: should implement some form of static string pooling - switch (t->ty) - { - case Tarray: - dtdword(pdt, len); -#ifndef IN_GCC - pdt = dtabytes(pdt, TYnptr, 0, (len + 1) * sz, (char *)string); -#else - pdt = dtawords(pdt, len + 1, string, sz); -#endif - break; - - case Tsarray: - { TypeSArray *tsa = (TypeSArray *)type; - integer_t dim; - -#ifndef IN_GCC - pdt = dtnbytes(pdt, len * sz, (char *)string); -#else - pdt = dtnwords(pdt, len, string, sz); -#endif - if (tsa->dim) - { - dim = tsa->dim->toInteger(); - if (len < dim) - { - // Pad remainder with 0 - pdt = dtnzeros(pdt, (dim - len) * tsa->next->size()); - } - } - break; - } - case Tpointer: -#ifndef IN_GCC - pdt = dtabytes(pdt, TYnptr, 0, (len + 1) * sz, (char *)string); -#else - pdt = dtawords(pdt, len + 1, string, sz); -#endif - break; - - default: - printf("StringExp::toDt(type = %s)\n", type->toChars()); - assert(0); - } - return pdt; -} - -dt_t **SymOffExp::toDt(dt_t **pdt) -{ - Symbol *s; - - //printf("SymOffExp::toDt('%s')\n", var->toChars()); - assert(var); - if (!(var->isDataseg() || var->isCodeseg()) || var->needThis()) - { error("non-constant expression %s", toChars()); - return pdt; - } - s = var->toSymbol(); - return dtxoff(pdt, s, offset, TYnptr); -} - -dt_t **VarExp::toDt(dt_t **pdt) -{ - //printf("VarExp::toDt() %d\n", op); - VarDeclaration *v = var->isVarDeclaration(); - if (v && v->isConst() && type->toBasetype()->ty != Tsarray && v->init) - { dt_t **pdtend; - - for (pdtend = pdt; *pdtend; pdtend = &((*pdtend)->DTnext)) - ; - *pdtend = v->init->toDt(); - return pdt; - } - error("non-constant expression %s", toChars()); - pdt = dtnzeros(pdt, 1); - return pdt; -} - -/* ================================================================= */ - -// Generate the data for the static initializer. - -void ClassDeclaration::toDt(dt_t **pdt) -{ - //printf("ClassDeclaration::toDt(this = '%s')\n", toChars()); - - // Put in first two members, the vtbl[] and the monitor - dtxoff(pdt, toVtblSymbol(), 0, TYnptr); - dtdword(pdt, 0); // monitor - - // Put in the rest - toDt2(pdt, this); - - //printf("-ClassDeclaration::toDt(this = '%s')\n", toChars()); -} - -void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) -{ - unsigned offset; - unsigned i; - dt_t *dt; - unsigned csymoffset; - -#define LOG 0 - -#if LOG - printf("ClassDeclaration::toDt2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); -#endif - if (baseClass) - { - baseClass->toDt2(pdt, cd); - offset = baseClass->structsize; - } - else - { - offset = 8; - } - - // Note equivalence of this loop to struct's - for (i = 0; i < fields.dim; i++) - { - VarDeclaration *v = (VarDeclaration *)fields.data[i]; - Initializer *init; - - //printf("\t\tv->offset = %d, offset = %d\n", v->offset, offset); - dt = NULL; - init = v->init; - if (init) - { //printf("\t\t%s has initializer %s\n", v->toChars(), init->toChars()); - dt = init->toDt(); - } - else if (v->offset >= offset) - v->type->toDt(&dt); - if (dt) - { - if (v->offset < offset) - error("2duplicate union initialization for %s", v->toChars()); - else - { - if (offset < v->offset) - dtnzeros(pdt, v->offset - offset); - dtcat(pdt, dt); - offset = v->offset + v->type->size(); - } - } - } - - // Interface vptr initializations - toSymbol(); // define csym - - for (i = 0; i < vtblInterfaces->dim; i++) - { BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; - -#if 1 || INTERFACE_VIRTUAL - for (ClassDeclaration *cd2 = cd; 1; cd2 = cd2->baseClass) - { - assert(cd2); - csymoffset = cd2->baseVtblOffset(b); - if (csymoffset != ~0) - { - if (offset < b->offset) - dtnzeros(pdt, b->offset - offset); - dtxoff(pdt, cd2->toSymbol(), csymoffset, TYnptr); - break; - } - } -#else - csymoffset = baseVtblOffset(b); - assert(csymoffset != ~0); - dtxoff(pdt, csym, csymoffset, TYnptr); -#endif - offset = b->offset + 4; - } - - if (offset < structsize) - dtnzeros(pdt, structsize - offset); - -#undef LOG -} - -void StructDeclaration::toDt(dt_t **pdt) -{ - unsigned offset; - unsigned i; - dt_t *dt; - - //printf("StructDeclaration::toDt(), this='%s'\n", toChars()); - offset = 0; - - // Note equivalence of this loop to class's - for (i = 0; i < fields.dim; i++) - { - VarDeclaration *v = (VarDeclaration *)fields.data[i]; - Initializer *init; - - //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset); - dt = NULL; - init = v->init; - if (init) - { //printf("\t\thas initializer %s\n", init->toChars()); - dt = init->toDt(); - } - else if (v->offset >= offset) - v->type->toDt(&dt); - if (dt) - { - if (v->offset < offset) - error("overlapping initialization for struct %s.%s", toChars(), v->toChars()); - else - { - if (offset < v->offset) - dtnzeros(pdt, v->offset - offset); - dtcat(pdt, dt); - offset = v->offset + v->type->size(); - } - } - } - - if (offset < structsize) - dtnzeros(pdt, structsize - offset); - - dt_optimize(*pdt); -} - -/* ================================================================= */ - -dt_t **Type::toDt(dt_t **pdt) -{ - //printf("Type::toDt()\n"); - Expression *e = defaultInit(); - return e->toDt(pdt); -} - -dt_t **TypeSArray::toDt(dt_t **pdt) -{ - int i; - unsigned len; - - len = dim->toInteger(); - if (len) - { - while (*pdt) - pdt = &((*pdt)->DTnext); - if (next->toBasetype()->ty == Tbit) - { - Bits databits; - - databits.resize(len); - if (next->defaultInit()->toInteger()) - databits.set(); -#ifdef IN_GCC - pdt = dtnbits(pdt, databits.allocdim * sizeof(databits.data[0]), - (char *)databits.data, sizeof(databits.data[0])); -#else - pdt = dtnbytes(pdt, databits.allocdim * sizeof(databits.data[0]), - (char *)databits.data); -#endif - } - else - { - next->toDt(pdt); - if ((*pdt)->dt == DT_azeros && !(*pdt)->DTnext) - { - (*pdt)->DTazeros *= len; - } - else - { - for (i = 1; i < len; i++) - { - pdt = next->toDt(pdt); - } - } - } - } - return pdt; -} - -dt_t **TypeStruct::toDt(dt_t **pdt) -{ - sym->toDt(pdt); - return pdt; -} - -dt_t **TypeTypedef::toDt(dt_t **pdt) -{ - if (sym->init) - { - dt_t *dt = sym->init->toDt(); - - while (*pdt) - pdt = &((*pdt)->DTnext); - *pdt = dt; - return pdt; - } - sym->basetype->toDt(pdt); - return pdt; -} - - - diff -uNr gdc-0.11/d/root/toobj.c gdc-0.12/d/root/toobj.c --- gdc-0.11/d/root/toobj.c 2005-04-28 05:11:56.000000000 +0200 +++ gdc-0.12/d/root/toobj.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,998 +0,0 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include -#include -#include - -#include "mars.h" -#include "module.h" -#include "mtype.h" -#include "declaration.h" -#include "statement.h" -#include "enum.h" -#include "aggregate.h" -#include "init.h" -#include "attrib.h" -#include "id.h" -#include "import.h" -#include "template.h" - -#include -#ifndef IN_GCC -#include "cc.h" -#include "global.h" -#include "oper.h" -#include "code.h" -#include "type.h" -#include "dt.h" -#include "cgcv.h" -#include "outbuf.h" -#include "irstate.h" -#else -#include "dt.h" -#endif - -#ifdef IN_GCC -#include "d-dmd-gcc.h" -#endif - -void obj_lzext(Symbol *s1,Symbol *s2); - -#ifdef IN_GCC -static bool m_in_a(Module * m, Array * a) { - for (unsigned i = 0; i < a->dim; i++) - if ( m == (Module *) a->data[i] ) - return true; - return false; -} -static void find_module_deps(Module * the_module, Array * out_deps) -{ - Array work; - unsigned wi = 0; - - work.push(the_module); - while (wi < work.dim) { - Module * a_module = (Module *) work.data[wi]; - for (unsigned i = 0; i < a_module->aimports.dim; i++) { - Module * an_imp = (Module*) a_module->aimports.data[i]; - if (m_in_a(an_imp, & work) || m_in_a(an_imp, out_deps)) - continue; - if (an_imp->strictlyneedmoduleinfo) - out_deps->push(an_imp); - else - work.push(an_imp); - } - wi++; - } -} -#endif - - -/* ================================================================== */ - -// Put out instance of ModuleInfo for this Module - -void Module::genmoduleinfo() -{ - Symbol *msym = toSymbol(); - unsigned offset; - unsigned sizeof_ModuleInfo = 12 * 4; - - ////////////////////////////////////////////// - - csym->Sclass = SCglobal; - csym->Sfl = FLdata; - - /* The layout is: - { - void **vptr; - monitor_t monitor; - char[] name; // class name - ModuleInfo importedModules[]; - ClassInfo localClasses[]; - uint flags; // initialization state - void *ctor; - void *dtor; - void *unitTest; - } - */ - dt_t *dt = NULL; - - if (moduleinfo) - dtxoff(&dt, moduleinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ModuleInfo - else - dtdword(&dt, 0); // BUG: should be an assert() - dtdword(&dt, 0); // monitor - - // name[] - char *name = ident->toChars(); - size_t namelen = strlen(name); - dtdword(&dt, namelen); - dtabytes(&dt, TYnptr, 0, namelen + 1, name); - - Array aclasses; - int i; - - //printf("members->dim = %d\n", members->dim); - for (i = 0; i < members->dim; i++) - { - Dsymbol *member; - - member = (Dsymbol *)members->data[i]; - //printf("\tmember '%s'\n", member->toChars()); - member->addLocalClass(&aclasses); - } - - // importedModules[] - int aimports_dim = aimports.dim; -#ifndef IN_GCC - for (i = 0; i < aimports.dim; i++) - { Module *m = (Module *)aimports.data[i]; - if (!m->needModuleInfo()) - aimports_dim--; - } -#else - Array adeps; - find_module_deps(this, & adeps); - aimports_dim = adeps.dim; -#endif - dtdword(&dt, aimports_dim); - if (aimports.dim) - dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr); - else - dtdword(&dt, 0); - - // localClasses[] - dtdword(&dt, aclasses.dim); - if (aclasses.dim) - dtxoff(&dt, csym, sizeof_ModuleInfo + aimports.dim * 4, TYnptr); - else - dtdword(&dt, 0); - - dtdword(&dt, 0); // flags - - if (sctor) - dtxoff(&dt, sctor, 0, TYnptr); - else - dtdword(&dt, 0); - - if (sdtor) - dtxoff(&dt, sdtor, 0, TYnptr); - else - dtdword(&dt, 0); - - if (stest) - dtxoff(&dt, stest, 0, TYnptr); - else - dtdword(&dt, 0); - - ////////////////////////////////////////////// - -#ifndef IN_GCC - for (i = 0; i < aimports.dim; i++) - { - Module *m; - - m = (Module *)aimports.data[i]; - if (m->needModuleInfo()) - { Symbol *s = m->toSymbol(); - s->Sflags |= SFLweak; - dtxoff(&dt, s, 0, TYnptr); - } - } -#else - for (i = 0; i < adeps.dim; i++) - { - Module *m; - Symbol *s; - - m = (Module *) adeps.data[i]; - s = m->toSymbol(); - s->Sflags |= SFLweak; // doesn't do anything yet, but see d-decls.cc:Module::toSymbol - dtxoff(&dt, s, 0, TYnptr); - } -#endif - - for (i = 0; i < aclasses.dim; i++) - { - ClassDeclaration *cd; - - cd = (ClassDeclaration *)aclasses.data[i]; - dtxoff(&dt, cd->toSymbol(), 0, TYnptr); - } - - csym->Sdt = dt; -#if ELFOBJ - // Cannot be CONST because the startup code sets flag bits in it - csym->Sseg = DATA; -#endif - outdata(csym); - - ////////////////////////////////////////////// - - obj_moduleinfo(msym); -} - -/* ================================================================== */ -void Dsymbol::toObjFile() -{ - //printf("Dsymbol::toObjFile('%s')\n", toChars()); - // ignore -} -/* ================================================================== */ - -void ClassDeclaration::toObjFile() -{ unsigned i; - unsigned offset; - Symbol *sinit; - enum_SC scclass; - - //printf("ClassDeclaration::toObjFile('%s')\n", toChars()); - - if (!members) - return; - - if (global.params.symdebug) - toDebug(); - - assert(!scope); // semantic() should have been run to completion - - if (parent && parent->isTemplateInstance()) - scclass = SCcomdat; - else - scclass = SCglobal; - - // Put out the members - for (i = 0; i < members->dim; i++) - { - Dsymbol *member; - - member = (Dsymbol *)members->data[i]; - member->toObjFile(); - } - - // Generate C symbols - toSymbol(); - toVtblSymbol(); - sinit = toInitializer(); - - ////////////////////////////////////////////// - - // Generate static initializer - sinit->Sclass = scclass; - sinit->Sfl = FLdata; -#if ELFOBJ // Burton - sinit->Sseg = CDATA; -#endif /* ELFOBJ */ - toDt(&sinit->Sdt); - outdata(sinit); - - ////////////////////////////////////////////// - - // Put out the ClassInfo - csym->Sclass = scclass; - csym->Sfl = FLdata; - - /* The layout is: - { - void **vptr; - monitor_t monitor; - byte[] initializer; // static initialization data - char[] name; // class name - void *[] vtbl; - Interface[] interfaces; - ClassInfo *base; // base class - void *destructor; - void *invariant; // class invariant - uint flags; - void *deallocator; - } - */ - dt_t *dt = NULL; - offset = CLASSINFO_SIZE; // must be ClassInfo.size - if (classinfo) - { - assert(classinfo->structsize == CLASSINFO_SIZE); - } - - if (classinfo) - dtxoff(&dt, classinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo - else - dtdword(&dt, 0); // BUG: should be an assert() - dtdword(&dt, 0); // monitor - - // initializer[] - assert(structsize >= 8); - dtdword(&dt, structsize); // size - dtxoff(&dt, sinit, 0, TYnptr); // initializer - - // name[] - char *name = ident->toChars(); - size_t namelen = strlen(name); - dtdword(&dt, namelen); - dtabytes(&dt, TYnptr, 0, namelen + 1, name); - - // vtbl[] - dtdword(&dt, vtbl.dim); - dtxoff(&dt, vtblsym, 0, TYnptr); - - // interfaces[] - dtdword(&dt, vtblInterfaces->dim); - if (vtblInterfaces->dim) - dtxoff(&dt, csym, offset, TYnptr); // (*) - else - dtdword(&dt, 0); - - // base - if (baseClass) - dtxoff(&dt, baseClass->toSymbol(), 0, TYnptr); - else - dtdword(&dt, 0); - - // destructor - if (dtor) - dtxoff(&dt, dtor->toSymbol(), 0, TYnptr); - else - dtdword(&dt, 0); - - // invariant - if (inv) - dtxoff(&dt, inv->toSymbol(), 0, TYnptr); - else - dtdword(&dt, 0); - - // flags - dtdword(&dt, com); - - - // deallocator - if (aggDelete) - dtxoff(&dt, aggDelete->toSymbol(), 0, TYnptr); - else - dtdword(&dt, 0); - - ////////////////////////////////////////////// - - // Put out vtblInterfaces->data[]. Must immediately follow csym, because - // of the fixup (*) - - offset += vtblInterfaces->dim * (4 * 4); - for (i = 0; i < vtblInterfaces->dim; i++) - { BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; - ClassDeclaration *id = b->base; - - /* The layout is: - * { - * ClassInfo *interface; - * void *[] vtbl; - * unsigned offset; - * } - */ - - // Fill in vtbl[] - b->fillVtbl(this, &b->vtbl, 1); - - dtxoff(&dt, id->toSymbol(), 0, TYnptr); // ClassInfo - - // vtbl[] - dtdword(&dt, id->vtbl.dim); - dtxoff(&dt, csym, offset, TYnptr); - - dtdword(&dt, b->offset); // this offset - - offset += id->vtbl.dim * 4; - } - - // Put out the vtblInterfaces->data[].vtbl[] - // This must be mirrored with ClassDeclaration::baseVtblOffset() - //printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces->dim, toChars()); - for (i = 0; i < vtblInterfaces->dim; i++) - { BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; - ClassDeclaration *id = b->base; - int j; - - //printf(" interface[%d] is '%s'\n", i, id->toChars()); - j = 0; - if (id->vtblOffset()) - { - // First entry is ClassInfo reference - //dtxoff(&dt, id->toSymbol(), 0, TYnptr); - - // First entry is struct Interface reference - dtxoff(&dt, csym, CLASSINFO_SIZE + i * (4 * 4), TYnptr); - j = 1; - } - assert(id->vtbl.dim == b->vtbl.dim); - for (; j < id->vtbl.dim; j++) - { - FuncDeclaration *fd; - - assert(j < b->vtbl.dim); -#if 0 - Object *o = (Object *)b->vtbl.data[j]; - if (o) - { - printf("o = %p\n", o); - assert(o->dyncast() == DYNCAST_DSYMBOL); - Dsymbol *s = (Dsymbol *)o; - printf("s->kind() = '%s'\n", s->kind()); - } -#endif - fd = (FuncDeclaration *)b->vtbl.data[j]; - if (fd) - dtxoff(&dt, fd->toThunkSymbol(b->offset), 0, TYnptr); - else - dtdword(&dt, 0); - } - } - -#if 1 - // Put out the overriding interface vtbl[]s. - // This must be mirrored with ClassDeclaration::baseVtblOffset() - //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset); - ClassDeclaration *cd; - Array bvtbl; - - for (cd = this->baseClass; cd; cd = cd->baseClass) - { - for (int k = 0; k < cd->vtblInterfaces->dim; k++) - { BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k]; - - if (bs->fillVtbl(this, &bvtbl, 0)) - { - //printf("\toverriding vtbl[] for %s\n", bs->base->toChars()); - ClassDeclaration *id = bs->base; - int j; - - j = 0; - if (id->vtblOffset()) - { - // First entry is ClassInfo reference - //dtxoff(&dt, id->toSymbol(), 0, TYnptr); - - // First entry is struct Interface reference - dtxoff(&dt, cd->toSymbol(), CLASSINFO_SIZE + k * (4 * 4), TYnptr); - j = 1; - } - - for (; j < id->vtbl.dim; j++) - { - FuncDeclaration *fd; - - assert(j < bvtbl.dim); - fd = (FuncDeclaration *)bvtbl.data[j]; - if (fd) - dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr); - else - dtdword(&dt, 0); - } - } - } - } -#endif -#if INTERFACE_VIRTUAL - // Put out the overriding interface vtbl[]s. - // This must be mirrored with ClassDeclaration::baseVtblOffset() - //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset); - for (i = 0; i < vtblInterfaces->dim; i++) - { BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; - ClassDeclaration *cd; - - for (cd = this->baseClass; cd; cd = cd->baseClass) - { - for (int k = 0; k < cd->vtblInterfaces->dim; k++) - { BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k]; - - if (b->base == bs->base) - { - //printf("\toverriding vtbl[] for %s\n", b->base->toChars()); - ClassDeclaration *id = b->base; - int j; - - j = 0; - if (id->vtblOffset()) - { - // First entry is ClassInfo reference - //dtxoff(&dt, id->toSymbol(), 0, TYnptr); - - // First entry is struct Interface reference - dtxoff(&dt, cd->toSymbol(), CLASSINFO_SIZE + k * (4 * 4), TYnptr); - j = 1; - } - - for (; j < id->vtbl.dim; j++) - { - FuncDeclaration *fd; - - assert(j < b->vtbl.dim); - fd = (FuncDeclaration *)b->vtbl.data[j]; - if (fd) - dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr); - else - dtdword(&dt, 0); - } - } - } - } - } -#endif - - - csym->Sdt = dt; -#if ELFOBJ // Burton - // ClassInfo cannot be const data, because we use the monitor on it - csym->Sseg = DATA; -#endif /* ELFOBJ */ - outdata(csym); - if (isExport()) - obj_export(csym,0); - - ////////////////////////////////////////////// - - // Put out the vtbl[] - //printf("putting out %s.vtbl[]\n", toChars()); - dt = NULL; - if (0) - i = 0; - else - { dtxoff(&dt, csym, 0, TYnptr); // first entry is ClassInfo reference - i = 1; - } - for (; i < vtbl.dim; i++) - { - FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration(); - - //printf("\tvtbl[%d] = %p\n", i, fd); - if (fd && (fd->fbody || !isAbstract())) - { - dtxoff(&dt, fd->toSymbol(), 0, TYnptr); - } - else - dtdword(&dt, 0); - } - vtblsym->Sdt = dt; - vtblsym->Sclass = scclass; - vtblsym->Sfl = FLdata; -#if ELFOBJ // Burton - vtblsym->Sseg = CDATA; -#endif /* ELFOBJ */ - outdata(vtblsym); - if (isExport()) - obj_export(vtblsym,0); -} - -/****************************************** - * Get offset of base class's vtbl[] initializer from start of csym. - * Returns ~0 if not this csym. - */ - -unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc) -{ - unsigned csymoffset; - int i; - - //printf("ClassDeclaration::baseVtblOffset('%s', bc = %p)\n", toChars(), bc); - csymoffset = CLASSINFO_SIZE; - csymoffset += vtblInterfaces->dim * (4 * 4); - - for (i = 0; i < vtblInterfaces->dim; i++) - { - BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; - - if (b == bc) - return csymoffset; - csymoffset += b->base->vtbl.dim * 4; - } - -#if 1 - // Put out the overriding interface vtbl[]s. - // This must be mirrored with ClassDeclaration::baseVtblOffset() - //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset); - ClassDeclaration *cd; - Array bvtbl; - - for (cd = this->baseClass; cd; cd = cd->baseClass) - { - for (int k = 0; k < cd->vtblInterfaces->dim; k++) - { BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k]; - - if (bs->fillVtbl(this, NULL, 0)) - { - if (bc == bs) - { //printf("\tcsymoffset = x%x\n", csymoffset); - return csymoffset; - } - csymoffset += bs->base->vtbl.dim * 4; - } - } - } -#endif -#if INTERFACE_VIRTUAL - for (i = 0; i < vtblInterfaces->dim; i++) - { BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; - ClassDeclaration *cd; - - for (cd = this->baseClass; cd; cd = cd->baseClass) - { - //printf("\tbase class %s\n", cd->toChars()); - for (int k = 0; k < cd->vtblInterfaces->dim; k++) - { BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k]; - - if (bc == bs) - { //printf("\tcsymoffset = x%x\n", csymoffset); - return csymoffset; - } - if (b->base == bs->base) - csymoffset += bs->base->vtbl.dim * 4; - } - } - } -#endif - - return ~0; -} - -/* ================================================================== */ - -void InterfaceDeclaration::toObjFile() -{ unsigned i; - unsigned offset; - Symbol *sinit; - enum_SC scclass; - - //printf("InterfaceDeclaration::toObjFile('%s')\n", toChars()); - - if (members && global.params.symdebug) - toDebug(); - - if (parent && parent->isTemplateInstance()) - scclass = SCcomdat; - else - scclass = SCglobal; - - // Put out the members - for (i = 0; i < members->dim; i++) - { - Dsymbol *member; - - member = (Dsymbol *)members->data[i]; - if (!member->isFuncDeclaration()) - member->toObjFile(); - } - - // Generate C symbols - toSymbol(); - - ////////////////////////////////////////////// - - // Put out the ClassInfo - csym->Sclass = scclass; - csym->Sfl = FLdata; - - /* The layout is: - { - void **vptr; - monitor_t monitor; - byte[] initializer; // static initialization data - char[] name; // class name - void *[] vtbl; - Interface[] interfaces; - Object *base; // base class - void *destructor; - void *invariant; // class invariant - uint flags; - void *deallocator; - } - */ - dt_t *dt = NULL; - - if (classinfo) - dtxoff(&dt, classinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo - else - dtdword(&dt, 0); // BUG: should be an assert() - dtdword(&dt, 0); // monitor - - // initializer[] - dtdword(&dt, 0); // size - dtdword(&dt, 0); // initializer - - // name[] - char *name = ident->toChars(); - size_t namelen = strlen(name); - dtdword(&dt, namelen); - dtabytes(&dt, TYnptr, 0, namelen + 1, name); - - // vtbl[] - dtdword(&dt, 0); - dtdword(&dt, 0); - - // vtblInterfaces->data[] - dtdword(&dt, vtblInterfaces->dim); - if (vtblInterfaces->dim) - { - if (classinfo) - assert(classinfo->structsize == CLASSINFO_SIZE); - offset = CLASSINFO_SIZE; - dtxoff(&dt, csym, offset, TYnptr); // (*) - } - else - dtdword(&dt, 0); - - // base - assert(!baseClass); - dtdword(&dt, 0); - - // dtor - dtdword(&dt, 0); - - // invariant - dtdword(&dt, 0); - - // flags - dtdword(&dt, com); - - // deallocator - dtdword(&dt, 0); - - ////////////////////////////////////////////// - - // Put out vtblInterfaces->data[]. Must immediately follow csym, because - // of the fixup (*) - - offset += vtblInterfaces->dim * (4 * 4); - for (i = 0; i < vtblInterfaces->dim; i++) - { BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; - ClassDeclaration *id = b->base; - - // ClassInfo - dtxoff(&dt, id->toSymbol(), 0, TYnptr); - - // vtbl[] - dtdword(&dt, 0); - dtdword(&dt, 0); - - // this offset - dtdword(&dt, b->offset); - } - - csym->Sdt = dt; -#if ELFOBJ // Burton - csym->Sseg = CDATA; -#endif /* ELFOBJ */ - outdata(csym); - if (isExport()) - obj_export(csym,0); -} - -/* ================================================================== */ - -void StructDeclaration::toObjFile() -{ unsigned i; - - //printf("StructDeclaration::toObjFile('%s')\n", toChars()); - - // Anonymous structs/unions only exist as part of others, - // do not output forward referenced structs's - if (!isAnonymous() && members) - { - if (global.params.symdebug) - toDebug(); - - // Generate static initializer - toInitializer(); - if (parent && parent->isTemplateInstance()) - sinit->Sclass = SCcomdat; - else - sinit->Sclass = SCglobal; - sinit->Sfl = FLdata; - toDt(&sinit->Sdt); - -#if !ELFOBJ - /* ELF comdef's generate multiple - * definition errors for them from the gnu linker. - * Need to figure out how to generate proper comdef's for ELF. - */ - // See if we can convert a comdat to a comdef, - // which saves on exe file space. - if (sinit->Sclass == SCcomdat && - sinit->Sdt->dt == DT_azeros && - sinit->Sdt->DTnext == NULL) - { - sinit->Sclass = SCglobal; - sinit->Sdt->dt = DT_common; - } -#endif - -#if ELFOBJ // Burton - sinit->Sseg = CDATA; -#endif /* ELFOBJ */ - outdata(sinit); - - // Put out the members - for (i = 0; i < members->dim; i++) - { - Dsymbol *member; - - member = (Dsymbol *)members->data[i]; - member->toObjFile(); - } - } -} - -/* ================================================================== */ - -void VarDeclaration::toObjFile() -{ - Symbol *s; - unsigned sz; - Dsymbol *parent; - - //printf("VarDeclaration::toObjFile(%p '%s') protection %d\n", this, toChars(), protection); - - if (isDataseg()) - { - s = toSymbol(); - sz = type->size(); - - parent = this->toParent(); -#if 1 /* private statics should still get a global symbol, in case - * another module inlines a function that references it. - */ - if (/*protection == PROTprivate ||*/ - !parent || parent->ident == NULL || parent->isFuncDeclaration()) - s->Sclass = SCstatic; - else -#endif - if (parent->isTemplateInstance() || - storage_class & STCcomdat) - // Global template data members need to be in comdat's - // in case multiple .obj files instantiate the same - // template with the same types. - s->Sclass = SCcomdat; - else - s->Sclass = SCglobal; - s->Sfl = FLdata; - - if (init) - { s->Sdt = init->toDt(); - - // Look for static array that is block initialized - Type *tb; - ExpInitializer *ie = init->isExpInitializer(); - - tb = type->toBasetype(); - if (tb->ty == Tsarray && ie && - !tb->next->equals(ie->exp->type->toBasetype()->next) && - ie->exp->implicitConvTo(tb->next) - ) - { - int dim; - - dim = ((TypeSArray *)tb)->dim->toInteger(); - - if (tb->next->toBasetype()->ty == Tbit) - { integer_t value; - -#ifndef IN_GCC - value = ie->exp->toInteger(); - value = (value & 1) ? ~(integer_t)0 : (integer_t)0; - if (value == 0) - { - dtnzeros(&s->Sdt, ((unsigned)dim + 31) / 32 * 4); - } - else - { - while (dim >= 32) - { - dtnbytes(&s->Sdt, 4, (char *)&value); - dim -= 32; - } - if (dim) - { - value = (1 << dim) - 1; - dtnbytes(&s->Sdt, 4, (char *)&value); - } - } -#else - - s->Sdt = NULL; - if (ie->exp->toInteger()) { - Bits databits; - databits.resize(dim); - databits.set(); - dtnbits(& s->Sdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data, sizeof(databits.data[0])); - } else { - dtnzeros(&s->Sdt, ((unsigned)dim + 31) / 32 * 4); - } -#endif - } - else - { - // Duplicate Sdt 'dim-1' times, as we already have the first one - while (--dim > 0) - { - ie->exp->toDt(&s->Sdt); - } - } - } - } - else - { - if (storage_class & STCextern) - { - s->Sclass = SCextern; - s->Sfl = FLextern; - s->Sdt = NULL; - // BUG: if isExport(), shouldn't we make it dllimport? - return; - } - type->toDt(&s->Sdt); - } - dt_optimize(s->Sdt); - - // See if we can convert a comdat to a comdef, - // which saves on exe file space. - if (s->Sclass == SCcomdat && - s->Sdt->dt == DT_azeros && - s->Sdt->DTnext == NULL) - { - s->Sclass = SCglobal; - s->Sdt->dt = DT_common; - } - -#if ELFOBJ // Burton - if (s->Sdt && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL) - s->Sseg = UDATA; - else - s->Sseg = DATA; -#endif /* ELFOBJ */ - outdata(s); - if (isExport()) - obj_export(s,0); - } -#ifdef IN_GCC - else { - // This is needed for VarDeclarations in mixins that are to be - // local variables of a function. Otherwise, it would be - // enough to make a check for isVarDeclaration() in - // DeclarationExp::toElem. - d_gcc_emit_local_variable(this); - } -#endif -} - -/* ================================================================== */ - -void TypedefDeclaration::toObjFile() -{ - //printf("TypedefDeclaration::toObjFile('%s')\n", toChars()); - - if (global.params.symdebug) - toDebug(); -} - -/* ================================================================== */ - -void EnumDeclaration::toObjFile() -{ - //printf("EnumDeclaration::toObjFile('%s')\n", toChars()); - - if (global.params.symdebug) - toDebug(); -} - - diff -uNr gdc-0.11/d/root/total.h gdc-0.12/d/root/total.h --- gdc-0.11/d/root/total.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/total.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,43 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_TOTAL_H -#define DMD_TOTAL_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include -#include -#include -#include -#include - -#include "root.h" -#include "stringtable.h" - -#include "mars.h" -#include "lexer.h" -#include "parse.h" -#include "identifier.h" -#include "enum.h" -#include "aggregate.h" -#include "mtype.h" -#include "expression.h" -#include "declaration.h" -#include "statement.h" -#include "scope.h" -#include "import.h" -#include "module.h" -#include "id.h" -#include "debcond.h" -#include "version.h" - -#endif /* DMD_TOTAL_H */ diff -uNr gdc-0.11/d/root/typinf.c gdc-0.12/d/root/typinf.c --- gdc-0.11/d/root/typinf.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/typinf.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,578 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -#include -#include - -//#include "mem.h" - -#include "mars.h" -#include "module.h" -#include "mtype.h" -#include "scope.h" -#include "init.h" -#include "expression.h" -#include "attrib.h" -#include "declaration.h" -#include "template.h" -#include "id.h" -#include "enum.h" -#include "import.h" -#include "aggregate.h" - -#include -#ifndef IN_GCC -#include "cc.h" -#include "global.h" -#include "oper.h" -#include "code.h" -#include "type.h" -#include "dt.h" -#include "cgcv.h" -#include "outbuf.h" -#include "irstate.h" -#else -#include "symbol.h" -#include "dt.h" -#endif - - -/******************************************* - * Get a canonicalized form of the TypeInfo for use with the internal - * runtime library routines. Canonicalized in that static arrays are - * represented as dynamic arrays, enums are represented by their - * underlying type, etc. This reduces the number of TypeInfo's needed, - * so we can use the custom internal ones more. - */ - -Expression *Type::getInternalTypeInfo(Scope *sc) -{ TypeInfoDeclaration *tid; - Expression *e; - Type *t; - static TypeInfoDeclaration *internalTI[TMAX]; - - //printf("Type::getInternalTypeInfo() %s\n", toChars()); - t = toBasetype(); - switch (t->ty) - { - case Tsarray: - t = t->next->arrayOf(); // convert to corresponding dynamic array type - break; - - case Tarray: - if (t->next->ty != Tclass) - break; - case Tfunction: - case Tdelegate: - case Tclass: - case Tpointer: - tid = internalTI[t->ty]; - if (!tid) - { tid = new TypeInfoDeclaration(t, 1); - internalTI[t->ty] = tid; - } - e = new VarExp(0, tid); - e = e->addressOf(); - e->type = tid->type; // do this so we don't get redundant dereference - return e; - - default: - break; - } - //printf("\tcalling getTypeInfo() %s\n", t->toChars()); - return t->getTypeInfo(sc); -} - - -/**************************************************** - * Get the exact TypeInfo. - */ - -Expression *Type::getTypeInfo(Scope *sc) -{ - Expression *e; - - //printf("Type::getTypeInfo() %s\n", toChars()); - if (!vtinfo) - { vtinfo = getTypeInfoDeclaration(); - - /* If this has a custom implementation in std/typeinfo, then - * do not generate a COMDAT for it. - */ - if (!builtinTypeInfo()) - { // Generate COMDAT - if (sc) // if in semantic() pass - sc->module->members->push(vtinfo); - else // if in obj generation pass - vtinfo->toObjFile(); - } - } - e = new VarExp(0, vtinfo); - e = e->addressOf(); - e->type = vtinfo->type; // do this so we don't get redundant dereference - return e; -} - -TypeInfoDeclaration *Type::getTypeInfoDeclaration() -{ - //printf("Type::getTypeInfoDeclaration() %s\n", toChars()); - return new TypeInfoDeclaration(this, 0); -} - -TypeInfoDeclaration *TypeTypedef::getTypeInfoDeclaration() -{ - return new TypeInfoTypedefDeclaration(this); -} - -TypeInfoDeclaration *TypePointer::getTypeInfoDeclaration() -{ - return new TypeInfoPointerDeclaration(this); -} - -TypeInfoDeclaration *TypeDArray::getTypeInfoDeclaration() -{ - return new TypeInfoArrayDeclaration(this); -} - -TypeInfoDeclaration *TypeSArray::getTypeInfoDeclaration() -{ - return new TypeInfoStaticArrayDeclaration(this); -} - -TypeInfoDeclaration *TypeAArray::getTypeInfoDeclaration() -{ - return new TypeInfoAssociativeArrayDeclaration(this); -} - -TypeInfoDeclaration *TypeStruct::getTypeInfoDeclaration() -{ - return new TypeInfoStructDeclaration(this); -} - -TypeInfoDeclaration *TypeClass::getTypeInfoDeclaration() -{ - return new TypeInfoClassDeclaration(this); -} - -TypeInfoDeclaration *TypeEnum::getTypeInfoDeclaration() -{ - return new TypeInfoEnumDeclaration(this); -} - -TypeInfoDeclaration *TypeFunction::getTypeInfoDeclaration() -{ - return new TypeInfoFunctionDeclaration(this); -} - -TypeInfoDeclaration *TypeDelegate::getTypeInfoDeclaration() -{ - return new TypeInfoDelegateDeclaration(this); -} - - -/**************************************************** - */ - -#if 1 - -void TypeInfoDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoDeclaration::toDt() %s\n", toChars()); - dtxoff(pdt, Type::typeinfo->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo - dtdword(pdt, 0); // monitor -} - -void TypeInfoTypedefDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoTypedefDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Ttypedef); - - TypeTypedef *tc = (TypeTypedef *)tinfo; - TypedefDeclaration *sd = tc->sym; - - /* Put out: - * TypeInfo base; - * char[] name; - */ - - sd->basetype->getTypeInfo(NULL); - dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for basetype - - char *name = sd->toPrettyChars(); - size_t namelen = strlen(name); - dtdword(pdt, namelen); - dtabytes(pdt, TYnptr, 0, namelen + 1, name); -} - -void TypeInfoEnumDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoEnumDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Enum - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Tenum); - - TypeEnum *tc = (TypeEnum *)tinfo; - EnumDeclaration *sd = tc->sym; - - /* Put out: - * TypeInfo base; - * char[] name; - */ - - sd->memtype->getTypeInfo(NULL); - dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for enum members - - char *name = sd->toPrettyChars(); - size_t namelen = strlen(name); - dtdword(pdt, namelen); - dtabytes(pdt, TYnptr, 0, namelen + 1, name); -} - -void TypeInfoPointerDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoPointerDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfopointer->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Pointer - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Tpointer); - - TypePointer *tc = (TypePointer *)tinfo; - - tc->next->getTypeInfo(NULL); - dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for type being pointed to -} - -void TypeInfoArrayDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoArrayDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfoarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Array - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Tarray); - - TypeDArray *tc = (TypeDArray *)tinfo; - - tc->next->getTypeInfo(NULL); - dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type -} - -void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoStaticArrayDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfostaticarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_StaticArray - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Tsarray); - - TypeSArray *tc = (TypeSArray *)tinfo; - - tc->next->getTypeInfo(NULL); - dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type - - dtdword(pdt, tc->dim->toInteger()); // length -} - -void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoAssociativeArrayDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_AssociativeArray - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Taarray); - - TypeAArray *tc = (TypeAArray *)tinfo; - - tc->next->getTypeInfo(NULL); - dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type - - tc->index->getTypeInfo(NULL); - dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type -} - -void TypeInfoFunctionDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoFunctionDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfofunction->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Function - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Tfunction); - - TypeFunction *tc = (TypeFunction *)tinfo; - - tc->next->getTypeInfo(NULL); - dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for function return value -} - -void TypeInfoDelegateDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoDelegateDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfodelegate->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Delegate - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Tdelegate); - - TypeDelegate *tc = (TypeDelegate *)tinfo; - - tc->next->next->getTypeInfo(NULL); - dtxoff(pdt, tc->next->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for delegate return value -} - -void TypeInfoStructDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars()); - - dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Tstruct); - - TypeStruct *tc = (TypeStruct *)tinfo; - StructDeclaration *sd = tc->sym; - - /* Put out: - * char[] name; - * uint xsize; - * uint function(void*) xtoHash; - * int function(void*,void*) xopEquals; - * int function(void*,void*) xopCmp; - */ - - char *name = sd->toPrettyChars(); - size_t namelen = strlen(name); - dtdword(pdt, namelen); - dtabytes(pdt, TYnptr, 0, namelen + 1, name); - - dtdword(pdt, sd->structsize); // xsize - - FuncDeclaration *fd; - FuncDeclaration *fdx; - TypeFunction *tf; - Type *ta; - - static TypeFunction *tftohash; - - if (!tftohash) - { - Scope sc; - tftohash = new TypeFunction(NULL, Type::tuns32, 0, LINKd); - tftohash = (TypeFunction *)tftohash->semantic(0, &sc); - } - - TypeFunction *tfeqptr; - { - Scope sc; - Array *arguments = new Array; - Argument *arg = new Argument(In, tc->pointerTo(), NULL, NULL); - - arguments->push(arg); - tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc); - } - -#if 0 - TypeFunction *tfeq; - { - Scope sc; - Array *arguments = new Array; - Argument *arg = new Argument(In, tc, NULL, NULL); - - arguments->push(arg); - tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeq = (TypeFunction *)tfeq->semantic(0, &sc); - } -#endif - - fdx = search_function(sd, Id::tohash); - if (fdx) - { fd = fdx->overloadExactMatch(tftohash); - if (fd) - dtxoff(pdt, fd->toSymbol(), 0, TYnptr); - else - //fdx->error("must be declared as extern (D) uint toHash()"); - dtdword(pdt, 0); - } - else - dtdword(pdt, 0); - - fdx = search_function(sd, Id::eq); - for (int i = 0; i < 2; i++) - { - if (fdx) - { fd = fdx->overloadExactMatch(tfeqptr); - if (fd) - dtxoff(pdt, fd->toSymbol(), 0, TYnptr); - else - //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); - dtdword(pdt, 0); - } - else - dtdword(pdt, 0); - - fdx = search_function(sd, Id::cmp); - } -} - -void TypeInfoClassDeclaration::toDt(dt_t **pdt) -{ - //printf("TypeInfoClassDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfoclass->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Tclass); - - TypeClass *tc = (TypeClass *)tinfo; - Symbol *s; - - if (!tc->sym->vclassinfo) - tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym); - s = tc->sym->vclassinfo->toSymbol(); - dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo -} - -void TypeInfoDeclaration::toObjFile() -{ - Symbol *s; - unsigned sz; - Dsymbol *parent; - - //printf("TypeInfoDeclaration::toObjFile(%p '%s') protection %d\n", this, toChars(), protection); - - s = toSymbol(); - sz = type->size(); - - parent = this->toParent(); - s->Sclass = SCcomdat; - s->Sfl = FLdata; - - toDt(&s->Sdt); - - dt_optimize(s->Sdt); - - // See if we can convert a comdat to a comdef, - // which saves on exe file space. - if (s->Sclass == SCcomdat && - s->Sdt->dt == DT_azeros && - s->Sdt->DTnext == NULL) - { - s->Sclass = SCglobal; - s->Sdt->dt = DT_common; - } - -#if ELFOBJ // Burton - if (s->Sdt && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL) - s->Sseg = UDATA; - else - s->Sseg = DATA; -#endif /* ELFOBJ */ - outdata(s); - if (isExport()) - obj_export(s,0); -} - -#endif - -/* ========================================================================= */ - -/* These decide if there's an instance for them already in std.typeinfo, - * because then the compiler doesn't need to build one. - */ - -int Type::builtinTypeInfo() -{ - return 0; -} - -int TypeBasic::builtinTypeInfo() -{ - return 1; -} - -int TypeDArray::builtinTypeInfo() -{ - return next->isTypeBasic() != NULL; -} - -/* ========================================================================= */ - -/*************************************** - * Create a static array of TypeInfo references - * corresponding to an array of Expression's. - * Used to supply hidden _arguments[] value for variadic D functions. - */ - -Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim) -{ - /* Improvements: - * 1) create an array literal instead, - * as it would eliminate the extra dereference of loading the - * static variable. - */ - - ArrayInitializer *ai = new ArrayInitializer(0); - VarDeclaration *v; - Type *t; - Expression *e; - OutBuffer buf; - Identifier *id; - char *name; - - // Generate identifier for _arguments[] - buf.writestring("_arguments_"); - for (int i = 0; i < dim; i++) - { t = args[i]->type; - t->toDecoBuffer(&buf); - } - buf.writeByte(0); - id = Lexer::idPool((char *)buf.data); - - Module *m = sc->module; - Dsymbol *s = m->symtab->lookup(id); - - if (s && s->parent == m) - { // Use existing one - v = s->isVarDeclaration(); - assert(v); - } - else - { // Generate new one - - for (int i = 0; i < dim; i++) - { t = args[i]->type; - e = t->getTypeInfo(sc); - ai->addInit(new IntegerExp(i), new ExpInitializer(0, e)); - } - - t = Type::typeinfo->type->arrayOf(); - ai->type = t; - v = new VarDeclaration(0, t, id, ai); - m->members->push(v); - m->symtab->insert(v); - sc = sc->push(); - sc->linkage = LINKc; - sc->stc = STCstatic | STCcomdat; - ai->semantic(sc, t); - v->semantic(sc); - v->parent = m; - sc = sc->pop(); - } - e = new VarExp(0, v); - e = e->semantic(sc); - return e; -} - diff -uNr gdc-0.11/d/root/unialpha.c gdc-0.12/d/root/unialpha.c --- gdc-0.11/d/root/unialpha.c 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/root/unialpha.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,323 +0,0 @@ - -// Copyright (c) 2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include - -/******************************* - * Return !=0 if unicode alpha. - * Use table from C99 Appendix D. - */ - -int isUniAlpha(unsigned u) -{ - static unsigned short table[][2] = - { - { 0x00AA, 0x00AA }, - { 0x00B5, 0x00B5 }, - { 0x00B7, 0x00B7 }, - { 0x00BA, 0x00BA }, - { 0x00C0, 0x00D6 }, - { 0x00D8, 0x00F6 }, - { 0x00F8, 0x01F5 }, - { 0x01FA, 0x0217 }, - { 0x0250, 0x02A8 }, - { 0x02B0, 0x02B8 }, - { 0x02BB, 0x02BB }, - { 0x02BD, 0x02C1 }, - { 0x02D0, 0x02D1 }, - { 0x02E0, 0x02E4 }, - { 0x037A, 0x037A }, - { 0x0386, 0x0386 }, - { 0x0388, 0x038A }, - { 0x038C, 0x038C }, - { 0x038E, 0x03A1 }, - { 0x03A3, 0x03CE }, - { 0x03D0, 0x03D6 }, - { 0x03DA, 0x03DA }, - { 0x03DC, 0x03DC }, - { 0x03DE, 0x03DE }, - { 0x03E0, 0x03E0 }, - { 0x03E2, 0x03F3 }, - { 0x0401, 0x040C }, - { 0x040E, 0x044F }, - { 0x0451, 0x045C }, - { 0x045E, 0x0481 }, - { 0x0490, 0x04C4 }, - { 0x04C7, 0x04C8 }, - { 0x04CB, 0x04CC }, - { 0x04D0, 0x04EB }, - { 0x04EE, 0x04F5 }, - { 0x04F8, 0x04F9 }, - { 0x0531, 0x0556 }, - { 0x0559, 0x0559 }, - { 0x0561, 0x0587 }, - { 0x05B0, 0x05B9 }, - { 0x05BB, 0x05BD }, - { 0x05BF, 0x05BF }, - { 0x05C1, 0x05C2 }, - { 0x05D0, 0x05EA }, - { 0x05F0, 0x05F2 }, - { 0x0621, 0x063A }, - { 0x0640, 0x0652 }, - { 0x0660, 0x0669 }, - { 0x0670, 0x06B7 }, - { 0x06BA, 0x06BE }, - { 0x06C0, 0x06CE }, - { 0x06D0, 0x06DC }, - { 0x06E5, 0x06E8 }, - { 0x06EA, 0x06ED }, - { 0x06F0, 0x06F9 }, - { 0x0901, 0x0903 }, - { 0x0905, 0x0939 }, - { 0x093D, 0x093D }, - { 0x093E, 0x094D }, - { 0x0950, 0x0952 }, - { 0x0958, 0x0963 }, - { 0x0966, 0x096F }, - { 0x0981, 0x0983 }, - { 0x0985, 0x098C }, - { 0x098F, 0x0990 }, - { 0x0993, 0x09A8 }, - { 0x09AA, 0x09B0 }, - { 0x09B2, 0x09B2 }, - { 0x09B6, 0x09B9 }, - { 0x09BE, 0x09C4 }, - { 0x09C7, 0x09C8 }, - { 0x09CB, 0x09CD }, - { 0x09DC, 0x09DD }, - { 0x09DF, 0x09E3 }, - { 0x09E6, 0x09EF }, - { 0x09F0, 0x09F1 }, - { 0x0A02, 0x0A02 }, - { 0x0A05, 0x0A0A }, - { 0x0A0F, 0x0A10 }, - { 0x0A13, 0x0A28 }, - { 0x0A2A, 0x0A30 }, - { 0x0A32, 0x0A33 }, - { 0x0A35, 0x0A36 }, - { 0x0A38, 0x0A39 }, - { 0x0A3E, 0x0A42 }, - { 0x0A47, 0x0A48 }, - { 0x0A4B, 0x0A4D }, - { 0x0A59, 0x0A5C }, - { 0x0A5E, 0x0A5E }, - { 0x0A66, 0x0A6F }, - { 0x0A74, 0x0A74 }, - { 0x0A81, 0x0A83 }, - { 0x0A85, 0x0A8B }, - { 0x0A8D, 0x0A8D }, - { 0x0A8F, 0x0A91 }, - { 0x0A93, 0x0AA8 }, - { 0x0AAA, 0x0AB0 }, - { 0x0AB2, 0x0AB3 }, - { 0x0AB5, 0x0AB9 }, - { 0x0ABD, 0x0AC5 }, - { 0x0AC7, 0x0AC9 }, - { 0x0ACB, 0x0ACD }, - { 0x0AD0, 0x0AD0 }, - { 0x0AE0, 0x0AE0 }, - { 0x0AE6, 0x0AEF }, - { 0x0B01, 0x0B03 }, - { 0x0B05, 0x0B0C }, - { 0x0B0F, 0x0B10 }, - { 0x0B13, 0x0B28 }, - { 0x0B2A, 0x0B30 }, - { 0x0B32, 0x0B33 }, - { 0x0B36, 0x0B39 }, - { 0x0B3D, 0x0B3D }, - { 0x0B3E, 0x0B43 }, - { 0x0B47, 0x0B48 }, - { 0x0B4B, 0x0B4D }, - { 0x0B5C, 0x0B5D }, - { 0x0B5F, 0x0B61 }, - { 0x0B66, 0x0B6F }, - { 0x0B82, 0x0B83 }, - { 0x0B85, 0x0B8A }, - { 0x0B8E, 0x0B90 }, - { 0x0B92, 0x0B95 }, - { 0x0B99, 0x0B9A }, - { 0x0B9C, 0x0B9C }, - { 0x0B9E, 0x0B9F }, - { 0x0BA3, 0x0BA4 }, - { 0x0BA8, 0x0BAA }, - { 0x0BAE, 0x0BB5 }, - { 0x0BB7, 0x0BB9 }, - { 0x0BBE, 0x0BC2 }, - { 0x0BC6, 0x0BC8 }, - { 0x0BCA, 0x0BCD }, - { 0x0BE7, 0x0BEF }, - { 0x0C01, 0x0C03 }, - { 0x0C05, 0x0C0C }, - { 0x0C0E, 0x0C10 }, - { 0x0C12, 0x0C28 }, - { 0x0C2A, 0x0C33 }, - { 0x0C35, 0x0C39 }, - { 0x0C3E, 0x0C44 }, - { 0x0C46, 0x0C48 }, - { 0x0C4A, 0x0C4D }, - { 0x0C60, 0x0C61 }, - { 0x0C66, 0x0C6F }, - { 0x0C82, 0x0C83 }, - { 0x0C85, 0x0C8C }, - { 0x0C8E, 0x0C90 }, - { 0x0C92, 0x0CA8 }, - { 0x0CAA, 0x0CB3 }, - { 0x0CB5, 0x0CB9 }, - { 0x0CBE, 0x0CC4 }, - { 0x0CC6, 0x0CC8 }, - { 0x0CCA, 0x0CCD }, - { 0x0CDE, 0x0CDE }, - { 0x0CE0, 0x0CE1 }, - { 0x0CE6, 0x0CEF }, - { 0x0D02, 0x0D03 }, - { 0x0D05, 0x0D0C }, - { 0x0D0E, 0x0D10 }, - { 0x0D12, 0x0D28 }, - { 0x0D2A, 0x0D39 }, - { 0x0D3E, 0x0D43 }, - { 0x0D46, 0x0D48 }, - { 0x0D4A, 0x0D4D }, - { 0x0D60, 0x0D61 }, - { 0x0D66, 0x0D6F }, - { 0x0E01, 0x0E3A }, - { 0x0E40, 0x0E5B }, -// { 0x0E50, 0x0E59 }, - { 0x0E81, 0x0E82 }, - { 0x0E84, 0x0E84 }, - { 0x0E87, 0x0E88 }, - { 0x0E8A, 0x0E8A }, - { 0x0E8D, 0x0E8D }, - { 0x0E94, 0x0E97 }, - { 0x0E99, 0x0E9F }, - { 0x0EA1, 0x0EA3 }, - { 0x0EA5, 0x0EA5 }, - { 0x0EA7, 0x0EA7 }, - { 0x0EAA, 0x0EAB }, - { 0x0EAD, 0x0EAE }, - { 0x0EB0, 0x0EB9 }, - { 0x0EBB, 0x0EBD }, - { 0x0EC0, 0x0EC4 }, - { 0x0EC6, 0x0EC6 }, - { 0x0EC8, 0x0ECD }, - { 0x0ED0, 0x0ED9 }, - { 0x0EDC, 0x0EDD }, - { 0x0F00, 0x0F00 }, - { 0x0F18, 0x0F19 }, - { 0x0F20, 0x0F33 }, - { 0x0F35, 0x0F35 }, - { 0x0F37, 0x0F37 }, - { 0x0F39, 0x0F39 }, - { 0x0F3E, 0x0F47 }, - { 0x0F49, 0x0F69 }, - { 0x0F71, 0x0F84 }, - { 0x0F86, 0x0F8B }, - { 0x0F90, 0x0F95 }, - { 0x0F97, 0x0F97 }, - { 0x0F99, 0x0FAD }, - { 0x0FB1, 0x0FB7 }, - { 0x0FB9, 0x0FB9 }, - { 0x10A0, 0x10C5 }, - { 0x10D0, 0x10F6 }, - { 0x1E00, 0x1E9B }, - { 0x1EA0, 0x1EF9 }, - { 0x1F00, 0x1F15 }, - { 0x1F18, 0x1F1D }, - { 0x1F20, 0x1F45 }, - { 0x1F48, 0x1F4D }, - { 0x1F50, 0x1F57 }, - { 0x1F59, 0x1F59 }, - { 0x1F5B, 0x1F5B }, - { 0x1F5D, 0x1F5D }, - { 0x1F5F, 0x1F7D }, - { 0x1F80, 0x1FB4 }, - { 0x1FB6, 0x1FBC }, - { 0x1FBE, 0x1FBE }, - { 0x1FC2, 0x1FC4 }, - { 0x1FC6, 0x1FCC }, - { 0x1FD0, 0x1FD3 }, - { 0x1FD6, 0x1FDB }, - { 0x1FE0, 0x1FEC }, - { 0x1FF2, 0x1FF4 }, - { 0x1FF6, 0x1FFC }, - { 0x203F, 0x2040 }, - { 0x207F, 0x207F }, - { 0x2102, 0x2102 }, - { 0x2107, 0x2107 }, - { 0x210A, 0x2113 }, - { 0x2115, 0x2115 }, - { 0x2118, 0x211D }, - { 0x2124, 0x2124 }, - { 0x2126, 0x2126 }, - { 0x2128, 0x2128 }, - { 0x212A, 0x2131 }, - { 0x2133, 0x2138 }, - { 0x2160, 0x2182 }, - { 0x3005, 0x3007 }, - { 0x3021, 0x3029 }, - { 0x3041, 0x3093 }, - { 0x309B, 0x309C }, - { 0x30A1, 0x30F6 }, - { 0x30FB, 0x30FC }, - { 0x3105, 0x312C }, - { 0x4E00, 0x9FA5 }, - { 0xAC00, 0xD7A3 }, - }; - -#ifdef DEBUG - for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) - { - //printf("%x\n", table[i][0]); - assert(table[i][0] <= table[i][1]); - if (i < sizeof(table) / sizeof(table[0]) - 1) - assert(table[i][1] < table[i + 1][0]); - } -#endif - - if (u > 0xD7A3) - goto Lisnot; - - // Binary search - int mid; - int low; - int high; - - low = 0; - high = sizeof(table) / sizeof(table[0]) - 1; - while (low <= high) - { - mid = (low + high) >> 1; - if (u < table[mid][0]) - high = mid - 1; - else if (u > table[mid][1]) - low = mid + 1; - else - goto Lis; - } - -Lisnot: -#ifdef DEBUG - for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) - { - assert(u < table[i][0] || u > table[i][1]); - } -#endif - return 0; - -Lis: -#ifdef DEBUG - for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) - { - if (u >= table[i][0] && u <= table[i][1]) - return 1; - } - assert(0); // should have been in table -#endif - return 1; -} - diff -uNr gdc-0.11/d/root/utf.c gdc-0.12/d/root/utf.c --- gdc-0.11/d/root/utf.c 2004-12-19 18:51:04.000000000 +0100 +++ gdc-0.12/d/root/utf.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,193 +0,0 @@ -// utf.c -// Copyright (c) 2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -// Description of UTF-8 at: -// http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - -#include -#include - -#include "utf.h" - -int utf_isValidDchar(dchar_t c) -{ - return c < 0xD800 || - (c > 0xDFFF && c <= 0x10FFFF && c != 0xFFFE && c != 0xFFFF); -} - -/******************************************** - * Decode a single UTF-8 character sequence. - * Returns: - * NULL success - * !=NULL error message string - */ - -char *utf_decodeChar(unsigned char *s, unsigned len, unsigned *pidx, dchar_t *presult) -{ - dchar_t V; - unsigned i = *pidx; - unsigned char u = s[i]; - - assert(i >= 0 && i < len); - - if (u & 0x80) - { unsigned n; - unsigned char u2; - - /* The following encodings are valid, except for the 5 and 6 byte - * combinations: - * 0xxxxxxx - * 110xxxxx 10xxxxxx - * 1110xxxx 10xxxxxx 10xxxxxx - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - for (n = 1; ; n++) - { - if (n > 4) - goto Lerr; // only do the first 4 of 6 encodings - if (((u << n) & 0x80) == 0) - { - if (n == 1) - goto Lerr; - break; - } - } - - // Pick off (7 - n) significant bits of B from first byte of octet - V = (dchar_t)(u & ((1 << (7 - n)) - 1)); - - if (i + (n - 1) >= len) - goto Lerr; // off end of string - - /* The following combinations are overlong, and illegal: - * 1100000x (10xxxxxx) - * 11100000 100xxxxx (10xxxxxx) - * 11110000 1000xxxx (10xxxxxx 10xxxxxx) - * 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) - * 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) - */ - u2 = s[i + 1]; - if ((u & 0xFE) == 0xC0 || - (u == 0xE0 && (u2 & 0xE0) == 0x80) || - (u == 0xF0 && (u2 & 0xF0) == 0x80) || - (u == 0xF8 && (u2 & 0xF8) == 0x80) || - (u == 0xFC && (u2 & 0xFC) == 0x80)) - goto Lerr; // overlong combination - - for (unsigned j = 1; j != n; j++) - { - u = s[i + j]; - if ((u & 0xC0) != 0x80) - goto Lerr; // trailing bytes are 10xxxxxx - V = (V << 6) | (u & 0x3F); - } - if (!utf_isValidDchar(V)) - goto Lerr; - i += n; - } - else - { - V = (dchar_t) u; - i++; - } - - assert(utf_isValidDchar(V)); - *pidx = i; - *presult = V; - return NULL; - - Lerr: - *presult = (dchar_t) s[i]; - *pidx = i + 1; - return "invalid UTF-8 sequence"; -} - -/*************************************************** - * Validate a UTF-8 string. - * Returns: - * NULL success - * !=NULL error message string - */ - -char *utf_validateString(unsigned char *s, unsigned len) -{ - unsigned idx; - char *err = NULL; - dchar_t dc; - - for (idx = 0; idx < len; ) - { - err = utf_decodeChar(s, len, &idx, &dc); - if (err) - break; - } - return err; -} - - -/******************************************** - * Decode a single UTF-16 character sequence. - * Returns: - * NULL success - * !=NULL error message string - */ - - -char *utf_decodeWchar(unsigned short *s, unsigned len, unsigned *pidx, dchar_t *presult) -{ - char *msg; - unsigned i = *pidx; - unsigned u = s[i]; - - assert(i >= 0 && i < len); - if (u & ~0x7F) - { if (u >= 0xD800 && u <= 0xDBFF) - { unsigned u2; - - if (i + 1 == len) - { msg = "surrogate UTF-16 high value past end of string"; - goto Lerr; - } - u2 = s[i + 1]; - if (u2 < 0xDC00 || u2 > 0xDFFF) - { msg = "surrogate UTF-16 low value out of range"; - goto Lerr; - } - u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00); - i += 2; - } - else if (u >= 0xDC00 && u <= 0xDFFF) - { msg = "unpaired surrogate UTF-16 value"; - goto Lerr; - } - else if (u == 0xFFFE || u == 0xFFFF) - { msg = "illegal UTF-16 value"; - goto Lerr; - } - else - i++; - } - else - { - i++; - } - - assert(utf_isValidDchar(u)); - *pidx = i; - *presult = (dchar_t)u; - return NULL; - - Lerr: - *presult = (dchar_t)s[i]; - *pidx = i + 1; - return msg; -} - diff -uNr gdc-0.11/d/root/utf.h gdc-0.12/d/root/utf.h --- gdc-0.11/d/root/utf.h 2004-10-26 02:41:27.000000000 +0200 +++ gdc-0.12/d/root/utf.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,23 +0,0 @@ -// utf.h -// Copyright (c) 2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_UTF_H -#define DMD_UTF_H - - -typedef unsigned dchar_t; - -int utf_isValidDchar(dchar_t c); - -char *utf_decodeChar(unsigned char *s, unsigned len, unsigned *pidx, dchar_t *presult); -char *utf_decodeWchar(unsigned short *s, unsigned len, unsigned *pidx, dchar_t *presult); - -char *utf_validateString(unsigned char *s, unsigned len); - -#endif diff -uNr gdc-0.11/d/root/version.c gdc-0.12/d/root/version.c --- gdc-0.11/d/root/version.c 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/version.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,160 +0,0 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include - -#include "root.h" - -#include "identifier.h" -#include "dsymbol.h" -#include "debcond.h" -#include "version.h" -#include "module.h" - -/* ================================================== */ - -DebugSymbol::DebugSymbol(Identifier *ident) - : Dsymbol(ident) -{ -} - -DebugSymbol::DebugSymbol(unsigned level) - : Dsymbol() -{ - this->level = level; -} - -Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s) -{ - assert(!s); - DebugSymbol *ds = new DebugSymbol(ident); - ds->level = level; - return ds; -} - -void DebugSymbol::addMember(ScopeDsymbol *sd) -{ - //printf("DebugSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); - Module *m; - - // Do not add the member to the symbol table, - // just make sure subsequent debug declarations work. - m = sd->isModule(); - if (ident) - { - if (!m) - error("declaration must be at module level"); - else - { - if (!m->debugids) - m->debugids = new Array(); - m->debugids->push(ident->toChars()); - } - } - else - { - if (!m) - error("level declaration must be at module level"); - else - m->debuglevel = level; - } -} - -void DebugSymbol::semantic(Scope *sc) -{ - //printf("DebugSymbol::semantic() %s\n", toChars()); -} - -void DebugSymbol::toCBuffer(OutBuffer *buf) -{ - buf->writestring("debug = "); - if (ident) - buf->writestring(ident->toChars()); - else - buf->printf("%u", level); - buf->writestring(";"); - buf->writenl(); -} - -char *DebugSymbol::kind() -{ - return "debug"; -} - -/* ================================================== */ - -VersionSymbol::VersionSymbol(Identifier *ident) - : Dsymbol(ident) -{ -} - -VersionSymbol::VersionSymbol(unsigned level) - : Dsymbol() -{ - this->level = level; -} - -Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s) -{ - assert(!s); - VersionSymbol *ds = new VersionSymbol(ident); - ds->level = level; - return ds; -} - -void VersionSymbol::addMember(ScopeDsymbol *sd) -{ - //printf("VersionSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); - Module *m; - - // Do not add the member to the symbol table, - // just make sure subsequent debug declarations work. - m = sd->isModule(); - if (ident) - { - VersionCondition::checkPredefined(ident->toChars()); - if (!m) - error("declaration must be at module level"); - else - { - if (!m->versionids) - m->versionids = new Array(); - m->versionids->push(ident->toChars()); - } - } - else - { - if (!m) - error("level declaration must be at module level"); - else - m->versionlevel = level; - } -} - -void VersionSymbol::semantic(Scope *sc) -{ -} - -void VersionSymbol::toCBuffer(OutBuffer *buf) -{ - buf->writestring("version = "); - if (ident) - buf->writestring(ident->toChars()); - else - buf->printf("%u", level); - buf->writestring(";"); - buf->writenl(); -} - -char *VersionSymbol::kind() -{ - return "version"; -} - - diff -uNr gdc-0.11/d/root/version.h gdc-0.12/d/root/version.h --- gdc-0.11/d/root/version.h 2005-04-18 03:52:53.000000000 +0200 +++ gdc-0.12/d/root/version.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,49 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_VERSION_H -#define DMD_VERSION_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "dsymbol.h" - -struct OutBuffer; - -struct DebugSymbol : Dsymbol -{ - unsigned level; - - DebugSymbol(Identifier *ident); - DebugSymbol(unsigned level); - Dsymbol *syntaxCopy(Dsymbol *); - - void addMember(ScopeDsymbol *s); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - char *kind(); -}; - -struct VersionSymbol : Dsymbol -{ - unsigned level; - - VersionSymbol(Identifier *ident); - VersionSymbol(unsigned level); - Dsymbol *syntaxCopy(Dsymbol *); - - void addMember(ScopeDsymbol *s); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf); - char *kind(); -}; - -#endif /* DMD_VERSION_H */ diff -uNr gdc-0.11/d/setup-gcc.sh gdc-0.12/d/setup-gcc.sh --- gdc-0.11/d/setup-gcc.sh 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/setup-gcc.sh 2005-05-29 00:00:56.000000000 +0200 @@ -19,6 +19,9 @@ exit 1 fi +# 0.5. Find out what GDC version this is +gdc_ver=`cat gcc/d/gdc-version` + # 1. Create a link to the Phobos sources in the top-level directory ln -s gcc/d/phobos libphobos || exit 1 @@ -34,18 +37,21 @@ # 3. Patch the gcc subdirectory cd gcc || exit 1 patch -p1 < d/patch-gcc-${gcc_ver}.x || exit 1 +sed -e 's/ ?(gdc [^)]*)//' \ + -e 's/\(version_string[^"]*"[^"]*\)"/\1 ('"$gdc_ver"')"/' \ + version.c > version.c.tmp && mv -f version.c.tmp version.c # 4. Maybe apply Darwin patches if test "`uname`" = Darwin; then - read -p 'Apply Darwin patches (y/n)?' v - if echo "$v" | grep -qi "^y"; then - patch -p1 < d/patch-gcc-darwin-eh-${gcc_ver}.x || exit 1 - if test "$gcc_ver" = 3.3; then - cd "$top" || exit 1 - patch -p1 < gcc/d/gcc-3.3.5-framework-headers.patch || exit 1 - patch -p1 < gcc/d/gcc-3.3.5-framework-linker.patch || exit 1 - else - echo "Note: Frameworks patch not supported for GCC $gcc_ver." - fi + patch -p1 < d/patch-gcc-darwin-eh-${gcc_ver}.x || exit 1 + if test "$gcc_ver" = 3.3; then + cd "$top" || exit 1 + patch -p1 < gcc/d/gcc-3.3.5-framework-headers.patch || exit 1 + patch -p1 < gcc/d/gcc-3.3.5-framework-linker.patch || exit 1 + else + echo "Note: Frameworks patch not supported for GCC $gcc_ver." fi fi + +echo "GDC setup complete." +exit 0 diff -uNr gdc-0.11/d/symbol.h gdc-0.12/d/symbol.h --- gdc-0.11/d/symbol.h 2005-04-16 20:11:40.000000000 +0200 +++ gdc-0.12/d/symbol.h 2005-05-25 03:51:33.000000000 +0200 @@ -152,7 +152,6 @@ tree ScontextDecl; // The DECL_CONTEXT to use for child declarations, but see IRState::declContext unsigned Sunique; // For conflicting symbol names union { - AggregateDeclaration * aggDecl; // AggregateDeclaration.sinit set in AggregateDeclaration::toInitializer Array * thunks; // of struct Thunk; for FuncDeclarations } Sspecial; };